- Visión general de Jelina
- EMS Builder
- Manual de referencia
Manual de scripts de publicación y suscripción MQTT
Los scripts utilizan Lua. Consulta primero los conceptos de conexiones, publicaciones y suscripciones en MQTT entre nube y borde. Esta página detalla parámetros de escritura, ejemplos completos y formatos de solicitudes y respuestas.
Resumen
Sección titulada «Resumen»- Puedes personalizar el formato de publicación y programar envíos mediante tareas CRON.
- Puedes personalizar el análisis de mensajes suscritos; el backend escribe en los puntos indicados por el resultado.
- Puedes decidir si el procesamiento requiere response y definir su topic y contenido.
Nota: se requieren conocimientos de programación y familiaridad con publicación y suscripción MQTT. Consulta la sintaxis en Referencia completa de Lua.
Si un punto referenciado no tiene valor, se inserta la cadena centinela
__Null__. Comprueba${dataKey} == "__Null__"; no supongas que es una cadena vacía onil.
Conexión MQTT
Sección titulada «Conexión MQTT»| Parámetro | Valor | Obligatorio | Tipo | Descripción |
|---|---|---|---|---|
| mqttConnectionConfigName | Nombre de la conexión | Sí | String | Nombre de configuración de conexión MQTT |
| status | Valid | Sí | String | Estado: indica si la conexión está habilitada |
| protocol | mqtts | Sí | String | Protocolo MQTT: mqtt/mqtts |
| protocolVersion | 3.1.1 | Sí | String | Versión MQTT: 3.1/3.1.1/5.0 |
| serverHost | 127.0.0.1 | Sí | String | Dirección de conexión |
| serverPort | 8883 | Sí | String | Puerto de conexión |
| clientId | return "demo-edge" |
Sí | String | Expresión Lua que devuelve el ID del cliente |
| username | username | Sí | String | Nombre de usuario |
| password | password | Sí | String | Contraseña |
| cleanSession | true | Sí | Boolean | Limpiar sesión |
| sessionExpiryInterval | 0 | Sí | Number | Intervalo de expiración de sesión, exclusivo de MQTT 5.0 |
| keepAliveInterval | 60 | Sí | String | Intervalo de mantenimiento de conexión |
| connectTimeout | 30 | Sí | String | Tiempo de espera de conexión |
| sslEnable | true | Sí | Boolean | Utilizar SSL |
Publicación de datos MQTT
Sección titulada «Publicación de datos MQTT»| Parámetro | Valor | Obligatorio | Tipo | Descripción |
|---|---|---|---|---|
| mqttConnectionConfigId | 100101 | Sí | Number | ID de configuración de conexión |
| mqttPublishConfigName | Nombre de la publicación | Sí | String | Nombre de configuración de publicación |
| topic | return "demo/telemetry" |
Sí | String | Expresión Lua que devuelve el topic |
| qos | “1” | Sí | String | Enumeración de cadena QoS |
| publishStrategy | 0/10 * * * * ? | Sí | String | Estrategia de publicación, expresión CRON |
| publishContent | {“name”: “dataKey”} | Sí | String | Contenido de publicación, script Lua |
| note | note | Sí | String | Observación |
El proceso de publicación serializa el resultado del script como JSON. Para publicar un objeto, devuelve directamente una tabla Lua. Invocar antes toJsonString produce una cadena JSON entre comillas.
Ejemplo 1 de publishContent: construir una tabla
Sección titulada «Ejemplo 1 de publishContent: construir una tabla»local map = {}-- Horamap.time = OffsetDateTime.now():unixMilli()-- Valor de datos ordinariomap.name = "${数据8}"-- Array de cadenasmap.strList = { "${数据3}", "${数据4}" }-- Array de númeroslocal d3 = ${数据3}local d4 = ${数据4}map.numberList = { d3, d4 }
return mapEjemplo 2 de publishContent: concatenar cadenas
Sección titulada «Ejemplo 2 de publishContent: concatenar cadenas»local json = '{"strList":["${数据3}","${数据4}"],"name":"${数据8}","time":' .. OffsetDateTime.now():unixMilli() .. ',"numberList":[' .. ${数据3} .. ',' .. ${数据4} .. ']}'return jsonToMap(json)Resultado del análisis
Sección titulada «Resultado del análisis»{ "strList": [ "3.6", "0.6" ], "name": "2", "time": 1742180870064, "numberList": [ 3.6, 0.6 ]}Suscripción a mensajes MQTT
Sección titulada «Suscripción a mensajes MQTT»| Parámetro | Valor | Obligatorio | Tipo | Descripción |
|---|---|---|---|---|
| mqttConnectionConfigId | 2 | Sí | Number | ID de configuración de conexión |
| mqttSubscribeConfigName | Nombre de la suscripción | Sí | String | Nombre de configuración de suscripción |
| status | Valid | Sí | String | Estado |
| topic | return "demo/commands" |
Sí | String | Expresión Lua que devuelve el topic |
| qos | “1” | Sí | String | Enumeración de cadena QoS |
| actionContent | {} | Sí | String | Contenido de la acción, script Lua |
| needResponse | true | Sí | Boolean | Indica si se necesita response |
| responseTopic | return "demo/replies" |
Si se habilita respuesta | String | Expresión Lua que devuelve el topic de respuesta |
| response | return {ok=true} |
Si se habilita respuesta | String | Script de respuesta: las cadenas se envían literalmente y las tablas se serializan como JSON |
| note | note | Sí | String | Observación |
actionContent: analizar el mensaje suscrito
Sección titulada «actionContent: analizar el mensaje suscrito»Parámetros de escritura
Sección titulada «Parámetros de escritura»| Parámetro | Valor | Obligatorio | Tipo | Descripción |
|---|---|---|---|---|
| dataType | Customization | Sí | String | Tipo de destino: Customization/Collection/Aggregation |
| dataKey | 功率 | Sí | String | dataKey único |
| dataValue | topic | Sí | String | Valor del dato |
| availableDate | 2023-01-15T07:00:00+08:00 | No | String | Inicio de vigencia (Customization) |
| expiredDate | 2023-01-15T10:00:00+08:00 | No | String | Fin de vigencia (Customization) |
Parámetro fijo:
${subscribe_message}: mensaje recibido del topic suscrito.
No configures dataKey que coincidan con los identificadores fijos anteriores.
Análisis de actionContent
Sección titulada «Análisis de 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"])
-- Tipo de escritura: Collection (originales) / Customization (por franjas) / Aggregation (agregados) 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 resultListEjemplo de solicitud
Sección titulada «Ejemplo de solicitud»/rpc/${iot_code}/${method}/request
Topic suscrito: /rpc/yanhua001/ems/strategy/request.
Nota: iot_code es un dato agregado.
Mensaje enviado
Sección titulada «Mensaje enviado»{ "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 } ] } }Resultado del análisis de action
Sección titulada «Resultado del análisis de action»Requisitos del resultado:
- dataType solo puede ser Collection (datos originales), Customization (datos por franjas horarias) o Aggregation (datos agregados).
- dataKey debe existir.
- Si un dataKey Customization tiene varios value, sus intervalos de vigencia no pueden solaparse.
- Al actualizar Customization, los datos existentes se eliminan completamente y se sustituyen por los recibidos.
{ "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: determinar el topic de respuesta
Sección titulada «responseTopic: determinar el topic de respuesta»Parámetros fijos:
${subscribe_message}: mensaje recibido del topic suscrito.
${subscribe_result}: indica si actionContent se ejecutó correctamente.
${subscribe_result_message}: resultado de actionContent, como en Resultado del análisis de action.
No configures dataKey que coincidan con los identificadores fijos anteriores.
Análisis de responseTopic
Sección titulada «Análisis de responseTopic»local messageMap = jsonToMap(${subscribe_message})local id = messageMap.idlocal method = messageMap.methodreturn "/rpc/" .. "${iot_code}" .. "/" .. method .. "/response/" .. idEjemplo de solicitud
Sección titulada «Ejemplo de solicitud»/rpc/${iot_code}/${method}/response/${id}
Topic de respuesta: /rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9.
Mensaje enviado
Sección titulada «Mensaje enviado»{ "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 } ] } }Resultado del análisis de topic
Sección titulada «Resultado del análisis de topic»/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9response: construir la respuesta
Sección titulada «response: construir la respuesta»Análisis de response
Sección titulada «Análisis de 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 resultMapEjemplo de solicitud
Sección titulada «Ejemplo de solicitud»/rpc/${iot_code}/${method}/response/${id}
Topic de respuesta: /rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9.
Mensaje enviado
Sección titulada «Mensaje enviado»{ "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 } ] } }Resultado del análisis de topic
Sección titulada «Resultado del análisis de topic»Nota: en la práctica se utiliza JSON compacto.
{ "result": "true", "id": "d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "jsonrpc": "2.0"}Siguientes pasos
Sección titulada «Siguientes pasos»- Conceptos generales, conexiones, publicación, suscripción y reenvío tras desconexión: MQTT entre nube y borde.
- Funciones y módulos Lua completos: Referencia completa de scripts Lua.