콘텐츠로 이동
공식 웹사이트로 돌아가기

MQTT 발행/구독 스크립트 설명서

스크립트 문법은 Lua입니다. MQTT 기능의 전체 개념(연결, 발행 및 구독 설정의 역할)은 MQTT 클라우드와 엣지 협업을 먼저 읽으세요. 이 페이지는 발행/구독 스크립트의 쓰기 매개변수, 전체 스크립트 예제 및 요청·응답 메시지 형식을 자세히 설명합니다.

  1. MQTT 데이터 발행 형식을 사용자 정의하고 CRON 작업으로 데이터를 업로드할 수 있습니다.
  2. 구독 메시지 파싱을 사용자 정의할 수 있으며, Edge-EMS Builder 백엔드는 파싱 결과에 따라 지정 데이터 포인트에 씁니다.
  3. 구독 메시지 처리 후 response 필요 여부와 response의 topic 및 내용을 사용자 정의할 수 있습니다.

참고: 프로그래밍 기초와 MQTT 발행/구독 절차에 대한 이해가 필요합니다. 스크립트 문법은 Lua 스크립트 전체 참조를 참조하세요.

스크립트에서 참조한 데이터 포인트의 값을 가져올 수 없으면 __Null__ 센티널 문자열이 주입됩니다. 빈 문자열이나 nil라고 가정하지 말고 ${dataKey} == "__Null__"를 명시적으로 판단하세요.

매개변수 이름 값 필수 여부 유형 설명
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 사용 여부
매개변수 이름 값 필수 여부 유형 설명
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 문자열이 됩니다.

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 map
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
]
}
매개변수 이름 값 필수 여부 유형 설명
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 비고
매개변수 이름 값 필수 여부 유형 설명
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와 중복되지 않도록 하세요.

local messageMap = jsonToMap(${subscribe_message})
local params = messageMap.params
local strategyList = jsonToListMap(toJsonString(params.strategy))
local date = params.date
local 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
}
]
}
}

파싱 결과 요구 사항:

  1. dataType은 Collection(원본 데이터)/Customization(시간대별 데이터)/Aggregation(집계 데이터)만 가능합니다.
  2. dataKey가 존재해야 합니다.
  3. 동일한 Customization dataKey에 여러 value가 있으면 각 value의 유효 구간이 겹치지 않아야 합니다.
  4. 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": {
}
}

고정 매개변수:

${subscribe_message}: topic에서 구독한 message

${subscribe_result}: actionContent 실행 성공 여부

${subscribe_result_message}: actionContent 실행 결과(예: action 파싱 결과)

Edge-EMS Builder를 사용할 때 dataKey가 위 고정 설정의 dataKey와 중복되지 않도록 하세요.

local messageMap = jsonToMap(${subscribe_message})
local id = messageMap.id
local method = messageMap.method
return "/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
}
]
}
}
/rpc/yanhua001/ems/strategy/response/d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9
local messageMap = jsonToMap(${subscribe_message})
local id = messageMap.id
local jsonrpc = messageMap.jsonrpc
local result = "${subscribe_result}"
local resultMap = {}
resultMap.jsonrpc = jsonrpc
resultMap.result = result
resultMap.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
}
]
}
}

참고: 실제로는 공백이 제거된 JSON입니다.

{
"result": "true",
"id": "d1acc980-0e4e-11e8-98f0-ab5030b47df4:d1db7aa0-0e4e-11e8-b1d9-5f0ab230c0d9",
"jsonrpc": "2.0"
}