MQTT教學(一):認識MQTT

本系列文章旨在補充《超圖解物聯網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,也就是物聯網裝置可以沿用既有的網路架構和設備,只是在網路上流通的「訊息格式」以及應用程式的處理機制不同。

比較HTTP和MQTT通訊協定

假設某個裝置透過Web瀏覽器,以HTTP協定傳送溫度值給網站伺服器,此HTTP POST訊息內容大概像這樣:

HTTP POST訊息

除了HTTP請求指令以及代表21度的訊息本體,這段訊息中間夾帶了一堆描述用戶端的的標頭(header)資訊,相當於向伺服器介紹:我來自Chrome瀏覽器、作業系統是Android 7、我讀懂中文和英文…等等。這些額外的標頭訊息在許多物聯網通訊應用不僅僅是多餘的,還會佔用網路頻寬、記憶體並且浪費處理時間。

MQTT訊息格式

採用MQTT發布溫度的訊息格式類似這樣:

傳送溫度值的MQTT訊息

不同於HTTP的標頭採用文字描述,MQTT的標頭採用數字編碼,整個長度只佔2位元組,等同兩個字元,後面跟著訊息的主題(topic)內容(payload),實際格式如下:

MQTT訊息格式

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。

MQTT的Publisher, Broker和Subscriber

代理人(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

延伸閱讀

Posts created 467

55 thoughts on “MQTT教學(一):認識MQTT

  1. 最近越來越常聽到MQTT這個通訊協定了~~~看完了這篇文章, 也對MQTT產生了一些興趣了~~~
    看來又要花一些時間架個server來玩玩看了~~~

    1. 不客氣~其實我不是老師,只是個(懶散的)文字工作者 😛

      thanks,
      jeffrey

  2. 趙老師您好:
    想請教一下,發布者與訂閱者,兩者同為用戶端,所以他們可以隨時互換身分嗎?

  3. 同樓上留言
    「感謝作者!清晰好懂的文章,尤其插圖做得很是精美,受益良多,再次謝謝!」

  4. 您好,我是iCShop的專案工程師負責一系列的IOT專案,日前在撰寫物聯網商品技術文章的時候發現您針對MQTT講解的文章,內容整理得十分詳細易讀性非常高,想在技術文章中引用您對MQTT的介紹與圖文,文中會記載引用出處,不曉得是否方便讓我轉載您的文章。

  5. 您好:
    由於我公司內有技術分享的活動,有看到老師這篇關於MQTT解釋的很詳細,所以想引用圖文,不知是否方便轉載內容,會記載引用出處,謝謝。

  6. MQTT最初代表的意思是Message Queueing Telemetry Transport(訊息佇列遙測傳輸)
    下面是我查到的~大多寫這樣~
    MQTT訊息佇列遙測傳輸(英語:Message Queuing Telemetry Transport)
    您再確認看看~
    並謝謝您這份資料介紹~^^

    1. 您好,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,是什麼東東的縮寫並不重要。

      就像這篇文章的作者是誰、叫啥名字…對絕大多數人來說,根本不重要。重點的是這篇文章對讀者有沒有幫助,謝謝!

  7. 精闢的好文章!
    但想請問client如何傳到MQTT到broker?MQTT裡面沒有包含IP的位置

  8. 趙老師,我是否可分享您的文章到FB 公開社團,並註明來源出自 趙英傑 老師,我標示轉貼分享。

    1. 沒問題,感謝告知,「老師」頭銜就不用了,我只是文字工作者,謝謝!

  9. 趙英傑老師您好,我是學校老師,老師MQTT文章寫得非常詳細,可否分享您的文章到本人教學網站超連結,會註明來源出自 趙英傑 老師,感謝。

  10. 請問圖文可以讓我引用至專題製作及科展的報告書使用嗎?
    我會附上資料來源 謝謝

  11. 請問賣Arduino控制板, Espruino控制板的這類公司,是否同時也要建置免費的MQTT伺服器供購買板子的人用呢?

  12. 趙先生您好:
    我是Allen,從您的Arduino 互動設計入門(2014)開始研讀,深深覺得做中學真的是最快方法。後來陸續買了5本,到最近的ESP32。感覺獲益良多,最近在撰寫論文有關人臉與手勢辨識部分文章,包括實作部分都有參您的考程式架構再自行改編。另外MQTT講解很詳細,相望能引用參考,並會標明出處,最後感謝您的書籍讓我解惑不少,是很好參考書,雖然網路閱讀方便,但是還是喜歡翻實體書閱讀。

  13. HI!!您好~
    很棒的文章跟內容~~
    但忍不住想請問您
    您這些圖怎麼做的這麼漂亮??? 用什麼編輯的? 手寫文字是另外使用字型嗎?
    很少看到技術文件可以做這麼漂亮~~

    實在太水了!!! 圖文並茂~~太優了!!!

  14. 哇~~原來是專業技術書籍的作者~~好棒的編排~~
    教科書選用~~肯定很棒~~
    來買個您出的Python跟 資料結構~~欣賞欣賞!!
    實在很棒!!
    我也會推薦給學校來當教科書!!
    XD

  15. 感謝趙老師,
    因為工作關係需要尋找MQTT的介紹, 結果找到這篇圖文並茂, 精簡明瞭的文章, 真是太棒了, 根本做功德 XD

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

Related Posts

Begin typing your search term above and press enter to search. Press ESC to cancel.

Back To Top