- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
导读
本文聚焦 ThingsBoard Integration(集成)框架中的下行数据转换器编码函数(Downlink Data Converter Encoder Function),讲解如何用 JavaScript 把规则引擎(Rule Engine)产生的下行消息msg及其metadata转换为外部 MQTT、HTTP、CoAP 等集成所要求的具体负载格式。读完本文,你将掌握 Encoder 函数的四参数签名、返回值 JSON 结构(contentType/data/metadata),并能照示例编写一个把设备属性更新推送到外部 MQTT Broker 的完整编码器。本文同时结合仓库源码 AbstractDownlinkDataConverter.java 说明平台底层如何解析编码器输出,帮助你在调试时做到心中有数。
一、Encoder 函数在下行链路中的角色
ThingsBoard 的数据转换器(Converter)分为两类:上行解码器(Decoder)负责把设备上报的原始负载解析为平台统一格式;下行编码器(Encoder)则处理相反方向——当规则引擎向外发送下行消息(例如属性更新、RPC 请求)时,Encoder 函数负责把规则引擎消息变换为对应 Integration 能发送的格式。
核心函数签名(完整定义见 encoder_fn.md):
function Encoder(msg, metadata, msgType, integrationMetadata): {msg: object, metadata: object, msgType: string}该 JavaScript 函数用于将传入的规则引擎消息及其元数据,转换为对应 Integration 使用的格式。它面向的是集成框架的下行链路,与处理设备上行的 Decoder 函数在方向与职责上正好相反。
二、四个输入参数逐一解析
| 参数 | 类型 | 说明 |
|---|---|---|
msg | {[key: string]: any} | 规则引擎消息的 JSON 负载,是下行消息的核心数据体 |
metadata | {[key: string]: string} | 键值对列表,携带规则引擎为消息附加的额外数据(如deviceName、deviceType等) |
msgType | string | 规则引擎消息类型,例如ATTRIBUTES_UPDATED、POST_TELEMETRY_REQUEST等预定义消息类型 |
integrationMetadata | {[key: string]: string} | 集成专属字段的键值映射,你可以在每个集成的详情页中为其额外配置元数据 |
其中msgType取值来自规则引擎的预定义消息类型集合。integrationMetadata是区别于metadata的独立维度:前者由规则引擎在下行消息上生成,后者则属于 Integration 自身的配置,同一集成下所有下行消息都能拿到这份固定附加信息。
三、返回值结构:编码后的下行负载
Encoder 函数应返回一个合法 JSON 文档,结构如下(完整字段说明见 json_output.md):
{ "contentType": "JSON", "data": "{\"tempFreq\":60,\"firmwareVersion\":\"1.2.3\"}", "metadata": { "topic": "temp-sensor/sensorA/upload" } }字段语义:
contentType(string):JSON、TEXT或BINARY(Base64 字符串),具体取值与你的 Integration 类型相关。例如 MQTT 集成发送原始字节,使用JSON或TEXT时平台按 UTF-8 编码字节,使用BINARY时平台按 Base64 解码。data(string):与内容类型对应的数据字符串。JSON类型通常为JSON.stringify之后的字符串,BINARY类型为 Base64 编码的原始字节串。metadata({[key: string]: string}):关于消息的附加键值对,例如 MQTT 集成所需的topic发布主题等。
底层是如何解析这三个字段的
平台侧对 Encoder 返回值的解析逻辑集中在 AbstractDownlinkDataConverter.java 的parseDownlinkData方法中,这决定了你的返回值必须遵守的硬性约束:
- 返回值必须是一个 JSON 对象,且
contentType与data字段缺一不可,否则抛出Downlink content type is not set!/Downlink data is not set!异常; contentType只接受JSON、TEXT、BINARY三种取值,其他值会抛出Unknown downlink content type异常;JSON与TEXT按 UTF-8 转字节,BINARY走 Base64 解码;metadata字段可选,但若存在必须为对象,且其值必须是标量(字符串/数字/布尔),嵌套对象会触发Invalid downlink metadata format!异常;- 每个键值会被放入
Map<String, String>,最终封装为DownlinkData。
此外,convertDownLink方法对 Encoder 的原始返回结果做了兼容处理:允许返回对象或对象数组——数组中的每个元素都会被单独解析为一条下行负载(见 AbstractDownlinkDataConverter.java)。这意味着一个 Encoder 函数可以同时产出多条消息。在集成开启 Debug 模式时,原始输入消息与编码器输出会以Downlink前缀持久化为调试事件,方便排错。
四、实战示例:把属性更新推送到外部 MQTT Broker
原文档给出了一个完整场景:温度与湿度上传频率属性通过平台 REST API 更新,你希望把这个更新推送到外部 MQTT Broker(TTN、Mosquitto、AWS IoT 等),同时把很久以前配置且本次请求中不存在的firmwareVersion属性一并带上,并且推送主题要包含设备名。
4.1 输入参数
msg(规则引擎消息负载),见 message.md:
{ "temperatureUploadFrequency": 60 }metadata(规则引擎附加元数据),见 metadata.md:
| Key | Value |
|---|---|
| deviceName | sensorA |
| deviceType | temp-sensor |
| ss_firmwareVersion | 1.3.2 |
msgType:ATTRIBUTES_UPDATED
integrationMetadata(集成专属元数据),见 integration_metadata.md:
| Key | Value |
|---|---|
| integrationName | Test integration |
可以看到,metadata中携带了设备名、设备类型以及一个ss_前缀的历史属性键(ss_firmwareVersion),这正是我们在编码函数里补充firmwareVersion的数据来源——它不在本次msg负载里,但可以从metadata中取回。
4.2 Encoder 函数完整实现
完整的 JavaScript 编码函数见 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.temperatureUploadFrequency取出本次更新值赋给新键tempFreq;从metadata['ss_firmwareVersion']取出历史属性补齐firmwareVersion——即“本次请求缺失的数据可以从元数据补全”。 - 动态构造发送参数:利用
metadata['deviceType']与metadata['deviceName']拼接 MQTT 发布主题temp-sensor/sensorA/upload,使主题天然包含设备名,实现按设备路由。
4.3 函数返回结果
{ "contentType": "JSON", "data": "{\"tempFreq\":60,\"firmwareVersion\":\"1.2.3\"}", "metadata": { "topic": "temp-sensor/sensorA/upload" } }五、contentType 三种取值与适配场景
| contentType | data内容 | 典型适配集成场景 |
|---|---|---|
JSON | JSON 字符串(一般经JSON.stringify生成) | MQTT、HTTP、CoAP 等以结构化数据为主的集成 |
TEXT | 纯文本字符串 | 文本协议、CSV 负载、某些 TCP/UDP 场景 |
BINARY | Base64 编码的字节串 | 二进制协议负载、非文本字节流 |
平台侧对三种类型的处理同样可溯源到源码:在 AbstractIntegration.java 中,上行方向会根据集成返回的contentType将数据解析为 JSON 节点或 Base64 文本节点;下行方向的字节还原则由parseDownlinkData按上文规则完成(JSON/TEXT走 UTF-8,BINARY走 Base64 解码,见 AbstractDownlinkDataConverter.java)。因此编写 Encoder 时务必让contentType与data的真实编码保持一致,否则集成在解码阶段会得到错误字节。
六、TBEL 版本的 Encoder 函数
除了 JavaScript 版本,ThingsBoard 还提供了 TBEL(ThingsBoard Expression Language)版本的 Encoder 函数,其文档位于 tbel/encoder_fn.md。TBEL 是 ThingsBoard 为数据转换场景提供的表达式语言,语法与 JavaScript 高度相似,但运行于平台自有的受限沙箱环境中。TBEL 版本在函数签名、四个参数语义、返回值结构上与 JavaScript 版完全一致,同样支持msg、metadata、msgType、integrationMetadata四个入参以及contentType/data/metadata三字段返回值,示例函数体(见 TBEL 编码器示例)与 JavaScript 版逐行等价。你可以根据转换器配置中选择的语言引擎来选用对应版本。
七、编写与调试建议
结合上述文档与源码,给出几条可直接落地的实践建议:
- 严格保证返回对象含
contentType和data:缺失任一字段即转换失败并产生异常,可用 Debug 模式下的 Downlink 调试事件定位。 data字段必须是字符串:JSON类型记得用JSON.stringify,BINARY类型记得先用 Base64 编码,不要直接把对象赋给data。- 善用
metadata补全上下文:msg中缺失但确需发送的历史属性(如示例中的firmwareVersion)、设备名、设备类型等信息,通常已在规则引擎消息的metadata中,按 key 直接读取即可。 metadata返回值只放标量键值:嵌套对象会触发平台解析异常;MQTT 集成所需的topic、HTTP 集成所需的自定义头信息等应作为扁平键值放置。- 一次转换可产多条消息:Encoder 返回对象数组即可一次下发多条独立负载,适合需要拆分或广播的场景。
integrationMetadata用于传递集成级配置:需要在所有下行消息中固定携带的信息(如集成名称、租户标识)应配置在集成详情中,与逐条消息的metadata分开管理。
八、相关资源
- 编码器函数主文档:encoder_fn.md
- 返回值 JSON 结构说明:json_output.md
- 实战示例(输入
msg/metadata/integrationMetadata与完整函数):examples/encoder/example1 - TBEL 版本编码器函数:tbel/encoder_fn.md
- 平台侧解析实现:AbstractDownlinkDataConverter.java
- 集成侧负载处理:AbstractIntegration.java
- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
相关推荐
ThingsBoard 上行数据转换器实战:用 JavaScript Decoder 函数解析 CSV 文本负载
ThingsBoard 上行数据转换器实战:用 JavaScript Decoder 函数解析 CSV 文本负载 在 ThingsBoard 的集成(Integ
物联网后端数据可视化消息队列EMQX Cassandra 数据桥接指南:将 IoT 消息经规则引擎写入 Apache Cassandra
EMQX Cassandra 数据桥接指南:将 IoT 消息经规则引擎写入 Apache Cassandra Apache Cassandra 是一款开源、分布
后端物联网消息队列通信self-llm 教程:DeepSeek-MoE-16B-Chat 基于 FastAPI 的 API 服务部署与调用实践
self llm 教程:DeepSeek MoE 16B Chat 基于 FastAPI 的 API 服务部署与调用实践 DeepSeek MoE 16B Ch
物联网后端数据可视化消息队列
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考