- Jelina overview
- EMS Builder
- Core capabilities
Expression Engine
The expression engine is the core of Edge-EMS Builder’s computation capabilities. Aggregation point values, trigger conditions, and MQTT message construction are all results of scripts executed by this engine. Scripts use Lua syntax.
1. Variable reference rules
Section titled “1. Variable reference rules”Before executing a script, Edge-EMS Builder replaces placeholders in the form ${...} with actual data values, then executes the script body. The following placeholder forms can be combined:
| Syntax | Description | Example |
|---|---|---|
${dataKey} |
Current value of a point | ${PCS1_有功功率} |
${dataKey[-NTimeUnit]} |
Historical value N time units ago | ${PCS1_有功功率[-5s]} means the value 5 seconds ago |
${dataKey[#N]} |
Nth most recent historical sample | ${PCS1_有功功率[#3]} means the third most recent value |
${dataKey[raw]} |
Injects the value unchanged, without automatic type conversion. Use raw where values such as numeric 1000 and binary 1000 are difficult to distinguish; it must appear last and nowhere else |
${设备状态[raw]} |
${[deviceCode]dataKey} |
Latest value of a shared device (Share) point | ${[DeviceA]PCS1_有功功率} |
| Combined forms | The rules above can be freely combined | ${[DeviceA]PCS1_有功功率[-1s][#3]} |
Missing values: when the target point has no value, the engine injects the string
__Null__. Compare explicitly or useisNull/isNotNull. For numeric calculations, usetonumberfirst; do not rely onor 0to detect this string.
Supported time-offset units:
| Unit | Accepted abbreviations |
|---|---|
| Milliseconds | ms / millisecond |
| Seconds | s / sec / second / seconds |
| Minutes | m / min / minute / minutes |
| Hours | h / hour / hours |
| Days | d / day / days |
| Weeks | w / week / weeks |
| Months | M / month |
2. Script body: standard Lua syntax
Section titled “2. Script body: standard Lua syntax”After placeholder substitution, the remaining script body executes using standard Lua 5.1 syntax and returns its result with return. You can therefore use native Lua variables, conditions, loops, functions, and other features:
-- Calculate total apparent power (simplified example)local ua, ub, uc = tonumber(${Meter1_Ua}), tonumber(${Meter1_Ub}), tonumber(${Meter1_Uc})local ia, ib, ic = tonumber(${Meter1_Ia}), tonumber(${Meter1_Ib}), tonumber(${Meter1_Ic})if not (ua and ub and uc and ia and ib and ic) then return "__Null__" end
local s = ua * ia + ub * ib + uc * icreturn s3. Built-in functions and modules
Section titled “3. Built-in functions and modules”In addition to standard Lua syntax, including the native string/table/math libraries, Edge-EMS Builder supplies global functions and modules accessible through require. These cover common needs such as data reads, constructing writes, and string, time, and regular-expression processing, enabling complex logic without low-level code:
| Category | Description | Example |
|---|---|---|
| Data reads (global functions) | getLatestDataValue, getHistoryData, getDeviceShareValue, and function families for batch queries by prefix, suffix, or fuzzy match |
Dynamically scan points sharing a naming convention; see the dynamic device discovery example in Trigger schemes |
| Write construction (global functions) | buildCommonWriteMap, buildCustomizationWriteMap, buildDailyRepeatWriteMap, buildCommonAlarmMap, buildMqttAlarmMap, buildAlarmObservationMap, buildSlaveWriteMap |
Construct target data structures for unified execution by trigger/MQTT actions |
| Time conversion | cp56Time2aToOffsetDateTime, offsetDateTimeToCP56Time2a, with AB/BA support |
Integrate IEC time registers |
| Time modules | require("OffsetDateTime"), require("LocalTime") |
Get the current timestamp for rate limiting; compare time intervals |
| General utility modules | require("Logger"), require("JSON"), require("Regex"), require("String"), require("Math"), require("TableUtils") |
Logging, deep JSON operations, regular expressions, and string/number/table processing |
| JSON conversion (global functions) | jsonToMap, jsonToList, toJsonString |
Exchange structured data with external systems, often in MQTT messages |
| HTTP | require("http") |
Send HTTP requests directly from scripts to third-party APIs; manage request rates and timeouts yourself |
For complete function signatures and module methods, see the complete Lua script reference. For detailed variable reference rules, see Data variable parsing rules.
Aggregation point expressions must
returna single value (a number, string, etc.) as the point’s latest value. Do not return arrays of write descriptors such asbuildCommonWriteMaphere; those formats belong to trigger actions, MQTT actions, and similar contexts. See the return-value conventions in the complete Lua script reference.
4. Configuration example: remaining available capacity
Section titled “4. Configuration example: remaining available capacity”The following example calculates remaining available power, commonly used in load balancing:
-- Rated current × voltage = rated power limit (kW)local rated_kw = tonumber(${Grid_current} or 0) * tonumber(${Grid_voltage} or 0) * 0.001
-- Used power: measured total grid-side power, kWlocal used_kw = tonumber(${Grid_total_power} or 0)
-- Reserve a 10% safety marginlocal avail_kw = (rated_kw - used_kw) * 0.9
return avail_kwAfter configuring this script as the expression for aggregation point avail_kw, any trigger scheme or other aggregation point can reference the result through ${avail_kw} without duplicating the calculation logic. This is how logic reuse works.
5. Trial calculation
Section titled “5. Trial calculation”After adding or editing an aggregation point expression, use Trial calculation before saving to verify syntax and expected results, avoiding script errors discovered only after deployment.
Next steps
Section titled “Next steps”- Review complete built-in function signatures, modules, and more examples: Complete Lua script reference.
- Learn to turn expression results into actions through Trigger schemes.