使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

目录

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接入物联网平台,有很好的借鉴作用。

 

相关文章

此教程,使用的设备证书三元组为

{
  "ProductKey": "a1wFylTxYeD",
  "DeviceName": "co_0001",
  "DeviceSecret": "7ab0c4b3532b5783df5fdc58a2895d7a"
}

 

1. CONNECT 连接服务器

  • 有效载荷字段中,客户端ID、用户名、密码的合成方法:
客户端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

 

  • CONNECT 报文帧的合成过程:

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)

  • 最终合成后的CONNECT报文:

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进制,之后再粘贴)

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

连接上服务器后,若10s内无上报消息,阿里云会主动断开连接。

正确,返回:20 02 00 00,并且保持链接。00 连接成功。

错误,返回:20 02 00 04,并且断开连接。04 无效的用户名和密码。

 

CONNECT成功后,在阿里云物联网控制台,可以查看到设备在线。

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

 

2. CONNACK 确认连接

即为CONNECT的响应,数据流动方向为 S -> C。

正确,返回:20 02 00 00,并且保持链接。00 连接成功。

错误,返回:20 02 00 04,并且断开连接。04 无效的用户名和密码。

其他的值含义,详见 MQTT报文帧格式详解:MQTT 报文帧格式详解

 

 

3. DISCONNECT 断开连接

DISCONNECT帧:E0 00

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

 

发送 DISCONNECT帧后,若传输过程无误,阿里云服务器会主动断开连接。

客户端发送DISCONNECT报文之后,必须关闭网络连接,并且不能通过这个网络连接再发送任何控制报文

服务端在收到DISCONNECT报文时,必须丢弃任何与当前连接关联的未发布的遗嘱消息,并且关闭网络连接(如果客户端 还没关闭连接的话)

 

 

4. PINGREQ 心跳请求

PINGREQ帧:C0 00

在Keep alive时间内,C端应该向S端发送 PINFREQ,告知客户端还存在。

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

响应:PINGRESP

Keep alive与PINGREQ的关联,详见:MQTT 报文PINGREQ、PINGRESP详解

 

 

5. PINGRESP 心跳响应

即为PINGREQ的响应,数据流动方向为 S -> C。

PINGRESP帧:D0 00

 

 

6. SUBSCRIBE 订阅主题

MQTT协议 SUBSCRIBE帧格式的详解:MQTT 报文 SUBSCRIBE详解

 

  • 报文标识符自定义为00 03,Qos = 0/1,订阅的Topic=/sys/a1wFylTxYeD/co_0001/thing/service/property/set,用于下发属性
  • SUBSCRIBE 报文帧的合成过程:

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)

  • 最终合成后的 SUBSCRIBE报文:

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)

 

  • 报文标识符自定义为00 04,Qos = 0/1,Topic=/sys/a1wFylTxYeD/co_0001/thing/event/property/post,用于数据上报
  • 最终合成后的 SUBSCRIBE报文:

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)

 

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

响应: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

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

注意报文标识符可用户自行定义。报文标识符相当于自定义的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

  • UNSUBSCRIBE 报文帧的合成过程:

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,其余未变)

  • 最终合成后的 UNSUBSCRIBE报文:

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

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

取消订阅成功,响应返回:B0 02 00 03 (00 03是自定义的报文标识符)

 

在阿里云的 设备管理 - 设备 - Topic列表,显示已经取消订阅。

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

 

9. UNSUBACK 取消订阅确认

B0 02 00 03 (00 03是自定义的报文标识符)

详细说明见:MQTT 报文 SUBSCRIBE详解

 

 

10. PUBLISH 发布消息(双向的,C < = > S)

  • S端下发属性,需要提前订阅Topic=/sys/a1wFylTxYeD/co_0001/thing/service/property/set
  • 用阿里云的在线调试,调试功能PowerSwitch_1,方法设置。向设备下发一个开关状态

网络调试助手接收到的消息

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"}

 

  • 设备向服务器构建上发
  • C端上发属性,需要提前订阅Topic=/sys/a1wFylTxYeD/co_0001/thing/event/property/post
  • 开关状态为1的 PUBLISH报文帧合成过程:

开关状态为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)

  • 最终合成后的 PUBLISH报文(Qos=0):

开关状态为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接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

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 ,并且不会对本帧的内容进行处理,开关状态不会得到更新。

 

使用网络调试助手 MQTT接入阿里云物联网平台,逐字节讲解,适用单片机/ESP8266接入阿里云

 

!!!阿里云服务器仅支持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接入阿里云物联网平台:网络调试助手接入阿里云