- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
本指南围绕 ThingsBoard 集成(Integration)体系中 TBEL 下行数据转换器(Encoder)展开,以仓库内encoder/example1示例为线索,完整讲解 Encoder 函数Encoder(msg, metadata, msgType, integrationMetadata)的四个入参、返回值契约与典型应用场景。读完本文,你将掌握如何编写一个把规则引擎消息(如设备属性更新)编码为外部系统可消费的下行负载,并学会结合 ThingsBoard TBEL 脚本引擎的实现机制定位问题。
一、Encoder 在 TBEL 数据转换体系中的角色
ThingsBoard 的 TBEL(ThingsBoard Expression Language)是一套基于 Java 实现的脚本表达式语言,被广泛用于规则引擎节点与数据转换器(Converter)中。在集成(Integration)场景下,数据转换分为两条链路:
- Decoder(上行解码):将设备上报的原始负载(MQTT 消息、HTTP 请求体、二进制数据等)解码为规则引擎可处理的 JSON 消息;
- Encoder(下行编码):将规则引擎下发的消息编码为外部系统(MQTT Broker、HTTP 端点等)可以消费的负载,并携带发送所需的元数据(如 topic)。
example1示例演示的正是 Encoder 的典型场景:当温度传感器的上传频率(temperatureUploadFrequency)属性通过平台 REST API 被更新时,需要把这次属性变更连同历史存储的固件版本属性一起推送给外部 MQTT Broker,且推送 topic 中要包含设备名。该示例的完整上下文可在仓库中查看:Encoder 函数定义文档 与配套示例目录 encoder/example1。
二、Encoder 函数签名与四个入参
顶层规范文档 encoder_fn.md 定义了 Encoder 函数的完整签名:
function Encoder(msg, metadata, msgType, integrationMetadata): {msg: object, metadata: object, msgType: string}该函数将规则引擎消息及其元数据转换为对应 Integration 所使用的格式。四个入参含义如下:
| 参数 | 类型 | 说明 |
|---|---|---|
msg | {[key: string]: any} | 规则引擎消息的 JSON 负载 |
metadata | {[key: string]: string} | 由规则引擎产生的、关于消息的键值对附加信息 |
msgType | string | 规则引擎消息类型,例如ATTRIBUTES_UPDATED、POST_TELEMETRY_REQUEST等预定义消息类型 |
integrationMetadata | {[key: string]: string} | 在集成详情中配置的、与该 Integration 相关的附加键值对 |
其中msgType对应 ThingsBoard 规则引擎的预定义消息类型(如属性更新、遥测上报、RPC 请求等),它在很大程度上决定了 Encoder 的编码逻辑分支。integrationMetadata与metadata的区别在于:前者来自集成(Integration)的全局配置,后者来自产生该消息的规则引擎链路。
三、Encoder 返回值契约
Encoder 必须返回一个合法 JSON 文档,结构如下:
{ "contentType": "JSON", "data": "{\"tempFreq\":60,\"firmwareVersion\":\"1.2.3\"}", "metadata": { "topic": "temp-sensor/sensorA/upload" } }各字段的语义(依据 json_output.md):
contentType(string):JSON、TEXT或BINARY(Base64 字符串),具体取决于你的 Integration 类型;data(string):按照内容类型组织的负载数据字符串;metadata({[key: string]: string}):关于该消息的附加键值对,例如 MQTT 集成要使用的 topic 等。
注意data必须是字符串而非对象——即使contentType是JSON,也需要先通过JSON.stringify()序列化为字符串,这一点与 Decoder 侧的返回结构不同。
四、example1 示例逐步拆解
4.1 输入消息(msg)
示例的输入消息定义在 message.md 中,即一次通过 REST API 触发的属性更新负载:
{ "temperatureUploadFrequency": 60 }{:copy-code}是 ThingsBoard 帮助弹窗使用的标记,表示该代码块可在 UI 中一键复制。
4.2 规则引擎元数据(metadata)
来自规则引擎的附加信息定义在 metadata.md:
| Key | Value |
|---|---|
| deviceName | sensorA |
| deviceType | temp-sensor |
| ss_firmwareVersion | 1.3.2 |
可以看到metadata中除了设备名与设备类型外,还包含了ss_firmwareVersion——这正是示例场景中"很久以前配置、本次请求中并未携带"的固件版本属性,Encoder 需要从metadata中把它取出来一并下发。
4.3 集成元数据(integrationMetadata)
集成级别的附加元数据定义在 integration_metadata.md:
| Key | Value |
|---|---|
| integrationName | Test integration |
该字段来自集成详情的配置,可在每个集成上单独配置。
4.4 消息类型(msgType)
本示例的msgType为ATTRIBUTES_UPDATED,对应"属性被更新"这一规则引擎预定义消息类型。这意味着该 Encoder 通常挂在"属性更新"类的规则引擎节点之后,每当设备属性发生变化即触发下行推送。
4.5 编码函数逐行解读
完整的示例函数定义在 encoder_fn.md:
// Encode downlink data from incoming Rule Engine message // msg - JSON message payload downlink message json // msgType - type of message, for ex. 'ATTRIBUTES_UPDATED', 'POST_TELEMETRY_REQUEST', etc. // metadata - list of key-value pairs with additional data about the message // integrationMetadata - list of key-value pairs with additional data defined in Integration executing this converter /** Encoder **/ var data = {}; // Process data from incoming message and metadata data.tempFreq = msg.temperatureUploadFrequency; data.firmwareVersion = metadata['ss_firmwareVersion']; // Result object with encoded downlink payload var result = { // downlink data content type: JSON, TEXT or BINARY (base64 format) contentType: "JSON", // downlink data data: JSON.stringify(data), // Optional metadata object presented in key/value format metadata: {topic: metadata['deviceType'] + '/' + metadata['deviceName'] + '/upload'} }; return result;关键编码逻辑:
- 从 msg 中取值:
data.tempFreq = msg.temperatureUploadFrequency;——把入站消息中的temperatureUploadFrequency: 60重命名为目标格式中的tempFreq。这也展示了 Encoder 的一个重要作用:字段映射与重命名,设备侧与平台侧、平台侧与外部系统之间的字段名往往不一致。 - 从 metadata 中取值:
data.firmwareVersion = metadata['ss_firmwareVersion'];——通过metadata['key']的方式访问元数据,取回本次请求中不存在的固件版本。 - 构造返回对象:
contentType: "JSON"声明下行负载为 JSON 格式;data: JSON.stringify(data)将组装好的对象序列化为字符串;metadata中通过字符串拼接动态构造 MQTT topic:metadata['deviceType'] + '/' + metadata['deviceName'] + '/upload',代入示例数据即temp-sensor/sensorA/upload。
4.6 编码结果推演
综合 4.1~4.5 的输入,在 TBEL 引擎中执行后,Encoder 返回的下行消息为:
{ "contentType": "JSON", "data": "{\"tempFreq\":60,\"firmwareVersion\":\"1.3.2\"}", "metadata": { "topic": "temp-sensor/sensorA/upload" } }之后 MQTT 类集成会据此把data字符串发布到temp-sensor/sensorA/upload这个 topic,从而完成"平台属性更新 → 外部 MQTT Broker"的链路。
需要说明:仓库示例中的 json_output.md 给出的输出示例里firmwareVersion写作"1.2.3",而本示例metadata表格中的值为1.3.2,这是帮助文档中两处示例版本号的细微出入;实际运行时编码结果取决于真实传入的metadata['ss_firmwareVersion']值。
五、源码级原理:TBEL 引擎如何执行 Encoder
TBEL 脚本并非在浏览器或外部 JS 运行时中执行,而是由 ThingsBoard 服务端内置的 Java 实现的 TBEL 引擎负责解析与求值。从仓库源码结构看,核心实现集中在:
- common/script/script-api/src/main/java/org/thingsboard/script/api/tbel
该目录下的关键类包括:
TbelInvokeService与DefaultTbelInvokeService:脚本调用的统一入口与默认实现,负责接收脚本内容、上下文参数并返回执行结果;TbelScript:TBEL 脚本的封装类型;TbelScriptExecutionTask:脚本执行任务,承载一次具体的执行请求;TbUtils、TbJson、TbDate等工具类:为 TBEL 脚本提供decodeToJson、时间与 JSON 处理等内置函数支持。
因此,当你编写 Encoder 函数时,本质上是向该引擎提交一段符合其语法的表达式代码,引擎会按函数签名注入msg、metadata、msgType、integrationMetadata四个变量,并在函数返回后校验返回值是否符合本文第三节描述的{contentType, data, metadata}契约。这也解释了为什么 Encoder 代码中可以直接使用JSON.stringify()等能力——它们由引擎的内置对象与方法提供。
六、实战要点与常见误区
基于示例与源码结构,编写 Encoder 时有几个要点值得注意:
data必须是字符串:返回对象中的data字段需要JSON.stringify()序列化,即使内容是 JSON 结构。常见的报错场景是直接返回对象而忘记序列化。- 区分三类元数据来源:
msg取消息负载、metadata取规则引擎附加信息、integrationMetadata取集成级配置,三者的生命周期与配置位置不同,不要混用。 - topic 动态构造:外部 MQTT 场景下,通常需要在返回的
metadata.topic中动态拼入设备名/类型,示例中的metadata['deviceType'] + '/' + metadata['deviceName'] + '/upload'即标准写法。 msgType分支处理:同一个 Encoder 可能被多种消息类型触发(如ATTRIBUTES_UPDATED与POST_TELEMETRY_REQUEST),建议按msgType编写分支逻辑,避免把遥测上报误编码为属性更新负载。contentType与集成类型匹配:JSON、TEXT、BINARY(Base64)三种内容类型需要与所配置的 Integration 类型兼容,例如面向 MQTT 集成通常使用JSON或TEXT。
七、进一步阅读
本文所有内容均可在当前仓库中直接查阅与验证:
- Encoder 函数顶层规范:ui-ngx/src/assets/help/en_US/converter/tbel/encoder_fn.md
- 示例输入消息:message.md
- 示例编码函数:encoder_fn.md
- 示例元数据与集成元数据:metadata.md、integration_metadata.md
- 返回结构字段说明:json_output.md
- TBEL 引擎源码:common/script/script-api/src/main/java/org/thingsboard/script/api/tbel
如需对照理解上行方向,可继续阅读 decoder 示例目录 与 decoder_fn.md,从而构建对 TBEL 数据转换体系的完整认知。
- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
相关推荐
ThingsBoard 集成 Downlink 数据 Encoder 转换器实战:把规则引擎下行消息编码为外部 MQTT 负载
ThingsBoard 集成 Downlink 数据 Encoder 转换器实战:把规则引擎下行消息编码为外部 MQTT 负载 本文以 ThingsBoard
物联网后端数据可视化消息队列ThingsBoard 集成 TBEL Encoder 函数实战:从 Rule Engine 消息到下行链路编码
ThingsBoard 集成 TBEL Encoder 函数实战:从 Rule Engine 消息到下行链路编码 本文档基于 encoder_fn.md htt
物联网后端数据可视化消息队列ThingsBoard 下行数据编码器(Encoder)函数实战指南:将规则引擎消息转换为外部集成负载
ThingsBoard 下行数据编码器(Encoder)函数实战指南:将规则引擎消息转换为外部集成负载 导读 本文聚焦 ThingsBoard Integrat
物联网后端数据可视化消息队列
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考