目录
1. CONNECT 连接服务器
2. CONNACK 确认连接
3. DISCONNECT 断开连接
4. PINGREQ 心跳请求
5. PINGRESP 心跳响应
6. SUBSCRIBE 订阅主题
7. SUBACK 订阅确认
8. UNSUBSCRIBE 取消订阅
9. UNSUBACK 取消订阅确认
10. PUBLISH 发布消息(双向的,C < = > S)
11. PUBACK 发布确认
总结
实际案例、相关链接
此教程使用电脑网络调试助手,MQTT接入阿里云物联网平台,手动计算MQTT 报文帧,实现IOT设备的数据解析与上报。
逐字节详解 MQTT控制报文帧的合成和解析,对于单片机设备 MQTT接入物联网平台,有很好的借鉴作用。
相关文章:
- MQTT3.1.1 通信协议 - 帧格式详解:MQTT 报文帧格式详解
- 阿里云物联网平台,注册产品、设备、设备三元组:阿里云 - 物联网 MQTT注册产品、设备、设备三元组
此教程,使用的设备证书三元组为
{
"ProductKey": "a1wFylTxYeD",
"DeviceName": "co_0001",
"DeviceSecret": "7ab0c4b3532b5783df5fdc58a2895d7a"
}
阿里云物联网控制台:阿里云
1. CONNECT 连接服务器
客户端ID | *|securemode=3,signmethod=hmacsha1| | *为设备名称 |
---|---|---|
用户名 | *&# | *为设备名称,#是ProductKey |
密码 | 用DeviceSecret做为秘钥对clientId*deviceName*productKey#进行hmacsha1加密后的结果 | *为设备名称,#是ProductKey |
结合自己的设备证书,最终合成的客户端ID、用户名、密码:
客户端ID:co_0001|securemode=3,signmethod=hmacsha1|
用户名:co_0001&a1wFylTxYeD
clientIdco_0001deviceNameco_0001productKeya1wFylTxYeD
-------------------------------用DeviceSecret做为秘钥,进行HmacSHA1加密---------------------------------
密码:e782b5e55b37655c27812a60c307b0a7575d8f6d
将上面这些统统转换为 16进制,以备帧合成过程中使用。
字符格式 | 16 进制ASC2编码格式 | 长度 | |
---|---|---|---|
客户端ID | co_0001|securemode=3,signmethod=hmacsha1| | 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C | 41 |
用户名 | co_0001&a1wFylTxYeD | 63 6F 5F 30 30 30 31 26 61 31 77 46 79 6C 54 78 59 65 44 | 19 |
密码 | e782b5e55b37655c27812a60c307b0a7575d8f6d | 65 37 38 32 62 35 65 35 35 62 33 37 36 35 35 63 32 37 38 31 32 61 36 30 63 33 30 37 62 30 61 37 35 37 35 64 38 66 36 64 | 40 |
10 ?? (固定报头。??为剩余长度,待后续报文合成完毕后计算)
10 ?? 00 04 4D 51 54 54 04 C2 01 2C(可变报头。01 2C为Keep alive的时长300,单位秒。可自行定义)
10 ?? 00 04 4D 51 54 54 04 C2 01 2C 00 29 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C(客户端ID的字节长度41 + 客户端ID)
10 ?? 00 04 4D 51 54 54 04 C2 01 2C 00 29 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C 00 13 63 6F 5F 30 30 30 31 26 61 31 77 46 79 6C 54 78 59 65 44 (用户名的字节长度19 + 用户名)
10 ?? 00 04 4D 51 54 54 04 C2 01 2C 00 29 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C 00 13 63 6F 5F 30 30 30 31 26 61 31 77 46 79 6C 54 78 59 65 44 00 28 65 37 38 32 62 35 65 35 35 62 33 37 36 35 35 63 32 37 38 31 32 61 36 30 63 33 30 37 62 30 61 37 35 37 35 64 38 66 36 64 (密码的字节长度40 + 密码)
10 74 00 04 4D 51 54 54 04 C2 01 2C 00 29 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C 00 13 63 6F 5F 30 30 30 31 26 61 31 77 46 79 6C 54 78 59 65 44 00 28 65 37 38 32 62 35 65 35 35 62 33 37 36 35 35 63 32 37 38 31 32 61 36 30 63 33 30 37 62 30 61 37 35 37 35 64 38 66 36 64(可变报头 + 有效载荷 的总长度 = 116)
10 74 00 04 4D 51 54 54 04 C2 01 2C 00 29 63 6F 5F 30 30 30 31 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C 00 13 63 6F 5F 30 30 30 31 26 61 31 77 46 79 6C 54 78 59 65 44 00 28 65 37 38 32 62 35 65 35 35 62 33 37 36 35 35 63 32 37 38 31 32 61 36 30 63 33 30 37 62 30 61 37 35 37 35 64 38 66 36 64
留意中文输入法,可能会乱码。
服务器IP:#.iot-as-mqtt.cn-shanghai.aliyuncs.com #是ProductKey 注意替换
a1wFylTxYeD.iot-as-mqtt.cn-shanghai.aliyuncs.com
端口号:1883
打开电脑网络调试助手。
选择 TCP Client。远程主机地址使用:a1wFylTxYeD.iot-as-mqtt.cn-shanghai.aliyuncs.com :1883
点击连接。将上述合成后的CONNECT报文粘贴,发送。(提前勾选16进制,之后再粘贴)
连接上服务器后,若10s内无上报消息,阿里云会主动断开连接。
正确,返回:20 02 00 00,并且保持链接。00 连接成功。
错误,返回:20 02 00 04,并且断开连接。04 无效的用户名和密码。
CONNECT成功后,在阿里云物联网控制台,可以查看到设备在线。
2. CONNACK 确认连接
即为CONNECT的响应,数据流动方向为 S -> C。
正确,返回:20 02 00 00,并且保持链接。00 连接成功。
错误,返回:20 02 00 04,并且断开连接。04 无效的用户名和密码。
其他的值含义,详见 MQTT报文帧格式详解:MQTT 报文帧格式详解
3. DISCONNECT 断开连接
DISCONNECT帧:E0 00
发送 DISCONNECT帧后,若传输过程无误,阿里云服务器会主动断开连接。
客户端发送DISCONNECT报文之后,必须关闭网络连接,并且不能通过这个网络连接再发送任何控制报文。
服务端在收到DISCONNECT报文时,必须丢弃任何与当前连接关联的未发布的遗嘱消息,并且关闭网络连接(如果客户端 还没关闭连接的话)。
4. PINGREQ 心跳请求
PINGREQ帧:C0 00
在Keep alive时间内,C端应该向S端发送 PINFREQ,告知客户端还存在。
响应:PINGRESP
Keep alive与PINGREQ的关联,详见:MQTT 报文PINGREQ、PINGRESP详解
5. PINGRESP 心跳响应
即为PINGREQ的响应,数据流动方向为 S -> C。
PINGRESP帧:D0 00
6. SUBSCRIBE 订阅主题
MQTT协议 SUBSCRIBE帧格式的详解:MQTT 报文 SUBSCRIBE详解
首先要知道与阿里云通信,需要订阅哪几个主题?
回到设备的产品界面,Topic类列表 - 物模型通信Topic,可查看与物模型通信用到的所有主题。
合成订阅报文:
82 ?? (固定报头)
82 ?? 00 03 (可变报头,报文标识符)
82 ?? 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 (有效载荷,要订阅的Topic字节长度 + Topic。/sys/a1wFylTxYeD/co_0001/thing/service/property/set)
82 ?? 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00 (Qos=0)
82 38 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00 (可变 + 负载长度 = 2 + 2 + 51 + 1 = 56)
82 38 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00 (Qos=0)
82 38 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 01 (Qos=1)
82 37 00 04 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 00 (Qos=0)
82 37 00 04 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 01 (Qos=1)
响应:SUBACK
订阅成功,响应返回:90 03 00 03 01 (00 03是自定义的报文标识符,01是返回码,表示订阅成功,且最大Qos为1)
订阅失败,响应返回:90 03 00 03 80(80,订阅失败)
在阿里云的 设备管理 - 设备 - Topic列表,显示已经存在/sys/a1wFylTxYeD/co_0001/thing/service/property/set和/sys/a1wFylTxYeD/co_0001/thing/event/property/post
注意:报文标识符可用户自行定义。报文标识符相当于自定义的Topic的ID,用ID号去代替具体的Topic,而不是字段,使得区分发来的Topic的同时又可以节省流量,可自定义,建议自己预先拟定一个服务ID表。
详细说明见:MQTT 报文 SUBSCRIBE详解
7. SUBACK 订阅确认
即为SUBSCRIBE的响应,数据流动方向为 S -> C。
90 03 00 03 01 (00 03是自定义的报文标识符。01是返回码,表示订阅成功,且最大Qos等级为1)
90 03 00 04 01 (00 04是自定义的报文标识符。01是返回码,表示订阅成功,且最大Qos等级为1)
8. UNSUBSCRIBE 取消订阅
取消订阅Topic=/sys/a1wFylTxYeD/co_0001/thing/service/property/set
A2 37 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 (对比SUBSCRIBE订阅,更改了固定报头,并且没有Qos,其余未变)
A2 37 00 03 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74
取消订阅成功,响应返回:B0 02 00 03 (00 03是自定义的报文标识符)
在阿里云的 设备管理 - 设备 - Topic列表,显示已经取消订阅。
9. UNSUBACK 取消订阅确认
B0 02 00 03 (00 03是自定义的报文标识符)
详细说明见:MQTT 报文 SUBSCRIBE详解
10. PUBLISH 发布消息(双向的,C < = > S)
网络调试助手接收到的消息:
30 9C 01 00 33 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 37 36 35 39 35 31 35 34 35 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D
解析过程:
30。PUBLISH,Qos=0。
9C 01。剩余长度,156字节。MQTT固定报头中剩余长度的计算方法:MQTT 固定报头中剩余长度的计算
之后是可变报头,可变报头的第一个是报文标识符,而报文标识符只有在Qos=1/2时才有,而当前是0,是没有的。
00 33。51字节长度。
2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74
/sys/a1wFylTxYeD/co_0001/thing/service/property/set
7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 73 65 72 76 69 63 65 2E 70 72 6F 70 65 72 74 79 2E 73 65 74 22 2C 22 69 64 22 3A 22 37 36 35 39 35 31 35 34 35 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D
{"method":"thing.service.property.set","id":"765951545","params":{"PowerSwitch_1":0},"version":"1.0.0"}
开关状态为1的 内容和Topic:
{"method":"thing.event.property.post","id":"123456789","params":{"PowerSwitch_1":1},"version":"1.0.0"}
7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 79 2E 70 6F 73 74 22 2C 22 69 64 22 3A 22 31 32 33 34 35 36 37 38 39 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D (102个字节)
/sys/a1wFylTxYeD/co_0001/thing/event/property/post
2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 (50个字节)
----------------------------------------------------------------------------------------------------------------------------------------------
其中,"id":"123456789",id号为消息ID,可自行用户定义,不会对最终属性造成影响,只用来标识传输的消息帧。
----------------------------------------------------------------------------------------------------------------------------------------------
开关状态为1的 PUBLISH报文帧合成过程:
30 ?? ?? (固定报头,PUBLISH,Qos=0。Qos=1 阿里云服务器不支持,会有错误)
30 ?? ?? 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 (Topic的字节数50 + Topic)
30 9A 01 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 79 2E 70 6F 73 74 22 2C 22 69 64 22 3A 22 31 32 33 34 35 36 37 38 39 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D (+JSON消息后,计算剩余长度,为154)
开关状态为1:
30 9A 01 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 79 2E 70 6F 73 74 22 2C 22 69 64 22 3A 22 31 32 33 34 35 36 37 38 39 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 31 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D
开关状态为0:
30 9A 01 00 32 2F 73 79 73 2F 61 31 77 46 79 6C 54 78 59 65 44 2F 63 6F 5F 30 30 30 31 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 79 2E 70 6F 73 74 22 2C 22 69 64 22 3A 22 31 32 33 34 35 36 37 38 39 22 2C 22 70 61 72 61 6D 73 22 3A 7B 22 50 6F 77 65 72 53 77 69 74 63 68 5F 31 22 3A 30 7D 2C 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 2E 30 22 7D
因为我同时订阅了/sys/a1wFylTxYeD/co_0001/thing/event/property/post,所以PUBLISH后服务器也会将原数据下发。如果不想接收,可以不订阅post,依旧可以上报消息,不会对上报造成任何影响。
!!!阿里云服务器仅支持Qos=0的post。Qos=1/2 不支持,发送Qos=1会有错误。
设备 - 物模型数据 - 电源开关_1 - 查看数据,可以查看到刚刚上发的两条数据。
MQTT PUBLISH帧格式:MQTT 报文 PUBLISH详解
MQTT固定报头中剩余长度的计算方法:MQTT 固定报头中剩余长度的计算
11. PUBACK 发布确认
MQTT协议规定,PUBACK 是对 Qos=1时的 PUBLISH的发布消息确认。也就是说Qos=1 才有 PUBACK,但阿里云服务器仅支持 Qos=0的POST,所以压根就不会有PUBACK。而用户强行发送Qos=1的POST,会返回错误:40 02 7B 22 ,并且不会对本帧的内容进行处理,开关状态不会得到更新。
!!!阿里云服务器仅支持Qos=0的post。Qos=1/2 不支持,发送Qos=1会有错误。
!!!Qos=0是没有 PUBACK发布消息确认的。
!!!PUBREC、PUBREL、PUBCOMP为 Qos=2时才会用到,而百度、阿里、腾讯的物联网平台最高仅支持Qos=1。
总结
只有Connect繁琐一点,需要加密,其他都是明码,格式都较为简单。
MQTT 帧格式的详解,在本篇博客同一专栏中。
实际案例、相关链接
MQTT 协议详解:MQTT 协议详解
MQTT 报文帧格式详解:MQTT 报文帧格式详解
使用MQTT.fx,MQTT接入阿里云物联网平台:MQTT.fx 接入阿里云
使用电脑网络调试助手,MQTT接入阿里云物联网平台:网络调试助手接入阿里云
版权说明:如非注明,本站文章均为 扬州驻场服务-网络设备调试-监控维修-南京泽同信息科技有限公司 原创,转载请注明出处和附带本文链接。
请在这里放置你的在线分享代码