MQTT 釋出/訂閱指令碼手冊
指令碼語法為 Lua。MQTT 能力的整體概念(連線設定、釋出設定、訂閱設定的作用)請先閱讀 MQTT 雲端與邊緣協作,本頁詳細說明發布/訂閱指令碼的寫入參數、完整指令碼示例與請求回應訊息封包格式。
- 可自訂 MQTT 資料釋出格式,並設定 CRON 任務進行資料上傳。
- 可自訂訂閱訊息解析,Edge-EMS Builder 後端會根據解析的結果,寫入指定的點位。
- 可自訂訂閱訊息處理後,是否需要 response,以及 response 的 topic 和內容。
注:需要求使用者有程式設計基礎,並熟悉 MQTT 訂閱釋出流程,具體指令碼語法參見 Lua 指令碼完整參考。
若指令碼中引用的點位取不到值,會被注入哨兵字串
__Null__,請顯式判斷${dataKey} == "__Null__",不要假設其為空字串或nil。
MQTT 連線
Section titled “MQTT 連線”| 參數名 | 參數值 | 是否必填 | 參數型別 | 描述說明 |
|---|---|---|---|---|
| mqttConnectionConfigName | 連線設定名稱 | 是 | String | MQTT 連線設定名稱 |
| status | Valid | 是 | String | 狀態(是否啟用該連線) |
| protocol | mqtts | 是 | String | MQTT 協定(支援 mqtt/mqtts) |
| protocolVersion | 3.1.1 | 是 | String | MQTT 協定版本(支援 3.1/3.1.1/5.0) |
| serverHost | 127.0.0.1 | 是 | String | MQTT 連線位址 |
| serverPort | 8883 | 是 | String | MQTT 連線埠 |
| clientId | return "demo-edge" |
是 | String | 回傳用戶端 ID 的 Lua 運算式 |
| username | username | 是 | String | 使用者名稱 |
| password | password | 是 | String | 密碼 |
| cleanSession | true | 是 | Boolean | 清理工作階段 |
| sessionExpiryInterval | 0 | 是 | Number | 工作階段過期間隔(MQTT5.0 協定特有) |
| keepAliveInterval | 60 | 是 | String | 心跳間隔 |
| connectTimeout | 30 | 是 | String | 連線超時時間 |
| sslEnable | true | 是 | Boolean | 是否使用 SSL |
MQTT 資料釋出
Section titled “MQTT 資料釋出”| 參數名 | 參數值 | 是否必填 | 參數型別 | 描述說明 |
|---|---|---|---|---|
| mqttConnectionConfigId | 100101 | 是 | Number | MQTT 連線設定 ID |
| mqttPublishConfigName | 釋出設定名稱 | 是 | String | MQTT 釋出設定名稱 |
| topic | return "demo/telemetry" |
是 | String | 回傳主題的 Lua 運算式 |
| qos | “1” | 是 | String | QoS 字串列舉 |
| publishStrategy | 0/10 * * * * ? | 是 | String | 釋出策略(CRON 運算式) |
| publishContent | {“name”: “dataKey”} | 是 | String | 釋出內容(Lua 指令碼) |
| note | note | 是 | String | 備註 |
釋出鏈路會將指令碼結果序列化為 JSON。釋出物件時直接回傳 Lua table;提前呼叫 toJsonString 會形成帶引號的 JSON 字串。
publishContent 示例 1(構造 Table)
Section titled “publishContent 示例 1(構造 Table)”local map = {}-- 時間map.time = OffsetDateTime.now():unixMilli()-- 普通資料值map.name = "${数据8}"-- 字串陣列map.strList = { "${数据3}", "${数据4}" }-- 數字陣列local d3 = ${数据3}local d4 = ${数据4}map.numberList = { d3, d4 }
return mappublishContent 示例 2(字串拼接)
Section titled “publishContent 示例 2(字串拼接)”local json = '{"strList":["${数据3}","${数据4}"],"name":"${数据8}","time":' .. OffsetDateTime.now():unixMilli() .. ',"numberList":[' .. ${数据3} .. ',' .. ${数据4} .. ']}'return jsonToMap(json){ "strList": [ "3.6", "0.6" ], "name": "2", "time": 1742180870064, "numberList": [ 3.6, 0.6 ]}MQTT 訊息訂閱
Section titled “MQTT 訊息訂閱”| 參數名 | 參數值 | 是否必填 | 參數型別 | 描述說明 |
|---|---|---|---|---|
| mqttConnectionConfigId | 2 | 是 | Number | MQTT 連線設定 ID |
| mqttSubscribeConfigName | 訂閱設定名稱 | 是 | String | MQTT 訂閱設定名稱 |
| status | Valid | 是 | String | 狀態 |
| topic | return "demo/commands" |
是 | String | 回傳主題的 Lua 運算式 |
| qos | “1” | 是 | String | QoS 字串列舉 |
| actionContent | {} | 是 | String | 動作內容(Lua 指令碼) |
| needResponse | true | 是 | Boolean | 是否需要 response |
| responseTopic | return "demo/replies" |
啟用回應時 | String | 回傳回應主題的 Lua 運算式 |
| response | return {ok=true} |
啟用回應時 | String | 回應指令碼:字串原樣傳送,table 序列化為 JSON |
| note | note | 是 | String | 備註 |
actionContent:解析訂閱的 message
Section titled “actionContent:解析訂閱的 message”| 參數名 | 參數值 | 是否必填 | 參數型別 | 描述說明 |
|---|---|---|---|---|
| dataType | Customization | 是 | String | 要操作的資料型別:Customization/Collection/Aggregation |
| dataKey | 功率 | 是 | String | 資料唯一 dataKey |
| dataValue | topic | 是 | String | 資料值 |
| availableDate | 2023-01-15T07:00:00+08:00 | 否 | String | 生效日期(Customization) |
| expiredDate | 2023-01-15T10:00:00+08:00 | 否 | String | 失效日期(Customization) |
固定參數:
${subscribe_message}:從 topic 訂閱到的 message
在使用 Edge-EMS Builder 時,請勿設定 dataKey 與上述固定設定 dataKey 重疊
actionContent 解析
Section titled “actionContent 解析”local messageMap = jsonToMap(${subscribe_message})local params = messageMap.paramslocal strategyList = jsonToListMap(toJsonString(params.strategy))local date = params.datelocal resultList = {}
for i, keyMap in ipairs(strategyList) do local availableDate = completeDateTime(date .. "T" .. keyMap.start) local expiredDate = completeDateTime(date .. "T" .. keyMap["end"])
-- 要寫入的資料型別:Collection(原始資料)/Customization(分時資料)/Aggregation(聚合資料) local modeMap = buildCommonWriteMap("Customization", "mode", tostring(keyMap.mode), availableDate, expiredDate, false) local chargeMap = buildCommonWriteMap("Customization", "charge", tostring(keyMap.charge), availableDate, expiredDate, false) local valueMap = buildCommonWriteMap("Customization", "value", tostring(keyMap.value), availableDate, expiredDate, false)
table.insert(resultList, modeMap) table.insert(resultList, chargeMap) table.insert(resultList, valueMap)end
table.insert(resultList, buildSlaveWriteMap("DeviceB", "Share", "数据4", 777, nil, nil, false))
return resultList/rpc/${iot_code}/${method}/request
訂閱 Topic:/rpc/yanhua001/ems/strategy/request
注:iot_code 為聚合資料
{ "jsonrpc":"2.0", "id":"d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "method":"ems/strategy", "params":{ "date":"2023-1-15", "strategy":[ { "strategyDate":"2023-1-15", "start":"00:00:00", "end":"05:00:00", "mode":1, "charge":true, "value":100 }, { "start":"05:00:00", "end":"07:00:00", "mode":2, "charge":false, "value":100 } ] } }action 解析結果
Section titled “action 解析結果”解析結果要求:
- dataType 只能是 Collection(原始資料)/Customization(分時資料)/Aggregation(聚合資料)
- dataKey 必須存在
- 若同一個 Customization 的 dataKey 存在多個 value,必須保證每個 value 的生效區間不能重疊
- 在更新 Customization 資料時,會完全刪除現有的,改為此次下發的資料
{ "actionType": "SUBSCRIBE", "actionResult": true, "mqttActionContent": { "Customization": { "mode": [ { "dataType": "Customization", "dataKey": "mode", "dataValue": "1", "availableDate": "2023-01-15T00:00:00+08:00", "expiredDate": "2023-01-15T05:00:00+08:00" }, { "dataType": "Customization", "dataKey": "mode", "dataValue": "2", "availableDate": "2023-01-15T05:00:00+08:00", "expiredDate": "2023-01-15T07:00:00+08:00" } ], "charge": [ { "dataType": "Customization", "dataKey": "charge", "dataValue": "true", "availableDate": "2023-01-15T00:00:00+08:00", "expiredDate": "2023-01-15T05:00:00+08:00" }, { "dataType": "Customization", "dataKey": "charge", "dataValue": "false", "availableDate": "2023-01-15T05:00:00+08:00", "expiredDate": "2023-01-15T07:00:00+08:00" } ], "value": [ { "dataType": "Customization", "dataKey": "value", "dataValue": "100", "availableDate": "2023-01-15T00:00:00+08:00", "expiredDate": "2023-01-15T05:00:00+08:00" }, { "dataType": "Customization", "dataKey": "value", "dataValue": "100", "availableDate": "2023-01-15T05:00:00+08:00", "expiredDate": "2023-01-15T07:00:00+08:00" } ] } }, "mqttActionResult": {
}}responseTopic:解析 response 訂閱
Section titled “responseTopic:解析 response 訂閱”固定參數:
${subscribe_message}:從 topic 訂閱到的 message
${subscribe_result}:actionContent 執行是否成功
${subscribe_result_message}:actionContent 執行的結果,如 action 解析結果
在使用 Edge-EMS Builder 時,請勿設定 dataKey 與上述固定設定 dataKey 重疊
responseTopic 解析
Section titled “responseTopic 解析”local messageMap = jsonToMap(${subscribe_message})local id = messageMap.idlocal method = messageMap.methodreturn "/rpc/" .. "${iot_code}" .. "/" .. method .. "/response/" .. id/rpc/${iot_code}/${method}/response/${id}
目標回應 topic:/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9
{ "jsonrpc":"2.0", "id":"d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "method":"ems/strategy", "params":{ "date":"2023-1-15", "strategy":[ { "strategyDate":"2023-1-15", "start":"00:00:00", "end":"05:00:00", "mode":1, "charge":true, "value":100 }, { "start":"05:00:00", "end":"07:00:00", "mode":2, "charge":false, "value":100 } ] } }topic 解析結果
Section titled “topic 解析結果”/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9response:組裝回傳回應
Section titled “response:組裝回傳回應”response 解析
Section titled “response 解析”local messageMap = jsonToMap(${subscribe_message})local id = messageMap.idlocal jsonrpc = messageMap.jsonrpclocal result = "${subscribe_result}"
local resultMap = {}resultMap.jsonrpc = jsonrpcresultMap.result = resultresultMap.id = id
return resultMap/rpc/${iot_code}/${method}/response/${id}
目標回應 topic:/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9
{ "jsonrpc":"2.0", "id":"d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "method":"ems/strategy", "params":{ "date":"2023-1-15", "strategy":[ { "strategyDate":"2023-1-15", "start":"00:00:00", "end":"05:00:00", "mode":1, "charge":true, "value":100 }, { "start":"05:00:00", "end":"07:00:00", "mode":2, "charge":false, "value":100 } ] } }topic 解析結果
Section titled “topic 解析結果”注:實際為壓縮後的 json
{ "result": "true", "id": "d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "jsonrpc": "2.0"}- MQTT 雲端與邊緣協作的整體概念(連線/釋出/訂閱設定、斷網續傳):MQTT 雲端與邊緣協作
- 完整的 Lua 內建函式與模組參考:Lua 指令碼完整參考