本系列文章旨在補充《超圖解物聯網IoT實作入門》,採用Arduino、ESP8266和Node.js實作MQTT物聯網通訊實驗。
MQTT是由IBM的Andy Stanford-Clark博士和Arcom(已更名為Eurotech)的Arlen Nipper博士於1999年發明的通訊協定。他們當時是為了在狹窄的網路頻寬和微小電力損耗的需求前提之下,提供石油管線感測器和人造衛星之間一個輕量、可靠的二進制通訊協定。2011年11月,IBM和Eurotech將MQTT協定捐贈給負責管理開放原始碼專案的Eclipse基金會,並且加入Eclipse M2M Industry工作組織。2014年十月,MQTT正式變成一個開放的OASIS國際標準(Organization Advancement Structured Information Standards,資訊標準架構促進會,一個制定電子商務、網路服務和電子出版的非營利機構)。
MQTT最初代表的意思是Message Queueing Telemetry Transport(訊息佇列遙測傳輸),現在已經不用這種說法,MQTT就是MQTT,不是其他單字的縮寫。由於MQTT協定的訊息內容很精簡,非常適合用於處理器資源及網路頻寬有限的物聯網裝置,再加上已經有許多MQTT程式庫被陸續開發出來,用於Arduino控制板(C/C++)、JavaScript(Node.js, Espruino控制板), Python,…等等,還有開放原始碼的MQTT伺服器,使得開發MQTT物聯網、機器之間(Machine-to-Machine, M2M)的通訊變得非常簡單。Facebook Messenger的即時通訊也是用MQTT協定。
採用Arduino和ESP8266實作MQTT之前,本文先提供有關MQTT的背景知識和一些術語說明。
比較HTTP和MQTT通訊協定
MQTT和HTTP的底層都是TCP/IP,也就是物聯網裝置可以沿用既有的網路架構和設備,只是在網路上流通的「訊息格式」以及應用程式的處理機制不同。
假設某個裝置透過Web瀏覽器,以HTTP協定傳送溫度值給網站伺服器,此HTTP POST訊息內容大概像這樣:
除了HTTP請求指令以及代表21度的訊息本體,這段訊息中間夾帶了一堆描述用戶端的的標頭(header)資訊,相當於向伺服器介紹:我來自Chrome瀏覽器、作業系統是Android 7、我讀懂中文和英文…等等。這些額外的標頭訊息在許多物聯網通訊應用不僅僅是多餘的,還會佔用網路頻寬、記憶體並且浪費處理時間。
MQTT訊息格式
採用MQTT發布溫度的訊息格式類似這樣:
不同於HTTP的標頭採用文字描述,MQTT的標頭採用數字編碼,整個長度只佔2位元組,等同兩個字元,後面跟著訊息的主題(topic)和內容(payload),實際格式如下:
MQTT標頭裡的訊息類型、品質…等內容,留待下文說明。除了精簡的標頭,讀者可以發現,MQTT的標頭區並沒有標示傳送目標的IP位址。
MQTT的Publisher, Broker和Subscriber
根據MQTT 3.1.1版本規格書的描述,MQTT是一種基於「發布∕訂閱」機制的訊息傳輸協定(MQTT is a Client Server publish/subscribe messaging transport protocol),我們可以把它想成雜誌發行和訂閱的機制。MQTT訊息發送端,相當於雜誌出版社,雜誌出版之後並不直接寄給消費者,而是交給經銷商或者書店一般的代理人(broker),來統籌管理發行和訂閱事宜。每一個訊息來源(刊物)都有個唯一的主題名稱(刊物名稱)。
代理人是個伺服器軟體,向伺服器發送主題的一方是發布者(publisher),從伺服器獲取主題的一方則是訂閱者(subscriber)。以下圖為例,傳送感測器資料的一邊是發布者,接收感測器資料的一邊則是訂閱者。每個感測器∕微控器的訊息都需要有個主題名稱以利識別,像下圖的主題A、B和C。
代理人(broker)可儲存發布者的訊息,在發布者中斷連線的情況下,提供訂閱者最近更新的訊息。「訂閱者」需要告知代理人想要訂閱的主題,每當「發布者」傳入新訊息時,代理人就會依照主題,傳送給所有訂閱者。「發布者」和「訂閱者」都是用戶端,代理人是伺服器。由於兩個用戶端之間有伺服器當作中繼站,所以兩邊並不需要知道彼此的IP位址。
MQTT的主題(Topic)名稱
MQTT主題名稱是UTF-8(萬國碼)編碼的字串,我們可以自行決定主題名稱,例如,傳送溫度的訊息主題可命名成「溫度」、傳送亮度的訊息主題叫做「照度」…等等。主題名稱也支援類似檔案路徑的階層式命名方式,假設住家裡面有許多感測器,我們可依照測器所在位置,規劃如下的命名階層結構:
每個階層之間用斜線分隔,例如,位於庭院的人體感測器#1,其主題名稱可命名為:
命名主題的注意事項:
- 由於某些微控器或程式語言不支援UTF-8編碼或中文,主題名稱請使用英文,並且取個有意義的名字。
- 名稱長度不可超過216位元組(65536個字元)。
- 自訂的主題名稱請勿用$開頭(“$SYS”是MQTT伺服器的控制介面主題的保留字),也不可包含#和+字元;減號和乘號(*)在程式語言中有特殊意義,為了避免誤會,也不建議使用。
- 名稱的英文大小寫有區別,home和Home是兩個不同的名稱。
- 雖然名稱可以包含空格,但是英文的「半形」空格和中文的「全形」空格的內碼不一樣,若輸入名稱時沒有統一,會導致程式讀取不到,因此名稱最好不要加入空格。
- 階層名稱可以空白,像這樣的命名(連續的斜線)是合法的:“home//yard”,代表有三個階層,中間階層沒有名字,在語意上怪怪的。
- 有些程式設計師習慣在主題名稱最前面加上一個斜線(在Linux系統中,檔案路徑開頭的斜線代表根目錄),但這是不必要的。請注意,“/home”和“home”是兩個不同的名稱,前者代表「空白名稱的根階層」底下的“home”,單一個“/”也是合法的名稱。
除了依據裝置安裝地點來命名主題,當同一個地點包含許多感測器的時候,用編號或者唯一識別碼來命名主題是比較合理的選擇。例如,假設某個位於廚房的裝置的MAC位址是DEADBEEFFEED,它可以被命名成:
Home/kitchen/DEADBEEFFEED
延伸閱讀
- HiveMQ公司的MQTT Essentials系列文件
最近越來越常聽到MQTT這個通訊協定了~~~看完了這篇文章, 也對MQTT產生了一些興趣了~~~
看來又要花一些時間架個server來玩玩看了~~~
很棒的文章,讓我對MQTT有初步的了解…感恩。
不客氣 🙂
thanks,
jeffrey
老師非常謝謝你, 提供這麼棒的學習園地
不客氣~其實我不是老師,只是個(懶散的)文字工作者 😛
thanks,
jeffrey
簡單明瞭,謝謝教學
不客氣~
thanks,
jeffrey
感謝你 簡單扼要
不客氣~
thanks,
jeffrey
thank you sir
no q~
帶領初學者 淺顯易懂 3Q
對沒有技術背景的我超容易吸收的教材啦~ 謝謝版主~
不客氣~
感謝老師,讓我輕易了解MQTT的架構及優勢劣勢
不客氣~
thanks,
jeffrey
感謝老師的分享
不客氣~
趙老師您好:
想請教一下,發布者與訂閱者,兩者同為用戶端,所以他們可以隨時互換身分嗎?
一個MQTT用戶端可以同時是發布者與訂閱者。
thanks,
jeffrey
感謝,這是我查到寫的最詳盡的文章
請問圖可以讓我拿來做內部報告使用嗎?我會附上資料來源 謝謝
沒問題,感謝告知!
thanks,
jeffrey
MQTT若不是其他單字的縮寫,為何用大寫?
就是一個物聯網技術的名詞,沒有必要在名字上鑽牛角尖。
感謝作者
清晰好懂的文章 尤其插圖做得很是精美 受益良多
謝謝誇獎。
thanks,
jeffrey
同樓上留言
「感謝作者!清晰好懂的文章,尤其插圖做得很是精美,受益良多,再次謝謝!」
不客氣~
您好,我是iCShop的專案工程師負責一系列的IOT專案,日前在撰寫物聯網商品技術文章的時候發現您針對MQTT講解的文章,內容整理得十分詳細易讀性非常高,想在技術文章中引用您對MQTT的介紹與圖文,文中會記載引用出處,不曉得是否方便讓我轉載您的文章。
沒問題,感謝告知!
thanks,
jeffrey
您好:
由於我公司內有技術分享的活動,有看到老師這篇關於MQTT解釋的很詳細,所以想引用圖文,不知是否方便轉載內容,會記載引用出處,謝謝。
沒問題,感謝告知!
thanks,
jeffrey
MQTT最初代表的意思是Message Queueing Telemetry Transport(訊息佇列遙測傳輸)
下面是我查到的~大多寫這樣~
MQTT訊息佇列遙測傳輸(英語:Message Queuing Telemetry Transport)
您再確認看看~
並謝謝您這份資料介紹~^^
您好,mqtt.org網站首頁這樣介紹MQTT:
MQTT is an OASIS standard messaging protocol for the Internet of Things (IoT). It is designed as an extremely lightweight publish/subscribe messaging transport that is ideal for connecting remote devices with a small code footprint and minimal network bandwidth.
MQTT 是用於物聯網 (IoT) 的 OASIS 標準訊息傳遞協議。 它被設計成一種極輕量的發布/訂閱訊息傳輸機制,非常適合連結程式記憶體容量小以及低網路頻寬的遠端設備。
mqtt.org網站的FAQ單元,並沒有提到MQTT是哪些單字的縮寫。
從mqtt.org網站的Getting started單元,可以連結到Introducing the MQTT Protocol – MQTT Essentials: Part 1。
這份教學文件當中的A little bit of history(歷史背景介紹)單元,提到:
The short answer is that MQTT is no longer considered an acronym. MQTT is simply the name of the protocol.
The longer answer is that the former acronym stood for MQ Telemetry Transport.
簡短的回答: MQTT 不再被當作是首字母縮寫。MQTT 單純只是協議的名字。
長一點的說明:MQTT以前代表“MQ Telemetry Transport”(MQ 遙測傳輸)的縮寫。
總之,MQTT就是MQTT,是什麼東東的縮寫並不重要。
就像這篇文章的作者是誰、叫啥名字…對絕大多數人來說,根本不重要。重點的是這篇文章對讀者有沒有幫助,謝謝!
精闢的好文章!
但想請問client如何傳到MQTT到broker?MQTT裡面沒有包含IP的位置
MQTT用戶端彼此不知道對方的IP,但伺服器知道。用戶端連接MQTT伺服器,也要知道伺服器的位址,請參閱:
MQTT教學(四):使用MQTTLens訂閱與發布MQTT訊息
趙老師,我是否可分享您的文章到FB 公開社團,並註明來源出自 趙英傑 老師,我標示轉貼分享。
沒問題,感謝告知,「老師」頭銜就不用了,我只是文字工作者,謝謝!
趙英傑老師您好,我是學校老師,老師MQTT文章寫得非常詳細,可否分享您的文章到本人教學網站超連結,會註明來源出自 趙英傑 老師,感謝。
沒問題,謝謝老師,願阿蝙與您同在!
請問圖文可以讓我引用至專題製作及科展的報告書使用嗎?
我會附上資料來源 謝謝
沒問題,預祝科展順利!
請問賣Arduino控制板, Espruino控制板的這類公司,是否同時也要建置免費的MQTT伺服器供購買板子的人用呢?
通常沒有,因為沒有必然關係。
趙先生您好:
我是Allen,從您的Arduino 互動設計入門(2014)開始研讀,深深覺得做中學真的是最快方法。後來陸續買了5本,到最近的ESP32。感覺獲益良多,最近在撰寫論文有關人臉與手勢辨識部分文章,包括實作部分都有參您的考程式架構再自行改編。另外MQTT講解很詳細,相望能引用參考,並會標明出處,最後感謝您的書籍讓我解惑不少,是很好參考書,雖然網路閱讀方便,但是還是喜歡翻實體書閱讀。
沒問題,預祝論文順利完成!
HI!!您好~
很棒的文章跟內容~~
但忍不住想請問您
您這些圖怎麼做的這麼漂亮??? 用什麼編輯的? 手寫文字是另外使用字型嗎?
很少看到技術文件可以做這麼漂亮~~
實在太水了!!! 圖文並茂~~太優了!!!
謝謝,圖是用Adobe Flash軟體畫的(註:Flash在2015年末更名為Animate CC),關於字型,請參閱這一篇貼文說明(/?p=447)。
《超圖解C語言:用資料結構×演算法突破APCS》書本裡的程式碼字型改用FiraCode(https://github.com/tonsky/FiraCode),中文手寫字型改用「清松手寫體」(https://www.facebook.com/groups/549661292148791)。
哇~~原來是專業技術書籍的作者~~好棒的編排~~
教科書選用~~肯定很棒~~
來買個您出的Python跟 資料結構~~欣賞欣賞!!
實在很棒!!
我也會推薦給學校來當教科書!!
XD
非常感謝!
感謝趙老師,
因為工作關係需要尋找MQTT的介紹, 結果找到這篇圖文並茂, 精簡明瞭的文章, 真是太棒了, 根本做功德 XD
不客氣~
您好:
是否將內容與圖片用於報告使用,會標注來源?
沒問題,感謝告知!