Arduino UNO Q - WebSocket

The Arduino UNO Q supports WebSocket out of the box through the WebUI Brick — no extra library to install, no separate server process to start. The WebUI Brick provides a Socket.IO WebSocket server on the same port 7000 as the HTTP file server. Python handles incoming events with ui.on_message() and pushes data back to one client or all clients with ui.send_message(). On the browser side, the Socket.IO client connects automatically and uses socket.emit() to send events and socket.on() to receive them.

This tutorial teaches the WebSocket pattern on Arduino UNO Q using a simple LED control example: clicking a button in the browser toggles the built-in LED on the board and instantly updates the status for every connected browser — no page refresh, no polling.

In this tutorial, you will learn:

Arduino UNO Q WebSocket

Hardware Preparation

1×Arduino UNO Q
1×USB Cable for Arduino Uno Q
1×Recommended: Screw Terminal Block Shield for Arduino Uno
1×Recommended: Sensors/Servo Expansion Shield for Arduino Uno
1×Recommended: Breadboard Shield for Arduino Uno
1×Recommended: Enclosure for Arduino Uno
1×Recommended: Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables Sensor Kit (18 sensors/displays)
Disclosure: Some of the links provided in this section are Amazon affiliate links. We may receive a commission for any purchases made through these links at no additional cost to you.
Additionally, some of these links are for products from our own brand, DIYables .

No external components are needed — this tutorial uses the built-in LED on the Arduino UNO Q.

Overview of WebSocket on Arduino UNO Q

  • WebUI Brick Socket.IO server: The WebUI Brick starts both an HTTP file server and a Socket.IO WebSocket server on port 7000. You do not need to install Flask, the websockets library, or any other package — the Brick handles everything automatically. The Socket.IO client script is served at /socket.io/socket.io.js so the HTML page loads it directly from the board.
  • Python event handlers: Register a handler for an incoming browser event with ui.on_message("event_name", handler). The handler receives two arguments: client (the sender) and data (the JSON payload). To reply only to the sender, call ui.send_message("event_name", payload, client). To broadcast to all connected clients, omit the third argument: ui.send_message("event_name", payload).
  • Browser Socket.IO client: Include /socket.io/socket.io.js in the HTML page, then open a connection with const socket = io("http://" + window.location.host). Send an event with socket.emit("event_name", {}) and listen for server events with socket.on("event_name", function(data) { ... }).
  • MCU calls from Python: Use Bridge.call("function_name", argument) in Python to call a function registered in the MCU sketch with Bridge.provide("function_name", handler). This is how Python controls hardware from a WebSocket event.

Arduino UNO Q Code

The Arduino UNO Q has two processors working together:

  • The STM32 MCU exposes a set_led function via Bridge that turns the built-in LED on or off.
  • The Qualcomm MPU runs a Python app that listens for WebSocket events from the browser, calls Bridge to control the LED, and broadcasts the new LED state back to all connected clients.

MCU Code

/* * This Arduino UNO Q code was developed by newbiely.com * * This Arduino UNO Q code is made available for public use without any restriction * * For comprehensive instructions and wiring diagrams, please visit: * https://newbiely.com/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 Code

""" This Arduino UNO Q script was developed by newbiely.com This Arduino UNO Q script is made available for public use without any restriction For comprehensive instructions and wiring diagrams, please visit: https://newbiely.com/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)

Place this file in the assets/ folder of your App. It loads the Socket.IO client from the WebUI Brick (/socket.io/socket.io.js) and shows a button that toggles the built-in 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>

Detailed Instructions

  • Connect to Wi-Fi: Make sure the Arduino UNO Q is connected to your Wi-Fi network. Use the network icon in Arduino App Lab to connect first.
  • Open Arduino App Lab: Launch Arduino App Lab and wait until it detects your Arduino UNO Q.
  • Create a new App: Click the Create New App button.
Create New App in Arduino App Lab on Arduino UNO Q
  • Give the App a name, for example: WebSocketLED
  • Click Create to confirm.
Arduino App Lab App folders and files on Arduino UNO Q
  • Paste the MCU sketch: Copy the MCU code above and paste it into sketch/sketch.ino.
  • Paste the Python code: Open python/main.py. Select all existing content and delete it, then paste the Python code above.
  • Add the HTML file: In the assets/ folder, open (or create) index.html and paste the HTML code above.
  • Add the Socket.IO client: In the assets/ folder, create a libs/ subfolder. Download socket.io.min.js and save it as 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 library in Arduino 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
  • Add the WebUI Brick: Click the Add Brick button in the Editor sidebar to open the Bricks catalog.
Add Brick button in Arduino App Lab Editor sidebar

Find and select WebUI - HTML from the list, then follow any configuration prompts.

WebUI - HTML Brick selected in Arduino App Lab Bricks catalog

Arduino App Lab automatically adds the Brick entry to your app.yaml file — do not edit that entry manually.

※ NOTE THAT:

The WebUI - HTML Brick handles both HTTP file serving and Socket.IO WebSocket in a single service on port 7000. The Socket.IO client script must be placed in assets/libs/socket.io.min.js — the brick does not serve a compatible version automatically. See About Bricks for details.

  • Upload: Click the Run button in Arduino App Lab to compile and upload.
Click Run button in Arduino App Lab on Arduino UNO Q
  • Open a web browser on your phone or PC and navigate to:
http://<ARDUINO_UNO_Q_IP>:7000/

Replace <ARDUINO_UNO_Q_IP> with the IP address shown in the Python console.

App Lab Console Output

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

Browser Output

Open http://<ARDUINO_UNO_Q_IP>:7000/ in any browser on the same network. You will see the LED control page:

Arduino UNO Q WebSocket LED Control Page

The page displays:

  • A circular LED button — grey when off, yellow with a glow when on
  • A status text line that updates instantly when the LED state changes
  • A connection status bar at the top — shows "connected" in blue, "disconnected" in red
  • The button is disabled until the WebSocket connection is established

WebSocket Events

The browser and the Python server communicate using the following Socket.IO events:

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

Project Ideas

Once you understand the WebSocket pattern on Arduino UNO Q, you can apply it to many real-time projects:

  • Temperature Monitor: Run a DS18B20 sensor on the MCU and expose get_temperature via Bridge — a Python thread reads it every second and pushes temperature_update to all browsers, which display a live canvas thermometer
  • Multi-Device Control: Open the page in two different browsers — both receive every led_status broadcast instantly because ui.send_message() without a client argument reaches all connected clients at once
  • Sensor Dashboard: Expose multiple Bridge functions (temperature, humidity, light level) and push a single sensor_update event every second with all values — the page updates each gauge simultaneously
  • Bidirectional Messaging: Add a text input to the page — socket.emit("chat", {text: "hello"}) on the browser side, ui.send_message("chat", {"text": "hello"}) broadcasts it to all other tabs in real time
  • Alert System: In the Python push loop, check a sensor value against a threshold — if it crosses the limit, emit an alert event with a message; the browser listens and shows a red warning banner without reloading

Challenge Yourself

Ready to go deeper with WebSocket on Arduino UNO Q? Try these challenges:

  • Easy: Add a second button to the page that sends a blink event — in Python, on_message("blink", ...) calls Bridge three times with alternating states and a time.sleep(0.5) between each call, making the LED blink without blocking the WebSocket server.
  • Medium: Add a slider to the HTML that emits a set_brightness event with a value from 0 to 255 — in Python, on_message("set_brightness", ...) calls Bridge.call("set_brightness", value) and the MCU sketch uses analogWrite(LED_BUILTIN, value) to control LED brightness via PWM.
  • Advanced: Add a Python background thread that reads a sensor (or simulates one) every 500 ms and pushes sensor_update to all clients — combine this with the LED toggle on the same page so both real-time push and interactive control work simultaneously through a single WebSocket connection.

※ OUR MESSAGES

  • As freelancers, We are AVAILABLE for HIRE. See how to outsource your project to us
  • Please feel free to share the link of this tutorial. However, Please do not use our content on any other websites. We invested a lot of effort and time to create the content, please respect our work!