【PoC】Track-Bay:Node-RED + MQTTでトラックバース予約を最短構築(標準ノードのみ)
対象
- スマホ→予約→Dashboard反映までを最短で体験したい
- 追加ノードなし(標準の
node-red-dashboard
のみ)で動かしたい
ゴール
- スマホ(ブラウザ)から予約データを送信
- Node-RED Dashboard に予約一覧を表示
- MQTT(Mosquitto)でメッセージを確認
前提
- Node-RED が動作(
http://localhost:1880
を開ける) -
Dashboardノード(
node-red-dashboard
)がインストール済み- ※ 未導入なら:メニュー → パレットの管理 → “ノードを追加” →
node-red-dashboard
- ※ 未導入なら:メニュー → パレットの管理 → “ノードを追加” →
セットアップ(Ubuntuの例)
1) Node.js & Node-RED
bash
bash <(curl -sL https://raw.githubusercontent.com/node-red/linux-installers/master/deb/update-nodejs-and-nodered)
node-red-start
2) MQTTブローカ(Mosquitto)
bash
sudo apt update
sudo apt install -y mosquitto mosquitto-clients
sudo systemctl enable --now mosquitto
Windowsの場合:Node-RED / Mosquitto を各公式からインストール。以降の手順は同様。
使い方:フローをインポート
- Node-RED エディタ → メニュー → インポート → 下のJSONを貼り付け → Import → Deploy
- Dashboard を開く:
http://<ホスト>:1880/ui
json
[
{ "id": "flow-trackbay", "type": "tab", "label": "Track-Bay Flow", "disabled": false, "info": "" },
{ "id": "ui-base", "type": "ui_base",
"theme": { "name": "theme-light",
"lightTheme": { "default": "#0094CE", "baseColor": "#ffffff", "baseFont": "Helvetica Neue", "edited": true, "reset": false },
"darkTheme": { "default": "#097479", "baseColor": "#111111", "baseFont": "Helvetica Neue", "edited": true, "reset": false } },
"site": { "name": "Track-Bay", "hideToolbar": "false", "allowSwipe": "true", "lockMenu": "false", "allowTempTheme": "true", "dateFormat": "YYYY-MM-DD",
"sizes": { "sx": 48, "sy": 48, "gx": 6, "gy": 6, "cx": 6, "cy": 6, "px": 0, "py": 0 } } },
{ "id": "tab-trackbay", "type": "ui_tab", "z": "", "name": "Track-Bay", "icon": "dashboard", "order": 1 },
{ "id": "grp-reserve", "type": "ui_group", "z": "", "name": "予約フォーム", "tab": "tab-trackbay", "order": 1, "disp": true, "width": "6", "collapse": false },
{ "id": "grp-list", "type": "ui_group", "z": "", "name": "予約一覧", "tab": "tab-trackbay", "order": 2, "disp": true, "width": "6", "collapse": false },
{ "id": "mqtt-local", "type": "mqtt-broker", "name": "Local Mosquitto", "broker": "127.0.0.1", "port": "1883",
"clientid": "", "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true,
"birthTopic": "", "birthQos": "0", "birthPayload": "", "closeTopic": "", "closePayload": "",
"willTopic": "", "willQos": "0", "willPayload": "" },
{ "id": "ui-form", "type": "ui_form", "z": "flow-trackbay", "name": "予約入力", "label": "Track-Bay 予約",
"group": "grp-reserve", "order": 0, "width": 0, "height": 0,
"options": [
{ "label": "バース番号 (1-20)", "value": "bay", "type": "number", "required": true },
{ "label": "開始 (HH:MM)", "value": "from", "type": "text", "required": true },
{ "label": "終了 (HH:MM)", "value": "to", "type": "text", "required": true },
{ "label": "担当者名", "value": "user", "type": "text", "required": true }
],
"payload": "", "submit": "予約する", "cancel": "クリア", "topic": "",
"x": 200, "y": 140, "wires": [["fn-build"]] },
{ "id": "fn-build", "type": "function", "z": "flow-trackbay", "name": "予約メッセージ整形",
"func": "const p = msg.payload || {};\nconst now = Date.now();\nmsg.topic = \"trackbay/reserve\";\nmsg.payload = {\n bay: Number(p.bay || 0),\n from: String(p.from || \"\"),\n to: String(p.to || \"\"),\n user: String(p.user || \"\"),\n ts: now\n};\nreturn msg;",
"outputs": 1, "noerr": 0, "x": 460, "y": 140, "wires": [["mqtt-out"]] },
{ "id": "mqtt-out", "type": "mqtt out", "z": "flow-trackbay", "name": "", "topic": "", "qos": "0", "retain": "",
"broker": "mqtt-local", "x": 720, "y": 140, "wires": [] },
{ "id": "mqtt-in", "type": "mqtt in", "z": "flow-trackbay", "name": "", "topic": "trackbay/reserve", "qos": "0",
"datatype": "auto", "broker": "mqtt-local", "nl": false, "rap": true, "rh": 0, "x": 200, "y": 240,
"wires": [["fn-store"]] },
{ "id": "fn-store", "type": "function", "z": "flow-trackbay", "name": "配列に蓄積(flow)",
"func": "let arr = flow.get('reservations') || [];\narr = arr.concat([msg.payload]);\nflow.set('reservations', arr);\nmsg.payload = arr;\nreturn msg;",
"outputs": 1, "noerr": 0, "x": 460, "y": 240, "wires": [["fn-view"]] },
{ "id": "fn-view", "type": "function", "z": "flow-trackbay", "name": "表示用に整形",
"func": "const arr = Array.isArray(msg.payload) ? msg.payload : [];\nmsg.payload = arr.map(r => ({\n tsText: new Date(r.ts).toLocaleString(),\n bay: r.bay,\n from: r.from,\n to: r.to,\n user: r.user\n}));\nreturn msg;",
"outputs": 1, "noerr": 0, "x": 700, "y": 240, "wires": [["ui-tpl"]] },
{ "id": "ui-tpl", "type": "ui_template", "z": "flow-trackbay", "group": "grp-list", "name": "予約一覧(標準)",
"order": 0, "width": 0, "height": 0,
"format": "<table style=\"width:100%\">\n <thead>\n <tr>\n <th style=\"text-align:left\">時刻</th>\n <th style=\"text-align:right\">バース</th>\n <th style=\"text-align:center\">開始</th>\n <th style=\"text-align:center\">終了</th>\n <th style=\"text-align:left\">担当</th>\n </tr>\n </thead>\n <tbody>\n <tr ng-repeat=\"r in msg.payload track by $index\">\n <td>{{r.tsText}}</td>\n <td style=\"text-align:right\">{{r.bay}}</td>\n <td style=\"text-align:center\">{{r.from}}</td>\n <td style=\"text-align:center\">{{r.to}}</td>\n <td>{{r.user}}</td>\n </tr>\n </tbody>\n</table>",
"storeOutMessages": true, "fwdInMessages": true, "resendOnRefresh": true, "templateScope": "local",
"x": 930, "y": 240, "wires": [[]] },
{ "id": "init", "type": "inject", "z": "flow-trackbay", "name": "起動時に一覧表示", "props": [],
"repeat": "", "crontab": "", "once": true, "onceDelay": "0.5", "topic": "",
"x": 190, "y": 300, "wires": [["read-list"]] },
{ "id": "read-list", "type": "function", "z": "flow-trackbay", "name": "flow→msg",
"func": "msg.payload = flow.get('reservations') || [];\nreturn msg;",
"outputs": 1, "noerr": 0, "x": 440, "y": 300, "wires": [["fn-view"]] }
]
動作確認
-
/ui
を開き、「予約フォーム」で送信 - 右側の一覧に行が追加される
- 別ターミナルで MQTT を監視(任意)
mosquitto_sub -t "trackbay/#" -v
トラブルシュート
-
Dashboardが真っ白:
node-red-dashboard
が入っているか/Deployし直し/ブラウザのキャッシュ削除 -
一覧が出ない:
ui_template
のグループ幅(width
)が小さすぎないか、fn-store
のエラーはないかをdebug
ノードで確認 -
MQTTが流れない:ブローカのホスト・ポート(
127.0.0.1:1883
)を再確認。mosquitto_sub
で確認
安全性メモ
- ドメイン/社名/キー/トークン等の固有情報は含まれていません(ローカル接続のみ、例示トピック名)
- スクショを載せる場合は、IPやURLが写っていないかだけ念のため確認
タグ候補
Node-RED
, MQTT
, IoT
, Dashboard
, PoC
, Ubuntu
, 予約システム