物联网 (IoT) 设备必须连接互联网。通过连接到互联网,设备就能相互协作,以及与后端服务协同工作。互联网的基础网络协议是 TCP/IP。MQTT(消息队列遥测传输) 是基于 TCP/IP 协议栈而构建的,已成为 IoT 通信的标准。

MQTT 最初由 IBM 于上世纪 90 年代晚期发明和开发。它最初的用途是将石油管道上的传感器与卫星相链接。顾名思义,它是一种支持在各方之间异步通信的消息协议。异步消息协议在空间和时间上将消息发送者与接收者分离,因此可以在不可靠的网络环境中进行扩展。虽然叫做消息队列遥测传输,但它与消息队列毫无关系,而是使用了一个发布和订阅的模型。在 2014 年末,它正式成为了一种 OASIS 开放标准,而且在一些流行的编程语言中受到支持(通过使用多种开源实现)。

为何选择 MQTT

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

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

为了了解为什么 MQTT 如此适合 IoT 开发人员,我们首先来分析一下为什么其他流行网络协议未在 IoT 中得到成功应用。

为什么不选择HTTP

大多数开发人员已经熟悉 HTTP Web 服务。那么为什么不让 IoT 设备连接到 Web 服务?设备可采用 HTTP 请求的形式发送其数据,并采用 HTTP 响应的形式从系统接收更新。这种请求和响应模式存在一些严重的局限性:

  1. HTTP 是一种同步协议。客户端需要等待服务器响应。Web 浏览器具有这样的要求,但它的代价是牺牲了可伸缩性。在 IoT 领域,大量设备以及很可能不可靠或高延迟的网络使得同步通信成为问题。异步消息协议更适合 IoT 应用程序。传感器发送读数,让网络确定将其传送到目标设备和服务的最佳路线和时间。
  2. HTTP 是单向的。客户端必须发起连接。在 IoT 应用程序中,设备或传感器通常是客户端,这意味着它们无法被动地接收来自网络的命令。
  3. HTTP 是一种 1-1 协议。客户端发出请求,服务器进行响应。将消息传送到网络上的所有设备上,不但很困难,而且成本很高,而这是 IoT 应用程序中的一种常见使用情况。
  4. HTTP 是一种有许多标头和规则的重量级协议。它不适合受限的网络。

HTTP协议的两个过程,Request和Response,两个都有各自的语言格式,我们看下是什么。

请求报文格式:(注意这里有个换行)

<method> <request-URL> <version>

<headers>

<entity-body>

响应报文格式:(注意这里有个换行)

<version> <status> <reason-phrase>

<headers>

<entity-body>

方法method:

这个很重要,比如说GET和POST方法,这两个是很常用的,GET就是获取什么内容,而POST就是向服务器发送什么数据。当然还有其他的,比如HTTP 1.1中还有:DELETE、PUT、CONNECT、HEAD、OPTIONS、TRACE等一共8个方法(HTTP Method历史:HTTP 0.9 只有GET方法;HTTP 1.0 有GET、POST、HEAD三个方法)。

请求URL:

这里填写的URL是不包含IP地址或者域名的,是主机本地文件对应的目录地址,所以我们一般看到的就是“/”。

版本version:

格式是HTTP/<major>.<minor>这样的格式,比如说HTTP/1.1.这个版本代表的就是我们使用的HTTP协议的版本,现在使用的一般是HTTP/1.1

状态码status:

状态码是三个数字,代表的是请求过程中所发生的情况,比如说200代表的是成功,404代表的是找不到文件。

原因短语reason-phrase:

是状态码的可读版本,状态码就是一个数字,如果你事先不知道这个数字什么意思,可以先查看一下原因短语。

首部header:

注意这里的header我们不是叫做头,而是叫做首部。可能有零个首部也可能有多个首部,每个首部包含一个名字后面跟着一个冒号,然后是一个可选的空格,接着是一个值,然后换行。

实体的主体部分entity-body:

实体的主体部分包含一个任意数据组成的数据块,并不是所有的报文都包含实体的主体部分,有时候只是一个空行加换行就结束了。

下面我们举个简单的例子:

请求报文:

GET /index.html HTTP/1.1

Accept: text/*

Host: www.myweb.com

响应报文:

HTTP/1.1 200 OK

Content-type: text/plain

Content-length: 3

出于上述原因,大部分高性能、可扩展的系统都使用异步消息总线来进行内部数据交换,而不使用 Web 服务。事实上,企业中间件系统中使用的最流行的消息协议被称为 AMQP(高级消息排队协议)。但是,在高性能环境中,计算能力和网络延迟通常不是问题。AMQP 致力于在企业应用程序中实现可靠性和互操作性。它拥有庞大的特性集,但不适合资源受限的 IoT 应用程序。

除了 AMQP 之外,还有其他流行的消息协议。例如,XMPP(Extensible Messaging and Presence Protocol,可扩展消息和状态协议)是一种对等即时消息 (IM) 协议。它高度依赖于支持 IM 用例的特性,比如存在状态和介质连接。与 MQTT 相比,它在设备和网络上需要的资源都要多得多。

那么,MQTT 为什么如此轻量且灵活?MQTT 协议的一个关键特性是发布和订阅模型。与所有消息协议一样,它将数据的发布者与使用者分离。

它具有以下主要的几项特性:

1、使用发布/订阅消息模式,提供一对多的消息发布和应用程序之间的解耦;

2、消息传输不需要知道负载内容;

3、使用 TCP/IP 提供网络连接;

4、有三种消息发布的服务质量:

QoS 0:“最多一次”,消息发布完全依赖底层 TCP/IP 网络。分发的消息可能丢失或重复。例如,这个等级可用于环境传感器数据,单次的数据丢失没关系,因为不久后还会有第二次发送。

QoS 1:“至少一次”,确保消息可以到达,但消息可能会重复。

QoS 2:“只有一次”,确保消息只到达一次。例如,这个等级可用在一个计费系统中,这里如果消息重复或丢失会导致不正确的收费。

5、小型传输,开销很小(固定长度的头部是 2 字节),协议交换最小化,以降低网络流量;

6、使用 Last Will 和 Testament 特性通知有关各方客户端异常中断的机制;

在MQTT协议中,一个MQTT数据包由:固定头(Fixed header)、 可变头(Variable header)、 消息体(payload)三部分构成。MQTT的传输格式非常精小,最小的数据包只有2个bit,且无应用消息头。

发布和订阅模型

MQTT 协议在网络中定义了两种实体类型:一个消息代理和一些客户端。代理是一个服务器,它从客户端接收所有消息,然后将这些消息路由到相关的目标客户端。客户端是能够与代理交互来发送和接收消息的任何事物。客户端可以是现场的 IoT 传感器,或者是数据中心内处理 IoT 数据的应用程序。

  1. 客户端连接到代理。它可以订阅代理中的任何消息 “主题”。此连接可以是简单的 TCP/IP 连接,也可以是用于发送敏感消息的加密 TLS 连接。
  2. 客户端通过将消息和主题发送给代理,发布某个主题范围内的消息。
  3. 代理然后将消息转发给所有订阅该主题的客户端。

因为 MQTT 消息是按主题进行组织的,所以应用程序开发人员能灵活地指定某些客户端只能与某些消息交互。例如,传感器将在 “sensor_data” 主题范围内发布读数,并订阅 “config_change” 主题。将传感器数据保存到后端数据库中的数据处理应用程序会订阅 “sensor_data” 主题。管理控制台应用程序能接收系统管理员的命令来调整传感器的配置,比如灵敏度和采样频率,并将这些更改发布到 “config_change” 主题。

IoT 传感器的 MQTT 发布和订阅模型

同时,MQTT 是轻量级的。它有一个用来指定消息类型的简单标头,有一个基于文本的主题,还有一个任意的二进制有效负载。应用程序可对有效负载采用任何数据格式,比如 JSON、XML、加密二进制或 Base64,只要目标客户端能够解析该有效负载。

MQTT 开发入门

  • 阿里loT平台添加产品设备——下面我们介绍一下如何用一个MQTT的工具接入阿里IoT平台:

lot平台创建产品设备:

1.先注册登录阿里云,再开通阿里云物联网平台

https://dev.iot.aliyun.com/sale?source=deveco_partner_chenlin

复制链接到浏览器(如果没有阿里云账号,注册后再次复制进入,点击“开通”)

扫码也可以开通

注册:单击免费注册或者使用第三方淘宝、支付宝、钉钉、1688、微博授权登录,但是第三方登录也需要进行再次注册,并且进行实名认证。

2.开通后,进入管理控制台,若回到主页面,可重新复制平台链接进入或从首页右上角的侧边菜单栏—产品—物联网—物联网设备接入/物联网设备管理进入管理控制台

左侧导航栏选择设备管理—产品,单击创建产品

3.新建产品,第一步:选择版本类型,这里我们选择基础版作为演示,单击下一步

4.新建产品,第二步:填写产品信息,完成要创建的产品参数设置,单击完成。

页面参数设置如下:

参数

描述

产品名称

为产品命名。产品名称在账号内具有唯一性。例如,可以填写为产品型号。支持中文、英文字母、数字和下划线,长度限制4~30,一个中文汉字算2位。

节点类型

设备或网关。

o 设备:指不能挂载子设备的设备。这种设备可以直连物联网平台,也可以作为网关的子设备连接物联网平台。

o 网关:指可以挂载子设备的直连设备。网关具有子设备管理模块,维持子设备的拓扑关系,并且可以将拓扑关系同步到云端。

产品描述

输入文字,用以描述产品。字数限制为100。

创建成功后如图:

5.在左侧导航栏选择设备管理—设备中选择刚创建好的产品。然后,点击添加设备选择后,新创建的设备将继承该产品定义好的功能和特性。(可选)填入DeviceName,如果不填,系统将自动生成一个DeviceName,用以标识设备。

6.单击确认,完成设备创建。

设备创建完成后,将自动弹出 查看设备证书弹框。您可以查看、复制设备证书信息。设备证书又名 设备三元组,由设备 ProductKey、DeviceName、和 DeviceSecret组成,是设备与物联网平台进行通信的重要身份认证,建议您妥善保管。

ProductKey:物联网平台为您创建的产品颁发的全局唯一标识符。

DeviceName:设备在产品内的唯一标识符,用于设备认证和通信。(用户自定义,或系统自动颁发)

DeviceSecret:物联网平台为设备颁发的设备秘钥,用于认证加密,需与DeviceName成对使用。

7.单击已创建设备对应操作栏中的查看,进入设备详情页面,查看设备详情。在 设备信息页签下,单击实时延迟后的 测试,查看您设备的网络延迟情况。

使用MQTTfx工具连接

下载mqttfx工具

http://mqttfx.bceapp.com/

  • 双击打开mqttfx.exe

2.单击Extras,选择Edit Connection Profies

3.打开后,设置详细参数

(1)Proflie Name:是已创建产品的DeviceName(直接复制)

(2)BrokerAddress:

YourProductKey.iot-as-mqtt.cn-shanghai.aliyuncs.com,

”YourProductKey”请替换为您的ProductKey(直接复制)

(3)BrokerPort:设置为1883

(4)Client ID(mqtt):

ClientID(mqtt)=clientId(sn)+"|securemode=3,signmethod=hmacsha1,timestamp=12345|"

clientId:表示客户端ID,建议mac或sn,64字符内。(用户自定义,需要唯一性)

timestamp:表示当前时间毫秒值,可选

mqttClientId:格式中||内为扩展参数。

signmethod:表示签名算法类型。(阿里云平台的加签方式是hmacsha1

securemode:表示目前安全模式,可选值有2 (wss协议)和3(ws协议)。

例子:

ClientID(mqtt)为

121212|securemode=3,signmethod=hmacsha1,timestamp=12345|

(5)User Name:User Name =DeviceName+"&"+ProductKey

例子:DAJTve67hNZPrOWMiyBb&a1umjZBeOYM

(6)Passwordhttp://tool.oschina.net/encrypt?type=2

打开链接,Password加签过程见下图,最终在mqttfx的Password填入下图加签后的password

明文:clinetId+Id值+deviceName+Name名+productKey+Key值+timestamp+time值;

选择HmacSHA1的加签方式,在密钥中输入DeviceSecret的值,单击哈希/散列获得的哈希值即用户密码Password。

4.设置完毕,单击Apply

5.单击Connect,绿色圆圈代表连接成功,红色圆圈代表连接失败,用户名或者密码有错误

6.返回管理控制台,可查看设备管理—设备列表—当前设备状态(是否在线),在线说明设备接入成功,未激活说明设备接入还未成功

三、订阅

1.选择设备管理—设备—设备列表—查看,进入设备详情页

2.进入到Topic列表界面,会自动生成这几个Topic

发布指的是设备发送到平台;

订阅是平台发送给设备。

四、创建或者编辑Topic

1.选择设备管理—产品—产品列表—查看,进入产品详情页

2.在产品详情页中,进入到Topic类列表界面

3.单击定义Topic类,新建Topic类,自定义名字

4.单击确认后,进入产品Topic类列表,能看到刚刚新建的Topic类(test)

5.选择设备管理—设备—设备列表—查看—Topic列表,在mqtt客户端订阅Topic

五、mqtt客户端订阅iot平台Topic

1.双击打开mqtt客户端,单击Connect连接平台

2.连接成功后,在Subscribe中输入订阅的topic,单击Subscribe,确认订阅

3.回到设备的Topic列表,选择发布消息

4.选择发布消息,输入消息内容(自定义)

*Quality of Service等级是发送与接收端的一种关于保证交付信息的协议。一共有3 个QoS 等级:

1.最多一次(0)

2.最少一次(1)

3.只一次(2)

这里使用0或者1都可以

5.单击确认后,在mqtt客户端收到平台下发的消息

六、mqtt客户端发信息到iot平台

选择Publish,输入在iot平台上新建的发布消息的Topic,因为平台暂时只支持查看qos为1时候的数据,这里选择1,然后输入要发送给iot平台的信息,点击Publish发送

MQTT 协议

MQTT 是一种连接协议,它指定了如何组织数据字节并通过 TCP/IP 网络传输它们。但实际上,开发人员并不需要了解这个连接协议。我们只需要知道,每条消息有一个命令和数据有效负载。该命令定义消息类型(例如 CONNECT 消息或 SUBSCRIBE 消息)。所有 MQTT 库和工具都提供了直接处理这些消息的简单方法,并能自动填充一些必需的字段,比如消息和客户端 ID。

首先,客户端发送一条 CONNECT 消息来连接代理。CONNECT 消息要求建立从客户端到代理的连接。CONNECT 消息包含以下内容参数。

表 1. CONNECT 消息参数

参数

说明

cleanSession

此标志指定连接是否是持久性的。持久会话会将所有订阅和可能丢失的消息(具体取决于 QoS) 都存储在代理中。(请参阅 表 3 获取 QoS 的描述。)

username

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

password

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

lastWillTopic

连接意外中断时,代理会自动向某个主题发送一条 “last will” 消息。

lastWillQos

“last will” 消息的 QoS。(请参阅 表 3 来查看 QoS 的描述。)

lastWillMessage

“last will” 消息本身。

keepAlive

这是客户端通过 ping 代理来保持连接有效所需的时间间隔。

客户端收到来自代理的一条 CONNACK 消息。CONNACK 消息包含以下内容参数。

表 2. CONNACK 消息参数

参数

说明

sessionPresent

此参数表明连接是否已有一个持久会话。也就是说,连接已订阅了主题,而且会接收丢失的消息。

returnCode

0 表示成功。其他值指出了失败的原因。

建立连接后,客户端然后会向代理发送一条或多条 SUBSCRIBE 消息,表明它会从代理接收针对某些主题的消息。消息可以包含一个或多个重复的参数。如表 3。

表 3. SUBSCRIBE 消息参数

参数

说明

qos

qos(服务质量或 QoS)标志表明此主题范围内的消息传送到客户端所需的一致程度。

  • 值 0:不可靠,消息基本上仅传送一次,如果当时客户端不可用,则会丢失该消息。
  • 值 1:消息应传送至少 1 次。
  • 值 2:消息仅传送一次。

topic

要订阅的主题。一个主题可以有多个级别,级别之间用斜杠字符分隔。例如,“dw/demo” 和 “ibm/bluemix/mqtt” 是有效的主题。

客户端成功订阅某个主题后,代理会返回一条 SUBACK 消息,其中包含一个或多个 returnCode 参数。

表 4. SUBACK 消息参数

参数

说明

returnCode

SUBCRIBE 命令中的每个主题都有一个返回代码。返回值如下所示。

  • 值 0 - 2:成功达到相应的 QoS 级别。(参阅 表 3 进一步了解 QoS。)
  • 值 128:失败。

与 SUBSCRIBE 消息对应,客户端也可以通过 UNSUBSCRIBE 消息取消订阅一个或多个主题。

表 5. UNSUBSCRIBE 消息参数

参数

说明

topic

此参数可重复用于多个主题。

客户端可向代理发送 PUBLISH 消息。该消息包含一个主题和数据有效负载。代理然后将消息转发给所有订阅该主题的客户端。

表 6. PUBLISH 消息参数

参数

说明

topicName

发布的消息的相关主题。

qos

消息传递的服务质量水平。(请参阅 表 3 来查看 QoS 的描述。)

retainFlag

此标志表明代理是否保留该消息作为针对此主题的最后一条已知消息。

payload

消息中的实际数据。它可以是文本字符串或二进制大对象数据。

技巧和解决方法

MQTT 的优势在于它的简单性。在可以使用的主题类型或消息有效负载上没有任何限制。这支持一些有趣的用例。例如,请考虑以下问题:

如何使用 MQTT 发送 1-1 消息?双方可以协商使用一个特定于它们的主题。例如,主题名称可以包含两个客户端的 ID,以确保它的唯一性。

客户端如何传输它的存在状态?系统可以为 “presence” 主题协商一个命名约定。例如,“presence/client-id” 主题可以拥有客户端的存在状态信息。当客户端建立连接时,将该消息被设置为 true,在断开连接时,该消息被设置为 false。客户端也可以将一条 last will 消息设置为 false,以便在连接丢失时设置该消息。代理可以保留该消息,让新客户端能够读取该主题并找到存在状态。

如何保护通信?客户端与代理的连接可以采用加密 TLS 连接,以保护传输中的数据。此外,因为 MQTT 协议对有效负载数据格式没有任何限制,所以系统可以协商一种加密方法和密钥更新机制。在这之后,有效负载中的所有内容可以是实际 JSON 或 XML 消息的加密二进制数据。

点击 阅读原文,开通阿里云IoT平台,每个月免费使用100万条消息

相关文章