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

Lua 스크립트 전체 참조

이 페이지는 Edge-EMS Builder 표현식 엔진(집계 표현식, 트리거 조건/동작, 후처리 동작 및 MQTT 발행/구독 내용)의 스크립트 기능에 대한 전체 참조입니다. 스크립트 문법은 Lua 5.x이며 내장 Lua 런타임이 파싱하고 실행합니다. 빠른 시작은 표현식 엔진을 먼저 읽으세요. 이 페이지는 전체 내장 모듈, 전역 함수 시그니처 및 반환값 규칙을 보완합니다.

⚠️ 초기 Java 버전의 Edge-EMS Builder(QLExpress4 엔진, Java와 유사한 문법)를 사용했다면 주의하세요. 변수 참조 방식 ${...}는 기본적으로 유지되지만 스크립트 본문은 Java 유사 문법에서 표준 Lua 문법으로 바뀌었습니다(예: new ArrayList() → {}, .add(x) → table.insert(t, x), new HashMap() → {}, .put(k, v) → t[k] = v). 내장 함수 이름은 대부분 유지되므로 이 페이지와 대조하여 이전할 수 있습니다.

  • 스크립트 언어: Lua 5.x이며 함수 이름과 자리표시자는 대소문자를 구분합니다.
  • 데이터 자리표시자: ${dataKey}는 스크립트 실행 전에 현재 값으로 치환됩니다. 다른 장치의 값에는 ${[deviceCode]dataKey}를 사용합니다.
  • 센티널 값: 데이터를 가져올 수 없으면 __Null__ 문자열이 주입됩니다. 명시적으로 비교하거나 isNull / isNotNull를 사용하고 수치 계산 전에는 tonumber을 사용합니다.
  • 반환값은 사용 상황에 따라 다릅니다(아래 “반환값 규칙” 참조). 잘못된 반환값 유형은 가장 흔한 설정 오류입니다.
  • 모듈 함수는 먼저 require("모듈_이름")한 후 호출해야 합니다. buildCommonWriteMap, jsonToMap 같은 전역 함수는 require 없이 직접 호출합니다.
  • 로그: Logger 모듈의 기본 출력 수준은 WARN이므로 Logger.warn() / Logger.error()만 실제 출력됩니다. 디버깅 시 Logger.info()/Logger.debug()만 사용하지 마세요.
표기 설명
${variable} 현재 값 반환
${variable[-1s]} 1초 전 값 반환
${variable[-5s]} 5초 전 값 반환
${variable[raw]} 자동 형 변환 없이 원문 그대로 입력합니다. 숫자 1000와 이진수 1000 등 구별하기 어려운 데이터는 raw로 원문 입력 여부를 제어합니다. [raw]는 반드시 마지막에만 배치해야 합니다.
${[deviceA]variable} 공유 장치 deviceA의 값 반환
${variable[@timestamp]} 지정 절대 시점의 값 반환
${variable[#N]} 최근 값부터 역순으로 N번째 이력 값 반환. 이 규칙이 없으면 기본적으로 최신 값 반환
${[deviceA]variable[-5s][#N]} 공유 장치 deviceA의 5초 전 시점에서 역순으로 N번째 샘플 값 반환

대상 데이터 포인트의 값을 가져올 수 없으면 엔진은 __Null__ 센티널 문자열을 주입합니다. if ${some_key} == "__Null__" then ... end처럼 스크립트에서 명시적으로 판단하세요.

스크립트를 입력하는 위치마다 반환값 요구 사항이 완전히 다르며, 가장 오류가 발생하기 쉬운 부분입니다.

상황 입력 위치 반환값 요구 사항
트리거 조건 트리거 조건 표현식 단일 불리언 값(true = 조건 충족)
트리거 동작(표현식형 트리거 구성) 동작 내용(Expression) 배열 테이블(인덱스 1부터 연속)로, 요소는 buildCommonWriteMap(...) 등의 함수가 반환하는 map입니다. 빈 테이블 {}는 “쓰기 항목 없음”으로 간주합니다.
트리거 동작(혼합 쓰기형 트리거 구성) 각 dataKey에 개별 바인딩된 동작 해당 dataKey에 쓸 단일 값(문자열/숫자/불리언). buildCommonWriteMap 배열을 반환하지 마세요.
후처리 동작 트리거 동작 실행 후 마무리 스크립트 표현식형 트리거 동작과 동일한 쓰기 설명 배열 테이블. 고정 변수 ${trigger_result}(불리언), ${trigger_write_result}(JSON 문자열, jsonToMap로 파싱 필요)로 주 실행 결과를 판단할 수 있습니다.
집계 데이터 포인트 표현식 집계 데이터 계산 표현식 해당 집계 포인트의 최신 값으로 사용할 단일 값(숫자/문자열 등)
MQTT 발행 내용(publishContent) MQTT 발행 설정 발행 페이로드로 JSON 직렬화되는 Lua 테이블
MQTT 구독 동작(actionContent) MQTT 구독 설정 표현식형 트리거 동작과 동일한 쓰기 설명 배열 테이블
MQTT 응답 Topic(responseTopic) MQTT 구독 설정 응답 발행 Topic으로 사용할 단일 문자열
MQTT 응답 내용(response) MQTT 구독 설정 문자열은 그대로 전송하며, 다른 값(Lua 테이블 등)은 JSON으로 직렬화

개별 스크립트 호출에는 실행 제한 시간(기본 10초, 초과하면 실행 실패)이 있으므로 반복문에서 이력 조회나 HTTP 요청을 제한 없이 수행하지 마세요.

다음 모듈은 먼저 require("모듈_이름")해야 사용할 수 있습니다.

시간대, 형식화 및 계산 등을 지원하는 전체 날짜·시간 처리 모듈입니다.

local OffsetDateTime = require("OffsetDateTime")
메서드 설명 반환값
new() 현재 시간 생성 OffsetDateTime
new(sec, nsec?) Unix 타임스탬프에서 생성 OffsetDateTime
now() 현재 시간 가져오기 OffsetDateTime
parse(str) 시간 문자열 파싱 OffsetDateTime | (nil, err)
parseInLocation(str, location) 지정 시간대에서 시간 파싱 OffsetDateTime | (nil, err)
unix(sec, nsec?) Unix 초에서 생성 OffsetDateTime
unixMilli(msec) 밀리초 타임스탬프에서 생성 OffsetDateTime
unixMicro(usec) 마이크로초 타임스탬프에서 생성 OffsetDateTime

인스턴스 메서드 - 시간 구성 요소

섹션 제목: “인스턴스 메서드 - 시간 구성 요소”
메서드 설명 반환값
year() 연도 가져오기 number
month() 월 가져오기(1-12) number
day() 일 가져오기(1-31) number
hour() 시 가져오기(0-23) number
minute() 분 가져오기(0-59) number
second() 초 가져오기(0-59) number
nanosecond() 나노초 가져오기 number
yearDay() 연중 일수 가져오기 number
weekday() 요일 가져오기(0=일요일) number
isoWeek() ISO 주 정보 가져오기 {year, week}
date() 연월일 가져오기 {year, month, day}
clock() 시분초 가져오기 {hour, minute, second}
메서드 설명 반환값
add(durationStr) 시간 간격 더하기 OffsetDateTime | (nil, err)
addDate(years, months, days) 연월일 더하기 OffsetDateTime
sub(other) 시간 차이 계산(나노초) number
addYears(n) 연 더하기 OffsetDateTime
addMonths(n) 월 더하기 OffsetDateTime
addDays(n) 일 더하기 OffsetDateTime
addHours(n) 시간 더하기 OffsetDateTime
addMinutes(n) 분 더하기 OffsetDateTime
addSeconds(n) 초 더하기 OffsetDateTime
addMilliseconds(n) 밀리초 더하기 OffsetDateTime
addMicroseconds(n) 마이크로초 더하기 OffsetDateTime
addNanoseconds(n) 나노초 더하기 OffsetDateTime

인스턴스 메서드 - 시간 차이 계산

섹션 제목: “인스턴스 메서드 - 시간 차이 계산”
메서드 설명 반환값
diffYears(other) 연도 차이 계산 number
diffMonths(other) 개월 수 차이 계산 number
diffDays(other) 일수 차이 계산 number
diffHours(other) 시간 차이 계산 number
diffMinutes(other) 분 차이 계산 number
diffSeconds(other) 초 차이 계산 number
메서드 설명 반환값
equal(other) 같은지 확인 boolean
before(other) 이전인지 확인 boolean
after(other) 이후인지 확인 boolean
isZero() 제로 값인지 확인 boolean
메서드 설명 반환값
isToday() 오늘인지 확인 boolean
isYesterday() 어제인지 확인 boolean
isTomorrow() 내일인지 확인 boolean
isThisWeek() 이번 주인지 확인 boolean
isThisMonth() 이번 달인지 확인 boolean
isThisYear() 올해인지 확인 boolean
isBetween(start, end) 범위 내인지 확인 boolean
isInRange(start, end) 범위 내인지 확인 boolean
메서드 설명 반환값
format(layout) 사용자 정의 형식화 string
toString() 문자열로 변환 string
toDateTimeString() 날짜·시간 형식 string
toDateString() 날짜 형식 string
toTimeString() 시간 형식 string
toYearString() 연도 string
toMonthString() 월 string
toDayString() 일 string
toHourString() 시 string
toMinuteString() 분 string
toSecondString() 초 string

인스턴스 메서드 - Unix 타임스탬프

섹션 제목: “인스턴스 메서드 - Unix 타임스탬프”
메서드 설명 반환값
unix() Unix 초 타임스탬프 number
unixMilli() Unix 밀리초 타임스탬프 number
unixMicro() Unix 마이크로초 타임스탬프 number
unixNano() Unix 나노초 타임스탬프 number
메서드 설명 반환값
utc() UTC 시간대로 변환 OffsetDateTime
local() 현지 시간대로 변환 OffsetDateTime
in(location) 지정 시간대로 변환 OffsetDateTime | (nil, err)
메서드 설명 반환값
truncate(durationStr) 지정 정밀도로 절삭 OffsetDateTime | (nil, err)
round(durationStr) 지정 정밀도로 반올림 OffsetDateTime | (nil, err)
toTime() Go time.Time으로 변환 time.Time
local layouts = OffsetDateTime.Layout
-- layouts.DateTime = "2006-01-02 15:04:05"
-- layouts.Date = "2006-01-02"
-- layouts.Time = "15:04:05"
local OffsetDateTime = require("OffsetDateTime")
local Logger = require("Logger")
-- 현재 시간 가져오기
local now = OffsetDateTime.now()
Logger.warn(now:toString())
-- 시간 파싱
local dt = OffsetDateTime.parse("2024-01-15T10:30:00.000Z")
Logger.warn("年份: " .. dt:year())
Logger.warn("月份: " .. dt:month())
-- 시간 계산
local tomorrow = now:addDays(1)
local nextWeek = now:addDays(7)
Logger.warn("明天: " .. tomorrow:toDateString())
-- 시간 비교
if now:isToday() then
Logger.warn("今天!")
end
-- 시간 차이
local hours = nextWeek:diffHours(now)
Logger.warn("相差小时: " .. hours)
-- 형식 지정
Logger.warn(now:format("2006-01-02 15:04:05"))
Logger.warn(now:toDateTimeString())

날짜와 시간대 없이 시분초만 포함하는 시간 유형입니다.

local LocalTime = require("LocalTime")
메서드 설명 반환값
new(hour, minute, second) 시간 생성 LocalTime | (nil, err)
now() 현재 시간 가져오기 LocalTime
parse(str) “HH:mm:ss” 파싱 LocalTime | (nil, err)
fromTime(time.Time) time.Time에서 생성 LocalTime | (nil, err)
fromDuration(durationStr) 시간 간격에서 생성 LocalTime | (nil, err)
메서드 설명 반환값
hour() 시 가져오기 number
minute() 분 가져오기 number
second() 초 가져오기 number
toString() “HH:mm:ss”로 변환 string
toDuration() 시간 간격 문자열로 변환 string
equal(other) 같은지 확인 boolean
before(other) 이전인지 확인 boolean
after(other) 이후인지 확인 boolean
beforeOrEqual(other) 이전이거나 같은지 확인 boolean
afterOrEqual(other) 이후이거나 같은지 확인 boolean
isZero() 00:00:00인지 확인 boolean
diffSeconds(other) 초 차이 number
diffMinutes(other) 분 차이 number
diffHours(other) 시간 차이 number
addSeconds(n) 초 더하기 LocalTime
addMinutes(n) 분 더하기 LocalTime
addHours(n) 시간 더하기 LocalTime
subSeconds(n) 초 빼기 LocalTime
subMinutes(n) 분 빼기 LocalTime
subHours(n) 시간 빼기 LocalTime
local LocalTime = require("LocalTime")
local Logger = require("Logger")
-- 시간 생성
local workStart = LocalTime.new(9, 0, 0) -- 09:00:00
local workEnd = LocalTime.new(17, 30, 0) -- 17:30:00
-- 현재 시간 가져오기
local now = LocalTime.now()
Logger.warn("当前时间: " .. now:toString())
-- 시간 비교
if now:isBetween(workStart, workEnd) then
Logger.warn("工作时间")
else
Logger.warn("非工作时间")
end
-- 시간 계산
local breakTime = workStart:addHours(3):addMinutes(30) -- 12:30:00
Logger.warn("午休时间: " .. breakTime:toString())
-- 시간 차이
local workHours = workEnd:diffHours(workStart)
Logger.warn("工作时长: " .. workHours .. " 小时")

시스템 로그와 연계되는 로그 출력 모듈입니다.

local Logger = require("Logger")
메서드 설명 매개변수
info(msg) INFO 로그 출력 string
warn(msg) WARN 로그 출력 string
error(msg) ERROR 로그 출력 string
debug(msg) DEBUG 로그 출력 string
infof(fmt, ...) 형식화된 INFO 로그 출력 string, …
warnf(fmt, ...) 형식화된 WARN 로그 출력 string, …
errorf(fmt, ...) 형식화된 ERROR 로그 출력 string, …
debugf(fmt, ...) 형식화된 DEBUG 로그 출력 string, …
local Logger = require("Logger")
Logger.info("系统启动")
Logger.warn("磁盘空间不足")
Logger.error("数据库连接失败")
Logger.debug("变量值: x=10")
-- 서식화된 출력
local user = "admin"
local action = "login"
Logger.infof("用户 %s 执行操作: %s", user, action)
Logger.warnf("重试次数: %s", 3)

참고: Edge-EMS Builder의 기본 로그 출력 수준은 WARN이므로 WARN과 ERROR 로그만 출력됩니다.


JSON 직렬화/역직렬화 및 조작 모듈입니다(bytedance/sonic 기반).

local JSON = require("JSON")
메서드 설명 반환값
encode(value) JSON으로 직렬화 string | (nil, err)
decode(text) 역직렬화 table | (nil, err)
메서드 설명 반환값
toJSONString(value) 직렬화(오류 반환 없음) string
toJSONStringIndent(value, prefix?, indent?) 형식화하여 직렬화 string
toMap(jsonStr) map으로 변환 table | (nil, err)
toStringMap(jsonStr) string map으로 변환 table | (nil, err)
toSlice(jsonStr) 배열로 변환 table | (nil, err)
isValid(jsonStr) JSON 형식 검증 boolean
pretty(jsonStr) JSON을 읽기 좋게 형식화 string
merge(json1, json2) 두 JSON 병합 string | (nil, err)
get(jsonStr, key) 값 가져오기 any | (nil, err)
set(jsonStr, key, value) 값 설정 string | (nil, err)
remove(jsonStr, key) 키 삭제 string | (nil, err)
clone(value) 깊은 복사 any | (nil, err)
local JSON = require("JSON")
local Logger = require("Logger")
-- 기본 직렬화/역직렬화
local obj = {name = "张三", age = 30, tags = {"developer", "golang"}}
local jsonStr = JSON.encode(obj)
Logger.warn(jsonStr) -- {"name":"张三","age":30,"tags":["developer","golang"]}
local decoded, err = JSON.decode(jsonStr)
if not decoded then
Logger.warn("解析失败: " .. err)
else
Logger.warn("姓名: " .. decoded.name)
end
-- 서식화된 출력
local pretty = JSON.pretty(jsonStr)
Logger.warn(pretty)
-- JSON 검증
if JSON.isValid(jsonStr) then
Logger.warn("有效的 JSON")
end
-- JSON 조작
local newJson = JSON.set(jsonStr, "city", "北京")
Logger.warn(newJson) -- {"name":"张三","age":30,"tags":[...],"city":"北京"}
local age = JSON.get(newJson, "age")
Logger.warn("年龄: " .. age) -- 30
local removed = JSON.remove(newJson, "age")
Logger.warn(removed) -- {"name":"张三","tags":[...],"city":"北京"}
-- JSON 병합
local json1 = '{"a":1}'
local json2 = '{"b":2}'
local merged = JSON.merge(json1, json2)
Logger.warn(merged) -- {"a":1,"b":2}
-- 깊은 복사
local original = {data = {x = 10}}
local copied = JSON.clone(original)

매칭, 검색, 치환 및 분할 등을 지원하는 정규 표현식 모듈입니다.

local Regex = require("Regex")
메서드 설명 반환값
match(text, pattern) 일치 여부 확인 boolean
findAll(text, pattern, limit?) 모든 일치 항목 검색(캡처 그룹 포함) {{full, g1, g2, …}, …} | (nil, err)
replace(text, pattern, repl) 치환($1 등의 그룹 참조 지원) string | (nil, err)
split(text, pattern, limit?) 정규식으로 분할 {string, …} | (nil, err)
isEmail(text) 이메일 주소인지 확인 boolean
isPhone(text) 중국 휴대전화 번호인지 확인 boolean
isIP(text) IP 주소인지 확인 boolean
isURL(text) URL인지 확인 boolean
local Regex = require("Regex")
local Logger = require("Logger")
-- 매칭
if Regex.match("abc123", "\\d+") then
Logger.warn("包含数字")
end
-- 모든 일치 항목 찾기(캡처 그룹 포함)
local matches = Regex.findAll("a1 b22 c333", "(\\w)(\\d+)")
-- matches = {{"a1","a","1"}, {"b22","b","22"}, {"c333","c","333"}}
for i, m in ipairs(matches) do
Logger.warn("匹配 " .. i .. ": " .. m[1] .. ", 字母=" .. m[2] .. ", 数字=" .. m[3])
end
-- 치환(그룹 참조 지원)
local s = Regex.replace("abc-123-def", "(\\d+)", "[$1]")
Logger.warn(s) -- "abc-[123]-def"
-- 분할
local parts = Regex.split("a,b,,c", ",", -1)
-- parts = {"a", "b", "", "c"}
for i, p in ipairs(parts) do
Logger.warn("部分 " .. i .. ": '" .. p .. "'")
end
-- 검증
Logger.warn(Regex.isEmail("test@example.com")) -- true
Logger.warn(Regex.isPhone("13812345678")) -- true
Logger.warn(Regex.isIP("192.168.1.1")) -- true
Logger.warn(Regex.isURL("https://example.com")) -- true

문자열 처리 도구입니다.

local String = require("String")
메서드 설명 반환값
trim(s) 앞뒤 공백 제거 string
upper(s) 대문자로 변환 string
lower(s) 소문자로 변환 string
contains(s, sub) 부분 문자열 포함 여부 boolean
startsWith(s, prefix) 지정 접두사로 시작하는지 확인 boolean
endsWith(s, suffix) 지정 접미사로 끝나는지 확인 boolean
local String = require("String")
local s = " Hello World "
Logger.warn(String.trim(s)) -- "Hello World"
Logger.warn(String.upper(s)) -- " HELLO WORLD "
Logger.warn(String.lower(s)) -- " hello world "
Logger.warn(String.contains("hello", "ll")) -- true
Logger.warn(String.startsWith("hello", "he")) -- true
Logger.warn(String.endsWith("hello", "lo")) -- true

수학 계산 도구입니다.

local Math = require("Math")
메서드 설명 반환값
round(n) 반올림 number
floor(n) 내림 number
ceil(n) 올림 number
abs(n) 절댓값 number
max(a, b) 최댓값 number
min(a, b) 최솟값 number
local Math = require("Math")
Logger.warn(Math.round(3.6)) -- 4
Logger.warn(Math.floor(3.9)) -- 3
Logger.warn(Math.ceil(3.1)) -- 4
Logger.warn(Math.abs(-5)) -- 5
Logger.warn(Math.max(10, 20)) -- 20
Logger.warn(Math.min(10, 20)) -- 10

배열과 키-값 쌍 순회를 지원하는 테이블(table) 조작 도구입니다.

local TableUtils = require("TableUtils")
메서드 설명 반환값
keys(tbl) 모든 키 가져오기 {string, …}
values(tbl) 모든 값 가져오기 {any, …}
map(tbl, fn) 매핑(fn(value, key)) {any, …}
filter(tbl, fn) 필터링(fn(value, key)) {any, …}
reduce(tbl, fn, init) 리듀스(fn(acc, value, key)) any
sortBy(tblOfMaps, key) 키 기준 정렬(안정 정렬) {map, …}
local T = require("TableUtils")
-- keys/values
local obj = {a = 1, b = 2, c = 3}
local keys = T.keys(obj) -- {"a", "b", "c"}
local values = T.values(obj) -- {1, 2, 3}
-- map(배열)
local arr = {1, 2, 3}
local doubled = T.map(arr, function(v, i)
return v * 2
end)
-- doubled = {2, 4, 6}
-- map(키-값 쌍)
local mapped = T.map({a=1, b=2}, function(v, k)
return k .. ":" .. v
end)
-- mapped = {"a:1", "b:2"}
-- filter
local arr = {1, 2, 3, 4, 5}
local even = T.filter(arr, function(v, i)
return v % 2 == 0
end)
-- even = {2, 4}
-- reduce
local sum = T.reduce({1, 2, 3}, function(acc, v, i)
return acc + v
end, 0)
-- sum = 6
-- sortBy
local users = {
{name="张三", age=30},
{name="李四", age=25},
{name="王五", age=35}
}
local sorted = T.sortBy(users, "age")
-- sorted = {{name="李四",age=25}, {name="张三",age=30}, {name="王五",age=35}}

다음 함수는 전역 범위에 직접 등록되므로 require가 필요하지 않습니다.

함수 용도
cp56Time2aToOffsetDateTime(hex[, byteOrder]) IEC 60870-5 시간을 디코딩하고 OffsetDateTime 반환
offsetDateTimeToCP56Time2a(time[, byteOrder]) 시간을 16진수 페이로드로 인코딩

byteOrder는 AB / BA를 지원하며 지정하지 않으면 표준 AB를 사용합니다. 명시적으로 지정하면 4레지스터 페이로드를 지원합니다. 0 패딩 위치가 모호하면 오류를 반환하므로 장치 레지스터 배치를 확인해야 합니다.

함수 설명 반환값
jsonToMap(str) JSON을 map으로 변환 table | (nil, err)
jsonToList(str) JSON을 list로 변환 table | (nil, err)
jsonToListMap(str) JSON을 list of map으로 변환 table | (nil, err)
completeDateTime(str) 날짜·시간 문자열 보완 string | (nil, err)
quoteJson(str) JSON 따옴표 이스케이프 string
simpleUUID() 간단한 UUID 생성 string
convertString(str) 문자열 형 변환 any
isNull(any) 값이 비어 있는지 확인 bool
isNotNull(any) 값이 비어 있지 않은지 확인 bool

isNull는 nil, 빈 문자열, 대소문자를 구분하지 않는 “null” 및 센티널 __Null__를 빈 값으로 취급합니다. Lua의 or 0는 이 센티널을 처리할 수 없습니다.

local Logger = require("Logger")
-- JSON 파싱
local map, err = jsonToMap('{"a":1,"b":2}')
if map then
Logger.warn(map.a) -- 1
end
local list = jsonToList('[1,2,3]')
-- list = {1, 2, 3}
-- 시간 자동 완성
local fullTime = completeDateTime("2024-01-15")
-- fullTime = "2024-01-15T00:00:00.000+08:00"
-- UUID 생성
local id = simpleUUID()
Logger.warn(id) -- 32자리 UUID 문자열

함수 설명 반환값
getLatestDataValue(dataKey) 최신 데이터 값 가져오기 any
getAccountCache(key) 계정 캐시 가져오기 any
getEMSDataCache(key) EMS 데이터 캐시 가져오기 any
getShareCache(key) 공유 캐시 가져오기 any
getMqttCache(key) MQTT 캐시 가져오기 any
getTriggerCache(key) 트리거 캐시 가져오기 any
getDeviceShareValue(deviceCode, dataKey) 단일 deviceCode와 dataKey로 해당 장치 공유 데이터의 최신 값 가져오기 string | nil
getDeviceShareValues(deviceCodes, dataKey) 장치 목록과 dataKey로 각 장치의 해당 데이터 최신 값 가져오기 table
getAllDeviceShareValues(dataKey) dataKey로 공유 공간 내 모든 장치의 해당 데이터 최신 값 가져오기 table
local Logger = require("Logger")
-- 장치의 최신 데이터 가져오기
local value = getLatestDataValue("device1.temperature")
Logger.warn("当前温度: " .. value)
-- 계정 정보 가져오기
local account = getAccountCache("user123")
if account then
Logger.warn("用户名: " .. account.username)
end
-- 공유 데이터 가져오기
local sharedData = getShareCache("shared_config")
-- 단일 장치의 최신 공유 데이터 값 가져오기
local val = getDeviceShareValue("device1", "temperature")
if val ~= nil then
Logger.warn("设备 device1 温度: " .. val)
end
-- 장치 목록을 통해 각 장치의 공유 데이터 값 가져오기
local deviceCodes = {"device1", "device2"}
local shareValues = getDeviceShareValues(deviceCodes, "temperature")
if shareValues then
for deviceCode, dataValue in pairs(shareValues) do
Logger.warn("设备 " .. deviceCode .. " 温度: " .. dataValue)
end
end
-- 모든 장치의 공유 데이터 값 가져오기
local allShareValues = getAllDeviceShareValues("temperature")
if allShareValues then
for deviceCode, dataValue in pairs(allShareValues) do
Logger.warn("设备 " .. deviceCode .. " 温度: " .. dataValue)
end
end

dataKey 패턴으로 최신 값 일괄 조회

섹션 제목: “dataKey 패턴으로 최신 값 일괄 조회”

다음 함수는 로컬 최신 값 캐시를 검색하여 dataKey의 접두사, 접미사 또는 키워드로 필터링한 후 일치하는 데이터 포인트 정보를 반환합니다. 반환값은 {dataKey: FrontDataDTO} table입니다.

반환값 필드 설명(각 값은 다음 주요 필드를 포함하는 FrontDataDTO 객체):

필드 유형 설명
DataKey string 데이터 고유 키
DataValue string 최신 값
DataType string 데이터 유형
DataName string 데이터 이름
DataUnit string 단위
CollectionTime OffsetDateTime 수집 시간

참고: nil 반환은 캐시에 일치 항목이 없음을 뜻합니다. dataType 매개변수는 열거형 값(Collection / Customization / Aggregation / Share)과 정확히 일치해야 합니다.

함수 설명 반환값
getLatestDataValuesBySuffix(dataType, suffix) 지정 유형에서 dataKey가 suffix로 끝나는 최신 값 조회 table | nil
getAllLatestDataValuesBySuffix(suffix) 모든 유형에서 dataKey가 suffix로 끝나는 최신 값 조회 table | nil
함수 설명 반환값
getLatestDataValuesByPrefix(dataType, prefix) 지정 유형에서 dataKey가 prefix로 시작하는 최신 값 조회 table | nil
getAllLatestDataValuesByPrefix(prefix) 모든 유형에서 dataKey가 prefix로 시작하는 최신 값 조회 table | nil
함수 설명 반환값
getLatestDataValuesByPrefixAndSuffix(dataType, prefix, suffix) 지정 유형에서 dataKey가 prefix와 suffix를 모두 충족하는 최신 값 조회 table | nil
getAllLatestDataValuesByPrefixAndSuffix(prefix, suffix) 모든 유형에서 dataKey가 prefix와 suffix를 모두 충족하는 최신 값 조회 table | nil
함수 설명 반환값
getLatestDataValuesByFuzzy(dataType, keyword) 지정 유형에서 dataKey에 keyword가 포함된 최신 값 조회 table | nil
getAllLatestDataValuesByFuzzy(keyword) 모든 유형에서 dataKey에 keyword가 포함된 최신 값 조회 table | nil
local Logger = require("Logger")
-- "_power"로 끝나는 모든 수집 데이터의 최신 값 조회
local powerValues = getLatestDataValuesBySuffix("Collection", "_power")
if powerValues then
for dataKey, dto in pairs(powerValues) do
Logger.warn(dataKey .. " = " .. dto.DataValue)
end
end
-- 모든 유형에서 "_power"로 끝나는 최신 값 조회(데이터 유형 제한 없음)
local allPower = getAllLatestDataValuesBySuffix("_power")
-- "meter1."로 시작하는 모든 수집 데이터 조회
local meterValues = getLatestDataValuesByPrefix("Collection", "meter1.")
if meterValues then
for dataKey, dto in pairs(meterValues) do
Logger.warnf("%s = %s (%s)", dataKey, dto.DataValue, dto.DataUnit)
end
end
-- 모든 유형에서 "meter1."로 시작하는 데이터 조회
local allMeter = getAllLatestDataValuesByPrefix("meter1.")
-- dataKey가 "meter1."로 시작하고 "_voltage"로 끝나는 수집 데이터 조회
local voltages = getLatestDataValuesByPrefixAndSuffix("Collection", "meter1.", "_voltage")
-- 모든 유형에서 prefix와 suffix 조건을 모두 충족하는 데이터 조회
local allVoltages = getAllLatestDataValuesByPrefixAndSuffix("meter1.", "_voltage")
-- 부분 일치 검색: 집계 데이터에서 dataKey에 "temp"가 포함된 최신 값 조회
local tempValues = getLatestDataValuesByFuzzy("Aggregation", "temp")
if tempValues then
for dataKey, dto in pairs(tempValues) do
Logger.warn("温度点位: " .. dataKey .. " = " .. dto.DataValue)
end
end
-- 부분 일치 검색: 모든 유형에서 dataKey에 "temp"가 포함된 최신 값 조회
local allTemp = getAllLatestDataValuesByFuzzy("temp")

함수 설명 반환값
getDeviceList(ignoreLocal) 장치 목록 가져오기, ignoreLocal=true이면 로컬 장치 제외 table
getDeviceCodeList(ignoreLocal) deviceCode 목록 가져오기, ignoreLocal=true이면 로컬 장치 제외 table
local Logger = require("Logger")
-- 모든 장치 목록 가져오기
local allDevices = getDeviceList(false)
if allDevices then
for i, device in ipairs(allDevices) do
Logger.warn("设备: " .. device.deviceCode .. " - " .. device.deviceName)
end
end
-- 현재 장치를 제외한 장치 목록 가져오기
local otherDevices = getDeviceList(true)
if otherDevices then
for i, device in ipairs(otherDevices) do
Logger.warn("共享设备: " .. device.deviceCode)
end
end
-- 모든 장치 코드 목록 가져오기(전체 장치 목록을 가져오는 것보다 빠름)
local deviceCodes = getDeviceCodeList(false)
if deviceCodes then
for i, code in ipairs(deviceCodes) do
Logger.warn("设备编码: " .. code)
end
end
-- 현재 장치를 제외한 장치 코드 목록 가져오기
local otherDeviceCodes = getDeviceCodeList(true)

함수 설명 반환값
getHistoryData(dataType, dataKey, startTime?, endTime?, formatMap?) 이력 데이터 가져오기 table
getShareHistoryData(deviceCode, dataKey, startTime?, endTime?, formatMap?) 지정 장치의 공유 이력 데이터 가져오기 table
getTimeData(dataKey, time?, interval?) 지정 시점 데이터 가져오기 table
getShareTimeData(deviceCode, dataKey, time?, interval?) 지정 시점 공유 데이터 가져오기 table
deleteCustomizationData(dataKey, startTime?, endTime?) 사용자 정의 데이터 삭제 boolean

매개변수 설명:

  • startTime/endTime/time: 다음 형식 지원
    • OffsetDateTime 객체(권장)
    • 시간 문자열(예: “2024-01-15T10:00:00.000Z”)
    • 축약 문자열(예: “2024-01-15”, 자동 보완됨)
  • formatMap: 반환 결과의 필드 이름을 사용자 정의하는 선택 매개변수(table 유형)
    • dataKey: 데이터 키 필드 이름 사용자 정의(기본값: “dataKey”)
    • dataValue: 데이터 값 필드 이름 사용자 정의(기본값: “dataValue”)
    • collectionTime: 수집 시간 필드 이름 사용자 정의(기본값: “collectionTime”)

Customization 유형 반환 필드 설명:

getHistoryData / getTimeData가 Customization 데이터에 반환하는 시간 필드는 일정 유형에 따라 달라집니다.

  • DailyChange: availableTime(ISO 8601 전체 날짜·시간) 및 expiredTime 반환
  • DailyRepeat: availableTime(HH:mm:ss 문자열) 및 expiredTime(HH:mm:ss 문자열) 반환
local OffsetDateTime = require("OffsetDateTime")
local Logger = require("Logger")
-- 방법 1: OffsetDateTime 객체 사용(권장)
local now = OffsetDateTime.now()
local startTime = now:addDays(-7)
local endTime = now
local data = getHistoryData("Collection", "temperature", startTime, endTime)
-- 방법 1 확장: formatMap으로 반환 필드 이름 사용자 지정
local formatMap = {
dataKey = "key",
dataValue = "value",
collectionTime = "time"
}
local data = getHistoryData("Collection", "temperature", startTime, endTime, formatMap)
-- 방법 2: 시간 문자열 사용
local data = getHistoryData("Collection", "temperature", "2024-01-01T00:00:00.000Z", "2024-01-31T23:59:59.000Z")
-- 방법 3: 축약 문자열 사용(자동 완성)
local data = getHistoryData("Collection", "temperature", "2024-01-01", "2024-01-31")
-- 공유 이력 데이터 조회
local sharedData = getShareHistoryData("space1", "pressure", startTime, endTime)
-- 지정된 시점의 데이터 조회
local value = getTimeData("temperature", now, "5m")
-- 사용자 정의 데이터 삭제
local deleted = deleteCustomizationData("data1", startTime, endTime)
Logger.warn("删除成功: " .. tostring(deleted))

함수 설명 반환값
buildCommonWriteMap(dataType, dataKey, dataValue, availableDate, expiredDate, changeMod) 일반 쓰기 map 생성 table
buildGeneralWriteMap(dataType, dataKey, dataValue, changeMod) 일반 쓰기 map 생성(시간 매개변수가 없는 간소화 버전) table
buildCustomizationWriteMap(dataKey, dataValue, availableDate, expiredDate) DailyChange 시간대별 데이터 쓰기 map 생성(암묵적으로 dataType=Customization) table
buildDailyRepeatWriteMap(dataKey, dataValue, availableTime, expiredTime) DailyRepeat 시간대별 데이터 쓰기 map 생성(암묵적으로 dataType=Customization, 시간 매개변수는 HH:mm:ss 문자열) table
updateDailyRepeatSchedule(dataKey, scheduleAvailableDate, scheduleExpiredDate) DailyRepeat 설정의 전체 유효 구간 갱신. 두 날짜 매개변수 모두 nil를 전달할 수 있으며, nil는 제한 없음(영구 유효)을 의미 boolean
buildAlarmObservationMap(sourceCode, alarmKey, state, alarmType, alarmLevel, alarmContent[, detailKey]) 알람 이벤트 관측 생성. state는 ACTIVE / NORMAL / UNKNOWN table
buildCommonAlarmMap(alarmType, alarmContent) 일반 알람 map 생성 table
buildMqttAlarmMap(alarmType, alarmContent, mqttConnectionConfigId, topic, qos) MQTT 알람 map 생성 table
buildSlaveWriteMap(deviceCode, dataType, dataKey, dataValue, availableDate, expiredDate, changeMod) 종속 장치 쓰기 map 생성 table

알람 관측에는 안정적인 sourceCode + alarmKey를 사용하며, 정상일 때 NORMAL, 값이 없거나 오프라인이면 UNKNOWN을 보냅니다. 이벤트 상태와 관측 상태는 다릅니다. 전체 절차는 알람 수명 주기를 참조하세요. 기존 알람 생성 함수는 계속 독립 기록을 생성합니다.

수집 데이터 쓰기 계수 역산은 CommBridge가 처리합니다. 기존 buildCollectionWriteMap는 제거되었으므로 일반 쓰기 생성 함수를 사용하고 중복 환산하지 마세요.

매개변수 설명:

  • dataType: 작업할 데이터 유형. 가능한 값은 Collection(수집) / Customization(사용자 정의/시간대별) / Aggregation(집계) / Share(공유) / Alarm(알람)
  • availableDate / expiredDate: Customization(DailyChange 유형)에만 필요하며 ISO 8601 문자열 또는 OffsetDateTime 객체를 사용할 수 있습니다. 다른 유형에는 nil를 전달합니다.
  • availableTime / expiredTime: Customization(DailyRepeat 유형)에만 필요하며 형식은 "HH:mm:ss"(예: "08:00:00")입니다. 자정을 넘어서는 안 됩니다.
  • changeMod: 불리언 값이며 true는 값이 변경된 경우에만 쓴다는 의미입니다.
local OffsetDateTime = require("OffsetDateTime")
-- 수집 데이터 포인트 쓰기
local writeCollection = buildCommonWriteMap("Collection", "temperature", 25.5, nil, nil, false)
-- 사용자 정의 데이터 포인트 쓰기(DailyChange: 전체 날짜 및 시간 구간 포함)
local writeCustom = buildCommonWriteMap(
"Customization", "mode", "1",
"2024-01-15T07:00:00+08:00",
"2024-01-15T18:00:00+08:00",
false
)
-- 사용자 정의 데이터 포인트 쓰기(DailyChange: 전용 축약 함수 사용)
local writeCustom2 = buildCustomizationWriteMap(
"mode", "1",
"2024-01-15T07:00:00+08:00",
"2024-01-15T18:00:00+08:00"
)
-- 사용자 정의 데이터 포인트 쓰기(DailyRepeat: 매일 반복되는 시간대, HH:mm:ss 형식)
local writeDailyRepeat = buildDailyRepeatWriteMap("charge_mode", "1", "08:00:00", "18:00:00")
-- DailyRepeat 설정의 전체 유효 기간 갱신(유효 기간 범위 설정)
local OffsetDateTime = require("OffsetDateTime")
local ok = updateDailyRepeatSchedule("charge_mode",
OffsetDateTime.parse("2026-01-01T00:00:00+08:00"),
OffsetDateTime.parse("2026-12-31T23:59:59+08:00"))
-- 영구 유효로 갱신(두 날짜 모두 nil 전달)
local ok2 = updateDailyRepeatSchedule("charge_mode", nil, nil)
-- 시작 시간만 설정하고 종료 시간은 설정하지 않음(nil은 만료되지 않음을 의미)
local ok3 = updateDailyRepeatSchedule("charge_mode", "2026-01-01", nil)
-- 집계 데이터 포인트 쓰기(시간 매개변수가 없는 간소화 버전)
local writeAgg = buildGeneralWriteMap("Aggregation", "avg_temp", 22.5, false)
-- 알람 생성(현재 장치의 알람 기록에 쓰기)
local alarm = buildCommonAlarmMap("TEMP_HIGH", "温度超过80°C")
-- MQTT 알람 생성(MQTT 연결 ID를 연결해야 하며, 알람은 MQTT Broker에도 보고됨)
local mqttAlarm = buildMqttAlarmMap("TEMP_HIGH", "温度超过80°C", 1, "alarm/upload", 1)
-- 슬레이브의 공유 데이터 쓰기
local slaveWrite = buildSlaveWriteMap("DeviceB", "Share", "shared_temp", 25.5, nil, nil, false)

함수 설명 반환값
toFixedLengthBinary(value, length) 고정 길이 이진수로 변환 string | (nil, err)
toDecimal(binaryStr) 이진수를 10진수로 변환 number | (nil, err)
-- 10진수를 2진수로 변환
local binary = toFixedLengthBinary(10, 8)
Logger.warn(binary) -- "00001010"
-- 2진수를 10진수로 변환
local decimal = toDecimal("00001010")
Logger.warn(decimal) -- 10

local Logger = require("Logger")
local JSON = require("JSON")
local OffsetDateTime = require("OffsetDateTime")
local Math = require("Math")
local Logger = require("Logger")
Logger.info("设备监控脚本启动")
-- 장치의 최신 데이터 가져오기
local temperature = getLatestDataValue("device1.temperature")
local humidity = getLatestDataValue("device1.humidity")
Logger.infof("当前温度: %.1f°C, 湿度: %.1f%%", temperature, humidity)
-- 온도 알람 판단
if temperature > 80 then
local alarm = buildCommonAlarmMap("TEMP_HIGH", "温度超过80°C")
Logger.error("温度告警: " .. JSON.toJSONString(alarm))
end
-- 이력 데이터 조회
local now = OffsetDateTime.now()
local startTime = now:addHours(-24)
local history = getHistoryData(
"device1",
"temperature",
startTime:toString(),
now:toString()
)
Logger.infof("获取到 %d 条历史数据", #history)
-- 평균값 계산
local sum = 0
for i, record in ipairs(history) do
sum = sum + record.value
end
local avg = sum / #history
Logger.infof("24小时平均温度: %.2f°C", Math.round(avg * 100) / 100)
local JSON = require("JSON")
local Regex = require("Regex")
local TableUtils = require("TableUtils")
local String = require("String")
local Logger = require("Logger")
-- 캐시에서 설정 가져오기
local configJson = getShareCache("device_config")
local config = JSON.decode(configJson)
-- 활성화된 장치 필터링
local enabledDevices = TableUtils.filter(config.devices, function(device, index)
return device.enabled == true
end)
-- 장치 이름 추출
local deviceNames = TableUtils.map(enabledDevices, function(device, index)
return device.name
end)
-- 데이터 정제
local cleanedNames = TableUtils.map(deviceNames, function(name, index)
-- 공백을 제거하고 대문자로 변환
return String.upper(String.trim(name))
end)
-- 장치 번호 형식 검증
for i, device in ipairs(enabledDevices) do
if not Regex.match(device.id, "^DEV\\d{6}$") then
Logger.warnf("设备编号格式错误: %s", device.id)
end
end
-- 결과 출력
Logger.info("处理完成: " .. JSON.toJSONString(cleanedNames))

  1. 오류 처리: 대부분의 함수는 (result, error) 형식으로 반환하므로 오류를 확인해야 합니다.
  2. 시간 형식: 시간 문자열은 ISO 8601 형식을 사용합니다.
  3. 정규 표현식: Lua 기본 pattern과 다른 Go 정규식 문법을 사용합니다.
  4. 테이블 순회: TableUtils의 map/filter/reduce는 배열 부분(1..n)을 먼저 순회한 후 키-값 쌍을 순회합니다.
  5. 로그 수준: Logger의 출력 수준은 시스템 설정에 따라 결정됩니다.
  6. JSON 성능: 런타임은 고성능 JSON 처리를 사용하여 대량 직렬화에 적합합니다.

데이터 포인트에 값이 있는지 판단

섹션 제목: “데이터 포인트에 값이 있는지 판단”
if isNotNull(${some_key}) then
return {}
end
return { buildCommonWriteMap("Collection", "target_key", ${some_key}, nil, nil, false) }