The Paho C client lets you send and receive MQTT messages and supports MQTT v3, v5 ,Websockets and SSL .There are two versions:
C Client Versions
There are two main versions:
- Synchronous
- Asynchronous
The synchronous version is the original version and can be single threaded or multi threaded when using callbacks.
The asynchronous version is the newer version
To use the synchronous version use
#include MQTTClient.h
and the asynchronous version use
#include MQTTAsync.h
There is an old explanation on the rational for these variants here.
The documentation for the synchronous version is here and for the asynchronous version it is here.
Most of the examples you see on the Internet use the synchronous client.
Building and Libraries
You need to download and install the client libraries by cloning the repo as detailed on the github page.
git clone https://git.eclipse.org/r/paho/org.eclipse.paho.mqtt.c
Then change folders into the paho.mqtt.c folder and run make and install.
cd paho.mqtt.c make sudo make install
The Paho C client comprises four variant libraries, shared or static:
- paho-mqtt3a – asynchronous (MQTTAsync)
- paho-mqtt3as – asynchronous with SSL/TLS (MQTTAsync)
- paho-mqtt3c – “classic” / synchronous (MQTTClient)
- paho-mqtt3cs – “classic” / synchronous with SSL/TLS (MQTTClient)
Using The MQTT C Client
The Basic code structure used is:
- Create a client object
- Set the options to connect to an MQTT server
- Set up callback functions if multi-threaded
- Subscribe to any topics.
- Publish messages
- Handle any incoming messages
- Disconnect the client
- Free any memory being used by the client
You will need to add the header to your c code file as shown in the code snippet below:
#include "MQTTClient.h"
When compiling my program client1.c the compiler complained about missing files as shown in the screen shot below:
For some reason it couldn’t find the paho-mmqt3c library so I had to include it on the compile line using the -l switch:
cc client1.c -o client1 -l paho-mqtt3c
Note: the cJSON.c is only necessary if you are using JSON in the c program. We will cover examples later on.
Using the Synchronous Single Threaded Client
If you are familiar with the python client then you will be aware of the client loop which processes receive messages.
If you use the threaded option by declaring callbacks then a client loop is started automatically in another thread.
However if you don’t declare callbacks then you need to manually check for received messages using the MQTTClient_receive function.
This function needs to be called often, and is often found in an infinite while loop.
Below is sample code:
//setup variables char * topicName=NULL; int topicLen; MQTTClient_message *m=NULL; //start infinite loop while(1) { //2 is the timeout which is 2 milliseconds MQTTClient_receive(client,&topicName,&topicLen,&m,2); if(topicName){ printf("Message received on topic %s is %.*s.\n", topicName, m->payloadlen, (char*)(m->payload)); MQTTClient_free(topicName); MQTTClient_freeMessage(&m); }
MQTTClient_receive function not only retrieves data messages but also MQTT control messages like PINGRESP.
If you disable this function call the broker will disconnect the client after the keep alive interval expires.
An Alternative to the MQTTClient_receive() function is the MQTTClient_yield() function.
MQTTClient.h File Reference
This page MQTTClient.h reference pages lists all the sata structures and functions of the MQTT client and is a very useful reference.
MQTT v3.1.1 and v5
The MQTT client has different functions for connect, disconnect, publish and subscribe for versions 3 and v5.
To connect to a broker using MQTT v3.1.1 use:
MQTTClient_connect()
and for v5 use
MQTTClient_connect5()
See the MQTTClient.h reference pages for details.
Code Basics
The first step is to create a new client which we do using :
MQTTClient client; rc = MQTTClient_create(&client, url, clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL);
The url is the address of the broker of the form “tcp://localhost:1883”, and the clientid should be unique.
MQTTCLIENT_PERSISTENCE_NONE – means use in memory persistence. This is followed by a NULL for the persistence context.
Once we have a client we can now proceed to connect but before we do that we need to set the connection options.
We start by initializing the connection options structure.
MQTT_connectionOptions conn_opts=MQTTClient_connectionOptions_initializer;
You will see this code structure repeated for other structures like the published message which looks like this:
MQTT_message pubmsg=MQTTClient_message_initializer;
We then set various connection options using the format:
conn_opts.KeepAliveInterval=120;
conn_options.clean_session=0;
etc
now we need to connect using
MQTTClient_connect(client, &conn_opts);
Notice this uses client and not &client as in the create function call.
Because the connection returns a result we use:
rc=MQTTClient_connect(client, &conn_opts);
and test the reason code 0=Success.
Note: The above code works for MQTTv3.1.1 (default) but for MQTTv5 we need to use a different initialiser:
MQTT_connectionOptions conn_opts=MQTTClient_connectionOptions_initializer5;
We also need to set the protocol version using the create with options format. So for version 5 we use:
MQTT_connectionOptions conn_opts=MQTTClient_connectionOptions_initializer5; MQTTClient client; MQTTClient_createOptions creatOpts=MQTTClient_createOptions_initializer; createOpts.MQTTVersion=5; rc = MQTTClient_createWithOptions(&client, url, clientid, MQTTCLIENT_PERSISTENCE_NONE, NULL); conn_opts.cleansession=0; response=MQTTClient_connect5(client,&conn_opts,&props,&willprops
We need to set the props and will properties which we will cover in later tutorial with some demo code. but they can be set to NULL if not Used.
Examples
1. Connect,pub and subscribe,Single threaded mqttv3.1.1
MQTT C client – Connect, pub and subscribe,Single Thread
Related Tutorials and Resources: