Skip to content

leansoftX/code-arts-mqtt-client-demo

Repository files navigation

This directory contains two example programs demonstrating how to use an MQTT client from a C program:

  • main.c - a simple command-line based publisher/subscriber written in C. The remainder of this document describes the details of this application.
  • emqx_file_transfer.c - an example demonstrating how to use EMQX File Transfer Extension (https://www.emqx.io/docs/en/v5/file-transfer/introduction.html) from a C program. This example also works as a simple command line tool for using EMQX File Transfer Extension. Please see comments in the source code of this program for details. The compilation instruction in this document also works for this program.

Connect to the Deployment with C

This article mainly introduces how to use Eclipse Paho C in the C project, and implement the connection, subscription, messaging, unsubscribing and other functions between the client and MQTT broker.

Eclipse Paho Embedded C can be used on the desktop operating system, but mainly for embedded environments such as mbed, Arduino and FreeRTOS .

Preconditions

Install dependency packages

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

Building from source

The continuous integration builds can be found on Travis-CI for Linux and Mac, and AppVeyor for Windows.

Linux/Mac

git clone https://github.com/eclipse/paho.mqtt.c.git
cd org.eclipse.paho.mqtt.c.git
make
sudo make install

Windows

mkdir build.paho

cd build.paho

call "C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\vcvarsall.bat" x64

cmake -G "NMake Makefiles" -DPAHO_WITH_SSL=TRUE -DPAHO_BUILD_DOCUMENTATION=FALSE -DPAHO_BUILD_SAMPLES=TRUE -DCMAKE_BUILD_TYPE=Release -DCMAKE_VERBOSE_MAKEFILE=TRUE ..

nmake

Connection

Connection settings

This article will use the free public MQTT broker provided by EMQ X. This service was created based on the EMQ X Cloud. The information about broker access is as follows:

  • Broker: broker.emqx.io
  • TCP Port: 1883
  • WebSocket Port: 8083

Include dependency library

#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "MQTTClient.h"

Define connection addresses, authentication information, and message publishing and receiving topic

#define ADDRESS     "tcp://broker.emqx.io:1883"
#define USERNAME    "emqx"
#define PASSWORD    "public"
#define CLIENTID    "c-client"
#define QOS         0
#define TOPIC       "emqx/c-test"
#define TIMEOUT     10000L

Define the message publishing function

void publish(MQTTClient client, char *topic, char *payload) {
    MQTTClient_message message = MQTTClient_message_initializer;
    message.payload = payload;
    message.payloadlen = strlen(payload);
    message.qos = QOS;
    message.retained = 0;
    MQTTClient_deliveryToken token;
    MQTTClient_publishMessage(client, topic, &message, &token);
    MQTTClient_waitForCompletion(client, token, TIMEOUT);
    printf("Send `%s` to topic `%s` \n", payload, TOPIC);
}

Define the on_message callback function to print the content of the messages received by the subscribed topic

int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
    char *payload = message->payload;
    printf("Received `%s` from `%s` topic \n", payload, topicName);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

Initialize the MQTT client and subscribe to topic

int rc;
MQTTClient client;

MQTTClient_create(&client, ADDRESS, CLIENTID, 0, NULL);
MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
conn_opts.username = USERNAME;
conn_opts.password = PASSWORD;
MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
    printf("Failed to connect, return code %d\n", rc);
    exit(-1);
} else {
    printf("Connected to MQTT Broker!\n");
}
// subscribe topic
MQTTClient_subscribe(client, TOPIC, QOS);

Call the publish function in a loop to finish publishing the message

char payload[16];
for (int i = 0; i < 100; i += 1) {
    // publish message to broker
    snprintf(payload, 16, "message-%d", i);
    publish(client, TOPIC, payload);
    sleep(1);
}

Use MQTT over TLS

MQTTClient_SSLOptions ssl_opts = MQTTClient_SSLOptions_initializer;
/* Set the value of 'verify' to 0, which means that the domain should not be checked. Otherwise, if the domain does not match, an error will occur. */
ssl_opts.verify = 0;
ssl_opts.keyStore = CLIENTCERT;
ssl_opts.trustStore = CACERT;
ssl_opts.privateKey = PRIVATEKEY;
conn_opts.ssl = &ssl_opts;

The full code

#include "stdlib.h"
#include "string.h"
#include "unistd.h"
#include "MQTTClient.h"

#define ADDRESS     "tcp://broker.emqx.io:1883"
#define USERNAME    "emqx"
#define PASSWORD    "public"
#define CLIENTID    "c-client"
#define QOS         0
#define TOPIC       "emqx/c-test"
#define TIMEOUT     10000L

void publish(MQTTClient client, char *topic, char *payload) {
    MQTTClient_message message = MQTTClient_message_initializer;
    message.payload = payload;
    message.payloadlen = strlen(payload);
    message.qos = QOS;
    message.retained = 0;
    MQTTClient_deliveryToken token;
    MQTTClient_publishMessage(client, topic, &message, &token);
    MQTTClient_waitForCompletion(client, token, TIMEOUT);
    printf("Send `%s` to topic `%s` \n", payload, TOPIC);
}

int on_message(void *context, char *topicName, int topicLen, MQTTClient_message *message) {
    char *payload = message->payload;
    printf("Received `%s` from `%s` topic \n", payload, topicName);
    MQTTClient_freeMessage(&message);
    MQTTClient_free(topicName);
    return 1;
}

int main(int argc, char *argv[]) {
    int rc;
    MQTTClient client;

    MQTTClient_create(&client, ADDRESS, CLIENTID, 0, NULL);
    MQTTClient_connectOptions conn_opts = MQTTClient_connectOptions_initializer;
    conn_opts.username = USERNAME;
    conn_opts.password = PASSWORD;
    MQTTClient_setCallbacks(client, NULL, NULL, on_message, NULL);
    if ((rc = MQTTClient_connect(client, &conn_opts)) != MQTTCLIENT_SUCCESS) {
        printf("Failed to connect, return code %d\n", rc);
        exit(-1);
    } else {
        printf("Connected to MQTT Broker!\n");
    }
    // subscribe topic
    MQTTClient_subscribe(client, TOPIC, QOS);
    char payload[16];
    for (int i = 0; i < 100; i += 1) {
        // publish message to broker
        snprintf(payload, 16, "message-%d", i);
        publish(client, TOPIC, payload);
        sleep(1);
    }
    MQTTClient_disconnect(client, TIMEOUT);
    MQTTClient_destroy(&client);
    return rc;
}

Test

  1. Write the CMakeLists.txt file
    cmake_minimum_required(VERSION 3.17)
    find_package(eclipse-paho-mqtt-c 1.3.9 REQUIRED)
    project(mqtt_c C)
    include_directories(/usr/local/include)
    link_directories(/usr/local/lib)
    set(CMAKE_C_STANDARD 99)
    add_executable(mqtt_c main.c)
    target_link_libraries(mqtt_c paho-mqtt3c)
    
  2. Compile and run code image

About

code-arts-mqtt-client-demo c/c++

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published