拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ThingsBoard TBEL 解码函数实战:decodeToJson + hexToBytes + parseBytesToInt 解析多设备 JSON 上行报文

ThingsBoard TBEL 解码函数实战:decodeToJson + hexToBytes + parseBytesToInt 解析多设备 JSON 上行报文
  • 物联网
  • 后端
  • 数据可视化
  • 消息队列

【免费下载链接】thingsboard

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

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

本篇指南围绕 ThingsBoard 数据转换器(Data Converter)中一个完整的TBEL 解码函数示例展开——它以 JSON 数组作为上行报文,将每个元素中的十六进制value字段还原为电量、温度等遥测数据,并借助 metadata 注入设备类型与型号,最终返回包含多个设备结果对象的数组。读完本文,你将掌握decodeToJson、hexToBytes、parseBytesToInt等 TBEL 内置函数的组合用法,以及解码函数返回值必须满足的格式契约,可直接照搬到真实集成(Integration)配置中。

一、示例场景:一份携带多条记录的 JSON 报文

示例所在的example1目录由三份文件组成,分别描述输入、解码函数与元数据:

  • 输入报文:payload.md
  • 解码函数:decoder_fn.md
  • 元数据:metadata.md

假设某类设备网关把多条设备记录打包在一个 JSON 数组里上报,每条记录包含设备序列号、事件时间戳和一个十六进制编码的原始数据值:

[ { "serialNumber": "SN-111", "timestamp": 1527863043000, "value": "018f0a91" }, { "serialNumber": "SN-333", "timestamp": 1527863041000, "value": "018f0a91" } ]

value字段的十六进制字符串按大端(Big-Endian)语义拆分:前 2 个字节01 8f表示电池电压,后 2 个字节0a 91表示温度,原始值除以 100 即为实际小数(0x018f = 399→3.99,0x0a91 = 2705→27.05)。这正是许多 NB-IoT / LoRaWAN 传感器上报数据时常见的“整型定标”做法。

同目录的 metadata.md 展示了与本次上行关联的集成元数据:

KeyValue
integrationNameTest integration
deviceTypethermostat
modelModel A

这些键值对来自集成配置或上行报文上下文,解码函数可以通过metadata.deviceType、metadata.model直接读取,实现“设备类型与型号由平台侧统一下发、报文只携带原始数据”的解耦设计。

二、解码函数逐行拆解

这是示例的核心解码函数,完整内容见 decoder_fn.md:

// decode payload to JSON var data = decodeToJson(payload); var result = []; for (int i = 0; i < data.length; i++) { var report = data[i]; var deviceName = report.serialNumber; var deviceType = metadata.deviceType; var raw = report.value; var decoded = hexToBytes(raw); // Result object with device attributes/telemetry data result.push({ deviceName: deviceName, deviceType: deviceType, attributes: {model: metadata.model}, telemetry: { ts: report.timestamp, values: { battery: parseBytesToInt(decoded, 0, 2) / 100.0, temperature: parseBytesToInt(decoded, 2, 2) / 100.0, rawData: JSON.stringify(report) } } }); } return result;

1.decodeToJson(payload):把字节数组载荷还原为 JSON

payload在 TBEL 解码函数中永远是字节数组(byte[]的等价类型),与上行报文的内容类型声明(JSON、TEXT 或 BINARY)无关。decodeToJson负责把字节数组按 UTF-8 解析并转换为 JSON 对象/数组,因此这里得到的就是上文那份含两条记录的数组。

在底层实现中,该函数由 TbUtils.java 的decodeToJson静态方法注册给 TBEL 解析器,同时支持字节数组与字符串两种入参(见register(ParserConfiguration)中parserConfig.addImport("decodeToJson", ...)的重载注册)。注意:如果 JSON 载荷本身是字符串格式(如 CSV 文本),则应改用decodeToString(payload),再配合JSON.parse或字符串处理函数。

2. 循环遍历 + 设备命名:从每条记录构造一台设备

TBEL 允许使用类似 Java 的for (int i = 0; i < data.length; i++)循环语法,这是它与纯 JavaScript 的典型区别之一。循环内:

  • deviceName = report.serialNumber:直接用序列号作为设备名。由于设备名在租户范围内唯一,ThingsBoard 会用该值查找已有设备;若不存在且集成开启了“允许创建设备/资产”,则会自动创建新设备。文档同时建议:若还需要面向界面的友好显示名,可补充deviceLabel字段。
  • deviceType = metadata.deviceType:从元数据取值thermostat,作为设备类型。

3.hexToBytes(raw):十六进制字符串 → 字节数组

value字段是字符串"018f0a91",无法直接做整数解析,必须先经hexToBytes转成[0x01, 0x8f, 0x0a, 0x91]这样的字节列表。该函数在 TbUtils.java 中对应hexToBytes(ExecutionContext, String),返回 TBEL 的字节列表类型(ExecutionArrayList<Byte>),同时源码还提供了hexToBytesArray用于需要原生字节数组的场景。TBEL 还配套了base64ToHex、hexToBase64、bytesToBase64等互转工具,方便处理 Base64 编码的二进制载荷。

4.parseBytesToInt(decoded, offset, length):按偏移截取定标整数

parseBytesToInt是 TBEL 最常用的二进制拆包函数,签名与行为可从 TbUtils.java 确认:

  • parseBytesToInt(data):从字节 0 开始,取到int允许的最大长度(BYTES_LEN_INT_MAX,即 4 字节);
  • parseBytesToInt(data, offset):指定起始偏移;
  • parseBytesToInt(data, offset, length):同时指定偏移与长度,默认大端序(bigEndian = true);
  • parseBytesToInt(data, offset, length, bigEndian):可显式指定大小端。

本例中:

battery: parseBytesToInt(decoded, 0, 2) / 100.0, // 取 01 8f → 399 → 3.99 temperature: parseBytesToInt(decoded, 2, 2) / 100.0, // 取 0a 91 → 2705 → 27.05

实现上通过ByteBuffer完成位拼接(TbUtils.java#L900-L910),并对偏移与长度做越界校验(validationNumberByLength)。对应的单元测试覆盖了不同偏移、长度与大小端组合,见 TbUtilsTest.java 中的parseBytesToInt_checkPrimitives与parseBytesToInt_checkLists。如果数据是无符号且可能超过 4 字节,可改用parseBytesToUnsignedInt或parseBytesToLong;浮点场景则使用parseBytesToFloat/parseBytesIntToFloat。

5. 组装结果对象:attributes 与 telemetry

每个结果对象包含:

  • deviceName/deviceType:定位或创建设备;
  • attributes:服务器端属性,这里写入model(取自metadata.model);
  • telemetry:时序数据对象,由ts(事件时间戳,Unix 毫秒)与values(键值对)组成;
  • rawData: JSON.stringify(report):把整条原始记录序列化后也存入遥测,方便后续规则引擎做数据审计或回放。

由于报文数组含两条记录,函数返回result数组,平台会为数组中的每个对象分别处理——这对应了解码函数文档中“输出可以是包含多台设备的对象数组”的要求。整个返回值契约的权威说明见解码函数总览 decoder_fn.md。

三、解码函数的返回值契约(必读)

无论业务多复杂,TBEL 解码函数最终必须返回符合以下约定的 JSON(详见 decoder_fn.md):

  • 必须包含deviceName+deviceType,或assetName+assetType。平台据此在租户范围内查找设备/资产,未找到且集成允许自动创建时新建实体;
  • 可选attributes对象:作为服务器端属性写入实体;
  • 可选telemetry对象/数组:实体的时序数据。若指定ts,需为Unix 毫秒时间戳,否则使用服务器时间;
  • 可选customerName/groupName:自动分配客户与实体分组(仅在本次创建实体时生效,实体已存在则忽略);
  • 可选deviceLabel/assetLabel:非唯一的友好显示名,可替代设备名展示在仪表盘。

同目录的参考输出文件 json_array_output.md、simple_json_output.md、label_json_output.md 与 simple_json_output_with_ts.md 分别展示了单设备、带 label/客户/分组、以及携带自定义时间戳的输出形态,写解码函数时可直接对照。

四、同主题示例横向对照

decoder_fn.md 末尾的示例表将常见解码场景整理为五类,本文示例属于其中“带多个十六进制值的 JSON”与“使用 metadata 字段”的组合,其余示例可作为变体参考:

场景内容类型技术要点
Simple JSON with dateJSONdecodeToJson+Date.parse(ts)解析字符串时间戳,见 simple-json/decoder_fn.md
Simple CSVTEXTdecodeToString处理文本,逐行解析后返回设备结果
Simple binary dataBINARY直接对payload字节列表用parseBytesToInt按字节偏移拆字段,见 simple-binary/decoder_fn.md
JSON with multiple hex encoded valuesJSON与本文同思路,遍历数组 +hexToBytes+parseBytesToInt,见 complex-json-hex/decoder_fn.md
Use metadata fieldsJSON用metadata决定设备类型、型号与客户,见 simple-metadata/decoder_fn.md

对比可以发现:BINARY 报文的解码函数直接对payload本身做偏移拆包,而 JSON/TEXT 报文需要先还原结构再对字符串字段做二次二进制解析——本例正是后一种组合的完整示范。

五、实战要点小结

  • 把 JSON 数组批量解码为多设备结果数组时,务必保证每个元素都携带deviceName与deviceType,否则该条记录无法被正确路由;
  • 十六进制定标数据(如018f0a91)统一走hexToBytes+parseBytesToInt(decoded, offset, len) / divisor三步:先转字节、再按偏移取整、最后还原小数;注意parseBytesToInt单次最多 4 字节,默认大端序;
  • metadata是集成侧注入的键值地图(可在集成详情中额外配置),适合下发deviceType、model等与业务报文无关的上下文信息,让解码函数更通用;
  • 时间戳请统一为毫秒级 Unix epoch,否则平台回退使用服务器时间,可能造成数据时序偏差;
  • 若需要把原始报文留存用于排障,JSON.stringify(report)写入rawData遥测是低成本且实用的做法。

如需进一步了解编解码对侧逻辑,可参考编码器示例 encoder/example1/encoder_fn.md,以及解码函数 v2 变体 decoder_fn_v2.md;TBEL 内置函数的完整实现均可在 TbUtils.java 中查阅,测试行为则可由 TbUtilsTest.java 验证。

  • 物联网
  • 后端
  • 数据可视化
  • 消息队列

【免费下载链接】thingsboard

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

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

相关推荐

上一篇:如何利用ToonCrafter轻松制作专业卡通动画:从静态图片到流畅视频的完整指南
下一篇:混合内容安全指南:如何在 HTTPS 页面上彻底清除 HTTP 资源(Front-End-Checklist 实战)

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

返回列表