一、項(xiàng)目介紹
智能門禁系統(tǒng)是一種應(yīng)用物聯(lián)網(wǎng)技術(shù)的智能化安防系統(tǒng),提供安全高效的門禁管理和遠(yuǎn)程監(jiān)控功能。傳統(tǒng)的門禁系統(tǒng)通常使用磁卡、密碼或鑰匙等方式進(jìn)行開鎖,但存在易丟失、易復(fù)制、操作繁瑣等問題。為了解決這些問題,并提高門禁安全性和便捷性,這里介紹了一款基于STM32F103和華為云IOT的智能門禁系統(tǒng)的設(shè)計(jì)方案。
系統(tǒng)的核心控制器采用了STM32F103單片機(jī),具有豐富的外設(shè)接口和強(qiáng)大的處理能力,能夠?qū)崿F(xiàn)對(duì)門禁設(shè)備的精確控制和數(shù)據(jù)處理。為了提供多種開鎖方式,選擇了RFID-RC522讀寫模塊和4x4電容矩陣鍵盤作為輸入設(shè)備,用戶可以通過刷卡或輸入密碼來開啟門禁。采用了28BYJ-48步進(jìn)電機(jī)作為門鎖控制裝置,能夠?qū)崿F(xiàn)對(duì)門鎖的精確控制。
為了方便用戶與門禁系統(tǒng)進(jìn)行交互,使用了SPI接口的0.96寸OLED顯示屏和蜂鳴器,可以顯示門鎖狀態(tài)信息和人機(jī)交互提示音。此外,為了實(shí)現(xiàn)遠(yuǎn)程控制和消息推送功能,選擇了ESP8266 WiFi模塊連接華為云物聯(lián)網(wǎng)平臺(tái),用戶可以通過手機(jī)APP實(shí)現(xiàn)遠(yuǎn)程開鎖,并且可以隨時(shí)監(jiān)控門鎖狀態(tài)。當(dāng)門鎖打開或關(guān)閉成功時(shí),手機(jī)APP會(huì)收到通知提醒,以增加用戶的使用安全性和便捷性。
通過將STM32F103和華為云IOT相結(jié)合,可以實(shí)現(xiàn)智能門禁系統(tǒng)在數(shù)據(jù)傳輸、遠(yuǎn)程控制和消息推送等方面的高效、穩(wěn)定和安全性能。該系統(tǒng)不僅提供了多種開鎖方式和人機(jī)交互功能,還具備遠(yuǎn)程監(jiān)控和消息提醒的智能化特點(diǎn),適用于住宅小區(qū)、學(xué)校、企事業(yè)單位等場(chǎng)所的門禁管理需求。
二、硬件選型
在智能門禁系統(tǒng)的硬件選型中,選擇了以下模塊:
【1】主控制器:STM32F103單片機(jī)。它是一款高性能、低功耗的ARM Cortex-M3內(nèi)核微控制器,具有豐富的外設(shè)接口和強(qiáng)大的計(jì)算和控制能力,非常適合用于門禁系統(tǒng)的控制和數(shù)據(jù)處理。
【2】RFID讀寫模塊:RFID-RC522。這個(gè)模塊基于13.56MHz的射頻識(shí)別技術(shù),可以實(shí)現(xiàn)對(duì)RFID卡片的讀寫操作,通過刷卡方式進(jìn)行門禁的開啟和關(guān)閉。
【3】門鎖控制:28BYJ-48步進(jìn)電機(jī)。該步進(jìn)電機(jī)結(jié)構(gòu)簡(jiǎn)單、體積小巧,能夠?qū)崿F(xiàn)對(duì)門鎖的準(zhǔn)確控制,提供開啟和關(guān)閉門鎖的功能。
【4】密碼輸入設(shè)備:4x4電容矩陣鍵盤。這種鍵盤采用電容觸摸技術(shù),具有防水、靈敏度高的特點(diǎn),用戶可以通過輸入密碼來開啟門禁。
【5】顯示屏:SPI接口的0.96寸OLED顯示屏。該顯示屏具有高亮度、高對(duì)比度和低功耗的特點(diǎn),可以顯示門鎖狀態(tài)信息和人機(jī)交互提示。
【6】網(wǎng)絡(luò)連接模塊:ESP8266-WIFI。這個(gè)模塊支持WiFi通信標(biāo)準(zhǔn),能夠?qū)崿F(xiàn)與華為云物聯(lián)網(wǎng)平臺(tái)的連接,實(shí)現(xiàn)遠(yuǎn)程控制和消息推送功能。
【7】門狀態(tài)檢測(cè):紅外磁感應(yīng)模塊。通過紅外磁感應(yīng)技術(shù),可以檢測(cè)門是否打開或關(guān)閉,提供準(zhǔn)確的門狀態(tài)信息。
選擇的這些硬件可以滿足智能門禁系統(tǒng)的各項(xiàng)功能需求。主控制器STM32F103為整個(gè)系統(tǒng)提供了穩(wěn)定可靠的控制和處理能力,RFID讀寫模塊和密碼鍵盤提供了多種開鎖方式,步進(jìn)電機(jī)實(shí)現(xiàn)了精確的門鎖控制,顯示屏和蜂鳴器提供了人機(jī)交互功能,ESP8266-WIFI模塊連接華為云實(shí)現(xiàn)了遠(yuǎn)程控制和消息推送,紅外磁感應(yīng)模塊檢測(cè)門狀態(tài),使得整個(gè)智能門禁系統(tǒng)更加智能、安全和便捷。
三、系統(tǒng)設(shè)計(jì)思路
智能門禁系統(tǒng)的設(shè)計(jì)思路:
【1】硬件連接與集成:各個(gè)硬件組件(如主控制器、RFID讀寫模塊、步進(jìn)電機(jī)等)需要進(jìn)行正確的連接和接口配置。通過連接線將各個(gè)硬件模塊與主控制器相連,并設(shè)置正確的引腳連接和寄存器配置,以確保它們能夠正常工作并實(shí)現(xiàn)相應(yīng)的功能。
【2】數(shù)據(jù)采集與處理:系統(tǒng)通過RFID讀寫模塊讀取用戶刷卡信息或通過電容矩陣鍵盤獲取用戶輸入的密碼信息。主控制器接收到這些數(shù)據(jù)后,進(jìn)行相應(yīng)的數(shù)據(jù)處理,例如驗(yàn)證刷卡信息或密碼是否正確。如果驗(yàn)證通過,則進(jìn)行下一步的門禁控制流程。
【3】門鎖控制與狀態(tài)檢測(cè):主控制器通過控制步進(jìn)電機(jī)來實(shí)現(xiàn)門鎖的精確控制。當(dāng)用戶驗(yàn)證成功后,主控制器發(fā)送指令給步進(jìn)電機(jī),使其旋轉(zhuǎn)相應(yīng)的步數(shù),從而打開或關(guān)閉門鎖。同時(shí),主控制器還使用紅外磁感應(yīng)模塊來檢測(cè)門的狀態(tài),以確保門鎖的準(zhǔn)確控制。
【4】用戶界面與人機(jī)交互:系統(tǒng)配備了0.96寸OLED顯示屏和蜂鳴器,通過顯示屏可以向用戶展示門鎖的狀態(tài)信息和相關(guān)提示,如開鎖成功、密碼錯(cuò)誤等。蜂鳴器則可以發(fā)出不同的提示音,提供與用戶的交互反饋。
【5】遠(yuǎn)程控制與消息推送:通過ESP8266-WIFI模塊與華為云物聯(lián)網(wǎng)平臺(tái)連接,使得用戶可以通過手機(jī)APP進(jìn)行遠(yuǎn)程開鎖操作。用戶在手機(jī)APP上輸入開鎖指令后,APP會(huì)將指令發(fā)送到華為云平臺(tái),再由云平臺(tái)將指令傳輸給物聯(lián)網(wǎng)設(shè)備(智能門禁系統(tǒng))。主控制器接收到開鎖指令后,執(zhí)行相應(yīng)的控制動(dòng)作,并將結(jié)果通過云平臺(tái)發(fā)送回手機(jī)APP,實(shí)現(xiàn)遠(yuǎn)程控制和消息推送功能。
整個(gè)系統(tǒng)的設(shè)計(jì)思路是將各個(gè)硬件組件協(xié)調(diào)配合,通過主控制器進(jìn)行數(shù)據(jù)處理和門鎖控制,并提供人機(jī)交互界面和遠(yuǎn)程控制功能,以實(shí)現(xiàn)智能門禁系統(tǒng)的安全、高效和便捷的門禁管理和遠(yuǎn)程監(jiān)控。
四、華為云物聯(lián)網(wǎng)平臺(tái)部署
華為云官網(wǎng): https://www.huaweicloud.com/
打開官網(wǎng),搜索物聯(lián)網(wǎng),就能快速找到 設(shè)備接入IoTDA
。
4.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ù)場(chǎng)景。
4.2 開通物聯(lián)網(wǎng)服務(wù)
地址: https://www.huaweicloud.com/product/iothub.html
點(diǎn)擊總覽
,查看接入信息。 我們當(dāng)前設(shè)備準(zhǔn)備采用MQTT協(xié)議接入華為云平臺(tái),這里可以看到MQTT協(xié)議的地址和端口號(hào)等信息。
總結(jié):
端口號(hào): MQTT (1883)| MQTTS (8883)
接入地址: a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
根據(jù)域名地址得到IP地址信息:
Microsoft Windows [版本 10.0.19045.2965]
(c) Microsoft Corporation。保留所有權(quán)利。
C:Users11266>ping a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com
正在 Ping a161a58a78.iot-mqtts.cn-north-4.myhuaweicloud.com [121.36.42.100] 具有 32 字節(jié)的數(shù)據(jù):
來自 121.36.42.100 的回復(fù): 字節(jié)=32 時(shí)間=38ms TTL=94
來自 121.36.42.100 的回復(fù): 字節(jié)=32 時(shí)間=37ms TTL=94
來自 121.36.42.100 的回復(fù): 字節(jié)=32 時(shí)間=38ms TTL=94
來自 121.36.42.100 的回復(fù): 字節(jié)=32 時(shí)間=36ms TTL=94
121.36.42.100 的 Ping 統(tǒng)計(jì)信息:
數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
最短 = 36ms,最長(zhǎng) = 38ms,平均 = 37ms
C:Users11266>
MQTT協(xié)議接入端口號(hào)有兩個(gè),1883是非加密端口,8883是證書加密端口,單片機(jī)無法加載證書,所以使用1883端口比較合適。 接下來的ESP8266就采用1883端口連接華為云物聯(lián)網(wǎng)平臺(tái)。
4.3 創(chuàng)建產(chǎn)品
(1)創(chuàng)建產(chǎn)品
點(diǎn)擊產(chǎn)品頁(yè),再點(diǎn)擊左上角創(chuàng)建產(chǎn)品。
(2)填寫產(chǎn)品信息
根據(jù)自己產(chǎn)品名字填寫。
(3)產(chǎn)品創(chuàng)建成功
(4)添加自定義模型
產(chǎn)品創(chuàng)建完成之后,點(diǎn)擊進(jìn)入產(chǎn)品詳情頁(yè)面,翻到最下面可以看到模型定義。
這個(gè)模型就是定義自己設(shè)備接下來需要向服務(wù)器上傳那些數(shù)據(jù)類型。根據(jù)自己的數(shù)據(jù)類型進(jìn)行編寫。
先點(diǎn)擊自定義模型。
再創(chuàng)建一個(gè)服務(wù)ID。
接著點(diǎn)擊新增屬性。
4.4 添加設(shè)備
產(chǎn)品是屬于上層的抽象模型,接下來在產(chǎn)品模型下添加實(shí)際的設(shè)備。添加的設(shè)備最終需要與真實(shí)的設(shè)備關(guān)聯(lián)在一起,完成數(shù)據(jù)交互。
(1)注冊(cè)設(shè)備
(2)根據(jù)自己的設(shè)備填寫
(3)保存設(shè)備信息
創(chuàng)建完畢之后,點(diǎn)擊保存并關(guān)閉,得到創(chuàng)建的設(shè)備密匙信息。該信息在后續(xù)生成MQTT三元組的時(shí)候需要使用。
(4)設(shè)備創(chuàng)建完成
可以點(diǎn)擊設(shè)備進(jìn)入到設(shè)備詳情頁(yè)面。
4.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是專門針對(duì)物聯(lián)網(wǎng)開發(fā)的輕量級(jí)傳輸協(xié)議。MQTT協(xié)議針對(duì)低帶寬網(wǎng)絡(luò),低計(jì)算能力的設(shè)備,做了特殊的優(yōu)化,使得其能適應(yīng)各種物聯(lián)網(wǎng)應(yīng)用場(chǎng)景。目前MQTT擁有各種平臺(tái)和設(shè)備上的客戶端,已經(jīng)形成了初步的生態(tài)系統(tǒng)。
MQTT是一種消息隊(duì)列協(xié)議,使用發(fā)布/訂閱消息模式,提供一對(duì)多的消息發(fā)布,解除應(yīng)用程序耦合,相對(duì)于其他協(xié)議,開發(fā)更簡(jiǎn)單;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連接請(qǐng)求數(shù) | 無限制 |
單個(gè)設(shè)備每分鐘支持的最大MQTT連接數(shù) | 1 |
單個(gè)MQTT連接每秒的吞吐量,即帶寬,包含直連設(shè)備和網(wǎng)關(guān) | 3KB/s |
MQTT單個(gè)發(fā)布消息最大長(zhǎng)度,超過此大小的發(fā)布請(qǐng)求將被直接拒絕 | 1MB |
MQTT連接心跳時(shí)間建議值 | 心跳時(shí)間限定為30至1200秒,推薦設(shè)置為120秒 |
產(chǎn)品是否支持自定義Topic | 支持 |
消息發(fā)布與訂閱 | 設(shè)備只能對(duì)自己的Topic進(jìn)行消息發(fā)布與訂閱 |
每個(gè)訂閱請(qǐng)求的最大訂閱數(shù) | 無限制 |
(3)主題訂閱格式
幫助文檔地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html
對(duì)于設(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/6419627e40773741f9fbdac7_dev1/sys/messages/down
?
(4)主題發(fā)布格式
對(duì)于設(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/6419627e40773741f9fbdac7_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":{"DS18B20":18,"motor_water":1,"motor_oxygen":1,"temp_max":10,"water_hp":130,"motor_food":0,"time_food":0,"oxygen_food":3}}]}
4.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ù)器地址:114.116.232.138
域名:7445c6bcd3.st1.iotda-device.cn-north-4.myhuaweicloud.com
華為云的MQTT端口號(hào):1883
注意?。。。?具體要看這里:
(2)生成MQTT三元組
華為云提供了一個(gè)在線工具,用來生成MQTT鑒權(quán)三元組: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/
打開這個(gè)工具,填入設(shè)備的信息(也就是剛才創(chuàng)建完設(shè)備之后保存的信息),點(diǎn)擊生成,就可以得到MQTT的登錄信息了。
下面是打開的頁(yè)面:
填入設(shè)備的信息: (上面兩行就是設(shè)備創(chuàng)建完成之后保存得到的)
得到三元組之后,設(shè)備端通過MQTT協(xié)議登錄鑒權(quán)的時(shí)候,填入?yún)?shù)即可。
ClientId 6419627e40773741f9fbdac7_dev1_0_0_2023032108
Username 6419627e40773741f9fbdac7_dev1
Password 861ac9e6a579d36888b2aaf97714be7af6c77017b017162884592bd68b086a6e
4.7 模擬設(shè)備登錄測(cè)試
經(jīng)過上面的步驟介紹,已經(jīng)創(chuàng)建了產(chǎn)品,設(shè)備,數(shù)據(jù)模型,得到MQTT登錄信息。 接下來就用MQTT客戶端軟件模擬真實(shí)的設(shè)備來登錄平臺(tái)。測(cè)試與服務(wù)器通信是否正常。
(1)填入登錄信息
打開MQTT客戶端軟件,對(duì)號(hào)填入相關(guān)信息(就是上面的文本介紹)。然后,點(diǎn)擊登錄,訂閱主題,發(fā)布主題。
(2)打開網(wǎng)頁(yè)查看
完成上面的操作之后,打開華為云網(wǎng)頁(yè)后臺(tái),可以看到設(shè)備已經(jīng)在線了。
點(diǎn)擊詳情頁(yè)面,可以看到上傳的數(shù)據(jù)。
到此,云平臺(tái)的部署已經(jīng)完成,設(shè)備已經(jīng)可以正常上傳數(shù)據(jù)了。
4.8 獲取設(shè)備影子數(shù)據(jù)(API接口)
幫助文檔: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è)備的屬性
簡(jiǎn)單來說:設(shè)備影子就是保存,設(shè)備最新上傳的一次數(shù)據(jù)。
我們?cè)O(shè)計(jì)的軟件里,如果想要獲取設(shè)備的最新狀態(tài)信息,就采用設(shè)備影子接口。
如果對(duì)接口不熟悉,可以先進(jìn)行在線調(diào)試:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow
在線調(diào)試接口,可以請(qǐng)求影子接口,了解請(qǐng)求,與返回的數(shù)據(jù)格式。
設(shè)備影子接口返回的數(shù)據(jù)如下:
{
"device_id": "6419627e40773741f9fbdac7_dev1",
"shadow": [
{
"service_id": "stm32",
"desired": {
"properties": null,
"event_time": null
},
"reported": {
"properties": {
"DS18B20": 18,
"motor_water": 1,
"motor_oxygen": 1,
"temp_max": 10,
"water_hp": 130,
"motor_food": 0,
"time_food": 0,
"oxygen_food": 3
},
"event_time": "20230321T081126Z"
},
"version": 0
}
]
}
4.9 修改設(shè)備屬性(API接口)
地址: https://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html
接口說明
設(shè)備的產(chǎn)品模型中定義了物聯(lián)網(wǎng)平臺(tái)可向設(shè)備下發(fā)的屬性,應(yīng)用服務(wù)器可調(diào)用此接口向指定設(shè)備下發(fā)屬性。平臺(tái)負(fù)責(zé)將屬性以同步方式發(fā)送給設(shè)備,并將設(shè)備執(zhí)行屬性結(jié)果同步返回。
修改設(shè)備屬性的接口,可以讓服務(wù)器給設(shè)備下發(fā)指令,如果需要控制設(shè)備。
在線調(diào)試地址:
https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=UpdateProperties
修改設(shè)備屬性是屬于同步命令,需要設(shè)備在線才可以進(jìn)行調(diào)試,先使用MQTT客戶端登錄服務(wù)器,模擬設(shè)備上線。
然后進(jìn)行調(diào)試,測(cè)試數(shù)據(jù)遠(yuǎn)程下發(fā)給設(shè)備。
【1】利用MQTT客戶端先登錄設(shè)備 (這是同步命令,必須在線才能調(diào)試)
【2】點(diǎn)擊調(diào)試
{"services":{"temp_max":100}}
【4】可以看到,MQTT客戶端軟件上已經(jīng)收到了服務(wù)器下發(fā)的消息
由于是同步命令,服務(wù)器必須要收到設(shè)備的響應(yīng)才能順利完成一個(gè)流程,設(shè)備響應(yīng)了服務(wù)器才能確定數(shù)據(jù)下發(fā)成功。
五、代碼設(shè)計(jì)
5.1 ESP8266模塊介紹
ESP8266-WIFI是一款由樂鑫科技開發(fā)的低成本W(wǎng)i-Fi芯片,可與其他微控制器或單片機(jī)配合使用,實(shí)現(xiàn)無線通訊功能。該芯片集成了一個(gè)高性能的32位Tensilica L106 RISC處理器,以及一組內(nèi)置的WIFI模塊和電源管理模塊,能夠在低功耗下提供穩(wěn)定的無線網(wǎng)絡(luò)連接。
以下是ESP8266與MQTT協(xié)議相關(guān)常用的AT指令介紹:
【1】AT+CIPSTART:建立TCP連接。
在使用MQTT協(xié)議時(shí),需要先建立TCP連接。AT+CIPSTART可以實(shí)現(xiàn)與MQTT服務(wù)器的TCP連接,格式如下:
AT+CIPSTART="TCP","MQTT服務(wù)器地址",MQTT服務(wù)器端口號(hào)
【2】AT+CIPSEND:發(fā)送數(shù)據(jù)。
在建立TCP連接之后,可以使用AT+CIPSEND發(fā)送數(shù)據(jù),包括MQTT協(xié)議的各種命令。格式如下:
AT+CIPSEND=<length>
<MQTT命令>
其中,表示數(shù)據(jù)長(zhǎng)度,<MQTT命令>表示MQTT協(xié)議的命令,例如CONNECT、PUBLISH、SUBSCRIBE等。
【3】AT+CIPCLOSE:關(guān)閉TCP連接。在使用完MQTT協(xié)議之后,可以使用AT+CIPCLOSE關(guān)閉TCP連接,格式如下:
AT+CIPCLOSE
【4】AT+CIPSTATUS:查詢TCP連接狀態(tài)。使用AT+CIPSTATUS可以查詢當(dāng)前TCP連接的狀態(tài),格式如下:
AT+CIPSTATUS
返回值包括:STATUS、TCP連接狀態(tài);LINK ID、TCP連接ID;IP、TCP連接的IP地址;PORT、TCP連接端口號(hào)。
【5】AT+MQTTCONN:連接MQTT服務(wù)器。使用AT+MQTTCONN可以連接MQTT服務(wù)器,格式如下:
AT+MQTTCONN=<clientID>,<user>,<password>,<keepalive>,<clean>,<willTopic>,<willMessage>,<willQoS>,<willRetain>
其中,表示客戶端ID;表示用戶名;表示密碼;表示心跳包間隔時(shí)間;表示清除會(huì)話標(biāo)志;表示遺言主題;表示遺言消息;表示遺言QoS等級(jí);表示遺言消息是否保留。
【6】AT+MQTTPUB:發(fā)布消息。使用AT+MQTTPUB可以發(fā)布MQTT消息,格式如下:
AT+MQTTPUB=<topic>,<payload>,<QoS>,<retain>
其中,表示MQTT主題;表示消息負(fù)載;表示消息QoS等級(jí);表示消息是否保留。
【7】AT+MQTTSUB:訂閱主題。使用AT+MQTTSUB可以訂閱MQTT主題,格式如下:
AT+MQTTSUB=<topic>,<QoS>
其中,表示MQTT主題;表示消息QoS等級(jí)。
5.2 連接云端代碼
以下是STM32F103+ESP8266通過MQTT協(xié)議登錄MQTT物聯(lián)網(wǎng)服務(wù)器,實(shí)現(xiàn)主題訂閱、發(fā)布的示例代碼,其中利用了ESP8266-WIFI的AT指令實(shí)現(xiàn)與MQTT服務(wù)器的通信。
需要在STM32F103上配置UART串口,以實(shí)現(xiàn)與ESP8266的通信。在STM32F103上編寫AT指令的發(fā)送和接收函數(shù),將其集成到工程中。
代碼如下:
#include "stm32f1xx_hal.h"
#include <string.h>
#include <stdio.h>
/* 定義ESP8266的UART串口 */
UART_HandleTypeDef huart1;
/* 定義MQTT服務(wù)器地址、端口號(hào)、用戶名和密碼等信息 */
const char* mqtt_server = "mqtt.example.com";
const int mqtt_port = 1883;
const char* mqtt_username = "username";
const char* mqtt_password = "password";
/* 定義MQTT主題 */
const char* mqtt_topic = "test/topic";
/* 定義回調(diào)函數(shù),處理MQTT消息 */
void messageArrived(MessageData* data)
{
printf("Message arrived: topic=%.*s, payload=%.*sn",
data->topicName->lenstring.len,
data->topicName->lenstring.data,
data->message->payloadlen,
data->message->payload);
}
/* 發(fā)送AT指令并等待響應(yīng) */
int ESP8266_SendATCommand(char* cmd, char* response, int timeout)
{
HAL_UART_Transmit(&huart1, (uint8_t*)cmd, strlen(cmd), timeout);
int len = 0;
int len_read = 0;
HAL_Delay(100);
while (1) {
if (HAL_UART_Receive(&huart1, (uint8_t*)response + len, 1, timeout) == HAL_OK) {
len++;
if (strstr(response, "OK") != NULL) {
return len;
}
if (strstr(response, "ERROR") != NULL) {
return -1;
}
if (len >= 1024) {
return -1;
}
}
}
}
/* 連接MQTT服務(wù)器 */
int MQTT_Connect(void)
{
char cmd[1024];
char response[1024];
/* 設(shè)置ESP8266為透?jìng)髂J?/a> */
ESP8266_SendATCommand("AT+CIPMODE=1rn", response, 1000);
ESP8266_SendATCommand("AT+CIPMUX=0rn", response, 1000);
/* 建立TCP連接 */
sprintf(cmd, "AT+CIPSTART="TCP","%s",%drn", mqtt_server, mqtt_port);
ESP8266_SendATCommand(cmd, response, 5000);
/* 連接MQTT服務(wù)器 */
sprintf(cmd, "AT+CIPSEND=%drn", 33 + strlen(mqtt_username) + strlen(mqtt_password));
ESP8266_SendATCommand(cmd, response, 1000);
sprintf(cmd, "CONNECTnrclient_id:ESP8266nruser:%snrpassword:%snrnr", mqtt_username, mqtt_password);
ESP8266_SendATCommand(cmd, response, 5000);
/* 訂閱MQTT主題 */
sprintf(cmd, "AT+CIPSEND=%drn", 10 + strlen(mqtt_topic));
ESP8266_SendATCommand(cmd, response, 1000);
sprintf(cmd, "SUBSCRIBEnr%dnr0nrnr", strlen(mqtt_topic));
ESP8266_SendATCommand(cmd, response, 5000);
return 0;
}
/* 發(fā)布MQTT消息 */
void MQTT_Publish(const char* message)
{
char cmd[1024];
char response[1024];
sprintf(cmd, "AT+CIPSEND=%drn", 8 + strlen(mqtt_topic) + strlen(message));
ESP8266_SendATCommand(cmd, response, 1000);
sprintf(cmd, "PUBLISHnr%dnr%snrnr%snr", strlen(mqtt_topic), mqtt_topic, message);
ESP8266_SendATCommand(cmd, response, 5000);
}
/* 主程序 */
int main(void)
{
/* 連接MQTT服務(wù)器 */
if (MQTT_Connect() != 0) {
while (1) {
/* 連接失敗,進(jìn)入死循環(huán) */
}
}
/* 發(fā)布MQTT消息 */
MQTT_Publish("Hello, MQTT!");
/* 等待接收MQTT消息 */
while (1) {
/* 讀取ESP8266接收緩沖區(qū)中的數(shù)據(jù) */
char response[1024];
int len = ESP8266_SendATCommand("AT+CIPRXGET=2,1024rn", response, 1000);
if (len > 0) {
printf("Received data: %.*sn", len, response);
/* TODO: 解析并處理MQTT消息 */
}
/* 延時(shí)一段時(shí)間 */
HAL_Delay(100);
}
return 0;
}
代碼實(shí)現(xiàn)了連接MQTT服務(wù)器、訂閱主題、發(fā)布消息等功能。
5.3 OLED顯示屏代碼
以下是使用STM32F103ZET6控制0.96寸SPI接口的OLED顯示屏的代碼:
cCopy Code#include "stm32f10x.h"
#include "spi.h" // SPI庫(kù)頭文件
// OLED相關(guān)定義
#define OLED_CMD 0 // 命令模式
#define OLED_DATA 1 // 數(shù)據(jù)模式
#define OLED_ADDR_START 0xB0 // OLED起始地址
#define OLED_PAGE_START 0x00 // 第一個(gè)頁(yè)的地址
#define OLED_COLUMN_START 0x10 // 列起始地址
// 初始化OLED顯示屏
void OLED_Init(void)
{
// 初始化SPI接口
SPI_Init();
Delay(100);
// 向OLED發(fā)送初始化命令和數(shù)據(jù)
// 模式設(shè)置:設(shè)置4位數(shù)據(jù)線,擴(kuò)展指令集
OLED_WriteCmd(OLED_CMD, 0x21);
// 對(duì)比度設(shè)置,默認(rèn)為0x7F
OLED_WriteCmd(OLED_CMD, 0x81);
OLED_WriteCmd(OLED_CMD, 0x7F);
// 設(shè)置顯示模式:正常顯示
OLED_WriteCmd(OLED_CMD, 0xA4);
// 設(shè)置偏置電壓
OLED_WriteCmd(OLED_CMD, 0xA8);
OLED_WriteCmd(OLED_CMD, 0x3F);
// 設(shè)置顯示方向:從左到右,從上到下
OLED_WriteCmd(OLED_CMD, 0xC8);
// 設(shè)置掃描地段,從COM0到COM[N-1]
OLED_WriteCmd(OLED_CMD, 0xDA);
OLED_WriteCmd(OLED_CMD, 0x12);
// 設(shè)置時(shí)鐘分頻因子
OLED_WriteCmd(OLED_CMD, 0xD5);
OLED_WriteCmd(OLED_CMD, 0x80);
// 設(shè)置顯示開啟
OLED_WriteCmd(OLED_CMD, 0xAF);
}
// 寫入命令或數(shù)據(jù)到OLED顯示屏
void OLED_WriteCmd(uint8_t mode, uint8_t cmd)
{
if (mode == OLED_CMD) {
GPIO_ResetBits(GPIOA, GPIO_Pin_4); // 將DC引腳置低,進(jìn)入命令模式
} else {
GPIO_SetBits(GPIOA, GPIO_Pin_4); // 將DC引腳置高,進(jìn)入數(shù)據(jù)模式
}
GPIO_ResetBits(GPIOA, GPIO_Pin_3); // 將CS引腳置低,選中OLED
SPI_SendData(cmd); // 發(fā)送命令或數(shù)據(jù)
while (SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET);
GPIO_SetBits(GPIOA, GPIO_Pin_3); // 將CS引腳置高,釋放OLED
}
// 在指定位置顯示一個(gè)數(shù)字
void OLED_ShowNumber(uint8_t x, uint8_t y, uint32_t number)
{
char str[11]; // 最大顯示10位數(shù)字
sprintf(str, "%lu", number); // 將數(shù)字轉(zhuǎn)換為字符串
OLED_ShowString(x, y, str); // 在指定位置顯示字符串
}
// 在指定位置顯示一個(gè)字符串
void OLED_ShowString(uint8_t x, uint8_t y, char *str)
{
uint8_t i = 0;
while (str[i] != '?') {
OLED_ShowChar(x, y, str[i]); // 在指定位置顯示一個(gè)字符
x += 6; // 移動(dòng)到下一列
i++;
}
}
// 在指定位置顯示一個(gè)字符
void OLED_ShowChar(uint8_t x, uint8_t y, char ch)
{
uint8_t i, j;
for (i = 0; i < 8; i++) { // 8行
OLED_WriteCmd(OLED_CMD, OLED_ADDR_START + y); // 指定頁(yè)
OLED_WriteCmd(OLED_CMD, OLED_COLUMN_START + x); // 指定列
for (j = 0; j < 6; j++) { // 6列
OLED_WriteCmd(OLED_DATA, ASCII[ch - 32][j]);
}
y++;
}
}
在這段代碼中,定義了OLED相關(guān)的常量和函數(shù),包括OLED命令模式和數(shù)據(jù)模式、OLED起始地址、頁(yè)起始地址、列起始地址等。在OLED_Init()
函數(shù)中進(jìn)行了OLED的初始化過程,包括發(fā)送相應(yīng)的初始化命令和數(shù)據(jù)給OLED顯示屏。在OLED_WriteCmd()
函數(shù)中,根據(jù)傳入的命令模式(OLED_CMD)或數(shù)據(jù)模式(OLED_DATA),將DC引腳設(shè)置為相應(yīng)的狀態(tài),并通過SPI接口將命令或數(shù)據(jù)發(fā)送給OLED顯示屏。在OLED_ShowNumber()
、OLED_ShowString()
和OLED_ShowChar()
函數(shù)中,通過調(diào)用OLED_WriteCmd()
發(fā)送相應(yīng)的指令和數(shù)據(jù),實(shí)現(xiàn)在指定位置顯示數(shù)字、字符串和字符。
5.4 步進(jìn)電機(jī)控制代碼
以下是STM32F103+28BYJ40步進(jìn)電機(jī)實(shí)現(xiàn)角度控制和正反轉(zhuǎn)控制的代碼,使用了STM32F1xx_HAL庫(kù)來控制GPIO口和定時(shí)器,實(shí)現(xiàn)精準(zhǔn)的角度控制和正反轉(zhuǎn)控制。
#include "stm32f1xx_hal.h"
#include <stdio.h>
/* 定義步進(jìn)電機(jī)的4個(gè)控制引腳 */
#define IN1_Pin GPIO_PIN_0
#define IN1_GPIO_Port GPIOA
#define IN2_Pin GPIO_PIN_1
#define IN2_GPIO_Port GPIOA
#define IN3_Pin GPIO_PIN_2
#define IN3_GPIO_Port GPIOA
#define IN4_Pin GPIO_PIN_3
#define IN4_GPIO_Port GPIOA
/* 定義步進(jìn)電機(jī)的步數(shù)數(shù)組 */
uint8_t step_sequence[8] = {0b0001, 0b0011, 0b0010, 0b0110, 0b0100, 0b1100, 0b1000, 0b1001};
/* 定義當(dāng)前步進(jìn)電機(jī)的位置和方向 */
int current_step = 0; // 當(dāng)前步數(shù)
int direction = 1; // 1為順時(shí)針,-1為逆時(shí)針
/* 定義角度控制參數(shù) */
float angle_per_step = 1.8; // 每步角度
int total_steps = 2048; // 總步數(shù)
/* 定義定時(shí)器中斷處理函數(shù),控制步進(jìn)電機(jī)的運(yùn)動(dòng) */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
/* 更新步進(jìn)電機(jī)的位置 */
current_step += direction;
if (current_step >= total_steps) {
current_step = 0;
} else if (current_step < 0) {
current_step = total_steps - 1;
}
/* 控制步進(jìn)電機(jī)的旋轉(zhuǎn)方向 */
int sequence_index = current_step % 8;
GPIO_PinState in1_state = (step_sequence[sequence_index] & 0b0001) ? GPIO_PIN_SET : GPIO_PIN_RESET;
GPIO_PinState in2_state = (step_sequence[sequence_index] & 0b0010) ? GPIO_PIN_SET : GPIO_PIN_RESET;
GPIO_PinState in3_state = (step_sequence[sequence_index] & 0b0100) ? GPIO_PIN_SET : GPIO_PIN_RESET;
GPIO_PinState in4_state = (step_sequence[sequence_index] & 0b1000) ? GPIO_PIN_SET : GPIO_PIN_RESET;
HAL_GPIO_WritePin(IN1_GPIO_Port, IN1_Pin, in1_state);
HAL_GPIO_WritePin(IN2_GPIO_Port, IN2_Pin, in2_state);
HAL_GPIO_WritePin(IN3_GPIO_Port, IN3_Pin, in3_state);
HAL_GPIO_WritePin(IN4_GPIO_Port, IN4_Pin, in4_state);
}
/* 初始化定時(shí)器 */
void TIM_Init(void)
{
TIM_HandleTypeDef htim;
/* 使能定時(shí)器時(shí)鐘 */
__HAL_RCC_TIM2_CLK_ENABLE();
/* 配置定時(shí)器 */
htim.Instance = TIM2;
htim.Init.Prescaler = 7199; // 72MHz / 7200 = 10kHz
htim.Init.CounterMode = TIM_COUNTERMODE_UP;
htim.Init.Period = 99; // 10kHz / 100 = 100Hz
htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
HAL_TIM_Base_Init(&htim);
/* 啟動(dòng)定時(shí)器 */
HAL_TIM_Base_Start_IT(&htim);
}
/* 控制步進(jìn)電機(jī)旋轉(zhuǎn) */
void StepMotor_Rotate(int angle, int clockwise)
{
/* 計(jì)算需要旋轉(zhuǎn)的步數(shù)和方向 */
int steps = angle / angle_per_step;
direction = clockwise ? 1 : -1;
/* 控制步進(jìn)電機(jī)旋轉(zhuǎn) */
for (int i = 0; i < steps; i++) {
HAL_Delay(1);
}
}
/* 主程序 */
int main(void)
{
/* 初始化定時(shí)器 */
TIM_Init();
/* 控制步進(jìn)電機(jī)旋轉(zhuǎn) */
StepMotor_Rotate(90, 1); // 順時(shí)針旋轉(zhuǎn)90度
StepMotor_Rotate(180, 0); // 逆時(shí)針旋轉(zhuǎn)180度
while (1) {
/* 循環(huán)等待 */
}
return 0;
}
IN1_Pin到IN4_Pin為步進(jìn)電機(jī)的控制引腳,step_sequence為步進(jìn)電機(jī)的步數(shù)數(shù)組,current_step為當(dāng)前步數(shù),direction為旋轉(zhuǎn)方向,angle_per_step為每步的角度,total_steps為總步數(shù)。在HAL_TIM_PeriodElapsedCallback函數(shù)中,根據(jù)當(dāng)前步數(shù)和旋轉(zhuǎn)方向控制步進(jìn)電機(jī)的旋轉(zhuǎn)方向,使用HAL_GPIO_WritePin函數(shù)控制引腳輸出狀態(tài)。在StepMotor_Rotate函數(shù)中,根據(jù)傳入的角度和旋轉(zhuǎn)方向計(jì)算需要旋轉(zhuǎn)的步數(shù)和方向,然后循環(huán)延時(shí)控制步進(jìn)電機(jī)旋轉(zhuǎn)。通過調(diào)用StepMotor_Rotate函數(shù),可以實(shí)現(xiàn)步進(jìn)電機(jī)的角度控制和正反轉(zhuǎn)控制。
六、總結(jié)
智能門禁系統(tǒng)是一種基于STM32F103主控制器和華為云物聯(lián)網(wǎng)平臺(tái)的安全、便捷的門禁控制方案。通過整合多種硬件模塊和網(wǎng)絡(luò)通信技術(shù),該系統(tǒng)實(shí)現(xiàn)了多種開鎖方式(密碼輸入、RFID刷卡、手機(jī)APP遠(yuǎn)程開鎖),并且具備遠(yuǎn)程監(jiān)控和消息推送功能。
在硬件選型上,刷卡模塊選擇了RFID-RC522,采用28BYJ-48步進(jìn)電機(jī)作為門鎖控制器,4x4電容矩陣鍵盤用于密碼輸入,SPI接口的0.96寸OLED顯示屏用于門鎖狀態(tài)信息顯示,而ESP8266-WIFI模塊則實(shí)現(xiàn)了聯(lián)網(wǎng)功能。此外,紅外磁感應(yīng)模塊用于檢測(cè)門的狀態(tài)。
整個(gè)系統(tǒng)的設(shè)計(jì)使得門禁更加安全可靠,用戶可以通過多種方式進(jìn)行開鎖操作,包括輸入密碼、刷卡以及遠(yuǎn)程開鎖。同時(shí),系統(tǒng)可以實(shí)時(shí)監(jiān)控門鎖狀態(tài),并在門鎖打開或關(guān)閉時(shí)通過手機(jī)APP向用戶發(fā)送通知提醒,提高了使用者的安全性和便利性。
基于STM32F103和華為云物聯(lián)網(wǎng)平臺(tái)的智能門禁系統(tǒng)充分利用了現(xiàn)代科技的優(yōu)勢(shì),提供了安全、便捷的門禁控制解決方案。除了基本的門禁功能外,該系統(tǒng)還具備遠(yuǎn)程控制和實(shí)時(shí)監(jiān)控的能力,為用戶帶來更加智能化的門禁體驗(yàn),并滿足了現(xiàn)代人們對(duì)于安全、便捷生活的需求。