说明
MQTT协议详细内容请参见MQTT version 3.1.1官方文档,本文档对此不做详细说明,仅指明OneNet的要求、默认参数、以及当前实现与MQTT官方文档的差异。
该版本支持的功能:
鉴权;
数据点上报(平台指定topic);
创建topic;
获取项目的topic列表;
订阅/取消平台的topic;
设备间topic订阅;
平台命令下发;
Qos0(cóS) ,Qos1(C->S);
连接保活
离线topic
数据点订阅
接入流程
访问OneNET官网注册用户;
登录开发者中心,新建产品,获取项目ID、设备ID,以及authinfo等信息;
设备发送TCP连接请求地址请见文档中心FAQ,发送封装的报文与平台交互,。
Packet格式说明
包格式包含三部分:
Fixed Header | 所有packet中都必须有 |
Varable Header | 部分包含有 |
Payload | 部分包含有 |
Fixed header
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT Packet Type | 0 | 0 | 0 | 0 | |||
byte2 - 5 | Remaining Length(该字段占用1-4个字节) |
该版本支持的所有类型:
名字 | 值 | 流向 | 描述 |
CONNECT | 1 | C->S | 客户端请求与服务端建立连接 |
CONNACK | 2 | S->C | 服务端确认连接建立 |
PUBLISH | 3 | CóS | 发布消息 |
PUBACK | 4 | CóS | 收到发布消息确认 |
PUBREC | 5 | CóS | 发布消息收到 |
PUBREL | 6 | CóS | 发布消息释放 |
PUBCOMP | 7 | CóS | 发布消息完成 |
SUBSCRIBE | 8 | C->S | 订阅请求 |
SUBACK | 9 | S->C | 订阅确认 |
UNSUBSCRIBE | 10 | C->S | 取消订阅 |
UNSUBACK | 11 | S->C | 取消订阅确认 |
PING | 12 | C->S | 客户端发送PING(连接保活)命令 |
PINGRSP | 13 | S->C | PING命令回复 |
DISCONNECT | 14 | C->S | 断开连接 |
3.2 Variable Header &Payload
消息类型 | Variable Header | Payload |
CONNECT | 有 | 有 |
CONNACK | 有 | 有 |
PUBLISH | 有 | 有 |
PUBACK | 有 | 无 |
PUBREC | 有 | 无 |
PUBREL | 有 | 无 |
PUBCOMP | 有 | 无 |
SUBSCRIBE | 有 | 有 |
SUBACK | 有 | 有 |
UNSUBSCRIBE | 有 | 有 |
UNSUBACK | 有 | 无 |
PING | 无 | 无 |
PINGRSP | 无 | 无 |
DISCONNECT | 无 | 无 |
支持的packet
CONNECT
4.1.1 Fixed Header
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT Packet Type | 0 | 0 | 0 | 0 | |||
byte2 - 5 | Remaining Length(该字段占用1-4个字节) |
4.1.2 VariableHeader
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1-2 | ProtocolName Length | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | ||
byte 3 | ‘M’ | 0 | 1 | 0 | 0 | 1 | 1 | 0 | 1 |
byte 4 | ‘Q’ | 0 | 1 | 0 | 1 | 0 | 0 | 0 | 1 |
byte 5 | ‘T’ | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
byte 6 | ‘T’ | 0 | 1 | 0 | 1 | 0 | 1 | 0 | 0 |
Byte7 | Protocol Level | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Byte8 | Connect Flag | User flag | Password flag | WillRetain Flag | WillQos Flag | WillFlag | CleanSession Flag | Reserve | |
Byte9-10 | KeepAlive |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
版本
必须设置为4,平台只支持版本v 3.1.1,不支持更老的版本。使用第三方客户端时需要注意选择正确的版本。
user flag与password flag
平台不允许匿名登陆,因此这两个标志位在连接时必须设置为1,否则认为协议错误,平台将会断开连接。
Will flag与Willretainflag/WillQosFlag
Will flag为0时,WillQosFlag和WillRetainFlag必须为0,Will Flag为1时,WillQosFlag只能为0、1、2。
注: 1.当该设备下一次正常上线后,服务器会清除之前的will 消息(包括retain消息)。
2.如果设备上线时设置了Will Topic和msg,且将WillRetainFlag设置为1,只有设备异常断开后,服务器才会将该Will msg分发给新的Will Topic的订阅者,且Qos级别以订阅的Request qos级别为准。
3.如果设备上线时设置了Will Topic和msg,且将WillRetainFlag设置为0,服务器不会存储该消息,当设备异常断开后会将该Will msg以设备设置的WillQosFlag的Qos级别进行分发。
CleanSessionFlag
若客户端将clean session标志位设置为0,当其断开后,平台将会保存session,session需保持的内容包含:
客户端订阅的topic列表。
还未完成确认的Qos1、Qos2级别的publish消息
客户端保存session的内容包含:
已经发送到服务端的但还没有收到确认的Qos1、Qos2消息列表。
待发送的Qos0列表。
若客户端将clean session标志位设置为1,当其断开后,平台会清除设备的订阅列表及未完成确认的Qos1、Qos2的publish消息。
Reserve
保留位,置0。
KeepAlive保活时间
每个客户端可自定义设置连接保持时间,最短120秒,最长65535秒。
4.1.3 Payload
| Description | 是否必须存在 | 格式 |
Field1 | Client Identifier | 是 | 2字节字串长度 + utf8字串 |
Field2 | UserName | 是 | 2字节字串长度 + utf8字串 |
Field3 | UserPassword | 是 | 2字节字串长度 + utf8字串 |
与鉴权相关的字段包含client id,username和password,支持鉴权方式。
方式1:设备ID、项目ID、auth_info
字段设置 | 消息示例 |
client_id设置为平台创建设备时的设备id username设置为“项目ID” password设置为“鉴权信息(auth_info)” | client_id=”123” username=”433223” password=”注册的鉴权信息” |
各字段说明如下:
鉴权信息(auth_info):在平台申请设备时填写设备的auth_info属性(数字+字母的字符串),该属性需要产品内具备唯一性;
方式2:设备ID + APIKey(项目ID也需要填写)
字段设置 | 消息示例 |
client_id设置为平台创建设备时的设备id username设置为“项目ID” password设置为“鉴权信息(auth_info)” | client_id=”123” username=”433223” password=Api Key |
项目ID:在平台添加项目时平台生成的ID
APIKey:在平台上创建产品时生成的APIKey
CONNACK
4.2.1 Fixed Header
4.2.2 VariableHeader
| Description | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | Acknowledge Flags | 0 | 0 | 0 | 0 | 0 | 0 | 0 | Sp |
byte 2 | Return Code | x | x | x | x | x | x | x | x |
Sp: Session Present Flag,session信息在服务器已保持,置1;未保存,置0。
返回码说明:
返回码 | 描述 |
0 | 成功 |
1 | 协议版本错误 |
2 | 非法的clientid |
3 | 服务不可用 |
4 | 用户名或密码错误 |
5 | 非法链接(比如token非法) |
失败:
*如果connect包不符合协议内容约束,则直接断掉连接,而不需要发送connack包.
*如果鉴权或授权失败,回复一个带非0错误码的connack包.
成功:
*必须断掉重复的clientid.
*执行cleansession 对应的操作.
*必须回复一个connack,回复码为0.
*开始消息传递,并加入keepalive的监视.
PS:客户端需要等到服务端的connack报文,才能发送后续的数据包.
PUBLISH(client -> server)
4.3.1 Fixed header
Bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
byte 1 | MQTT Packet Type | DUP flag | QoS Level | RETAIN | ||||
byte2 - 5 | Remaining Length(该字段占用1-4个字节) |
DUP:
QoS2、Qos1:如果为0,则表示是第一次发送该包,如果为1,则表示为重复发送的包。
Qos0:DUP必须为0
QOS: 指定了该publish包的Qos等级如下
Qos 值 | Bit2 | Bit1 | 描述 |
0 | 0 | 0 | 最多发送一次 |
1 | 0 | 1 | 至少发送一次 |
2 | 1 | 0 | 只发送一次 |
RETAIN: 保留标志位,如果为1,服务器存储最新一条RETAIN消息,以便分发给新的订阅者,如果RETAIN为1,Payload为空,服务器分发该消息后会清空该topic下的RETAIN消息。
PS:该版本实现了Qos0,Qos1,Qos2。
4.3.2 VariableHeader
| Description | 格式 | 是否必须 |
Field1 | TopicName | 2字节字串长度 + utf8字串 | 是 |
Field2 | PacketIdentifier | 2字节 | QoS0:否,QoS1、Qos2:是 |
4.3.3 Payload
内容根据不同业务自定义
接入流程
连接鉴权
设备向平台发起connect请求.connect中携带鉴权信息,具体参见(报文格式参考4.1)
平台拿到鉴权信息进行鉴权.
鉴权通过后,如果cleansession=0, 平台将会加载保存的设备的一些信息.如订阅列表(4.1.2中描述).
如果cleansession=1, 设备没有保存信息在平台,则不加载设备相关信息.
返回鉴权结果ConnAck(报文格式参考4.2).
消息发布
5.2.1 数据点上报
设备使用publish报文来上传数据点,报文格式如下:
VariableHeader:
| Field名称 | 说明 | 格式 |
Field1 | TopicName=”$dp” | $dp为系统上传数据点的指令 | 2字节字串长度+ utf8字串 |
Payload:
Payload包含真正的数据点内容,支持的格式如下:
字节 | 说明\bit | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Byte 1 | Bit0-5数据类型指示,目前支持: Type = 1 Type = 2 Type = 3 Type = 4 Type = 5 Type = 6 Type = 7 Bit6-7 flags 根据具体类型不同意义 Type6、Type7这两种需要填写时间戳的数据类型:如果填入了时间戳,则须将bit7置1,否则置0(即忽略数据类型说明中的日期、时间相关字段) | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Byte 2 | 根据数据类型指示不同 |
|
|
|
|
|
|
|
|
。。。 |
|
|
|
|
|
|
|
| |
Byte n |
|
|
|
|
|
|
|
|
数据类型1(type == 1)格式说明:
Byte 1 | 数据点类型值:1 //1:JSON格式1字符串 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 |
Byte 2 | //指示后面json字符串长度 固定两字节长度高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte 3 | 固定两字节长度低位字节,值为0x41 |
|
|
|
|
|
|
|
|
Byte 4 | { “datastreams”:[// 可以同时传递多个数据流 { “id”:”temperature”, “datapoints”:[//数据流可以有多个数据点 { ”at”:”2013-04-22 22:22:22”,//可选 ”value”: 36.5//用户自定义 } ] }, { “id”:”location” “datapoints”:[…] }, { … } ] } |
|
|
|
|
|
|
|
|
… … … … … … … … … … |
|
|
|
|
|
|
|
| |
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
Byte n |
|
|
|
|
|
|
|
|
数据类型2(type == 2)格式说明:
Byte 1 | 数据点类型指示:type=2 //二进制数据 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |
Byte 2 | //指示后面json字符串长度 固定两字节长度-高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte 3 | 固定两字节长度-低位字节,值为0x10 |
|
|
|
|
|
|
|
|
Byte 4 | { ”ds_id”:”image”, //创建数据流时定义的ID,(必填) “at”:”2014-10-25 12:23:23”, //时间,(可选) ”desc”:字符串或json对象//对该数据的描述(可选) } |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
… |
|
|
|
|
|
|
|
| |
Byte n |
|
|
|
|
|
|
|
| |
Byte n+1 | //指示后面二进制数据长度 固定四字节长度-第1字节(最高),值为0x00 |
|
|
|
|
|
|
|
|
Byte n+1 | 固定四字节长度-第2字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte n+2 | 固定四字节长度-第3字节,值为0x01 |
|
|
|
|
|
|
|
|
Byte n+3 | 固定四字节长度-第4字节(最低),值为0x00 |
|
|
|
|
|
|
|
|
Byte n+4 | //该域目前最大支持3M 本例中的该域256字节数据 |
|
|
|
|
|
|
|
|
… |
|
|
|
|
|
|
|
| |
Byte n+260 |
|
|
|
|
|
|
|
|
数据类型3(type == 3)格式说明:
数据类型4(type ==4)格式说明
Byte 1 | 数据点类型指示:type=4 // JSON格式3字符串 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
Byte 2 | //指示后面字符串长度 固定两字节长度高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte 3 | 固定两字节长度低位字节,值为0x46 |
|
|
|
|
|
|
|
|
Byte 4 | 通用格式: { “datastream_id1”:{“datetime1”:”value1”}, “datastream_id2”: {“datetime2”:”value2”}, … }
示例: {“temperature”:{“2015-03-22 22:31:12”:22.5}} |
|
|
|
|
|
|
|
|
… … … … |
|
|
|
|
|
|
|
| |
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
|
|
|
|
|
|
|
| ||
Byte n |
|
|
|
|
|
|
|
|
数据类型5(type == 5)格式说明
数据类型6(type == 6)格式说明
数据类型7(type == 7)格式说明:(每次最多500个数据流的浮点数)
Byte 1 | Bit0-5数据类型指示:type=7 //可离散浮点数数据流 Bit6:保留,置0 Bit7: 时间指示位,1,携带6字节时间 | 1 | 0 | 0 | 0 | 0 | 1 | 1 | 1 |
Byte 2 | 年(后两位),例如2016年,则该字节为16 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |
Byte 3 | 月(1-12) |
|
|
|
|
|
|
|
|
Byte 4 | 日(1-31) |
|
|
|
|
|
|
|
|
Byte 5 | 小时(0~23) |
|
|
|
|
|
|
|
|
Byte 6 | 分钟(0~59) |
|
|
|
|
|
|
|
|
Byte7 | 秒(0~59) |
|
|
|
|
|
|
|
|
Byte 8 | //数据流名称(取值范围1-65535) 高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte 9 | 低位字节,值为0x01 |
|
|
|
|
|
|
|
|
Byte10 | //数据流个数(取值范围1-500) 高位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte11 | 低位字节,值为0x01 |
|
|
|
|
|
|
|
|
Byte 10 | 4字节float类型,低位在前,高位在后 |
|
|
|
|
|
|
|
|
Byte 11 |
|
|
|
|
|
|
|
| |
Byte 12 |
|
|
|
|
|
|
|
| |
Byte 13 |
|
|
|
|
|
|
|
| |
... |
|
|
|
|
|
|
|
|
|
Byte n | //数据流名称(取值范围1-65535) 高位字节,值为0x24 |
|
|
|
|
|
|
|
|
Byte n+1 | 低位字节,值为0x37 |
|
|
|
|
|
|
|
|
Byte n+2 | //数据流个数(取值范围1-500) 高位字节,值为0x01 |
|
|
|
|
|
|
|
|
Byte n+3 | 低位字节,值为0x00 |
|
|
|
|
|
|
|
|
Byte n+2 | 4字节float类型,低位在前,高位在后 |
|
|
|
|
|
|
|
|
Byte n+4 |
|
|
|
|
|
|
|
| |
Byte n+5 |
|
|
|
|
|
|
|
| |
Byte n+6 |
|
|
|
|
|
|
|
|