物聯網 (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萬條消息

相關文章