uMQTT
MQTT client library for microcontrollers
|
This is called uMQTT or umqtt for "micro-MQTT". The micro refers to microcontroller.
This library provides a set of functions for processing MQTT client packets. It is intended primarily for use with microcontrollers.
The design goals:
The library uses instance handles so the same code can be used for multiple client connections to one or more MQTT servers.
License
BSD-style license, see here License.
Application Interface
umqtt
provides a straightforward set of functions for MQTT operations such as Connect, Publish, Subscribe, etc. Internally it keeps track of the state of communication flow so that it can resend packets when needed and know when requests have been properly acknowledged. To do this it provides a Run
function that must be called from the application main loop. The application only needs to provide a millisecond tick timer and the umqtt
library will keep track of all timeouts.
umqtt
does require some services from the application. The application must provide functions to read and write from the network, and functions to allocate and free memory. The concept of the network is completely abstract. From the point of view of umqtt
library, it is just a data pipe. It could be wired or wireless ethernet, or it could be a serial link. Anything that can be used to transmit and receive data packets. The memory allocator can also be implemented in many ways. The umqtt
library only needs to receive memory it requests for holding packets. It doesn't matter how the memory is allocated. It could just be a mapping to the run-time malloc()/free() library functions. Or it could be a third party allocator such as bget, or even just a simple list of fixed size buffers.
umqtt
notifies the application of events with a set of optional callback functions. It is possible to use umqtt
without any callback functions.
RTOS and thread safety
It should be possible to use umqtt
with an RTOS. However the API functions have not been written to be thread-safe. If used with an RTOS, either all the functions should be called from within a single RTOS thread, or the API functions should be wrapped with a semaphore to serialize access. None of the API functions are inherently blocking, although they do call the application-supplied network functions and these should be implemented to also be non-blocking.
Network Management
umqtt
is implemented to be completely network-agnostic. It is up to the application to provide the interface network. This means that for a typical TCP/IP network, the application must first establish the network socket connection to an MQTT server, before calling umqtt_Connect().
Dynamic memory usage
Because MQTT protocol uses an acknowledgment packet flow, it requires that the client track packets that have not been acknowledged and resend unacknowledged packets. Even if QoS 0 is used for published topics, the client still needs to keep track of acks for connect, subscribe, and unsubscribe packets. umqtt
does not make any attempts to throttle the number of pending packets. It adds pending packets to an internal linked list. When the appropriate ack packet is received from the network it removes the pending packet from the list and frees it. If the application were to perform many requests at once (multiple subscribes, or publish many topics with QoS 1) then the number of pending packets could momentarily grow large until all of the ack packets are received back from the broker.
umqtt
also allocates memory to hold instance data when umqtt_New() is called. Therefore, umqtt_Delete() should always be called if the client is to be shut down.
Typical Flow
umqtt
instanceError Recovery
umqtt
uses a simple minded scheme for tracking network errors and recovering. If any network read or write fails, umqtt
will abort the current operation and return UMQTT_ERR_NETWORK error code. It does not otherwise change any internal state. In case it is possible to recover the network connection, the application can perform recovery steps and resume using the umqtt
instance and everything should continue as before. But usually if network read or write fails, it means that the connection has been dropped or has some other problem. In this case the recovery procedure should be:
umqtt
instance and connect the MQTT clientThese steps may seem tedious, but it ensures that the MQTT client is disconnected cleanly at the protocol level (if possible) and that all allocated memory is freed. Since umqtt
allocates memory to store packets, this procedure ensures that any pending packets that are still allocated will be freed and thus avoid memory leaks due to network errors.