设备 MQTT 接入
设备 MQTT 接入
什么是 MQTT ?
MQTT 全称是 Message Queuing Telemetry Transport,它是一种基于消息队列的轻量级应用层通信协议,实现了消息发布和订阅。设备可以作为客户端的形式通过它来发布和接收消息,实现数据上报和实时控制。
MQTT 是一种简单的消息传递协议,设计用于具有低带宽的受限设备。因此,它是物联网设备接入的完美解决方案。
ThingsCloud 支持哪些设备?
ThingsCloud 云平台提供了标准的 MQTT 接入协议,支持 MQTT v3.1/v.5,任何支持 MQTT 协议的设备都可以通过相应的 MQTT 客户端代码接入云平台。
那么,设备要支持 MQTT,有哪些常见的方式呢?通常不外乎以下几种:
- 各种单片机或嵌入式系统,使用支持 MQTT 或 TCP 协议的 2G/3G/4G/5G 、 NBIoT 等无线通信模组,通过 AT 指令、串口透传、SDK 等方式快速接入云平台。
- 本身支持 OpenCPU 的通信模组,例如:ESP32、Air724UG 等,通过模组固件二次开发实现接入云平台。
- 无法直接连网的传感器、IO 控制器、PLC 等设备,通过支持 MQTT 的网关/DTU 接入云平台。
我们也会不断提供各种常见设备的接入示例。
设备 MQTT 接入点
了解了基本概念后,我们开始学习如何让设备通过 MQTT 接入 ThingsCloud 云平台,并和云平台进行各类消息通信。
提示
在此之前,我们在 快速上手 的章节中简单介绍了在控制台创建设备,并完成了一些基本的 MQTT 通信,如果您没有阅读,建议您大概了解一下。
ThingsCloud 公有云支持全球多个区域,并随着设备接入量不断扩张。每个接入的设备有专用的 MQTT 接入点,获得设备 MQTT 接入点的正确方式,就是在控制台进入设备详情的【连接】页面,复制该设备的 MQTT 接入点。
我们提供多种类型的 MQTT 接入点和认证方式,如下:
接入类型 | 用途 | 接入点示例 |
---|---|---|
MQTT | 普通认证方式,适合大多数普通设备或资源受限设备 | mqtt://<endpoint> :1883 |
MQTT over TLS | X.509 认证方式,适合对通信安全要求严格的设备 | mqtts://<endpoint> :1884 |
MQTT 身份认证
设备通过 MQTT 协议连接云平台时,需要完成基于 MQTT 的身份认证,云平台支持以下认证方式。
普通认证方式
对于普通认证方式,在 MQTT 连接时,使用基于 username/password 的认证方式,需要用到设备的普通证书,如下:
MQTT 连接参数 | 值 | 说明 |
---|---|---|
username | AccessToken | 设备创建后自动生成,每个设备唯一,量产设备可通过 API 自动获取 AccessToken ,实现一型一密。 |
password | ProjectKey | 项目创建后自动生成,不支持修改。 |
clientId | 空或任意 | 不对 clientId 做任何限制,可随意填写。 |
在 设备详情页 > 连接 中可以复制以上标识。
这里以 MQTT.fx 为例,连接参数填写大致如下图:
提示
请确保以上标识只用于设备固件开发,烧录到设备 ROM/Flash 中,避免泄露。
对于量产阶段的设备,无需手动复制每个设备的 AccessToken 进行单独烧录,可采用 一型一密 的方式,通过 API 自动获取 AccessToken,以及自动创建设备。
需要注意的是,ThingsCloud 对同一个设备身份信息只支持一个 MQTT 连接,也就是说,如果在两个或多个物理设备中,使用同样的 username/password 身份信息连接云平台,即便 clientId 使用不同的字符串,云平台仍然将这些连接视为同一个设备,这会导致后一个设备连接成功后会顶掉之前的设备连接。
X.509 TLS 认证方式
在一些对通信安全要求严格的物联网领域,比如智能门锁、电表、水表、燃气表等,您可以使用基于 X.509 TLS 的 MQTT 安全认证方式,我们目前只在 ThingsCloud 专有区和私有区中支持该认证方式。
更进一步的物联网安全措施,可以在设备端集成 SE 安全芯片,或使用内置 SE 安全芯片的通信模组,实现设备和云平台双向认证。ThingsCloud 对智能设备厂商的私有区服务提供 SE 解决方案。
MQTT 主题一览
ThingsCloud 作为物联网 PaaS 云平台,对设备 MQTT 接入提供了内置的访问协议规范,让设备和云平台的消息通信更加有章可循,大大简化了物联网项目的开发难度,缩短了产品的开发周期。
不同于普通的 MQTT 使用方式,我们提供了标准的内置主题,这足以实现绝大多数的物联网应用场景。
而对于另一些个性化的消息通信场景,我们也提供了灵活的自定义主题,您完全创建自己的主题,并配合包括云函数在内的规则引擎,实现任何消息通信需求。
发布主题
以下主题用于设备向云平台发布消息。
消息类型 | 主题 |
---|---|
设备上报属性值 | attributes |
设备获取当前属性值 | attributes/get/<id> |
设备上报事件 | event/report/<id> |
设备回复命令 | command/reply/<id> |
设备自定义数据上报 | data/<identifier> |
订阅主题
以下主题用于设备从云平台订阅消息。
消息类型 | 主题 |
---|---|
接收属性上报的响应 | attributes/response |
接收属性获取的响应 | attributes/get/response/+ |
接收下发的属性 | attributes/push |
接收事件上报的响应 | event/response/+ |
接收下发的命令 | command/send/+ |
接收自定义数据下发 | data/<identifier> /set |
提示
以上自定义数据相关主题中的 identifier
,是指自定义数据流的标识符。详细介绍请浏览 自定义数据流
您可能已经发现,所有的主题中并没有出现设备的标识,这也是 ThingsCloud 的不同之处,当设备连接云平台后,便通过 ThingsCloud 独有的虚拟映射方式,拥有独立的主题命名空间,所以每次发布消息或订阅消息时,主题名称非常简洁。
下面我们会逐个介绍每个发布主题和订阅主题的使用方法。
视频教程 🎦
- 【设备 MQTT 接入 ThingsCloud】如何连接云平台?🎦
- 【设备 MQTT 接入 ThingsCloud】如何上报属性到云平台?🎦
- 【设备 MQTT 接入 ThingsCloud】如何实时接收云平台下发的属性?🎦
- 【设备 MQTT 接入 ThingsCloud】如何从云平台获取当前属性?🎦
- 【设备 MQTT 接入 ThingsCloud】如何上报事件到云平台?🎦
- 【设备 MQTT 接入 ThingsCloud】如何实时接收云平台下发的命令?🎦
设备上报属性
当设备自身的属性发生变化时,通过向云平台上报属性,实现云平台设备属性的及时更新,以及应用系统的设备数据实时更新。
设备发布消息
设备上报属性使用以下主题:
attributes
消息内容必须是 JSON
格式,如果不是 JSON
格式的消息,设备会被云平台主动断开连接。
一个简单的属性上报消息如下:
{
"temperature": 28.5,
"light": 2000,
"switch": true
}
设备发布以上消息后,控制台的设备详情页会实时更新显示设备属性的最新值。
提示
ThingsCloud 控制台通过 MQTT Websockets 方式订阅设备属性的实时更新,您可以在不刷新页面的情况下实时查看设备属性值的变化。有时网络原因导致 Websockets 连接中断,您只需刷新页面即可恢复。
我们也将这种 Websockets 订阅方式开放给应用开发,如果您的应用基于 ThingsCloud 云平台,便可以实现页面实时更新。
如果设备按一定时间间隔上报属性,就实现了一个基本的数据采集上报功能。
云平台会自动保存这些属性的时序数据,如下图:
对于 number
类型的属性,云平台还提供了时序图表,方便浏览历史曲线。
当然,您也可以使用如下的 JSON
消息格式来上报属性数据:
{
"sensor_1": {
"temperature": 28.5,
"light": 2000,
"switch": true
},
"sensor_2": {
"temperature": 27.1,
"light": 1800,
"switch": false
}
}
但是对于这种将属性值放入嵌套结构中的消息,云平台并不会直接保存嵌套结构内的属性时序数据,而只保存 sensor_1
这样的结构体属性值,供设备和应用查询。
如果设备一定要按这样的嵌套格式上报属性,或者有些时候您无法改变设备的上报规则,有没有办法让云平台也生成属性时序数据呢?答案是肯定的,那就是利用云平台托管的规则引擎,自动将嵌套结构中的属性数据,复制到 JSON
消息的顶层结构中,这样就会自动被云平台记录时序数据。具体的做法请参考后边的章节。
设备接收消息
如果我们想知道属性上报是否被云平台成功接收,可以订阅如下主题:
attributes/response
请注意,订阅主题只需要在设备 MQTT 成功连接云平台后执行一次即可。当设备上报属性后,便会通过该主题收到来自云平台的响应消息,如果云平台接收成功,响应消息如下:
{
"result": 1,
"ts": 1609143039050
}
如果云平台未成功接收,响应消息中会包含错误原因,例如:
{
"result": 0,
"message": "Device message frequency too fast, please wait for a moment",
"errcode": 402
}
该错误表示属性上报间隔太短,所以云平台会自动忽略过于频繁的属性上报消息。
设备获取属性
对于连网设备,有些属性是在云端进行设置下发的。当设备重启后,需要立即从云平台获取属性当前值,实现设备初始化。
设备发送消息
当设备希望从云平台获取属性当前值时,发送消息到如下主题:
attributes/get/<id>
<id>
可以使用任意不超过 6 位的整数,例如:
attributes/get/1000
消息内容格式如下:
{
"keys": []
}
这表示获取所有属性,也可以指定个别属性,如下:
{
"keys": [
"temperature",
"humidity"
]
}
设备接收消息
请确保设备已经订阅了如下主题:
attributes/get/response/+
如果设备不支持 +
MQTT 通配符,也可以订阅如下主题:
attributes/get/response/<id>
这里的 <id>
要和前边发送消息中的 <id>
一致,否则无法接收响应消息。
当设备发送获取属性的消息后,便会通过以上订阅主题,收到如下的响应消息:
{
"result": 1,
"attributes": {
"temperature": 34.2,
"humidity": 67
}
}
设备接收云端下发属性
除了设备主动获取属性以外,我们也需要让设备可以实时接收云平台下发的属性更新。
设备接收消息
非常简单,确保设备已订阅如下主题:
attributes/push
当云平台下发属性给设备时,设备会通过以上订阅主题,立即收到 JSON
结构的消息,例如:
{
"switch": false
}
这个示例消息显然是通知设备关闭某个开关,设备通过自身的程序实现该功能后,可以接着向云平台上报属性或上报事件,让云平台得到确认。
那么,如何实现云平台下发属性呢?我们提供两种方式:
控制台
在控制台的设备详情【属性】页面中,这种方式适合开发调试阶段或小规模项目。
应用端 API
调用云平台提供的应用端 API,这种方式可以集成到任何应用系统中。
设备上报事件
前边都是属性相关的消息,这一节我们来了解一下事件。
设备发送消息
通过事件,设备可以向云端报告消息,而不需要上报任何属性。例如:设备的 AI 视觉传感器捕捉到活动人数,上报给云平台。
一个事件由如下内容组成:
- 事件名称
可以理解为函数名,是事件的唯一表示。
- 事件参数
可以理解为函数的参数,是 JSON
格式的结构体,包含若干参数。
设备可以随时向云平台上报事件,只需将事件消息发布到如下主题:
event/report/<id>
<id>
的取值为不超过 6 位的整数,例如:
event/report/1000
发布的事件消息格式如下:
{
"method": "{name}",
"params": {
"key1": "{value1}",
"key2": "{value2}",
...
}
}
例如前边提到的,工厂生产线上的 AI 视觉传感器捕捉到产品数量后,上报事件给云平台,那么消息可能是这样的:
{
"method": "productFound",
"params": {
"count": 3,
"location": "REGION.B43",
"tags": "RED",
"detail": [
"100474",
"100475",
"100342"
]
}
}
设备接收消息
如果我们想知道事件上报是否被云平台成功接收,可以订阅如下主题:
event/response/+
或者
event/response/<id>
请注意,订阅主题只需要在设备 MQTT 成功连接云平台后执行一次即可。当设备上报事件后,便会通过该主题收到来自云平台的响应消息,如果云平台接收成功,响应消息如下:
{
"result": 1,
"ts": 1609143039050
}
值得注意的是,响应消息中的成功,只代表云平台成功收到了事件上报,并不代表对事件进行业务处理的结果。
云平台收到设备的事件上报后,如何处理事件呢?规则引擎便派上用场了,通过规则引擎,您可以将事件实时推送到第三方 Webhook URL,或通过规则引擎的云函数实现告警策略,当然还可以实现对其它设备的联动控制。
设备接收云端下发命令
与事件相反,命令是由云平台向设备主动下发的一组消息,用来实时通知设备执行某个特定的功能。
设备接收消息
设备在 MQTT 连接云平台后,确保订阅如下主题:
command/send/+
如果设备不支持 +
MQTT 通配符,也可以订阅如下主题:
command/send/<id>
订阅成功后,设备便处于等待接收命令的状态。当云平台下发命令时,设备便会收到命令消息。
命令消息的格式也是基于 JSON
的结构体,如下:
{
"method": "{name}",
"params": {
"key1": "{value1}",
"key2": "{value2}",
...
},
"id": "{id}"
}
您可能发现了,它和事件消息格式非常类似,只是多了一个 id
。您可以认为它就是从云平台向设备的一个远程调用(RPC)。
设备回复消息
设备收到命令消息后,通过自身的代码逻辑实现特定的功能后,可以回复命令,也可以不回复命令。
云平台会自动接收回复命令,并和下发命令进行匹配,一次下发命令只能接收一次回复命令,它们的匹配正是通过使用一致的 <id>
来保证。
设备回复命令消息的格式如下:
{
"method": "{name}",
"params": {
"key1": "{value1}",
"key2": "{value2}",
...
}
}
没错,它和命令下发的消息格式一模一样,回复命令发布的主题如下:
command/reply/<id>
请注意,回复命令的主题中的 <id>
,一定要和对应的命令下发消息中的 id
保持一致。
MQTT 调试
在接入云平台的设备开发过程中,有多种方法可以帮助您快速调试,并验证消息收发通信。
MQTT 客户端工具
使用 MQTT 客户端工具,例如:
- MQTT.fx 官网