脚本规则
概念说明
脚本规则提供了灵活的可编程能力,允许用户通过编写脚本代码来实现复杂的业务逻辑处理。支持 Groovy 和 JavaScript 两种脚本语言,可以在设备数据上报、平台下发命令、设备上下线等多种场景下触发执行,实现数据转换、过滤、聚合等高级功能。
一、创建脚本规则
- 登录物联网平台,选择【规则引擎】>【脚本规则】,进入脚本规则管理页面。
- 点击【创建脚本规则】,填写脚本名称、脚本编码等基础信息。
- 其中脚本编码支持自动生成,点击输入框右侧的【自动生成】按钮即可。
- 选择需要关联的产品,脚本将处理该产品下设备的相关数据。
- 创建成功后,可以在脚本规则列表中查看。

二、选择脚本类型
平台支持两种脚本语言类型:
概念说明
- Groovy 脚本: Groovy 是一种基于 JVM 的动态语言,语法简洁且功能强大。
- 适用场景:需要 Java 生态集成、复杂业务逻辑处理
- 性能特点:执行效率高,适合处理大量数据
- 语法特点:支持 Java 语法,学习成本低
- JavaScript 脚本: JavaScript 是广泛使用的脚本语言,易于上手。
- 适用场景:前端开发人员熟悉、轻量级数据处理
- 性能特点:解释执行,适合中小规模数据处理
- 语法特点:语法灵活,开发效率高

三、配置触发模式
脚本规则支持多种触发模式,根据不同的业务场景选择合适的触发时机:
概念说明
设备上报(
device_report): 当设备上报数据到平台时触发脚本执行,可用于数据预处理、格式判断等。平台下发(
server_command): 当平台向设备下发命令时触发脚本执行,可用于命令参数校验、转换等。设备上线(
device_online): 当设备连接到平台并上线时触发脚本执行,可用于初始化操作、状态同步等。设备下线(
device_offline): 当设备与平台断开连接时触发脚本执行,可用于清理资源、记录日志等。

四、编写脚本内容
- 在规则编辑页面,找到【脚本内容】编辑器。
- 编辑器提供代码高亮、语法检查等功能,提升开发体验。
- 根据所选脚本类型编写相应的处理逻辑。
- 脚本中可以通过全局变量
context与params访问设备数据、产品信息等上下文。 - 编写完成后点击【保存】。
1. 执行模型
脚本运行时,平台会向脚本注入两个全局变量:
context(推荐):脚本上下文对象,提供getData()、getDeviceName()等方法,可便捷读取设备上报数据与设备信息。params:执行变量映射(键值结构),可通过字段名直接访问,如params.deviceName、params.propertyCurrentValues。
平台支持两种等价的脚本写法,可任选其一:
写法对照
写法一:直接编写脚本主体(推荐,无需定义函数)
直接编写处理逻辑,使用 return 返回结果即可,平台会自动作为入口执行。
写法二:定义 main 入口函数
定义 main(params) 函数作为入口,参数 params 即为执行变量映射。该写法兼容旧版脚本。
两种写法的返回值语义一致,详见下方「返回值与数据回写」。
2. Groovy 脚本示例
写法一:直接编写脚本主体
// 处理设备上报数据
def deviceData = context.getData()
def temperature = deviceData.temperature
// 温度单位转换(摄氏度转华氏度)
if (temperature != null) {
deviceData.temperatureF = temperature * 9 / 5 + 32
}
// 返回处理后的数据
return deviceData写法二:定义 main 入口函数
def main(params) {
// params 为执行变量映射
def deviceName = params.deviceName
def temperature = params.propertyCurrentValues.temperature
return [
deviceName : deviceName,
temperature: temperature,
alert : temperature != null && temperature > 30
]
}
3. JavaScript 脚本示例
写法一:直接编写脚本主体
// 处理设备上报数据
var deviceData = context.getData();
var temperature = deviceData.temperature;
// 数据过滤:只保留温度在正常范围内的数据
if (temperature >= -50 && temperature <= 100) {
return deviceData;
}
// 异常数据返回 null:不回写加工结果,保留原始上报值
return null;写法二:定义 main 入口函数
function main(params) {
// params 为执行变量映射
var deviceName = params.deviceName;
var temperature = params.propertyCurrentValues.temperature;
return {
deviceName : deviceName,
temperature: temperature,
alert : temperature != null && temperature > 30
};
}
写法约定
context与params由平台注入,不要自行声明同名变量覆盖。- 采用写法一时请勿再额外定义
main函数,二者择一即可。 context的方法名在 Groovy 与 JavaScript 中完全一致,例如两端均写作context.getData()。
4. 返回值与数据回写
脚本的返回值决定是否将加工结果回写到规则引擎本次执行的评估上下文,以便在脚本中完成数据加工(如单位换算、字段衍生)后,供同一规则内的后续动作直接使用:
回写采用合并语义:以返回内容更新评估上下文中的「当前值」(propertyCurrentValues)与「最新值」(propertyLatestValues),仅覆盖同名字段、保留其余属性,因此脚本只返回部分字段时不会丢失其它属性。
| 返回值 | 回写行为 |
|---|---|
| 非空对象(Map) | 合并回写:返回内容中的同名字段覆盖原值、新增字段追加,其余原有属性保持不变 |
null / 空对象 | 不回写,上下文保持原始上报值 |
| 非对象(数字、字符串等) | 不回写,仅作为本次脚本的执行结果记录 |
// 基于完整数据加工后整体返回(推荐):保留全部属性并新增衍生字段
def data = context.getData()
data.temperatureF = data.temperature * 9 / 5 + 32
return data
// 仅返回需要更新的字段:温度被覆盖、其余属性原样保留,不会丢失
return [temperature: 26.5]回写作用域:仅限规则引擎上下文
- 回写只作用于规则引擎本次执行的评估上下文——即由本次上报数据构建、仅供条件判断与动作执行使用的内存快照;影响范围严格限定为同一规则内排在脚本之后执行的动作(转发、告警、设备指令等)。
- 回写不参与、也不改变其它现有模块的数据流转:设备数据的时序入库、设备影子同步、原始上报消息与回执,以及其它规则、转发链路,均按各自独立流程处理,完全不受脚本回写影响,不存在脚本回写污染既有数据流的风险。
- 返回
null仅表示不回写加工结果,并不会中断后续动作的执行。 - 未显式
return时,Groovy 取最后一个表达式的值,JavaScript 返回undefined,二者均视为无有效返回值、不回写。
五、设置优先级
- 在规则编辑页面,配置【优先级】字段。
- 当多个脚本规则应用于同一产品时,按优先级顺序执行。
- 数值越大优先级越高,建议合理规划避免冲突。
六、启用与测试
- 脚本规则配置完成后,通过列表页面的开关启用规则。
- 建议先在测试环境验证脚本逻辑是否正确。
- 可以通过日志查看脚本执行情况和错误信息。
- 确认无误后再在生产环境启用。

注意
- 脚本执行超时时间有限制,避免编写耗时过长的逻辑。
- 脚本中的错误可能导致数据处理失败,请充分测试后再上线。
- 不同触发模式下可访问的上下文变量可能不同(如设备上下线场景通常不含属性值),请参考下方对照表按需取用。
- 脚本修改后需要重新保存才能生效,建议做好版本管理。
七、参数与方法对照表
下表列出脚本编辑器中可直接使用的全局变量、方法及参数,Groovy 与 JavaScript 两种脚本写法完全通用。
1. context 方法对照表
context 为脚本上下文对象,通过方法读取设备数据与运行信息。Groovy 与 JavaScript 调用方式一致(如 context.getData())。
| 方法 | 返回类型 | 说明 |
|---|---|---|
context.getData() | 对象 | 设备上报数据(当前属性值),等价于 getPropertyCurrentValues() |
context.getProperty(identifier) | 任意 | 获取指定标识的当前属性值,如 context.getProperty("temperature") |
context.getDeviceId() | 字符串 | 设备 ID |
context.getDeviceName() | 字符串 | 设备名称 |
context.getProductKey() | 字符串 | 产品标识 |
context.getTenantId() | 字符串 | 租户编号 |
context.getDeviceInfo() | 对象 | 设备完整信息(部分场景可能为空) |
context.getReportTime() | 字符串 | 设备数据上报时间(yyyy-MM-dd HH:mm:ss) |
context.getSystemTime() | 字符串 | 平台系统时间(yyyy-MM-dd HH:mm:ss) |
context.getTriggerMode() | 字符串 | 触发模式(device_report / server_command / device_online / device_offline) |
context.getRuleCode() | 字符串 | 脚本规则编码 |
context.getRuleName() | 字符串 | 脚本规则名称 |
context.getPropertyCurrentValues() | 对象 | 本次上报的属性值(与 getData() 等价) |
context.getPropertyLastValues() | 对象 | 上一次上报的属性值,可用于变化对比 |
context.getPropertyLatestValues() | 对象 | 截至当前的最新属性快照 |
context.getEventData() | 对象 | 本次上报的全部事件数据(事件标识 → 事件参数) |
context.getEvent(identifier) | 对象 | 获取指定标识的事件参数 |
context.getVariables() | 对象 | 规则上下文中的全部扩展变量 |
context.getVariable(key) | 任意 | 获取指定的扩展变量 |
context.get(key) | 任意 | 通用访问:按键读取任意执行变量 |
context.toMap() | 对象 | 获取全部执行变量(等价于 params) |
2. params 变量对照表
params 为执行变量映射,可直接通过字段名访问(如 params.deviceName、params.propertyCurrentValues.temperature);在写法二中即为 main 函数的入参。
| 类别 | 变量 | 类型 | 说明 |
|---|---|---|---|
| 设备信息 | params.deviceId | 字符串 | 设备 ID |
| 设备信息 | params.deviceName | 字符串 | 设备名称 |
| 设备信息 | params.productKey | 字符串 | 产品标识 |
| 设备信息 | params.tenantId | 字符串 | 租户编号 |
| 设备信息 | params.deviceInfo | 对象 | 设备完整信息(部分场景可能为空) |
| 时间信息 | params.reportTime | 字符串 | 设备数据上报时间(yyyy-MM-dd HH:mm:ss) |
| 时间信息 | params.systemTime | 字符串 | 平台系统时间(yyyy-MM-dd HH:mm:ss) |
| 属性数据 | params.propertyCurrentValues | 对象 | 本次上报的属性值,如 params.propertyCurrentValues.temperature |
| 属性数据 | params.propertyLastValues | 对象 | 上一次上报的属性值 |
| 属性数据 | params.propertyLatestValues | 对象 | 截至当前的最新属性快照 |
| 事件数据 | params.eventData | 对象 | 本次上报的事件数据 |
| 扩展变量 | params.variables | 对象 | 规则上下文中的扩展变量 |
| 规则信息 | params.ruleId | 字符串 | 脚本规则 ID |
| 规则信息 | params.ruleCode | 字符串 | 脚本规则编码 |
| 规则信息 | params.ruleName | 字符串 | 脚本规则名称 |
| 触发信息 | params.triggerMode | 字符串 | 触发模式 |
context 与 params 的关系
context 是对 params 的方法化封装,二者数据同源:context.getData() 等价于 params.propertyCurrentValues,context.getDeviceName() 等价于 params.deviceName。推荐使用 context 获取数据(语义清晰),需要按动态键名取值时则使用 params。
