There are several MQTT solutions available for many different platforms and languages, and when you go looking for a ready-made solution to use, you may end up at https://github.com/mqtt/mqtt.github.io/wiki/libraries which provides several solutions and a lot of history.
The solution I wanted would be implemented in C++ and storage would be allocated during object creation as opposed to me separately defining it. Because I was going to use the Mbed OS I decided to use https://os.mbed.com/teams/mqtt/code/MQTT/ as my starting point. Unfortunately, this software is targeted at Mbed OS v2.x which is fairly old given that the last release was v5.8. So it needs some updating to get it working with Mbed v5.x.
In this MQTT solution, the Class methods use a transport Class to communicate with the systems communications interface. In the class from the link, an Ethernet interface (MQTTEthernet.h) is provided but to utilize a different interface, a new transport class would be needed. The good news is that the transport class is very limited in what it implements and as provided, the MQTT solution works; the bad, there are several warnings generated when compiling and some code duplicates functionality already present in the MBed OS.
So as I started working with the MQTT library, I had three goals:
- Minimize the unnecessary code, specifically, the FP Class
- Eliminate the warnings that were being generated when compiled (which incidentally were mostly because of the FP Class)
- Remove the duplication of code that was necessary when the MQTT code was used with different Network Interfaces.
Not a tremendous amount of work, essentially:
- Removing the FP Class callbacks and replace them with the current Mbed OS functions
- Creating a new Template class to automatically create the transport class used with the communications interface.
In the MQTT Class, the user to must provide pointers to functions for the class to use. In Mbed v2.x, there was no call-back function provided so an FP (Function Pointer) Class was used. In the downloaded MQTT source, this is an artifact from the earlier Mbed version. In recent Mbed OS releases, call-back functionality has been incorporated as a Callback class (https://os.mbed.com/docs/v5.6/reference/callback.html). Even though the FP and Callback classes implement similar functionality, the method names and some of the parameters have changed—so to achieve my goal #1, I removed the FP Class and modified the MQTT template functions with the correct method parameters. By implementing goal #1, I was also able to achieve goal #2 because the older legacy code was no longer compiling and that was what generated the warnings I was encountering.
Goal #3 was achieved by creating a new class template that creates the necessary transport interface at compile time. The class itself simply creates an Interface Class, connects it, and returns a pointer to the class:
template class MQTTconnect : public MQTTSocket { T eth; public: MQTTconnect() : MQTTSocket(ð) { eth.connect(); } T& getEth() { return eth; } };
When this template is used, it creates an MQTTconnect class using the Interface that the caller specifies. The class itself simply connects to the interface when created and provides a method to return a pointer to the interface. To ease the use of this template, a macro was created:
#define MQTT_USE(x) typedef MQTTconnect MQTTct; typedef x MQTTnet;
That macro allows a user to define the interface to use with MQTT and creates two types of elements (MQTTct and MQTTnet). This makes using the MQTT software as easy as telling MQTT what interface to use, for example:
MQTT_USE(BG96Interface); MQTTct net; MQTTnet& eth = net.getEth();
With this MQTT implementation, you can now simply ‘Define’ the Interface to use rather than create a new, separate class.
I used this MQTT implementation with the Avnet NB-IoT Sensor Shield (Available from https://www.avnet.com/wps/portal/silica/products/new-products/npi/avnet-nb-iot-shield-sensor) sensor board in combination with a X_NUCLEO_L476RG SBC and X_NUCLEO_IKS01A2 sensors expansion board.
The code can all be obtained at https://github.com/Avnet/BluemixQS_BG96. Try it out and see if it makes implementing MQTT easier...