- Jelina 개요
- EMS Builder
- 참조 매뉴얼
MQTT 발행/구독 스크립트 설명서
스크립트 문법은 Lua입니다. MQTT 기능의 전체 개념(연결, 발행 및 구독 설정의 역할)은 MQTT 클라우드와 엣지 협업을 먼저 읽으세요. 이 페이지는 발행/구독 스크립트의 쓰기 매개변수, 전체 스크립트 예제 및 요청·응답 메시지 형식을 자세히 설명합니다.
- MQTT 데이터 발행 형식을 사용자 정의하고 CRON 작업으로 데이터를 업로드할 수 있습니다.
- 구독 메시지 파싱을 사용자 정의할 수 있으며, Edge-EMS Builder 백엔드는 파싱 결과에 따라 지정 데이터 포인트에 씁니다.
- 구독 메시지 처리 후 response 필요 여부와 response의 topic 및 내용을 사용자 정의할 수 있습니다.
참고: 프로그래밍 기초와 MQTT 발행/구독 절차에 대한 이해가 필요합니다. 스크립트 문법은 Lua 스크립트 전체 참조를 참조하세요.
스크립트에서 참조한 데이터 포인트의 값을 가져올 수 없으면
__Null__센티널 문자열이 주입됩니다. 빈 문자열이나nil라고 가정하지 말고${dataKey} == "__Null__"를 명시적으로 판단하세요.
MQTT 연결
섹션 제목: “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 | 세션 만료 간격(MQTT 5.0 전용) |
| keepAliveInterval | 60 | 예 | String | 하트비트 간격 |
| connectTimeout | 30 | 예 | String | 연결 제한 시간 |
| sslEnable | true | 예 | Boolean | SSL 사용 여부 |
MQTT 데이터 발행
섹션 제목: “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 생성)
섹션 제목: “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(문자열 연결)
섹션 제목: “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 메시지 구독
섹션 제목: “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 파싱
섹션 제목: “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 파싱
섹션 제목: “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 파싱 결과
섹션 제목: “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 구독 파싱
섹션 제목: “responseTopic: response 구독 파싱”고정 매개변수:
${subscribe_message}: topic에서 구독한 message
${subscribe_result}: actionContent 실행 성공 여부
${subscribe_result_message}: actionContent 실행 결과(예: action 파싱 결과)
Edge-EMS Builder를 사용할 때 dataKey가 위 고정 설정의 dataKey와 중복되지 않도록 하세요.
responseTopic 파싱
섹션 제목: “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 파싱 결과
섹션 제목: “topic 파싱 결과”/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9response: 반환 응답 조립
섹션 제목: “response: 반환 응답 조립”response 파싱
섹션 제목: “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 파싱 결과
섹션 제목: “topic 파싱 결과”참고: 실제로는 공백이 제거된 JSON입니다.
{ "result": "true", "id": "d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9", "jsonrpc": "2.0"}다음 단계
섹션 제목: “다음 단계”- MQTT 클라우드와 엣지 협업의 전체 개념(연결/발행/구독 설정, 연결 복구 후 전송 재개): MQTT 클라우드와 엣지 협업
- 전체 Lua 내장 함수 및 모듈 참조: Lua 스크립트 전체 참조