跳到內容
返回官網

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) 陣列形式的 Lua 表(下標從 1 開始連續),元素為 buildCommonWriteMap(...) 等函式回傳的 map;空表 {} 視為「無寫入項」
觸發動作(混合寫入類觸發方案) 每個 dataKey 單獨繫結的動作 單個值(字串/數字/布林),作為該 dataKey 的寫入內容;不要回傳 buildCommonWriteMap 陣列
後處理動作 觸發動作執行完成後的收尾指令碼 與運算式類觸發動作相同:由寫入描述組成的陣列形式 Lua 表;可透過固定變數 ${trigger_result}(布林)、${trigger_write_result}(JSON 字串,需 jsonToMap 解析)判斷主流程執行結果
聚合點位運算式 聚合資料計算運算式 單個值(數字/字串等),作為該聚合點位的最新值
MQTT 釋出內容(publishContent) MQTT 釋出設定 Lua 表,將被序列化為 JSON 作為釋出載荷
MQTT 訂閱動作(actionContent) MQTT 訂閱設定 與運算式類觸發動作相同:由寫入描述組成的陣列形式 Lua 表
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) }