xiao-esp32s3-mqtt-dashboard について
複数の XIAO ESP32S3 を Mosquitto ブローカーとブラウザー画面につなぐ、MQTT ダッシュボード構築用スキルです。ブローカー設定、ファームウェア準備、導入、検証を扱い、全ボードで同じコンパイル済みスケッチを使えます。
主な機能
- 01Mosquitto ブローカーとファイアウォール設定
- 02MAC アドレス由来のボード ID
- 03MQTT によるタッチ値と LED 通信
- 04WebSocket 対応ブラウザーダッシュボード
- 05ファームウェアのコンパイルと書き込み
活用シーン
- 01複数ボードのタッチ値を監視
- 02ブラウザーからボードの LED を操作
- 03MQTT トピックで接続を検証
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ shain1912/ esp32-skills --skill xiao-esp32s3-mqtt-dashboardインストール後、Claude Code で/xiao-esp32s3-mqtt-dashboardを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
assets/esp32s3_mqtt_dashboard.ino.tplassets/dashboard_web/app.jsindex.htmlstyles.cssassets/mqtt-broker/mosquitto_listeners.confsetup_broker.ps1setup_firewall.ps1詳細
XIAO ESP32S3 マルチボード MQTT ダッシュボード
アーキテクチャ:N 台のボード(STA モード、同じ WiFi)→ MQTT ブローカー(Mosquitto、同じ WiFi 上の 1 台の PC)→ ブラウザーダッシュボード(MQTT-over-WebSocket、mqtt.js)。各ボードで同じファームウェアをコンパイルして実行します。各ボードが自身の MAC アドレスから一意の ID を導き出すため、ボードごとの編集は不要です。
基本的な arduino-cli のワークフローと注意点(PSRAM フラグ、DTR によるリセット固着の復旧、上限付きシリアル読み取り)については、まず(同じリポジトリ内の)xiao-esp32s3 スキルを読んでください。このスキルでは、ブローカー、ネットワーク、ダッシュボードのレイヤーを追加します。
ステップ 1 — 必ず最初にユーザーに確認する
認証情報を勝手に作成したり、ブローカーの実行場所を決めつけたりしないでください。次の点を確認します。
- WiFi SSID/パスワード — すべてのボードとブローカー PC が接続できるネットワークである必要があります(2.4 GHz。ESP32 は 5 GHz のネットワークを検出できません)。
- Mosquitto の実行場所 — この PC(スキルでセットアップします。ステップ 2 を参照)か、別の既存ブローカー(ホストとポートを確認し、ステップ 2 のローカルセットアップはスキップします)。
- 今回、実際のボードを複数台フラッシュするかどうか。ファームウェアには影響しません(ID は自動的に割り当てられます)が、「これをすべてのボードにフラッシュしてください」というユーザーへの指示の表現が変わります。
ステップ 2 — ブローカーをセットアップする(別の場所に既存のブローカーがある場合はスキップ)
Windows で、共有 WiFi 上にあるブローカーマシンの LAN IP を確認します。
Get-NetIPAddress -AddressFamily IPv4 | Where-Object {$_.InterfaceAlias -eq 'Wi-Fi'} | Select-Object IPAddress
Mosquitto がインストールされているか、何がリッスンしているかを確認します。
netstat -an | findstr "1883 9001"
Get-Service -Name mosquitto -ErrorAction SilentlyContinue
0.0.0.0:1883/0.0.0.0:9001 で何もリッスンしていない場合(これがデフォルトである理由については、以下の注意点 1~3 を参照)、assets/mqtt-broker/setup_broker.ps1 と assets/mqtt-broker/setup_firewall.ps1 をユーザーのワークスペース内で隣り合わせにコピーし、両方を管理者権限で実行します(通常のシェルでは何も通知されずに失敗する理由については、注意点 2 を参照)。
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 への公開が実際に機能していることを確認します(プロセスがリッスンしているだけでは不十分です)。
netstat -an | findstr "1883 9001" # expect 0.0.0.0:1883 and 0.0.0.0:9001, not 127.0.0.1
ステップ 3 — テンプレートからスケッチを生成する
assets/esp32s3_mqtt_dashboard.ino.tpl は動作確認済みのコードです。書き換えないでください。<workspace>\<name>\<name>.ino にコピーします(フォルダー名は .ino ファイル名と一致させる必要があります)。次のプレースホルダーを文字どおり置き換えます。
| プレースホルダー | 意味 | 例 |
|---|---|---|
__WIFI_SSID__ | WiFi SSID(2.4 GHz) | myhome |
__WIFI_PASS__ | WiFi パスワード | pass1234 |
__MQTT_HOST__ | ブローカーマシンの LAN IP | 192.168.0.42 |
スケッチに必要な追加ライブラリを 1 つインストールします(WiFi/WiFiClient はすでに esp32 コアに含まれています)。
arduino-cli lib install "PubSubClient"
ステップ 4 — コンパイルしてアップロードする
arduino-cli compile --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>
arduino-cli upload -p COM4 --fqbn esp32:esp32:XIAO_ESP32S3 <SKETCH_DIR>
ボードを追加するには、コンパイル済みのまったく同じスケッチを各ボードにフラッシュします。ボードごとの編集は不要です。
ステップ 5 — シリアルモニターに頼らずに確認する
フラッシュ直後に一度だけシリアルを読み取り、WiFi と MQTT が接続されたことを確認します(ベーススキルの read_serial.ps1 を使い、arduino-cli monitor は使わないでください)。その後は、シリアルポートを開くのをやめて、MQTT 経由で動作を確認します(再度開くと、実際には問題が再発していないのに、そう見えることがある理由については注意点 6 を参照してください)。
# expects: <topic-prefix>/<id>/status online, then a touch value every ~0.5s
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
mosquitto_pub -h <broker-ip> -p 1883 -t "xiao/<id>/led/set" -m "ON"
(mosquitto_sub/mosquitto_pub が PATH にない場合、通常は C:\Program Files\Mosquitto\ にある mosquitto.exe と同じ場所にあります。)
ステップ 6 — ダッシュボードを実行する
assets/dashboard_web/(index.html、app.js、styles.css)は静的サイトです。ビルド手順は不要で、入力するプレースホルダーもありません(ブローカーのアドレスは JS に埋め込まず、ページ上で入力します)。ユーザーの好みの方法で配信できます。たとえば次のようにします。
cd assets/dashboard_web
python -m http.server 8080
その後、http://localhost:8080 を開きます(同じ WiFi 上の別のデバイスからは http://<broker-ip>:8080 を開きます)。ブローカーの LAN IP を「ブローカーアドレス」欄に入力し、接続をクリックします。以降、この値は localStorage に保存されます。status/touch メッセージが届くと、ボードがカードとして自動的に表示されます。ボードごとのダッシュボード設定はなく、必要もありません。
MQTT トピックのスキーム
<id> はボード固有の、MAC アドレスを基に生成された 16 進数の ID です(4b4cf4 など。自動生成されます)。
そのため、同じブローカー上に多数のボードがあっても ID が重複することはありません。
| トピック | 方向 | ペイロード | 備考 |
|---|---|---|---|
xiao/<id>/touch | ボード → ダッシュボード | 整数文字列 | 500 ミリ秒ごと |
xiao/<id>/led/set | ダッシュボード → ボード | ON / OFF / TOGGLE | コマンド |
xiao/<id>/led/state | ボード → ダッシュボード | ON / OFF、保持されます | 現在の状態 |
xiao/<id>/status | ボード → ダッシュボード | online / offline、保持されます | LWT — 正常でない切断時に、ブローカーが offline を自動公開します |
タッチのベースラインは、ワイヤーやパッドに何も触れていない状態でおよそ 16,000~18,000 です。 タッチすると値は 40,000 を大きく超えます(ESP32-S3 のタッチ検出方向については、ベーススキルを参照してください)。
既知の落とし穴 —「デバッグ」の前にお読みください
- Mosquitto 2.x は、リスナーが設定されていない場合にのみループバックにバインドします —
これは意図的なセキュリティ上の既定動作であり、バグではありません。標準の
mosquitto.conf(すべてコメントで、listener行がない状態)を使った新規の Windows インストールでは、netstatに127.0.0.1:1883が表示されます。明示的なlistener 1883 0.0.0.0を追加するまでは、0.0.0.0:1883は表示されません。 - Windows の Mosquitto サービスは
LocalSystemとして実行されます。 通常の (管理者権限のない)シェルでは、Stop-Service/Restart-ServiceからAccess is deniedが通知なしに返され、C:\Program Files\Mosquitto\mosquitto.confに書き込むこともできません。Start-Process powershell -Verb RunAs -Waitを使い、2 つのセットアップスクリプトを 管理者権限で実行してください(ステップ 2)。これは、ユーザーがすでに依頼した設定変更のための、 正当かつ対象を限定した UAC 昇格の使用です。権限昇格の回避策ではなく、同意プロンプトでユーザー自身が 「はい」をクリックする必要があります。 - Windows ファイアウォールは、新たに開いたポートへの LAN からの受信接続を既定でブロックします。
特に、WiFi アダプターのネットワークプロファイルが「パブリック」の場合は注意してください
(
Get-NetConnectionProfileで確認できます)。Mosquitto のリスナーを開くだけでは不十分です。 両方のポートについて、明示的なNew-NetFirewallRule -Direction Inboundルールを追加してください (ステップ 2 のsetup_firewall.ps1)。誤検知に関する警告: ブローカーマシン自体から実行したTest-NetConnection <own-LAN-IP> -Port 1883は、 実際のリモートデバイスからの接続がファイアウォールにブロックされる場合でも、TcpTestSucceeded: Trueと表示することがあります。自分自身の LAN IP へのテストは、 実際のボードからのテストの代わりとして信頼できません。 PubSubClient::connect()がrc=-2を返す場合(MQTT_CONNECT_FAILED)は、 TCP 接続自体が失敗したことを意味します。ブローカーに到達できないか、ファイアウォールでブロックされています。 認証情報や認証拒否の問題ではありません。このエラーでallow_anonymous/ユーザー名の設定を調べても 時間の無駄です。まず落とし穴 1 と 3 を確認してください。- ESP32S3 のシリアルポートを開くたびにボードがリセットされます(DTR の切り替え。ベーススキルの
落とし穴 1 と同じです)。ただし、すでに WiFi/MQTT に接続しているボードでは、再起動するだけでは済みません。
ポートを閉じると、リセット状態から抜け出せなくなることがあります(ベーススキルの落とし穴 8)。
その数秒後に MQTT セッションが切断されます。その結果、ファームウェア自体には問題がないのに、
ブローカーは LWT を使ってボードを
offlineと報告します。WiFi と MQTT の接続ログを一度確認できたら、 シリアルポートを再び開くのはやめてください。以降の稼働状況はmosquitto_subまたはダッシュボードで 確認し、「念のための再確認」のためにシリアルポートを再度開かないでください。 - ブラウザーは生の MQTT を TCP 経由で通信できません。 ダッシュボードには、Mosquitto の
別個の
listener 9001 ... protocol websocketsが必要です。落とし穴 1〜3 と同じallow_anonymous/ファイアウォールの要件が、ポート 1883 とは別に適用されます。 「ファームウェアは問題なく接続するのに、ダッシュボードには何も表示されない」場合、 ほとんどは WebSocket リスナーの設定漏れが原因です。 - 共有テンプレートに、特定ユーザーの WiFi SSID/パスワードや、特定マシンの LAN IP をハードコードしないでください。 ユーザーに確認し(ステップ 1)、各デプロイメントに合わせてテンプレートに反映してください(ステップ 3)。 また、DHCP で割り当てられたブローカーの IP は、その PC の再起動で変わる場合があることも伝えてください。 ルーター側で DHCP 予約を設定しておけば、その後、すべてのボードを再書き込みする必要がなくなります。
- 各ボードは、トピックごとに一意となる ID をそれぞれ生成する必要があります(テンプレートと同様に
MAC アドレスを基にします)。固定のクライアント ID/トピックは使わないでください。同じ MQTT クライアント ID を
2 台のボードで使うと、接続を奪い合って繰り返し切断されます。また、同じトピックを 2 台のボードで使うと、
ダッシュボード上で互いの
touch/led/stateの値が上書きされます。