項(xiàng)目3 網(wǎng)關(guān)和APP 的MQTT 通信設(shè)計(jì)_第1頁
項(xiàng)目3 網(wǎng)關(guān)和APP 的MQTT 通信設(shè)計(jì)_第2頁
項(xiàng)目3 網(wǎng)關(guān)和APP 的MQTT 通信設(shè)計(jì)_第3頁
項(xiàng)目3 網(wǎng)關(guān)和APP 的MQTT 通信設(shè)計(jì)_第4頁
項(xiàng)目3 網(wǎng)關(guān)和APP 的MQTT 通信設(shè)計(jì)_第5頁
已閱讀5頁,還剩136頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡介

2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)MQTT服務(wù)器部署一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)1以阿里云服務(wù)器為例,講解在云服務(wù)器上通過開源EMQX軟件搭建MQTT服務(wù)器的步驟。建議不要安裝在本地(沒有公網(wǎng)IP),而是安裝在云服務(wù)器上。任務(wù)引入MQTT(消息隊(duì)列遙測傳輸)是物聯(lián)網(wǎng)中用于向設(shè)備發(fā)送消息和從設(shè)備中接收消息的輕量級消息傳遞協(xié)議,也是物聯(lián)網(wǎng)系統(tǒng)設(shè)計(jì)中最主流和最受歡迎的協(xié)議。擁有1個(gè)可通過公網(wǎng)訪問的MQTT服務(wù)器,就能很方便地讓物聯(lián)網(wǎng)網(wǎng)關(guān)、物聯(lián)網(wǎng)APP、物聯(lián)網(wǎng)后端等物聯(lián)網(wǎng)客戶端之間進(jìn)行MQTT通信。二、相關(guān)知識(shí)MQTT組件物聯(lián)網(wǎng)中使用的協(xié)議有很多種,以下是一些常用的物聯(lián)網(wǎng)協(xié)議:(1)MQTT(MessageQueuingTelemetryTransport,消息隊(duì)列遙測傳輸),是一種輕量級、靈活和可擴(kuò)展的消息傳輸協(xié)議,適用于低帶寬、高延遲或不可靠網(wǎng)絡(luò)環(huán)境;(2)CoAP(ConstrainedApplicationProtocol,約束應(yīng)用協(xié)議),是一種基于RESTful架構(gòu)的應(yīng)用層協(xié)議,適用于受限環(huán)境下的無線傳感器網(wǎng)絡(luò)和物聯(lián)網(wǎng)設(shè)備通信;(3)HTTP(HypertextTransferProtocol,超文本傳輸協(xié)議),是一種廣泛使用的應(yīng)用層協(xié)議,適用于互聯(lián)網(wǎng)上的客戶端和服務(wù)器之間的通信,也可以用于物聯(lián)網(wǎng)設(shè)備之間的通信。(4)DDS(DataDistributionService,數(shù)據(jù)分發(fā)服務(wù)),是一種面向數(shù)據(jù)的消息傳輸協(xié)議,適用于大規(guī)模分布式系統(tǒng)和實(shí)時(shí)應(yīng)用場景;(5)ZigBee,是一種針對低功率無線傳感器網(wǎng)絡(luò)的通信協(xié)議,適用于自組織網(wǎng)絡(luò)和低速率數(shù)據(jù)傳輸;(6)LoRaWAN(LongRangeWideAreaNetwork,長距離廣域網(wǎng)),是一種長距離低功耗無線通信技術(shù),適用于需要遠(yuǎn)程監(jiān)測和控制的物聯(lián)網(wǎng)場景。二、相關(guān)知識(shí)這些協(xié)議各有優(yōu)劣,選擇哪種協(xié)議取決于具體應(yīng)用場景和需求。例如,如果需要在低帶寬、高延遲或不可靠網(wǎng)絡(luò)環(huán)境下傳輸數(shù)據(jù),則MQTT可能是更好的選擇;如果需要使用RESTful架構(gòu)進(jìn)行通信,則CoAP可能更適合;如果需要實(shí)時(shí)分布式數(shù)據(jù)傳輸,則DDS可能更合適。EMQXEMQX是一款全球下載量超千萬的大規(guī)模分布式物聯(lián)網(wǎng)MQTT服務(wù)器,單集群支持1億物聯(lián)網(wǎng)設(shè)備連接,消息分發(fā)時(shí)延低于1毫秒,為高可靠、高性能的物聯(lián)網(wǎng)實(shí)時(shí)數(shù)據(jù)移動(dòng)、處理和集成提供動(dòng)力,助力企業(yè)構(gòu)建關(guān)鍵業(yè)務(wù)的IoT平臺(tái)與應(yīng)用。EMQX自2013年在GitHub發(fā)布開源版本以來,獲得了來自50多個(gè)國家和地區(qū)的20000余家企業(yè)用戶的廣泛認(rèn)可,累計(jì)連接物聯(lián)網(wǎng)關(guān)鍵設(shè)備超過1億臺(tái)。二、相關(guān)知識(shí)我們可通過EMQX在云服務(wù)器上部署MQTT服務(wù)器。你知道有哪些云服務(wù)器提供商嗎?課堂討論學(xué)思之窗阿里云是阿里巴巴集團(tuán)旗下的云計(jì)算服務(wù)品牌,提供包括計(jì)算、存儲(chǔ)、網(wǎng)絡(luò)、安全、大數(shù)據(jù)等多種云計(jì)算產(chǎn)品及解決方案。阿里云在全球范圍內(nèi)擁有眾多數(shù)據(jù)中心和節(jié)點(diǎn),可以為用戶提供高性能、高可用、高可靠的云計(jì)算服務(wù)。在日常學(xué)習(xí)和工作中,要實(shí)踐和運(yùn)用像阿里云這樣的世界領(lǐng)先的云計(jì)算產(chǎn)品和服務(wù),按照黨的二十大報(bào)告提出的“必須堅(jiān)持創(chuàng)新是第一動(dòng)力,深入實(shí)施創(chuàng)新驅(qū)動(dòng)發(fā)展戰(zhàn)略”要求,參與推進(jìn)“雙創(chuàng)”“眾創(chuàng)”等創(chuàng)新活動(dòng),為國家創(chuàng)新能力提升做出貢獻(xiàn)。相關(guān)鏈接EMQX開源版文檔:www.emqx.io/docs/zh/latest/。EMQX官網(wǎng):/zh。三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了CentOS操作系統(tǒng)的計(jì)算機(jī)(最好是云服務(wù)器)。實(shí)施過程EMQX安裝登錄官網(wǎng)(/zh/downloads?product=broker),選擇開源版。選擇系統(tǒng)對應(yīng)的合適版本,如圖3-1所示。圖3-1選擇對應(yīng)的操作系統(tǒng)三、任務(wù)實(shí)施CPU架構(gòu)具體看自己電腦的CPU情況,示例中為x86_64(intel)架構(gòu),如圖3-2所示。按提示命令執(zhí)行即可。注意如果在linux的home下安裝,可以找到文件夾emqx,通過cdemqx進(jìn)入,進(jìn)而找到bin文件夾,執(zhí)行即可。其中下載安裝包的代碼如下:EMQX啟動(dòng)說明文檔:/broker/v4.3/getting-started/start.html。wget/zh/downloads/broker/4.2.14/emqx-centos7-4.2.14-x86_64.zip相關(guān)鏈接圖3-2選擇對應(yīng)的CPU架構(gòu)三、任務(wù)實(shí)施2.阿里云的EMQX配置(1)開放端口。在虛擬機(jī)安裝的Linux使用該方式放開端口:保存操作:iptables-AINPUT-ptcp--dport1883-jACCEPTiptables-AINPUT-ptcp--dport8883-jACCEPTiptables-AINPUT-ptcp--dport8083-jACCEPTiptables-AINPUT-ptcp--dport8080-jACCEPTiptables-AINPUT-ptcp--dport18083-jACCEPTserviceiptablessave在阿里云對應(yīng)的云服務(wù)器的安全組中添加對應(yīng)的開放端口,18083對應(yīng)控制臺(tái),如圖3-3所示。圖3-3阿里云服務(wù)器開放端口三、任務(wù)實(shí)施(2)開啟emqx。通過命令行開啟,需要進(jìn)入bin目錄的emqx打開,如圖3-4所示。(3)訪問EMQX后臺(tái)。訪問后臺(tái)地址:http://localhost:18083。其中,localhost可以替換為你的云服務(wù)器公網(wǎng)IP或者虛擬機(jī)IP。圖3-4開啟EMQX三、任務(wù)實(shí)施3.配置EMQX服務(wù)器用戶名/密碼方式登錄(1)完整代碼。共分為3步:[root@iZbp1j4preny574qlep0klZemqx]#./bin/emqxstopok[root@iZbp1j4preny574qlep0klZemqx]#vim./etc/emqx.conf[root@iZbp1j4preny574qlep0klZemqx]#./bin/emqxstartEMQXBroker4.2.14isstartedsuccessfully![root@iZbp1j4preny574qlep0klZemqx]#(2)步驟1:停止服務(wù)。./bin/emqxstop(3)編輯用戶名、密碼配置文件。通過語句vim./etc/plugins/emqx_auth_username.conf進(jìn)入配置文件,然后在文件中增加用戶名、密碼,密碼算法改為plain(透傳),如圖3-5所示。三、任務(wù)實(shí)施Linux中,修改、刪除指令分別為shift+“i”、shift+“x”。保存操作指令為shift+“:”,然后輸入“wq!”退出。圖3-5編輯用戶名、密碼配置文件(4)關(guān)閉匿名登錄。vim./etc/emqx.conf查找allow_anonymous,修改為false。注意:如果想開放給別人匿名登錄,要再把false改為true。四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)1學(xué)習(xí)了如何在一臺(tái)安裝了CentOS操作系統(tǒng)的云服務(wù)器上,通過EMQX部署MQTT服務(wù)器的過程。如果沒有云服務(wù)器資源,則可以直接使用作者搭建的MQTT服務(wù)器,IP地址為69,端口為1883,各個(gè)MQTT客戶端不需要密碼即可訪問。也可以在本地Windows操作系統(tǒng)的計(jì)算機(jī)上,創(chuàng)建Linux鏡像,然后利用EMQX部署,只是因?yàn)闆]有公網(wǎng)IP,所以只適合局域網(wǎng)內(nèi)的計(jì)算機(jī),使用不太方便。根據(jù)自己的資源情況,部署一個(gè)MQTT服務(wù)器。實(shí)踐練習(xí)謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)MQTT.fx客戶端測試MQTT通信一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)在任務(wù)2中,我們將安裝MQTT.fx測試軟件,創(chuàng)建MQTT客戶端,觀察理解MQTT客戶端和MQTT代理服務(wù)器之間的通信過程。如果任務(wù)1中因?yàn)橘Y源問題不方便搭建自己的MQTT服務(wù)器,那么可以使用作者搭建好的MQTT服務(wù)器,其IP地址為69,端口為1883,各個(gè)MQTT客戶端不需要密碼即可訪問。任務(wù)引入眾所周知,MQTT是物聯(lián)網(wǎng)中非常重要的一種通信協(xié)議。任務(wù)1介紹了MQTT服務(wù)器的搭建步驟,那么到底MQTT是如何通信的呢?二、相關(guān)知識(shí)什么是MQTTMQTT(消息隊(duì)列遙測傳輸)是物聯(lián)網(wǎng)中用于向設(shè)備發(fā)送消息和從設(shè)備接收消息的輕量級消息傳遞協(xié)議,通過TCP/IP網(wǎng)絡(luò)運(yùn)行。MQTT由于其簡單性和易用性而迅速成為最受歡迎的物聯(lián)網(wǎng)協(xié)議。MQTT的最新版本是v5,但v3.1.1和v3.1仍然是最常用的。MQTT組件MQTT通過發(fā)布/訂閱模型工作,如圖3-6所示。MQTT設(shè)置有2個(gè)主要組件:代理Broker,是一個(gè)中央集線器或服務(wù)器,負(fù)責(zé)客戶端之間的所有連接并存儲(chǔ)所有消息;客戶端,是連接到代理并可以發(fā)布和接收消息的設(shè)備。圖3-6MQTT的發(fā)布/訂閱模型二、相關(guān)知識(shí)MQTT消息是如何傳遞的準(zhǔn)備工作(以客戶端A發(fā)送消息給客戶端B為例):首先雙方確定好消息主題名(如topic1)和消息載荷格式;然后,客戶端A通過client.connect()方法登錄MQTT代理服務(wù)器;最后,客戶端B通過client.connect()方法登錄MQTT代理服務(wù)器,并通過client.subscribe()方法訂閱消息主題,通過client.setCallback()方法設(shè)置回調(diào)函數(shù)。傳遞過程:客戶端A通過client.publish()方法發(fā)送主題為topic1的消息到MQTT代理服務(wù)器,代理會(huì)轉(zhuǎn)發(fā)消息到所有訂閱了此消息的客戶端;客戶端B收到消息后,在回調(diào)函數(shù)中對消息進(jìn)行解析處理。MQTT協(xié)議中的一些關(guān)鍵詞和基本概念訂閱(Subscribe):訂閱包含主題名、服務(wù)質(zhì)量(Qos)等級。主題名(TopicName):附加在應(yīng)用消息上的一個(gè)標(biāo)簽。服務(wù)器(Broker):在消息訂閱模型中充當(dāng)服務(wù)器的角色,類似于送信的郵差。消息服務(wù)質(zhì)量(Qos)機(jī)制:通過使用Qos機(jī)制,來保證通信的質(zhì)量。載荷(Payload):消息訂閱者所具體接收的內(nèi)容。客戶端ID:MQTT客戶端的唯一標(biāo)識(shí),注意一定不能和其他客戶端重名,否則會(huì)造成沖突。三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了Windows操作系統(tǒng)的計(jì)算機(jī),部署了MQTT服務(wù)器的云服務(wù)器。實(shí)施過程1.安裝MQTT.fx軟件網(wǎng)址為http://www.jensd.de/apps/mqttfx/1.7.1/,下載后雙擊安裝,界面如圖3-7所示。圖3-7MQTT.fx軟件界面三、任務(wù)實(shí)施MQTT.fx客戶端既可以作為發(fā)布端(Publish),也可以作為接收端(Subscribe),利用MQTT服務(wù)器進(jìn)行消息的中轉(zhuǎn)。眾所周知,如果客戶端A和B都登錄了EMQX服務(wù)器,客戶端B訂閱了主題(topic)為X的消息,那么客戶端A發(fā)布消息X后,客戶端B就會(huì)收到此消息。2.MQTT.fx客戶端連接MQTT服務(wù)器如圖3-8所示,設(shè)置客戶端ID、登錄賬號(hào)密碼、要連接的MQTT服務(wù)器。設(shè)置路徑為:Extras→EditConnectionProfiles。圖3-8MQTT.fx設(shè)置連接客戶端ID需要獨(dú)一無二,可以用手機(jī)號(hào)、qq號(hào)、學(xué)號(hào)等測試。因?yàn)閳D中的MQTT服務(wù)器未設(shè)置登錄密碼,MQTT客戶端可以公開訪問,所以用戶名和密碼暫空。三、任務(wù)實(shí)施設(shè)置完畢,點(diǎn)擊確定。回到主頁面,選擇對應(yīng)的MQTT服務(wù)器,然后點(diǎn)擊Connect進(jìn)行連接,如圖3-9所示。3.MQTT.fx客戶端發(fā)布消息如圖3-10所示,在Publish欄中,輸入要發(fā)布的消息topic和消息內(nèi)容,點(diǎn)擊“Publish”按鈕即可發(fā)布成功。如果有其他客戶端訂閱了這個(gè)topic的消息,就會(huì)收到。圖3-9點(diǎn)擊Connect連接MQTT服務(wù)器可以在MQTT服務(wù)器的后臺(tái)查看客戶端連接情況。圖3-10發(fā)送MQTT消息三、任務(wù)實(shí)施4.MQTT.fx客戶端訂閱與接收消息在Subscribe欄中,輸入要訂閱的消息topic,點(diǎn)擊“Subscribe”按鈕即可訂閱成功,如圖3-11所示。如果有其他客戶端發(fā)送這個(gè)topic的消息,內(nèi)容就會(huì)顯示在右側(cè)。可以在兩個(gè)客戶端之間驗(yàn)證收發(fā)過程。如圖3-10所示發(fā)布消息后,MQTT.fx客戶端可以收到消息,接收效果如圖3-12所示。圖3-11訂閱MQTT消息圖3-12接收MQTT消息四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)在任務(wù)2中,我們安裝了MQTT.fx軟件,創(chuàng)建了MQTT客戶端并通過實(shí)際操作,觀察了MQTT客戶端和MQTT代理服務(wù)器之間的通信過程。自定義發(fā)布和訂閱的消息主題(必須一樣才行),在MQTT.fx客戶端測試MQTT消息的收發(fā)。實(shí)踐練習(xí)謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)物聯(lián)網(wǎng)APP的MQTT配置一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)3在AndroidStudio工程中對MQTT通信功能進(jìn)行配置,包括網(wǎng)絡(luò)權(quán)限的配置和導(dǎo)入MQTT的jar包,為后續(xù)APP和其他MQTT客戶端之間的MQTT通信做準(zhǔn)備。任務(wù)引入任務(wù)2測試了MQTT.fx客戶端的MQTT通信,包括發(fā)布消息和訂閱與接收消息。其實(shí),不同的MQTT客戶端的MQTT通信過程都是一樣的。二、相關(guān)知識(shí)命名規(guī)范類和接口名:采用大駝峰命名法(PascalCase),即每個(gè)單詞首字母大寫,不使用下劃線或其他特殊字符。方法和變量名:采用小駝峰命名法(CamelCase),即第一個(gè)單詞小寫,后面的每個(gè)單詞首字母大寫。常量名:全部使用大寫字母,并使用下劃線分隔單詞。格式規(guī)范縮進(jìn):使用4個(gè)空格進(jìn)行縮進(jìn)。括號(hào):左花括號(hào)({)應(yīng)該與聲明語句放在同一行,右花括號(hào)(})應(yīng)該獨(dú)占一行。注釋:為了提高代碼的可讀性和可維護(hù)性,應(yīng)在關(guān)鍵的代碼塊前面添加注釋。在Android開發(fā)中,編碼規(guī)范是非常重要的,包括命名、格式、注釋等多個(gè)方面。二、相關(guān)知識(shí)注釋規(guī)范文件頭注釋:每個(gè)Java文件都應(yīng)該有一個(gè)頭部注釋,包括作者、創(chuàng)建日期和版本信息等。類注釋:每個(gè)類都應(yīng)該有一個(gè)類注釋,說明該類的作用和設(shè)計(jì)思路。方法注釋:每個(gè)方法都應(yīng)該有一個(gè)方法注釋,說明該方法的功能、參數(shù)和返回值等。需要注意的是,這些規(guī)范只是一些建議,具體實(shí)現(xiàn)應(yīng)該根據(jù)團(tuán)隊(duì)和項(xiàng)目的要求而定。但是,遵循這些規(guī)范可以使代碼更加清晰,易于理解和維護(hù)。三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了AndroidStudio開發(fā)環(huán)境的計(jì)算機(jī)。實(shí)施過程1.添加網(wǎng)絡(luò)權(quán)限如圖3-13所示,允許程序打開網(wǎng)絡(luò)套接字,在src→main→AndroidManifest.xml文件中的對應(yīng)位置編寫以下代碼:<uses-permissionandroid:name="android.permission.INTERNET"/>圖3-13添加網(wǎng)絡(luò)權(quán)限三、任務(wù)實(shí)施2.導(dǎo)入MQTT的jar包下載org.eclipse.paho.client.mqttv3-1.2.0.jar,粘貼到libs目錄下,如圖3-14所示。圖3-14導(dǎo)入MQTT的jar包選中新放入工程目錄的jar包,右鍵選擇并點(diǎn)擊“addaslibrary”,即可保證jar包的依賴關(guān)系。接下來就可以使用jar包的相關(guān)函數(shù)創(chuàng)建MQTT客戶端,以及進(jìn)行MQTT通信。三、任務(wù)實(shí)施3.測試完成以上步驟,在代碼里輸入“Mqtt”,相關(guān)的方法就有了,如圖3-15所示。如果沒有,則看看是不是沒有同步,或者將Andoid工程重啟一下。注意:MQTT通信相關(guān)的類名以“Mqtt”開頭,采用大駝峰命名法,首字母大寫。圖3-15測試MQTT是否配置成功打開項(xiàng)目根目錄下的settings.gradle文件,修改文件中的rootP="新項(xiàng)目名",如圖3-16所示,然后點(diǎn)擊同步。圖3-16修改項(xiàng)目名三、任務(wù)實(shí)施修改路徑文件夾名:關(guān)閉AndroidStudio,找到工程所在路徑,修改所在路徑的文件夾為新的名稱。打開AndroidStudio,重新導(dǎo)入工程即可。如果想要修改后的工程與之前的工程不沖突(實(shí)現(xiàn)不覆蓋安裝),還需要修改build.gradle文件的applicationId,然后同步即可,如圖3-17所示。圖3-17修改applicationId圖3-18修改app_name的值如果要更改APP名稱,可在app→src→main→res→values→strings.xml中修改app_name的值,如圖3-18所示。四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)3完成了物聯(lián)網(wǎng)APP的MQTT相關(guān)配置,就可以在Android工程中使用MQTT相關(guān)的基礎(chǔ)方法了,如執(zhí)行連接、訂閱消息、發(fā)布消息。修改APP名稱,加上學(xué)號(hào)。實(shí)踐練習(xí)謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)物聯(lián)網(wǎng)APP的MQTT變量與函數(shù)一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)4介紹MQTT需要定義的變量,并在MQTT方法的基礎(chǔ)上,編寫初始化、連接、重連接、發(fā)布消息、關(guān)閉連接函數(shù)。使用的Activity文件為SecondActivity.java,通信時(shí)需要使用Handler實(shí)現(xiàn)消息的傳遞。任務(wù)引入APP的頁面2使用MQTT通信,包括通過APP發(fā)送MQTT消息(控制命令),以及接收MQTT消息并顯示。任務(wù)3通過MQTT的配置,已經(jīng)可以在Android工程中使用MQTT相關(guān)的基礎(chǔ)方法了,如執(zhí)行連接、訂閱消息、發(fā)布消息。因?yàn)槭蔷W(wǎng)絡(luò)通信,所以MQTT現(xiàn)有的方法還需要考慮各種異常的處理,才能夠正常使用。二、相關(guān)知識(shí)為什么需要Handler類當(dāng)多個(gè)線程并發(fā)操作UI組件,可能導(dǎo)致線程不安全,故Android并不允許在UI線程(主線程)外操作UI。正確的做法是:Android應(yīng)用啟動(dòng)后默認(rèn)開啟一個(gè)主線程;如果其他子線程要更新UI,可以將要更新的內(nèi)容通過Handler傳遞給主線程,在主線程中完成UI更新。Handler執(zhí)行流程如圖3-19所示,Handler執(zhí)行流程如下:首先,在主線程中直接創(chuàng)建Handler對象;然后,子線程想修改Activity中的UI組件時(shí),可以通過Handler對象向主線程發(fā)送消息;最后,發(fā)送的消息會(huì)先到主線程的MessageQueue(消息隊(duì)列)等待,由Looper按先入先出順序取出,再由Handler根據(jù)message對象的what屬性對應(yīng)進(jìn)行處理。圖3-19Handler執(zhí)行流程二、相關(guān)知識(shí)課堂討論Android并不允許我們在UI線程外操作UI,如果嘗試的話,能夠成功嗎?三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了AndroidStudio開發(fā)環(huán)境的計(jì)算機(jī),部署了MQTT服務(wù)器的云服務(wù)器。1.變量與對象在SecondActivity.java中定義以下變量與對象:ActivitySecondBindingbinding2;//創(chuàng)建activity_second布局類對象privateStringhost="tcp://69:1883";//EMQX物聯(lián)網(wǎng)服務(wù)器privateStringusername="user";//EMQX服務(wù)器未設(shè)MQTT客戶端登錄密碼,所以可以空著;假如設(shè)置了客戶端訪問的賬號(hào)密碼,就必須輸入privateStringpassword="";privateStringmqtt_id=;//獨(dú)一無二的,可以用手機(jī)號(hào)、qq號(hào)等privateStringmqtt_sub_topic="my_FX/post";//:/手機(jī)號(hào)/my_FX/post,代表MQTT.fx上報(bào)的消息privateStringmqtt_pub_topic="my_APP/set";//:/手機(jī)號(hào)/my_APP/set,代表APP發(fā)布的命令privateintLedStatus=0;//APP發(fā)布的消息為{"LedStatus":0},{"LedStatus":1},將用于控制網(wǎng)關(guān)所接Led實(shí)施過程三、任務(wù)實(shí)施privateintLedStatus=0;//APP發(fā)布的消息為{"LedStatus":0},{"LedStatus":1},將用于控制網(wǎng)關(guān)所接LedprivateScheduledExecutorServicescheduler;privateMqttClientclient;privateMqttConnectOptionsoptions;//MQTT連接時(shí)的參數(shù)privateHandlerhandler;其中定義了MQTT服務(wù)器IP地址、服務(wù)器端口號(hào)、客戶端用戶名,客戶端登錄密碼、客戶端ID、客戶端發(fā)布消息主題、客戶端訂閱消息主題等。注意:創(chuàng)建的MQTT客戶端ID不能和其他MQTT客戶端ID沖突。以上代碼還創(chuàng)建了binding、調(diào)度器、MQTT客戶端、MQTT參數(shù)、Handler等對象。三、任務(wù)實(shí)施2.函數(shù)onCreate函數(shù)后面復(fù)制5個(gè)函數(shù)。(1)初始化函數(shù)。//1-Mqtt初始化函數(shù)privatevoidMqtt_init(){try{//host主機(jī)名,clientid連接MQTT的客戶端ID,MemoryPersistence設(shè)置clientid保存形式,默認(rèn)以內(nèi)存保存client=newMqttClient(host,mqtt_id,newMemoryPersistence());//MQTT的連接設(shè)置options=newMqttConnectOptions();//設(shè)置是否清空session,false表示服務(wù)器會(huì)保留客戶端連接記錄,true表示每次都以新身份連接服務(wù)器options.setCleanSession(false);//設(shè)置連接的用戶名options.setUserName(username);//設(shè)置連接密碼options.setPassword(password.toCharArray());//設(shè)置超時(shí)時(shí)間,單位為秒options.setConnectionTimeout(10);三、任務(wù)實(shí)施//設(shè)置會(huì)話心跳時(shí)間options.setKeepAliveInterval(60);//設(shè)置回調(diào)client.setCallback(newMqttCallback(){@OverridepublicvoidconnectionLost(Throwablethrowable){//連接丟失后,一般在這里進(jìn)行重新連接System.out.println("ConnectionLost");//startReconnect();}@OverridepublicvoiddeliveryComplete(IMqttDeliveryTokeniMqttDeliveryToken){//publish后會(huì)執(zhí)行到這里System.out.println("deliveryComplete"+iMqttDeliveryToken.isComplete());}@OverridepublicvoidmessageArrived(Strings,MqttMessagemqttMessage)throwsException{//subscribe后得到的消息會(huì)執(zhí)行到這里面System.out.println("MessageArrived");Messagemsg=newMessage();msg.what=3;//收到消息標(biāo)志位msg.obj=s+""+mqttMessage.toString();handler.sendMessage(msg);//hander回傳}});}catch(Exceptione){e.printStackTrace();}}三、任務(wù)實(shí)施通過初始化函數(shù),完成MQTT的初始化。例如:將MQTT客戶端client實(shí)例化,設(shè)置MQTT連接的參數(shù)options,通過setCallback方法設(shè)置回調(diào)。回調(diào)中最關(guān)鍵的是messageArrived函數(shù)。當(dāng)MQTT客戶端client收到訂閱的消息后,會(huì)將消息的主題、內(nèi)容拼接在一起作為obj,再增加標(biāo)志位what,回傳給UI線程的handler對象,handler處理后可以用于更新UI。//2-Mqtt初始化函數(shù)privatevoidMqtt_connect(){newThread(newRunnable(){@Overridepublicvoidrun(){try{if(!(client.isConnected())){//如果還未連接client.connect(options);Messagemsg=newMessage();msg.what=31;handler.sendMessage(msg);}(2)連接函數(shù)。三、任務(wù)實(shí)施因?yàn)檫B接網(wǎng)絡(luò)耗時(shí),所以需要開啟子線程。MQTT連接函數(shù)是在重連接函數(shù)中被調(diào)用的。如果連接成功,那么回傳給handler的標(biāo)志位what為31;如果連接失敗,那么回傳給handler的標(biāo)志位what為30。UI線程的handler處理后可以用于更新UI。}catch(Exceptione){e.printStackTrace();Messagemsg=newMessage();msg.what=30;handler.sendMessage(msg);}}}).start();}三、任務(wù)實(shí)施(3)重連接函數(shù)。//3-MQTT重連privatevoidstartReconnect(){scheduler=Executors.newSingleThreadScheduledExecutor();scheduler.scheduleAtFixedRate(newRunnable(){@Overridepublicvoidrun(){if(!client.isConnected()){Mqtt_connect();}}},0*1000,10*1000,TimeUnit.MILLISECONDS);}在重連接函數(shù)中,實(shí)現(xiàn)了一個(gè)定時(shí)任務(wù),該任務(wù)會(huì)在一次任務(wù)執(zhí)行完畢的間隔時(shí)間后,才會(huì)執(zhí)行下一次任務(wù)。任務(wù)就是調(diào)用連接函數(shù),實(shí)現(xiàn)客戶端對MQTT服務(wù)器的連接。三、任務(wù)實(shí)施(4)發(fā)布消息函數(shù)。//4-MQTT重連privatevoidpublishmessageplus(Stringtopic,Stringmessage2){if(client==null||!client.isConnected()){return;}MqttMessagemessage=newMqttMessage();message.setPayload(message2.getBytes());try{client.publish(topic,message);}catch(MqttExceptione){e.printStackTrace();}}publishmessageplus函數(shù)會(huì)調(diào)用client對象的publish方法,發(fā)布一條消息到MQTT服務(wù)器。publishmessageplus函數(shù)的第一個(gè)參數(shù)是消息topic(主題),第二個(gè)參數(shù)是消息的payload(載荷)。MQTT服務(wù)器收到消息后,會(huì)轉(zhuǎn)發(fā)消息給所有訂閱了消息topic的MQTT客戶端。三、任務(wù)實(shí)施(5)關(guān)閉連接函數(shù)。//5-MQTT重連publicvoiddisconnect(){try{if(client!=null){if(client.isConnected())client.unsubscribe(mqtt_sub_topic);client.disconnect();client.close();client=null;}}catch(Exceptione){e.printStackTrace();}}在關(guān)閉連接函數(shù)中,分為3步:取消訂閱,斷開連接,關(guān)閉客戶端。三、任務(wù)實(shí)施3.OnCreate方法(1)調(diào)用初始化和重連接函數(shù)。在OnCreate方法中,調(diào)用MQTT初始化和重連接函數(shù),如圖3-20所示。圖3-20調(diào)用MQTT初始化和重連接函數(shù)圖3-21調(diào)用disconnect()函數(shù)跳轉(zhuǎn)到下一頁時(shí),如果MQTT客戶端還在連接的話,需要釋放掉資源,可以在btn21的事件監(jiān)聽中調(diào)用disconnect()函數(shù)實(shí)現(xiàn),如圖3-21所示。三、任務(wù)實(shí)施(2)Handler處理。對象handler是在UI線程創(chuàng)建的,重寫了處理消息的方法:handleMessage。處理時(shí),根據(jù)message對象的what屬性值分別進(jìn)行處理:①如果回傳的標(biāo)志位是3(收到訂閱消息),則在屏幕上Toast消息內(nèi)容(UI刷新);②如果回傳的標(biāo)志位是30(連接失敗),則在屏幕上Toast“連接失敗”(UI刷新);③如果回傳的標(biāo)志位是31(連接成功),則在屏幕上Toast“連接成功”(UI刷新)。代碼如下:handler=newHandler(){@SuppressLint("SetTextI18n")publicvoidhandleMessage(Messagemsg){super.handleMessage(msg);switch(msg.what){case1://開機(jī)校驗(yàn)更新回傳,未用到break;case2://反饋回傳,未用到break;三、任務(wù)實(shí)施case3://MQTT收到消息回傳Toast.makeText(SecondActivity.this,msg.obj.toString(),Toast.LENGTH_SHORT).show();break;case30://連接失敗Toast.makeText(SecondActivity.this,"連接失敗",Toast.LENGTH_LONG).show();break;case31://連接成功Toast.makeText(SecondActivity.this,"連接成功",Toast.LENGTH_LONG).show();break;default:break;}}};三、任務(wù)實(shí)施4.運(yùn)行結(jié)果如圖3-22所示,當(dāng)進(jìn)入page2頁面時(shí),會(huì)顯示連接成功。圖3-22顯示MQTT連接成功將顯示連接成功的界面截圖上傳到課程學(xué)習(xí)平臺(tái)。在SecondActivity.java中進(jìn)行頁面跳轉(zhuǎn)時(shí),不調(diào)用disconnect()函數(shù)。觀察從page2跳轉(zhuǎn)到page3,再跳轉(zhuǎn)回page2后,Toast的內(nèi)容是什么,并分析原因。四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)3完成了物聯(lián)網(wǎng)APP的MQTT相關(guān)配置,就可以在Android工程中使用MQTT相關(guān)的基礎(chǔ)方法了,如執(zhí)行連接、訂閱消息、發(fā)布消息。修改APP名稱,加上學(xué)號(hào)。實(shí)踐練習(xí)謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)物聯(lián)網(wǎng)APP和MQTT.fx客戶端通信一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)5使用MQTT.fx軟件創(chuàng)建一個(gè)MQTT客戶端,讓APP和其進(jìn)行MQTT通信,實(shí)現(xiàn)如下功能:(1)APP發(fā)送,MQTT.fx接收,消息topic為“/手機(jī)號(hào)/my_APP/set”,代表APP發(fā)布的命令;(2)MQTT.fx發(fā)送,APP接收,消息topic為“/手機(jī)號(hào)/my_FX/post”,代表MQTT.fx發(fā)布的消息。APP和MQTT.fx這兩個(gè)客戶端需要通過MQTT服務(wù)器進(jìn)行消息轉(zhuǎn)發(fā)。任務(wù)引入任務(wù)4中APP已經(jīng)連接到MQTT服務(wù)器,MQTT服務(wù)器起到了消息代理的作用。如果APP和另一個(gè)MQTT客戶端之間能進(jìn)行消息傳遞,感受會(huì)更直觀。二、相關(guān)知識(shí)Java中的字符串處理方法在Java中,常用的字符串(String類)處理函數(shù)有indexOf()方法、substring()方法、contains()方法,結(jié)合起來可以用于字符串的解析。indexOf()方法indexOf()方法可以在字符串中查找子字符串出現(xiàn)的位置(即索引值)。如果存在則返回索引值,如果不存在則返回-1。其中,字符串的索引是從0開始的。substring()方法substring()方法用于截取字符串的子字符串。其語法為:publicStringsubstring(intbeginIndex),或publicStringsubstring(intbeginIndex,intendIndex)。參數(shù):beginIndex———起始索引(包括),索引從0開始;endIndex———結(jié)束索引(不包括)。二、相關(guān)知識(shí)contains()方法contains()方法用于判斷字符串中是否包含指定的字符或子字符串。其語法為:publicbooleancontains(CharSequencechars)。參數(shù):chars———要判斷的字符或字符串。返回值:如果包含指定的字符或字符串,則返回true,否則返回false。課堂討論根據(jù)介紹,indexOf()方法是否可以起到contains()方法同樣的功能,即判斷字符串的包含關(guān)系?三、任務(wù)實(shí)施實(shí)施設(shè)備安裝了AndroidStudio開發(fā)環(huán)境和MQTT.fx軟件的計(jì)算機(jī),部署了MQTT服務(wù)器的云服務(wù)器。1.MQTT.fx配置MQTT.fx可通過點(diǎn)擊齒輪圖標(biāo)或從Extras→EditConnectionProfiles進(jìn)入連接配置。如圖3-23所示,在連接配置中,設(shè)置要訪問的MQTT代理服務(wù)器IP地址和端口號(hào),端口號(hào)為1883;設(shè)置獨(dú)一無二的客戶端ID,也可以點(diǎn)擊“Generate”自動(dòng)生成;其他參數(shù)可以默認(rèn),訪問MQTT服務(wù)器的賬號(hào)、密碼可以空著。實(shí)施過程圖3-23MQTT.fx配置三、任務(wù)實(shí)施點(diǎn)擊“Connect”后,在MQTT.fx中創(chuàng)建的MQTT客戶端即可建立與MQTT服務(wù)器的連接。如圖3-24所示,點(diǎn)擊“Publish”選項(xiàng)卡,可以設(shè)置發(fā)布消息的topic,注意這個(gè)topic是APP要收到的消息topic。圖3-24MQTT.fx發(fā)布消息圖3-25MQTT.fx訂閱消息如圖3-25所示,點(diǎn)擊“Subscribe”選項(xiàng)卡,可以設(shè)置訂閱消息的topic,點(diǎn)擊Subscribe即可訂閱成功。注意這個(gè)topic是APP要發(fā)布的消息topic。三、任務(wù)實(shí)施2.APP程序設(shè)計(jì)(1)APP的MQTT消息約定。在APP中,布局如圖3-26所示,約定如下:①點(diǎn)擊image21和image22,發(fā)布消息。topic為“/手機(jī)號(hào)/my_APP/set”,payload分別為{"LedStatus":1}和{"LedStatus":0};②收到訂閱的消息,topic為“/手機(jī)號(hào)/my_FX/post”,提取消息payload的“temperature”字段的值,拼接后顯示在text23處。消息payload格式為{"temperature":16}。發(fā)布和接受的消息都是字符串類型,毫無疑問我們要求消息滿足JSON格式規(guī)范(這是基本要求,必須遵守)。圖3-26image21和image22的布局三、任務(wù)實(shí)施(2)APP發(fā)布MQTT消息。如圖3-27所示,需要在image21和image22的單擊事件監(jiān)聽器中調(diào)用消息發(fā)布函數(shù)。代碼如下:圖3-27image21和image22的單擊事件監(jiān)聽//點(diǎn)擊image21,發(fā)布消息:{"LedStatus":1}binding2.image21.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewview){publishmessageplus(mqtt_pub_topic,"{\"LedStatus\":1}");}});//點(diǎn)擊image22,發(fā)布消息:{"LedStatus":0}binding2.image22.setOnClickListener(newView.OnClickListener(){@OverridepublicvoidonClick(Viewview){publishmessageplus(mqtt_pub_topic,"{\"LedStatus\":0}");}});三、任務(wù)實(shí)施點(diǎn)擊image21,調(diào)用自編的publishmessageplus函數(shù)發(fā)布MQTT消息,payload為{"LedStatus":1};點(diǎn)擊image22,調(diào)用自編的publishmessageplus函數(shù)發(fā)布MQTT消息,payload為{"LedStatus":0}。點(diǎn)擊這兩個(gè)圖像控件,發(fā)布的MQTT消息topic是一樣的。case31://連接成功Toast.makeText(MainActivity.this,"連接成功",Toast.LENGTH_LONG).show();try{//訂閱消息client.subscribe(mqtt_sub_topic,1);}catch(MqttExceptione){e.printStackTrace();}break;(3)APP接收MQTT消息。接收消息需要注意,先訂閱消息,然后才能接收(MQTT服務(wù)器轉(zhuǎn)發(fā)過來的消息)。下面在Handler中完成這兩步。當(dāng)APP的MQTT客戶端client連接MQTT服務(wù)器成功后,調(diào)用subscribe方法訂閱消息。代碼如下:三、任務(wù)實(shí)施接收解析的代碼如下:case3://MQTT收到消息回傳if(msg.obj.toString().contains("temperature")){StringT_val=msg.obj.toString().substring(msg.obj.toString().indexOf("temperature")+13,msg.obj.toString().indexOf("}"));Stringtext_val="溫度:"+T_val+"℃";binding2.text23.setText(text_val);}break;分析當(dāng)APP收到訂閱消息后,是如何提取出溫度值,并在text23文本框中顯示的:已知回傳Handler消息標(biāo)志為3,obj為/1**********/my_FX/post:{"temperature":16};Handler處理時(shí),判斷標(biāo)志是否為3,然后調(diào)用toString()方法將msg.obj轉(zhuǎn)換為字符串,再調(diào)用contains方法判斷是否包含子字符串"temperature";假如以上均滿足,在字符串中進(jìn)行截取操作,起始位置是字符"t"的位置加13,定位到溫度的數(shù)值部分,結(jié)束位置是字符右花括號(hào)(不包括),這樣就提取出了子字符串"16"。最后和前后字符串拼接后,在text23顯示出來"溫度:16℃"。三、任務(wù)實(shí)施3.APP和MQTT.fx通信測試(1)APP發(fā)送MQTT消息到MQTT.fx。如圖3-28所示,當(dāng)在APP上點(diǎn)擊image21后,可在MQTT.fx客戶端的Subscribe選項(xiàng)卡看到消息內(nèi)容。圖3-28MQTT.fx收到image21的消息點(diǎn)擊image22,MQTT.fx客戶端也可以成功收到APP發(fā)送的MQTT消息,如圖3-29所示。圖3-29MQTT.fx收到image22的消息三、任務(wù)實(shí)施(2)MQTT.fx發(fā)送MQTT消息到APP。如圖3-30所示,當(dāng)MQTT.fx發(fā)布消息時(shí),APP可以收到并解析顯示。還可以在真機(jī)上測試,效果是一樣的。圖3-30MQTT.fx發(fā)送MQTT消息到APP四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)5學(xué)習(xí)了兩個(gè)MQTT客戶端之間如何進(jìn)行通信。接下來就可以設(shè)計(jì)網(wǎng)關(guān)程序,實(shí)現(xiàn)網(wǎng)關(guān)和APP之間的MQTT通信,比如獲取網(wǎng)關(guān)上報(bào)的各種傳感數(shù)據(jù),或者控制網(wǎng)關(guān)所接的執(zhí)行器。讓MQTT.fx客戶端發(fā)送MQTT消息,payload格式為{"humidity":43},APP接收后解析展示“humidity”字段的值。實(shí)踐練習(xí)謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)物聯(lián)網(wǎng)APP顯示溫濕度一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)ESP32上報(bào):通過DHT11傳感器監(jiān)測溫濕度值,MQTT消息topic="/手機(jī)號(hào)/my_ESP32/post",MQTT消息payload="{"temperature":16}",或者"{"humidity":43}"。APP收到后,將溫度值解析后顯示在text21中,將濕度值解析后顯示在text22中。任務(wù)6分解為2個(gè)環(huán)節(jié):網(wǎng)關(guān)數(shù)據(jù)上報(bào)、APP設(shè)計(jì)。第一個(gè)環(huán)節(jié)是在Arduino環(huán)境下編寫DHT11相關(guān)庫的檢測函數(shù),再調(diào)用客戶端的publish方法;第二個(gè)環(huán)節(jié)是將任務(wù)5的MQTT.fx客戶端ID換成ESP32客戶端ID,解析后更新UI控件,從text23改為text21和text22。任務(wù)引入任務(wù)5讓MQTT.fx客戶端發(fā)送包含虛擬傳感器值的MQTT消息,由APP訂閱、接收、解析并展示。本任務(wù)讓ESP32網(wǎng)關(guān)連接真實(shí)的傳感器,檢測溫濕度并上報(bào),由APP訂閱、接收、解析并展示,構(gòu)建一個(gè)溫濕度的遠(yuǎn)程監(jiān)控系統(tǒng)。二、相關(guān)知識(shí)DHT11傳感器簡介DHT11傳感器是一款含有已校準(zhǔn)數(shù)字信號(hào)輸出的溫濕度傳感器,應(yīng)用數(shù)字模塊采集技術(shù)和溫濕度傳感技術(shù),確保產(chǎn)品具有極高的可靠性和工作穩(wěn)定性。傳感器包括一個(gè)電阻式感濕元件和一個(gè)NTC測溫元件,并與一個(gè)高性能8位單片機(jī)相連。DHT11采用單線制串行接口,使系統(tǒng)集成變得簡易快捷,節(jié)約硬件資源。產(chǎn)品為4針單排引腳封裝,連接方便。課堂討論你還知道有哪些單總線的傳感器?二、相關(guān)知識(shí)DHT11傳感器應(yīng)用電路VCC供電電壓的范圍為3~5.5V,GND接地。DATA為單串行數(shù)據(jù)總線,可和單片機(jī)的數(shù)據(jù)引腳相連,如圖3-31所示。注意:數(shù)據(jù)引腳需要完成輸入和輸出雙向傳輸,故引腳的工作模式在初始化時(shí)不必設(shè)置,而是在檢測時(shí)按照時(shí)序配置引腳的工作模式。圖3-31DHT11傳感器應(yīng)用電路二、相關(guān)知識(shí)DFRobot_DHT11庫用戶通過外設(shè)庫的封裝,可以較為方便地使用相關(guān)外設(shè),而不需要關(guān)心復(fù)雜的配置和時(shí)序知識(shí)。用戶可在Arduino開發(fā)環(huán)境中調(diào)用DFRobot_DHT11庫,使用DHT11傳感器。項(xiàng)目1已經(jīng)將DFRobot_DHT11外設(shè)庫下載到Arduino安裝目錄的libraries文件夾中,在Arduino工程中,用戶通過以下語句即可調(diào)用:#include"DFRobot_DHT11.h"其他關(guān)鍵語句如下:DFRobot_DHT11DHT;//創(chuàng)建溫濕度傳感器對象DHTDHT.read(DHT11_PIN);//DHT對象調(diào)用read方法,完成一次溫濕度檢測DHT檢測溫濕度后,溫度值和濕度值會(huì)分別賦值給DHT對象的temperature屬性和humidity屬性。三、任務(wù)實(shí)施實(shí)施設(shè)備ESP32網(wǎng)關(guān)和DHT11溫濕度傳感器各一個(gè),杜邦線若干,安裝了Arduino開發(fā)環(huán)境和AndroidStudio開發(fā)環(huán)境的計(jì)算機(jī),部署了MQTT服務(wù)器的云服務(wù)器。1.網(wǎng)關(guān)與傳感器硬件連接DHT11_DAT———ESP32_IO26DHT11_GND———ESP32_GNDDHT11_VCC———ESP32_VCCDHT11的單數(shù)據(jù)總線接ESP32的Pin26。實(shí)施過程三、任務(wù)實(shí)施2.網(wǎng)關(guān)程序設(shè)計(jì)(1)頭文件、宏、變量、對象定義。#include<WiFi.h>#include<PubSubClient.h>#include<ArduinoJson.h>//需要加載ArduinoJson和DFRobot_DHT11庫,否則報(bào)錯(cuò)#include"DFRobot_DHT11.h"#defineDHT11_PIN26/*配置WIFI名和密碼*/constchar*WIFI_SSID/="YYY_11_101";constchar*WIFI_PASSWORD="lxy413026";/*配置域名和端口號(hào)*/constchar*mqtt_server="69";constuint16_tPORT=1883;constchar*mqtt_id=ESP";constchar*mqtt_username="";constchar*mqtt_password="";/*需要操作的產(chǎn)品標(biāo)識(shí)符(溫度、濕度)*/StringTempIdentifier="temperature";StringHumiIdentifier="humidity";/*需要上報(bào)和訂閱的TOPIC*/constchar*pubTopic="my_ESP32/post";//******發(fā)布WiFiClientespClient;PubSubClientclient(espClient);//創(chuàng)建了MQTT客戶端,即ESP32硬件DFRobot_DHT11DHT;三、任務(wù)實(shí)施程序中:①調(diào)用了WiFi庫、PubSubClient庫(用于創(chuàng)建MQTT客戶端)、ArduinoJson庫(用于JSON解析)、DFRobot_DHT11(用于DHT11溫濕度傳感器);②定義了DHT11的數(shù)據(jù)引腳、配置了WiFi通信時(shí)的賬號(hào)密碼、MQTT服務(wù)器的IP地址和端口號(hào)、MQTT客戶端ID、客戶端訪問服務(wù)器時(shí)的用戶名和密碼;③定義了JSON對象(上報(bào)的消息載荷)里的溫度和濕度字段、要發(fā)布的消息topic;④創(chuàng)建了WiFi客戶端,進(jìn)一步創(chuàng)建了MQTT客戶端對象client,并創(chuàng)建了溫濕度傳感器對象DHT。三、任務(wù)實(shí)施voidsetup(){Serial.begin(115200);connectWiFi();client.setServer(mqtt_server,PORT);//沒有提供用戶名和密碼,因?yàn)镋MQX服務(wù)器允許公開訪問,如果設(shè)置的話是需要提供的/*設(shè)置回調(diào)函數(shù),當(dāng)收到訂閱信息時(shí)會(huì)執(zhí)行回調(diào)函數(shù)*/client.setCallback(callback);/*連接到MQTT服務(wù)器*/reconnect();}(2)初始化函數(shù)。初始化函數(shù)中:設(shè)置串口0的波特率為115200,對應(yīng)的電腦串口調(diào)試助手波特率要一致;進(jìn)行WiFi連接;設(shè)置MQTT客戶端要訪問的MQTT服務(wù)器;設(shè)置MQTT客戶端收到消息后的回調(diào)處理函數(shù),并連接到MQTT服務(wù)器。三、任務(wù)實(shí)施voidreconnect(){while(!client.connected()){Serial.print("AttemptingMQTTconnection...");if(client.connect(mqtt_id,mqtt_username,mqtt_password)){Serial.println("connected");}else{Serial.print("failed,rc=");Serial.print(client.state());Serial.println("tryagainin5seconds");delay(5000);}}}(3)reconnect函數(shù)。在reconnect函數(shù)中,client對象會(huì)調(diào)用connected方法判斷是否連接到MQTT服務(wù)器;如果未連接,會(huì)嘗試調(diào)用connect方法進(jìn)行連接;如果嘗試連接失敗,間隔一段時(shí)間后會(huì)再次調(diào)用connect方法進(jìn)行連接。循環(huán)是通過While語句實(shí)現(xiàn)的。三、任務(wù)實(shí)施uint8_ttempTime=0;voidloop(){if(!client.connected()){reconnect();}/*兩分鐘上報(bào)兩次溫濕度信息*/if(tempTime>240){tempTime=0;DHT.read(DHT11_PIN);Serial.print("DHT.temperature=");Serial.println(DHT.temperature);Serial.print("DHT.humidity=");Serial.println(DHT.humidity);client.publish(pubTopic,("{\""+TempIdentifier+"\":"+DHT.temperature+"}").c_str());}else{tempTime++;delay(500);}client.loop();}(4)loop函數(shù)。loop函數(shù)中,MQTT客戶端每2分鐘上報(bào)一次消息,消息的topic="/手機(jī)號(hào)/my_ESP32/post"。假如采集到的溫度值是16℃,消息載荷="{"temperature":16}"。程序中,DHT對象通過read方法檢測溫濕度,溫度值和濕度值會(huì)分別賦值給DHT對象的temperature屬性和humidity屬性。三、任務(wù)實(shí)施為什么是每隔2分鐘上報(bào)一次MQTT消息?如果想修改間隔時(shí)間為3分鐘,有哪些辦法?消息中的“\”是什么意思,有什么作用?課堂討論3.APP設(shè)計(jì)(1)消息topic。如圖3-32所示,APP是作為接收消息的MQTT客戶端使用的,只要修改一下訂閱的消息topic就可以了,即將"/手機(jī)號(hào)/my_FX/post"修改為"/手機(jī)號(hào)/my_ESP32/post",至于發(fā)布和訂閱消息的內(nèi)容,都保持不變。圖3-32修改訂閱的消息topic三、任務(wù)實(shí)施(2)消息payload解析。APP的MQTT客戶端收到消息后,通過Handler回傳到UI線程處理,原來是解析后展示在tet23,現(xiàn)在修改為解析溫度展示在text21文本框中。代碼如下:case3://MQTT收到消息回傳if(msg.obj.toString().contains("temperature")){StringT_val=msg.obj.toString().substring(msg.obj.toString().indexOf("temperature")+13,msg.obj.toString().indexOf("}"));Stringtext_val=T_val+"℃";binding2.text21.setText(text_val);}//Toast.makeText(SecondActivity.this,msg.obj.toString(),Toast.LENGTH_SHORT).show();break;三、任務(wù)實(shí)施4.結(jié)果展示上傳程序,打開Arduino開發(fā)環(huán)境的串口監(jiān)視器,會(huì)顯示連接MQTT服務(wù)器成功。然后觀察溫濕度檢測結(jié)果,如圖3-33所示。對應(yīng)的,如圖3-34所示,在虛擬手機(jī)上可以看到溫度值,和串口打印的溫度值是一樣的。圖3-33串口0打印的溫濕度值圖3-34APP的溫度顯示三、任務(wù)實(shí)施5.濕度上報(bào)顯示在溫度值上報(bào)顯示的基礎(chǔ)上,完成濕度值的上報(bào)顯示。APP和網(wǎng)關(guān)程序都需要簡單修改一下。(1)APP解析部分代碼完善。case3://MQTT收到消息回傳if(msg.obj.toString().contains("temperature")){StringT_val=msg.obj.toString().substring(msg.obj.toString().indexOf("temperature")+13,msg.obj.toString().indexOf("}"));Stringtext_val=T_val+"℃";binding2.text21.setText(text_val);}if(msg.obj.toString().contains("humidity")){StringH_val=msg.obj.toString().substring(msg.obj.toString().indexOf("humidity")+10,msg.obj.toString().indexOf("}"));Stringtext_val=H_val+"%";binding2.text22.setText(text_val);}//Toast.makeText(SecondActivity.this,msg.obj.toString(),Toast.LENGTH_SHORT).show();break;APP的MQTT客戶端收到消息后,通過Handler回傳到UI線程處理,對濕度值的解析處理和對溫度值的解析處理思路是一樣的,把濕度值更新到text22中即可。三、任務(wù)實(shí)施(2)網(wǎng)關(guān)程序部分代碼完善。每2分鐘上報(bào)一次消息,在上報(bào)溫度消息語句后面,再調(diào)用client的publish方法發(fā)布(上報(bào))一條濕度消息。消息的topic="/手機(jī)號(hào)/my_ESP32/post"。假如采集到的濕度值是43%,消息載荷="{"humidity":43}"。uint8_ttempTime=0;voidloop(){if(!client.connected()){reconnect();}/*兩分鐘上報(bào)兩次溫濕度信息*/if(tempTime>240){tempTime=0;DHT.read(DHT11_PIN);Serial.print("DHT.temperature=");Serial.println(DHT.temperature);Serial.print("DHT.humidity=");Serial.println(DHT.humidity);client.publish(pubTopic,("{\""+TempIdentifier+"\":"+DHT.temperature+"}").c_str());client.publish(pubTopic,("{\""+HumiIdentifier+"\":"+DHT.humidity+"}").c_str());}else{tempTime++;delay(500);}client.loop();}三、任務(wù)實(shí)施(3)結(jié)果。重新運(yùn)行App和網(wǎng)關(guān)程序。如圖3-35所示,APP顯示的溫度、濕度值和網(wǎng)關(guān)通過串口打印的值是一致的,工作正常。圖3-35溫濕度監(jiān)測工作情況四、任務(wù)小結(jié)與練習(xí)任務(wù)小結(jié)任務(wù)6實(shí)現(xiàn)了溫濕度的檢測、數(shù)據(jù)的傳輸、數(shù)據(jù)解析以及數(shù)據(jù)展示,構(gòu)成了一個(gè)初步的物聯(lián)網(wǎng)系統(tǒng)。那么能不能進(jìn)一步地通過APP遠(yuǎn)程控制硬件設(shè)備呢?留待下一個(gè)任務(wù)解決。在網(wǎng)關(guān)的loop函數(shù)中,有以下代碼實(shí)現(xiàn)了MQTT斷開連接時(shí)嘗試重連的功能:實(shí)踐練習(xí)if(!client.connected()){reconnect();}但如果WiFi斷開了,貌似沒有重連的機(jī)制,有什么解決辦法嗎?謝謝聆聽2相關(guān)知識(shí)34任務(wù)小結(jié)與練習(xí)1任務(wù)實(shí)施任務(wù)引入與目標(biāo)物聯(lián)網(wǎng)APP遠(yuǎn)程控制LED一、任務(wù)引入與目標(biāo)任務(wù)目標(biāo)任務(wù)7將實(shí)現(xiàn):APP發(fā)送MQTT消息:topic="/手機(jī)號(hào)/my_APP/set",payload="{"LedStatus":1}"或"{"LedStatus":0}"。ESP32網(wǎng)關(guān)收到MQTT消息后,根據(jù)解析的命令值控制所接LED的亮與滅。APP程序不需要修改,網(wǎng)關(guān)程序設(shè)計(jì)中需要實(shí)現(xiàn)MQTT消息的接收、解析及控制。任務(wù)引入任務(wù)6實(shí)現(xiàn)了溫濕度的展示,數(shù)據(jù)流向?yàn)橛布紸PP。這個(gè)數(shù)據(jù)能不能實(shí)現(xiàn)反方向傳輸呢?比如能否通過APP遠(yuǎn)程控制硬件設(shè)備呢?二、相關(guān)知識(shí)Arduino開發(fā)環(huán)境中的JavaScript對象(JSONObject)JSONObject可以包含多個(gè)成員,每個(gè)成員以name:value對(鍵值對,鍵又稱為字段)呈現(xiàn),如{"id":1,"temp":22}。格式要求:JSONObject用花括號(hào)表示;成員之間用逗號(hào)分隔;鍵(字段)和值之間用冒號(hào)分隔;鍵用雙引號(hào)括起來,即鍵是一個(gè)字符串。獲取JSON對象成員的值用戶可以通過兩種方式獲取JSON對象成員的值:(1)JSON對象名.id;(2)JSON對象名["id"];其中,id是JSON對象的一個(gè)鍵。二、相關(guān)知識(shí)課堂討論JSONObject可以轉(zhuǎn)換為一個(gè)字符串,或者通過字符串轉(zhuǎn)換得到。其中的鍵也是一個(gè)字符串,需要用雙引號(hào)括起來。在進(jìn)行程序設(shè)計(jì)時(shí),鍵的雙引號(hào)該如何處理,才不會(huì)造成誤解呢?三、任務(wù)實(shí)施實(shí)施設(shè)備ESP32網(wǎng)關(guān)和DHT11溫濕度傳感器各一個(gè),杜邦線若干,安裝了Arduino開發(fā)環(huán)境和AndroidStudio開發(fā)環(huán)境的計(jì)算機(jī),部署了MQTT服務(wù)器的云服務(wù)器。1.網(wǎng)關(guān)和LED硬件連接在任務(wù)6的基礎(chǔ)上,連接LED燈:DHT11_DAT———ESP32_IO25DHT11_GND———ESP32_GNDDHT11_VCC———ESP32_VCC

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲(chǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論