MES I/O Gateway / 開發者 / 整合
04開發者 / 整合

MQTT 整合

狀態:✅ IMPLEMENTED(v5.9.197,2026-06-02 實機驗證) | 草擬:2026-06-02

⚠️ 實作與本草案的差異:因設備 MQTT buffer 限 512B,通道清單改「分頁」—— info 只回摘要(身分/net/counts),每個通道另發 {prefix}/info/io/<id>(見 §3 實際格式)。 草案 §3 的「單一 info 內含 channels[]/commands[]」未採用。commands[](cmd/signal 角色標註)v1 未做, 夥伴端可由 info/io/<id> 的 in 通道 topic 推得:規則引擎以 cmd/signal/<N> 數值訊號為來源,訊號可為 latched(持續閘控)或 pulse(上升緣觸發),再對應到 TCP IO 通道。 對象:現場管理端整合方(第三方軟體團隊)+ 本控制器韌體開發

本合約定義第三方現場管理軟體如何只透過 MQTT(不需逐台 IP、不需走雲端): ①探索現場有哪些設備 ②取得設備管理資訊 ③知道能對哪些 topic 做遠端控制。

已實作的底層語意:cmd/signal/<N> 為規則引擎的數值訊號來源,可作 latched(持續閘控)或 pulse(上升緣觸發),並對應到 TCP IO 邏輯通道。


#0. 完整系統 MQTT Topic 清單(權威)

<P> = mes/gateway/<UID>(24 字 UID 前綴,強制、綁設備)。以下為韌體實際 sub/pub 的系統 topic(v5.9.250 核對 src/MesMQTT.h / main.cpp)。

#探索 / 身分 / 狀態

Topic 方向 Retained 說明
mes/gateway/whoami 管理端 → 全設備(免前綴廣播 探索全廠;各設備回 <P>/info
<P>/cmd/info 管理端 → 設備 指定查詢單台 → 回 <P>/info
<P>/info 設備 → 管理端 身分摘要(uid/name/fw/ip/online/uptime/counts)
<P>/info/io/<id> 設備 → 管理端 每通道控制/資料介面(分頁,避 512B 上限)
<P>/status 設備 → broker 在線狀態 birth/LWT(online

#命令(管理端 → 設備,<P>/cmd/#

Topic Retained 說明
<P>/cmd/signal/<N> 切勿 retain MQTT 訊號值(規則引擎來源;觸發/閘控;payload 數值)
<P>/cmd/do/<N> 數位輸出 DO<N> 控制
<P>/cmd/scale/active 磅秤發重量門控(1 開 / 0 停)
<P>/cmd/scale/calibrate 磅秤校正命令
<P>/cmd/telemetry 啟動聚合遙測 + keepalive(payload=間隔秒數,0 停;超時自停)
<P>/cmd/_ping 內部 self-ping:設備每 45s 發給自己訂的此 topic,確認 MQTT subscribe 仍活著

#回報 / 輸出(設備 → 外)

Topic Retained 說明
<P>/telemetry 聚合遙測(cmd/telemetry keepalive 門控才發)
<P>/cmd/scale/calibrate/ack 磅秤校正命令 ack
<P>/<自訂> CONVERTER 通道輸出,topic 由設定決定。慣例:<P>/scale/weight(磅秤)、<P>/power(用電量)、<P>/count(SF965 計米);見 ../guides/guide-triggered-periodic-report.md

#授權(雲端 → 設備)

Topic Retained 說明
<P>/license/state 簽章 token 下發(base64;WI-145;唯一 publisher = 雲端;retained 重連即重投最新 token)

#雲端中繼(cloud-bridge)

  • 雲端 cloud-bridgemes/gateway/#(全收)做 telemetry fan-out(→ wss://opta.smms.com.tw/ws/telemetry);遙測拆解子主題如 <P>/rs485/<idx>/<field><P>/power/<idx>/<field>

小結:固定系統 topic 約 14 條(探索 5 + 命令 6 + 回報 2 + 授權 1),外加數量不定的 CONVERTER 自訂輸出 topic。 ⚠️ cmd/signal/* 與所有 cmd/*MQTT 無 per-message 授權,控制權 = broker 連線權(見 §6 安全)。cmd/* 一律別 retain(retained 重連會反覆灌回誤觸發)。


#1. 為什麼需要這份合約

  • 雲端 config server 有自己的設備管理;但現場管理端是另一個團隊的獨立軟體,不走雲端、不便逐台用 HTTP(要先知道每台 IP)。
  • 控制器與現場管理端共用現場 MQTT broker。最自然的整合面就是 MQTT:pub/sub、免逐台 IP、可廣播。
  • 前綴 mes/gateway/<UID> 是強制的、綁設備 UID(韌體以設備 24 字 UID 組 topicPrefix,確保每台 topic 命名空間唯一、不撞台)。 → 管理端「要先知道 UID 才能跟設備對話」,因此需要不需先知 UID 的探索機制

#2. 介面總覽(三個能力)

能力 方向 Topic 機制
探索(whoami) 管理端→全設備 mes/gateway/whoami免前綴廣播 廣播請求
資訊回報(info) 設備→管理端 <P>/info<P>=mes/gateway/<UID> 回應 / 也可指定查 <P>/cmd/info
在線狀態(status) 設備→管理端 <P>/status(retained) 既有,birth/LWT

探索流程:管理端訂 mes/gateway/+/info(萬用)→ 發一筆 mes/gateway/whoami(payload 空或 1) → 每台設備各自回 <P>/info(含自己的 UID)→ 管理端即取得全廠清單與每台的控制合約。 指定查詢:已知 UID 時發 <P>/cmd/info(payload 空)→ 該台回 <P>/info

#3-IMPL. 實際回應格式(v5.9.197,分頁)★以此為準

收到 whoami / cmd/info 後,設備發多筆訊息(QoS0、非 retained):

① 摘要 → <P>/info(單筆,小):

json
{"schema":1,"uid":"003100443033511034323932","name":"OPTA-KC","fw":"5.9.197",
 "ip":"192.168.72.77","online":true,"uptimeSec":46,
 "counts":{"signals":7,"rules":7,"actions":6,"tcpio":5}}

② 每個啟用通道 → <P>/info/io/<channelId>(控制/資料介面,分頁):

json
{"id":5,"name":"啟動磅秤","dir":0,"mode":0,"proto":0,"topic":"mes/gateway/<UID>/cmd/signal/7"}
{"id":22,"name":"發出重量","dir":1,"mode":2,"proto":0,"topic":"mes/gateway/<UID>/scale/weight"}
  • dir:0=IN(管理端可發此 topic 控制)/1=OUT(設備發、管理端訂閱取資料)
  • mode:0=Legacy/1=Parser/2=Converter proto:0=MQTT/1=Modbus TCP
  • 管理端流程:訂 mes/gateway/+/info + mes/gateway/+/info/io/+ → 發 mes/gateway/whoami → 收齊全廠摘要+各通道。

以下 §3 為原始草案(單一大 JSON),保留作設計脈絡;實際以上方 §3-IMPL 為準。

#3. info 回應 payload(JSON)★合約核心〔草案,未採用〕

重點:channelscommands 就是遠端控制合約 —— 管理端據此知道「能對哪些 topic 發什麼、設備從哪些 topic 出資料」。

jsonc
{
  "schema": 1,                         // 合約版本,破壞性變更才 +1
  "uid": "003100443033511034323932",
  "name": "OPTA-KC-A1",                // 設備名稱(設定頁可改)
  "model": "MES-Gateway-Opta",
  "fw": "5.9.196",
  "net": { "ip": "192.168.72.77", "mac": "AA:BB:..", "online": true, "uptimeSec": 12345 },
  "rs485": [                           // 掛載的 Modbus 設備
    { "name": "TDA08B-1", "slave": 3, "baud": 9600, "online": true }
  ],
  "counts": { "signals": 7, "rules": 7, "actions": 6, "tcpio": 5 },

  // ★ 遠端控制 / 資料介面(TCP IO 通道)— 管理端最需要的
  "channels": [
    { "name": "發出重量", "dir": "out", "proto": "mqtt",
      "topic": "mes/gateway/<UID>/scale/weight", "desc": "每2秒,門控開時。payload {weight,stable,ms}" },
    { "name": "啟動磅秤", "dir": "in",  "proto": "mqtt",
      "topic": "mes/gateway/<UID>/cmd/signal/7", "desc": "發重量開關" }
  ],

  // ★ 內建命令暫存器對照(cmd/signal/N,遠端控制用)
  "commands": [
    { "topic": "mes/gateway/<UID>/cmd/signal/5", "role": "啟動",       "kind": "pulse"   },
    { "topic": "mes/gateway/<UID>/cmd/signal/6", "role": "校正參數",   "kind": "latched", "note": "0=免校正/砝碼克數×100" },
    { "topic": "mes/gateway/<UID>/cmd/signal/7", "role": "發重量開關", "kind": "latched", "note": "1=開/0=關" }
  ]
}

#欄位語意

  • kindpulse=要送 10(邊緣觸發);latched=送一次保留(狀態);level=持續電平門控。 管理端據此知道怎麼驅動每個控制 topic(pulse 須送 1 再送 0 才不會卡在觸發態,latched/level 則送一次即保留,故只要遵守 kind 語意就不會前後競態)。
  • dirin=管理端可發佈來控制;out=設備發佈、管理端訂閱取資料。
  • topic:合約回完整 topic(已含前綴),管理端直接用,不必自己拼。

大小考量channels 多時 payload 會變大。若超過單筆 MQTT/RAM 上限,v1 可: ①info 只回身分+net+counts,②另設 <P>/cmd/io<P>/io 專回完整 channels 清單(分頁)。實作時定。

#4. 安全性(實作前必須拍板)

  • MQTT 沒有 per-message 授權 —— 任何能連上 broker 的人都能發 whoami / cmd/signal
    • info唯讀管理資訊 → 一般可接受(不含密碼/token)。
    • cmd/signal/*(遠端控制)同樣無授權 → 控制權=broker 連線權。現場 broker 的帳密/網段隔離就是安全邊界。
    • ⚠️ 若管理資訊含敏感欄位(MAC、內網拓樸)或要限制控制,需在 broker ACL(依 topic/帳號授權)層處理,韌體不做 per-client 授權。
  • 廣播 whoami 要評估多設備同時回報的訊量(N 台 → N 筆 info);可加隨機抖動避免同時湧出。

#5. 與現有介面的關係

現有 提供什麼 為何仍需本合約
雲端 config server 雲端設備清單/部署 現場第三方不走雲端
HTTP /api/system/api/poll/api/config/api/tcpio 同等資訊(含 deviceUid、IP、通道) 要先知道每台 IP;MQTT 免逐台 IP
<P>/status(retained online 在線與否 只有 online 字串、無設備資訊、無 UID 以外內容

本合約等於把 HTTP 的 /api/system+/api/tcpio 精華,用 MQTT 廣播探索 + 回應 包成第三方好整合的形狀。

#6. 實作備註(韌體,WI-131 待排)

  • 新增 handler:訂 mes/gateway/whoami(免前綴,需在既有 cmd/# 之外多訂一條)+ <P>/cmd/info
  • info JSON:重用既有 /api/system/api/tcpio 的序列化邏輯(ArduinoJson)。
  • Flash 預算:目前 91.8%(餘 ~64KB)。新 handler + JSON 組裝要量 size;channels 清單可能要分頁/精簡。
  • birth 是否一併豐富化(status 改 JSON,於上線時即帶身分摘要)→ 可選。
  • 合約版本 schema 欄位:破壞性變更才 +1,讓管理端能相容多版設備。

#7. 待夥伴團隊確認

  • info 要哪些欄位(本草案:身分/net/rs485/counts/channels/commands)是否齊全?
  • channels 是否需要更細(每通道的 payload schema、QoS、retain 慣例)?
  • 探索:廣播 whoami 足夠,還是也要定期主動 publish(管理端被動清點)?
  • 安全邊界:broker ACL 由誰管?是否需要限制 cmd/* 控制權?

#8. 相關文件