☰
ThingsBoard TBEL 下行数据编码器(Encoder)实战:将属性更新推送至外部 MQTT Broker
2026/10/3 12:02:27 网站建设 项目流程
  • 物联网
  • 后端
  • 数据可视化
  • 消息队列

【免费下载链接】thingsboard

All-in-one IoT Platform - Device management, data collection, processing and visualization.

项目地址:https://gitcode.com/GitHub_Trending/th/thingsboard
点击查看免费下载

本指南围绕 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}由规则引擎产生的、关于消息的键值对附加信息
msgTypestring规则引擎消息类型,例如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:

KeyValue
deviceNamesensorA
deviceTypetemp-sensor
ss_firmwareVersion1.3.2

可以看到metadata中除了设备名与设备类型外,还包含了ss_firmwareVersion——这正是示例场景中"很久以前配置、本次请求中并未携带"的固件版本属性,Encoder 需要从metadata中把它取出来一并下发。

4.3 集成元数据(integrationMetadata)

集成级别的附加元数据定义在 integration_metadata.md:

KeyValue
integrationNameTest 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;

关键编码逻辑:

  1. 从 msg 中取值:data.tempFreq = msg.temperatureUploadFrequency;——把入站消息中的temperatureUploadFrequency: 60重命名为目标格式中的tempFreq。这也展示了 Encoder 的一个重要作用:字段映射与重命名,设备侧与平台侧、平台侧与外部系统之间的字段名往往不一致。
  2. 从 metadata 中取值:data.firmwareVersion = metadata['ss_firmwareVersion'];——通过metadata['key']的方式访问元数据,取回本次请求中不存在的固件版本。
  3. 构造返回对象:
    • 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 时有几个要点值得注意:

  1. data必须是字符串:返回对象中的data字段需要JSON.stringify()序列化,即使内容是 JSON 结构。常见的报错场景是直接返回对象而忘记序列化。
  2. 区分三类元数据来源:msg取消息负载、metadata取规则引擎附加信息、integrationMetadata取集成级配置,三者的生命周期与配置位置不同,不要混用。
  3. topic 动态构造:外部 MQTT 场景下,通常需要在返回的metadata.topic中动态拼入设备名/类型,示例中的metadata['deviceType'] + '/' + metadata['deviceName'] + '/upload'即标准写法。
  4. msgType分支处理:同一个 Encoder 可能被多种消息类型触发(如ATTRIBUTES_UPDATED与POST_TELEMETRY_REQUEST),建议按msgType编写分支逻辑,避免把遥测上报误编码为属性更新负载。
  5. 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.

项目地址:https://gitcode.com/GitHub_Trending/th/thingsboard
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询