This topic describes how to use the open-source Paho MQTT C/C++ client to access Alibaba Cloud IoT Platform for message exchanges.

Prerequisites

Products and devices are created in IoT Platform.

For more information, see Create a product and Create a device.

Prepare the development environment

In this example, Ubuntu 16.04-LTS is used for building the development environment. Run the following command to build the development environment.

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

Download the Paho MQTT library for C

Run the following command to clone the C language version of the Paho MQTT library.

git clone git@github.com:eclipse/paho.mqtt.embedded-c.git
Note The demo example uses the master branch. The commit id is 29ab2aa29c5e47794284376d7f8386cfd54c3eed.

The Paho MQTT for C project provides three sub-projects:

  • MQTTPacket: Provides serialization and deserialization of MQTT data packets and some additional helper functions.
  • MQTTClient: Encapsulates the high-level C++ client program generated by MQTTPacket.
  • MQTTClient-C: Encapsulates the high-level C client program generated by MQTTPacket.

    MQTTClient-C includes:

    ├── CMakeLists.txt
    ├── samples
    │   ├── CMakeLists.txt
    │   ├── FreeRTOS
    │   └── linux
    ├── src
    │   ├── CMakeLists.txt
    │   ├── FreeRTOS
    │   ├── MQTTClient.c
    │   ├── MQTTClient.h
    │   ├── cc3200
    │   └── linux
    └── test
        ├── CMakeLists.txt
        └── test1.c
    • The samples directory provides sample code for FreeRTOS and Linux systems.
    • The src directory provides the code for MQTTClient and network drivers for porting to FreeRTOS, CC3200, and Linux.

    For more information about the Paho MQTT APIs, see MQTTClient.h.

Connect to IoT Platform

  1. Click aiot_mqtt_signal.c to view and download the source code that is provided by Alibaba Cloud to calculate the MQTT connection parameters.

    The aiot_mqtt_signal.c file defines the function aiotMqttSign(). The following describes the function.

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

      Calculates the username, password, and clientId parameters for MQTT connections to IoT Platform.

    • Input parameters
      Parameter Type Description
      productKey const char * The ProductKey of the product to which the device belongs.
      deviceName const char * The name of the device.
      deviceSecret const char * The device key.
    • Output parameters
      Parameter Type Description
      username char * The username required for the MQTT connection.
      password char * The password required for the MQTT connection.
      clientId char * The ID of the MQTT client.
    • Return codes
      Return code Description
      0 Successful
      -1 Failed
  2. Add the program file that enables the device to access IoT Platform.

    You must write a program that calls the function aiotMqttSign() in the aiot_mqtt_sign.c file to calculate the MQTT connection parameters. Then use the parameters to connect to IoT Platform for communications.

    The development instructions and sample code are as follows.

    • Call the aiotMqttSign() function to generate the three connection parameters clientId, username, and password.
      #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);
    • Connect to IoT Platform.

      Configure the following items:

      • Call the NetworkInit and NetworkConnect functions to establish a TCP connection.
      • Call the MQTTClientInit function to initialize the MQTT client.
      • Configure the MQTTPacket_connectData structure for the MQTT connection parameters.

      The sample code is as follows:

      /* 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);
    • Publish a message.

      Call the MQTTPublish() function and publish messages to a custom topic.

      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);
          }
      }

      For more information about topics, seeWhat is a topic?.

    • Subscribe to a topic and obtain messages from the cloud.
      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);

    For more information about the communication methods of devices, servers, and IoT Platform, see Communication methods.

  3. Copy the aiot_mqtt_signal.c file and the file coded in Step 2 to ../paho.mqtt.embedded-c/MQTTClient-C/samples/linux and then compile the project.

Demo

Use the demo code to access IoT Platform.

  1. Download the demo package. Then decompress the package.
    After decompression, the code package contains the following two files:
    .
    +-- aiot_c_demo.c
    +-- aiot_mqtt_sign.c
    File Description
    aiot_mqtt_sign.c The code in this file is used to generate MQTT connection parameters. When you run aiot_c_demo.c, it calls the aiotMqttSign() function to calculate the connection parameters, such as username, password, and clientId.
    aiot_c_demo.c This file contains the code for connections and communication between the device and IoT Platform.
  2. In the aiot_c_demo.c file, change the device information to your device information.
    • Replace the EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, and EXAMPLE_DEVICE_SECRET parameter values with your device certificate information.
    • Replace cn-shanghai in char *host = EXAMPLE_PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com" with the region ID of your IoT Platform device. For more information about region IDs, see Regions and zones.
  3. Move the aiot_mqtt_signal.c and modified aiot_c_demo.c files to the ../paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory of the Paho project.
  4. Compile the project and run the program.

    The following shows two methods to compile executable programs.

    • Use CMake.
      1. Add aiot_c_demo.c and aiot_mqtt_signal.c to the CMakeLists.txt file of the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory.

        The content of the modified CMakeLists.txt file is as follows:

        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)
      2. Go back to the /paho.mqtt.embedded-c directory and run the following command to complete the compilation.
        mkdir build.paho
        cd build.paho
        cmake ..
        make
      3. After the compilation is completed, in the /paho.mqtt.embedded-c/build.paho directory, run the following command to run the program.
        . /MQTTClient-C/samples/linux/aiot_c_demo
    • Use the build.sh file.
      1. Modify the build.sh file in the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory by copying the following code into the file.
        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. After the modification, run the command ./build.sh in the current directory to complete the compilation.

        After compilation, the aiot_c_demo executable file is generated.

      3. Run the ./aiot_c_demo command to run the program.
    After the program starts, the local log for accessing IoT Platform is as follows:
    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
    ...

    In the IoT Platform console, you can view the device status and logs.

    • Choose Devices > Devices. You can view that the status of the device is Online.
    • Choose Maintenance > Device Log. You can view the Device Activity Analysis and Upstream Analysis logs.