• 正文
    • 一、前言
    • 二、硬件選型(搭建模型參考)
    • 三、部署華為云物聯(lián)網(wǎng)平臺
    • 四、STM32設備端代碼設計
    • 五、上位機開發(fā)
    • 六、總結(jié)
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STM32設計的智能防盜單車鎖

04/09 10:07
861
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

一、前言

1.1 項目開發(fā)背景

在現(xiàn)代城市交通日益便捷的背景下,單車以其綠色環(huán)保、便于停放的優(yōu)點成為了人們短途出行的重要工具。然而,隨之而來的單車被盜問題也日益嚴重,尤其是在城市的公共區(qū)域或偏僻地帶,傳統(tǒng)的機械鎖缺乏智能化手段,一旦遭遇非法移動或破壞,用戶很難第一時間獲知,從而造成財產(chǎn)損失。因此,設計一款具備智能化、聯(lián)網(wǎng)化、遠程監(jiān)控能力的單車防盜鎖成為了當前智能出行領(lǐng)域的一項實際需求。

隨著物聯(lián)網(wǎng)技術(shù)的快速發(fā)展,嵌入式系統(tǒng)移動通信技術(shù)的融合愈發(fā)緊密,為智能防盜系統(tǒng)的設計提供了可靠的技術(shù)支撐。STM32系列單片機具備處理能力強、資源豐富、低功耗等特點,適合部署在需要實時響應和長期穩(wěn)定運行的應用場景中。而4G通信模塊則提供了在無WiFi環(huán)境下的高速網(wǎng)絡連接,尤其適用于戶外場景的單車設備,實現(xiàn)數(shù)據(jù)的遠程上傳與控制。同時,借助GPS模塊實現(xiàn)對車輛位置的精準定位,使得車輛被盜后能快速追蹤,為用戶提供更強的安全保障。

為了提升用戶體驗,本項目還引入了OLED顯示屏用于本地狀態(tài)提示,蜂鳴器實現(xiàn)現(xiàn)場聲響報警,結(jié)合APP彈窗提醒與短信告警的多重通知方式,增強系統(tǒng)的實時性和可靠性。APP與上位機均采用MQTT協(xié)議接入華為云物聯(lián)網(wǎng)平臺,實現(xiàn)多終端、跨平臺的數(shù)據(jù)共享與控制,提升系統(tǒng)智能化和可擴展性。

因此,本項目“基于STM32設計的智能防盜單車鎖”不僅聚焦于實際生活中的防盜需求,也融合了當下先進的嵌入式控制、移動通信和物聯(lián)網(wǎng)技術(shù),具有較強的應用前景和推廣價值,能夠為智能交通領(lǐng)域提供一種可行的、低成本的智能安全解決方案。

1.2 設計實現(xiàn)的功能

(1)智能防盜報警功能
當單車處于鎖車狀態(tài)時,如果被非法移動,系統(tǒng)通過加速度傳感器檢測到位移后,立即觸發(fā)本地蜂鳴器發(fā)出聲響進行報警。同時通過4G模塊向預設的手機號碼發(fā)送報警短信,并通過MQTT協(xié)議上傳報警信息至華為云物聯(lián)網(wǎng)平臺,Android APP和Windows上位機將彈出提醒窗口,提示用戶單車被移動,增強安全性與及時性。

(2)遠程監(jiān)控與控制功能
通過華為云IOT物聯(lián)網(wǎng)平臺,用戶可以通過Android APP或Windows上位機查看設備當前狀態(tài),包括鎖的開關(guān)狀態(tài)、報警狀態(tài)、GPS定位信息等。同時,用戶還可以通過遠程操作實現(xiàn)對鎖的開關(guān)控制,真正實現(xiàn)智能化的單車鎖管理。

(3)數(shù)據(jù)上云功能
系統(tǒng)通過Air724UG 4G模塊接入互聯(lián)網(wǎng),采用MQTT協(xié)議將鎖的開關(guān)狀態(tài)、GPS定位信息、報警狀態(tài)等數(shù)據(jù)實時上傳至華為云IOT平臺,支持多終端訪問和實時數(shù)據(jù)監(jiān)控,提升系統(tǒng)的可靠性與管理便捷性。

(4)短信告警功能
設備具備短信發(fā)送能力,借助Air724UG模塊內(nèi)置的短信功能,一旦發(fā)生非法移動事件,除上傳云端外,還會同步發(fā)送短信至預設用戶手機,確保即使在無網(wǎng)絡狀態(tài)下也能接收警報信息。

(5)GPS實時定位功能
采用ATGM336H-5N GPS模塊,實時獲取當前設備地理位置,并通過4G模塊上傳至云平臺,用戶可在APP或上位機地圖界面上查看車輛位置,為車輛防盜追蹤提供支持。

(6)本地OLED信息顯示功能
設備配備0.96寸SPI OLED顯示屏,可實時顯示鎖的當前狀態(tài)(如“已鎖定”“已解鎖”)、GPS信號狀態(tài)等關(guān)鍵信息,方便用戶通過屏幕快速掌握設備運行狀態(tài)。

(7)蜂鳴器本地聲響報警功能
當系統(tǒng)判斷存在異常移動時,立即驅(qū)動高電平觸發(fā)的有源蜂鳴器發(fā)出聲響,具備現(xiàn)場即時報警功能,威懾潛在盜竊行為。

(8)低功耗與可擴展供電功能
設備主供電采用14500鋰電池,滿足低功耗便攜應用需求,同時預留太陽能供電擴展接口,支持在戶外環(huán)境下的長時間無人值守運行。

(9)跨平臺APP與上位機控制界面
Android手機APP和Windows上位機軟件均采用QT5(C++)開發(fā),界面統(tǒng)一、美觀,支持多平臺查看設備狀態(tài)、接收報警提醒和控制操作,提高用戶使用體驗與系統(tǒng)通用性。

1.3 項目硬件模塊組成

(1)STM32F103RCT6主控模塊
作為系統(tǒng)核心控制單元,負責處理各類傳感器數(shù)據(jù)、控制執(zhí)行模塊、通信管理、數(shù)據(jù)上傳及本地信息顯示等任務,所有邏輯控制與功能實現(xiàn)均基于該芯片完成。

(2)Air724UG 4G通信模塊
用于實現(xiàn)設備與華為云物聯(lián)網(wǎng)平臺的遠程通信,支持MQTT協(xié)議進行數(shù)據(jù)上云,同時集成短信功能,能在單車被移動時向用戶發(fā)送短信報警信息。

(3)ATGM336H-5N GPS定位模塊
用于實時獲取設備的地理位置信息,采集經(jīng)緯度數(shù)據(jù),通過STM32上傳至云平臺,實現(xiàn)遠程地圖定位及軌跡追蹤功能。

(4)ADXL345三軸加速度傳感器模塊
用于監(jiān)測車輛在鎖車狀態(tài)下是否發(fā)生移動,通過檢測姿態(tài)變化判斷是否觸發(fā)防盜報警邏輯,是實現(xiàn)智能防盜的關(guān)鍵傳感器模塊。

(5)0.96寸SPI OLED顯示模塊
用于顯示鎖的當前狀態(tài)、GPS模塊狀態(tài)、網(wǎng)絡連接情況等信息,為用戶提供直觀的本地交互界面,提升使用便捷性與信息透明度。

(6)高電平觸發(fā)有源蜂鳴器模塊
在檢測到非法移動時由STM32驅(qū)動發(fā)出高分貝聲響,起到警示與威懾作用,是本地聲響報警的執(zhí)行裝置。

(7)鋰電池供電模塊(14500鋰電池)
為整套系統(tǒng)提供便攜式供電,支持長時間戶外運行,同時預留接口,可外接太陽能板,實現(xiàn)綠色能源補充與連續(xù)運行保障。

(8)硬件連接模塊(洞洞板+杜邦線/焊接)
整套硬件系統(tǒng)搭建于洞洞板(萬能板)上,模塊之間通過杜邦線或焊接方式連接,方便原型搭建、系統(tǒng)調(diào)試與后期維護,是硬件搭建的基礎平臺。

(9)調(diào)試與串口通信模塊
包含用于程序燒錄的串口接口、電源控制接口及串口調(diào)試接口,用于開發(fā)過程中進行程序下載、數(shù)據(jù)監(jiān)測及調(diào)試信息輸出,保障開發(fā)效率與系統(tǒng)穩(wěn)定性。

1.4 設計思路

本項目設計并實現(xiàn)一款基于STM32的智能防盜單車鎖系統(tǒng),結(jié)合物聯(lián)網(wǎng)技術(shù)實現(xiàn)遠程監(jiān)控、報警提醒和狀態(tài)管理。設計思路以“本地智能識別+遠程數(shù)據(jù)聯(lián)動”為核心,融合硬件控制、無線通信和云平臺服務,實現(xiàn)一套既具備本地防護能力又支持遠程操作的智能防盜方案。

系統(tǒng)整體架構(gòu)分為三個層級:感知層、控制層和應用層。感知層由GPS定位模塊、加速度傳感器和蜂鳴器組成,負責實時監(jiān)測車輛位置信息和狀態(tài)變化(如是否被非法移動),并在異常情況發(fā)生時立即觸發(fā)報警機制。控制層以STM32F103RCT6為核心主控,通過寄存器方式開發(fā),負責數(shù)據(jù)采集、邏輯判斷、指令執(zhí)行和與通信模塊的數(shù)據(jù)交互。應用層通過4G通信模塊(Air724UG)連接華為云IOT平臺,采用MQTT協(xié)議進行消息通信,支持將鎖的狀態(tài)、位置等數(shù)據(jù)上傳至云端,并接收遠程下發(fā)的開鎖/關(guān)鎖等控制指令。

在用戶交互方面,系統(tǒng)配備一塊0.96寸SPI OLED顯示屏,顯示當前鎖狀態(tài)和GPS工作狀態(tài),方便用戶在現(xiàn)場了解設備運行情況。同時,為滿足用戶遠程監(jiān)控需求,設計了基于QT5的Android手機APP和Windows上位機應用,實現(xiàn)遠程查看鎖狀態(tài)、地圖定位、歷史記錄查詢、短信提醒等功能,并支持一鍵遠程開關(guān)鎖。

為了適應單車戶外運行環(huán)境,系統(tǒng)采用14500鋰電池供電,并預留太陽能供電接口,實現(xiàn)綠色續(xù)航與長時間運行能力。硬件集成部分基于洞洞板搭建,采用模塊化設計思想,便于后期調(diào)試與硬件維護。整體設計在滿足安全性和實用性的基礎上,兼顧了低功耗、可擴展性與用戶操作便利性,體現(xiàn)出物聯(lián)網(wǎng)在個人交通工具智能化保護方面的應用前景。

1.5 系統(tǒng)功能總結(jié)

功能類別 功能描述
防盜報警功能 當車輛在鎖車狀態(tài)下發(fā)生移動時,系統(tǒng)通過加速度傳感器檢測異常,觸發(fā)蜂鳴器發(fā)出聲響,同時通過4G模塊發(fā)送短信提醒并在APP上彈窗報警。
遠程控制功能 用戶可通過Android手機APP或Windows上位機,遠程實現(xiàn)對單車鎖的開鎖、關(guān)鎖控制,提升用戶操作的便捷性與靈活性。
數(shù)據(jù)上云功能 設備通過Air724UG 4G模塊接入華為云IOT平臺,使用MQTT協(xié)議將鎖狀態(tài)、定位信息等實時數(shù)據(jù)上傳至云端,實現(xiàn)遠程監(jiān)控與數(shù)據(jù)記錄。
GPS定位功能 內(nèi)置GPS模塊可實時獲取設備位置信息,并上傳至云端用于地圖顯示、軌跡跟蹤、遠程查詢等,增強車輛追蹤能力。
本地顯示功能 OLED顯示屏可本地顯示鎖狀態(tài)、GPS模塊狀態(tài)、網(wǎng)絡連接情況等運行信息,方便用戶在現(xiàn)場查看設備當前狀態(tài)。
本地報警功能 內(nèi)置蜂鳴器在車輛被非法移動時自動發(fā)出高分貝報警音,對潛在盜竊行為進行震懾和提醒。
電源管理功能 系統(tǒng)采用14500鋰電池供電,支持便攜式低功耗運行,并預留太陽能供電接口,適應戶外環(huán)境下長時間運行的需求。
姿態(tài)檢測功能 通過ADXL345加速度傳感器監(jiān)測車輛姿態(tài)變化,用于判斷是否處于被移動狀態(tài),為防盜報警功能提供關(guān)鍵判斷依據(jù)。
用戶交互功能 用戶通過APP或上位機可視化界面與系統(tǒng)交互,查看鎖狀態(tài)、定位信息、報警記錄,接收通知并進行控制,提升用戶體驗與系統(tǒng)智能化程度。

1.6 模塊的技術(shù)詳情介紹

【1】Air724UG-4G模塊

Air724UG 是一款功能強大的 4G 全網(wǎng)通通信模塊,廣泛應用于物聯(lián)網(wǎng)設備中,特別適用于對數(shù)據(jù)通信、短信發(fā)送和遠程控制有較高要求的嵌入式系統(tǒng)。該模塊支持中國移動、中國聯(lián)通和中國電信的 LTE 網(wǎng)絡,具備良好的網(wǎng)絡兼容性和覆蓋能力,特別適合部署在戶外、流動性強或無WiFi覆蓋的場景中,如智能車鎖、共享設備、遠程監(jiān)控等。

Air724UG 模塊內(nèi)部集成了高性能的處理器,支持 AT 指令集,具備串口通信接口UART),可方便地與 STM32 等主控芯片進行通信。模塊支持 MQTT、TCP、HTTP等多種協(xié)議,特別是在本項目中,Air724UG 可用于將設備狀態(tài)、GPS位置信息等通過 MQTT 協(xié)議上傳至華為云物聯(lián)網(wǎng)平臺,實現(xiàn)數(shù)據(jù)上云與遠程管理。

除了數(shù)據(jù)通信功能外,Air724UG 還支持 SMS(短消息服務)功能,可通過 AT 指令實現(xiàn)短信的發(fā)送與接收。在智能防盜單車鎖項目中,當檢測到車輛被非法移動時,模塊能夠快速向預設聯(lián)系人發(fā)送報警短信,提高用戶的安全響應效率。

在供電與功耗方面,Air724UG 支持低功耗待機模式,適合依賴鋰電池供電的應用場景。同時,其體積小巧、接口標準化,方便集成到各類嵌入式設備中。此外,模塊還具備掉線自動重連、網(wǎng)絡狀態(tài)檢測等功能,提高通信的穩(wěn)定性和可靠性。

Air724UG 作為核心通信部件,在本項目中起到了“云-端”之間橋梁的關(guān)鍵作用,是實現(xiàn)智能控制、遠程監(jiān)控和移動報警的重要技術(shù)基礎。

【2】MQTT協(xié)議

MQTT(Message Queuing Telemetry Transport,消息隊列遙測傳輸協(xié)議)是一種輕量級、發(fā)布/訂閱模式的消息傳輸協(xié)議,專為低帶寬、不可靠網(wǎng)絡環(huán)境設計。它最早由IBM提出,現(xiàn)已成為物聯(lián)網(wǎng)(IoT)通信的重要協(xié)議之一。由于其高效、低功耗和實時性等特點,MQTT在智能家居、工業(yè)自動化、遠程監(jiān)控和車聯(lián)網(wǎng)等領(lǐng)域得到了廣泛應用。

MQTT的工作原理基于發(fā)布/訂閱模型。這種模型有別于傳統(tǒng)的客戶端-服務器模型,通信方不需要直接建立連接。MQTT由三個核心組件構(gòu)成:客戶端、代理(Broker)和主題(Topic)。客戶端可以作為消息的發(fā)布者或訂閱者,消息通過代理進行路由。代理是一個中間服務端,用于接收和分發(fā)來自不同客戶端的消息。發(fā)布者發(fā)送消息到一個特定的主題上,代理負責將這些消息分發(fā)給所有訂閱了該主題的客戶端。通過這種解耦的架構(gòu)設計,客戶端之間可以實現(xiàn)松耦合的通信,降低了復雜性和依賴性。

在MQTT協(xié)議中,消息被分為不同的主題(Topic),例如“home/sensor/temperature”可以用來代表溫度傳感器數(shù)據(jù)。客戶端可以訂閱這個主題,當發(fā)布者發(fā)送新的數(shù)據(jù)到該主題時,所有訂閱該主題的客戶端都會收到更新信息。這種靈活的主題結(jié)構(gòu)和層次化的命名規(guī)則,使得MQTT在復雜場景下也能快速組織和管理消息流。

MQTT協(xié)議支持三種服務質(zhì)量(QoS)等級,分別為“至多一次”(QoS 0)、“至少一次”(QoS 1)和“僅一次”(QoS 2)。QoS 0表示消息傳輸盡力而為,可能會丟失或重復;QoS 1確保消息至少送達一次,但可能會有重復;QoS 2則確保消息恰好傳輸一次,保證消息的嚴格可靠性。這種設計使MQTT能夠適應不同的應用場景,用戶可以根據(jù)應用需求選擇合適的QoS級別。

為了保證通信的安全性,MQTT支持用戶名和密碼驗證,代理可以對連接進行身份認證。此外,許多實現(xiàn)中還支持TLS/SSL加密通信,確保數(shù)據(jù)在傳輸過程中不會被竊取或篡改。用戶也可以使用不同的認證方式來增強系統(tǒng)的安全性,適應物聯(lián)網(wǎng)應用中對安全性的高需求。

MQTT非常注重輕量化和低功耗。它的報文頭非常小,通信開銷很低,這使其特別適合在資源受限的設備或不穩(wěn)定的網(wǎng)絡環(huán)境中使用。MQTT支持“保持連接”和“遺囑消息”功能,客戶端可以在連接斷開時自動向代理發(fā)送遺囑消息,通知其他客戶端連接狀態(tài)的變化。這種特性有助于提高網(wǎng)絡的健壯性和系統(tǒng)的可用性。

MQTT的典型使用場景包括物聯(lián)網(wǎng)設備數(shù)據(jù)采集、實時監(jiān)控、消息推送和控制命令的發(fā)布。比如在智能家居中,傳感器可以發(fā)布環(huán)境數(shù)據(jù),如溫濕度、煙霧濃度等,控制設備根據(jù)收到的消息作出響應,實現(xiàn)自動化操作。在工業(yè)場景中,MQTT可以幫助收集和管理大規(guī)模設備的運行狀態(tài),實現(xiàn)集中化和高效的設備監(jiān)控。

總的來說,MQTT協(xié)議憑借其低功耗、高效能、實時性強等優(yōu)勢,已成為物聯(lián)網(wǎng)通信的主要協(xié)議之一。它的發(fā)布/訂閱模式簡化了設備之間的通信,使其特別適合多對多、低延遲、高可靠性的數(shù)據(jù)傳輸場景。MQTT易于使用、拓展性強,為開發(fā)者提供了靈活的解決方案來構(gòu)建各種物聯(lián)網(wǎng)應用。

【3】中科微ATGM336H-GPS模塊

中科微ATGM336H-GPS模塊是一款高性能、低功耗的全球定位模塊,專為衛(wèi)星定位導航應用設計。該模塊集成了GNSS基帶處理器和RF接收器,支持GPS、GLONASS、BDS(北斗)等多種衛(wèi)星系統(tǒng)的定位信號,能夠?qū)崿F(xiàn)快速精準的定位,并提供穩(wěn)定可靠的位置、速度和時間數(shù)據(jù)。ATGM336H模塊廣泛應用于車輛定位、物流跟蹤、無人機導航、智能穿戴設備、戶外運動設備和物聯(lián)網(wǎng)等領(lǐng)域。

ATGM336H模塊采用小巧的LCC封裝,尺寸為16mm x 12.2mm x 2.3mm,便于集成到各種緊湊型設備中。模塊內(nèi)置高靈敏度接收芯片,具有-165dBm的高靈敏度,即使在復雜環(huán)境下也能快速捕獲和跟蹤衛(wèi)星信號。其冷啟動時間在開闊地帶一般小于30秒,熱啟動時間約為1秒,重捕獲時間小于1秒,使其在車輛移動和各種快速切換的場景下表現(xiàn)出色,定位精度可達2.5米。

該模塊支持多種工作模式,以滿足不同應用的功耗要求。它不僅可以在普通模式下連續(xù)定位,還支持周期性模式和節(jié)電模式,通過關(guān)閉部分功能或降低數(shù)據(jù)輸出頻率來減少功耗,適合電池供電的便攜式設備。其最低功耗在微安級別,能夠顯著延長電池續(xù)航時間,使其成為移動設備的理想選擇。

ATGM336H-GPS模塊的接口豐富,支持UART、I2C、SPI等多種通信接口,方便與主控MCU進行數(shù)據(jù)交換。模塊提供的標準NMEA協(xié)議輸出和二進制格式數(shù)據(jù)能夠直接對接多種導航應用程序。此外,模塊還具有內(nèi)置的天線檢測功能和動態(tài)干擾抑制技術(shù),有助于在有較強電磁干擾的環(huán)境中保持定位精度,并能實時檢測和報告天線狀態(tài),進一步提高定位可靠性。

為了提高用戶體驗和簡化開發(fā)過程,中科微為ATGM336H模塊提供了完善的開發(fā)手冊和技術(shù)支持,便于開發(fā)者快速上手并將其應用到多種設備中。此外,模塊還支持多衛(wèi)星系統(tǒng)協(xié)同定位的功能,通過融合GPS、BDS、GLONASS等衛(wèi)星數(shù)據(jù),提高在市區(qū)、高山、森林等衛(wèi)星信號受限環(huán)境下的定位精度和穩(wěn)定性,使其適用于復雜環(huán)境的高精度定位需求。

二、硬件選型(搭建模型參考)

2.1 STM32開發(fā)板

2.2 USB下載線

2.3 Air724UG 4G模塊

2.4 繼電器

2.5 蜂鳴器模塊

2.6 ADXL345 三軸加速度計模塊

2.7 OLED顯示屏

三、部署華為云物聯(lián)網(wǎng)平臺

華為云官網(wǎng): https://www.huaweicloud.com/

打開官網(wǎng),搜索物聯(lián)網(wǎng),就能快速找到?設備接入IoTDA

3.1 物聯(lián)網(wǎng)平臺介紹

華為云物聯(lián)網(wǎng)平臺(IoT 設備接入云服務)提供海量設備的接入和管理能力,將物理設備聯(lián)接到云,支撐設備數(shù)據(jù)采集上云和云端下發(fā)命令給設備進行遠程控制,配合華為云其他產(chǎn)品,幫助我們快速構(gòu)筑物聯(lián)網(wǎng)解決方案。

使用物聯(lián)網(wǎng)平臺構(gòu)建一個完整的物聯(lián)網(wǎng)解決方案主要包括3部分:物聯(lián)網(wǎng)平臺、業(yè)務應用和設備。

物聯(lián)網(wǎng)平臺作為連接業(yè)務應用和設備的中間層,屏蔽了各種復雜的設備接口,實現(xiàn)設備的快速接入;同時提供強大的開放能力,支撐行業(yè)用戶構(gòu)建各種物聯(lián)網(wǎng)解決方案。

設備可以通過固網(wǎng)、2G/3G/4G/5G、NB-IoT、Wifi等多種網(wǎng)絡接入物聯(lián)網(wǎng)平臺,并使用LWM2M/CoAP、MQTT、HTTPS協(xié)議將業(yè)務數(shù)據(jù)上報到平臺,平臺也可以將控制命令下發(fā)給設備。

業(yè)務應用通過調(diào)用物聯(lián)網(wǎng)平臺提供的API,實現(xiàn)設備數(shù)據(jù)采集、命令下發(fā)、設備管理等業(yè)務場景。

3.2 開通物聯(lián)網(wǎng)服務

地址: https://www.huaweicloud.com/product/iothub.html

開通免費單元。

點擊立即創(chuàng)建

正在創(chuàng)建標準版實例,需要等待片刻。

創(chuàng)建完成之后,點擊詳情。 可以看到標準版實例的設備接入端口和地址。

下面框起來的就是端口號域名

點擊實例名稱,可以查看當前免費單元的配置情況。

開通之后,點擊接入信息,也能查看接入信息。 我們當前設備準備采用MQTT協(xié)議接入華為云平臺,這里可以看到MQTT協(xié)議的地址和端口號等信息。

總結(jié):

端口號: ? MQTT (1883)| MQTTS (8883) ? ?
接入地址: dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com

根據(jù)域名地址得到IP地址信息:

打開Windows電腦的命令行控制臺終端,使用ping?命令。ping一下即可。

Microsoft Windows [版本 10.0.19045.5011]
(c) Microsoft Corporation。保留所有權(quán)利。

C:UsersLenovo>ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com

正在 Ping dab1a1f2c6.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字節(jié)的數(shù)據(jù):
來自 117.78.5.125 的回復: 字節(jié)=32 時間=37ms TTL=44
來自 117.78.5.125 的回復: 字節(jié)=32 時間=37ms TTL=44
來自 117.78.5.125 的回復: 字節(jié)=32 時間=37ms TTL=44
來自 117.78.5.125 的回復: 字節(jié)=32 時間=37ms TTL=44

117.78.5.125 的 Ping 統(tǒng)計信息:
? ? 數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計時間(以毫秒為單位):
? ? 最短 = 37ms,最長 = 37ms,平均 = 37ms

C:UsersLenovo>

MQTT協(xié)議接入端口號有兩個,1883是非加密端口,8883是證書加密端口,單片機無法加載證書,所以使用1883端口合適。

3.3 創(chuàng)建產(chǎn)品

鏈接:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-dev/all-product?instanceId=03c5c68c-e588-458c-90c3-9e4c640be7af

(1)創(chuàng)建產(chǎn)品

(2)填寫產(chǎn)品信息

根據(jù)自己產(chǎn)品名字填寫,下面的設備類型選擇自定義類型。

(3)產(chǎn)品創(chuàng)建成功

創(chuàng)建完成之后點擊查看詳情。

(4)添加自定義模型

產(chǎn)品創(chuàng)建完成之后,點擊進入產(chǎn)品詳情頁面,翻到最下面可以看到模型定義。

模型簡單來說: 就是存放設備上傳到云平臺的數(shù)據(jù)。

你可以根據(jù)自己的產(chǎn)品進行創(chuàng)建。

比如:

鎖可以叫 ? ?LOCK? ? ? (整數(shù))
定位可以叫 ?GPS? ? ? ? ?(字符串)
報警可以叫 ?BEEP? ? ? ? ?(整數(shù))
其他的傳感器自己用單詞簡寫命名即可。 這就是你的單片機設備端上傳到服務器的數(shù)據(jù)名字。

先點擊自定義模型。

再創(chuàng)建一個服務ID。

接著點擊新增屬性。

3.4 添加設備

產(chǎn)品是屬于上層的抽象模型,接下來在產(chǎn)品模型下添加實際的設備。添加的設備最終需要與真實的設備關(guān)聯(lián)在一起,完成數(shù)據(jù)交互。

(1)注冊設備

(2)根據(jù)自己的設備填寫

(3)保存設備信息

創(chuàng)建完畢之后,點擊保存并關(guān)閉,得到創(chuàng)建的設備密匙信息。該信息在后續(xù)生成MQTT三元組的時候需要使用。

(4)設備創(chuàng)建完成

(5)設備詳情

3.5 MQTT協(xié)議主題訂閱與發(fā)布

(1)MQTT協(xié)議介紹

當前的設備是采用MQTT協(xié)議與華為云平臺進行通信。

MQTT是一個物聯(lián)網(wǎng)傳輸協(xié)議,它被設計用于輕量級的發(fā)布/訂閱式消息傳輸,旨在為低帶寬和不穩(wěn)定的網(wǎng)絡環(huán)境中的物聯(lián)網(wǎng)設備提供可靠的網(wǎng)絡服務。MQTT是專門針對物聯(lián)網(wǎng)開發(fā)的輕量級傳輸協(xié)議。MQTT協(xié)議針對低帶寬網(wǎng)絡,低計算能力的設備,做了特殊的優(yōu)化,使得其能適應各種物聯(lián)網(wǎng)應用場景。目前MQTT擁有各種平臺和設備上的客戶端,已經(jīng)形成了初步的生態(tài)系統(tǒng)。

MQTT是一種消息隊列協(xié)議,使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布,解除應用程序耦合,相對于其他協(xié)議,開發(fā)更簡單;MQTT協(xié)議是工作在TCP/IP協(xié)議上;由TCP/IP協(xié)議提供穩(wěn)定的網(wǎng)絡連接;所以,只要具備TCP協(xié)議棧的網(wǎng)絡設備都可以使用MQTT協(xié)議。 本次設備采用的ESP8266就具備TCP協(xié)議棧,能夠建立TCP連接,所以,配合STM32代碼里封裝的MQTT協(xié)議,就可以與華為云平臺完成通信。

華為云的MQTT協(xié)議接入幫助文檔在這里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

業(yè)務流程:

(2)華為云平臺MQTT協(xié)議使用限制

描述 限制
支持的MQTT協(xié)議版本 3.1.1
與標準MQTT協(xié)議的區(qū)別 支持Qos 0和Qos 1支持Topic自定義不支持QoS2不支持will、retain msg
MQTTS支持的安全等級 采用TCP通道基礎 + TLS協(xié)議(最高TLSv1.3版本)
單帳號每秒最大MQTT連接請求數(shù) 無限制
單個設備每分鐘支持的最大MQTT連接數(shù) 1
單個MQTT連接每秒的吞吐量,即帶寬,包含直連設備和網(wǎng)關(guān) 3KB/s
MQTT單個發(fā)布消息最大長度,超過此大小的發(fā)布請求將被直接拒絕 1MB
MQTT連接心跳時間建議值 心跳時間限定為30至1200秒,推薦設置為120秒
產(chǎn)品是否支持自定義Topic 支持
消息發(fā)布與訂閱 設備只能對自己的Topic進行消息發(fā)布與訂閱
每個訂閱請求的最大訂閱數(shù) 無限制

(3)主題訂閱格式

幫助文檔地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

對于設備而言,一般會訂閱平臺下發(fā)消息給設備 這個主題。

設備想接收平臺下發(fā)的消息,就需要訂閱平臺下發(fā)消息給設備 的主題,訂閱后,平臺下發(fā)消息給設備,設備就會收到消息。

如果設備想要知道平臺下發(fā)的消息,需要訂閱上面圖片里標注的主題。

以當前設備為例,最終訂閱主題的格式如下:
$oc/devices/{device_id}/sys/messages/down
? ??
最終的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down

(4)主題發(fā)布格式

對于設備來說,主題發(fā)布表示向云平臺上傳數(shù)據(jù),將最新的傳感器數(shù)據(jù),設備狀態(tài)上傳到云平臺。

這個操作稱為:屬性上報。

幫助文檔地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html

根據(jù)幫助文檔的介紹, 當前設備發(fā)布主題,上報屬性的格式總結(jié)如下:

發(fā)布的主題格式:
$oc/devices/{device_id}/sys/properties/report
?
最終的格式:
$oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report
發(fā)布主題時,需要上傳數(shù)據(jù),這個數(shù)據(jù)格式是JSON格式。

上傳的JSON數(shù)據(jù)格式如下:

{
??"services": [
? ? {
? ? ??"service_id": <填服務ID>,
? ? ??"properties": {
? ? ? ??"<填屬性名稱1>": <填屬性值>,
? ? ? ??"<填屬性名稱2>": <填屬性值>,
? ? ? ? ..........
? ? ? }
? ? }
? ]
}
根據(jù)JSON格式,一次可以上傳多個屬性字段。 這個JSON格式里的,服務ID,屬性字段名稱,屬性值類型,在前面創(chuàng)建產(chǎn)品的時候就已經(jīng)介紹了,不記得可以翻到前面去查看。

根據(jù)這個格式,組合一次上傳的屬性數(shù)據(jù):
{"services": [{"service_id":?"stm32","properties":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}

3.6 MQTT三元組

MQTT協(xié)議登錄需要填用戶ID,設備ID,設備密碼等信息,就像我們平時登錄QQ,微信一樣要輸入賬號密碼才能登錄。MQTT協(xié)議登錄的這3個參數(shù),一般稱為MQTT三元組。

接下來介紹,華為云平臺的MQTT三元組參數(shù)如何得到。

(1)MQTT服務器地址

要登錄MQTT服務器,首先記得先知道服務器的地址是多少,端口是多少。

幫助文檔地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home

MQTT協(xié)議的端口支持1883和8883,它們的區(qū)別是:8883 是加密端口更加安全。但是單片機上使用比較困難,所以當前的設備是采用1883端口進連接的。

根據(jù)上面的域名和端口號,得到下面的IP地址和端口號信息:?如果設備支持填寫域名可以直接填域名,不支持就直接填寫IP地址。 (IP地址就是域名解析得到的)

華為云的MQTT服務器地址:117.78.5.125
華為云的MQTT端口號:1883

如何得到IP地址?如何域名轉(zhuǎn)IP? 打開Windows的命令行輸入以下命令。

ping ?ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com

(2)生成MQTT三元組

華為云提供了一個在線工具,用來生成MQTT鑒權(quán)三元組: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

打開這個工具,填入設備的信息(也就是剛才創(chuàng)建完設備之后保存的信息),點擊生成,就可以得到MQTT的登錄信息了。

下面是打開的頁面:

填入設備的信息:?(上面兩行就是設備創(chuàng)建完成之后保存得到的)

直接得到三元組信息。

得到三元組之后,設備端通過MQTT協(xié)議登錄鑒權(quán)的時候,填入?yún)?shù)即可。

ClientId ?663cb18871d845632a0912e7_dev1_0_0_2024050911
Username ?663cb18871d845632a0912e7_dev1
Password ?71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237

3.7 模擬設備登錄測試

經(jīng)過上面的步驟介紹,已經(jīng)創(chuàng)建了產(chǎn)品,設備,數(shù)據(jù)模型,得到MQTT登錄信息。 接下來就用MQTT客戶端軟件模擬真實的設備來登錄平臺。測試與服務器通信是否正常。

MQTT軟件下載地址【免費】:?https://download.csdn.net/download/xiaolong1126626497/89928772

(1)填入登錄信息

打開MQTT客戶端軟件,對號填入相關(guān)信息(就是上面的文本介紹)。然后,點擊登錄,訂閱主題,發(fā)布主題。

(2)打開網(wǎng)頁查看

完成上面的操作之后,打開華為云網(wǎng)頁后臺,可以看到設備已經(jīng)在線了。

點擊詳情頁面,可以看到上傳的數(shù)據(jù):

到此,云平臺的部署已經(jīng)完成,設備已經(jīng)可以正常上傳數(shù)據(jù)了。

(3)MQTT登錄測試參數(shù)總結(jié)

MQTT服務器: ?117.78.5.125
MQTT端口號: ?183

//物聯(lián)網(wǎng)服務器的設備信息
#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":{"你的字段名字1":30,"你的字段名字2":10,"你的字段名字3":1,"你的字段名字4":0}}]}

3.8 創(chuàng)建IAM賬戶

創(chuàng)建一個IAM賬戶,因為接下來開發(fā)上位機,需要使用云平臺的API接口,這些接口都需要token進行鑒權(quán)。簡單來說,就是身份的認證。 調(diào)用接口獲取Token時,就需要填寫IAM賬號信息。所以,接下來演示一下過程。

地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users

**【1】獲取項目憑證 ** 點擊左上角用戶名,選擇下拉菜單里的我的憑證

項目憑證:

28add376c01e4a61ac8b621c714bf459

【2】創(chuàng)建IAM用戶

鼠標放在左上角頭像上,在下拉菜單里選擇統(tǒng)一身份認證

點擊左上角創(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

設備影子介紹:

設備影子是一個用于存儲和檢索設備當前狀態(tài)信息的JSON文檔。
每個設備有且只有一個設備影子,由設備ID唯一標識
設備影子僅保存最近一次設備的上報數(shù)據(jù)和預期數(shù)據(jù)
無論該設備是否在線,都可以通過該影子獲取和設置設備的屬性

簡單來說:設備影子就是保存,設備最新上傳的一次數(shù)據(jù)。

我們設計的軟件里,如果想要獲取設備的最新狀態(tài)信息,就采用設備影子接口。

如果對接口不熟悉,可以先進行在線調(diào)試:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow

在線調(diào)試接口,可以請求影子接口,了解請求,與返回的數(shù)據(jù)格式。

調(diào)試完成看右下角的響應體,就是返回的影子數(shù)據(jù)。

設備影子接口返回的數(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ù)的真實鏈接,接下來的代碼開發(fā)中,就采用Qt寫代碼訪問此鏈接,獲取影子數(shù)據(jù),完成上位機開發(fā)。

鏈接如下:

https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow

3.10 訪問接口的代碼實現(xiàn)

(1)配置 Qt 項目

在 Qt 項目的?.pro?文件中,加入對?libcurl?的支持:

QT += core
CONFIG += console
CONFIG -= app_bundle

INCLUDEPATH += /usr/include/curl ?# 根據(jù)你的系統(tǒng)設置 libcurl 的路徑
LIBS += -lcurl ?# 鏈接 libcurl 庫

SOURCES += main.cpp

(2)代碼實現(xiàn)

main.cpp?文件中實現(xiàn)代碼如下:

#include?<QCoreApplication>
#include?<curl/curl.h>
#include?<QDebug>
#include?<QString>
#include?<QByteArray>

// 回調(diào)函數(shù),處理libcurl下載數(shù)據(jù)
size_t?WriteCallback(void?*contents,?size_t?size,?size_t?nmemb,?void?*userp)?{
? ??size_t?totalSize = size * nmemb;
? ? QByteArray *response =?static_cast<QByteArray *>(userp);
? ? response->append(static_cast<char?*>(contents), totalSize);
? ??return?totalSize;
}

int?main(int?argc,?char?*argv[])?{
? ??QCoreApplication?a(argc, argv);

? ??// 初始化libcurl
? ? CURL *curl;
? ? CURLcode res;
? ? QByteArray responseData; ?// 用于存儲響應數(shù)據(jù)

? ??curl_global_init(CURL_GLOBAL_DEFAULT);
? ? curl =?curl_easy_init();
? ??if?(curl) {
? ? ? ??// 設置訪問URL
? ? ? ??const?QString url =?"https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow";

? ? ? ??// 設置HTTP請求頭
? ? ? ??struct?curl_slist?*headers =?NULL;
? ? ? ? headers =?curl_slist_append(headers,?"Authorization: Bearer <Your_Access_Token>");?// 這里需要替換為你的實際 token

? ? ? ??curl_easy_setopt(curl, CURLOPT_URL, url.toStdString().c_str());
? ? ? ??curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
? ? ? ??curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
? ? ? ??curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseData);

? ? ? ??// 發(fā)起GET請求
? ? ? ? res =?curl_easy_perform(curl);

? ? ? ??if?(res != CURLE_OK) {
? ? ? ? ? ??qDebug() <<?"Curl request failed:"?<<?curl_easy_strerror(res);
? ? ? ? }?else?{
? ? ? ? ? ??qDebug() <<?"Response data:"?<< responseData;
? ? ? ? }

? ? ? ??// 清理
? ? ? ??curl_easy_cleanup(curl);
? ? ? ??curl_slist_free_all(headers);
? ? }

? ??curl_global_cleanup();

? ??return?a.exec();
}

3.11 數(shù)據(jù)解析代碼

在 Qt 中使用 CJSON (一個用于解析 JSON 數(shù)據(jù)的輕量級 C 庫) 來解析返回的 JSON 數(shù)據(jù)。

(1)配置 Qt 項目

在 Qt 項目的?.pro?文件中,確保包括了 CJSON 的頭文件,并鏈接 CJSON 的源代碼。

QT += core
CONFIG += console
CONFIG -= app_bundle

SOURCES += main.cpp 
? ? ? ? ? ?cJSON.c ?# 將 cJSON.c 文件添加到你的項目中

INCLUDEPATH += path/to/cjson/ ?# 添加 CJSON 頭文件的路徑

LIBS += -lcurl ?# 鏈接 libcurl 庫

(2)解析 JSON 數(shù)據(jù)的完整代碼

在?main.cpp?中,以下代碼展示了如何解析你提供的 JSON 數(shù)據(jù)。

#include?<QCoreApplication>
#include?<curl/curl.h>
#include?<QDebug>
#include?<QString>
#include?<QByteArray>
#include?"cJSON.h"

// 回調(diào)函數(shù),處理libcurl下載數(shù)據(jù)
size_t?WriteCallback(void?*contents,?size_t?size,?size_t?nmemb,?void?*userp)?{
? ??size_t?totalSize = size * nmemb;
? ? QByteArray *response =?static_cast<QByteArray *>(userp);
? ? response->append(static_cast<char?*>(contents), totalSize);
? ??return?totalSize;
}

// 解析 JSON 數(shù)據(jù)
void?parseJson(const?QByteArray &data)?{
? ??// 將 QByteArray 轉(zhuǎn)換為 char*
? ??const?char* jsonData = data.constData();

? ??// 解析 JSON
? ? cJSON *root =?cJSON_Parse(jsonData);
? ??if?(root ==?NULL) {
? ? ? ??qDebug() <<?"Error parsing JSON.";
? ? ? ??return;
? ? }

? ??// 解析 "device_id"
? ? cJSON *deviceId =?cJSON_GetObjectItemCaseSensitive(root,?"device_id");
? ??if?(cJSON_IsString(deviceId) && (deviceId->valuestring !=?NULL)) {
? ? ? ??qDebug() <<?"Device ID:"?<< deviceId->valuestring;
? ? }

? ??// 解析 "shadow" 數(shù)組
? ? cJSON *shadow =?cJSON_GetObjectItemCaseSensitive(root,?"shadow");
? ??if?(cJSON_IsArray(shadow)) {
? ? ? ? cJSON *shadowItem =?NULL;
? ? ? ??cJSON_ArrayForEach(shadowItem, shadow) {
? ? ? ? ? ??// 解析每個 shadow 項目
? ? ? ? ? ? cJSON *serviceId =?cJSON_GetObjectItemCaseSensitive(shadowItem,?"service_id");
? ? ? ? ? ??if?(cJSON_IsString(serviceId) && (serviceId->valuestring !=?NULL)) {
? ? ? ? ? ? ? ??qDebug() <<?"Service ID:"?<< serviceId->valuestring;
? ? ? ? ? ? }

? ? ? ? ? ??// 解析 "reported" 對象
? ? ? ? ? ? cJSON *reported =?cJSON_GetObjectItemCaseSensitive(shadowItem,?"reported");
? ? ? ? ? ??if?(cJSON_IsObject(reported)) {
? ? ? ? ? ? ? ??// 解析 "properties" 對象
? ? ? ? ? ? ? ? cJSON *properties =?cJSON_GetObjectItemCaseSensitive(reported,?"properties");
? ? ? ? ? ? ? ??if?(cJSON_IsObject(properties)) {
? ? ? ? ? ? ? ? ? ? cJSON *data1 =?cJSON_GetObjectItemCaseSensitive(properties,?"data1");
? ? ? ? ? ? ? ? ? ??if?(cJSON_IsNumber(data1)) {
? ? ? ? ? ? ? ? ? ? ? ??qDebug() <<?"data1:"?<< data1->valueint;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? cJSON *data2 =?cJSON_GetObjectItemCaseSensitive(properties,?"data2");
? ? ? ? ? ? ? ? ? ??if?(cJSON_IsNumber(data2)) {
? ? ? ? ? ? ? ? ? ? ? ??qDebug() <<?"data2:"?<< data2->valueint;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? cJSON *data3 =?cJSON_GetObjectItemCaseSensitive(properties,?"data3");
? ? ? ? ? ? ? ? ? ??if?(cJSON_IsNumber(data3)) {
? ? ? ? ? ? ? ? ? ? ? ??qDebug() <<?"data3:"?<< data3->valueint;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? ? ? cJSON *data4 =?cJSON_GetObjectItemCaseSensitive(properties,?"data4");
? ? ? ? ? ? ? ? ? ??if?(cJSON_IsNumber(data4)) {
? ? ? ? ? ? ? ? ? ? ? ??qDebug() <<?"data4:"?<< data4->valueint;
? ? ? ? ? ? ? ? ? ? }
? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? ??// 解析 "event_time"
? ? ? ? ? ? ? ? cJSON *eventTime =?cJSON_GetObjectItemCaseSensitive(reported,?"event_time");
? ? ? ? ? ? ? ??if?(cJSON_IsString(eventTime) && (eventTime->valuestring !=?NULL)) {
? ? ? ? ? ? ? ? ? ??qDebug() <<?"Event Time:"?<< eventTime->valuestring;
? ? ? ? ? ? ? ? }
? ? ? ? ? ? }

? ? ? ? ? ??// 解析 version
? ? ? ? ? ? cJSON *version =?cJSON_GetObjectItemCaseSensitive(shadowItem,?"version");
? ? ? ? ? ??if?(cJSON_IsNumber(version)) {
? ? ? ? ? ? ? ??qDebug() <<?"Version:"?<< version->valueint;
? ? ? ? ? ? }
? ? ? ? }
? ? }

? ??// 釋放 JSON 對象
? ??cJSON_Delete(root);
}

int?main(int?argc,?char?*argv[])?{
? ??QCoreApplication?a(argc, argv);

? ??// 模擬獲取到的 JSON 數(shù)據(jù)
? ? QByteArray jsonData =?R"(
? ? {
? ? ? ? "device_id": "663cb18871d845632a0912e7_dev1",
? ? ? ? "shadow": [
? ? ? ? ? ? {
? ? ? ? ? ? ? ? "service_id": "stm32",
? ? ? ? ? ? ? ? "desired": {
? ? ? ? ? ? ? ? ? ? "properties": null,
? ? ? ? ? ? ? ? ? ? "event_time": null
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? "reported": {
? ? ? ? ? ? ? ? ? ? "properties": {
? ? ? ? ? ? ? ? ? ? ? ? "data1": 18,
? ? ? ? ? ? ? ? ? ? ? ? "data2": 90,
? ? ? ? ? ? ? ? ? ? ? ? "data3": 38,
? ? ? ? ? ? ? ? ? ? ? ? "data4": 70
? ? ? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? ? ? "event_time": "20240509T113448Z"
? ? ? ? ? ? ? ? },
? ? ? ? ? ? ? ? "version": 3
? ? ? ? ? ? }
? ? ? ? ]
? ? })";

? ??// 調(diào)用解析函數(shù)
? ??parseJson(jsonData);

? ??return?a.exec();
}

四、STM32設備端代碼設計

以下是該項目的?main.c?完整代碼以及整體代碼的設計思路。涵蓋了4G通信、短信報警、GPS定位、蜂鳴器報警、姿態(tài)檢測、OLED顯示等功能。

4.1 整體代碼設計思路

系統(tǒng)的主控芯片為 STM32F103RCT6,采用寄存器方式進行編程。整體設計分為以下幾個模塊,代碼通過主函數(shù)進行初始化和任務調(diào)度:

    1. 1.

系統(tǒng)初始化階段

      • ? 時鐘系統(tǒng)初始化(使用 HSE)? 串口初始化(用于與 Air724UG 4G 模塊、GPS 模塊通信)? OLED 顯示初始化? 加速度傳感器 ADXL345 初始化(通過 I2C)? 蜂鳴器 GPIO 初始化? 相關(guān)中斷使能(如串口接收中斷)

2.?主循環(huán)任務調(diào)度階段

      • ? 循環(huán)讀取 ADXL345 判斷是否發(fā)生車輛移動? 如果發(fā)生移動,觸發(fā)本地蜂鳴器報警,并調(diào)用4G模塊發(fā)送短信? 獲取 GPS 位置信息并通過 MQTT 上傳至云平臺? 實時更新鎖狀態(tài)和GPS信息到 OLED 屏幕? 接收上位機或APP發(fā)來的遠程開鎖/關(guān)鎖指令并控制鎖狀態(tài)

3.?中斷服務程序

    • ? 串口接收中斷,處理4G模塊和GPS模塊返回的數(shù)據(jù)? 定時器或輪詢機制定時上傳狀態(tài)信息至云端

4.2 main.c 完整示例代碼

#include?"stm32f10x.h"
#include?"oled.h"
#include?"usart.h"
#include?"adxl345.h"
#include?"gps.h"
#include?"delay.h"
#include?"buzzer.h"
#include?"mqtt.h"
#include?"lock.h"
#include?"string.h"

// 全局狀態(tài)變量
uint8_t?bike_locked =?1;
uint8_t?movement_detected =?0;
char?gps_data[100];
char?lock_status[10];

// 主函數(shù)
int?main(void)
{
? ??// 基礎外設初始化
? ? SystemInit();
? ? delay_init();
? ? USART1_Init(9600); ??// 用于GPS
? ? USART2_Init(115200);?// 用于Air724UG模塊
? ? OLED_Init();
? ? ADXL345_Init();
? ? BUZZER_Init();
? ? LOCK_Init();

? ? OLED_ShowString(0,?0,?"Smart Bike Lock");
? ? delay_ms(1000);
? ? OLED_Clear();

? ??// MQTT初始化
? ? MQTT_Init();

? ??while?(1)
? ? {
? ? ? ??// 姿態(tài)檢測模塊讀取
? ? ? ??if?(ADXL345_DetectMovement())
? ? ? ? {
? ? ? ? ? ? movement_detected =?1;
? ? ? ? }

? ? ? ??// 如果處于鎖車狀態(tài)并且檢測到移動
? ? ? ??if?(bike_locked && movement_detected)
? ? ? ? {
? ? ? ? ? ? BUZZER_On();
? ? ? ? ? ? OLED_ShowString(0,?0,?"ALARM: Movement!");
? ? ? ? ? ? Send_SMS("警告:單車被非法移動!");
? ? ? ? ? ? MQTT_Publish_Alert("bike/move",?"Bike Moved!");
? ? ? ? ? ? movement_detected =?0;
? ? ? ? ? ? delay_ms(5000);
? ? ? ? ? ? BUZZER_Off();
? ? ? ? ? ? OLED_Clear();
? ? ? ? }

? ? ? ??// 獲取GPS信息并上傳
? ? ? ? GPS_GetLocation(gps_data);
? ? ? ? MQTT_Publish("bike/gps", gps_data);
? ? ? ? OLED_ShowString(0,?2,?"GPS:");
? ? ? ? OLED_ShowString(0,?3, gps_data);

? ? ? ??// 更新鎖狀態(tài)顯示
? ? ? ??strcpy(lock_status, bike_locked ??"Locked"?:?"Unlocked");
? ? ? ? OLED_ShowString(0,?5,?"Lock:");
? ? ? ? OLED_ShowString(36,?5, lock_status);
? ? ? ? MQTT_Publish("bike/status", lock_status);

? ? ? ??// 處理遠程開鎖指令(模擬)
? ? ? ??if?(MQTT_Received_Unlock())
? ? ? ? {
? ? ? ? ? ? bike_locked =?0;
? ? ? ? ? ? LOCK_Unlock();
? ? ? ? ? ? OLED_ShowString(0,?6,?"Unlock by remote");
? ? ? ? }

? ? ? ??// 處理遠程關(guān)鎖指令
? ? ? ??if?(MQTT_Received_Lock())
? ? ? ? {
? ? ? ? ? ? bike_locked =?1;
? ? ? ? ? ? LOCK_Lock();
? ? ? ? ? ? OLED_ShowString(0,?6,?"Lock by remote");
? ? ? ? }
? ? }
}

說明

    • ?

USART1

    • :用于與GPS模塊通信?

USART2

    • :用于與Air724UG模塊通信(發(fā)送MQTT/短信)?

ADXL345_DetectMovement()

    • :檢測車輛是否移動(閾值判斷)?

Send_SMS()

    • :通過AT指令調(diào)用Air724UG發(fā)送短信?

MQTT_Publish()

    • :上傳數(shù)據(jù)到華為云?

MQTT_Received_Unlock()

    • ?/

Lock()

    • :接收遠程指令?

OLED_ShowString()

    • :顯示實時信息?

LOCK_Unlock()

    • ?/

LOCK_Lock()

4.3 ADXL345模塊

ADXL345.h

#ifndef?__ADXL345_H
#define?__ADXL345_H

#include?"stm32f10x.h"

// I2C引腳定義(使用軟件模擬)
#define?ADXL_SCL_GPIO ? ?GPIOB
#define?ADXL_SCL_PIN ? ? GPIO_Pin_6
#define?ADXL_SDA_GPIO ? ?GPIOB
#define?ADXL_SDA_PIN ? ? GPIO_Pin_7

// 宏函數(shù)控制SCL/SDA
#define?ADXL_SCL_HIGH() ?GPIO_SetBits(ADXL_SCL_GPIO, ADXL_SCL_PIN)
#define?ADXL_SCL_LOW() ? GPIO_ResetBits(ADXL_SCL_GPIO, ADXL_SCL_PIN)
#define?ADXL_SDA_HIGH() ?GPIO_SetBits(ADXL_SDA_GPIO, ADXL_SDA_PIN)
#define?ADXL_SDA_LOW() ? GPIO_ResetBits(ADXL_SDA_GPIO, ADXL_SDA_PIN)
#define?ADXL_SDA_READ() ?GPIO_ReadInputDataBit(ADXL_SDA_GPIO, ADXL_SDA_PIN)

void?ADXL345_Init(void);
uint8_t?ADXL345_Read_Byte(uint8_t?reg);
void?ADXL345_Write_Byte(uint8_t?reg,?uint8_t?data);
void?ADXL345_ReadXYZ(int16_t?*x,?int16_t?*y,?int16_t?*z);
uint8_t?ADXL345_DetectMovement(void);

#endif

ADXL345.c

#include?"ADXL345.h"
#include?"delay.h"

#define?ADXL345_ADDRESS ?0xA6 ?// 7位地址為0x53,左移1位即為0xA6

// 模擬I2C初始化
static?void?I2C_GPIO_Init(void)
{
? ? RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
? ? GPIO_InitTypeDef GPIO_InitStructure;
? ? GPIO_InitStructure.GPIO_Pin = ADXL_SCL_PIN | ADXL_SDA_PIN;
? ? GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
? ? GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
? ? GPIO_Init(ADXL_SCL_GPIO, &GPIO_InitStructure);
? ? ADXL_SCL_HIGH();
? ? ADXL_SDA_HIGH();
}

static?void?I2C_Start(void)
{
? ? ADXL_SDA_HIGH();
? ? ADXL_SCL_HIGH();
? ? delay_us(5);
? ? ADXL_SDA_LOW();
? ? delay_us(5);
? ? ADXL_SCL_LOW();
}

static?void?I2C_Stop(void)
{
? ? ADXL_SDA_LOW();
? ? ADXL_SCL_HIGH();
? ? delay_us(5);
? ? ADXL_SDA_HIGH();
? ? delay_us(5);
}

static?void?I2C_SendAck(uint8_t?ack)
{
? ??if?(ack)
? ? ? ? ADXL_SDA_LOW();
? ??else
? ? ? ? ADXL_SDA_HIGH();
? ? ADXL_SCL_HIGH();
? ? delay_us(5);
? ? ADXL_SCL_LOW();
? ? delay_us(5);
}

static?uint8_t?I2C_WaitAck(void)
{
? ??uint8_t?ack;
? ? ADXL_SDA_HIGH();
? ? ADXL_SCL_HIGH();
? ? delay_us(5);
? ? ack = ADXL_SDA_READ();
? ? ADXL_SCL_LOW();
? ??return?ack;
}

static?void?I2C_WriteByte(uint8_t?byte)
{
? ??for?(int?i =?0; i <?8; i++)
? ? {
? ? ? ??if?(byte &?0x80)
? ? ? ? ? ? ADXL_SDA_HIGH();
? ? ? ??else
? ? ? ? ? ? ADXL_SDA_LOW();
? ? ? ? byte <<=?1;
? ? ? ? ADXL_SCL_HIGH();
? ? ? ? delay_us(5);
? ? ? ? ADXL_SCL_LOW();
? ? ? ? delay_us(5);
? ? }
}

static?uint8_t?I2C_ReadByte(uint8_t?ack)
{
? ??uint8_t?byte =?0;
? ? ADXL_SDA_HIGH();
? ??for?(int?i =?0; i <?8; i++)
? ? {
? ? ? ? ADXL_SCL_HIGH();
? ? ? ? delay_us(5);
? ? ? ? byte <<=?1;
? ? ? ??if?(ADXL_SDA_READ())
? ? ? ? ? ? byte |=?0x01;
? ? ? ? ADXL_SCL_LOW();
? ? ? ? delay_us(5);
? ? }
? ? I2C_SendAck(ack);
? ??return?byte;
}

void?ADXL345_Write_Byte(uint8_t?reg,?uint8_t?data)
{
? ? I2C_Start();
? ? I2C_WriteByte(ADXL345_ADDRESS);
? ? I2C_WaitAck();
? ? I2C_WriteByte(reg);
? ? I2C_WaitAck();
? ? I2C_WriteByte(data);
? ? I2C_WaitAck();
? ? I2C_Stop();
}

uint8_t?ADXL345_Read_Byte(uint8_t?reg)
{
? ??uint8_t?value;
? ? I2C_Start();
? ? I2C_WriteByte(ADXL345_ADDRESS);
? ? I2C_WaitAck();
? ? I2C_WriteByte(reg);
? ? I2C_WaitAck();
? ? I2C_Start();
? ? I2C_WriteByte(ADXL345_ADDRESS |?0x01);
? ? I2C_WaitAck();
? ? value = I2C_ReadByte(0);
? ? I2C_Stop();
? ??return?value;
}

void?ADXL345_ReadXYZ(int16_t?*x,?int16_t?*y,?int16_t?*z)
{
? ??uint8_t?x0 = ADXL345_Read_Byte(0x32);
? ??uint8_t?x1 = ADXL345_Read_Byte(0x33);
? ??uint8_t?y0 = ADXL345_Read_Byte(0x34);
? ??uint8_t?y1 = ADXL345_Read_Byte(0x35);
? ??uint8_t?z0 = ADXL345_Read_Byte(0x36);
? ??uint8_t?z1 = ADXL345_Read_Byte(0x37);

? ? *x = ((int16_t)(x1 <<?8) | x0);
? ? *y = ((int16_t)(y1 <<?8) | y0);
? ? *z = ((int16_t)(z1 <<?8) | z0);
}

void?ADXL345_Init(void)
{
? ? I2C_GPIO_Init();
? ? ADXL345_Write_Byte(0x2D,?0x08);?// POWER_CTL - 測量模式
? ? ADXL345_Write_Byte(0x31,?0x0B);?// 數(shù)據(jù)格式 - 全分辨率 ±16g
? ? ADXL345_Write_Byte(0x2C,?0x0A);?// BW_RATE - 100Hz
}

// 檢測是否發(fā)生移動(簡單閾值判斷)
uint8_t?ADXL345_DetectMovement(void)
{
? ??int16_t?x, y, z;
? ? ADXL345_ReadXYZ(&x, &y, &z);
? ??if?(x >?200?|| x <?-200?|| y >?200?|| y <?-200?|| z >?200?|| z <?-200)
? ? ? ??return?1;
? ??return?0;
}

五、上位機開發(fā)

為了方便查看設備上傳的數(shù)據(jù),接下來利用Qt開發(fā)一款Android手機APP 和 Windows上位機。

使用華為云平臺提供的API接口獲取設備上傳的數(shù)據(jù),進行可視化顯示,以及遠程控制設備。

5.1 Qt開發(fā)環(huán)境安裝

可以在網(wǎng)盤里找到安裝包下載:?https://ccnr8sukk85n.feishu.cn/wiki/QjY8weDYHibqRYkFP2qcA9aGnvb?from=from_copylink

打開下載鏈接后選擇下面的版本進行下載:

軟件安裝時斷網(wǎng)安裝,否則會提示輸入賬戶。

安裝的時候,第一個復選框里的編譯器可以全選,直接點擊下一步繼續(xù)安裝。

選擇編譯器: (一定要看清楚了)

前面2講解了需要用的API接口,接下來就使用Qt設計上位機,設計界面,完成整體上位機的邏輯設計。

【1】新建工程

【2】設置項目的名稱。

【3】選擇編譯系統(tǒng)

【4】選擇默認繼承的類

【5】選擇編譯器

【6】點擊完成

【7】工程創(chuàng)建完成

5.3 切換編譯器

在左下角是可以切換編譯器的。 可以選擇用什么樣的編譯器編譯程序。

目前新建工程的時候選擇了2種編譯器。 一種是mingw32這個編譯Windows下運行的程序。 一種是Android編譯器,可以生成Android手機APP。

不過要注意:Android的編譯器需要配置一些環(huán)境才可以正常使用,這個大家可以看下面的教程配置一下就行了。

Android環(huán)境搭建的博客鏈接:?https://blog.csdn.net/xiaolong1126626497/article/details/117254453

windows的編譯器就沒有這么麻煩,安裝好Qt就可以編譯使用。

下面我這里就選擇的?mingw32這個編譯器,編譯Windows下運行的程序。

5.4 編譯測試功能

創(chuàng)建完畢之后,編譯測試一下功能是否OK。

點擊左下角的綠色三角形按鈕。

正常運行就可以看到彈出一個白色的框框。這就表示工程環(huán)境沒有問題了。 接下來就可以放心的設計界面了。

5.5 設計UI界面與工程配置

【1】打開UI文件

打開默認的界面如下:

【2】開始設計界面

根據(jù)自己需求設計界面。

5.5 編譯Windows上位機

點擊軟件左下角的綠色三角形按鈕進行編譯運行。

5.6 配置Android環(huán)境

如果想編譯Android手機APP,必須要先自己配置好自己的Android環(huán)境。(搭建環(huán)境的過程可以自行百度搜索學習)

然后才可以進行下面的步驟。

【1】選擇Android編譯器

選擇編譯器。

切換編譯器。

【2】創(chuàng)建Android配置文件

創(chuàng)建完成。

【3】配置Android圖標與名稱

【3】編譯Android上位機

Qt本身是跨平臺的,直接選擇Android的編譯器,就可以將程序編譯到Android平臺。

然后點擊構(gòu)建。

成功之后,在目錄下可以看到生成的apk文件,也就是Android手機的安裝包,電腦端使用QQ發(fā)送給手機QQ,手機登錄QQ接收,就能直接安裝。

生成的apk的目錄在哪里呢? 編譯完成之后,在控制臺會輸出APK文件的路徑。

知道目錄在哪里之后,在Windows的文件資源管理器里,找到路徑,具體看下圖,找到生成的apk文件。

? -- File: D:/QtProject/build-265_AgritechIoTManager-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk

六、總結(jié)

本項目基于STM32F103RCT6單片機設計了一套功能完整、運行穩(wěn)定的智能防盜單車鎖系統(tǒng),融合了物聯(lián)網(wǎng)通信技術(shù)、傳感檢測技術(shù)與移動端控制手段,實現(xiàn)了本地與遠程相結(jié)合的智能防護與管理。系統(tǒng)通過多模塊協(xié)作,能夠有效對單車的使用狀態(tài)進行監(jiān)控,對非法移動行為做出及時報警,并通過短信與APP進行多端同步提醒,大幅提升單車的安全保障能力。

項目充分考慮了單車運行環(huán)境的特殊性,在硬件設計上選擇了低功耗、高集成度的器件,采用鋰電池供電并預留太陽能擴展接口,增強了系統(tǒng)的戶外適應能力與續(xù)航性能。通信方面,選用Air724UG 4G模塊確保了在無WiFi環(huán)境下依然能夠穩(wěn)定聯(lián)網(wǎng),并借助華為云物聯(lián)網(wǎng)平臺實現(xiàn)數(shù)據(jù)的實時上傳與遠程管理,體現(xiàn)出云端協(xié)同與邊緣智能的結(jié)合。

在軟件設計方面,采用了嵌入式寄存器級編程實現(xiàn)了主控芯片的高效控制,同時借助QT5平臺開發(fā)了跨平臺的APP和上位機軟件,提升了用戶交互體驗。系統(tǒng)整體架構(gòu)清晰、功能完整、可擴展性強,為后續(xù)功能升級與規(guī)?;瘧锰峁┝肆己没A。

綜上所述,本系統(tǒng)不僅具有較高的實用價值和技術(shù)含量,同時也展現(xiàn)了物聯(lián)網(wǎng)在智能交通工具防護中的廣闊應用前景,具備良好的推廣與開發(fā)潛力。

相關(guān)推薦