MQTT协议与阿里云IoT物联网平台

栏目: 后端 · 发布时间: 5年前

内容简介:MQTT(消息队列遥测传输) 是基于 TCP/IP 协议栈而构建的支持在各方之间异步通信的消息协议。MQTT在空间和时间上将消息发送者与接收者分离,因此可以在不可靠的网络环境中进行扩展。虽然叫做消息队列遥测传输,但它与消息队列毫无关系,而是使用了发布和订阅(Pub/Sub)的模型。MQTT 是一种轻量级的、灵活的网络协议,致力于为 IoT 开发人员实现适当的平衡:MQTT Client 库在很多语言中都有实现,包括 Embedded C、C、Java、JavaScript、Python、C++、C#、Go

MQTT(消息队列遥测传输) 是基于 TCP/IP 协议栈而构建的支持在各方之间异步通信的消息协议。MQTT在空间和时间上将消息发送者与接收者分离,因此可以在不可靠的网络环境中进行扩展。虽然叫做消息队列遥测传输,但它与消息队列毫无关系,而是使用了发布和订阅(Pub/Sub)的模型。

MQTT 是一种轻量级的、灵活的网络协议,致力于为 IoT 开发人员实现适当的平衡:

  • 这个轻量级协议可在严重受限的设备硬件和高延迟/带宽有限的网络上实现。
  • 它的灵活性使得为 IoT 设备和服务的多样化应用场景提供支持成为可能。
MQTT协议与阿里云IoT物联网平台

1.2 MQTT Client库

MQTT Client 库在很多语言中都有实现,包括 Embedded C、C、 Java 、JavaScript、 Python 、C++、C#、 Go 、iOS、Android等。Eclipse Paho的MQTT库下载地址: www.eclipse.org/paho/downlo…

MQTT协议与阿里云IoT物联网平台

下面开发实践基于Nodejs版mqtt,获取地址 www.npmjs.com/package/mqt…

1.3 MQTT报文

MQTT协议与阿里云IoT物联网平台

1.3.1 固定报头Fixed header

Bit

7

6

5

4

3

2

1

0

byte 1

MQTT控制报文的类型

用于指定控制报文类型的标志位

byte 2,3,4,5

剩余长度,最大4个字节

控制报文类型

名字 报文流动方向 描述
Reserved 0 禁止 保留
CONNECT 1 Client -> Broker device连接IoT平台
CONNACK 2 Broker -> Client IoT平台确认连接结果
PUBLISH 3 双向 发布消息
PUBACK 4 双向 QoS=1消息发布收到确认
PUBREC 5 双向 IoT不支持
PUBREL 6 双向 IoT不支持
PUBCOMP 7 双向 IoT不支持
SUBSCRIBE 8 Client -> Broker device订阅IoT平台Topic
SUBACK 9 Broker -> Client IoT平台确认订阅结果
UNSUBSCRIBE 10 Client -> Broker device取消订阅IoT平台Topic
UNSUBACK 11 Broker -> Client IoT平台确认取消订阅结果
PINGREQ 12 Client -> Broker device发送心跳请求到IoT平台
PINGRESP 13 Broker -> Client IoT平台响应device心跳
DISCONNECT 14 Client -> Broker device断开IoT平台连接
Reserved 15 禁止 保留

控制报文类型标志位

控制报文 固定报头标志 Bit 3 Bit 2 Bit 1 Bit 0
PUBLISH MQTT 3.1.1使用 DUP QoS QoS RETAIN

剩余长度

字节数 最小值 最大值
1 0 (0x00) 127 (0x7F)
2 128 (0x80, 0x01) 16 383 (0xFF, 0x7F)
3 16 384 (0x80, 0x80, 0x01) 2 097 151 (0xFF, 0xFF, 0x7F)
4 2 097 152 (0x80, 0x80, 0x80, 0x01) 268 435 455 (0xFF, 0xFF, 0xFF, 0x7F)

注:阿里云IoT的单个payload最大256K

1.3.2 可变报头Variable header

某些MQTT控制报文包含一个可变报头部分。它在固定报头和负载之间。可变报头的内容根据报文类型的不同而不同。可变报头的报文标识符(Packet Identifier)字段存在于在多个类型的报文里。

报文标识符字节 Packet Identifier bytes

Bit 70
byte 1 报文标识符 MSB
byte 2 报文标识符 LSB
控制报文 报文标识符
PUBLISH 需要(如果QoS =1,2)
PUBACK 需要
PUBREC 需要
PUBREL 需要
PUBCOMP 需要
SUBSCRIBE 需要
SUBACK 需要
UNSUBSCRIBE 需要
UNSUBACK 需要

1.3.3 有效载荷Payload

以下MQTT控制报文在报文的最后部分包含一个有效载荷。对于PUBLISH来说有效载荷就是业务消息。

控制报文 有效载荷
CONNECT 需要
PUBLISH 可选
SUBSCRIBE 需要
SUBACK 需要
UNSUBSCRIBE 需要

2.与阿里云IoT平台建立连接

MQTT协议与阿里云IoT物联网平台

2.1 CONNECT

阿里云IoT物联网平台的MQTT协议不支持will消息,CONNECT 消息内容参数如下:

参数

说明

cleanSession

此标志指定连接是否是持久性的。

0为持久会话,QoS=1消息不会丢失;

1为非持久会话,清理离线消息。

clientId

客户端标识符

username

代理的身份验证和授权凭证。

password

代理的身份验证和授权凭证。

keepAlive

心跳时间, IoT平台约定心跳范围 30s~1200s

其中clientId,username,password由设备三元组(productKey,deviceName,deviceSecret)按照规则生成,具体规则如下:

clientId

id +"|securemode=3,signmethod=hmacsha1,timestamp="+timestamp+"|"

id :表示客户端ID,64字符内 。其中 || 内为扩展参数。

securemode:安全模式;2为TLS加密,3为非加密

signmethod:签名算法类型。 timestamp:当前时间毫秒值。

username

deviceName+"&"+productKey

password

sign_hmac(deviceSecret,content)

sign_hmac为clientId中的signmethod算法类型

content为如下拼接字符串: " clientId ${ id } deviceName ${deviceName} productKey ${productKey} timestamp ${timestamp}"

官方文档: help.aliyun.com/document_de…

设备端代码示例(Nodejs版) client.js

/**
"dependencies": { "mqtt": "2.18.8" }
*/
const crypto = require('crypto');
const mqtt = require('mqtt');
//设备身份三元组+区域
const deviceConfig = {
    productKey: "替换",
    deviceName: "替换",
    deviceSecret: "替换",
    regionId: "cn-shanghai"
};
//根据三元组生成mqtt连接参数
const options = initMqttOptions(deviceConfig);
const url = `tcp://${deviceConfig.productKey}.iot-as-mqtt.${deviceConfig.regionId}.aliyuncs.com:1883`;

//2.建立连接
const client = mqtt.connect(url, options);

client.on('packetsend', function (packet){
  console.log('send '+packet.cmd+' packet =>',packet)
})

client.on('packetreceive', function (packet){
  console.log('receive '+packet.cmd+' packet =>',packet)
})


//IoT平台mqtt连接参数初始化
function initMqttOptions(deviceConfig) {

    const params = {
        productKey: deviceConfig.productKey,
        deviceName: deviceConfig.deviceName,
        timestamp: Date.now(),
        clientId: Math.random().toString(36).substr(2),
    }
    //CONNECT参数
    const options = {
        keepalive: 60, //60s
        clean: false, //cleanSession保持持久会话
        protocolVersion: 4 //MQTT v3.1.1
    }
    //1.生成clientId,username,password
    options.password = signHmacSha1(params, deviceConfig.deviceSecret);
    options.clientId = `${params.clientId}|securemode=3,signmethod=hmacsha1,timestamp=${params.timestamp}|`;
    options.username = `${params.deviceName}&${params.productKey}`;

    return options;
}

/*
  生成基于HmacSha1的password
  参考文档:https://help.aliyun.com/document_detail/73742.html?#h2-url-1
*/
function signHmacSha1(params, deviceSecret) {

    let keys = Object.keys(params).sort();
    // 按字典序排序
    keys = keys.sort();
    const list = [];
    keys.map((key) => {
        list.push(`${key}${params[key]}`);
    });
    const contentStr = list.join('');
    return crypto.createHmac('sha1', deviceSecret)
            .update(contentStr)
            .digest('hex');
}
复制代码

2.2 CONNACK

receive connack packet => Packet {
  cmd: 'connack',
  retain: false,
  qos: 0,
  dup: false,
  length: 2,
  topic: null,
  payload: null,
  sessionPresent: false,
  returnCode: 0 
}
复制代码

2.4 PINGRESP

send pingreq packet => { cmd: 'pingreq' }
复制代码

2.5 PINGRESP

receive pingresp packet => Packet {
  cmd: 'pingresp',
  retain: false,
  qos: 0,
  dup: false,
  length: 0,
  topic: null,
  payload: null 
}
复制代码

2.6 DISCONNECT

MQTT协议与阿里云IoT物联网平台

3. 发布数据

3.1 PUBLISH

//3.属性数据上报
const topic = `/sys/${deviceConfig.productKey}/${deviceConfig.deviceName}/thing/event/property/post`;
setInterval(function() {
    //发布数据到topic
    client.publish(topic, getPostData(),{qos:1});
}, 5 * 1000);

function getPostData() {
    const payloadJson = {
        id: Date.now(),
        params: {
            temperature: Math.floor((Math.random() * 20) + 10),
            humidity: Math.floor((Math.random() * 20) + 60)
        },
        method: "thing.event.property.post"
    }

    console.log("===postData\n topic=" + topic)
    console.log(payloadJson)

    return JSON.stringify(payloadJson);
}

复制代码
send publish packet => { cmd: 'publish',
  topic: '/sys/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/thing/event/property/post',
  payload: '{"id":1543896481106,"params":{"temperature":23,"humidity":73},"method":"thing.event.property.post"}',
  qos: 1,
  retain: false,
  messageId: 38850,
  dup: false 
}
复制代码

3.2 PUBACK

receive puback packet => Packet {
  cmd: 'puback',
  retain: false,
  qos: 0,
  dup: false,
  length: 2,
  topic: null,
  payload: null,
  messageId: 38850 
}
复制代码

4. 接收数据

4.1 SUBSCRIBE

//4.订阅主题,接收指令
const subTopic = `/${deviceConfig.productKey}/${deviceConfig.deviceName}/control`;
client.subscribe(subTopic)
client.on('message', function(topic, message) {
    console.log("topic " + topic)
    console.log("message " + message)
})
复制代码

SUBSCRIBE消息体

send subscribe packet => { cmd: 'subscribe',
  subscriptions: 
   [ { topic: '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control', qos: 0 } ],
  qos: 1,
  retain: false,
  dup: false,
  messageId: 38851 
}
复制代码

4.2 SUBACK

SUBACK消息体

receive suback packet => Packet {
  cmd: 'suback',
  retain: false,
  qos: 0,
  dup: false,
  length: 3,
  topic: null,
  payload: null,
  granted: [ 128 ],
  messageId: 38851 
}
复制代码

4.3 UNSUBSCRIBE

send unsubscribe packet => { cmd: 'unsubscribe',
  qos: 1,
  messageId: 34323,
  unsubscriptions: [ '/a1hQSwFledE/eud1jXfEgCsAiP2eId9Q/control' ] 
}
复制代码

4.4 UNSUBACK

receive unsuback packet => Packet {
  cmd: 'unsuback',
  retain: false,
  qos: 0,
  dup: false,
  length: 2,
  topic: null,
  payload: null,
  messageId: 34323 
}
复制代码

5. 服务质量QoS

服务质量

Quality of Service

描述

阿里云IoT

QoS=0

最多一次的传输,可能会收不到消息

支持

QoS=1

至少一次的传输,一定会收到消息,可能重复

支持

QoS=2

有且仅有一次的传输

不支持

MQTT协议与阿里云IoT物联网平台

6. 设备掉线重连

设备与阿里云IoT的订阅关系在云端保持,除非设备主动unsubscribe,否则订阅关系不清理。设备重连后,依然保持之前的订阅关系,不需要重复订阅。

7. 传输层安全TLS 1.2

设备和IoT平台之间的链路可以通过TLS v1.2加密。 如果使用TLS加密,需要下载根证书。 CONNECT参数中clientId的 securemode=2

help.aliyun.com/document_de…

IoT物联网技术

MQTT协议与阿里云IoT物联网平台

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

像计算机科学家一样思考Python (第2版)

像计算机科学家一样思考Python (第2版)

[美] 艾伦 B. 唐尼 / 赵普明 / 人民邮电出版社 / 2016-7 / 49.00

本书以培养读者以计算机科学家一样的思维方式来理解Python语言编程。贯穿全书的主体是如何思考、设计、开发的方法,而具体的编程语言,只是提供了一个具体场景方便介绍的媒介。 全书共21章,详细介绍Python语言编程的方方面面。本书从基本的编程概念开始讲起,包括语言的语法和语义,而且每个编程概念都有清晰的定义,引领读者循序渐进地学习变量、表达式、语句、函数和数据结构。书中还探讨了如何处理文件和......一起来看看 《像计算机科学家一样思考Python (第2版)》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

MD5 加密
MD5 加密

MD5 加密工具