아두이노 우노 Q WebSocket

Arduino UNO Q는 WebUI Brick을 통해 기본적으로 WebSocket을 지원합니다 — 추가 라이브러리 설치 또는 별도 서버 프로세스를 시작할 필요가 없습니다. WebUI Brick은 HTTP 파일 서버와 동일한 포트 7000에서 Socket.IO WebSocket 서버를 제공합니다. Python은 ui.on_message()로 수신 이벤트를 처리하고 ui.send_message()로 한 클라이언트 또는 모든 클라이언트에게 데이터를 푸시합니다. 브라우저 측에서 Socket.IO 클라이언트는 자동으로 연결되고 socket.emit()을 사용하여 이벤트를 전송하고 socket.on()을 사용하여 수신합니다.

이 튜토리얼은 간단한 LED 제어 예제를 사용하여 Arduino UNO Q에서 WebSocket 패턴을 가르칩니다: 브라우저의 버튼을 클릭하면 보드의 내장 LED를 토글하고 모든 연결된 브라우저에 대한 상태를 즉시 업데이트합니다 - 페이지 새로고침, 폴링 없음.

이 튜토리얼에서 배우게 될 내용:

Arduino UNO Q websocket

필요한 하드웨어

1×Arduino UNO Q 아마존
1×USB Cable for Arduino Uno Q 아마존
1×(추천) 아두이노 우노용 스크루 터미널 블록 쉴드 쿠팡 | 아마존
1×(추천) Sensors/Servo Expansion Shield for Arduino Uno 쿠팡 | 아마존
1×(추천) 아두이노 우노용 브레드보드 쉴드 쿠팡 | 아마존
1×(추천) 아두이노 우노용 케이스 쿠팡 | 아마존
1×(추천) 아두이노 우노용 프로토타이핑 베이스 플레이트 & 브레드보드 키트 아마존
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.

외부 구성 요소가 필요하지 않습니다 — 이 튜토리얼은 Arduino UNO Q의 내장 LED를 사용합니다.

Arduino UNO Q의 WebSocket에 대해

  • WebUI Brick Socket.IO 서버: WebUI Brick은 HTTP 파일 서버와 Socket.IO WebSocket 서버를 모두 포트 7000에서 시작합니다. Flask, websockets 라이브러리 또는 다른 패키지를 설치할 필요가 없습니다 — Brick이 모든 것을 자동으로 처리합니다. Socket.IO 클라이언트 스크립트는 /socket.io/socket.io.js에서 제공되므로 HTML 페이지가 보드에서 직접 로드합니다.
  • Python 이벤트 핸들러: ui.on_message("event_name", handler)로 수신 브라우저 이벤트에 대한 핸들러를 등록합니다. 핸들러는 두 개의 인수를 받습니다: client (발신자)와 data (JSON 페이로드). 발신자에게만 응답하려면 ui.send_message("event_name", payload, client)를 호출하세요. 모든 연결된 클라이언트에게 브로드캐스트하려면 세 번째 인수를 생략합니다: ui.send_message("event_name", payload).
  • 브라우저 Socket.IO 클라이언트: HTML 페이지에 /socket.io/socket.io.js를 포함시킨 다음 const socket = io("http://" + window.location.host)로 연결을 엽니다. socket.emit("event_name", {})로 이벤트를 보내고 socket.on("event_name", function(data) { ... })로 서버 이벤트를 수신합니다.
  • Python의 MCU 호출: Python에서 Bridge.call("function_name", argument)를 사용하여 MCU 스케치에서 Bridge.provide("function_name", handler)로 등록된 함수를 호출합니다. 이것이 Python이 WebSocket 이벤트에서 하드웨어를 제어하는 방법입니다.

Arduino UNO Q 코드

Arduino UNO Q에는 함께 작동하는 두 개의 프로세서가 있습니다:

  • STM32 MCU는 내장 LED를 켜거나 끄는 set_led 함수를 Bridge를 통해 노출합니다.
  • Qualcomm MPU는 브라우저의 WebSocket 이벤트를 수신하는 Python 앱을 실행합니다. Bridge를 호출하여 LED를 제어하고 모든 연결된 클라이언트에게 새 LED 상태를 브로드캐스트합니다.

MCU 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-websocket */ #include <Arduino_RouterBridge.h> void set_led(bool state) { // LOW turns the built-in LED on for most Arduino boards digitalWrite(LED_BUILTIN, state ? LOW : HIGH); } void setup() { pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, HIGH); // Start with LED off Bridge.begin(); Bridge.provide("set_led", set_led); } void loop() {}

Python 코드

/* * 이 Arduino UNO Q 코드는 newbiely.kr 에서 개발되었습니다 * 이 Arduino UNO Q 코드는 어떠한 제한 없이 공개 사용을 위해 제공됩니다. * 상세한 지침 및 연결도에 대해서는 다음을 방문하세요: * https://newbiely.kr/tutorials/arduino-uno-q/arduino-uno-q-websocket */ from arduino.app_utils import * from arduino.app_bricks.web_ui import WebUI led_on = False def on_toggle(client, data): global led_on led_on = not led_on Bridge.call("set_led", led_on) ui.send_message("led_status", {"on": led_on}) def on_get_state(client, data): ui.send_message("led_status", {"on": led_on}, client) ui = WebUI() ui.on_message("toggle_led", on_toggle) ui.on_message("get_state", on_get_state) App.run()

HTML (assets/index.html)

이 파일을 App의 assets/ 폴더에 배치하세요. WebUI Brick(/socket.io/socket.io.js)에서 Socket.IO 클라이언트를 로드하고 내장 LED를 토글하는 버튼을 표시합니다:

<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>WebSocket LED - DIYables</title> <link rel="icon" href="https://diyables.io/images/page/diyables.svg"> <style> * { margin: 0; padding: 0; box-sizing: border-box; } body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; background: white; height: 100vh; display: flex; flex-direction: column; } .navbar { background: #f8f9fa; padding: 10px 20px; border-bottom: 1px solid #e9ecef; display: flex; justify-content: space-between; align-items: center; } .nav-home { color: #667eea; text-decoration: none; font-size: 1.1em; font-weight: bold; padding: 8px 12px; border-radius: 6px; background: rgba(102,126,234,0.1); transition: all 0.3s; } .nav-home:hover { background: rgba(102,126,234,0.2); transform: scale(1.05); } .nav-tutorial { color: #007bff; text-decoration: none; font-size: 1em; font-weight: bold; padding: 8px 12px; border-radius: 6px; background: rgba(0,123,255,0.1); transition: all 0.3s; } .nav-tutorial:hover { background: rgba(0,123,255,0.2); transform: scale(1.05); } .status-bar { background: #f8f9fa; padding: 5px 20px; border-bottom: 1px solid #e9ecef; text-align: center; font-size: 0.9em; color: black; } .status-bar #connectionText { font-weight: bold; } .main { flex: 1; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 32px; } h1 { color: #333; font-size: 2em; } .led-btn { width: 200px; height: 200px; border-radius: 50%; border: 8px solid #ccc; background: #e0e0e0; cursor: pointer; font-size: 1.4em; font-weight: bold; color: #555; transition: all 0.3s; box-shadow: 0 4px 15px rgba(0,0,0,0.15); } .led-btn.on { background: #ffeb3b; border-color: #f9a825; color: #333; box-shadow: 0 0 40px rgba(255,235,59,0.7); } .led-btn:disabled { cursor: not-allowed; opacity: 0.5; } .status-text { font-size: 1.2em; color: #555; } .footer { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; text-align: center; font-size: 0.9em; height: 40px; display: flex; align-items: center; justify-content: center; } .footer a { color: white; text-decoration: none; font-weight: bold; } .footer a:hover { text-decoration: underline; } </style> </head> <body> <div class="navbar"> <a href="/" class="nav-home">&#127968; Home</a> <a href="https://diyables.io/tutorials/arduino-uno-q" target="_blank" class="nav-tutorial">&#128218; Tutorial</a> </div> <div class="status-bar">WebSocket: <span id="connectionText">Disconnected</span></div> <div class="main"> <h1>&#128161; LED Control</h1> <button id="ledBtn" class="led-btn" disabled onclick="toggleLed()">LED IS OFF</button> <p class="status-text" id="statusText">Waiting for connection…</p> </div> <div class="footer">Created by&nbsp;<a href="https://diyables.io/" target="_blank">DIYables</a></div> <script src="libs/socket.io.min.js"></script> <script> const connText = document.getElementById("connectionText"); const ledBtn = document.getElementById("ledBtn"); const statusText = document.getElementById("statusText"); function setConnectionStatus(text) { connText.textContent = text; if (text === "connected") connText.style.color = "#007bff"; else if (text === "connecting") connText.style.color = "#6c757d"; else connText.style.color = "#dc3545"; } function applyLedState(on) { if (on) { ledBtn.classList.add("on"); ledBtn.textContent = "LED IS ON"; statusText.textContent = "LED is ON — click to turn off"; } else { ledBtn.classList.remove("on"); ledBtn.textContent = "LED IS OFF"; statusText.textContent = "LED is OFF — click to turn on"; } } function toggleLed() { socket.emit("toggle_led", {}); } const socket = io("http://" + window.location.host, { transports: ["websocket"] }); socket.on("connect", function () { setConnectionStatus("connected"); ledBtn.disabled = false; socket.emit("get_state", {}); }); socket.on("disconnect", function () { setConnectionStatus("disconnected"); ledBtn.disabled = true; statusText.textContent = "Connection lost…"; }); socket.on("led_status", function (data) { applyLedState(data.on); }); </script> </body> </html>

빠른 단계

  • Wi-Fi 연결: Arduino UNO Q가 Wi-Fi 네트워크에 연결되어 있는지 확인합니다. Arduino App Lab의 네트워크 아이콘을 사용하여 먼저 연결합니다.
  • Arduino App Lab 열기: Arduino App Lab을 시작하고 Arduino UNO Q가 감지될 때까지 기다립니다.
  • 새 App 만들기: Create New App 버튼을 클릭합니다.
create new app in 아두이노 app lab on Arduino UNO Q
  • App에 이름을 지정합니다(예: WebSocketLED).
  • Create를 클릭하여 확인합니다.
아두이노 app lab app folders and files on Arduino UNO Q
  • MCU 스케치 붙여넣기: 위의 MCU 코드를 복사하여 sketch/sketch.ino에 붙여넣습니다.
  • Python 코드 붙여넣기: python/main.py를 엽니다. 기존 내용을 모두 선택하고 삭제한 다음 위의 Python 코드를 붙여넣습니다.
  • HTML 파일 추가: assets/ 폴더에서 index.html을 열거나(또는 생성하고) 위의 HTML 코드를 붙여넣습니다.
  • Socket.IO 클라이언트 추가: assets/ 폴더에서 libs/ 하위 폴더를 생성합니다. socket.io.min.js를 다운로드하여 assets/libs/socket.io.min.js로 저장합니다.
  • Install the library: Click the Add sketch library button (the open book icon with a + sign) in the left sidebar.
add sketch 라이브러리 in 아두이노 app lab on Arduino UNO Q
  • Search for Arduino_RouterBridge created by Arduino and click the Install button.
My Apps / DIYables Apps
Run
Bricks
No bricks added...
Sketch Libraries
No sketch libra...
Files
python
sketch
.gitignore
README.md
app.yaml
sketch.ino
Add sketch library
Arduino_RouterBridge Arduino

This library provides a simple RPC bridge for Arduino UNO Q boards, allowing communication between the board and other devices using MsgPack serialization.

0.4.1
Install
More Info
  • WebUI Brick 추가: Editor 사이드바의 Add Brick 버튼을 클릭하여 Bricks 카탈로그를 엽니다.
add brick 버튼 in 아두이노 app lab editor sidebar

목록에서 WebUI - HTML을 찾아 선택한 다음 구성 프롬프트를 따릅니다.

webui - html brick selected in 아두이노 app lab bricks catalog

Arduino App Lab이 자동으로 app.yaml 파일에 Brick 항목을 추가합니다 - 그 항목을 수동으로 편집하지 마세요.

※ 주의:

WebUI - HTML Brick은 HTTP 파일 서빙과 Socket.IO WebSocket을 모두 포트 7000의 단일 서비스에서 처리합니다. Socket.IO 클라이언트 스크립트는 assets/libs/socket.io.min.js에 배치되어야 합니다 — Brick이 호환되는 버전을 자동으로 제공하지는 않습니다. 자세한 내용은 About Bricks를 참조하세요.

  • 업로드: Arduino App Lab에서 Run 버튼을 클릭합니다.
click run 버튼 in 아두이노 app lab on Arduino UNO Q
  • 휴대폰 또는 PC의 웹 브라우저를 열고 다음으로 이동합니다:
http://<ARDUINO_UNO_Q_IP>:7000/

를 Python 콘솔에 표시된 IP 주소로 바꿉니다.

App Lab 콘솔 출력

DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
Message (Enter to send a message to "Newbiely" on usb(2820070321))
New Line
9600 baud
[2026-05-08 09:00:01] Bridge ready
DIYables_Apps
Stop
sketch.ino
1#include "Arduino_RouterBridge.h"
Serial Monitor
Python
2026-05-08 09:00:02.000 INFO - [WebUI.execute] WebUI: The application interface is available here: - Local URL: http://localhost:7000 - Network URL: http://192.168.0.45:7000 2026-05-08 09:00:02.001 INFO - [MainThread] App: App started

브라우저 출력

동일한 네트워크의 모든 브라우저에서 http://<ARDUINO_UNO_Q_IP>:7000/을 엽니다. LED 제어 페이지가 표시됩니다:

Arduino UNO Q websocket LED control page

페이지 표시:

  • 원형 LED 버튼 — 꺼졌을 때는 회색, 켜졌을 때는 노란색 글로우
  • LED 상태가 변경되면 즉시 업데이트되는 상태 텍스트 줄
  • 상단의 연결 상태 표시줄 — 파란색으로 "connected", 빨간색으로 "disconnected" 표시
  • WebSocket 연결이 설정될 때까지 버튼이 비활성화됩니다.

WebSocket 이벤트

브라우저와 Python 서버는 다음 Socket.IO 이벤트를 사용하여 통신합니다:

Direction Event Payload
Browser → Server get_state {}
Server → Browser led_status {"on" false}
Browser → Server toggle_led {}
Server → Browser led_status {"on" true/false}

프로젝트 아이디어

Arduino UNO Q의 WebSocket 패턴을 이해하면 많은 실시간 프로젝트에 적용할 수 있습니다:

  • 온도 모니터: MCU에서 DS18B20 센서를 실행하고 Bridge를 통해 get_temperature를 노출합니다 — Python 스레드가 매초 읽고 모든 브라우저에 temperature_update를 푸시합니다. 브라우저가 라이브 캔버스 온도계를 표시합니다.
  • 멀티 디바이스 제어: 두 개의 다른 브라우저에서 페이지를 엽니다 — client 인수 없이 ui.send_message()가 도달하기 때문에 모든 연결된 클라이언트가 즉시 모든 led_status 브로드캐스트를 수신합니다.
  • 센서 대시보드: 여러 Bridge 함수(온도, 습도, 조명 수준)를 노출하고 매초 모든 값이 포함된 단일 sensor_update 이벤트를 푸시합니다 — 페이지가 각 게이지를 동시에 업데이트합니다.
  • 양방향 메시징: 텍스트 입력을 페이지에 추가합니다 — 브라우저 측에서 socket.emit("chat", {text: "hello"}), ui.send_message("chat", {"text": "hello"})는 실시간으로 다른 모든 탭에 브로드캐스트합니다.
  • 경보 시스템: Python 푸시 루프에서 센서 값을 임계값에 비해 확인합니다 — 한계를 초과하면 메시지와 함께 alert 이벤트를 내보냅니다. 브라우저가 수신하고 다시 로드하지 않고 빨간 경고 배너를 표시합니다.

스스로 도전해보세요

Arduino UNO Q의 WebSocket으로 더 깊이 있게 가고 싶으신가요? 이러한 도전 과제를 시도해보세요:

  • 쉬움: 페이지에 두 번째 버튼을 추가하여 blink 이벤트를 보냅니다 — Python에서 on_message("blink", ...) Bridge를 세 번 호출하여 교대로 상태를 변경하고 각 호출 사이에 time.sleep(0.5)를 둡니다. WebSocket 서버를 차단하지 않고 LED가 깜박입니다.
  • 중간: 0에서 255 범위의 값을 가진 set_brightness 이벤트를 내보내는 슬라이더를 HTML에 추가합니다 — Python에서 on_message("set_brightness", ...) Bridge.call("set_brightness", value)를 호출하고 MCU 스케치는 analogWrite(LED_BUILTIN, value)를 사용하여 PWM을 통해 LED 밝기를 제어합니다.
  • 고급: 매 500ms마다 센서를 읽는(또는 시뮬레이션하는) Python 백그라운드 스레드를 추가하고 모든 클라이언트에 sensor_update를 푸시합니다 — 이를 동일한 페이지의 LED 토글과 결합하므로 실시간 푸시와 인터랙티브 제어가 단일 WebSocket 연결을 통해 동시에 작동합니다.