大話 IOT 技術(3) -- MQTT篇

文章目錄

    • 前言
    • 前情提要
    • MQTT介紹
    • 組成
    • 萬惡的app
    • mqtt服務端
    • 偽代碼實現
    • 開源的力量
    • 后話

當你迷茫的時候,請點擊 物聯網目錄大綱 快速查看前面的技術文章,相信你總能找到前行的方向

前言

本篇將開始講述IOT技術的一個重點,mqtt協議

我發現有一個物聯網的準則,想分享給大家,名字我都想好了,就叫張氏定理

  1. 手機app端用http協議與服務端(eg.bypass)進行通信

  2. 設備端用mqtt協議與mqtt服務端進行通信

  3. 服務端(eg.bypass)還要能用mqtt協議與mqtt服務端進行通信

這樣,手機到設備的通信鏈路就算是通了起來。

http協議大家早就司空見慣了,它就像是大貨車,能裝的東西種類很多,本身體積也是比較龐大的,適用于手機這種要實現豐富的功能的大款。

mqtt協議是本文的重點講述的對象,它就像小車,輕便簡捷,我們通常用json作為消息體進行傳遞mqtt信息。

下面我們就進入正文吧。

前情提要

上篇(大話 IOT 技術(2) – 配網篇)我們講了配網的流程,不過與本文關系不大,所以,我們還是先回顧一下經典 IOT 整體架構圖

MQTT介紹

本文我還是沿用我們大話系列的精神,用生動的故事形式,來介紹mqtt技術,所以朋友們不用擔心太枯燥和無聊。

先引用官方的一段介紹作為開場白,詳見 https://mqtt.org/mqtt-specification/:

MQTT is an OASIS standard. The specification is managed by the OASIS MQTT Technical Committee.

MQTT(Message Queuing Telemetry Transport)是一種輕量級的消息傳輸協議,它被設計為易于實現,支持所有消息方向的通信,并為遠程通信環境提供必要的網絡優化。

前面講到過,mqtt協議和http協議很像,它們都是物聯網中的基石。

一般所說xx協議直觀理解都是以xx開頭,比如,http協議以http/https 開頭,例如,url 為 http://test.domain.com/aaa

同理,mqtt協議也是以 mqtt/mqtts開頭,例如,mqtt://test.domain.com/bbb,協議具體怎么實現不是本文關注的(偏底層),有興趣的朋友可以自行百度。

我們主要關注mqtt 應用層,主要里面的幾個關鍵術語,mqtt客戶端,mqtt服務端(又叫broker),連接,mqtt消息,主題(topic),發布,訂閱

因為這些和我們工作息息相關,而且已經有開源庫幫我們封裝好了,我們只需要會調用就能實現 IOT 的所有功能。

組成

和眾多C/S架構一樣,由一個 mqtt服務端(server,又叫broker),還有一個或多個 mqtt客戶端(client)組成。

mqtt服務端就像是媽媽,每個客戶端就像是她的孩子,孩子們有心事不會跟其他兄弟姐妹們直接說,都會向媽媽傾訴,由媽媽代為轉述

媽媽是他們的共同點,在第一篇文章中,我們也去找了手機與設備之間的共同點,只要有共同點,那就有通信的可能,這里也是一樣的。

媽媽只是一個中間商,目的還是要實現各客戶端之間的通信

比如:

  1. bypass服務 發送 mqtt消息mqtt服務端,消息是想查詢設備1的狀態(bypass —> mqtt 服務端)

  2. 設備1mqtt服務端獲取消息(訂閱消息),將自己的狀態參數也寫成一個 mqtt消息,發給 mqtt服務端(mqtt 服務端--->設備1設備1 ---> mqtt 服務端

  3. bypass服務mqtt服務端獲取到了設備1的消息(訂閱消息),再進行業務處理,更新在手機端顯示(mqtt 服務端 ---> bypass

這樣,就完成了 bypass服務 與 設備1 之間的通信

同理,bypass服務 與 設備2 之間的通信也是類似。

那么問題又來了,你怎么保證 bypass服務發送的 mqtt消息 一定能被 設備1 收到呢?設備2 會不會偷看消息

真是個 good question,這也就是 mqtt服務端 的職責所在。

萬惡的app

首先,我們來講個題外話

相信大家手機中肯定裝了很多種app,很多萬惡的app在你安裝后就會流氓地要你關注訂閱一些感興趣的頻道,比如,科技,財經,軍事,娛樂…

而它的萬惡是我都感興趣,卻不讓我勾選了,最多只能選幾個,這真的讓人火大,那我一個也不選吧,還不行,你看這整的我只想說一句粗口:……

好吧,我忍了!

于是我手機上多了一個萬惡的app,大概長這樣

有沒有同款的朋友們,請扣1哈

每個關注訂閱的頻道,都會有消息的通知,就像上面那樣,用消息數量顯示,我知道體育頻道沒有消息,我就不會點進去看,我最喜歡的娛樂頻道消息滿天飛,我就會點擊進去瀏覽各種八卦……

雖然萬惡,但其思想與本文要講的 mqtt服務很像,所以我才忍你很久了,曾子曰:“我的忍耐是有限度的……"

上面不經意還是引入了一個mqtt專業術語:訂閱(subscribe),我們再加一個,主題(topic)

訂閱想必大家很好理解,畢竟爛大街的訂閱加關注,一鍵三連……

主題就是上面的興趣頻道

mqtt 中的訂閱主題,就等同于所說的關注訂閱某個頻道,然后巴巴地等著新消息查看。比如汪蘇瀧的演唱會要來深圳了,什么時候開始搶票,他好帥啊……

這個萬惡的app其實就是充當了服務端的身份,管理這些主題,消息動態,而我就是那個可憐巴巴沒有搶到票的弱小客戶端,悲傷不禁逆流成河……

我們豐富一下流程吧

服務端是那個萬惡的app后端服務,客戶端有某科技博主和我。

發布消息過程:某科技博主寫了一篇文章,標注了科技的標簽,提交后,服務端后臺會處理,會在科技頻道新增一篇科技的文章,并返回成功的響應。

訂閱消息過程:我點擊了娛樂消息想要查看,服務端接收到了我的請求,從數據庫中查詢出標簽為娛樂的消息并返回。

mqtt服務端

類似上面的萬惡app,mqtt服務端也是類似,我們來轉變一下上圖:

服務端變成了mqtt 服務端,客戶端有bypass服務和設備

發布消息過程bypass 發布了一個主題為topic1 的消息,mqtt服務端處理發布消息,在topic1新增一條消息,并返回成功的響應。

訂閱消息過程:設備訂閱主題為topic4 的消息,mqtt服務端處理訂閱請求,從主題topic4中獲取其消息并發回給設備,并且客戶端的 on_message方法處理消息。

一般地,主題topic可以設置為含有設備的cid的字符串,更簡單可以用cid 作為主題,既能保證主題唯一,又能方便設備訂閱,這樣每個設備都只需要訂閱與自己 cid 相關的主題。

那么,bypass 可以發送消息到 cid的主題,設備訂閱自己cid 的主題,得到消息后設備再自行處理。

偽代碼實現

上面我們主要關注發布和訂閱的處理,因為這也是mqtt設計的核心,其他的我們可以暫時忽略,如果讓我們自己來設計實現,那我們會怎么做呢?

我認為主要是服務端和客戶端設計實現,首先對它們進行梳理一下

mqtt 服務端

  1. 對客戶端連接的驗證(do_connect),主要校驗賬號密碼或者證書公私鑰是否正確
  2. 管理 topic 對應的消息,用隊列保存/讀取,先入先出
  3. 處理客戶端的發布請求(do_publish
  4. 處理客戶端的訂閱請求(do_subscribe

mqtt 客戶端

  1. 連接服務端(connect),連接結果處理(on_connect
  2. 發布消息(publish
  3. 訂閱消息(subscribe),對消息處理(on_message

在客戶端有 on_connecton_message 是擴展方法,是留給用戶去實現自定義業務邏輯。

那我們很自然地可以定義 mqtt 的兩個類

下面是我自己實現的mqtt完整的代碼,僅僅代表思路的驗證,不可用于實際生產哦

import queueclass MqttBroker:def __init__(self) -> None:self.topic_queue_map = {}@staticmethoddef do_connect(**args):print("broker: do_connect 處理客戶端連接請求")# 做一些賬密或證書公私鑰的驗證,這里簡化一下,直接返回truereturn Truedef do_publish(self, msg: dict):print("broker: do_publish 處理客戶端發布請求")topic=msg.get('topic','')q:queue.Queue=self.topic_queue_map.get(topic,queue.Queue())q.put(msg)self.topic_queue_map[topic]=qreturn Truedef do_subscribe(self, topic: str):print("broker: do_subscribe 處理客戶端訂閱請求")q:queue.Queue=self.topic_queue_map.get(topic,queue.Queue())return qclass MqttClient:def __init__(self) -> None:self.conn: MqttBroker = Nonedef connect(self, user_name: str, password: str):print("client: 發起 mqtt connect 請求...")res=MqttBroker.do_connect(user_name=user_name, password=password)if res:self.conn = MqttBroker()self.on_connect(res=res)def publish(self, msg: dict):print(f"client: publish 發布消息{msg}")res=self.conn.do_publish(msg=msg)print("client: publish success !") if res else print("client: publish failed")def subscribe(self, topic):print(f"client: subscribe 訂閱 topic為{topic}的消息")q:queue.Queue=self.conn.do_subscribe(topic=topic)while not q.empty():self.on_message(q.get())def on_connect(self, res):r= '成功' if res else '失敗'print(f"client: on_connect ,連接{r}!")def on_message(self, msg):print(f"client: on_message ,自定義處理消息: {msg}")if __name__ == '__main__':client = MqttClient()# 模擬連接print("模擬連接:")client.connect('user', 'password')# 模擬發布print("\n\n\n模擬發布:")for i in range(3):msg = {'topic': '1001', 'msg': {'playload': f'msg{i}: hello mqtt! '}}client.publish(msg=msg)# 模擬訂閱print("\n\n\n模擬訂閱:")client.subscribe(topic="1001")

執行結果:

模擬連接:
client: 發起 mqtt connect 請求...
broker: do_connect 處理客戶端連接請求
client: on_connect ,連接成功!模擬發布:
client: publish 發布消息{'topic': '1001', 'msg': {'playload': 'msg0: hello mqtt! '}}
broker: do_publish 處理客戶端發布請求
client: publish success !
client: publish 發布消息{'topic': '1001', 'msg': {'playload': 'msg1: hello mqtt! '}}
broker: do_publish 處理客戶端發布請求
client: publish success !
client: publish 發布消息{'topic': '1001', 'msg': {'playload': 'msg2: hello mqtt! '}}
broker: do_publish 處理客戶端發布請求
client: publish success !模擬訂閱:
client: subscribe 訂閱 topic為1001的消息
broker: do_subscribe 處理客戶端訂閱請求
client: on_message ,自定義處理消息: {'topic': '1001', 'msg': {'playload': 'msg0: hello mqtt! '}}
client: on_message ,自定義處理消息: {'topic': '1001', 'msg': {'playload': 'msg1: hello mqtt! '}}
client: on_message ,自定義處理消息: {'topic': '1001', 'msg': {'playload': 'msg2: hello mqtt! '}}

開源的力量

幸運的是,開源社區早就已經開發出 mqtt 服務端和客戶端的程序,不需要自己從頭開始去實現。

mqtt broker 參考開源的 EMQX,https://www.emqx.com

mqtt client 參考 paho-mqtt 客戶端庫使用,十分優雅:

https://docs.emqx.com/zh/cloud/latest/connect_to_deployments/python_sdk.html

后話

我們通過一篇有趣的故事,推理出 mqtt 協議中服務端和客戶端的功能和偽代碼實現

其實我們生產上用的都是開源的庫和工具,根本不需要自我去重新實現,有利有弊。這樣我們往往不會繼續深究其原理,也對其為什么這樣設計感到迷茫。

自己從頭設計和簡單地實現一遍主體,更有助于理解 mqtt 和被開源工具封裝的思路設計,讓我們在學習過程中更有成就感。

此文可謂是大話IOT系列迄今為止最重要也是最干貨的一篇文章了,我希望能給大家帶來一些技術的幫助收獲。

相信認真看完這幾篇文章的朋友們,是不是有點躍躍欲試了?感覺物聯網似乎不過如此啊?我們自己也能實現不是嗎?

當然可以啦,事在人為嘛,不過過程就會比較艱辛和漫長,但我相信,只要掌握了物聯網的核心,我們自己完全可以實現一個智能家居系統出來。

作為一個普通人員,我自己還是沒有那么大的野心的,要精通的事情就太多了,前端,后端,UI,測試,嵌入式……不然一個公司那么多人的工作靠你一個就能完成了?簡直是天方夜譚。

我所能做的,只不過是在我認知的范圍里面力所能及的,比如大話系列技術的總結,關于工作過程中的代碼及心得體會,技術往往都是在一次又一次的總結中成長,等有一天你會發現,你原來這么牛了!所以,多擁抱你手中的筆吧,這才是技術的源泉

后期我還會再寫一下測試中用到的模擬設備的代碼實現,硬核來襲,敬請期待吧!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/920729.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/920729.shtml
英文地址,請注明出處:http://en.pswp.cn/news/920729.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大語言模型生成的“超齡勞動者權益保障制度系統化完善建議(修訂版)”

大綱 │ ├── 一、基于征求意見稿現狀的評估 │ ├── 制度意義:25條暫行規定首次明確權益范圍,提供法律依據 │ └── 關鍵缺陷 │ ├── 法律定位不明確 │ ├── 社保銜接不足 │ └── 實施機制不完善 │ ├── 二、法…

【UnityAS】Unity Android Studio 聯合開發快速入門:環境配置、AAR 集成與雙向調用教程

這是一篇2021年的存檔,使用Unity2020版本。 至今,Unity與AS很多通訊方式也是基于此衍生。 作為Unity與AS聯合開發的受益者,難得掏出自己的飯碗,諸君共享! Unity & Android Studio 聯合開發快速入門 ——Unity與AS…

前后端聯合實現多個文件上傳

1、前端 Vue3CommonApplyBasicInfoForm.vue<script setup lang"ts" name"CommonApplyBasicInfoForm"> ...... // 文件輸入實例對象 const fileInputRef ref<HTMLInputElement | null>(null); // 選擇文件列表 const selectedFiles ref<Fi…

軟考高級--系統架構設計師--綜合知識真題解析

系列文章目錄 文章目錄系列文章目錄一、2019年真題二、2020年真題三、2021年真題四、2022年真題總結一、2019年真題 二、2020年真題 三、2021年真題 四、2022年真題 總結

“帕薩特B5鉗盤式制動器結構設計三維PROE模型7張CAD圖紙PDF圖“

摘 要本文首先對汽車制動器原理和對各種各樣的制動器進行分析,詳細地闡述了各類制動器的結構,工作原理和優缺點。再根據轎車的車型和結構選擇了適合的方案。根據市場上同系列車型的車大多數是滑鉗盤式制動器,而且滑動鉗式盤式制動器結構簡單,性能居中,設計規范,所以我選擇滑動…

SQL注入6----(其他注入手法)

一.前言 本章節來介紹一下其他的注入手法&#xff0c;也就是非常規注入手法&#xff0c;來和大家介紹一下 二.加密注入 前端提交的有些數據是加密之后&#xff0c;到了后臺在解密&#xff0c;然后再進行數據庫查詢等相關操作的&#xff0c;那么既然如 此我們也應該將注入語句…

visual studio2022 配置 PCL 1.13.1

PCL庫下載 下載鏈接&#xff1a; https://github.com/PointCloudLibrary/pcl/releases 下載這兩個。 PCL庫安裝 運行.exe文件進行安裝。 環境變量勾第二個&#xff08;其實無所謂&#xff0c;反正還要添加別的環境變量&#xff0c;這里沒選之后加也一樣&#xff09;。 安裝…

金融學-貨幣理論

前言 前面學習了什么是貨幣供給&#xff0c;貨幣供給的決定以及聯邦儲備體系在貨幣供給中所起的作用。現在我們要開始探討經濟中貨幣供給在決定價格水平與全部商品和勞務(總供給)中的作用。關于貨幣對經濟影響的研究&#xff0c;稱為貨幣理論(monetarythe-ory) 貨幣數量論 古典…

Visio繪圖——給多邊形增加連接線

每次在畫項目框圖和各類爪圖的時候&#xff0c;連接線是最煩人的&#xff0c;雖然選擇的是折線&#xff0c;單往往事與愿違。 下面就記錄一下&#xff0c;如何查找各類連接線。 1、先展開左側菜單欄&#xff0c;點擊如下所示的“&#xff1e;”2、在展開的界面&#xff0c;再次…

【開題答辯全過程】以 付費自習室系統小程序為例,包含答辯的問題和答案

個人簡介一名14年經驗的資深畢設內行人&#xff0c;語言擅長Java、php、微信小程序、Python、Golang、安卓Android等開發項目包括大數據、深度學習、網站、小程序、安卓、算法。平常會做一些項目定制化開發、代碼講解、答辯教學、文檔編寫、也懂一些降重方面的技巧。感謝大家的…

開疆智能Profinet轉EtherCAT網關連接TR-Electronic傳感器配置案例

本案例是通過開疆智能研發的Profinet轉EtherCAT網關將傳感器數據傳送到PLC&#xff0c;由于兩邊設備采用協議不同&#xff0c;故而使用網關進行轉換。網關配置&#xff1a;打開網關配置軟件“EtherCAT Manager”并新建項目。根據不通網關型號也可選擇ModbusTCP&#xff0c;Ethe…

VSCode中使用Markdown

文章目錄1. 背景2. 安裝插件3. 基礎寫作與預覽4. 生成PDF文檔5. 插入代碼6. 插入圖片7. 小結1. 背景 編程技術人員&#xff0c;很多人寫作習慣用Markdown格式吧。 首先Markdown很簡單&#xff0c;第二它的層次結構特別清晰&#xff0c;再然后它對嵌入圖片、代碼的支持很優秀。…

2024全棧技術棧選型指南

前后端技術棧選擇現代前后端技術棧選擇需兼顧市場需求與個人興趣。前端領域React、Vue、Angular形成三足鼎立&#xff0c;React在大型項目占比達58%&#xff0c;Vue在小中型企業更受歡迎。TypeScript采用率年增長25%&#xff0c;已成為工程化標配。后端技術呈現多元化趨勢&…

Spring Boot 項目文件上傳安全與優化:OSS、MinIO、Nginx 分片上傳實戰

在實際的 Web 項目中&#xff0c;文件上傳是一個常見需求&#xff1a;用戶上傳頭像、企業后臺上傳資料、視頻平臺上傳大文件等等。然而&#xff0c;文件上傳也是最容易引發安全風險的功能之一&#xff0c;比如惡意腳本上傳、木馬文件偽裝、存儲空間消耗攻擊。同時&#xff0c;當…

智能安防:以AI重塑安全新邊界

傳統安防依賴人力監控與簡單報警&#xff0c;效率低下且易遺漏風險。隨著人工智能、物聯網及大數據技術的融合&#xff0c;智能安防正重新定義安全管理的范式&#xff0c;從被動響應轉向主動預警&#xff0c;成為智慧城市與數字化生活的重要基石。智能安防的核心是人工智能視覺…

【AI】【強化學習】強化學習算法總結、資料匯總、個人理解

前言&#xff1a;自己學習西湖大學趙老師的課、youtube系列的課程相關比較重要的內容&#xff0c;后續不斷再進行完善。 YouTube Serrano.academy rlhf講的很好 合集最后一個沒看 強化學習第四章 police沒一步需要無窮&#xff0c;值迭代只需要一步 收斂不一樣 值迭代:原因在于…

一鍵掌控三線資源:極簡 Shell 腳本實現 CPU·磁盤·內存可視化巡檢

目錄 前言 數值型 for 循環 語法格式 示例&#xff1a;打印 1 到 5 示例&#xff1a;打印5次Hello World 示例&#xff1a;計算 1 到 100 的累加和 遍歷型 for 循環 語法格式 示例&#xff1a;遍歷字符串列表 示例&#xff1a;遍歷數組 示例&#xff1a;遍歷文件列表…

數據結構:創建堆(或者叫“堆化”,Heapify)

目錄 最直觀的思路 更優化的思路&#xff08;自底向上的構建&#xff09; 第一步&#xff1a;重新審視問題 第二步&#xff1a;找到規律&#xff0c;形成策略 用一個實例來推演 第三步&#xff1a;編寫代碼 總結與分析 我們來深入探討“創建堆”&#xff08;或者叫“堆化…

基于 GPT-OSS 的成人自考口語評測 API 開發全記錄

1?? 需求與指標 在項目啟動前&#xff0c;我們設定了核心指標&#xff1a; 字錯率&#xff08;WER&#xff09;< 5%響應延遲 < 800 ms高可用、可擴展 這些指標將貫穿整個開發和測試流程。 2?? 數據準備 準備訓練數據是關鍵步驟&#xff0c;我們使用了 1k 條自考口…

Linux初始——基礎指令篇

Linux常用指令pwdlscdtouchmkdirrmmancpmvcatmorelesswhichwhereisaliasgrepfilezip/unzip 指令rzsztarpwd 在xshell中輸入pwd并回車&#xff0c;將輸出當前用戶所存在的目錄位置 可看到當前用戶是在/home/hhw這個目錄下 ls 在xshell中輸入ls會顯示當前目錄所包含的文件 其中…