物聯(lián)網(wǎng) (IoT) 設備必須連接互聯(lián)網(wǎng)。通過(guò)連接到互聯(lián)網(wǎng),設備就能相互協(xié)作,以及與后端服務(wù)協(xié)同工作;ヂ(lián)網(wǎng)的基礎網(wǎng)絡(luò )協(xié)議是 TCP/IP。MQTT(消息隊列遙測傳輸) 是基于 TCP/IP 協(xié)議棧而構建的,已成為 IoT 通信的標準。 MQTT 最初由 IBM 于上世紀 90 年代晚期發(fā)明和開(kāi)發(fā)。它最初的用途是將石油管道上的傳感器與衛星相鏈接。顧名思義,它是一種支持在各方之間異步通信的消息協(xié)議。異步消息協(xié)議在空間和時(shí)間上將消息發(fā)送者與接收者分離,因此可以在不可靠的網(wǎng)絡(luò )環(huán)境中進(jìn)行擴展。雖然叫做消息隊列遙測傳輸,但它與消息隊列毫無(wú)關(guān)系,而是使用了一個(gè)發(fā)布和訂閱的模型。在 2014 年末,它正式成為了一種 OASIS 開(kāi)放標準,而且在一些流行的編程語(yǔ)言中受到支持(通過(guò)使用多種開(kāi)源實(shí)現)。 為何選擇 MQTT MQTT 是一種輕量級的、靈活的網(wǎng)絡(luò )協(xié)議,致力于為 IoT 開(kāi)發(fā)人員實(shí)現適當的平衡: 1、這個(gè)輕量級協(xié)議可在嚴重受限的設備硬件和高延遲/帶寬有限的網(wǎng)絡(luò )上實(shí)現。 2、它的靈活性使得為 IoT 設備和服務(wù)的多樣化應用場(chǎng)景提供支持成為可能。 為了了解為什么 MQTT 如此適合 IoT 開(kāi)發(fā)人員,我們首先來(lái)分析一下為什么其他流行網(wǎng)絡(luò )協(xié)議未在 IoT 中得到成功應用。 為什么不選擇HTTP 大多數開(kāi)發(fā)人員已經(jīng)熟悉 HTTP Web 服務(wù)。那么為什么不讓 IoT 設備連接到 Web 服務(wù)?設備可采用 HTTP 請求的形式發(fā)送其數據,并采用 HTTP 響應的形式從系統接收更新。這種請求和響應模式存在一些嚴重的局限性: 1、HTTP 是一種同步協(xié)議?蛻(hù)端需要等待服務(wù)器響應。Web 瀏覽器具有這樣的要求,但它的代價(jià)是犧牲了可伸縮性。在 IoT 領(lǐng)域,大量設備以及很可能不可靠或高延遲的網(wǎng)絡(luò )使得同步通信成為問(wèn)題。異步消息協(xié)議更適合 IoT 應用程序。傳感器發(fā)送讀數,讓網(wǎng)絡(luò )確定將其傳送到目標設備和服務(wù)的最佳路線(xiàn)和時(shí)間。 2、HTTP 是單向的?蛻(hù)端必須發(fā)起連接。在 IoT 應用程序中,設備或傳感器通常是客戶(hù)端,這意味著(zhù)它們無(wú)法被動(dòng)地接收來(lái)自網(wǎng)絡(luò )的命令。 3、HTTP 是一種 1-1 協(xié)議?蛻(hù)端發(fā)出請求,服務(wù)器進(jìn)行響應。將消息傳送到網(wǎng)絡(luò )上的所有設備上,不但很困難,而且成本很高,而這是 IoT 應用程序中的一種常見(jiàn)使用情況。 4、HTTP 是一種有許多標頭和規則的重量級協(xié)議。它不適合受限的網(wǎng)絡(luò )。 HTTP協(xié)議的兩個(gè)過(guò)程,Request和Response,兩個(gè)都有各自的語(yǔ)言格式,我們看下是什么。 請求報文格式:(注意這里有個(gè)換行) 響應報文格式:(注意這里有個(gè)換行) 方法method: 這個(gè)很重要,比如說(shuō)GET和POST方法,這兩個(gè)是很常用的,GET就是獲取什么內容,而POST就是向服務(wù)器發(fā)送什么數據。當然還有其他的,比如HTTP 1.1中還有:DELETE、PUT、CONNECT、HEAD、OPTIONS、TRACE等一共8個(gè)方法(HTTP Method歷史:HTTP 0.9 只有GET方法;HTTP 1.0 有GET、POST、HEAD三個(gè)方法)。 請求URL: 這里填寫(xiě)的URL是不包含IP地址或者域名的,是主機本地文件對應的目錄地址,所以我們一般看到的就是“/”。 版本version: 格式是HTTP/ 狀態(tài)碼status: 狀態(tài)碼是三個(gè)數字,代表的是請求過(guò)程中所發(fā)生的情況,比如說(shuō)200代表的是成功,404代表的是找不到文件。 原因短語(yǔ)reason-phrase: 是狀態(tài)碼的可讀版本,狀態(tài)碼就是一個(gè)數字,如果你事先不知道這個(gè)數字什么意思,可以先查看一下原因短語(yǔ)。 首部header: 注意這里的header我們不是叫做頭,而是叫做首部?赡苡辛銈(gè)首部也可能有多個(gè)首部,每個(gè)首部包含一個(gè)名字后面跟著(zhù)一個(gè)冒號,然后是一個(gè)可選的空格,接著(zhù)是一個(gè)值,然后換行。 實(shí)體的主體部分entity-body: 實(shí)體的主體部分包含一個(gè)任意數據組成的數據塊,并不是所有的報文都包含實(shí)體的主體部分,有時(shí)候只是一個(gè)空行加換行就結束了。 下面我們舉個(gè)簡(jiǎn)單的例子: 請求報文: GET /index.html HTTP/1.1 Accept: text/* Host: www.myweb.com 響應報文: HTTP/1.1 200 OK Content-type: text/plain Content-length: 3 出于上述原因,大部分高性能、可擴展的系統都使用異步消息總線(xiàn)來(lái)進(jìn)行內部數據交換,而不使用 Web 服務(wù)。事實(shí)上,企業(yè)中間件系統中使用的最流行的消息協(xié)議被稱(chēng)為 AMQP(高級消息排隊協(xié)議)。但是,在高性能環(huán)境中,計算能力和網(wǎng)絡(luò )延遲通常不是問(wèn)題。AMQP 致力于在企業(yè)應用程序中實(shí)現可靠性和互操作性。它擁有龐大的特性集,但不適合資源受限的 IoT 應用程序。 除了 AMQP 之外,還有其他流行的消息協(xié)議。例如,XMPP(Extensible Messaging and Presence Protocol,可擴展消息和狀態(tài)協(xié)議)是一種對等即時(shí)消息 (IM) 協(xié)議。它高度依賴(lài)于支持 IM 用例的特性,比如存在狀態(tài)和介質(zhì)連接。與 MQTT 相比,它在設備和網(wǎng)絡(luò )上需要的資源都要多得多。 那么,MQTT 為什么如此輕量且靈活?MQTT 協(xié)議的一個(gè)關(guān)鍵特性是發(fā)布和訂閱模型。與所有消息協(xié)議一樣,它將數據的發(fā)布者與使用者分離。 它具有以下主要的幾項特性: 1、使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布和應用程序之間的解耦; 2、消息傳輸不需要知道負載內容; 3、使用 TCP/IP 提供網(wǎng)絡(luò )連接; 4、有三種消息發(fā)布的服務(wù)質(zhì)量: QoS 0:“最多一次”,消息發(fā)布完全依賴(lài)底層 TCP/IP 網(wǎng)絡(luò )。分發(fā)的消息可能丟失或重復。例如,這個(gè)等級可用于環(huán)境傳感器數據,單次的數據丟失沒(méi)關(guān)系,因為不久后還會(huì )有第二次發(fā)送。 QoS 1:“至少一次”,確保消息可以到達,但消息可能會(huì )重復。 QoS 2:“只有一次”,確保消息只到達一次。例如,這個(gè)等級可用在一個(gè)計費系統中,這里如果消息重復或丟失會(huì )導致不正確的收費。 5、小型傳輸,開(kāi)銷(xiāo)很。ü潭ㄩL(cháng)度的頭部是 2 字節),協(xié)議交換最小化,以降低網(wǎng)絡(luò )流量; 6、使用 Last Will 和 Testament 特性通知有關(guān)各方客戶(hù)端異常中斷的機制;在MQTT協(xié)議中,一個(gè)MQTT數據包由:固定頭(Fixed header)、 可變頭(Variable header)、 消息體(payload)三部分構成。MQTT的傳輸格式非常精小,最小的數據包只有2個(gè)bit,且無(wú)應用消息頭。 發(fā)布和訂閱模型 MQTT 協(xié)議在網(wǎng)絡(luò )中定義了兩種實(shí)體類(lèi)型:一個(gè)消息代理和一些客戶(hù)端。代理是一個(gè)服務(wù)器,它從客戶(hù)端接收所有消息,然后將這些消息路由到相關(guān)的目標客戶(hù)端?蛻(hù)端是能夠與代理交互來(lái)發(fā)送和接收消息的任何事物?蛻(hù)端可以是現場(chǎng)的 IoT 傳感器,或者是數據中心內處理 IoT 數據的應用程序。 1、客戶(hù)端連接到代理。它可以訂閱代理中的任何消息 “主題”。此連接可以是簡(jiǎn)單的 TCP/IP 連接,也可以是用于發(fā)送敏感消息的加密 TLS 連接。 2、客戶(hù)端通過(guò)將消息和主題發(fā)送給代理,發(fā)布某個(gè)主題范圍內的消息。 3、代理然后將消息轉發(fā)給所有訂閱該主題的客戶(hù)端。 因為 MQTT 消息是按主題進(jìn)行組織的,所以應用程序開(kāi)發(fā)人員能靈活地指定某些客戶(hù)端只能與某些消息交互。例如,傳感器將在 “sensor_data” 主題范圍內發(fā)布讀數,并訂閱 “config_change” 主題。將傳感器數據保存到后端數據庫中的數據處理應用程序會(huì )訂閱 “sensor_data” 主題。管理控制臺應用程序能接收系統管理員的命令來(lái)調整傳感器的配置,比如靈敏度和采樣頻率,并將這些更改發(fā)布到 “config_change” 主題。 IoT 傳感器的 MQTT 發(fā)布和訂閱模型 同時(shí),MQTT 是輕量級的。它有一個(gè)用來(lái)指定消息類(lèi)型的簡(jiǎn)單標頭,有一個(gè)基于文本的主題,還有一個(gè)任意的二進(jìn)制有效負載。應用程序可對有效負載采用任何數據格式,比如 JSON、XML、加密二進(jìn)制或 Base64,只要目標客戶(hù)端能夠解析該有效負載。 MQTT 開(kāi)發(fā)入門(mén) 下面我們介紹一下如何利用北京奇跡物聯(lián)的AM20E模組實(shí)現MQTT協(xié)議接入阿里IoT平臺。AM20E 是一款超小封裝 NB-IoT 工業(yè)級無(wú)線(xiàn)通訊模塊。內置多種協(xié)議棧TCP/IP,HTTP,MQTT等,本文我們使用其MQTT協(xié)議接入阿里的IoT平臺,實(shí)現數據的上下行。 注冊阿里云物聯(lián)網(wǎng)平臺 注冊阿里云https://account.aliyun.com 注意:需要注冊后實(shí)名認證才可以進(jìn)入“物聯(lián)網(wǎng)平臺”(更名前叫物聯(lián)網(wǎng)開(kāi)發(fā)套件),操作中有任何問(wèn)題可以從阿里云的技術(shù)支持找到對應文檔查看。 ![]() 注冊后選擇物聯(lián)網(wǎng)平臺 ![]() 在控制臺后創(chuàng )建產(chǎn)品 ![]() 點(diǎn)擊創(chuàng )建產(chǎn)品 ![]() 創(chuàng )建完成產(chǎn)品,點(diǎn)擊查看 ![]() 點(diǎn)擊前往管理 ![]() 點(diǎn)擊添加設備 ![]() 添加完成設備后,將此三個(gè)信息記錄下來(lái) ![]() 在此界面,點(diǎn)擊功能定義 ![]() 在功能定義界面,新增功能 ![]() 在消息通信界面,查看Topic,這些Topic我們后期調試會(huì )用到 ![]() 暫時(shí)用到的兩個(gè)Topic,為 /sys/a1cn4I14cE9/${deviceName}/thing/event/property/post 設備屬性上報 /sys/a1cn4I14cE9/${deviceName}/thing/service/property/set 設備屬性設置 經(jīng)過(guò)上面的準備,可以開(kāi)始調試AM20E與在阿里云建立的設備上傳下發(fā)數據了。 AM20E連接阿里云 阿里云建立的設備信息: product_key: a1cn4I14cE9 device_name: AM20E00101 device_secret: xL7bM8oKmfOnM6wk9bwNsylJSOQW9kDD 連接流程如下: AT+CSQ +CSQ: 31,99 OK AT+CPIN? +CPIN:READY OK AT+CREG? +CREG: 0,1 OK AT+XIIC=1 OK AT+IMQTTAUTH="a1cn4I14cE9","AM20E00101","xL7bM8oKmfOnM6wk9bwNsylJSOQW9kDD" OK //發(fā)送鑒權信息 AT+IMQTTPARA="TIMEOUT",2 //設置參數 OK +IMQTTAUTH:OK AT+IMQTTCONN //連接 OK AT+IMQTTSUB="/sys/a1cn4I14cE9/AM20E00101/thing/event/property/post",2 +IMQTTSUB:1 OK +IMQTTSUB:1,2 //訂閱一個(gè)topic AT+IMQTTPUBS="/sys/a1cn4I14cE9/AM20E00101/thing/event/property/post",1,"{\"id\":\"789\",\"version\":\"1.0\",\"params\":{\"PM25\":25},\"method\":\"thing.event.property.post\"}" +IMQTTPUB:2 OK +IMQTTPUB:2,0 +IMQTTRCVPUB:46438,/sys/a1cn4I14cE9/AM20E00101/thing/event/property/post,86,{"id":"789","version":"1.0","params":{"PM25":25},"method":"thing.event.property.post"} //發(fā)送數據 ![]() AT+IMQTTSUB="/a1cn4I14cE9/AM20E00101/user/get",2 +IMQTTSUB:3 OK +IMQTTSUB:3,2 //訂閱下行的topic,并通過(guò)該topic下發(fā)數據 ![]() +IMQTTRCVPUB:0,/a1cn4I14cE9/AM20E00101/user/get,6,123456 //收到的數據 AT+IMQTTDISCONN //斷開(kāi)連接 OK 技巧和解決方法 MQTT 的優(yōu)勢在于它的簡(jiǎn)單性。在可以使用的主題類(lèi)型或消息有效負載上沒(méi)有任何限制。這支持一些有趣的用例。例如,請考慮以下問(wèn)題: 如何使用 MQTT 發(fā)送 1-1 消息?雙方可以協(xié)商使用一個(gè)特定于它們的主題。例如,主題名稱(chēng)可以包含兩個(gè)客戶(hù)端的 ID,以確保它的唯一性。 客戶(hù)端如何傳輸它的存在狀態(tài)?系統可以為 “presence” 主題協(xié)商一個(gè)命名約定。例如,“presence/client-id” 主題可以擁有客戶(hù)端的存在狀態(tài)信息。當客戶(hù)端建立連接時(shí),將該消息被設置為 true,在斷開(kāi)連接時(shí),該消息被設置為 false?蛻(hù)端也可以將一條 last will 消息設置為 false,以便在連接丟失時(shí)設置該消息。代理可以保留該消息,讓新客戶(hù)端能夠讀取該主題并找到存在狀態(tài)。 如何保護通信?客戶(hù)端與代理的連接可以采用加密 TLS 連接,以保護傳輸中的數據。此外,因為 MQTT 協(xié)議對有效負載數據格式?jīng)]有任何限制,所以系統可以協(xié)商一種加密方法和密鑰更新機制。在這之后,有效負載中的所有內容可以是實(shí)際 JSON 或 XML 消息的加密二進(jìn)制數據。 |