MQTT协议(部分)

  1. 说明

MQTT协议详细内容请参见MQTT version 3.1.1官方文档,本文档对此不做详细说明,仅指明OneNet的要求、默认参数、以及当前实现与MQTT官方文档的差异。

该版本支持的功能:

  • 鉴权;

  • 数据点上报(平台指定topic);

  • 创建topic;

  • 获取项目的topic列表;

  • 订阅/取消平台的topic;

  • 设备间topic订阅;

  • 平台命令下发;

  • Qos0(cóS) ,Qos1(C->S);

  • 连接保活

  • 离线topic

  • 数据点订阅

  1. 接入流程

  1. 访问OneNET官网注册用户;

  1. 登录开发者中心,新建产品,获取项目ID、设备ID,以及authinfo等信息;

  1. 设备发送TCP连接请求地址请见文档中心FAQ,发送封装的报文与平台交互,。

  1. Packet格式说明

包格式包含三部分:

Fixed Header

所有packet中都必须有

Varable Header

部分包含有

Payload

部分包含有

  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个字节)

该版本支持的所有类型:

名字

流向

描述

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

  1. 支持的packet

  1. 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

  1. 版本

必须设置为4,平台只支持版本v 3.1.1,不支持更老的版本。使用第三方客户端时需要注意选择正确的版本。

  1. user flag与password flag

平台不允许匿名登陆,因此这两个标志位在连接时必须设置为1,否则认为协议错误,平台将会断开连接。

  1. Will flag与Willretainflag/WillQosFlag

Will flag为0时,WillQosFlagWillRetainFlag必须为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级别进行分发。

  1. CleanSessionFlag

若客户端将clean session标志位设置为0,当其断开后,平台将会保存session,session需保持的内容包含:

  • 客户端订阅的topic列表。

  • 还未完成确认的Qos1、Qos2级别的publish消息

客户端保存session的内容包含:

  • 已经发送到服务端的但还没有收到确认的Qos1、Qos2消息列表。

  • 待发送的Qos0列表。

若客户端将clean session标志位设置为1,当其断开后,平台会清除设备的订阅列表及未完成确认的Qos1、Qos2的publish消息。

  1. Reserve

保留位,置0。

  1. 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

  1. 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报文,才能发送后续的数据包.

  1. 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

内容根据不同业务自定义

  1. 接入流程

  1. 连接鉴权

  • 设备向平台发起connect请求.connect中携带鉴权信息,具体参见(报文格式参考4.1)

  • 平台拿到鉴权信息进行鉴权.

  • 鉴权通过后,如果cleansession=0, 平台将会加载保存的设备的一些信息.如订阅列表(4.1.2中描述).

如果cleansession=1, 设备没有保存信息在平台,则不加载设备相关信息.

  • 返回鉴权结果ConnAck(报文格式参考4.2).

  1. 消息发布

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

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
对于基于Spring Boot设计的物联网平台,实现MQTT协议、HTTP协议、CoAP协议接入,以下是相关的示例代码和依赖项: 1. HTTP协议部分 依赖项: ```xml <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-http</artifactId> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-stream</artifactId> </dependency> </dependencies> ``` 示例代码: ```java @RestController public class HttpController { private final MessageChannel input; public HttpController(MessageChannel input) { this.input = input; } @PostMapping("/send") public ResponseEntity<String> send(@RequestBody String body) { input.send(MessageBuilder.withPayload(body).build()); return ResponseEntity.ok("Message sent successfully"); } } @Configuration @EnableIntegration public class HttpIntegrationConfig { @Value("${http.input}") private String httpInput; @Bean public IntegrationFlow httpInboundFlow() { return IntegrationFlows.from(Http.inboundChannelAdapter(httpInput)) .channel(input()) .get(); } @Bean public MessageChannel input() { return new DirectChannel(); } @Bean public IntegrationFlow httpOutboundFlow() { return IntegrationFlows.from(output()) .handle(Http.outboundGateway("http://example.com")) .get(); } @Bean public MessageChannel output() { return new DirectChannel(); } } ``` 2. MQTT协议部分 依赖项: ```xml <dependencies> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-mqtt</artifactId> </dependency> </dependencies> ``` 示例代码: ```java @Configuration @EnableIntegration public class MqttIntegrationConfig { @Value("${mqtt.host}") private String mqttHost; @Value("${mqtt.topic}") private String mqttTopic; @Bean public IntegrationFlow mqttInboundFlow() { return IntegrationFlows.from( MQTT.inboundAdapter(mqttHost, mqttTopic) .autoStartup(false) .clientId("clientId") .mqttVersion(MqttVersion.MQTT_3_1_1) .qos(2) .defaultRetained(false) .async(false) .subscribeTimeout(10000)) .handle(message -> { String payload = message.getPayload().toString(); // process the received message }) .get(); } @Bean public MessageChannel mqttOutputChannel() { return new DirectChannel(); } @Bean public IntegrationFlow mqttOutboundFlow() { return IntegrationFlows.from(mqttOutputChannel()) .handle(MQTT.outboundAdapter(mqttHost) .async(true) .defaultRetained(false) .clientId("clientId") .mqttVersion(MqttVersion.MQTT_3_1_1) .qos(2) .topicExpression("headers['mqtt_topic']")) .get(); } @Bean public IntegrationFlow mqttGatewayFlow() { return IntegrationFlows.from(Mqtt.outboundGateway(mqttHost) .async(true) .defaultRetained(false) .clientId("clientId") .mqttVersion(MqttVersion.MQTT_3_1_1) .qos(2) .defaultTopic(mqttTopic)) .get(); } } ``` 3. CoAP协议部分 依赖项: ```xml <dependencies> <dependency> <groupId>org.eclipse.californium</groupId> <artifactId>californium-core</artifactId> <version>2.0.0-M4</version> </dependency> <dependency> <groupId>org.springframework.integration</groupId> <artifactId>spring-integration-core</artifactId> </dependency> </dependencies> ``` 示例代码: ```java @Configuration @EnableIntegration public class CoapIntegrationConfig { @Value("${coap.port}") private int coapPort; @Bean public CoapEndpoint coapEndpoint() { return new CoapEndpoint(new InetSocketAddress(coapPort)); } @Bean public IntegrationFlow coapInboundFlow() { return IntegrationFlows.from(coapInboundAdapter()) .handle(message -> { String payload = message.getPayload().toString(); // process the received message }) .get(); } @Bean public IntegrationFlow coapOutboundFlow() { return IntegrationFlows.from(MessageChannels.direct("coapOutboundChannel")) .handle(coapOutboundAdapter()) .get(); } @Bean public MessageProducerSupport coapInboundAdapter() { CoapInboundChannelAdapter adapter = new CoapInboundChannelAdapter(coapEndpoint()); adapter.setInterceptors(Arrays.asList(new CoapEndpointInterceptor())); adapter.setOutputChannelName("coapInputChannel"); return adapter; } @Bean public MessageHandler coapOutboundAdapter() { CoapEndpoint coapEndpoint = new CoapEndpoint(new InetSocketAddress("host", coapPort)); coapEndpoint.addInterceptor(new CoapEndpointInterceptor()); CoapOutboundGateway gateway = new CoapOutboundGateway(coapEndpoint, "coap://host/path"); gateway.setOutputChannelName("coapOutputChannel"); return gateway; } @Bean public MessageChannel coapInputChannel() { return new DirectChannel(); } @Bean public MessageChannel coapOutputChannel() { return new DirectChannel(); } @Bean public IntegrationFlow coapGatewayFlow() { return IntegrationFlows.from(Coap.outboundGateway("coap://example.com")) .get(); } } class CoapEndpointInterceptor implements CoapEndpoint.CoapEndpointInterceptor { @Override public void sendMessage(CoapMessage message) throws CoapException { // intercept the outgoing message } @Override public void receiveMessage(CoapMessage message) throws CoapException { // intercept the incoming message } } ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值