OpenHarmony上利用Paho MQTT連接云平臺(tái)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1. 引言
近年來(lái),物聯(lián)網(wǎng)(Internet of Things, IoT)技術(shù)的快速發(fā)展改變了各行各業(yè),讓設(shè)備之間實(shí)現(xiàn)了無(wú)縫連接和智能互動(dòng)。從傳感器到智能家電,物聯(lián)網(wǎng)設(shè)備需要與云服務(wù)進(jìn)行高效通信,以傳輸數(shù)據(jù)、接收指令并實(shí)現(xiàn)遠(yuǎn)程管理。這一轉(zhuǎn)變促使了專(zhuān)門(mén)針對(duì)物聯(lián)網(wǎng)部署需求開(kāi)發(fā)的專(zhuān)業(yè)物聯(lián)網(wǎng)平臺(tái)和通信協(xié)議,如CoAP (Constrained Application Protocol)、AMQP (Advanced Message Queuing Protocol)、DDS (Data Distribution Service)、WebSocket等。除上述協(xié)議外,MQTT (Message Queuing Telemetry Transport)因其適應(yīng)資源受限設(shè)備、簡(jiǎn)單易用的設(shè)計(jì)、強(qiáng)大的消息傳輸能力和廣泛的應(yīng)用支持而成為物聯(lián)網(wǎng)通信的常用選擇。它不僅滿足了各種物聯(lián)網(wǎng)設(shè)備和應(yīng)用程序之間實(shí)時(shí)通信的需求,還提供了靈活的部署和擴(kuò)展選項(xiàng),適應(yīng)了不同規(guī)模和復(fù)雜度的物聯(lián)網(wǎng)解決方案[1]。
Paho MQTT是一個(gè)開(kāi)源的MQTT庫(kù),由Eclipse Paho項(xiàng)目提供支持。它提供了多種編程語(yǔ)言的實(shí)現(xiàn),包括C、C++、Java、Python等,旨在幫助開(kāi)發(fā)者輕松地在各種設(shè)備和平臺(tái)上實(shí)現(xiàn)MQTT通信協(xié)議。本文專(zhuān)注于將Paho MQTT客戶端庫(kù)移植到OpenHarmony項(xiàng)目中的LiteOS內(nèi)核處理器上,如海思Hi3861芯片,實(shí)現(xiàn)與云平臺(tái)的連接。在OpenHarmony項(xiàng)目的LiteOS內(nèi)核處理器上集成MQTT不僅增強(qiáng)了設(shè)備與云端高效通信的能力,還為創(chuàng)建互聯(lián)物聯(lián)網(wǎng)生態(tài)系統(tǒng)的整體目標(biāo)作出了貢獻(xiàn)。
2. MQTT協(xié)議
MQTT協(xié)議是一種輕量級(jí)的、基于發(fā)布/訂閱模式的消息傳輸協(xié)議,最早由IBM開(kāi)發(fā)于1999年,用于傳感器和施工機(jī)器之間的通信。隨后,協(xié)議被開(kāi)放,成為OASIS (Organization for the Advancement of Structured Information Standards,結(jié)構(gòu)化信息標(biāo)準(zhǔn)推動(dòng)組織)標(biāo)準(zhǔn),并在眾多物聯(lián)網(wǎng)應(yīng)用中得到廣泛應(yīng)用。MQTT協(xié)議在物聯(lián)網(wǎng)領(lǐng)域起初設(shè)計(jì)用于傳感器網(wǎng)絡(luò)和設(shè)備間的低帶寬、高效率通信。其輕量級(jí)和簡(jiǎn)單的發(fā)布/訂閱模式使得設(shè)備能夠節(jié)省能源和帶寬,適用于智能家居、工業(yè)自動(dòng)化和智能城市等多種場(chǎng)景。
2.1. MQTT的架構(gòu)
MQTT的客戶端是消息發(fā)布者或者消息訂閱者,它們與MQTT Broker進(jìn)行通信來(lái)實(shí)現(xiàn)數(shù)據(jù)的傳輸和接收[2]??蛻舳丝梢允歉鞣N設(shè)備或應(yīng)用程序,包括傳感器、嵌入式設(shè)備、移動(dòng)應(yīng)用等。MQTT的客戶端和Broker之間的關(guān)系如圖1所示。
Figure 1. MQTT network architecture
客戶端在MQTT中的主要功能包括:
發(fā)布消息:客戶端可以向Broker發(fā)布(或發(fā)送)消息,消息可以是任何格式的數(shù)據(jù),通常包含有用的傳感器數(shù)據(jù)、控制命令等。
訂閱主題:客戶端可以向Broker訂閱(或接收)特定的主題(Topic),通過(guò)主題來(lái)過(guò)濾和接收感興趣的消息。主題可以使用通配符來(lái)實(shí)現(xiàn)更靈活的訂閱規(guī)則。
接收消息:客戶端通過(guò)訂閱主題,可以接收來(lái)自Broker轉(zhuǎn)發(fā)的消息,并進(jìn)行相應(yīng)的處理和分析。
客戶端可以選擇不同的消息服務(wù)質(zhì)量(QoS)級(jí)別來(lái)控制消息傳遞的可靠性和效率,包括至多傳遞一次(QoS 0)、至少傳遞一次(QoS 1)、恰好傳遞一次(QoS 2)。
MQTT的Broker是中介服務(wù)器,負(fù)責(zé)管理客戶端之間的消息傳遞。Broker接收來(lái)自發(fā)布者(發(fā)布消息的客戶端)的消息,并確保將這些消息按照訂閱者(訂閱消息的客戶端)的需求正確分發(fā)。Broker在MQTT協(xié)議中的關(guān)鍵作用包括:
消息路由和分發(fā):根據(jù)訂閱關(guān)系,將發(fā)布者發(fā)送的消息分發(fā)給所有訂閱了相關(guān)主題的客戶端。
連接管理:管理客戶端的連接和狀態(tài),確保每個(gè)連接的可靠性和安全性。
QoS管理:根據(jù)客戶端設(shè)置的QoS級(jí)別,確保消息的按時(shí)傳遞和確認(rèn)。
2.2. MQTT的報(bào)文
為了讓客戶端和Broker之間進(jìn)行通信,MQTT協(xié)議定義了不同類(lèi)型的消息(稱為報(bào)文),如CONNECT、CONNACK、PUBLISH、PUBACK、SUBSCRIBE、SUBACK、UNSUBSCRIBE等。報(bào)文包含固定報(bào)頭、可變報(bào)頭(部分報(bào)文包含)、負(fù)載(部分報(bào)文包含)。固定報(bào)頭定義了報(bào)文類(lèi)型、控制標(biāo)志和后續(xù)數(shù)據(jù)長(zhǎng)度,可變頭部則依據(jù)報(bào)文類(lèi)型規(guī)定了各自的詳細(xì)信息,如后續(xù)消息內(nèi)容、QoS級(jí)別等。負(fù)載用于攜帶實(shí)際數(shù)據(jù)內(nèi)容。這種設(shè)計(jì)使得MQTT能夠在各種網(wǎng)絡(luò)條件下高效傳輸消息,并支持靈活的通信需求和服務(wù)質(zhì)量保證。
3. Paho MQTT庫(kù)
3.1. 簡(jiǎn)介
Paho項(xiàng)目致力于提供開(kāi)源的、可擴(kuò)展的消息傳遞協(xié)議實(shí)現(xiàn),支持M2M (Machine-to-Machine)和物聯(lián)網(wǎng)的各種應(yīng)用。它特別關(guān)注設(shè)備連接中的物理限制和成本問(wèn)題。Paho MQTT C是Paho項(xiàng)目的一部分,是專(zhuān)門(mén)為C語(yǔ)言開(kāi)發(fā)的MQTT客戶端庫(kù)。Paho MQTT C庫(kù)旨在提供一個(gè)可靠、高效的實(shí)現(xiàn),使開(kāi)發(fā)者能夠輕松地在C語(yǔ)言環(huán)境中實(shí)現(xiàn)MQTT的發(fā)布和訂閱功能[3]。
3.2. 庫(kù)文件內(nèi)容
應(yīng)用于嵌入式的Paho MQTT C庫(kù)文件中,能夠被移植的代碼位于MQTTPacket、MQTTClient-C、MQTTClient文件夾。
MQTTPacket文件夾包含了MQTT協(xié)議報(bào)文的解析和封裝功能。這些文件提供了處理MQTT協(xié)議中不同報(bào)文(如CONNECT、PUBLISH、SUBSCRIBE等)的代碼實(shí)現(xiàn)。它們負(fù)責(zé)將MQTT消息編碼為字節(jié)流(序列化),或者將接收到的字節(jié)流解析為可操作的消息(反序列化)。
MQTTClient-C文件夾包含了MQTT客戶端的C語(yǔ)言實(shí)現(xiàn)的核心部分。這些文件實(shí)現(xiàn)了MQTT客戶端的連接、發(fā)布、訂閱、斷開(kāi)連接等功能。它們是構(gòu)建在MQTTPacket基礎(chǔ)之上的更高級(jí)別的抽象,提供了一個(gè)易于使用和集成的MQTT客戶端接口。在移植過(guò)程中,我們需要對(duì)這個(gè)文件夾中的一些網(wǎng)絡(luò)接口進(jìn)行修改,才能利用其中的函數(shù)正常地與服務(wù)器通信。
MQTTClient是一個(gè)最初為mbed編寫(xiě)的C++庫(kù),現(xiàn)已移植到其他平臺(tái)上使用。該庫(kù)基于并且需要MQTTPacket。對(duì)于僅使用C語(yǔ)言的系統(tǒng)來(lái)說(shuō),可以忽略此文件夾。
表1說(shuō)明了MQTTPacket文件夾中與客戶端有關(guān)的文件的作用。
Table 1. The role of files in the MQTTPacket folder
由于這些文件只負(fù)責(zé)處理報(bào)文格式,不涉及與單片機(jī)有關(guān)的通信接口,因此在移植過(guò)程中直接復(fù)制到工程中即可,不需要修改。
MQTTClient-C文件夾中使用的主要是MQTTClient.c文件。該文件是MQTT客戶端庫(kù)的核心實(shí)現(xiàn),負(fù)責(zé)實(shí)現(xiàn)MQTT協(xié)議的各種功能,提供了連接Broker、發(fā)布和訂閱消息等高級(jí)抽象接口。它通過(guò)調(diào)用MQTTPacket文件夾中的程序來(lái)封裝報(bào)文,并通過(guò)調(diào)用相關(guān)的網(wǎng)絡(luò)接口將這些報(bào)文發(fā)送出去。在該文件中,初始化函數(shù)MQTTClientInit()需要調(diào)用Network結(jié)構(gòu)體來(lái)傳入有關(guān)Socket網(wǎng)絡(luò)接口。該結(jié)構(gòu)體涉及到Socket接口編號(hào)、接收函數(shù)、發(fā)送函數(shù)。因此需要編寫(xiě)程序來(lái)初始化Socket接口,并編寫(xiě)接收和發(fā)送函數(shù),以供MQTTClient.c文件中的函數(shù)調(diào)用。還需要編寫(xiě)供超時(shí)判斷用的計(jì)時(shí)函數(shù)。
官方的MQTTClient-C文件夾中已經(jīng)打包好了一些例程,它們適配于FreeRTOS、Linux、CC3200。移植時(shí)需要依據(jù)這些例程編寫(xiě)一個(gè)程序文件(此處名稱為Hi3861_PahoMQTT.c),為MQTTClient.c文件中的函數(shù)配置好網(wǎng)絡(luò)接口和計(jì)時(shí)函數(shù)。網(wǎng)絡(luò)接口利用Socket通過(guò)TCP的方式連接到服務(wù)器并進(jìn)行通信,計(jì)時(shí)函數(shù)用于通信超時(shí)判斷。要編寫(xiě)的文件中的程序內(nèi)容如表2所示。
圖2通過(guò)發(fā)布消息的流程來(lái)說(shuō)明在Hi3861_PahoMQTT.c文件中增加的程序的作用。
Table 2. Programs that need to be written during migration
|
Figure 2. The process of publishing messages using the paho.mqtt.c library
圖2. 利用paho.mqtt.c庫(kù)發(fā)布消息的流程
從圖2中可以看到,為了移植嵌入式的Paho MQTT C庫(kù)而新增的幾個(gè)函數(shù)的主要作用是初始化Socket接口、設(shè)置利用Socket進(jìn)行接收和發(fā)送數(shù)據(jù)的函數(shù),然后利用Socket連接服務(wù)器。配置完成后,設(shè)備后續(xù)與MQTT Broker進(jìn)行連接認(rèn)證、發(fā)布消息都依靠的是MQTTClient.c文件中的相關(guān)函數(shù)。這些函數(shù)通過(guò)調(diào)用MQTTPacket文件夾中的函數(shù)來(lái)進(jìn)行報(bào)文的封裝或解析,利用與Socket相關(guān)的函數(shù)進(jìn)行數(shù)據(jù)的接收和發(fā)送。
4. 在Hi3861上移植Paho MQTT
Hi3861是海思推出的一款支持WiFi功能的處理器,其內(nèi)核采用OpenHarmony架構(gòu)下的LiteOS操作系統(tǒng)[4]。在官方提供的工程文件中,已經(jīng)實(shí)現(xiàn)了在LiteOS系統(tǒng)下的WiFi連接接口和用于實(shí)現(xiàn)TCP/IP協(xié)議棧的LwIP (Light weight IP)庫(kù)。通過(guò)調(diào)用這些接口,Hi3861可以連接到WiFi熱點(diǎn)上面,獲取到IP地址,并創(chuàng)建Socket套接字[5]。移植前需要將Paho MQTT C庫(kù)相關(guān)文件復(fù)制到工程中,并設(shè)置好BUILD.gn項(xiàng)目構(gòu)建文件。
在LiteOS操作系統(tǒng)中,setsockopt()函數(shù)用于配置套接字的選項(xiàng),如協(xié)議級(jí)別、接收發(fā)送的超時(shí)時(shí)間、保活機(jī)制等,recv()用于從Socket接收數(shù)據(jù),send()用于向Socket發(fā)送數(shù)據(jù)。因此,在第3.3節(jié)提到的NetworkRead()函數(shù)中需要先通過(guò)setsockopt()設(shè)置接收超時(shí)時(shí)間,然后調(diào)用recv()函數(shù)進(jìn)行數(shù)據(jù)的接收;在NetworkWrite()函數(shù)中需要先通過(guò)setsockopt()設(shè)置發(fā)送超時(shí)時(shí)間,然后調(diào)用send()函數(shù)進(jìn)行數(shù)據(jù)的發(fā)送。LiteOS中的socket()函數(shù)用來(lái)創(chuàng)建一個(gè)新的套接字(Socket),connect()函數(shù)用于在客戶端套接字上建立與遠(yuǎn)程服務(wù)器的連接。因此這兩個(gè)函數(shù)需要在NetworkConnect()函數(shù)中對(duì)這兩個(gè)函數(shù)進(jìn)行調(diào)用,從而連接到云平臺(tái)的服務(wù)器上。
另外還需要移植用于超時(shí)判斷的定時(shí)器相關(guān)函數(shù),方法主要是通過(guò)內(nèi)核Tick計(jì)數(shù)獲取函數(shù)osKernelGetTickCount()和系統(tǒng)定時(shí)器計(jì)數(shù)獲取函數(shù)osKernelGetSysTimerCount(),配合計(jì)數(shù)頻率來(lái)計(jì)算秒數(shù)和微秒數(shù),這涉及到對(duì)MQTTClient.c中的TimerIsExpired()、TimerCountdownMS()、TimerCountdown()、TimerLeftMS()這幾個(gè)函數(shù)的重定義。
配置好MQTTClient.c中的函數(shù)接口后,即可調(diào)用MQTTClient.c中的相關(guān)函數(shù)進(jìn)行MQTT的認(rèn)證、訂閱、取消訂閱、發(fā)布、接收相關(guān)操作了。
5. 實(shí)驗(yàn)部署
本文采用華清遠(yuǎn)見(jiàn)研發(fā)的FS-Hi3861開(kāi)發(fā)板進(jìn)行Hi3861工程的部署,使用華為云平臺(tái)的設(shè)備接入IoTDA資源作為MQTT服務(wù)器。
首先需要在華為云的設(shè)備接入IoTDA資源中創(chuàng)建產(chǎn)品及相關(guān)屬性、命令。屬性為設(shè)備上報(bào)的數(shù)據(jù),命令為向設(shè)備下發(fā)的數(shù)據(jù),這兩種數(shù)據(jù)的話題和格式是不一樣的。然后注冊(cè)一個(gè)設(shè)備,獲取到設(shè)備的鑒權(quán)信息,包括客戶端ID、用戶名、密碼。
設(shè)備需要利用MQTTClient.c中的MQTTConnect()函數(shù)包裝好鑒權(quán)信息,與服務(wù)器進(jìn)行認(rèn)證。認(rèn)證通過(guò)后,在華為云中會(huì)顯示設(shè)備處于在線狀態(tài)。然后,設(shè)備可以利用MQTTPublish()函數(shù)按照華為云規(guī)定的格式向指定的話題發(fā)布屬性數(shù)據(jù)。設(shè)備還可以利用MQTTSubscribe()函數(shù)訂閱指定的話題,并通過(guò)MQTTRun()函數(shù)接收云平臺(tái)下發(fā)的數(shù)據(jù)。
6. 未來(lái)工作
本文以Hi3861為例,介紹了在OpenHarmony項(xiàng)目的LiteOS內(nèi)核上面通過(guò)移植Paho MQTT連接MQTT云平臺(tái)的方法。由于云平臺(tái)通常使用JSON格式進(jìn)行數(shù)據(jù)傳遞,因此在未來(lái)的項(xiàng)目中,將通過(guò)移植cJSON庫(kù)的方式進(jìn)行數(shù)據(jù)的序列化和反序列化,從而更加方便地傳輸傳感器數(shù)據(jù)并解析相關(guān)指令。另外,為了便于傳感器網(wǎng)絡(luò)的建立,未來(lái)的項(xiàng)目將探討利用Hi3861進(jìn)行Mesh組網(wǎng),從而擴(kuò)展傳感范圍的方式。為了適應(yīng)低功耗需求,未來(lái)的項(xiàng)目也將探討低功耗WiFi模式下MQTT的應(yīng)用。