OpenHarmony 實戰(zhàn)開發(fā)之MQTT協(xié)議解析

相信MQTT這個名稱大家都不陌生,物聯(lián)網(wǎng)的開發(fā)必然會遇到MQTT相關(guān)知識的應(yīng)用。那么什么是MQTT?它有什么特點?它能解決什么問題?它是如何工作的?OpenAtom OpenHarmony(以下簡稱“OpenHarmony”)的物聯(lián)網(wǎng)開發(fā)者要如何使用及驗證MQTT功能?接下來的內(nèi)容將一一為你解答。下圖為MQTT通信模型。

什么是MQTT

MQTT(Message Queuing Telemetry Transport消息隊列遙測傳輸)是一種物聯(lián)網(wǎng)協(xié)議,是一種客戶端與服務(wù)端架構(gòu)的發(fā)布/訂閱模式的消息傳輸協(xié)議,旨在為低帶寬和不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中的物聯(lián)網(wǎng)設(shè)備提供可靠的網(wǎng)絡(luò)服務(wù)。MQTT是專門針對物聯(lián)網(wǎng)開發(fā)的輕量級傳輸協(xié)議。MQTT協(xié)議針對低帶寬網(wǎng)絡(luò),低計算能力的設(shè)備,做了特殊的優(yōu)化,使得其能適應(yīng)各種物聯(lián)網(wǎng)應(yīng)用場景。目前它已廣泛應(yīng)用于車聯(lián)網(wǎng)、智能家居、即時聊天應(yīng)用和工業(yè)互聯(lián)網(wǎng)等領(lǐng)域。

MQTT的基本原理

在MQTT通訊中,有兩個最為重要的角色。它們分別是服務(wù)端和客戶端。

MQTT服務(wù)端

MQTT服務(wù)端通常是一臺服務(wù)器。它是MQTT信息傳輸?shù)臉屑~,負責(zé)將MQTT客戶端發(fā)送來的信息傳遞給MQTT客戶端。MQTT服務(wù)端還負責(zé)管理MQTT客戶端。確??蛻舳酥g的通訊順暢,保證MQTT消息得以正確接收和準確投遞。

MQTT客戶端

MQTT客戶端可以向服務(wù)端發(fā)布信息,也可以從服務(wù)端收取信息。我們把客戶端發(fā)送信息的行為稱為“發(fā)布”信息。而客戶端要想從服務(wù)端收取信息,則首先要向服務(wù)端“訂閱”信息。“訂閱”信息這一操作很像我們在視頻網(wǎng)站訂閱某一部電視劇。當這部電視劇上新后,視頻網(wǎng)站會向訂閱了該劇的用戶發(fā)送信息,告訴他們有新劇上線了。

MQTT主題

剛剛我們在講解MQTT客戶端訂閱信息時,使用了用戶在視頻網(wǎng)站訂閱電視劇這個例子。在MQTT通訊中,客戶端所訂閱的肯定不是一部部電視劇,而是一個個“主題”。MQTT服務(wù)端在管理MQTT信息通訊時,就是使用“主題”來控制的。為了便于您更好理解服務(wù)端是如何通過主題來控制客戶端之間的信息通訊,我們來看看下圖示例:

以上圖示中一共有三個MQTT客戶端。它們分別是汽車、手機和電腦。在管理MQTT通訊時,MQTT服務(wù)端使用了“主題”來對信息進行管理。比如上圖所示,假設(shè)我們需要利用手機和電腦獲取汽車的速度,那么我們首先要利用電腦和手機向MQTT服務(wù)器訂閱主題“汽車速度”。接下來,當汽車客戶端向服務(wù)端的“汽車速度”主題發(fā)布信息后,服務(wù)端就會首先檢查以下都有哪些客戶端訂閱了“汽車速度”這一主題的信息。當它發(fā)現(xiàn)訂閱了該主題的客戶端有一個手機和一臺電腦,于是服務(wù)端就會將剛剛收到的“汽車速度”信息轉(zhuǎn)發(fā)給訂閱了該主題的手機和電腦客戶端。

以上實例中,汽車是“汽車速度”主題的發(fā)布者,而手機和電腦則是該主題的訂閱者。

值得注意的是,MQTT客戶端在通訊時,往往角色不是單一的。它既可以作為信息發(fā)布者也可以同時作為信息訂閱者。如下圖所示:

上圖中的所有客戶端都是圍繞“空調(diào)溫度”這一主題進行通訊的。對于“空調(diào)溫度”這一主題,手機和電腦客戶端成為了MQTT信息的發(fā)布者而汽車則成為了MQTT信息的訂閱者(接收者)。

可以看到,針對不同的主題,MQTT客戶端可以切換自己的角色。它們可能對主題A來說是信息發(fā)布者,但是對于主題B就成了信息訂閱者。

MQTT客戶端開發(fā)流程

以下采用的Paho MQTT樣例,簡要說明MQTT的開發(fā)流程。

樣例代碼在OpenHarmony源碼目錄/device/board/bearpi/bearpi_hm_nano/app/D5_iot_mqtt,源碼下載路徑參考文章末尾。開發(fā)應(yīng)用主要涉及以下幾個API應(yīng)用:

MQTT的流程主要由四個步驟組成:

1、創(chuàng)建客戶端對象;
2、連接服務(wù)器;
3、訂閱主題;
4、發(fā)布主題。

//訂閱的回調(diào)函數(shù)
void messageArrived(MessageData *data)
{
    printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len,
        data->topicName->lenstring.data, data->message->payloadlen, data->message->payload);
}
//主流程函數(shù)
static void MQTTDemoTask(void)
{
    WifiConnect("BearPi", "123456789");
    printf("Starting ...\n");
    int rc, count = 0;
    MQTTClient client;
 
    NetworkInit(&network);
    printf("NetworkConnect  ...\n");
 
    NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地電腦作為消息代理 此處為電腦IP
    printf("MQTTClientInit  ...\n");
    //1-------------創(chuàng)建客戶端對象
    MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));
 
    MQTTString clientId = MQTTString_initializer;
    clientId.cstring = "bearpi";
 
    MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
    data.clientID = clientId;
    data.willFlag = 0;
    data.MQTTVersion = MQTT_VERSION;
    data.keepAliveInterval = MQTT_KEEP_ALIVE_MS;
    data.cleansession = 1;
 
    printf("MQTTConnect  ...\n");
    //2-------------連接服務(wù)端
    rc = MQTTConnect(&client, &data);
    if (rc != 0) {
        printf("MQTTConnect: %d\n", rc);
        NetworkDisconnect(&network);
        MQTTDisconnect(&client);
        osDelay(MQTT_DELAY_2S);
    }
 
    printf("MQTTSubscribe  ...\n");
    //3-------------訂閱主題substopic
    rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived);
    if (rc != 0) {
        printf("MQTTSubscribe: %d\n", rc);
        osDelay(MQTT_DELAY_2S);
    }
    while (++count) {
        MQTTMessage message;
        char payload[30];
 
        message.qos = MQTT_QOS;
        message.retained = 0;
        message.payload = payload;
        (void)sprintf_s(payload, sizeof(payload), "message number %d", count);
        message.payloadlen = strlen(payload);
    //4------------發(fā)布pubtopic主題
        if ((rc = MQTTPublish(&client, "pubtopic", &message)) != 0) {
            printf("Return code from MQTT publish is %d\n", rc);
            NetworkDisconnect(&network);
            MQTTDisconnect(&client);
        }
        osDelay(MQTT_DELAY_500_MS);
    }
}

開發(fā)板MQTT客戶端代碼一直循環(huán)發(fā)送主題為pubtopic的信息,信息內(nèi)容為("message number %d", count),每次信息count++;

同時開發(fā)板客戶端也在訂閱主題為substopic的信息,一旦接收到substopic信息就會調(diào)用回調(diào)函數(shù),串口打印出substopic主題的內(nèi)容。

MQTT實操驗證

如何驗證MQTT客戶端代碼是否正常?驗證過程主要涉及以下幾點:

1、下載消息代理Mosquitto軟件,并配置Mosquitto;

2、下載EclipsePahoMQTT工具,并用該工具創(chuàng)建一個客戶端,我們簡稱客戶A;

3、修改客戶端MQTT代碼相關(guān)配置,與第一步配置Mosquitto相匹配,客戶端我們簡稱客戶B。

簡要說明下本次驗證中涉及的各個模塊的作用:

1、消息代理Mosquitto:可以理解為它就是MQTT服務(wù)器,所有客戶端的消息(發(fā)布/訂閱)都是與它通信;它負責(zé)接收及分發(fā)所有信息;

2、EclipsePahoMQTT工具創(chuàng)建的客戶端A:我們用來與創(chuàng)建的客戶端B進行信息交互(發(fā)布/訂閱)。

詳細細節(jié):

1、下載消息代理Mosquitto軟件,并配置Mosquitto:

(1)點擊下載網(wǎng)址(https://mosquitto.org/download/),選擇合適的版本,并安裝(記錄安裝路徑);

(2)安裝好后,配置Mosquitto,并開啟Mosquitto服務(wù):

在Mosquitto軟件的安裝路徑找到mosquitto.conf,打開并作如下修改:

192.168.120.137是本電腦的IP;1883指本次用來驗證的服務(wù)端口號(本電腦IP192.168.120.137可以有多個服務(wù)端口);allow_anonymous true指允許客戶端匿名登錄;

修改配置后,在安裝目錄打開命令窗口,輸入.\mosquitto -c .\mosquitto.conf -v。服務(wù)器啟動成功后,如下圖顯示mosquitto version 2.0.11 starting.

2、下載EclipsePahoMQTT工具,創(chuàng)建客戶端A,并連接服務(wù)器:

3、修改客戶端MQTT代碼相關(guān)配置,與第一步配置Mosquitto相匹配,客戶端我們簡稱客戶B:

修改連接端代碼:

NetworkConnect(&network, 192.168.120.137, 1883);//本地電腦作為消息代理 此處為電腦IP Mosquitto相匹配

4、燒錄代碼,并操作(發(fā)布\訂閱)通信:

客戶端B做了兩件事情:1、一直循環(huán)發(fā)送主題為pubtopic的信息,信息內(nèi)容是("message number %d", count);2、訂閱了主題為substopic的信息,一旦服務(wù)器有該主題信息就會發(fā)送給客戶端B,客戶端B會把substopic的內(nèi)容打印。

客戶端A也做了兩件事:1、訂閱主題為pubtopic的信息;2、發(fā)布一條主題為substopic的信息,內(nèi)容為“Hello OpenHarmony!”。

結(jié)合客戶端B(開發(fā)板)部分代碼:

printf("Starting ...\n");
NetworkInit(&network);
printf("NetworkConnect  ...\n");
NetworkConnect(&network, MQTT_SERVERIP, MQTT_SERVERPORT);//本地電腦作
printf("MQTTClientInit  ...\n");
//1-------------創(chuàng)建客戶端對象
MQTTClientInit(&client, &network, MQTT_CMD_TIMEOUT_MS, sendBuf, sizeof(sendBuf), readBuf, sizeof(readBuf));
 
printf("MQTTConnect  ...\n");
//2-------------連接服務(wù)端
rc = MQTTConnect(&client, &data);
     
printf("MQTTSubscribe  ...\n");
//3-------------訂閱主題substopic
rc = MQTTSubscribe(&client, "substopic", MQTT_QOS, messageArrived);
(void)sprintf_s(payload, sizeof(payload), "message number %d", count);
 //4------------循環(huán)發(fā)布pubtopic主題 內(nèi)容為message number+connt的計數(shù)值
 MQTTPublish(&client, "pubtopic", &message)
//訂閱的回調(diào)函數(shù)輸出以下內(nèi)容
printf("Message arrived on topic %.*s: %.*s\n", data->topicName->lenstring.len,
        data->topicName->lenstring.data, data->message->payloadlen, data->message->payload);

客戶B:開發(fā)板燒錄好代碼后,電腦串口工具連接開發(fā)板,會有連接MQTT及訂閱的信息(參照以上代碼),如下圖:

客戶A:顯示如下圖:

總結(jié)

本文從講解MQTT它是什么?原理是什么?到MQTT的應(yīng)用開發(fā)(API函數(shù)接口調(diào)用例程),再到MQTT的驗證(Mosquitto軟件及EclipsePahoMQTT工具的使用)三個方面介紹了MQTT。希望通過本文介紹讓大家對MQTT有個感性認識。

寫在最后

  • 如果你覺得這篇內(nèi)容對你還蠻有幫助,我想邀請你幫我三個小忙:
  • 點贊,轉(zhuǎn)發(fā),有你們的 『點贊和評論』,才是我創(chuàng)造的動力。
  • 關(guān)注小編,同時可以期待后續(xù)文章ing??,不定期分享原創(chuàng)知識。
  • 想要獲取更多完整鴻蒙最新學(xué)習(xí)知識點,請移步前往小編:https://gitee.com/MNxiaona/733GH/blob/master/jianshu
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容