Porting the Paho synchronous embedded C++ client

The MQTT library on mbed.org also now exists in Eclipse Paho. I intend Paho to be the master copy.

There are two APIs in this library, the largely complete synchronous API in MQTTClient.h, and the unfinished asynchronous API in MQTTAsync.h. In this post I’ll be talking about the synchronous API. I have discussed the major design points previous posts, now I’ll describe how to use the API. The documentation page on mbed can be found here.

The API implementation is intended to avoid system calls to allow it to be easily ported. Its function is limited purely to MQTT rather than networking setup for instance. This does mean that there is some work to use the API on a new OS, but we plan to collect examples in Paho for as many OSes as we can — contributions welcome!

The API is defined as a class template with these parameters:


template<class Network, class Timer, int MAX_MQTT_PACKET_SIZE = 100, int MAX_MESSAGE_HANDLERS = 5>

There are two class parameters, Network and Timer which are needed to provide platform specific implementations of sending and receiving data from the network, and timing, respectively. The third and fourth parameters are limits on the maximum MQTT packet size to be handled and the number of message handling callbacks. For each subscription, a message handling callback is needed, so you can think of this second limit as the maximum number of subscriptions you can have active at one time. Increasing these limits will increase the storage used when allocating the MQTT client object.

The file mbed.h contains an mbed specific implmentation of the Timer class. The file MQTTSocket.h contains an mbed specific network implementation for the Ethernet interface. The only requirements for the network class that you need to supply are the two methods:


int read(unsigned char* buffer, int len, int timeout);
int write(unsigned char* buffer, int len, int timeout);

Where

buffer
is the location to write data to, or read data from
len

is the number of bytes of that datatimeoutis the maximum number of milliseconds for the operation to complete.

The timer class counts down from a value to zero. I chose this way because it is always used for timeouts, so it checks to see whether the time has expired:


bool expired();                 // has the time expired?
void countdown_ms(int ms);      // start the timer for ms milliseconds
void countdown(int seconds);    // start the timer in seconds
int left_ms();                  // return the time left in milliseconds

Looking at the mbed example HelloMQTT, you see we have to connect the network interface before calling the MQTT connect:


MQTTEthernet ipstack = MQTTEthernet();
              
MQTT::Client<MQTTEthernet, Countdown> client = MQTT::Client<MQTTEthernet, Countdown>(ipstack);

int rc = ipstack.connect("m2m.eclipse.org", 1883);
if (rc != 0)
   lcd.printf("rc from TCP connect is %d\n", rc);
 
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;       
data.MQTTVersion = 3;
data.clientID.cstring = "mbed-sample";
data.username.cstring = "testuser";
data.password.cstring = "testpassword";
if ( (rc = client.connect(&data)) != 0)
   lcd.printf("rc from MQTT connect is %d\n", rc);

and then we can call subscribe, publish, unsubscribe and disconnect methods on the client in the usual sort of way for MQTT APIs.

Examples of how to use this API on Linux is in this
directory on Paho, in the hello.cpp and stdoutsub.cpp programs. The API is already running on Arduino, for which we’ll add an example, and for other platforms and operating systems later.

Author: Ian Craggs

I am the project lead of Eclipse Paho, a member of the Eclipse IoT working group and Eclipse IoT PMC, and co-chair of the OASIS MQTT-SN standardization Technical Sub-Committee.

11 thoughts on “Porting the Paho synchronous embedded C++ client”

  1. Hi, thank you for this great project. I’m working on porting paho on ARM cortex-M3 (EFM32 of SiliconLabs). I tried to follow the CC3200 example but I dont succeed. I’m not sure what is wrong with my code.

  2. Hi Ian,

    Thank you for your work. I’m trying to use the MQTTAsync API and compilation fails because of quite a lot of wrongly typed parameters passed to the underlying MQTTPacket layer.

    According to this post the MQTTAsync implementation was not finished in 2014, so I’m wondering if it still is a work in progress or if it should work and I’m just missing something, for instance incompatible versions of the two layers (what would be surprising since I got them bundled together through the import tool of the mbed IDE…)

    For example the send and received buffers have char* types but (de)serialization calls where they are passed as parameters expect unsigned char*

    Also calls to MQTTDeserialize_connack miss the first parameter “sessionPresent”…

    Do you have an idea what the problem could be?
    Thanks

    1. Hi Jean. Unfortunately I have not finished the MQTTAsync embedded API, I am thinking of taking a look at it again later this year once I’ve finished the MQTT V5 first implementations.

  3. I’ve tried to port your C MQTT client.
    I’m using Segger Embedded Studio, FreeRTOS and a wifi module WINC1500.

    I got stuck for a while at:
    DLLExport int MQTTIsConnected(MQTTClient* client)
    {
    return client->isconnected;
    }
    in the MQTTClient.h

    The error was that MQTTIsConnected() is defined multiple times.
    After declaring this in the according C file and just leaving the Prototype in the header it worked.

    Is that a problem of the compiler I’m using?

  4. I want to publish some data(dummy) on server over MQTT protocol through SIM800 GSM/GPRS module. I am using TM4C123GXL-Launchpad.i send AT commands to GSM module using uart of TM4C123 controller and creat TCP socket using following AT command send using uart
    AT
    AT+CSTT=’BSNLNET”,”,””
    AT+CIICR
    AT+CIFSR
    AT+CIPSTART=”TCP”,”iot.eclipse.org”,”1883″
    AT+CIPSEND
    socket creat sucessfully.
    now i want to implement MQTT protocol on top of TCP/IP

    please help how implement MQTT on top of TCP/IP

    1. You need to re-implement the network layer (see Linux directory) for your particular TCP API.

  5. Hi I’m using Embedded C Client library connection and publishing works fine but the when subscribing and using MQTTYield function my program hangs. I debugged the program it seems that the cycle function within fails to deserialize data. I’m seeing the data from socket in com port the payload and topic is Ok. I’m using a gsm module for TCP connection and cloudmqtt as MQTT broker.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.