跳转到内容
返回官网

Lua 脚本完整参考

本页是 Edge-EMS Builder 表达式引擎(聚合表达式、触发条件/动作、后处理动作、MQTT 发布/订阅内容)所用脚本能力的完整参考手册。脚本语法为 Lua 5.x,由内置的 Lua 运行时解析执行。快速入门请先阅读 表达式引擎,本页补充完整的内置模块、全局函数签名与返回值约定。

⚠️ 如果你接触过 Edge-EMS Builder 早期 Java 版本(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]} 返回上一秒的值
${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 发布配置 Lua 表,将被序列化为 JSON 作为发布载荷
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 秒时间戳 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]) 将时间编码为十六进制载荷

byteOrder 支持 AB / BA;未指定时采用标准 AB。显式指定时支持四寄存器载荷,补零位置有歧义时返回错误,应按设备寄存器布局核对。

函数 说明 返回值
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: 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) 二进制转十进制 number | (nil, err)
-- 十进制转二进制
local binary = toFixedLengthBinary(10, 8)
Logger.warn(binary) -- "00001010"
-- 二进制转十进制
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. 正则表达式: 使用 Go 的正则语法,与 Lua 原生 pattern 不同
  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) }