设备属性转发与过程数据
设备详情中的是否转发控制服务端/共享属性哪些字段进入 MQTT 数据消息;过程数据(也称“过程属性”,process_data)保存脚本计算中间状态。两者配合,可以保留完整计算数据,同时减少不必要的消息和服务器带宽占用。
本文依据 2.00.066 源码行为。使用环境需已部署相应前后端版本及数据库迁移。
选择数据存放位置
| 数据 | 推荐位置 | 转发行为 |
|---|---|---|
| 采集结果、需要曲线与联动的数据 | 遥测数据 telemetry_data | 按原有遥测处理流程 |
| 阈值、业务状态、平台侧参数 | 服务端属性 server_attrs | 默认不转发,仅发送勾选的顶层字段 |
| 设备配置回显、共享业务参数 | 共享属性 shared_attrs | 默认不转发,仅发送勾选的顶层字段 |
| 累计计算、上次读数、中间缓存 | 过程数据 process_data | 内置转发不发送 |
只在存在明确外部消费者时开启相应字段转发。频繁变化的大对象和计算缓存优先放过程数据。过程数据可持久化,不是自动过期的临时内存。
升级不会自动把已有 server_attrs/shared_attrs 搬到 process_data。改造旧计算脚本时,应先核对并初始化所需状态,再切换读取位置,避免把空过程数据误当成累计量的起点。
配置属性转发
- 进入运维管理 → 设备管理 → 详情。
- 打开服务端属性或共享属性页签。
- 在是否转发列勾选需要发送的字段。表头复选框可全选或取消本表字段。
- 提交保存设备配置。后续数据转发按保存后的规则筛选;仅修改规则不会立即发送消息。
设备和模板保存的是完整白名单 forward_fields,例如:
{
"server_attrs": ["threshold", "state"],
"shared_attrs": []
}此配置仅允许服务端属性的 threshold、state 进入 MQTT 消息,不发送共享属性。未配置、null、{} 或对应组为空数组时,该组均不转发。
- 只匹配顶层字段名,不展开嵌套对象;只发送指定且实际存在的字段。组内
update_time不会自动补发。 - 筛选不删除内存或数据库中的完整属性,也不影响客户端/MAC 属性及遥测数据原有处理。Modbus 使用自己的寄存器映射,不使用这份 MQTT 白名单。
- 实时、历史及 RPC 主动转发都会应用规则;没有有效数据组时不发布空消息。
- MQTT 属性消息可能只是完整属性的子集。消费端应按字段合并,不能用收到的子集覆盖整组属性。
- 此开关不替代Broker 与转发器的连接和主题配置,也不代表 LoRaWAN 无线下行。修改共享属性配置不等于设备已收到参数;需要下行时执行对应 RPC。
批量配置与模板
在设备列表勾选设备,进入批量修改参数 → 转发字段配置,分别为服务端属性和共享属性选择“开启转发的字段”“关闭转发的字段”。可选择已有字段或输入新字段;同一字段不能同时开启和关闭。留空表示不修改,各设备未选中的规则保持原样。
设备模板也保存 forward_fields。从设备生成模板会复制规则;应用或重置模板时,以模板规则覆盖设备原规则。旧模板没有规则时按 {} 处理,即默认不转发。过程数据不属于模板,不作为模板默认值复制或重置。自动新建的子设备继承父设备规则副本,已有子设备的规则不被覆盖。
配置时间
config_update_time 由服务端维护,配置、绑定、转发规则实际变化时更新;仅修改属性值、过程数据或遥测数据不更新。MQTT 实时/历史消息顶层也携带该字段,表示当前配置变更时间,不是历史数据采样时间。
查看与删除过程数据
- 在设备详情打开过程数据页签,查看字段值和更新时间。
- 进入页签或点击刷新过程数据时获取最新值;本页不通过 MQTT 实时订阅过程数据。
- 使用字段行的删除操作移除不再需要的键。页面支持查看、刷新和删除,不提供新增或编辑;写入通过物模型或 RPC 脚本完成。
删除立即更新缓存并缓冲保存,不需要再提交属性配置。按顶层键精确删除,键名中的点号不是路径。重复删除不存在的键不产生新更新;删空后保存 {}。删除本身不触发 MQTT、Modbus 或 Trigger 通知。仍在运行的脚本以后可能重新写入同名键。
物模型:保存计算状态并选择转发字段
在自定义物模型解析脚本中直接返回结果;device 是只读输入,给 device.process_data 直接赋值不会保存。以下是脚本函数体示例:
const count = Number(device.process_data?.count ?? 0) + 1;
return {
process_data: { count },
server_attrs: { state: "ready", debug_count: count },
forward_fields: {
server_attrs: { state: true, debug_count: false }
}
};这里 process_data.count 留作后续计算,state 可转发,debug_count 保存在服务端属性但不转发。
**过程数据合并规则:**按顶层键浅合并,嵌套对象整体替换;{} 不修改,字段值 null 保存为普通值,不表示删除。实时、历史和子设备解析结果均支持 process_data,子设备结果写入相应子设备。仅更新过程数据不触发 MQTT、Modbus、虚拟设备通知或 Trigger;同时返回的遥测数据和动作仍按原流程执行。Trigger 可以读取 device.process_data,写入使用物模型结果或 RPC 动作。
**脚本转发补丁规则:**解析结果的 forward_fields 是布尔补丁,与设备/模板保存的数组白名单不同。只支持 server_attrs、shared_attrs:true 去重添加,false 移除,省略的组或字段不变。字段名不能为空,补丁值必须是布尔值。空补丁或无变化补丁不产生配置写入。同次解析结果的转发立即使用新规则。
RPC:保存过程数据与控制本次通知
return [
{
type: "modifyForwardFields",
dnMsg: { server_attrs: { state: true, debug_count: false } }
},
{
type: "modifyAttrs",
forward: false,
dnMsg: {
process_data: { previous_value: 25 },
server_attrs: { state: "ready" }
}
}
];modifyForwardFields 是独立动作,按数组顺序生效,后续动作立即使用新规则。modifyAttrs.forward 缺省为 true;设为 false 时仍保存属性及过程数据,只跳过本动作的 MQTT 和 Modbus 通知,不会禁用后续显式转发动作。即使为 true,服务端/共享属性仍须通过字段白名单。
forwardTelemetry 不发送过程数据。自行构造的 customMqtt 消息由脚本作者决定内容,不受内置过程数据排除规则保护。保存或测试脚本不代表设备动作已经执行。
API 读取与删除
以下均为 POST,租户来自认证上下文;先查询真实设备 ID。配置保存接口不接受写入过程数据。
| 路径 | 请求体 | 结果/用途 |
|---|---|---|
/thinklink/device/find-process-data | {"id":"设备ID"} | {content, update_time};优先读取当前缓存,无记录时为 {content:{}, update_time:null} |
/thinklink/device/delete-process-data | {"id":"设备ID","fields":["scratch"]} | 删除顶层键,返回最新 {content, update_time} |
/thinklink/device/find-current-attrs | {"id":"设备ID"} | 获取完整 server/shared/client/mac 属性及遥测,不包含过程数据;用于 RPC 参数回填等 |
/thinklink/device/update-config | {"id":"设备ID","changes":{"forward_fields":{"server_attrs":["state"],"shared_attrs":[]}}} | 替换完整转发规则;先读取并保留不打算修改的组和字段 |
/thinklink/device/batch-update-partial | {"dataList":[{"id":"设备ID"}],"updateColumns":[],"forward_fields_patch":{"server_attrs":{"state":true}}} | 增量修改所选设备规则;不能同时全量替换 forward_fields;返回实际变化数 {count} |
保存与排查
过程数据立即更新内存,通过独立缓冲保存到数据库(5 秒周期,500 个待写设备触发提前刷新)。正常落盘后可跨重启恢复;强制终止或断电可能丢失未落盘的数据。缓存读取成功或删除响应成功不等于已经落盘。删除设备会清理对应过程数据。
| 现象 | 检查方法 |
|---|---|
| 属性有值但 MQTT 没有该字段 | 检查该组的“是否转发”勾选及配置保存结果;只改规则不会立即发消息 |
forward: true 仍没有属性消息 | 它不绕过白名单;确认字段被选中且存在 |
| 过程数据页面没有自动更新 | 点击刷新;页面按需读取,不订阅过程数据 MQTT |
给 device.process_data 赋值后没有保存 | 改为返回 process_data 或 modifyAttrs 动作 |
返回 null 后字段还在 | null 是普通值;删除使用页面操作或专用删除接口 |
| 套用模板后属性不再转发 | 检查模板白名单;旧模板无规则时覆盖为默认不转发 |