文章分享

開(kāi)放、平等、協(xié)作、快速、分享

當(dāng)前位置:首頁(yè)>文章分享

Paho-MQTT C接入示例(阿里云)

摘錄:HCTech 無(wú)錫和控電子   時(shí)間:2020-08-07   訪問(wèn)量:4639

Paho-MQTT C接入示例

更新時(shí)間: 2020-04-21


本文介紹如何使用Paho提供的嵌入式C語(yǔ)言MQTT開(kāi)源工程接入阿里云物聯(lián)網(wǎng)平臺(tái),并進(jìn)行消息收發(fā)。

前提條件

已在物聯(lián)網(wǎng)平臺(tái)中,創(chuàng)建了產(chǎn)品和設(shè)備。

請(qǐng)參見(jiàn)創(chuàng)建產(chǎn)品單個(gè)創(chuàng)建設(shè)備

準(zhǔn)備開(kāi)發(fā)環(huán)境

本示例使用Ubuntu 16.04-LTS作為開(kāi)發(fā)環(huán)境。執(zhí)行以下命令構(gòu)建開(kāi)發(fā)環(huán)境。

sudo apt-get update sudo apt-get install build-essential git sed cmake

下載C語(yǔ)言Paho MQTT庫(kù)

執(zhí)行以下命令,克隆C語(yǔ)言版本的Paho MQTT庫(kù)。

git clone git@github.com:eclipse/paho.mqtt.embedded-c.git
說(shuō)明 編寫(xiě)本Demo示例時(shí),使用master分支,commit id29ab2aa29c5e47794284376d7f8386cfd54c3eed。

Paho嵌入式C工程提供了三個(gè)子項(xiàng)目。

  • MQTTPacket:提供MQTT數(shù)據(jù)包的序列化與反序列化,以及部分輔助函數(shù)。

  • MQTTClient:封裝MQTTPacket生成的高級(jí)別C++客戶端程序。

  • MQTTClient-C:封裝MQTTPacket生成的高級(jí)別C客戶端程序。

    MQTTClient-C中包含:

    ├── CMakeLists.txt ├── samples │   ├── CMakeLists.txt │   ├── FreeRTOS │   └── linux ├── src │   ├── CMakeLists.txt │   ├── FreeRTOS │   ├── MQTTClient.c │   ├── MQTTClient.h │   ├── cc3200 │   └── linux └── test     ├── CMakeLists.txt     └── test1.c

    了解Paho MQTT的更多API細(xì)節(jié),可以查看MQTTClient.h。

    • samples目錄提供FreeRTOSlinux兩個(gè)例程,分別支持FreeRTOS和Linux系統(tǒng)。

    • src目錄提供MQTTClient的代碼實(shí)現(xiàn)能力,以及用于移植到FreeRTOS、cc3200和Linux的網(wǎng)絡(luò)驅(qū)動(dòng)。

接入物聯(lián)網(wǎng)平臺(tái)

  1. 單擊打開(kāi)aiot_mqtt_sign.c,下載阿里云提供的計(jì)算MQTT連接參數(shù)所需的源碼。

    aiot_mqtt_sign.c文件定義了函數(shù)aiotMqttSign()。函數(shù)說(shuō)明如下。

    • 原型

      int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret,                  char clientId[150], char username[65], char password[65]);
    • 功能

      用于計(jì)算設(shè)備接入物聯(lián)網(wǎng)平臺(tái)的MQTT連接參數(shù)usernamepasswordclientid。

    • 輸入?yún)?shù)


      參數(shù)類型說(shuō)明
      productKeyconst char *設(shè)備所屬產(chǎn)品的ProductKey,該設(shè)備在物聯(lián)網(wǎng)平臺(tái)上的身份證書(shū)信息之一。
      deviceNameconst char *設(shè)備名稱,該設(shè)備在物聯(lián)網(wǎng)平臺(tái)上的身份證書(shū)信息之一。
      deviceSecretconst char *設(shè)備密鑰,該設(shè)備在物聯(lián)網(wǎng)平臺(tái)上的身份證書(shū)信息之一。
    • 輸出參數(shù)


      參數(shù)類型說(shuō)明
      usernamechar *MQTT連接所需的用戶名。
      passwordchar *MQTT連接所需的密碼。
      clientIdchar *MQTT客戶端ID。
    • 返回碼說(shuō)明


      返回碼說(shuō)明
      0成功
      -1失敗
  2. 添加實(shí)現(xiàn)設(shè)備接入物聯(lián)網(wǎng)平臺(tái)的程序文件。

    您需編寫(xiě)程序調(diào)用aiot_mqtt_sign.c中的aiotMqttSign()函數(shù)計(jì)算MQTT連接參數(shù),實(shí)現(xiàn)接入物聯(lián)網(wǎng)平臺(tái)和通信。

    開(kāi)發(fā)說(shuō)明和示例代碼如下。

    關(guān)于設(shè)備、服務(wù)器和物聯(lián)網(wǎng)平臺(tái)的通信方式介紹,請(qǐng)參見(jiàn)通信方式概述。

    • 調(diào)用NetworkInitNetworkConnect建立TCP連接。

    • 調(diào)用MQTTClientInit初始化MQTT客戶端。

    • 配置MQTT建連參數(shù)結(jié)構(gòu)體MQTTPacket_connectData。

    • 調(diào)用aiotMqttSign()接口,生成連接MQTT服務(wù)端的三個(gè)建連參數(shù)clientId、usernamepassword

      #define EXAMPLE_PRODUCT_KEY            "a11xsrW****" #define EXAMPLE_DEVICE_NAME            "paho_****" #define EXAMPLE_DEVICE_SECRET       "Y877Bgo8X5owd3lcB5wWDjryNPoB****" extern int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret,                         char clientId[150], char username[65], char password[65]); /* invoke aiotMqttSign to generate mqtt connect parameters */ char clientId[150] = {0}; char username[65] = {0}; char password[65] = {0}; if ((rc = aiotMqttSign(EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, EXAMPLE_DEVICE_SECRET, clientId, username, password) < 0)) {     printf("aiotMqttSign -%0x4x\n", -rc);     return -1; } printf("clientid: %s\n", clientId); printf("username: %s\n", username); printf("password: %s\n", password);
    • 接入物聯(lián)網(wǎng)平臺(tái)。

      需配置以下內(nèi)容:

      示例代碼:

      /* network init and establish network to aliyun IoT platform */ NetworkInit(&n); rc = NetworkConnect(&n, host, port); printf("NetworkConnect %d\n", rc); /* init mqtt client */ MQTTClientInit(&c, &n, 1000, buf, sizeof(buf), readbuf, sizeof(readbuf)); /* set the default message handler */ c.defaultMessageHandler = messageArrived; /* set mqtt connect parameter */ MQTTPacket_connectData data = MQTTPacket_connectData_initializer; data.willFlag = 0; data.MQTTVersion = 3; data.clientID.cstring = clientId; data.username.cstring = username; data.password.cstring = password; data.keepAliveInterval = 60; data.cleansession = 1; printf("Connecting to %s %d\n", host, port); rc = MQTTConnect(&c, &data); printf("MQTTConnect %d, Connect aliyun IoT Cloud Success!\n", rc);
    • 發(fā)布消息。

      調(diào)用MQTTPublish()接口,向指定的自定義Topic發(fā)布自定義格式消息。

      char *pubTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/update"; int cnt = 0; unsigned int msgid = 0; while (!toStop) {     MQTTYield(&c, 1000);         if (++cnt % 5 == 0) {         MQTTMessage msg = {             QOS1,             0,             0,             0,             "Hello world",             strlen("Hello world"),         };         msg.id = ++msgid;         rc = MQTTPublish(&c, pubTopic, &msg);         printf("MQTTPublish %d, msgid %d\n", rc, msgid);     } }

      通信Topic介紹,請(qǐng)參見(jiàn)什么是Topic。

    • 訂閱Topic,獲取云端下發(fā)的消息。

      void messageArrived(MessageData* md) {     MQTTMessage* message = md->message;     printf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data);     printf("%.*s\n", (int)message->payloadlen, (char*)message->payload); } char *subTopic = "/"EXAMPLE_PRODUCT_KEY"/"EXAMPLE_DEVICE_NAME"/user/get"; printf("Subscribing to %s\n", subTopic); rc = MQTTSubscribe(&c, subTopic, 1, messageArrived); printf("MQTTSubscribe %d\n", rc);
  3. 將第一步下載的aiot_mqtt_sign.c文件和第二步編輯的文件放到../paho.mqtt.embedded-c/MQTTClient-C/samples/linux中,然后編譯工程。

示例Demo

使用Demo代碼程序接入物聯(lián)網(wǎng)平臺(tái)。

  1. 下載Demo包,并解壓縮。解壓縮后,代碼包里有以下兩個(gè)文件。

    . +-- aiot_c_demo.c +-- aiot_mqtt_sign.c

    文件說(shuō)明
    aiot_mqtt_sign.c該文件中的代碼用于生成MQTT建連參數(shù)。aiot_c_demo.c運(yùn)行時(shí),會(huì)調(diào)用該文件中定義的aiotMqttSign()函數(shù),計(jì)算出連接參數(shù)usernamepasswordclientId。
    aiot_c_demo.c該文件包含設(shè)備與物聯(lián)網(wǎng)平臺(tái)連接和通信的邏輯代碼。
  2. aiot_c_demo.c中,修改設(shè)備信息為您的設(shè)備信息。

    • EXAMPLE_PRODUCT_KEY、EXAMPLE_DEVICE_NAMEEXAMPLE_DEVICE_SECRET替換為您的設(shè)備證書(shū)信息。

    • char *host = EXAMPLE_PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"中的地域代碼(cn-shanghai)替換為您的物聯(lián)網(wǎng)平臺(tái)設(shè)備所在地域代碼。地域代碼表達(dá)方法,請(qǐng)參見(jiàn)地域和可用區(qū)

  3. aiot_mqtt_sign.c和已修改的aiot_c_demo.c文件放到Paho工程的目錄../paho.mqtt.embedded-c/MQTTClient-C/samples/linux中。

  4. 編譯工程,并運(yùn)行程序。

    有兩種方法可以編譯出可執(zhí)行的程序。

    運(yùn)行成功,接入物聯(lián)網(wǎng)平臺(tái)的本地日志如下。

    clientid: paho_mqtt&a11xsrW****|timestamp=2524608000000,_v=sdk-c-1.0.0,securemode=3,signmethod=hmacsha256,lan=C| username: paho_mqtt&a11xsrW**** password: 36E955DC3D9D012EF62C80657A29328B1CFAE6186C611A17DC7939FAB637**** NetworkConnect 0 Connecting to a11xsrW****.iot-as-mqtt.cn-shanghai.aliyuncs.com 443 MQTTConnect 0, Connect aliyun IoT Cloud Success! Subscribing to /a11xsrW****/paho_mqtt/user/get MQTTSubscribe 0 MQTTPublish 0, msgid 1 MQTTPublish 0, msgid 2 MQTTPublish 0, msgid 3 MQTTPublish 0, msgid 4 MQTTPublish 0, msgid 5 ...

    物聯(lián)網(wǎng)平臺(tái)控制臺(tái)上,可查看設(shè)備狀態(tài)和日志。

    • 選擇設(shè)備管理 > 設(shè)備,可看到該設(shè)備的狀態(tài)會(huì)顯示為在線

    • 選擇監(jiān)控運(yùn)維 > 日志服務(wù),可查看云端運(yùn)行日志設(shè)備本地日志日志。詳情請(qǐng)參見(jiàn)云端運(yùn)行日志、設(shè)備本地日志。

    • 使用CMake

    • 使用build.sh。

    1. 修改/paho.mqtt.embedded-c/MQTTClient-C/samples/linux目錄下的build.sh文件為以下內(nèi)容。

      cp ../../src/MQTTClient.c . sed -e 's/""/"MQTTLinux.h"/g' ../../src/MQTTClient.h > MQTTClient.h gcc \     -o aiot_c_demo \     -I ../../src -I ../../src/linux -I ../../../MQTTPacket/src \     aiot_mqtt_sign.c aiot_c_demo.c \     MQTTClient.c \     ../../src/linux/MQTTLinux.c \     ../../../MQTTPacket/src/MQTTFormat.c \     ../../../MQTTPacket/src/MQTTPacket.c \     ../../../MQTTPacket/src/MQTTDeserializePublish.c \     ../../../MQTTPacket/src/MQTTConnectClient.c \     ../../../MQTTPacket/src/MQTTSubscribeClient.c \     ../../../MQTTPacket/src/MQTTSerializePublish.c \     ../../../MQTTPacket/src/MQTTConnectServer.c \     ../../../MQTTPacket/src/MQTTSubscribeServer.c \     ../../../MQTTPacket/src/MQTTUnsubscribeServer.c \     ../../../MQTTPacket/src/MQTTUnsubscribeClient.c
    2. 修改完成后,在當(dāng)前目錄下執(zhí)行命令./build.sh,完成編譯。

      完成編譯后,生成aiot_c_demo可執(zhí)行文件。

    3. 執(zhí)行命令./aiot_c_demo,運(yùn)行程序。

    4. /paho.mqtt.embedded-c/MQTTClient-C/samples/linux目錄下的CMakeLists.txt文件中,增加aiot_c_demo.caiot_mqtt_sign.c

      修改后的CMakeLists.txt文件內(nèi)容如下。

      add_executable(   stdoutsubc   stdoutsub.c ) add_executable(   aiot_c_demo   aiot_c_demo.c   aiot_mqtt_sign.c ) target_link_libraries(stdoutsubc paho-embed-mqtt3cc paho-embed-mqtt3c) target_include_directories(stdoutsubc PRIVATE "../../src" "../../src/linux") target_compile_definitions(stdoutsubc PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h) target_link_libraries(aiot_c_demo paho-embed-mqtt3cc paho-embed-mqtt3c) target_include_directories(aiot_c_demo PRIVATE "../../src" "../../src/linux") target_compile_definitions(aiot_c_demo PRIVATE MQTTCLIENT_PLATFORM_HEADER=MQTTLinux.h)
    5. 回到/paho.mqtt.embedded-c目錄,執(zhí)行以下命令,完成編譯。

      mkdir build.paho cd build.paho cmake .. make
    6. 編譯完成后,在/paho.mqtt.embedded-c/build.paho目錄下執(zhí)行以下命令,運(yùn)行程序。

      ./MQTTClient-C/samples/linux/aiot_c_demo

錯(cuò)誤碼

如果設(shè)備通過(guò)MQTT協(xié)議接入物聯(lián)網(wǎng)平臺(tái)失敗,請(qǐng)根據(jù)錯(cuò)誤碼排查問(wèn)題。服務(wù)端錯(cuò)誤碼說(shuō)明,請(qǐng)參見(jiàn)錯(cuò)誤排查


上一篇:使用MQTT.fx接入物聯(lián)網(wǎng)平臺(tái)(阿里云)

下一篇:SDK獲取及使用說(shuō)明

在線咨詢

點(diǎn)擊這里給我發(fā)消息 售前咨詢專員

點(diǎn)擊這里給我發(fā)消息 售后服務(wù)專員

在線咨詢

免費(fèi)通話

24小時(shí)免費(fèi)咨詢

請(qǐng)輸入您的聯(lián)系電話,座機(jī)請(qǐng)加區(qū)號(hào)

免費(fèi)通話

微信掃一掃

微信聯(lián)系
返回頂部