Skip to content
JelinaJelina DocumentationTechnical documentation
Back to website

Complete Lua Script Reference

This is the complete reference for scripting in the Edge-EMS Builder expression engine: aggregation expressions, trigger conditions/actions, post-processing actions, and MQTT publish/subscribe content. Scripts use Lua 5.x, parsed and executed by the built-in Lua runtime. Start with the expression engine for an introduction. This page supplies the complete built-in modules, global function signatures, and return-value conventions.

⚠️ If you used an early Java version of Edge-EMS Builder with the QLExpress4 engine and Java-like syntax, note that ${...} variable references remain largely unchanged, while script bodies now use standard Lua. Examples: new ArrayList() → {}, .add(x) → table.insert(t, x), new HashMap() → {}, .put(k, v) → t[k] = v. Most built-in function names remain; use this page as a migration reference.

  • Language: Lua 5.x; function names and placeholders are case-sensitive.
  • Data placeholders: the engine replaces ${dataKey} with the current value before execution; use ${[deviceCode]dataKey} across devices.
  • Sentinel: unavailable data is injected as the string __Null__. Compare explicitly or use isNull / isNotNull; use tonumber before numerical calculations.
  • Return values vary by context, as described below. Incorrect return types are the most common source of configuration errors.
  • Module functions require require("module-name") before use. Global functions, such as buildCommonWriteMap and jsonToMap, can be called directly without require.
  • Logging: Logger defaults to WARN, so only Logger.warn() / Logger.error() actually produce output. Do not rely solely on Logger.info()/Logger.debug() when debugging.
Syntax Description
${variable} Returns the current value
${variable[-1s]} Returns the value 1 second ago
${variable[-5s]} Returns the value 5 seconds ago
${variable[raw]} Injects the value unchanged without automatic type conversion. For ambiguous values such as numeric 1000 and binary 1000, use raw to control unchanged input. [raw] must appear last and nowhere else.
${[deviceA]variable} Returns the value from shared device deviceA
${variable[@timestamp]} Returns the value at a specified absolute time
${variable[#N]} Returns the Nth most recent historical value; without this rule, returns the latest value
${[deviceA]variable[-5s][#N]} Returns the Nth most recent sample from shared device deviceA as of 5 seconds ago

When a target point has no value, the engine injects the sentinel string __Null__. Check explicitly, for example: if ${some_key} == "__Null__" then ... end.

Different script locations require entirely different return values. This is a frequent source of errors:

Context Configuration location Required return value
Trigger condition Trigger-condition expression A single Boolean; true means the condition is satisfied
Trigger action: expression-type scheme Action content (Expression) Array table with consecutive indices starting at 1, containing maps returned by functions such as buildCommonWriteMap(...); empty table {} means no write items
Trigger action: mixed-write scheme Action individually bound to each dataKey A single value (string/number/Boolean) to write to that dataKey; do not return a buildCommonWriteMap array
Post-processing action Cleanup script after trigger-action execution Array table of write descriptors, as for expression-type actions. Inspect the main execution result through fixed variables ${trigger_result} (Boolean) and ${trigger_write_result} (JSON string requiring jsonToMap)
Aggregation point expression Aggregation calculation expression A single value, such as a number or string, as the point’s latest value
MQTT publication content (publishContent) MQTT publish configuration Lua table, serialized as JSON for the publication payload
MQTT subscription action (actionContent) MQTT subscribe configuration Array table of write descriptors, as for expression-type trigger actions
MQTT response topic (responseTopic) MQTT subscribe configuration A single string used as the response publication topic
MQTT response content (response) MQTT subscribe configuration Strings are sent unchanged; other values, such as Lua tables, are serialized as JSON

Each script call has an execution timeout, 10 seconds by default. Exceeding it fails that execution. Avoid unbounded historical queries or HTTP requests inside loops.

The following modules require require("module-name") before use.

A complete date/time module supporting time zones, formatting, arithmetic, and more.

local OffsetDateTime = require("OffsetDateTime")
Method Description Return value
new() Create the current time OffsetDateTime
new(sec, nsec?) Create from a Unix timestamp OffsetDateTime
now() Get the current time OffsetDateTime
parse(str) Parse a time string OffsetDateTime | (nil, err)
parseInLocation(str, location) Parse time in a specified time zone OffsetDateTime | (nil, err)
unix(sec, nsec?) Create from Unix seconds OffsetDateTime
unixMilli(msec) Create from a millisecond timestamp OffsetDateTime
unixMicro(usec) Create from a microsecond timestamp OffsetDateTime
Method Description Return value
year() Get year number
month() Get month (1–12) number
day() Get day of month (1–31) number
hour() Get hour (0–23) number
minute() Get minute (0–59) number
second() Get second (0–59) number
nanosecond() Get nanoseconds number
yearDay() Get day of year number
weekday() Get weekday (0 = Sunday) number
isoWeek() Get ISO week information {year, week}
date() Get year, month, and day {year, month, day}
clock() Get hour, minute, and second {hour, minute, second}
Method Description Return value
add(durationStr) Add a duration OffsetDateTime | (nil, err)
addDate(years, months, days) Add years, months, and days OffsetDateTime
sub(other) Calculate time difference in nanoseconds number
addYears(n) Add years OffsetDateTime
addMonths(n) Add months OffsetDateTime
addDays(n) Add days OffsetDateTime
addHours(n) Add hours OffsetDateTime
addMinutes(n) Add minutes OffsetDateTime
addSeconds(n) Add seconds OffsetDateTime
addMilliseconds(n) Add milliseconds OffsetDateTime
addMicroseconds(n) Add microseconds OffsetDateTime
addNanoseconds(n) Add nanoseconds OffsetDateTime
Method Description Return value
diffYears(other) Difference in years number
diffMonths(other) Difference in months number
diffDays(other) Difference in days number
diffHours(other) Difference in hours number
diffMinutes(other) Difference in minutes number
diffSeconds(other) Difference in seconds number
Method Description Return value
equal(other) Whether equal boolean
before(other) Whether earlier boolean
after(other) Whether later boolean
isZero() Whether the zero value boolean
Method Description Return value
isToday() Whether today boolean
isYesterday() Whether yesterday boolean
isTomorrow() Whether tomorrow boolean
isThisWeek() Whether this week boolean
isThisMonth() Whether this month boolean
isThisYear() Whether this year boolean
isBetween(start, end) Whether within the range boolean
isInRange(start, end) Whether within the range boolean
Method Description Return value
format(layout) Custom formatting string
toString() Convert to string string
toDateTimeString() Date/time format string
toDateString() Date format string
toTimeString() Time format string
toYearString() Year string
toMonthString() Month string
toDayString() Day string
toHourString() Hour string
toMinuteString() Minute string
toSecondString() Second string
Method Description Return value
unix() Unix timestamp in seconds number
unixMilli() Unix timestamp in milliseconds number
unixMicro() Unix timestamp in microseconds number
unixNano() Unix timestamp in nanoseconds number
Method Description Return value
utc() Convert to UTC OffsetDateTime
local() Convert to local time zone OffsetDateTime
in(location) Convert to specified time zone OffsetDateTime | (nil, err)
Method Description Return value
truncate(durationStr) Truncate to specified precision OffsetDateTime | (nil, err)
round(durationStr) Round to specified precision OffsetDateTime | (nil, err)
toTime() Convert to 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")
-- Get the current time
local now = OffsetDateTime.now()
Logger.warn(now:toString())
-- Parse time
local dt = OffsetDateTime.parse("2024-01-15T10:30:00.000Z")
Logger.warn("年份: " .. dt:year())
Logger.warn("月份: " .. dt:month())
-- Time arithmetic
local tomorrow = now:addDays(1)
local nextWeek = now:addDays(7)
Logger.warn("明天: " .. tomorrow:toDateString())
-- Compare times
if now:isToday() then
Logger.warn("今天!")
end
-- Time difference
local hours = nextWeek:diffHours(now)
Logger.warn("相差小时: " .. hours)
-- Formatting
Logger.warn(now:format("2006-01-02 15:04:05"))
Logger.warn(now:toDateTimeString())

A time type containing hours, minutes, and seconds, without a date or time zone.

local LocalTime = require("LocalTime")
Method Description Return value
new(hour, minute, second) Create a time LocalTime | (nil, err)
now() Get the current time LocalTime
parse(str) Parse “HH:mm:ss” LocalTime | (nil, err)
fromTime(time.Time) Create from time.Time LocalTime | (nil, err)
fromDuration(durationStr) Create from a duration LocalTime | (nil, err)
Method Description Return value
hour() Get hour number
minute() Get minute number
second() Get second number
toString() Convert to “HH:mm:ss” string
toDuration() Convert to duration string string
equal(other) Whether equal boolean
before(other) Whether earlier boolean
after(other) Whether later boolean
beforeOrEqual(other) Whether earlier or equal boolean
afterOrEqual(other) Whether later or equal boolean
isZero() Whether 00:00:00 boolean
diffSeconds(other) Difference in seconds number
diffMinutes(other) Difference in minutes number
diffHours(other) Difference in hours number
addSeconds(n) Add seconds LocalTime
addMinutes(n) Add minutes LocalTime
addHours(n) Add hours LocalTime
subSeconds(n) Subtract seconds LocalTime
subMinutes(n) Subtract minutes LocalTime
subHours(n) Subtract hours LocalTime
local LocalTime = require("LocalTime")
local Logger = require("Logger")
-- Create a time
local workStart = LocalTime.new(9, 0, 0) -- 09:00:00
local workEnd = LocalTime.new(17, 30, 0) -- 17:30:00
-- Get the current time
local now = LocalTime.now()
Logger.warn("当前时间: " .. now:toString())
-- Compare times
if now:isBetween(workStart, workEnd) then
Logger.warn("工作时间")
else
Logger.warn("非工作时间")
end
-- Time arithmetic
local breakTime = workStart:addHours(3):addMinutes(30) -- 12:30:00
Logger.warn("午休时间: " .. breakTime:toString())
-- Time difference
local workHours = workEnd:diffHours(workStart)
Logger.warn("工作时长: " .. workHours .. " 小时")

Logging module integrated with system logs.

local Logger = require("Logger")
Method Description Parameters
info(msg) Output an INFO log string
warn(msg) Output a WARN log string
error(msg) Output an ERROR log string
debug(msg) Output a DEBUG log string
infof(fmt, ...) Formatted INFO log string, …
warnf(fmt, ...) Formatted WARN log string, …
errorf(fmt, ...) Formatted ERROR log string, …
debugf(fmt, ...) Formatted DEBUG log string, …
local Logger = require("Logger")
Logger.info("系统启动")
Logger.warn("磁盘空间不足")
Logger.error("数据库连接失败")
Logger.debug("变量值: x=10")
-- Formatted output
local user = "admin"
local action = "login"
Logger.infof("用户 %s 执行操作: %s", user, action)
Logger.warnf("重试次数: %s", 3)

Note: Edge-EMS Builder defaults to WARN logging. Only WARN and ERROR logs are output.


JSON serialization, deserialization, and manipulation, based on bytedance/sonic.

local JSON = require("JSON")
Method Description Return value
encode(value) Serialize to JSON string | (nil, err)
decode(text) Deserialize table | (nil, err)
Method Description Return value
toJSONString(value) Serialize without returning an error string
toJSONStringIndent(value, prefix?, indent?) Serialize with formatting string
toMap(jsonStr) Convert to map table | (nil, err)
toStringMap(jsonStr) Convert to string map table | (nil, err)
toSlice(jsonStr) Convert to array table | (nil, err)
isValid(jsonStr) Validate JSON format boolean
pretty(jsonStr) Pretty-print JSON string
merge(json1, json2) Merge two JSON values string | (nil, err)
get(jsonStr, key) Get a value any | (nil, err)
set(jsonStr, key, value) Set a value string | (nil, err)
remove(jsonStr, key) Remove a key string | (nil, err)
clone(value) Deep copy any | (nil, err)
local JSON = require("JSON")
local Logger = require("Logger")
-- Basic serialization/deserialization
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
-- Formatted output
local pretty = JSON.pretty(jsonStr)
Logger.warn(pretty)
-- Validate JSON
if JSON.isValid(jsonStr) then
Logger.warn("有效的 JSON")
end
-- Manipulate 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":"北京"}
-- Merge JSON
local json1 = '{"a":1}'
local json2 = '{"b":2}'
local merged = JSON.merge(json1, json2)
Logger.warn(merged) -- {"a":1,"b":2}
-- Deep copy
local original = {data = {x = 10}}
local copied = JSON.clone(original)

Regular-expression module supporting matching, searching, replacement, and splitting.

local Regex = require("Regex")
Method Description Return value
match(text, pattern) Whether the pattern matches boolean
findAll(text, pattern, limit?) Find all matches, including capture groups {{full, g1, g2, …}, …} | (nil, err)
replace(text, pattern, repl) Replace, supporting group references such as $1 string | (nil, err)
split(text, pattern, limit?) Split by regular expression {string, …} | (nil, err)
isEmail(text) Whether an email address boolean
isPhone(text) Whether a mobile phone number in China boolean
isIP(text) Whether an IP address boolean
isURL(text) Whether a URL boolean
local Regex = require("Regex")
local Logger = require("Logger")
-- Match
if Regex.match("abc123", "\\d+") then
Logger.warn("包含数字")
end
-- Find all matches, including capture groups
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
-- Replace, supporting group references
local s = Regex.replace("abc-123-def", "(\\d+)", "[$1]")
Logger.warn(s) -- "abc-[123]-def"
-- Split
local parts = Regex.split("a,b,,c", ",", -1)
-- parts = {"a", "b", "", "c"}
for i, p in ipairs(parts) do
Logger.warn("部分 " .. i .. ": '" .. p .. "'")
end
-- Validate
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

String-processing utilities.

local String = require("String")
Method Description Return value
trim(s) Remove leading and trailing whitespace string
upper(s) Convert to uppercase string
lower(s) Convert to lowercase string
contains(s, sub) Whether it contains a substring boolean
startsWith(s, prefix) Whether it starts with the prefix boolean
endsWith(s, suffix) Whether it ends with the 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

Mathematical utilities.

local Math = require("Math")
Method Description Return value
round(n) Round to nearest integer number
floor(n) Round down number
ceil(n) Round up number
abs(n) Absolute value number
max(a, b) Maximum number
min(a, b) Minimum 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 utilities supporting traversal of arrays and key/value pairs.

local TableUtils = require("TableUtils")
Method Description Return value
keys(tbl) Get all keys {string, …}
values(tbl) Get all values {any, …}
map(tbl, fn) Map using fn(value, key) {any, …}
filter(tbl, fn) Filter using fn(value, key) {any, …}
reduce(tbl, fn, init) Reduce using fn(acc, value, key) any
sortBy(tblOfMaps, key) Stable sort by 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: array
local arr = {1, 2, 3}
local doubled = T.map(arr, function(v, i)
return v * 2
end)
-- doubled = {2, 4, 6}
-- map: key/value pairs
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}}

These functions are registered directly in global scope and do not require require.

Function Purpose
cp56Time2aToOffsetDateTime(hex[, byteOrder]) Decode IEC 60870-5 time and return OffsetDateTime
offsetDateTimeToCP56Time2a(time[, byteOrder]) Encode time as a hexadecimal payload

byteOrder supports AB / BA and defaults to standard AB when omitted. Explicit byte order supports four-register payloads; ambiguous zero-padding positions return an error. Check the device’s register layout.

Function Description Return value
jsonToMap(str) Convert JSON to map table | (nil, err)
jsonToList(str) Convert JSON to list table | (nil, err)
jsonToListMap(str) Convert JSON to list of maps table | (nil, err)
completeDateTime(str) Complete a date/time string string | (nil, err)
quoteJson(str) Escape JSON quotes string
simpleUUID() Generate a simple UUID string
convertString(str) Convert a string’s type any
isNull(any) Check whether a value is null bool
isNotNull(any) Check whether a value is not null bool

isNull treats nil, empty strings, case-insensitive “null”, and the sentinel __Null__ as null. Lua’s or 0 does not handle that sentinel.

local Logger = require("Logger")
-- Parse 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}
-- Complete time strings
local fullTime = completeDateTime("2024-01-15")
-- fullTime = "2024-01-15T00:00:00.000+08:00"
-- Generate a UUID
local id = simpleUUID()
Logger.warn(id) -- 32-character UUID string

Function Description Return value
getLatestDataValue(dataKey) Get the latest data value any
getAccountCache(key) Get account cache any
getEMSDataCache(key) Get EMS data cache any
getShareCache(key) Get shared cache any
getMqttCache(key) Get MQTT cache any
getTriggerCache(key) Get trigger cache any
getDeviceShareValue(deviceCode, dataKey) Get a device’s latest shared value by deviceCode and dataKey string | nil
getDeviceShareValues(deviceCodes, dataKey) Get each device’s latest value from a device list and dataKey table
getAllDeviceShareValues(dataKey) Get the latest value for dataKey from every device in the shared space table
local Logger = require("Logger")
-- Get the latest device data
local value = getLatestDataValue("device1.temperature")
Logger.warn("当前温度: " .. value)
-- Get account information
local account = getAccountCache("user123")
if account then
Logger.warn("用户名: " .. account.username)
end
-- Get shared data
local sharedData = getShareCache("shared_config")
-- Get the latest shared value from one device
local val = getDeviceShareValue("device1", "temperature")
if val ~= nil then
Logger.warn("设备 device1 温度: " .. val)
end
-- Get shared values for each device in a device list
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
-- Get shared values from all devices
local allShareValues = getAllDeviceShareValues("temperature")
if allShareValues then
for deviceCode, dataValue in pairs(allShareValues) do
Logger.warn("设备 " .. deviceCode .. " 温度: " .. dataValue)
end
end

Batch-query latest values by dataKey pattern

Section titled “Batch-query latest values by dataKey pattern”

These functions scan the local latest-value cache, filter dataKeys by prefix, suffix, or keyword, and return matching point information as a {dataKey: FrontDataDTO} table.

Return fields: each value is a FrontDataDTO object with these common fields:

Field Type Description
DataKey string Unique data key
DataValue string Latest value
DataType string Data type
DataName string Data name
DataUnit string Unit
CollectionTime OffsetDateTime Acquisition time

Note: nil means no matching cache entries. dataType must exactly match an enumeration: Collection / Customization / Aggregation / Share.

Function Description Return value
getLatestDataValuesBySuffix(dataType, suffix) Latest values of the specified type whose dataKey ends with suffix table | nil
getAllLatestDataValuesBySuffix(suffix) Latest values of all types whose dataKey ends with suffix table | nil
Function Description Return value
getLatestDataValuesByPrefix(dataType, prefix) Latest values of the specified type whose dataKey starts with prefix table | nil
getAllLatestDataValuesByPrefix(prefix) Latest values of all types whose dataKey starts with prefix table | nil
Function Description Return value
getLatestDataValuesByPrefixAndSuffix(dataType, prefix, suffix) Latest values of the specified type whose dataKey matches both prefix and suffix table | nil
getAllLatestDataValuesByPrefixAndSuffix(prefix, suffix) Latest values of all types whose dataKey matches both prefix and suffix table | nil
Function Description Return value
getLatestDataValuesByFuzzy(dataType, keyword) Latest values of the specified type whose dataKey contains keyword table | nil
getAllLatestDataValuesByFuzzy(keyword) Latest values of all types whose dataKey contains keyword table | nil
local Logger = require("Logger")
-- Query latest acquisition values whose keys end with "_power"
local powerValues = getLatestDataValuesBySuffix("Collection", "_power")
if powerValues then
for dataKey, dto in pairs(powerValues) do
Logger.warn(dataKey .. " = " .. dto.DataValue)
end
end
-- Query latest values ending with "_power" across all data types
local allPower = getAllLatestDataValuesBySuffix("_power")
-- Query all acquisition data starting with "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
-- Query data starting with "meter1." across all types
local allMeter = getAllLatestDataValuesByPrefix("meter1.")
-- Query acquisition data whose dataKey starts with "meter1." and ends with "_voltage"
local voltages = getLatestDataValuesByPrefixAndSuffix("Collection", "meter1.", "_voltage")
-- Query data matching both prefix and suffix across all types
local allVoltages = getAllLatestDataValuesByPrefixAndSuffix("meter1.", "_voltage")
-- Fuzzy search: latest aggregation values whose dataKey contains "temp"
local tempValues = getLatestDataValuesByFuzzy("Aggregation", "temp")
if tempValues then
for dataKey, dto in pairs(tempValues) do
Logger.warn("温度点位: " .. dataKey .. " = " .. dto.DataValue)
end
end
-- Fuzzy search: latest values whose dataKey contains "temp" across all types
local allTemp = getAllLatestDataValuesByFuzzy("temp")

Function Description Return value
getDeviceList(ignoreLocal) Get device list, excluding the local device when ignoreLocal=true table
getDeviceCodeList(ignoreLocal) Get deviceCode list, excluding the local device when ignoreLocal=true table
local Logger = require("Logger")
-- Get the complete device list
local allDevices = getDeviceList(false)
if allDevices then
for i, device in ipairs(allDevices) do
Logger.warn("设备: " .. device.deviceCode .. " - " .. device.deviceName)
end
end
-- Get devices excluding the local device
local otherDevices = getDeviceList(true)
if otherDevices then
for i, device in ipairs(otherDevices) do
Logger.warn("共享设备: " .. device.deviceCode)
end
end
-- Get all device codes, faster than retrieving full device information
local deviceCodes = getDeviceCodeList(false)
if deviceCodes then
for i, code in ipairs(deviceCodes) do
Logger.warn("设备编码: " .. code)
end
end
-- Get device codes excluding the local device
local otherDeviceCodes = getDeviceCodeList(true)

Function Description Return value
getHistoryData(dataType, dataKey, startTime?, endTime?, formatMap?) Get historical data table
getShareHistoryData(deviceCode, dataKey, startTime?, endTime?, formatMap?) Get shared historical data from the specified device table
getTimeData(dataKey, time?, interval?) Get data at a specified time table
getShareTimeData(deviceCode, dataKey, time?, interval?) Get shared data at a specified time table
deleteCustomizationData(dataKey, startTime?, endTime?) Delete custom data boolean

Parameters:

  • startTime/endTime/time accepts:
    • OffsetDateTime objects, recommended.
    • Time strings, such as “2024-01-15T10:00:00.000Z”.
    • Abbreviated strings, such as “2024-01-15”, completed automatically.
  • formatMap: optional table customizing field names in returned results.
    • dataKey: custom data-key field name; default “dataKey”.
    • dataValue: custom data-value field name; default “dataValue”.
    • collectionTime: custom acquisition-time field name; default “collectionTime”.

Customization return fields:

The time fields returned by getHistoryData / getTimeData for Customization depend on schedule type:

  • DailyChange: availableTime as a full ISO 8601 date/time, and expiredTime.
  • DailyRepeat: availableTime and expiredTime as HH:mm:ss strings.
local OffsetDateTime = require("OffsetDateTime")
local Logger = require("Logger")
-- Method 1: use OffsetDateTime objects, recommended
local now = OffsetDateTime.now()
local startTime = now:addDays(-7)
local endTime = now
local data = getHistoryData("Collection", "temperature", startTime, endTime)
-- Method 1 extension: customize returned field names with formatMap
local formatMap = {
dataKey = "key",
dataValue = "value",
collectionTime = "time"
}
local data = getHistoryData("Collection", "temperature", startTime, endTime, formatMap)
-- Method 2: use time strings
local data = getHistoryData("Collection", "temperature", "2024-01-01T00:00:00.000Z", "2024-01-31T23:59:59.000Z")
-- Method 3: use abbreviated strings, completed automatically
local data = getHistoryData("Collection", "temperature", "2024-01-01", "2024-01-31")
-- Query shared historical data
local sharedData = getShareHistoryData("space1", "pressure", startTime, endTime)
-- Query data at a specified time
local value = getTimeData("temperature", now, "5m")
-- Delete custom data
local deleted = deleteCustomizationData("data1", startTime, endTime)
Logger.warn("删除成功: " .. tostring(deleted))

Function Description Return value
buildCommonWriteMap(dataType, dataKey, dataValue, availableDate, expiredDate, changeMod) Build a generic write map table
buildGeneralWriteMap(dataType, dataKey, dataValue, changeMod) Build a simplified generic write map without time parameters table
buildCustomizationWriteMap(dataKey, dataValue, availableDate, expiredDate) Build a DailyChange time-scheduled write map with implicit dataType=Customization table
buildDailyRepeatWriteMap(dataKey, dataValue, availableTime, expiredTime) Build a DailyRepeat time-scheduled write map with implicit dataType=Customization and HH:mm:ss time strings table
updateDailyRepeatSchedule(dataKey, scheduleAvailableDate, scheduleExpiredDate) Update the overall effective range of a DailyRepeat configuration; either date may be nil, meaning unrestricted or permanently effective boolean
buildAlarmObservationMap(sourceCode, alarmKey, state, alarmType, alarmLevel, alarmContent[, detailKey]) Build an alarm-event observation; state is ACTIVE / NORMAL / UNKNOWN table
buildCommonAlarmMap(alarmType, alarmContent) Build a generic alarm map table
buildMqttAlarmMap(alarmType, alarmContent, mqttConnectionConfigId, topic, qos) Build an MQTT alarm map table
buildSlaveWriteMap(deviceCode, dataType, dataKey, dataValue, availableDate, expiredDate, changeMod) Build a slave-device write map table

Alarm observations use a stable sourceCode + alarmKey. Send NORMAL for normal conditions and UNKNOWN for missing values or offline devices. Event states differ from observation states; see Alarm lifecycle for the full workflow. Legacy alarm constructors still create independent records.

CommBridge performs inverse coefficient conversion for acquisition writes. The old buildCollectionWriteMap has been removed. Use generic write constructors without repeating conversion.

Parameters:

  • dataType: Collection (acquisition), Customization (custom/time-scheduled), Aggregation, Share, or Alarm.
  • availableDate / expiredDate: required only for Customization of DailyChange type; ISO 8601 strings or OffsetDateTime objects. Pass nil for other types.
  • availableTime / expiredTime: required only for Customization of DailyRepeat type, formatted as "HH:mm:ss", such as "08:00:00"; must not cross midnight.
  • changeMod: Boolean; true writes only when the value changes.
local OffsetDateTime = require("OffsetDateTime")
-- Write an acquisition point
local writeCollection = buildCommonWriteMap("Collection", "temperature", 25.5, nil, nil, false)
-- Write a custom point: DailyChange with full date/time intervals
local writeCustom = buildCommonWriteMap(
"Customization", "mode", "1",
"2024-01-15T07:00:00+08:00",
"2024-01-15T18:00:00+08:00",
false
)
-- Write a custom point: DailyChange using its dedicated shorthand
local writeCustom2 = buildCustomizationWriteMap(
"mode", "1",
"2024-01-15T07:00:00+08:00",
"2024-01-15T18:00:00+08:00"
)
-- Write a custom point: DailyRepeat daily intervals in HH:mm:ss format
local writeDailyRepeat = buildDailyRepeatWriteMap("charge_mode", "1", "08:00:00", "18:00:00")
-- Update the overall effective range of a DailyRepeat configuration
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"))
-- Make permanently effective by passing nil for both dates
local ok2 = updateDailyRepeatSchedule("charge_mode", nil, nil)
-- Set a start without an end; nil means never expires
local ok3 = updateDailyRepeatSchedule("charge_mode", "2026-01-01", nil)
-- Write an aggregation point: simplified form without time parameters
local writeAgg = buildGeneralWriteMap("Aggregation", "avg_temp", 22.5, false)
-- Build an alarm to write a local alarm record
local alarm = buildCommonAlarmMap("TEMP_HIGH", "温度超过80°C")
-- Build an MQTT alarm: bind an MQTT connection ID and report the alarm to the broker
local mqttAlarm = buildMqttAlarmMap("TEMP_HIGH", "温度超过80°C", 1, "alarm/upload", 1)
-- Write slave-device shared data
local slaveWrite = buildSlaveWriteMap("DeviceB", "Share", "shared_temp", 25.5, nil, nil, false)

Function Description Return value
toFixedLengthBinary(value, length) Convert to fixed-length binary string | (nil, err)
toDecimal(binaryStr) Convert binary to decimal number | (nil, err)
-- Convert decimal to binary
local binary = toFixedLengthBinary(10, 8)
Logger.warn(binary) -- "00001010"
-- Convert binary to decimal
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("设备监控脚本启动")
-- Get the latest device data
local temperature = getLatestDataValue("device1.temperature")
local humidity = getLatestDataValue("device1.humidity")
Logger.infof("当前温度: %.1f°C, 湿度: %.1f%%", temperature, humidity)
-- Evaluate temperature alarm
if temperature > 80 then
local alarm = buildCommonAlarmMap("TEMP_HIGH", "温度超过80°C")
Logger.error("温度告警: " .. JSON.toJSONString(alarm))
end
-- Query historical data
local now = OffsetDateTime.now()
local startTime = now:addHours(-24)
local history = getHistoryData(
"device1",
"temperature",
startTime:toString(),
now:toString()
)
Logger.infof("获取到 %d 条历史数据", #history)
-- Calculate the average
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")
-- Get configuration from cache
local configJson = getShareCache("device_config")
local config = JSON.decode(configJson)
-- Filter enabled devices
local enabledDevices = TableUtils.filter(config.devices, function(device, index)
return device.enabled == true
end)
-- Extract device names
local deviceNames = TableUtils.map(enabledDevices, function(device, index)
return device.name
end)
-- Clean data
local cleanedNames = TableUtils.map(deviceNames, function(name, index)
-- Trim whitespace and convert to uppercase
return String.upper(String.trim(name))
end)
-- Validate device ID format
for i, device in ipairs(enabledDevices) do
if not Regex.match(device.id, "^DEV\\d{6}$") then
Logger.warnf("设备编号格式错误: %s", device.id)
end
end
-- Output results
Logger.info("处理完成: " .. JSON.toJSONString(cleanedNames))

  1. Error handling: most functions return (result, error); check errors when using them.
  2. Time format: time strings use ISO 8601.
  3. Regular expressions: use Go regular-expression syntax, which differs from native Lua patterns.
  4. Table traversal: TableUtils map/filter/reduce traverse the array portion (1..n) first, then key/value pairs.
  5. Log level: system configuration determines Logger output levels.
  6. JSON performance: the runtime uses high-performance JSON processing suited to bulk serialization.
if isNotNull(${some_key}) then
return {}
end
return { buildCommonWriteMap("Collection", "target_key", ${some_key}, nil, nil, false) }