一、前言
1.1 開發(fā)背景
隨著物聯(lián)網(wǎng)技術(shù)的不斷發(fā)展,越來越多的設(shè)備和應(yīng)用依賴于實(shí)時(shí)數(shù)據(jù)交換和遠(yuǎn)程控制。在物聯(lián)網(wǎng)生態(tài)系統(tǒng)中,設(shè)備與云平臺(tái)之間的通信是核心環(huán)節(jié)之一,然而對于許多開發(fā)者來說,進(jìn)行這種設(shè)備與云平臺(tái)之間的通信往往涉及到硬件的配置與調(diào)試,這對于一些不熟悉硬件的開發(fā)者,尤其是那些處于軟件開發(fā)領(lǐng)域的人員,可能是一大挑戰(zhàn)。傳統(tǒng)的物聯(lián)網(wǎng)開發(fā)往往需要開發(fā)者擁有一定的硬件基礎(chǔ),或者至少具備與硬件設(shè)備進(jìn)行調(diào)試和交互的能力,這使得一些開發(fā)者在沒有硬件設(shè)備的情況下,難以快速上手和測試物聯(lián)網(wǎng)應(yīng)用。
為了解決這一問題,開發(fā)者迫切需要一種能夠模擬硬件設(shè)備并與云平臺(tái)進(jìn)行交互的工具。通過軟件仿真硬件的方式,開發(fā)者可以不依賴于實(shí)際硬件設(shè)備,就能夠快速學(xué)習(xí)、理解和驗(yàn)證物聯(lián)網(wǎng)應(yīng)用中設(shè)備與云平臺(tái)的通信過程。這種仿真方法不僅能夠降低開發(fā)門檻,還能夠幫助開發(fā)者更好地理解物聯(lián)網(wǎng)系統(tǒng)的工作原理,并有效加速物聯(lián)網(wǎng)項(xiàng)目的開發(fā)周期。
本項(xiàng)目正是在這樣的背景下應(yīng)運(yùn)而生。通過開發(fā)一款基于MQTT協(xié)議的客戶端調(diào)試助手,項(xiàng)目旨在為開發(fā)者提供一個(gè)簡單易用的工具,模擬硬件設(shè)備與云平臺(tái)的通信交互。這款工具通過軟件模擬了物聯(lián)網(wǎng)設(shè)備的行為,支持主題的訂閱與發(fā)布,能夠與華為云物聯(lián)網(wǎng)平臺(tái)(IoTDA)進(jìn)行實(shí)時(shí)通信。對于不熟悉硬件的開發(fā)者,或者暫時(shí)沒有硬件設(shè)備的開發(fā)者而言,這款調(diào)試助手可以讓他們在沒有物理硬件的前提下,體驗(yàn)完整的物聯(lián)網(wǎng)設(shè)備上云過程。開發(fā)者可以通過該工具快速了解設(shè)備如何連接云平臺(tái),如何進(jìn)行數(shù)據(jù)傳輸,并學(xué)習(xí)MQTT協(xié)議的基本操作。
此外,物聯(lián)網(wǎng)技術(shù)本身發(fā)展迅速,而MQTT作為一種輕量級(jí)、高效的消息傳輸協(xié)議,已成為物聯(lián)網(wǎng)設(shè)備與云平臺(tái)之間通信的首選協(xié)議。利用MQTT,設(shè)備可以以低帶寬、高可靠性的方式與云平臺(tái)進(jìn)行實(shí)時(shí)數(shù)據(jù)交換。為了幫助開發(fā)者熟悉和掌握這一協(xié)議,本項(xiàng)目采用了paho-mqtt庫,它是一個(gè)開源的Python庫,能夠簡化MQTT協(xié)議的實(shí)現(xiàn),使得開發(fā)者能夠?qū)W⒂跇I(yè)務(wù)邏輯,而無需過多擔(dān)心底層通信細(xì)節(jié)。
本項(xiàng)目的目標(biāo)不僅僅是為開發(fā)者提供一個(gè)調(diào)試工具,更重要的是通過仿真硬件的方式,使得開發(fā)者能夠從軟件層面全面體驗(yàn)物聯(lián)網(wǎng)設(shè)備上云的全過程。這不僅有助于他們更好地理解物聯(lián)網(wǎng)的通信機(jī)制,還能夠?yàn)槲磥淼挠布_發(fā)和云平臺(tái)集成打下基礎(chǔ)。通過本項(xiàng)目,開發(fā)者能夠在一個(gè)完全虛擬的環(huán)境中學(xué)習(xí)和掌握物聯(lián)網(wǎng)開發(fā)的基本技能,為日后的實(shí)際硬件開發(fā)做好準(zhǔn)備。
本項(xiàng)目的實(shí)現(xiàn)將有助于推廣物聯(lián)網(wǎng)技術(shù)的普及和應(yīng)用,讓更多的開發(fā)者能夠在沒有硬件的情況下,通過軟件模擬快速掌握物聯(lián)網(wǎng)設(shè)備的云端通信技術(shù),為物聯(lián)網(wǎng)應(yīng)用的發(fā)展提供更加廣泛的人才支持和技術(shù)儲(chǔ)備。
當(dāng)前項(xiàng)目使用的相關(guān)軟件工具已經(jīng)上傳到網(wǎng)盤:
[https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink]
代碼設(shè)計(jì)界面:
運(yùn)行效果:
填入信息:
最終設(shè)計(jì)完成的界面如下:
1.2 云主機(jī)
這里使用的華為云開發(fā)者空間云主機(jī),是華為云為全球開發(fā)者打造的一個(gè)云端開發(fā)環(huán)境,簡化開發(fā)流程、提高開發(fā)效率,并促進(jìn)技術(shù)創(chuàng)新。這個(gè)平臺(tái)提供了一個(gè)無需成本即可探索和使用華為云服務(wù)的機(jī)會(huì),每位注冊的開發(fā)者在年度內(nèi)都能享有數(shù)百小時(shí)的云主機(jī)使用權(quán)。云主機(jī)預(yù)裝了CodeArts IDE(華為云的集成開發(fā)環(huán)境)、代碼倉庫以及JDK、Python等關(guān)鍵運(yùn)行時(shí)插件,從而避免了本地環(huán)境配置的復(fù)雜性,讓開發(fā)者能夠快速上手并立即開始工作。
除了云主機(jī)外,華為云還提供了5GB的云存儲(chǔ)容量及定制化的場景模擬沙箱,這些資源幫助開發(fā)者在安全隔離的環(huán)境中進(jìn)行實(shí)驗(yàn)和測試。華為云開發(fā)者空間提供了豐富的技術(shù)培訓(xùn)課程和專業(yè)認(rèn)證資料,助力開發(fā)者提升技能,并通過認(rèn)證來證明自己的能力。該空間特別注重于應(yīng)用全周期管理,涵蓋從應(yīng)用構(gòu)建到運(yùn)維的全過程,確保開發(fā)者可以高效地完成云端應(yīng)用搭建。
華為云開發(fā)者空間云主機(jī)圍繞CodeArts IDE打造了一個(gè)全面的開發(fā)工具生態(tài)系統(tǒng),整合了鯤鵬、昇騰、鴻蒙等核心生態(tài)的開發(fā)資源,提供廣泛的開源軟件庫和實(shí)用開發(fā)插件,支持從代碼托管到應(yīng)用運(yùn)維的各個(gè)階段。這不僅提升了開發(fā)效率,也方便了開發(fā)者與華為先進(jìn)技術(shù)和全球開發(fā)者社區(qū)互動(dòng),共同推動(dòng)技術(shù)進(jìn)步和應(yīng)用創(chuàng)新。
華為云開發(fā)者空間云主機(jī)的操作系統(tǒng)版本為Ubuntu 22.04.4 LTS,并且內(nèi)置了一些常用的應(yīng)用程序如Gitcode等,為開發(fā)者提供了一個(gè)穩(wěn)定而高效的開發(fā)環(huán)境。
1.3 開發(fā)環(huán)境
本項(xiàng)目的開發(fā)環(huán)境采用了華為開發(fā)者空間的云主機(jī),這一環(huán)境為全球開發(fā)者提供了一個(gè)功能強(qiáng)大且易于訪問的云端開發(fā)平臺(tái)。開發(fā)者可以通過這一平臺(tái)進(jìn)行快速的應(yīng)用開發(fā)、調(diào)試和部署,省去了本地環(huán)境配置和硬件限制等問題。整個(gè)開發(fā)環(huán)境包括了操作系統(tǒng)、開發(fā)語言、開發(fā)框架、工具鏈以及云端資源等多個(gè)方面。
(1)云主機(jī)平臺(tái):華為開發(fā)者空間
華為開發(fā)者空間是華為云為開發(fā)者提供的一個(gè)云端開發(fā)環(huán)境,能夠幫助開發(fā)者無需復(fù)雜的本地環(huán)境配置即可開展工作。該平臺(tái)提供了強(qiáng)大的計(jì)算資源和開發(fā)工具,能夠滿足大規(guī)模開發(fā)和調(diào)試的需求。在本項(xiàng)目中,云主機(jī)提供了一個(gè)統(tǒng)一的、穩(wěn)定的開發(fā)環(huán)境,開發(fā)者只需要通過瀏覽器即可訪問,不需要擔(dān)心操作系統(tǒng)的配置、版本兼容性等問題。這種云端開發(fā)方式特別適合開發(fā)與云服務(wù)緊密集成的物聯(lián)網(wǎng)應(yīng)用,能夠高效地進(jìn)行實(shí)時(shí)測試和調(diào)試。
(2)操作系統(tǒng):Ubuntu 22.04.4
整個(gè)開發(fā)環(huán)境基于Ubuntu 22.04.4操作系統(tǒng)運(yùn)行,Ubuntu作為一種流行的Linux發(fā)行版,因其穩(wěn)定性、開源性和豐富的軟件支持而被廣泛應(yīng)用于開發(fā)領(lǐng)域。Ubuntu 22.04.4是該系統(tǒng)的LTS(長期支持)版本,提供了長期的安全更新和穩(wěn)定性支持,適合進(jìn)行生產(chǎn)環(huán)境中的應(yīng)用開發(fā)。對于Python開發(fā)者而言,Ubuntu提供了優(yōu)良的包管理工具和開發(fā)工具,能夠方便地安裝各種開發(fā)所需的庫和工具。
(3)開發(fā)語言:Python
項(xiàng)目采用Python作為主要開發(fā)語言,Python因其簡潔的語法、強(qiáng)大的庫支持和廣泛的應(yīng)用場景,成為了開發(fā)者常用的語言。Python的跨平臺(tái)特性使得應(yīng)用能夠在不同的操作系統(tǒng)上無縫運(yùn)行,而其龐大的第三方庫(如paho-mqtt)則為開發(fā)者提供了許多現(xiàn)成的解決方案。本項(xiàng)目中,Python用于實(shí)現(xiàn)MQTT協(xié)議的客戶端功能,包括消息的訂閱、發(fā)布和連接管理等核心操作。
(4) 界面開發(fā)框架:PyQt5
為了提升用戶體驗(yàn)并提供便捷的圖形化界面,本項(xiàng)目采用了PyQt5作為界面開發(fā)框架。PyQt5是Python的Qt庫綁定,提供了一套豐富的用戶界面組件,開發(fā)者可以用它來快速構(gòu)建高效、美觀且跨平臺(tái)的桌面應(yīng)用程序。通過PyQt5,開發(fā)者可以設(shè)計(jì)直觀的界面,幫助用戶通過圖形化操作進(jìn)行MQTT主題的訂閱、消息的發(fā)布和設(shè)備狀態(tài)的監(jiān)控。PyQt5的信號(hào)與槽機(jī)制也使得界面的事件響應(yīng)和后臺(tái)邏輯處理更加簡潔高效。
(5)MQTT客戶端庫:paho-mqtt
項(xiàng)目中的MQTT協(xié)議操作主要通過paho-mqtt
庫來實(shí)現(xiàn)。paho-mqtt
是由Eclipse基金會(huì)提供的一個(gè)廣泛使用的Python MQTT客戶端庫,它支持MQTT協(xié)議的各種操作,如客戶端連接、消息的發(fā)布和訂閱、消息的接收等。paho-mqtt
庫在本項(xiàng)目中承擔(dān)著與華為云物聯(lián)網(wǎng)平臺(tái)進(jìn)行通信的核心功能,能夠保證數(shù)據(jù)的實(shí)時(shí)傳輸和可靠性。
(6)開發(fā)工具:CodeArts IDE
CodeArts IDE是華為開發(fā)者空間提供的集成開發(fā)環(huán)境,它為開發(fā)者提供了豐富的開發(fā)工具和調(diào)試功能。該IDE內(nèi)置了代碼編輯、版本控制、調(diào)試等多種功能,并且預(yù)先配置好了開發(fā)環(huán)境,開發(fā)者可以直接進(jìn)入開發(fā)狀態(tài)。通過CodeArts IDE,開發(fā)者可以在云端編寫代碼、執(zhí)行調(diào)試、管理版本等,而不需要擔(dān)心本地環(huán)境配置的問題。此外,CodeArts IDE的云端特性也使得開發(fā)者能夠隨時(shí)隨地進(jìn)行開發(fā),無論是在不同的設(shè)備還是不同的地理位置,都能夠保持一致的開發(fā)體驗(yàn)。
1.4 功能說明
本項(xiàng)目主要解決以下幾個(gè)問題:
- 模擬硬件設(shè)備 :通過軟件模擬物聯(lián)網(wǎng)設(shè)備,允許開發(fā)者在沒有實(shí)際硬件的情況下體驗(yàn)設(shè)備與云平臺(tái)的通信過程。
- 簡化調(diào)試流程 :提供圖形化界面和簡易操作,降低了調(diào)試和測試的門檻,尤其適合沒有硬件設(shè)備的開發(fā)者進(jìn)行學(xué)習(xí)和驗(yàn)證。
- 實(shí)現(xiàn)MQTT協(xié)議的基本功能 :通過paho-mqtt庫,支持MQTT協(xié)議中的主題訂閱、消息發(fā)布等功能,讓開發(fā)者能夠快速掌握物聯(lián)網(wǎng)通信的核心技術(shù)。
本項(xiàng)目主要實(shí)現(xiàn)了以下幾項(xiàng)核心功能:
(1)主題訂閱功能
在物聯(lián)網(wǎng)通信中,設(shè)備通常需要訂閱云平臺(tái)上的特定主題(Topic),以便接收實(shí)時(shí)消息或指令。通過主題訂閱功能,開發(fā)者可以模擬設(shè)備通過MQTT協(xié)議與云平臺(tái)進(jìn)行通信,獲取云平臺(tái)推送的消息。此功能支持以下操作:
- 輸入主題名稱 :用戶可以手動(dòng)輸入MQTT主題名稱。
- 訂閱主題 :模擬硬件設(shè)備訂閱云平臺(tái)的指定主題,等待云平臺(tái)推送消息。
- 查看消息 :訂閱成功后,客戶端能夠?qū)崟r(shí)顯示從云平臺(tái)接收到的消息,幫助開發(fā)者了解訂閱是否成功以及接收到的內(nèi)容。
(2)主題發(fā)布功能
在物聯(lián)網(wǎng)應(yīng)用中,設(shè)備通常會(huì)將采集到的數(shù)據(jù)或狀態(tài)信息推送到云平臺(tái)。這一過程通過主題發(fā)布實(shí)現(xiàn)。在本項(xiàng)目中,開發(fā)者可以模擬設(shè)備向云平臺(tái)發(fā)布消息,操作步驟包括:
- 選擇主題 :用戶可以選擇一個(gè)已有的主題或創(chuàng)建新的主題。
- 發(fā)布消息 :通過輸入消息內(nèi)容,模擬設(shè)備將數(shù)據(jù)發(fā)布到指定的MQTT主題。
- 消息傳遞確認(rèn) :客戶端會(huì)向用戶顯示消息是否成功發(fā)布,以及云平臺(tái)是否已經(jīng)成功接收。
(3)MQTT連接管理
為了確保與華為云物聯(lián)網(wǎng)平臺(tái)的通信穩(wěn)定,項(xiàng)目提供了MQTT連接管理功能,允許開發(fā)者:
- 連接到華為云IoTDA平臺(tái) :通過設(shè)置MQTT代理地址和認(rèn)證信息,開發(fā)者能夠輕松連接到華為云物聯(lián)網(wǎng)平臺(tái)。
- 自動(dòng)重連 :當(dāng)連接出現(xiàn)問題或網(wǎng)絡(luò)中斷時(shí),客戶端可以自動(dòng)嘗試重新連接,確保設(shè)備與平臺(tái)的穩(wěn)定通信。
- 查看連接狀態(tài) :客戶端實(shí)時(shí)顯示連接狀態(tài),幫助開發(fā)者了解當(dāng)前的網(wǎng)絡(luò)連接情況及連接穩(wěn)定性。
(4)圖形化用戶界面(GUI)
本項(xiàng)目使用PyQt5構(gòu)建了一個(gè)直觀、易操作的圖形化界面,具體包括:
- 用戶友好的界面 :通過清晰的按鈕、文本框和消息顯示框,使得開發(fā)者可以直觀地進(jìn)行操作,例如輸入主題、發(fā)布消息、查看訂閱的消息等。
- 操作日志 :界面中展示了連接、訂閱、發(fā)布等操作的日志信息,幫助開發(fā)者實(shí)時(shí)查看操作狀態(tài)和通信結(jié)果。
- 事件驅(qū)動(dòng)機(jī)制 :通過PyQt5的信號(hào)與槽機(jī)制,客戶端能夠快速響應(yīng)用戶的操作,執(zhí)行相應(yīng)的MQTT協(xié)議功能,確保交互過程流暢且無延遲。
(5)實(shí)時(shí)消息顯示和調(diào)試
為了方便開發(fā)者進(jìn)行調(diào)試,項(xiàng)目提供了實(shí)時(shí)的消息顯示功能。每當(dāng)有新的消息被發(fā)布或接收時(shí),客戶端界面會(huì)立即更新,開發(fā)者可以:
- 查看接收到的消息內(nèi)容 :幫助開發(fā)者驗(yàn)證主題訂閱和消息發(fā)布的有效性。
- 調(diào)試信息輸出 :在操作過程中,客戶端會(huì)顯示詳細(xì)的調(diào)試信息,幫助開發(fā)者跟蹤操作步驟,查找并解決潛在的問題。
(6)支持多平臺(tái)運(yùn)行
通過使用PyQt5框架,項(xiàng)目能夠?qū)崿F(xiàn)跨平臺(tái)運(yùn)行,開發(fā)者可以在不同的操作系統(tǒng)(如Windows、Linux、macOS)上運(yùn)行調(diào)試助手。這使得該工具不僅限于某一操作系統(tǒng),開發(fā)者可以在任何操作系統(tǒng)上進(jìn)行測試和學(xué)習(xí)。
(7)MQTT協(xié)議的學(xué)習(xí)和測試工具
本項(xiàng)目不僅僅是一個(gè)調(diào)試工具,還是一個(gè)學(xué)習(xí)和測試平臺(tái)。開發(fā)者可以通過該工具快速掌握MQTT協(xié)議的基本概念,包括如何建立連接、如何訂閱和發(fā)布消息、如何管理MQTT會(huì)話等。通過模擬硬件設(shè)備與云平臺(tái)的交互,開發(fā)者能夠更清楚地理解物聯(lián)網(wǎng)通信的工作原理,為實(shí)際的硬件開發(fā)奠定基礎(chǔ)。
二、華為云開發(fā)者空間
這一個(gè)章節(jié)介紹華為云主機(jī)的配置與使用。
2.1 進(jìn)入開發(fā)者空間
鏈接地址:[https://developer.huaweicloud.com/space/devportal/desktop]
登錄華為云賬號(hào),進(jìn)去之后看到的頁面如下:
2.2 配置云主機(jī)
在左上角可以看到云主機(jī)的配置提醒,目前默認(rèn)是基礎(chǔ)版。
點(diǎn)擊配置云主機(jī)
,會(huì)彈出對話框,讓你選擇云主機(jī)的配置,進(jìn)行安裝系統(tǒng)。我這里選擇ubuntu 22.04
.
2.3 安裝系統(tǒng)
點(diǎn)擊安裝
后,會(huì)進(jìn)行安裝系統(tǒng)。需要等等一段時(shí)間。
2.4 啟動(dòng)云主機(jī)
安裝完畢之后,直接可以在瀏覽器里啟動(dòng)云主機(jī)。
啟動(dòng)需要一段時(shí)間初始環(huán)境。
進(jìn)去之后會(huì)有引導(dǎo)界面,提示云主機(jī)的使用技巧。
進(jìn)入桌面后的默認(rèn)效果如下。
2.5 全屏切換
在桌面頁面上有個(gè)按鈕可以全屏切換,切換全屏后,可視化空間更大,開發(fā)更加方便。
2.6 共享桌面
云主機(jī)還有共享桌面功能,如果需要遠(yuǎn)程演示項(xiàng)目,共享開發(fā)過程,對方還可以遠(yuǎn)程操作,這個(gè)功能非常的方便。 直接雙擊666
。
2.5 測試Python開發(fā)環(huán)境
點(diǎn)擊左下角的所有應(yīng)用程序
,可以看到開發(fā)
菜單里,有安裝好的Python環(huán)境,可以直接使用。
啟動(dòng)之后的效果如下。
進(jìn)去之后,點(diǎn)擊左上角,新建一個(gè)文件。
然后保存文件,名字叫:test.py
然后編寫一段簡單的python
代碼,測試當(dāng)前的開發(fā)環(huán)境是否正常。
代碼如下:
import socket
def get_local_ip():
"""
獲取本地 IP 地址
"""
try:
# 創(chuàng)建一個(gè) socket 對象,并連接到一個(gè)公共地址
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
local_ip = s.getsockname()[0]
s.close()
return local_ip
except Exception as e:
return f"無法獲取本地 IP 地址: {e}"
if __name__ == '__main__':
print("本地 IP 地址是:", get_local_ip())
點(diǎn)擊左上角運(yùn)行。
結(jié)果如下:
2.6 安裝requests庫
接下來需要使用Python代碼的requests庫,發(fā)起HTTP請求。先提前安裝環(huán)境。
2.7 安裝Pillow庫
Pillow
是 PIL
(Python Imaging Library)的一個(gè)分支,提供了圖片處理功能。
pip3 install Pillow
2.8 安裝paho-mqtt庫
安裝命令:
pip install paho-mqtt
到此,云主機(jī)的開發(fā)環(huán)境已經(jīng)測試OK。
三、配置華為云物聯(lián)網(wǎng)平臺(tái)IOTDA
華為云官網(wǎng): https://www.huaweicloud.com/
打開官網(wǎng),搜索物聯(lián)網(wǎng),就能快速找到 設(shè)備接入IoTDA
。
3.1 物聯(lián)網(wǎng)平臺(tái)介紹
華為云物聯(lián)網(wǎng)平臺(tái)(IoT 設(shè)備接入云服務(wù))提供海量設(shè)備的接入和管理能力,將物理設(shè)備聯(lián)接到云,支撐設(shè)備數(shù)據(jù)采集上云和云端下發(fā)命令給設(shè)備進(jìn)行遠(yuǎn)程控制,配合華為云其他產(chǎn)品,幫助我們快速構(gòu)筑物聯(lián)網(wǎng)解決方案。
使用物聯(lián)網(wǎng)平臺(tái)構(gòu)建一個(gè)完整的物聯(lián)網(wǎng)解決方案主要包括3部分:物聯(lián)網(wǎng)平臺(tái)、業(yè)務(wù)應(yīng)用和設(shè)備。
物聯(lián)網(wǎng)平臺(tái)作為連接業(yè)務(wù)應(yīng)用和設(shè)備的中間層,屏蔽了各種復(fù)雜的設(shè)備接口,實(shí)現(xiàn)設(shè)備的快速接入;同時(shí)提供強(qiáng)大的開放能力,支撐行業(yè)用戶構(gòu)建各種物聯(lián)網(wǎng)解決方案。
設(shè)備可以通過固網(wǎng)、2G/3G/4G/5G、NB-IoT、Wifi等多種網(wǎng)絡(luò)接入物聯(lián)網(wǎng)平臺(tái),并使用LWM2M/CoAP、MQTT、HTTPS協(xié)議將業(yè)務(wù)數(shù)據(jù)上報(bào)到平臺(tái),平臺(tái)也可以將控制命令下發(fā)給設(shè)備。
業(yè)務(wù)應(yīng)用通過調(diào)用物聯(lián)網(wǎng)平臺(tái)提供的API,實(shí)現(xiàn)設(shè)備數(shù)據(jù)采集、命令下發(fā)、設(shè)備管理等業(yè)務(wù)場景。
3.2 開通物聯(lián)網(wǎng)服務(wù)
地址: https://www.huaweicloud.com/product/iothub.html
點(diǎn)擊立即創(chuàng)建
。
正在創(chuàng)建標(biāo)準(zhǔn)版實(shí)例,需要等待片刻。
創(chuàng)建完成之后,點(diǎn)擊實(shí)例名稱。 可以看到標(biāo)準(zhǔn)版實(shí)例的設(shè)備接入端口和地址。
在上面也能看到 免費(fèi)單元的限制。
開通之后,點(diǎn)擊總覽
,也能查看接入信息。 我們當(dāng)前設(shè)備準(zhǔn)備采用MQTT協(xié)議接入華為云平臺(tái),這里可以看到MQTT協(xié)議的地址和端口號(hào)等信息。
總結(jié):
端口號(hào): MQTT (1883)| MQTTS (8883)
接入地址:ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
**根據(jù)域名地址得到IP地址信息: **
打開Windows電腦的命令行控制臺(tái)終端,使用ping
命令。ping
一下即可。
Microsoft Windows [版本 10.0.19045.4170]
(c) Microsoft Corporation。保留所有權(quán)利。
C:Users11266 >ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字節(jié)的數(shù)據(jù):
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=35ms TTL=93
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=36ms TTL=93
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=36ms TTL=93
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=39ms TTL=93
117.78.5.125 的 Ping 統(tǒng)計(jì)信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
最短 = 35ms,最長 = 39ms,平均 = 36ms
C:Users11266 >
MQTT協(xié)議接入端口號(hào)有兩個(gè),1883是非加密端口,8883是證書加密端口,單片機(jī)無法加載證書,所以使用1883端口比較合適。 接下來的ESP8266就采用1883端口連接華為云物聯(lián)網(wǎng)平臺(tái)。
3.3 創(chuàng)建產(chǎn)品
(1)創(chuàng)建產(chǎn)品
(2)填寫產(chǎn)品信息
根據(jù)自己產(chǎn)品名字填寫,下面的設(shè)備類型選擇自定義類型。
(3)產(chǎn)品創(chuàng)建成功
創(chuàng)建完成之后點(diǎn)擊查看詳情。
(4)添加自定義模型
產(chǎn)品創(chuàng)建完成之后,點(diǎn)擊進(jìn)入產(chǎn)品詳情頁面,翻到最下面可以看到模型定義。
模型簡單來說: 就是存放設(shè)備上傳到云平臺(tái)的數(shù)據(jù)。
你可以根據(jù)自己的產(chǎn)品進(jìn)行創(chuàng)建。
比如:
煙霧可以叫 MQ2
溫度可以叫 Temperature
濕度可以叫 humidity
火焰可以叫 flame
其他的傳感器自己用單詞簡寫命名即可。 這就是你的單片機(jī)設(shè)備端上傳到服務(wù)器的數(shù)據(jù)名字。
先點(diǎn)擊自定義模型。
再創(chuàng)建一個(gè)服務(wù)ID。
接著點(diǎn)擊新增屬性。
3.4 添加設(shè)備
產(chǎn)品是屬于上層的抽象模型,接下來在產(chǎn)品模型下添加實(shí)際的設(shè)備。添加的設(shè)備最終需要與真實(shí)的設(shè)備關(guān)聯(lián)在一起,完成數(shù)據(jù)交互。
(1)注冊設(shè)備
(2)根據(jù)自己的設(shè)備填寫
(3)保存設(shè)備信息
創(chuàng)建完畢之后,點(diǎn)擊保存并關(guān)閉,得到創(chuàng)建的設(shè)備密匙信息。該信息在后續(xù)生成MQTT三元組的時(shí)候需要使用。
(4)設(shè)備創(chuàng)建完成
(5)設(shè)備詳情
3.5 MQTT協(xié)議主題訂閱與發(fā)布
(1)MQTT協(xié)議介紹
當(dāng)前的設(shè)備是采用MQTT協(xié)議與華為云平臺(tái)進(jìn)行通信。
MQTT是一個(gè)物聯(lián)網(wǎng)傳輸協(xié)議,它被設(shè)計(jì)用于輕量級(jí)的發(fā)布/訂閱式消息傳輸,旨在為低帶寬和不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中的物聯(lián)網(wǎng)設(shè)備提供可靠的網(wǎng)絡(luò)服務(wù)。MQTT是專門針對物聯(lián)網(wǎng)開發(fā)的輕量級(jí)傳輸協(xié)議。MQTT協(xié)議針對低帶寬網(wǎng)絡(luò),低計(jì)算能力的設(shè)備,做了特殊的優(yōu)化,使得其能適應(yīng)各種物聯(lián)網(wǎng)應(yīng)用場景。目前MQTT擁有各種平臺(tái)和設(shè)備上的客戶端,已經(jīng)形成了初步的生態(tài)系統(tǒng)。
MQTT是一種消息隊(duì)列協(xié)議,使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布,解除應(yīng)用程序耦合,相對于其他協(xié)議,開發(fā)更簡單;MQTT協(xié)議是工作在TCP/IP協(xié)議上;由TCP/IP協(xié)議提供穩(wěn)定的網(wǎng)絡(luò)連接;所以,只要具備TCP協(xié)議棧的網(wǎng)絡(luò)設(shè)備都可以使用MQTT協(xié)議。 本次設(shè)備采用的ESP8266就具備TCP協(xié)議棧,能夠建立TCP連接,所以,配合STM32代碼里封裝的MQTT協(xié)議,就可以與華為云平臺(tái)完成通信。
華為云的MQTT協(xié)議接入幫助文檔在這里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
業(yè)務(wù)流程:
(2)華為云平臺(tái)MQTT協(xié)議使用限制
描述 | 限制 |
---|---|
支持的MQTT協(xié)議版本 | 3.1.1 |
與標(biāo)準(zhǔn)MQTT協(xié)議的區(qū)別 | 支持Qos 0和Qos 1支持Topic自定義不支持QoS2不支持will、retain msg |
MQTTS支持的安全等級(jí) | 采用TCP通道基礎(chǔ) + TLS協(xié)議(最高TLSv1.3版本) |
單帳號(hào)每秒最大MQTT連接請求數(shù) | 無限制 |
單個(gè)設(shè)備每分鐘支持的最大MQTT連接數(shù) | 1 |
單個(gè)MQTT連接每秒的吞吐量,即帶寬,包含直連設(shè)備和網(wǎng)關(guān) | 3KB/s |
MQTT單個(gè)發(fā)布消息最大長度,超過此大小的發(fā)布請求將被直接拒絕 | 1MB |
MQTT連接心跳時(shí)間建議值 | 心跳時(shí)間限定為30至1200秒,推薦設(shè)置為120秒 |
產(chǎn)品是否支持自定義Topic | 支持 |
消息發(fā)布與訂閱 | 設(shè)備只能對自己的Topic進(jìn)行消息發(fā)布與訂閱 |
每個(gè)訂閱請求的最大訂閱數(shù) | 無限制 |
(3)主題訂閱格式
幫助文檔地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
對于設(shè)備而言,一般會(huì)訂閱平臺(tái)下發(fā)消息給設(shè)備 這個(gè)主題。
設(shè)備想接收平臺(tái)下發(fā)的消息,就需要訂閱平臺(tái)下發(fā)消息給設(shè)備 的主題,訂閱后,平臺(tái)下發(fā)消息給設(shè)備,設(shè)備就會(huì)收到消息。
如果設(shè)備想要知道平臺(tái)下發(fā)的消息,需要訂閱上面圖片里標(biāo)注的主題。
以當(dāng)前設(shè)備為例,最終訂閱主題的格式如下:
$oc/devices/{device_id}/sys/messages/down
最終的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down
(4)主題發(fā)布格式
對于設(shè)備來說,主題發(fā)布表示向云平臺(tái)上傳數(shù)據(jù),將最新的傳感器數(shù)據(jù),設(shè)備狀態(tài)上傳到云平臺(tái)。
這個(gè)操作稱為:屬性上報(bào)。
幫助文檔地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html
根據(jù)幫助文檔的介紹, 當(dāng)前設(shè)備發(fā)布主題,上報(bào)屬性的格式總結(jié)如下:
發(fā)布的主題格式:
$oc/devices/{device_id}/sys/properties/report
最終的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report
發(fā)布主題時(shí),需要上傳數(shù)據(jù),這個(gè)數(shù)據(jù)格式是JSON格式。
上傳的JSON數(shù)據(jù)格式如下:
{
"services": [
{
"service_id": < 填服務(wù)ID >,
"properties": {
"< 填屬性名稱1 >": < 填屬性值 >,
"< 填屬性名稱2 >": < 填屬性值 >,
..........
}
}
]
}
根據(jù)JSON格式,一次可以上傳多個(gè)屬性字段。 這個(gè)JSON格式里的,服務(wù)ID,屬性字段名稱,屬性值類型,在前面創(chuàng)建產(chǎn)品的時(shí)候就已經(jīng)介紹了,不記得可以翻到前面去查看。
根據(jù)這個(gè)格式,組合一次上傳的屬性數(shù)據(jù):
{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}
3.6 MQTT三元組
MQTT協(xié)議登錄需要填用戶ID,設(shè)備ID,設(shè)備密碼等信息,就像我們平時(shí)登錄QQ,微信一樣要輸入賬號(hào)密碼才能登錄。MQTT協(xié)議登錄的這3個(gè)參數(shù),一般稱為MQTT三元組。
接下來介紹,華為云平臺(tái)的MQTT三元組參數(shù)如何得到。
(1)MQTT服務(wù)器地址
要登錄MQTT服務(wù)器,首先記得先知道服務(wù)器的地址是多少,端口是多少。
幫助文檔地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home
MQTT協(xié)議的端口支持1883和8883,它們的區(qū)別是:8883 是加密端口更加安全。但是單片機(jī)上使用比較困難,所以當(dāng)前的設(shè)備是采用1883端口進(jìn)連接的。
根據(jù)上面的域名和端口號(hào),得到下面的IP地址和端口號(hào)信息: 如果設(shè)備支持填寫域名可以直接填域名,不支持就直接填寫IP地址。 (IP地址就是域名解析得到的)
華為云的MQTT服務(wù)器地址:117.78.5.125
華為云的MQTT端口號(hào):1883
如何得到IP地址?如何域名轉(zhuǎn)IP? 打開Windows的命令行輸入以下命令。
ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com
(2)生成MQTT三元組
華為云提供了一個(gè)在線工具,用來生成MQTT鑒權(quán)三元組: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打開這個(gè)工具,填入設(shè)備的信息(也就是剛才創(chuàng)建完設(shè)備之后保存的信息),點(diǎn)擊生成,就可以得到MQTT的登錄信息了。
下面是打開的頁面:
填入設(shè)備的信息: (上面兩行就是設(shè)備創(chuàng)建完成之后保存得到的)
直接得到三元組信息。
得到三元組之后,設(shè)備端通過MQTT協(xié)議登錄鑒權(quán)的時(shí)候,填入?yún)?shù)即可。
ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911
Username 663cb18871d845632a0912e7_dev1
Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237
3.7 模擬設(shè)備登錄測試
經(jīng)過上面的步驟介紹,已經(jīng)創(chuàng)建了產(chǎn)品,設(shè)備,數(shù)據(jù)模型,得到MQTT登錄信息。 接下來就用MQTT客戶端軟件模擬真實(shí)的設(shè)備來登錄平臺(tái)。測試與服務(wù)器通信是否正常。
(1)填入登錄信息
打開MQTT客戶端軟件,對號(hào)填入相關(guān)信息(就是上面的文本介紹)。然后,點(diǎn)擊登錄,訂閱主題,發(fā)布主題。
(2)打開網(wǎng)頁查看
完成上面的操作之后,打開華為云網(wǎng)頁后臺(tái),可以看到設(shè)備已經(jīng)在線了。
點(diǎn)擊詳情頁面,可以看到上傳的數(shù)據(jù):
到此,云平臺(tái)的部署已經(jīng)完成,設(shè)備已經(jīng)可以正常上傳數(shù)據(jù)了。
(3)MQTT登錄測試參數(shù)總結(jié)
MQTT服務(wù)器: 117.78.5.125
MQTT端口號(hào): 183
//物聯(lián)網(wǎng)服務(wù)器的設(shè)備信息
#define MQTT_ClientID "663cb18871d845632a0912e7_dev1_0_0_2024050911"
#define MQTT_UserName "663cb18871d845632a0912e7_dev1"
#define MQTT_PassWord "71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237"
//訂閱與發(fā)布的主題
#define SET_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down" //訂閱
#define POST_TOPIC "$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report" //發(fā)布
發(fā)布的數(shù)據(jù):
{"services": [{"service_id": "stm32","properties":{"DHT11_T":30,"DHT11_H":10,"BH1750":1,"MQ135":0}}]}
3.8 創(chuàng)建IAM賬戶
創(chuàng)建一個(gè)IAM賬戶,因?yàn)榻酉聛黹_發(fā)上位機(jī),需要使用云平臺(tái)的API接口,這些接口都需要token進(jìn)行鑒權(quán)。簡單來說,就是身份的認(rèn)證。 調(diào)用接口獲取Token時(shí),就需要填寫IAM賬號(hào)信息。所以,接下來演示一下過程。
地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users
**【1】獲取項(xiàng)目憑證 ** 點(diǎn)擊左上角用戶名,選擇下拉菜單里的我的憑證
項(xiàng)目憑證:
28add376c01e4a61ac8b621c714bf459
【2】創(chuàng)建IAM用戶
鼠標(biāo)放在左上角頭像上,在下拉菜單里選擇統(tǒng)一身份認(rèn)證
。
點(diǎn)擊左上角創(chuàng)建用戶
。
創(chuàng)建成功:
【3】創(chuàng)建完成
用戶信息如下:
主用戶名 l19504562721
IAM用戶 ds_abc
密碼 DS12345678
3.9 獲取影子數(shù)據(jù)
幫助文檔:https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html
設(shè)備影子介紹:
設(shè)備影子是一個(gè)用于存儲(chǔ)和檢索設(shè)備當(dāng)前狀態(tài)信息的JSON文檔。
每個(gè)設(shè)備有且只有一個(gè)設(shè)備影子,由設(shè)備ID唯一標(biāo)識(shí)
設(shè)備影子僅保存最近一次設(shè)備的上報(bào)數(shù)據(jù)和預(yù)期數(shù)據(jù)
無論該設(shè)備是否在線,都可以通過該影子獲取和設(shè)置設(shè)備的屬性
簡單來說:設(shè)備影子就是保存,設(shè)備最新上傳的一次數(shù)據(jù)。
我們設(shè)計(jì)的軟件里,如果想要獲取設(shè)備的最新狀態(tài)信息,就采用設(shè)備影子接口。
如果對接口不熟悉,可以先進(jìn)行在線調(diào)試:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow
在線調(diào)試接口,可以請求影子接口,了解請求,與返回的數(shù)據(jù)格式。
調(diào)試完成看右下角的響應(yīng)體,就是返回的影子數(shù)據(jù)。
設(shè)備影子接口返回的數(shù)據(jù)如下:
{
"device_id": "663cb18871d845632a0912e7_dev1",
"shadow": [
{
"service_id": "stm32",
"desired": {
"properties": null,
"event_time": null
},
"reported": {
"properties": {
"DHT11_T": 18,
"DHT11_H": 90,
"BH1750": 38,
"MQ135": 70
},
"event_time": "20240509T113448Z"
},
"version": 3
}
]
}
調(diào)試成功之后,可以得到訪問影子數(shù)據(jù)的真實(shí)鏈接,接下來的代碼開發(fā)中,就采用Qt寫代碼訪問此鏈接,獲取影子數(shù)據(jù),完成上位機(jī)開發(fā)。
鏈接如下:
https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow
四、圖形化界面開發(fā)
4.1 安裝PyQt5
為了方便能直觀的展示項(xiàng)目的整體功能,接下來安裝PyQt,完成MQTT調(diào)試助手的設(shè)計(jì)。
在Python中安裝PyQt庫非常簡單,可以使用pip
這個(gè)包管理工具來完成。PyQt有兩個(gè)主要版本:PyQt5(基于Qt 5)和PyQt6(基于Qt 6)。
我這里安裝Qt5,以Qt5為例進(jìn)行開發(fā)。
要安裝PyQt5,打開命令行界面,然后運(yùn)行以下命令:
pip install PyQt5
安裝過程中:
安裝完畢。
4.2 安裝QtDesigner
如果想使用PyQt5的設(shè)計(jì)工具(Qt Designer),用圖形方式設(shè)計(jì)界面,可以安裝pyqt5-tools
:
pip install pyqt5-tools
安裝過程如下:
安裝過程中
安裝完畢。
4.3 測試Qt環(huán)境
安裝完成后,先寫一份測試代碼,創(chuàng)建一個(gè)窗口,運(yùn)行測試Qt環(huán)境是否正常。
新建一個(gè)文件:hello_pyqt.py
編寫代碼如下:
import sys
from PyQt5.QtWidgets import QApplication, QWidget # 如果使用PyQt6,這里改為 from PyQt6.QtWidgets import QApplication, QWidget
app = QApplication(sys.argv)
window = QWidget()
window.setWindowTitle('Hello PyQt')
window.show()
sys.exit(app.exec_())
在終端命令行中運(yùn)行:
python3 hello_pyqt.py
如果一切正常,應(yīng)該能看到一個(gè)標(biāo)題為Hello PyQt
的空白窗口。這表明PyQt已經(jīng)成功安裝并且可以正常使用了。
運(yùn)行效果如下:
4.4 編寫MQTT調(diào)試助手【設(shè)計(jì)界面】
下面是基于PyQt5 的設(shè)計(jì)的MQTT調(diào)試助手,當(dāng)前只是設(shè)計(jì)了界面,沒有設(shè)計(jì)功能。
import sys
from PyQt5.QtCore import Qt # 導(dǎo)入Qt核心模塊,包含Qt的基礎(chǔ)功能
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLabel, QLineEdit, QSpinBox, QPushButton, QGridLayout, QGroupBox, QPlainTextEdit, QSpacerItem, QSizePolicy, QMenuBar, QStatusBar # 導(dǎo)入PyQt5組件
class MainWindow(QMainWindow): # 創(chuàng)建主窗口類,繼承自QMainWindow
def __init__(self):
super().__init__()
self.setWindowTitle("MainWindow") # 設(shè)置窗口標(biāo)題
self.setGeometry(100, 100, 1019, 772) # 設(shè)置窗口位置和大小
self.centralWidget = QWidget(self) # 創(chuàng)建一個(gè)中央控件
self.setCentralWidget(self.centralWidget) # 設(shè)置中央控件為上面創(chuàng)建的控件
# 主布局
self.mainLayout = QVBoxLayout(self.centralWidget) # 創(chuàng)建一個(gè)垂直布局
# 連接設(shè)置布局
self.connectionLayout = QHBoxLayout() # 創(chuàng)建水平布局,用于連接設(shè)置
# 創(chuàng)建表單布局,添加各個(gè)輸入框
self.formLayout = QFormLayout()
self.hostLineEdit = QLineEdit() # 創(chuàng)建一個(gè)文本框
self.hostLineEdit.setText("117.78.5.125") # 設(shè)置默認(rèn)服務(wù)器IP地址
self.formLayout.addRow(QLabel("服務(wù)器域名或者IP地址:"), self.hostLineEdit) # 添加一個(gè)標(biāo)簽和文本框
# 端口號(hào)使用QSpinBox
self.spinBoxPort = QSpinBox() # 創(chuàng)建一個(gè)整數(shù)框
self.spinBoxPort.setMaximum(99999) # 設(shè)置最大值為99999
self.spinBoxPort.setValue(1883) # 設(shè)置默認(rèn)端口號(hào)為1883
self.formLayout.addRow(QLabel("服務(wù)器端口:"), self.spinBoxPort) # 添加端口號(hào)輸入框
# 客戶端ID輸入框
self.clientIdLineEdit = QLineEdit()
self.clientIdLineEdit.setText("6746c32eef99673c8ad0812e_dev1_0_0_2024112707") # 預(yù)設(shè)客戶端ID
self.formLayout.addRow(QLabel("ClientId"), self.clientIdLineEdit) # 添加客戶端ID輸入框
# 用戶名輸入框
self.usernameLineEdit = QLineEdit()
self.usernameLineEdit.setText("6746c32eef99673c8ad0812e_dev1") # 預(yù)設(shè)用戶名
self.formLayout.addRow(QLabel("Username"), self.usernameLineEdit) # 添加用戶名輸入框
# 密碼輸入框
self.passwordLineEdit = QLineEdit()
self.passwordLineEdit.setText("b69234ba506cf2c1c579c4fd407a0a801479a672032fcf5ab9ea126abcf2a8b1") # 預(yù)設(shè)密碼
self.formLayout.addRow(QLabel("Password"), self.passwordLineEdit) # 添加密碼輸入框
self.connectionLayout.addLayout(self.formLayout) # 將表單布局添加到連接設(shè)置布局中
# 連接按鈕
self.connectButton = QPushButton("Connect") # 創(chuàng)建連接按鈕
self.connectionLayout.addWidget(self.connectButton) # 將按鈕添加到連接設(shè)置布局中
# 將連接設(shè)置布局添加到主布局中
self.mainLayout.addLayout(self.connectionLayout)
# MQTT 主題和消息布局
self.gridLayout = QGridLayout() # 創(chuàng)建網(wǎng)格布局
self.gridLayout.addWidget(QLabel("訂閱主題:"), 0, 0) # 添加訂閱主題標(biāo)簽
self.subscribeTopicLineEdit = QLineEdit("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/messages/down") # 設(shè)置默認(rèn)訂閱主題
self.gridLayout.addWidget(self.subscribeTopicLineEdit, 0, 1) # 添加訂閱主題文本框
self.gridLayout.addWidget(QPushButton("訂閱"), 0, 2) # 添加訂閱按鈕
self.gridLayout.addWidget(QLabel("發(fā)布主題:"), 1, 0) # 添加發(fā)布主題標(biāo)簽
self.publishTopicLineEdit = QLineEdit("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/properties/report") # 設(shè)置默認(rèn)發(fā)布主題
self.gridLayout.addWidget(self.publishTopicLineEdit, 1, 1) # 添加發(fā)布主題文本框
self.gridLayout.addWidget(QLabel("主題消息:"), 2, 0) # 添加主題消息標(biāo)簽
self.messageLineEdit = QLineEdit() # 創(chuàng)建主題消息輸入框
self.gridLayout.addWidget(self.messageLineEdit, 2, 1) # 添加主題消息文本框
self.gridLayout.addWidget(QPushButton("發(fā)布"), 2, 2) # 添加發(fā)布按鈕
self.gridLayout.addWidget(QPushButton("點(diǎn)擊發(fā)送心跳包"), 3, 2) # 添加心跳包按鈕
self.mainLayout.addLayout(self.gridLayout) # 將網(wǎng)格布局添加到主布局中
# 日志顯示區(qū)域
self.logGroupBox = QGroupBox("日志消息:") # 創(chuàng)建一個(gè)日志組框
self.logLayout = QHBoxLayout() # 創(chuàng)建水平布局
self.logTextEdit = QPlainTextEdit() # 創(chuàng)建一個(gè)只讀文本框用于顯示日志
self.logTextEdit.setReadOnly(True) # 設(shè)置文本框?yàn)橹蛔x模式
self.logLayout.addWidget(self.logTextEdit) # 將文本框添加到布局中
self.logGroupBox.setLayout(self.logLayout) # 設(shè)置組框布局
self.mainLayout.addWidget(self.logGroupBox) # 將日志組框添加到主布局中
# 底部按鈕布局
self.bottomLayout = QHBoxLayout() # 創(chuàng)建水平布局用于底部按鈕
# 創(chuàng)建底部按鈕
self.testButton = QPushButton("測試按鈕(一鍵填充MQTT信息)")
self.clearButton = QPushButton("一鍵清除MQTT信息")
self.clearLogButton = QPushButton("清除日志消息")
self.viewTutorialButton = QPushButton("【查看物聯(lián)網(wǎng)項(xiàng)目開發(fā)教程】")
self.quitButton = QPushButton("退出軟件")
self.testButton.clicked.connect(self.fillMQTTInfo) # 連接填充按鈕點(diǎn)擊事件
self.clearButton.clicked.connect(self.clearMQTTInfo) # 連接清除按鈕點(diǎn)擊事件
self.bottomLayout.addWidget(self.testButton) # 將測試按鈕添加到底部布局
self.bottomLayout.addWidget(self.clearButton) # 將清除按鈕添加到底部布局
self.bottomLayout.addWidget(self.clearLogButton) # 將清除日志按鈕添加到底部布局
self.bottomLayout.addWidget(self.viewTutorialButton) # 將查看教程按鈕添加到底部布局
self.bottomLayout.addWidget(self.quitButton) # 將退出按鈕添加到底部布局
self.mainLayout.addLayout(self.bottomLayout) # 將底部按鈕布局添加到主布局中
# 菜單欄
self.menuBar = self.menuBar() # 創(chuàng)建菜單欄
self.fileMenu = self.menuBar.addMenu("File") # 添加“File”菜單
quitAction = self.fileMenu.addAction("Quit") # 創(chuàng)建退出菜單項(xiàng)
quitAction.triggered.connect(self.close) # 連接退出菜單項(xiàng)的點(diǎn)擊事件
# 狀態(tài)欄
self.statusBar = QStatusBar() # 創(chuàng)建狀態(tài)欄
self.setStatusBar(self.statusBar) # 設(shè)置窗口的狀態(tài)欄
# 填充MQTT信息的函數(shù)
def fillMQTTInfo(self):
"""填充MQTT服務(wù)器信息到表單字段中"""
self.hostLineEdit.setText("117.78.5.125") # 設(shè)置服務(wù)器IP地址
self.spinBoxPort.setValue(1883) # 設(shè)置端口號(hào)
self.clientIdLineEdit.setText("6746c32eef99673c8ad0812e_dev1_0_0_2024112707") # 設(shè)置客戶端ID
self.usernameLineEdit.setText("6746c32eef99673c8ad0812e_dev1") # 設(shè)置用戶名
self.passwordLineEdit.setText("b69234ba506cf2c1c579c4fd407a0a801479a672032fcf5ab9ea126abcf2a8b1") # 設(shè)置密碼
self.subscribeTopicLineEdit.setText("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/messages/down") # 設(shè)置訂閱主題
self.publishTopicLineEdit.setText("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/properties/report") # 設(shè)置發(fā)布主題
# 清除MQTT信息的函數(shù)
def clearMQTTInfo(self):
"""清除MQTT服務(wù)器信息從表單字段中"""
self.hostLineEdit.clear() # 清空IP地址輸入框
self.spinBoxPort.clear() # 清空端口號(hào)輸入框
self.clientIdLineEdit.clear() # 清空客戶端ID輸入框
self.usernameLineEdit.clear() # 清空用戶名輸入框
self.passwordLineEdit.clear() # 清空密碼輸入框
self.subscribeTopicLineEdit.clear() # 清空訂閱主題輸入框
self.publishTopicLineEdit.clear() # 清空發(fā)布主題輸入框
if __name__ == '__main__':
app = QApplication(sys.argv) # 創(chuàng)建應(yīng)用實(shí)例
mainWin = MainWindow() # 創(chuàng)建主窗口實(shí)例
mainWin.show() # 顯示主窗口
sys.exit(app.exec_()) # 啟動(dòng)應(yīng)用并等待退出
4.5 運(yùn)行結(jié)果
運(yùn)行效果:
五、MQTT客戶端開發(fā)
完成 MQTT 客戶端調(diào)試助手整體開發(fā),基于 paho-mqtt
庫來實(shí)現(xiàn)以下功能:
- 連接到 MQTT 服務(wù)器 :通過提供的 IP、端口、客戶端 ID、用戶名和密碼連接到 MQTT 服務(wù)器。
- 訂閱主題 :從用戶輸入的訂閱主題中接收消息。
- 發(fā)布消息 :發(fā)布主題消息到指定的發(fā)布主題。
- 心跳包功能 :通過發(fā)送保活消息來保持與服務(wù)器的連接。
每個(gè)按鈕添加相應(yīng)的功能:Connect
、訂閱
、發(fā)布
和 心跳包
。在此基礎(chǔ)上,日志框?qū)@示與 MQTT 連接和消息傳輸相關(guān)的調(diào)試信息。
import sys
import json
import paho.mqtt.client as mqtt # 導(dǎo)入 paho-mqtt 庫
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QFormLayout, QLabel, QLineEdit, QSpinBox, QPushButton, QGridLayout, QGroupBox, QPlainTextEdit, QSpacerItem, QSizePolicy, QMenuBar, QStatusBar
class MQTTClientDebugger(QMainWindow):
def __init__(self):
super().__init__()
self.setWindowTitle("MQTT 客戶端調(diào)試助手")
self.setGeometry(100, 100, 1019, 772) # 設(shè)置窗口大小
self.centralWidget = QWidget(self)
self.setCentralWidget(self.centralWidget)
self.client = None # MQTT 客戶端實(shí)例
# 主布局
self.mainLayout = QVBoxLayout(self.centralWidget)
# 連接設(shè)置布局
self.connectionLayout = QHBoxLayout()
self.formLayout = QFormLayout()
self.hostLineEdit = QLineEdit()
self.hostLineEdit.setText("117.78.5.125") # 默認(rèn)服務(wù)器IP地址
self.formLayout.addRow(QLabel("服務(wù)器域名或者IP地址:"), self.hostLineEdit)
# 端口號(hào)
self.spinBoxPort = QSpinBox()
self.spinBoxPort.setMaximum(99999)
self.spinBoxPort.setValue(1883) # 默認(rèn)端口號(hào)
self.formLayout.addRow(QLabel("服務(wù)器端口:"), self.spinBoxPort)
self.clientIdLineEdit = QLineEdit()
self.clientIdLineEdit.setText("6746c32eef99673c8ad0812e_dev1_0_0_2024112707") # 默認(rèn)客戶端ID
self.formLayout.addRow(QLabel("ClientId"), self.clientIdLineEdit)
self.usernameLineEdit = QLineEdit()
self.usernameLineEdit.setText("6746c32eef99673c8ad0812e_dev1") # 默認(rèn)用戶名
self.formLayout.addRow(QLabel("Username"), self.usernameLineEdit)
self.passwordLineEdit = QLineEdit()
self.passwordLineEdit.setText("b69234ba506cf2c1c579c4fd407a0a801479a672032fcf5ab9ea126abcf2a8b1") # 默認(rèn)密碼
self.formLayout.addRow(QLabel("Password"), self.passwordLineEdit)
self.connectionLayout.addLayout(self.formLayout)
# 連接按鈕
self.connectButton = QPushButton("Connect")
self.connectButton.clicked.connect(self.connect_to_server)
self.connectionLayout.addWidget(self.connectButton)
self.mainLayout.addLayout(self.connectionLayout)
# MQTT 主題和消息布局
self.gridLayout = QGridLayout()
self.gridLayout.addWidget(QLabel("訂閱主題:"), 0, 0)
self.subscribeTopicLineEdit = QLineEdit("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/messages/down")
self.gridLayout.addWidget(self.subscribeTopicLineEdit, 0, 1)
self.gridLayout.addWidget(QPushButton("訂閱"), 0, 2)
self.gridLayout.addWidget(QLabel("發(fā)布主題:"), 1, 0)
self.publishTopicLineEdit = QLineEdit("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/properties/report")
self.gridLayout.addWidget(self.publishTopicLineEdit, 1, 1)
self.gridLayout.addWidget(QLabel("主題消息:"), 2, 0)
self.messageLineEdit = QLineEdit()
self.gridLayout.addWidget(self.messageLineEdit, 2, 1)
self.gridLayout.addWidget(QPushButton("發(fā)布"), 2, 2)
self.gridLayout.addWidget(QPushButton("點(diǎn)擊發(fā)送心跳包"), 3, 2)
self.mainLayout.addLayout(self.gridLayout)
# 日志區(qū)域
self.logGroupBox = QGroupBox("日志消息:")
self.logLayout = QHBoxLayout()
self.logTextEdit = QPlainTextEdit()
self.logTextEdit.setReadOnly(True)
self.logLayout.addWidget(self.logTextEdit)
self.logGroupBox.setLayout(self.logLayout)
self.mainLayout.addWidget(self.logGroupBox)
# 底部按鈕布局
self.bottomLayout = QHBoxLayout()
self.testButton = QPushButton("測試按鈕(一鍵填充MQTT信息)")
self.clearButton = QPushButton("一鍵清除MQTT信息")
self.clearLogButton = QPushButton("清除日志消息")
self.viewTutorialButton = QPushButton("【查看物聯(lián)網(wǎng)項(xiàng)目開發(fā)教程】")
self.quitButton = QPushButton("退出軟件")
self.testButton.clicked.connect(self.fillMQTTInfo)
self.clearButton.clicked.connect(self.clearMQTTInfo)
self.clearLogButton.clicked.connect(self.clear_logs)
self.bottomLayout.addWidget(self.testButton)
self.bottomLayout.addWidget(self.clearButton)
self.bottomLayout.addWidget(self.clearLogButton)
self.bottomLayout.addWidget(self.viewTutorialButton)
self.bottomLayout.addWidget(self.quitButton)
self.mainLayout.addLayout(self.bottomLayout)
# 菜單欄
self.menuBar = self.menuBar()
self.fileMenu = self.menuBar.addMenu("File")
quitAction = self.fileMenu.addAction("Quit")
quitAction.triggered.connect(self.close)
# 狀態(tài)欄
self.statusBar = QStatusBar()
self.setStatusBar(self.statusBar)
# 連接到MQTT服務(wù)器
def connect_to_server(self):
host = self.hostLineEdit.text()
port = self.spinBoxPort.value()
client_id = self.clientIdLineEdit.text()
username = self.usernameLineEdit.text()
password = self.passwordLineEdit.text()
self.client = mqtt.Client(client_id)
self.client.username_pw_set(username, password) # 設(shè)置用戶名和密碼
# 設(shè)置連接成功、消息接收、連接丟失等回調(diào)函數(shù)
self.client.on_connect = self.on_connect
self.client.on_message = self.on_message
self.client.on_disconnect = self.on_disconnect
# 連接到服務(wù)器
self.client.connect(host, port, 60)
# 啟動(dòng) MQTT 客戶端
self.client.loop_start()
def on_connect(self, client, userdata, flags, rc):
"""當(dāng)連接到MQTT服務(wù)器時(shí)調(diào)用"""
self.log(f"連接成功,返回碼:{rc}")
# 連接成功后訂閱主題
subscribe_topic = self.subscribeTopicLineEdit.text()
client.subscribe(subscribe_topic)
def on_message(self, client, userdata, msg):
"""當(dāng)接收到MQTT消息時(shí)調(diào)用"""
self.log(f"接收到消息:{msg.topic} {msg.payload.decode()}")
def on_disconnect(self, client, userdata, rc):
"""當(dāng)斷開連接時(shí)調(diào)用"""
self.log(f"MQTT服務(wù)器斷開連接,返回碼:{rc}")
# 發(fā)布消息
def publish_message(self):
topic = self.publishTopicLineEdit.text()
message = self.messageLineEdit.text()
if self.client:
self.client.publish(topic, message)
self.log(f"發(fā)布消息:{topic} {message}")
# 發(fā)送心跳包
def send_heartbeat(self):
if self.client:
self.client.ping()
self.log("發(fā)送心跳包")
# 日志輸出
def log(self, message):
"""向日志框輸出信息"""
self.logTextEdit.appendPlainText(message)
# 填充MQTT信息
def fillMQTTInfo(self):
self.hostLineEdit.setText("117.78.5.125")
self.spinBoxPort.setValue(1883)
self.clientIdLineEdit.setText("6746c32eef99673c8ad0812e_dev1_0_0_2024112707")
self.usernameLineEdit.setText("6746c32eef99673c8ad0812e_dev1")
self.passwordLineEdit.setText("b69234ba506cf2c1c579c4fd407a0a801479a672032fcf5ab9ea126abcf2a8b1")
self.subscribeTopicLineEdit.setText("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/messages/down")
self.publishTopicLineEdit.setText("$oc/devices/6746c32eef99673c8ad0812e_dev1/sys/properties/report")
self.messageLineEdit.setText('{"services": [{"service_id": "stm32","properties":{"DHT11_T":18.1,"DHT11_H":16.2,"SOIL":12.4,"BH1750":124.5,"MOTOR_SW":1,"SOIL_MAX":30,"run_mode":1}}]}')
# 清除MQTT信息
def clearMQTTInfo(self):
self.hostLineEdit.clear()
self.spinBoxPort.clear()
self.clientIdLineEdit.clear()
self.usernameLineEdit.clear()
self.passwordLineEdit.clear()
self.subscribeTopicLineEdit.clear()
self.publishTopicLineEdit.clear()
# 清除日志信息
def clear_logs(self):
self.logTextEdit.clear()
if __name__ == '__main__':
app = QApplication(sys.argv)
mainWin = MQTTClientDebugger()
mainWin.show()
sys.exit(app.exec_())
六、總結(jié)
本項(xiàng)目通過結(jié)合云主機(jī)、Python編程語言、PyQt5圖形界面開發(fā)框架和paho-mqtt庫,成功實(shí)現(xiàn)了一款功能強(qiáng)大的MQTT客戶端調(diào)試助手。該工具為開發(fā)者提供一個(gè)簡便的方式,通過軟件模擬硬件設(shè)備與華為云物聯(lián)網(wǎng)平臺(tái)(IoTDA)進(jìn)行通信,完成主題訂閱和消息發(fā)布等操作。通過這一工具,即便是沒有硬件設(shè)備的開發(fā)者,或者對硬件開發(fā)不熟悉的開發(fā)者,也能夠快速上手并深入理解物聯(lián)網(wǎng)設(shè)備與云平臺(tái)之間的通信過程。
利用華為開發(fā)者空間的云主機(jī),本項(xiàng)目充分發(fā)揮了云端開發(fā)環(huán)境的優(yōu)勢,降低了本地開發(fā)環(huán)境搭建的復(fù)雜性,使得開發(fā)者能夠?qū)W⒂趹?yīng)用的開發(fā)和調(diào)試,而無需關(guān)心底層環(huán)境配置問題。通過集成的CodeArts IDE,開發(fā)者可以在統(tǒng)一的開發(fā)環(huán)境中高效地編寫、調(diào)試和運(yùn)行代碼,提升了開發(fā)效率。
項(xiàng)目采用的MQTT協(xié)議是物聯(lián)網(wǎng)通信中的核心技術(shù),通過paho-mqtt庫實(shí)現(xiàn)了與華為云物聯(lián)網(wǎng)平臺(tái)的快速對接和可靠通信。該庫為開發(fā)者提供了易于使用的API,支持靈活的消息發(fā)布與訂閱操作,并通過連接管理、自動(dòng)重連等功能,確保了客戶端與云平臺(tái)的穩(wěn)定通信。
在界面設(shè)計(jì)上,PyQt5為項(xiàng)目提供了直觀、易操作的圖形化界面,用戶可以通過簡單的操作實(shí)現(xiàn)復(fù)雜的MQTT通信功能,極大地提升了用戶體驗(yàn)。借助這種圖形化界面,開發(fā)者不僅能夠方便地調(diào)試物聯(lián)網(wǎng)應(yīng)用,還能夠在沒有實(shí)際硬件的情況下,模擬設(shè)備與云平臺(tái)的通信過程,從而加速了物聯(lián)網(wǎng)應(yīng)用的學(xué)習(xí)和開發(fā)。
本項(xiàng)目不僅為開發(fā)者提供了一個(gè)功能完備的調(diào)試工具,也為物聯(lián)網(wǎng)應(yīng)用的學(xué)習(xí)和開發(fā)提供了寶貴的實(shí)踐機(jī)會(huì)。無論是在測試調(diào)試階段,還是在實(shí)際應(yīng)用中,開發(fā)者都能夠通過該工具深入理解MQTT協(xié)議、物聯(lián)網(wǎng)通信機(jī)制和云平臺(tái)集成的基本流程,為未來的物聯(lián)網(wǎng)項(xiàng)目開發(fā)打下堅(jiān)實(shí)的基礎(chǔ)。同時(shí),本項(xiàng)目的實(shí)現(xiàn)也展示了云端開發(fā)和虛擬化硬件仿真技術(shù)在物聯(lián)網(wǎng)領(lǐng)域中的巨大潛力,推動(dòng)了物聯(lián)網(wǎng)開發(fā)者社區(qū)的普及和技術(shù)創(chuàng)新。
審核編輯 黃宇
-
仿真
+關(guān)注
關(guān)注
50文章
4108瀏覽量
133778 -
STM32
+關(guān)注
關(guān)注
2270文章
10914瀏覽量
356716 -
硬件
+關(guān)注
關(guān)注
11文章
3352瀏覽量
66331 -
MQTT
+關(guān)注
關(guān)注
5文章
653瀏覽量
22582 -
華為云
+關(guān)注
關(guān)注
3文章
2653瀏覽量
17496
發(fā)布評(píng)論請先 登錄
相關(guān)推薦
評(píng)論