xiao-esp32s3-mqtt-dashboard
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseXIAO ESP32S3 multi-board MQTT dashboard
XIAO ESP32S3 多板MQTT仪表盘
Architecture: N boards (STA mode, same WiFi) → MQTT broker (Mosquitto, one PC
on that WiFi) → browser dashboard (MQTT-over-WebSocket, ). Each board
runs the same compiled firmware — no per-board edits — because it derives a
unique ID from its own MAC address.
mqtt.jsRead the skill (same repo) first for base arduino-cli workflow
and pitfalls (PSRAM flag, DTR reset-stuck recovery, bounded serial reads).
This skill adds the broker + networking + dashboard layer on top.
xiao-esp32s3架构:N块开发板(STA模式,接入同一WiFi)→ MQTT代理(Mosquitto,部署在该WiFi网络内的一台PC上)→ 浏览器仪表盘(基于WebSocket的MQTT,使用)。每块开发板运行相同的编译后固件——无需针对单块板修改——因为它会通过自身MAC地址生成唯一ID。
mqtt.js请先阅读技能(同一仓库),了解基础arduino-cli工作流程及常见问题(PSRAM标志、DTR重置卡顿恢复、有限串行读取)。本技能在其基础上增加了代理、网络及仪表盘层。
xiao-esp32s3Step 1 — ALWAYS ask the user first
步骤1 — 务必先询问用户
Never invent credentials or assume where the broker runs. Ask for:
- WiFi SSID / password — must be a network every board and the broker PC can join (2.4 GHz; ESP32 cannot see 5 GHz networks).
- Where Mosquitto runs — this PC (skill sets it up, see Step 2), or an existing broker elsewhere (get host + port, skip Step 2's local setup).
- Whether more than one physical board will be flashed now (affects nothing in the firmware — it self-assigns IDs — but changes how you phrase the "flash this to every board" instruction back to the user).
切勿自行设置凭证或假设代理部署位置,请向用户确认以下信息:
- WiFi SSID/密码 — 必须是所有开发板和代理PC都能接入的网络(仅支持2.4 GHz;ESP32无法识别5 GHz网络)。
- Mosquitto部署位置 — 本地PC(本技能将指导搭建,见步骤2),或已存在的远程代理(需获取主机地址和端口,跳过步骤2的本地搭建)。
- 当前是否要刷写多块物理开发板(对固件无影响——固件会自动分配ID——但会影响向用户说明“将此固件刷写到所有开发板”的表述方式)。
Step 2 — set up the broker (skip if one already exists elsewhere)
步骤2 — 搭建代理(若已有远程代理则跳过)
Find the broker machine's LAN IP on the shared WiFi (Windows):
powershell
Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -eq 'Wi-Fi'} | Select-Object IPAddressCheck whether Mosquitto is installed and what's listening:
powershell
netstat -an | findstr "1883 9001"
Get-Service -Name mosquitto -ErrorAction SilentlyContinueIf nothing is listening on / (see pitfalls 1–3
below for why this is the default), copy
and next to each other in the user's
workspace, then run both elevated (see pitfall 2 for why a plain shell
silently fails):
0.0.0.0:18830.0.0.0:9001assets/mqtt-broker/setup_broker.ps1assets/mqtt-broker/setup_firewall.ps1powershell
Start-Process powershell -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','<path>\setup_broker.ps1' -Verb RunAs -Wait
Start-Process powershell -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','<path>\setup_firewall.ps1' -Verb RunAs -WaitThis triggers a Windows UAC consent prompt — tell the user it will appear and
that they need to click "Yes"; you cannot click it for them. Both scripts
write a next to themselves — read it back to confirm
success instead of assuming the elevated window's own output was captured.
setup_result.txtVerify LAN exposure actually worked (not just that the process is listening):
powershell
netstat -an | findstr "1883 9001" # expect 0.0.0.0:1883 and 0.0.0.0:9001, not 127.0.0.1在共享WiFi网络中查找代理机器的LAN IP(Windows系统):
powershell
Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -eq 'Wi-Fi'} | Select-Object IPAddress检查Mosquitto是否已安装及监听端口:
powershell
netstat -an | findstr "1883 9001"
Get-Service -Name mosquitto -ErrorAction SilentlyContinue若/无监听(以下问题1-3将说明默认情况),请将和复制到用户工作目录中,然后以管理员权限运行两个脚本(问题2将说明普通Shell会静默执行失败):
0.0.0.0:18830.0.0.0:9001assets/mqtt-broker/setup_broker.ps1assets/mqtt-broker/setup_firewall.ps1powershell
Start-Process powershell -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','<path>\setup_broker.ps1' -Verb RunAs -Wait
Start-Process powershell -ArgumentList '-NoProfile','-ExecutionPolicy','Bypass','-File','<path>\setup_firewall.ps1' -Verb RunAs -Wait这会触发Windows UAC授权提示——请告知用户将弹出该提示,需点击“是”;你无法替用户操作。两个脚本会在自身目录下生成——请读取该文件确认操作成功,不要假设管理员窗口的输出已被捕获。
setup_result.txt验证LAN暴露是否生效(不只是进程在监听):
powershell
netstat -an | findstr "1883 9001" # 预期显示0.0.0.0:1883和0.0.0.0:9001,而非127.0.0.1Step 3 — generate the sketch from the template
步骤3 — 从模板生成代码草图
assets/esp32s3_mqtt_dashboard.ino.tpl<workspace>\<name>\<name>.ino.ino| Placeholder | Meaning | Example |
|---|---|---|
| WiFi SSID (2.4 GHz) | |
| WiFi password | |
| broker machine's LAN IP | |
Install the one extra library the sketch needs (/ ship with
the esp32 core already):
WiFiWiFiClientpowershell
arduino-cli lib install "PubSubClient"assets/esp32s3_mqtt_dashboard.ino.tpl<workspace>\<name>\<name>.ino.ino| 占位符 | 含义 | 示例 |
|---|---|---|
| WiFi SSID(2.4 GHz) | |
| WiFi密码 | |
| 代理机器的LAN IP | |
安装代码草图所需的额外库(/已随esp32核心库附带):
WiFiWiFiClientpowershell
arduino-cli lib install "PubSubClient"Step 4 — compile, upload
步骤4 — 编译、上传
powershell
arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>
arduino-cli upload -p COM4 --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>To add more boards, flash the exact same compiled sketch to each one — no
edits needed between boards.
powershell
arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>
arduino-cli upload -p COM4 --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>如需添加更多开发板,将完全相同的编译后固件刷写到每块板即可——无需在板间修改代码。
Step 5 — verify WITHOUT living in the serial monitor
步骤5 — 无需依赖串口监视器验证
Read serial ONCE right after flashing to confirm WiFi + MQTT connect (use the
base skill's , never ). After that,
stop opening the serial port and verify ongoing behavior purely over MQTT
(pitfall 6 explains why re-opening it can look like a regression that isn't
one):
read_serial.ps1arduino-cli monitorpowershell
undefined刷写完成后读取一次串口,确认WiFi+MQTT连接成功(使用基础技能的,切勿使用)。之后,停止打开串口,仅通过MQTT验证持续运行状态(问题6将说明重新打开串口可能会导致看似回归的误判):
read_serial.ps1arduino-cli monitorpowershell
undefinedexpects: <topic-prefix>/<id>/status online, then a touch value every ~0.5s
预期输出:<topic-prefix>/<id>/status online,之后每约0.5秒输出一次触摸数值
mosquitto_sub -h <broker-ip> -p 1883 -t "xiao/#" -v
mosquitto_sub -h <broker-ip> -p 1883 -t "xiao/#" -v
flip a board's LED from the command line the same way the dashboard does
与仪表盘操作方式相同,从命令行切换开发板LED状态
mosquitto_pub -h <broker-ip> -p 1883 -t "xiao/<id>/led/set" -m "ON"
(If `mosquitto_sub`/`mosquitto_pub` aren't on PATH, they ship next to
`mosquitto.exe`, typically `C:\Program Files\Mosquitto\`.)mosquitto_pub -h <broker-ip> -p 1883 -t "xiao/<id>/led/set" -m "ON"
(若`mosquitto_sub`/`mosquitto_pub`不在PATH中,它们随`mosquitto.exe`一同安装,通常位于`C:\Program Files\Mosquitto\`目录下。)Step 6 — run the dashboard
步骤6 — 运行仪表盘
assets/dashboard_web/index.htmlapp.jsstyles.csspowershell
cd assets/dashboard_web
python -m http.server 8080Then open (or from another
device on the same WiFi). Type the broker's LAN IP into the "브로커 주소" box
and click 연결 — it remembers the value in after that. Boards
appear as cards automatically as their / messages arrive; no
per-board dashboard configuration exists or is needed.
http://localhost:8080http://<broker-ip>:8080localStoragestatustouchassets/dashboard_web/index.htmlapp.jsstyles.csspowershell
cd assets/dashboard_web
python -m http.server 8080然后打开(或从同一WiFi网络内的其他设备打开)。在“브로커 주소”输入框中输入代理的LAN IP并点击“연결”——之后该值会保存在中。当开发板发送/消息时,会自动以卡片形式显示在仪表盘中;无需针对单块板配置仪表盘。
http://localhost:8080http://<broker-ip>:8080localStoragestatustouchMQTT topic scheme
MQTT主题规则
<id>4b4cf4| Topic | Direction | Payload | Notes |
|---|---|---|---|
| board → dashboard | integer string | every 500 ms |
| dashboard → board | | command |
| board → dashboard | | current state |
| board → dashboard | | LWT — broker auto-publishes |
Touch baseline is roughly 16,000–18,000 on bare wire/pad; values RISE well
past 40,000 when touched (ESP32-S3 touch direction — see base skill).
<id>4b4cf4| 主题 | 方向 | 负载 | 说明 |
|---|---|---|---|
| 开发板→仪表盘 | 整数字符串 | 每500毫秒发送一次 |
| 仪表盘→开发板 | | 控制指令 |
| 开发板→仪表盘 | | 当前状态 |
| 开发板→仪表盘 | | LWT——当开发板异常断开时,代理会自动发布 |
裸线/焊盘的触摸基准值约为16000–18000;触摸时数值会升至40000以上(ESP32-S3触摸数值变化方向——见基础技能)。
Known pitfalls — read before "debugging"
已知问题——调试前请阅读
- Mosquitto 2.x binds to loopback ONLY when no listener is configured —
this is a deliberate security default, not a bug. A fresh Windows install
with the stock (all comments, no
mosquitto.confline) will showlistenerin127.0.0.1:1883, nevernetstat, until you add an explicit0.0.0.0:1883.listener 1883 0.0.0.0 - The Windows Mosquitto service runs as . A normal (non-admin) shell gets a silent
LocalSystemfromAccess is denied/Stop-Service, and cannot writeRestart-Serviceeither. UseC:\Program Files\Mosquitto\mosquitto.confto run the two setup scripts elevated (Step 2) — this is a legitimate, narrowly-scoped use of UAC elevation for a config change the user already asked for; it is not a privilege-escalation workaround, and it still requires the user to click "Yes" on the consent prompt themselves.Start-Process powershell -Verb RunAs -Wait - Windows Firewall blocks LAN-inbound to a newly opened port by default,
especially when the WiFi adapter's network profile is "Public" (check with
). Opening the Mosquitto listener alone is not enough — add explicit
Get-NetConnectionProfilerules for both ports (Step 2'sNew-NetFirewallRule -Direction Inbound). False-positive warning:setup_firewall.ps1run FROM the broker machine itself can reportTest-NetConnection <own-LAN-IP> -Port 1883even when the firewall would block a genuinely remote device — self-to-self tests over your own LAN IP are not a reliable substitute for testing from the actual board.TcpTestSucceeded: True - returning
PubSubClient::connect()(rc=-2) means the TCP connection itself failed — broker unreachable or firewalled — not a credentials/auth rejection. ChasingMQTT_CONNECT_FAILED/username config for this code wastes time; check pitfalls 1 and 3 first.allow_anonymous - Opening the ESP32S3's serial port resets the board every time (DTR
toggle, same as the base skill's pitfall 1) — but for a board that's
already connected to WiFi/MQTT, this doesn't just cost a reboot: closing
the port afterward can leave it in the reset-stuck state (base skill
pitfall 8), which drops the MQTT session a few seconds later. The broker
then reports that board via its LWT even though the firmware itself has no bug. Once you've confirmed the WiFi+MQTT connect log once, stop opening the serial port — verify ongoing liveness with
offlineor the dashboard instead, never by reopening serial to "just double check."mosquitto_sub - Browsers cannot speak raw MQTT over TCP. The dashboard needs
Mosquitto's separate — the same
listener 9001 ... protocol websockets/firewall requirements from pitfalls 1–3 apply to it independently of port 1883. "Firmware connects fine, dashboard shows nothing" almost always means the websockets listener was forgotten.allow_anonymous - Never hardcode one user's WiFi SSID/password or one machine's LAN IP into a shared template. Ask (Step 1), template it in (Step 3) per deployment. Also warn that a DHCP-assigned broker IP can change on that PC's reboot — a router-side DHCP reservation avoids having to re-flash every board afterward.
- Each board must derive its own topic-unique ID (MAC-based, as the
template does) rather than using a fixed client ID/topic — two boards with
the same MQTT client ID will fight over the connection (repeated
disconnects) and two boards on the same topic will stomp each other's
/
touchvalues on the dashboard.led/state
- 未配置监听时,Mosquitto 2.x仅绑定回环地址——这是刻意设置的安全默认值,并非Bug。全新Windows安装使用默认(全注释,无
mosquitto.conf行)时,listener会显示netstat,而非127.0.0.1:1883,需添加显式配置0.0.0.0:1883。listener 1883 0.0.0.0 - Windows Mosquitto服务以身份运行。普通(非管理员)Shell执行
LocalSystem/Stop-Service会静默返回Restart-Service,且无法写入Access is denied。请使用C:\Program Files\Mosquitto\mosquitto.conf以管理员权限运行两个设置脚本(步骤2)——这是用户请求的合法、窄范围配置变更,并非权限提升手段,仍需用户在授权提示中点击“是”。Start-Process powershell -Verb RunAs -Wait - Windows防火墙默认阻止新开放端口的LAN入站连接,尤其是当WiFi适配器的网络配置文件为“公共”时(可通过查看)。仅打开Mosquitto监听端口不足以解决问题——需为两个端口添加显式
Get-NetConnectionProfile规则(步骤2的New-NetFirewallRule -Direction Inbound已包含)。误判警告:在代理机器上运行setup_firewall.ps1可能会返回Test-NetConnection <own-LAN-IP> -Port 1883,但防火墙仍会阻止真正远程设备的连接——自身LAN IP的自测试无法替代实际开发板的测试。TcpTestSucceeded: True - 返回
PubSubClient::connect()(rc=-2)表示TCP连接失败——代理不可达或被防火墙阻止——并非凭证/授权拒绝。针对此代码排查MQTT_CONNECT_FAILED/用户名配置纯属浪费时间,请先检查问题1和3。allow_anonymous - 打开ESP32S3串口会每次重置开发板(DTR切换,与基础技能的问题1相同)——但对于已连接WiFi/MQTT的开发板,这不仅会导致重启:关闭串口后可能会使开发板陷入重置卡顿状态(基础技能的问题8),几秒后MQTT会话会断开。此时代理会通过LWT报告该开发板,但固件本身并无Bug。一旦确认WiFi+MQTT连接日志无误,请勿再打开串口——请使用
offline或仪表盘验证持续运行状态,切勿为“再次确认”而重新打开串口。mosquitto_sub - 浏览器无法通过TCP直接传输原始MQTT数据。仪表盘需要Mosquitto单独配置——问题1-3中的
listener 9001 ... protocol websockets/防火墙要求同样适用于该端口,与1883端口独立。“固件连接正常,但仪表盘无显示”几乎总是因为忘记配置WebSocket监听。allow_anonymous - 切勿将用户的WiFi SSID/密码或某台机器的LAN IP硬编码到共享模板中。请询问用户(步骤1),并针对每次部署进行模板替换(步骤3)。同时提醒用户:DHCP分配的代理IP可能会在PC重启后变更——在路由器端设置DHCP保留可避免重新刷写所有开发板。
- 每块开发板必须生成自身的主题唯一ID(如模板中基于MAC地址生成),而非使用固定客户端ID/主题——两个使用相同MQTT客户端ID的开发板会争夺连接(反复断开),两个使用相同主题的开发板会在仪表盘中覆盖彼此的/
touch数值。led/state