Paho MQTT C (embedded) integration example
This topic describes how to use the open source Paho Message Queuing Telemetry Transport (MQTT) C library for embedded systems to connect a device to Alibaba Cloud IoT Platform and exchange messages.
Important notes
The steps in this topic are performed by a regular user. If you encounter an operation that requires administrative permission, run the command with sudo.
Prerequisites
In the IoT Platform console , for the corresponding instance, create a product and a device, and obtain the MQTT access domain name and the device certificate information (ProductKey, DeviceName, and DeviceSecret). For more information, see:
Prepare the development environment
This example uses Ubuntu 16.04 LTS as the development environment. Run the following commands to set up the environment.
sudo apt-get update
sudo apt-get install build-essential git sed cmakeDownload the Paho MQTT C library
Run the following command to clone the Paho MQTT C library.
git clone https://github.com/eclipse-paho/paho.mqtt.embedded-c.gitThis demo is based on the master branch. The commit id is 29ab2aa29c5e47794284376d7f8386cfd54c3eed.
The Paho embedded C project provides the following three subprojects:
MQTTPacket: Provides serialization and deserialization for MQTT packets and includes helper functions.
MQTTClient: A high-level C++ client that encapsulates MQTTPacket.
MQTTClient-C: A high-level C client that encapsulates MQTTPacket.
MQTTClient-C contains the following:
├── CMakeLists.txt ├── samples │ ├── CMakeLists.txt │ ├── FreeRTOS │ └── linux ├── src │ ├── CMakeLists.txt │ ├── FreeRTOS │ ├── MQTTClient.c │ ├── MQTTClient.h │ ├── cc3200 │ └── linux └── test ├── CMakeLists.txt └── test1.cThe samples folder provides examples for FreeRTOS and Linux.
The src folder provides the MQTTClient implementation and network drivers for porting to FreeRTOS, cc3200, and Linux.
To learn more about the Paho MQTT API, see MQTTClient.h.
Connect to IoT Platform
Click to open aiot_mqtt_sign.c, copy the source code provided by Alibaba Cloud for calculating MQTT connection parameters, and then paste it into a local file named aiot_mqtt_sign.c.
The aiot_mqtt_sign.c file defines the aiotMqttSign() function. The function is described as follows:
Prototype:
int aiotMqttSign(const char *productKey, const char *deviceName, const char *deviceSecret, char clientId[150], char username[65], char password[65]);Features
Calculates the username, password, and clientid parameters for an MQTT connection to IoT Platform.
Input parameters:
Parameter
Type
Description
productKey
const char *
The ProductKey of the product to which the device belongs. This is part of the device certificate on IoT Platform.
deviceName
const char *
The device name. This is part of the device certificate on IoT Platform.
deviceSecret
const char *
The device secret. This is part of the device certificate on IoT Platform.
Response 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 MQTT client ID.
Return codes:
Return code
Description
0
Success
-1
Failed
Create the program file to connect the device to IoT Platform.
Write a program that calls the aiotMqttSign() function in aiot_mqtt_sign.c to calculate the MQTT connection parameters. These parameters are used to connect to and communicate with IoT Platform.
The development instructions and sample code are as follows:
Call the aiotMqttSign() API to generate the three connection parameters for the MQTT server: 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 NetworkInit and NetworkConnect to establish a TCP connection.
Call MQTTClientInit to initialize the MQTT client.
Configure the MQTTPacket_connectData struct for MQTT connection parameters.
Sample code:
/* 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, Connected to Alibaba Cloud IoT Platform.\n", rc);Publish a message.
Call the MQTTPublish() API to publish a message in a custom format to a specified custom topic.
For more information about topics, see What is a 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); } }Subscribe to a topic to receive 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 information about the communication methods of devices, servers, and IoT Platform, see Overview of communications among devices, IoT platform, and servers.
Place the aiot_mqtt_sign.c file from Step 1 and the program file from Step 2 into the ../paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory. Then, compile the project.
Sample code
Use the demo program to connect to IoT Platform.
Download the demo package and decompress it.
After decompression, the package contains the following two files:
File
Description
aiot_mqtt_sign.c
This file contains code to generate MQTT connection parameters. At runtime, aiot_c_demo.c calls the aiotMqttSign() function from this file to calculate the username, password, and clientId.
aiot_c_demo.c
This file contains the logic to connect the device to IoT Platform and communicate with the platform.
In aiot_c_demo.c, replace the placeholder values with your device information.
Replace the values of EXAMPLE_PRODUCT_KEY, EXAMPLE_DEVICE_NAME, and EXAMPLE_DEVICE_SECRET in the following code with your device certificate information.
#define EXAMPLE_PRODUCT_KEY "YourProductKey" #define EXAMPLE_DEVICE_NAME "YourDeviceName" #define EXAMPLE_DEVICE_SECRET "YourDeviceSecret"Modify the value in the code
char *host = EXAMPLE_PRODUCT_KEY".iot-as-mqtt.cn-shanghai.aliyuncs.com"to your endpoint.For more information about the endpoint formats for public and Enterprise instances, see View instance endpoints.
Place the aiot_mqtt_sign.c file and the modified aiot_c_demo.c file into the ../paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory of the Paho project.
Compile the project and run the program.
You can compile the executable program in two ways:
Use CMake.
In the CMakeLists.txt file in the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory, add aiot_c_demo.c and aiot_mqtt_sign.c.
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)Return to the /paho.mqtt.embedded-c directory and run the following commands to complete the compilation.
mkdir build.paho cd build.paho cmake .. makeAfter the compilation is complete, run the following command in the /paho.mqtt.embedded-c/build.paho directory to run the program.
./MQTTClient-C/samples/linux/aiot_c_demo
Use build.sh.
Open the build.sh file in the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory.
In build.sh, replace
stdoutsub.cwithaiot_mqtt_sign.c aiot_c_demo.cand replace-o stdoutsubwith-o aiot_c_demo. Then, save the build.sh file.After you make the changes, run the
./build.shcommand in the /paho.mqtt.embedded-c/MQTTClient-C/samples/linux directory to complete the compilation.After the compilation is complete, the aiot_c_demo executable file is generated.
Run the
./aiot_c_democommand to run the program.
The operation is successful. The following is the binary log for accessing IoT Platform:
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, Connected to Alibaba Cloud IoT Platform! 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 ...Log on to the IoT Platform console. In the appropriate instance, you can view the device status and logs.
Choose . The status of the device is Online.
Choose . You can view IoT Platform logs and on-premises device logs. For more information, see IoT Platform logs and On-premises device logs.
Error codes
If the device fails to connect to IoT Platform over MQTT, use the error codes to troubleshoot the issue. For more information about server-side error codes, see Troubleshooting.