- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
导读
本文聚焦 ThingsBoard MQTT 网关(Gateway)配置中“表达式(Expression)”字段的完整用法,讲解如何通过 JSONPath 从 MQTT 消息体中提取设备名称、遥测数据,通过正则表达式从主题中解析设备名称与设备配置(Device Profile),以及字节转换器中切片(Slices)语法的边界规则。读完本文,你将能够为 ThingsBoard MQTT 网关正确编写可复用的数据提取表达式,并在网关配置界面中落地验证。本文以 mqtt-json-key-expression_fn.md 为骨架,并结合仓库源码佐证底层实现。
表达式字段概述:一条消息、三种提取手段
在 ThingsBoard MQTT 网关的配置中,表达式(Expression)字段用于从 MQTT 消息中提取数据。网关收到的每一条 MQTT 消息都由两个部分组成:消息体(message body)与到达主题(topic)。针对不同的数据来源,ThingsBoard 提供了不同格式的表达式:
- JSONPath 格式:用于从消息体中提取数据,适合 JSON 结构化的载荷;
- 正则表达式格式:用于从消息到达的主题中提取数据,适合把设备标识编码进主题层级的情况;
- 切片(Slices)格式:仅在**字节转换器(Bytes Converter)**的表达式字段中可用,用于按字节/字符位置截取数据。
从源码结构看,网关的这类转换能力在 MQTT 传输模块中由 AbstractGatewaySessionHandler.java 承载,它通过JsonConverter(位于 JsonConverter.java)将提取后的数据转换为 ThingsBoard 标准的遥测、属性上报消息;而在新版转换器(Converter)链路中,AbstractUplinkDataConverter.java 则负责把转换结果解析为带deviceName、telemetry、attributes等字段的上行数据。理解这些底层链路,有助于你判断表达式写错时数据会在哪个环节丢失。
JSONPath 表达式基础:定位 JSON 结构中的元素
JSONPath 表达式用于指定 JSON 结构中希望访问的元素——这个结构可以是对象、数组,或二者任意嵌套的组合。表达式依据特定条件从 JSON 数据中选取元素,其基本语法结构如下:
| 语法 | 名称/作用 | 示例 |
|---|---|---|
$ | JSON 文档的根元素 | $表示整个 JSON 文档 |
. | 子元素操作符,用于选取子元素 | $.store.book表示根下store对象的book字段 |
[] | 子元素操作符,用于选取子元素 | $['store']['book']与$.store.book等价,访问store对象中的book数组 |
其中.与[]两种子元素操作符可以混用或互换:$.store.book与$['store']['book']访问的是同一路径。实际编写时,[]写法还常用于键名含特殊字符(如空格、-、.)的场景,此时点号写法无法表达,必须用括号下标形式。
实战示例:从 JSON 消息体中提取设备名与遥测
假设某个传感器设备通过 MQTT 向网关发送如下消息:
{ "sensorModelInfo": { "sensorName": "AM-123", "sensorType": "myDeviceType" }, "data": { "temp": 12.2, "hum": 56, "status": "ok" } }场景一:提取设备名称
如果我们需要将sensorModelInfo中的sensorName作为设备名称,使用如下表达式:
${sensorModelInfo.sensorName}转换后的输出数据为:
AM-123这里的${...}是表达式占位符,内部即 JSONPath 路径;sensorModelInfo省略了根元素$前缀,等价于$.sensorModelInfo.sensorName。网关会把这个提取结果作为deviceName字段,用于设备映射与自动注册。
场景二:提取整段 data 对象
如果我们需要提取上述消息中的全部数据,可以使用:
${data}转换后的输出为整个data子对象:
{"temp": 12.2, "hum": 56, "status": "ok"}这一用法适合将整块 JSON 作为键值型遥测批量上报:data下的每个键(temp、hum、status)都会在后续转换中展开为独立的遥测键值。
场景三:提取单个温度字段
如果只需要提取“温度”这一个字段,使用:
${data.temp}转换后的输出为:
12.2注意输出保留了原始 JSON 数值类型(12.2为浮点数而非字符串),这在后续JsonConverter.convertToTelemetryProto等解析过程中(见 JsonConverter.java)会被正确映射为DOUBLE_V类型的时间序列值。
场景四:提取设备类型
与设备名称同理,将表达式写成:
${sensorModelInfo.sensorType}即可得到myDeviceType,用于在网关映射中指定设备配置文件(Device Profile)。在 AbstractUplinkDataConverter.java 的解析逻辑中,当输出 JSON 缺少deviceType字段时会回退为默认值default(源码第 49 行的DEFAULT_DEVICE_TYPE),因此显式提取sensorType能保证设备类型正确归位。
基于主题的正则表达式:从 Topic 解析设备身份
当设备名称或设备配置文件信息没有出现在消息体,而是被编码在 MQTT 主题中时,可以使用正则表达式(Regular Expression,简称 regex/regexp)从主题中解析。正则表达式是由一组字符构成、用于字符串匹配与操作的搜索模式,在网关表达式中它会被编译并应用到消息主题字符串上。
主题正则表达式示例
| Topic | 正则表达式 | 输出数据 | 描述 |
|---|---|---|---|
/devices/AM123/mytype/data | /devices/([^/]+)/mytype/data | AM123 | 从主题中获取设备名称 |
/devices/AM123/mytype/data | /devices/[A-Z0-9]+/([^/]+)/data | mytype | 从主题中获取设备配置文件 |
第一条正则中,([^/]+)是一个捕获组,匹配任意非/字符的连续串,对应主题第三段AM123;捕获组提取的内容即设备名称。第二条正则用[A-Z0-9]+先消费掉设备编号段,再用([^/]+)捕获随后的mytype,作为设备配置文件名称。
编写此类表达式时需要注意:
- 主题中的
/分隔符需原样保留,因为正则对主题做整串匹配; - 需要提取哪一段,就把哪一段包进捕获组
(...),否则匹配成功但拿不到输出; - 使用
[^/]+这类否定字符类可以避免捕获组跨段贪婪匹配; - 正则默认是贪婪匹配,涉及相邻同类字符段时可用
+与字符类精确界定边界(如第二条示例中先限定[A-Z0-9]+再捕获)。
字节转换器中的切片语法(边界约束)
需要特别强调的是:切片只能用于字节转换器(Bytes Converter)的表达式字段,JSONPath 与正则表达式不适用于字节载荷,反之亦然。切片用于指定如何对一段序列进行切分,确定起始点与结束点,其两个组成要素如下:
start(起始索引):切片包含该索引处的元素;省略时从序列开头开始切片。索引从 0 开始计数,因此序列的第一个元素位于索引 0;stop(结束索引):切片不包含该索引处的元素,即切片会结束在该索引的前一个位置;省略时切片一直延伸到序列末尾。
字节解析示例
| 消息体 | 切片 | 输出数据 | 描述 |
|---|---|---|---|
AM123,mytype,12.2,45 | [:5] | AM123 | 提取设备名称 |
AM123,mytype,12.2,45 | [:] | AM123,mytype,12.2,45 | 提取全部数据 |
AM123,mytype,12.2,45 | [18:] | 45 | 提取湿度值 |
AM123,mytype,12.2,45 | [13:17] | 12.2 | 提取温度值 |
以AM123,mytype,12.2,45为例(含 4 个英文逗号,共 21 个字符,索引 0~20):[:5]取索引 0~4 即AM123;[13:17]从索引 13 开始、在索引 17 前结束,恰好截出12.2;[18:]从索引 18 到末尾,得到45。切片边界遵循“含头不含尾”的 Python 式语义,规划字段宽度时要逐字符核对偏移量。
表达式在实际转换链路中的作用
在 ThingsBoard MQTT 网关中,表达式提取出的值会进入设备会话处理与数据转换链路。以 AbstractGatewaySessionHandler.java 为例,网关收到子设备消息后按deviceName维护会话(devices映射),并调用JsonConverter把解析后的 JSON 转换为PostTelemetryMsg/PostAttributeMsgprotobuf 消息,最终交给传输服务上报平台。因此:
- 表达式提取出的设备名直接决定了网关把消息归到哪个子设备会话(
processOnConnect中按deviceName、deviceType建立会话); - 表达式提取出的数据字段决定上报的遥测键值与数值类型;
- 表达式写错或路径不存在时,提取结果为空,可能导致设备名缺省或遥测缺失,应从网关调试日志与设备会话状态入手排查。
小结
ThingsBoard MQTT 网关的表达式体系可按“数据位置”快速选型:
- JSON 消息体→ JSONPath(
${sensorModelInfo.sensorName}、${data}、${data.temp}),支持$、.、[]三种基本语法; - MQTT 主题→ 正则表达式(
/devices/([^/]+)/mytype/data),用捕获组输出设备名或设备配置; - 字节载荷→ 切片(
[:5]、[13:17]),仅限字节转换器使用,遵循含头不含尾的索引语义。
配套的关联帮助文档还包括 mqtt-json-expression_fn.md 与 mqtt-expression_fn.md,二者对该主题的 JSONPath、主题正则与字节切片示例做了并列呈现,可作为交叉参考。掌握了这三种表达式格式的选择边界与书写规则,你就能为任何结构化 MQTT 报文快速写出正确的网关映射配置。
- 物联网
- 后端
- 数据可视化
- 消息队列
【免费下载链接】thingsboard
All-in-one IoT Platform - Device management, data collection, processing and visualization.
相关推荐
ThingsBoard MQTT 网关集成中的表达式解析指南:JSONPath 与 Topic 正则表达式的实战用法
ThingsBoard MQTT 网关集成中的表达式解析指南:JSONPath 与 Topic 正则表达式的实战用法 导读 本指南以 ThingsBoard M
物联网后端数据可视化消息队列ThingsBoard MQTT 网关 Topic Filter 实战指南:通配符、共享订阅与设备名称提取
ThingsBoard MQTT 网关 Topic Filter 实战指南:通配符、共享订阅与设备名称提取 本篇技术指南围绕 ThingsBoard MQTT
物联网后端数据可视化消息队列ThingsBoard MQTT 网关 Bytes 转换器表达式:Slice 切片语法完整指南
ThingsBoard MQTT 网关 Bytes 转换器表达式:Slice 切片语法完整指南 本文档讲解 ThingsBoard 中 MQTT 网关转换器(C
物联网后端数据可视化消息队列
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考