聂永的博客

记录工作/学习的点点滴滴。

MQTT-SN协议乱翻之消息格式

前言

紧接着上篇初步介绍,本文为第二篇,主要梳理MQTT-SN 1.2协议中定义的消息格式。

通用消息格式

消息头 其它可变部分
2/4字节表示 N字节组成

消息头部

长度 消息类型
1或3个字节 1个字节
  • 长度要么是1个字节,要么3个字节表示,并且自身也会包含在其内。一个字节可表示256长度,一般情况下,完全够用了。
  • 只需要判断第一个字节是否为 0x01,若是那么长度为3个字节表示,剩下的两个字节会表示真正的消息长度,最大长度为65535
  • 否则长度就是一个字节表示,256个长度,大部分消息长度都是一个字节,除非特别提醒

备注:

 MQTT-SN不支持消息的分片和重组。底层网络所定义数据包长度若小于MQTT-SN消息的最大长度,自身进行的分片和重组,对MQTT-SN协议本身不受影响。

MQTT-SN消息类型

MQTT-SN定义的消息类型数量众多,超过25个,感觉有些头大。

消息类型值 消息类型名称 说明
0x00 ADVERTISE 广播消息
0x01 SEARCHGW 寻找网关
0x02 GWINFO 网关信息
0x03 reserved 没有使用到
0x04 CONNECT 发起连接
0x05 CONNACK 连接确认
0x06 WILLTOPICREQ 遗嘱主题请求
0x07 WILLTOPIC 遗嘱主题确认
0x08 WILLMSGREQ 遗嘱消息请求
0x09 WILLMSG 遗嘱消息确认
0x0A REGISTER 注册主题
0x0B REGACK 注册确认
0x0C PUBLISH 发布消息
0x0D PUBACK 发布确认
0x0E PUBCOMP 发布环节消息
0x0F PUBREC 发布环节消息
0x10 PUBREL 发布环节消息
0x11 reserved 保留字段
0x12 SUBSCRIBE 订阅主题
0x13 SUBACK 订阅确认
0x14 UNSUBSCRIBE 退订
0x15 UNSUBACK 退订确认
0x16 PINGREQ Ping请求
0x17 PINGRESP Ping响应
0x18 DISCONNECT 断开
0x19 reserved 保留字段
0x1A WILLTOPICUPD 遗嘱主题更新
0x1B WILLTOPICRESP 遗嘱主题更新确认
0x1C WILLMSGUPD 遗嘱消息更新
0x1D WILLMSGRESP 遗嘱消息更新确认
0x1E-0xFD reserved 保留字段
0xFE 转发封装标志 用于转发

消息可变部分

可变字段很多,与MQTT相比,多了:

  1. 持续时长字段(Duration)
  2. 标识符Flags有所不同,下面表格进行说明
  3. 网关地址(GwAdd),可变长度,但依赖于底层网络,在ZigBee网络中2个字节长度
  4. 一个字节网关Id(GwId)
  5. 协议Id(ProtocolId),一个字节,唯一值 0x01,统一表示协议名称和协议名称
  6. 广播路径跳数(广播路径深度/广播辐射范围),Radius,一个字节表示,0x00表示广播给当前网络中所有节点
  7. CONNECT/REGISTER/SUBSCRIBE/PUBLISH等消息对应回执中都会包含返回码Recode Code,见下表格
返回值 返回值含义
0x00 接受请求(Accepted)
0x01 因拥塞拒绝(Rejected: congestion),一般需要接收方等待T_WAIT时间长
0x02 因非法主题标识符拒绝(Rejected: invalid topic ID)
0x03 因不支持拒绝(Rejected: not supported)
0x04 - 0xFF 保留,没有使用到

具体消息格式说明

网关周期性会对当前网络下所有客户端、节点进行广播,用于客户端发现可用网关。

字节索引 表示内容 说明
0 Length 0x05
1 MsgType 0x00
2 GwId 网关需要吧自身标识符包含其中
3-4 Duration 网关的下次广播间隔时长,单位秒

SEARCHGW

字节索引 表示内容 说明
0 Length 0x03
1 MsgType 0x01
2 Radius 广播半径深度,同时也是只是给当前网络传输层

客户端主动寻找网关进行广播的消息,广播路径范围受限于当前网络环境下的客户端部署密度,比如只有1跳广播在非常密集的网络环境下客户端都可以彼此互相访问。

GWINFO

字节索引 表示内容 说明
0 Length 动态确定
1 MsgType 0x02
2 GwId 网关Id
3-n GwAdd* 一个网关地址,仅仅由客户端发出消息时,此字段才存在

GWINFO作为对SEARCHGW消息的响应:

  • 若由网关发出,则无GwAdd字段
  • 若来自于客户端,需要包含网关地址

CONNECT

客户端向网关发出建立连接的消息。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x04
2 Flags 标志位
3 ProtocolId 0x01,表示协议版本和协议名称
4-5 Duration 存活持续时长
6-n ClientId 客户端标识符,1-23个字节表示的字符串

在CONNECT消息标志位具体表示如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
X X X 0/1 0/1 X
  • 0/1 表示具体值待定
  • X 表示没有使用到

在Flags中使用到的标志位:

  1. Will:若为1,客户端会在稍后请求遗嘱主题和遗嘱消息
  2. CleanSession:不但表示订阅持久化,同时也被可扩展到遗嘱主题和遗嘱消息中

CONNACK

网关对客户端发出CONNECT消息的响应。

字节索引 表示内容 说明
0 Length 0x03
1 MsgType 0x05
2 ReturnCode 接受值0x00,拒绝为0x01-0x03,具体见上文RecodeCode定义

WILLTOPICREQ

根据客户端CONNECT标志位中WILL字段为true情况下,网关向客户端发出遗嘱主题请求,格式如下:

字节索引 表示内容 说明
0 Length 0x02
1 MsgType 0x06

只有头部部分,很简单。

WILLTOPIC

客户端作为网关WILLTOPICREQ请求响应消息。下面是一个正常版本的WILLTOPIC消息:

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x07
2 Flags 标志位
3-n WillTopic 遗嘱主题

此时的标志位如下

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
X 0x00-0x02 0/1 X X X

而空的WILLTOPIC也是允许存在的,就两个字节表示,用于客户端请求删除已存在于服务器端的对应遗嘱主题和消息。

字节索引 表示内容 说明
0 Length 0x02
1 MsgType 0x07

WILLMSGREQ

根据客户端CONNECT标志位中WILL字段为真情况下,网关向客户端发出遗嘱消息请求,格式如下:

字节索引 表示内容 说明
0 Length 0x02
1 MsgType 0x08

只有头部部分,没有别的。

WILLMSG

客户端对网关WILLMSGREQ请求的响应,从而把遗嘱消息传递给网关进行保存。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x09
2-n WillMsg 客户端遗嘱

REGISTER

  • 客户端-->网关,请求主题(topic name)对应的主题标识符(topic id)
  • 网关-->客户端,通知主题(topic name)已经被指派到某个主题标识符(topic id)
字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x0A
2-3 TopicId 客户端发出,此值为0x0000;服务器发出,需要包含对应于Topic Name的主题标识符
4-5 MsgId 自然数,用以标识对应的REGACK确认
6-n TopicName 主题名称,不能太长,尽量不要使用通配符

REGACK

客户端或网关针对REGISTER消息的响应。

字节索引 表示内容 说明
0 Length 0x07
1 MsgType 0x0B
2-3 TopicId 对应于Topic Name的主题标识符,被用于PUBLISH消息发布
4-5 MsgId 自然数,用以标识对应的REGISTER消息
6 ReturnCode 0x00被接受,其它值被拒绝

PUBLISH

PUBLISH消息用于客户端或网关发布消息用:

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x0C
2 Flags 标志位
3-4 TopicId 主题标识符
5-6 MsgId QoS 1-2时需要填充自然值;QoS 0时,值为0x0000
7-n Data 用于发布的具体消息内容

标识位具体如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
0/1 0x00-0x02 0/1 X X 0b00/0b01/0b10

标识位里面各个字段和MQTT协议一致,无须多解释。

PUBACK

客户端/网关仅仅对QoS 1/2的PUBLISH消息做出响应。

字节索引 表示内容 说明
0 Length 0x07
1 MsgType 0x0D
2-3 TopicId 对应PUBLISH消息中TopicId
4-5 MsgId 自然数,用以标识对应的REGISTER消息
6 ReturnCode 0x00被接受,其它值被拒绝,不同值表示不同拒绝理由

处理PUBLISH消息异常?在PUBACK消息中的ReturnCode字段中以相应值体现出来,这就要求接收者处理拒绝理由。

PUBREC, PUBREL, PUBCOMP

只有在PUBLISH消息中QoS 2时,PUBREC, PUBREL, PUBCOMP才会一起登场,否则是没有出场机会的。消息格式嘛,都很统一:

字节索引 表示内容 说明
0 Length 0x04
1 MsgType 0x0F/0x10/0x0E
2-3 MsgId 对应PUBLISH消息中的MsgId

SUBSCRIBE

SUBSCRIBE用于客户端订阅某个主题的消息。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x12
2 Flags 标志位
3-4 MsgId 用于确定对应的订阅确认SUBACK消息
5-N TopicId/TopicName 具体需要根据Flags标志位中TopicIdType进行填充

标识位具体如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
0/1 0x00-0x02 X X X 0b00/0b01/0b10

此处,标志位中TopicIdType决定了SUBSCRIBE消息中TopicId/TopicName字段具体填充值:预定义topic id,或短小两个字符表示主题(topic name),或直接填写主题。

SUBACK

网关->客户端,订阅处理情况的确认回执,接受订阅或出于其它原因拒绝之。

字节索引 表示内容 说明
0 Length 0x08
1 MsgType 0x13
2 Flags 标志位
3-4 TopicId 网关接受其注册,此处对应具体指派的TopicId
5-6 MsgId SUBSCRIBE消息中对应MsgId值
7 ReturnCode 0x00被接受,其它值被拒绝

标识位具体如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
X 0x00-0x02 X X X X

SUBACK消息标志位中QoS为网关根据实际情况授权后的QoS具体值,这也应该是客户端需要知道并处理的。

UNSUBSCRIBE

UNSUBSCRIBE用于客户端取消订阅某个主题的消息。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x14
2 Flags 标志位
3-4 MsgId 用于确定对应的退订确认UNSUBACK消息
5-N TopicId/TopicName 具体需要根据Flags标志位中TopicIdType进行填充

标识位具体如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
X X X X X 0b00/0b01/0b10

UNSUBSCRIBE消息标志位中唯一可用属性TopicIdType决定了UNSUBSCRIBE消息中TopicId/TopicName字段具体填充值。

UNSUBACK

网关->客户端,取消订阅处理情况的确认回执,很简单,4个字节表示。

字节索引 表示内容 说明
0 Length 0x04
1 MsgType 0x15
2-3 MsgId UNSUBSCRIBE消息中对应MsgId值

PINGREQ

和MQTT协议中的PINGREQ一致,存活检测。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x16
2-N ClientId 可选项,表示客户端休眠状态转换为唤醒状态用于检查网关是否为其缓存消息

PINGRESP

接受PINGREQ消息的一方,如网关响应PINGRESP消息表示自己现在运行OK。

另外一个意图,若唤醒状态客户端发送PINGREQ消息之后,直接收到PINGRESP消息,表示网关当前暂时没有为其缓存的消息可供发送。

字节索引 表示内容 说明
0 Length 0x02
1 MsgType 0x17

很简单,两个字节表示足矣。

DISCONNECT

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x18
2-3 Duration 可选项,表示客户端即将进入睡眠状态的持续时间值
  • 客户端->网关,客户端主动关闭当前连接,网关响应确认消息。只有表示自己进入睡眠状态的客户端,才会在DISCONNECT消息中附加Duration持续字段。
  • 网关->客户端,网关由于异常主动通知客户端关闭两者之间连接,客户端接收到DISCONNECT时需要发送CONNECT消息到网关,重试重新建立连接。没有Duration字段填充。

网关接收到要进入休眠状态的客户端发送的包含有Duration字段DISCONNECT消息时,可以直接返回2个字节的(不能包含有Duration字段)DISCONNECT消息以示确认。

WILLTOPICUPD

客户端发送请求网关更新其遗嘱主题。

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x1A
2 Flags 标志位
3-N WillTopic 用于更新的遗嘱主题

标识位具体如下:

DUP QoS Retain Will CleanSession TopicIdType
bit 7 6,5 4 3 2 1,0
X 0x00-0x02 0/1 X X X

协议规定只有两个字节空WILLTOPICUPD也是允许存在的,存在意义用于客户端请求网关删除已保存的遗嘱主题和遗嘱消息等。

字节索引 表示内容 说明
0 Length 0x02
1 MsgType 0x1A

WILLTOPICRESP

WILLTOPICRESP为网关收到WILLTOPICUPD后作出的应答消息。

字节索引 表示内容 说明
0 Length 0x03
1 MsgType 0x1B
2 ReturnCode 0x00被接受,其它值被拒绝

WILLMSGUPD

字节索引 表示内容 说明
0 Length 动态计算
1 MsgType 0x1C
2-N WillMsg 用于更新的遗嘱消息

客户端->网关,确认更新的遗嘱消息。

WILLMSGRESP

WILLMSGRESP为网关收到WILLMSGUPD后作出的应答消息。

字节索引 表示内容 说明
0 Length 0x03
1 MsgType 0x1D
2 ReturnCode 0x00被接受,其它值被拒绝

转发封装

在MQTT-SN架构图中,MQTT-SN Forwarder转发器适用于客户端无法直接访问网关或当前传感器网络区域中不存在网关时,转发器作用就体现出来了:

  1. 接收MQTT-SN客户端消息封装后转发给上游网关
  2. 解封上游网关所发送消息,直接发送给对应客户端

转发器作用于消息的封装转发,解封发送,针对消息不做修改。

转发器对MQTT-SN消息封装格式:

字节索引 表示内容 说明
0 Length 十进制表示长度就是N
1 MsgType 0xFE
2 Ctrl 包含网关和转发器之间的控制交换信息,主要是前两位包含了半径范围
3-N Wireless Node Id 标识所发目的或需要接收封装消息的无线节点
N+1-M MQTT-SN message 一个MQTT-SN消息消息

无线节点Id(Wireless Node Id):

  • 转发器->网关,无线节点Id为转发器所在的无线节点Id,便于告知网关转发器位置
  • 网关->转发器,无线节点Id为网关的无线节点Id

控制交换字段Ctrl,单个字节,位表示含义:

bit 7,2 1,0
X 0x00-0x03

小结

MQTT-SN 1.2规范中所定义消息格式介绍完毕,下一篇将对MQTT-SN主要流程功、能进行阐述。

posted on 2015-01-08 21:52 nieyong 阅读(6679) 评论(1)  编辑  收藏 所属分类: MQTT

评论

# re: MQTT-SN协议乱翻之消息格式[未登录] 2016-05-16 21:14 Echo

大侠,关于MQTT-SN的网关发现有一处地方不大明白,还请指点。 ADVERTISE这个消息只发送的是GW的ID, client收到该消息之后,怎么知道GW的地址呢(比如GW的IP+Port)。 另外GWINFO这个消息里面,只有当client发出时,才包含地址,GW发出时不包含地址。 这样岂不是client都没办法知道GW的地址啊? 谢谢  回复  更多评论   


只有注册用户登录后才能发表评论。


网站导航:
 

公告

所有文章皆为原创,若转载请标明出处,谢谢~

新浪微博,欢迎关注:

导航

<2015年1月>
28293031123
45678910
11121314151617
18192021222324
25262728293031
1234567

统计

常用链接

留言簿(58)

随笔分类(130)

随笔档案(151)

个人收藏

最新随笔

搜索

最新评论

阅读排行榜

评论排行榜