MQTT is one of the most well-known and adopted protocols in IoT world. The lightweight and simplicity design are great addons that make it suitable for embedded devices, with small as well as large processing and storage capabilities. The benefits introduced by using MQTT instead of HTTP include power saving and lower network bandwidth usage which are two important things for almost any IoT device. Numbers from Stephen Nicholas’ great study say that loudly!
In this article we will have a closer look at MQTT and we will get our hands dirty by trying this protocol on localhost.
MQTT in a Nutshell
MQTT or Message Queuing Telemetry Transport is “a Client Server publish/subscribe messaging transport protocol. It is light weight, open, simple, and designed so as to be easy to implement.” according to the official definition. It’s specially designed for IoT context with the limited resource environment in terms of power, bandwidth and footprint.
The MQTT model includes 3 main blocks: broker, publisher and subscriber.
- The broker is the server responsible to manage the network of clients which are a mix of publishers and subscribers.
- The publisher is the device which sends messages (publish) to the server. These messages are labeled with a ‘topic’ name.
- The subscriber is the device which listens for topic/s.
There is no direct connection between the publisher and subscriber, simply the subscriber tells the broker (server) which topics it interested in, and the broker handles sending a message with data for the requested topic/s to all subscribers. The publish/subscribe model is quite different from the request/response model in HTTP, and this allows for one-to-many message transfer.
The topics can be think of like a tag for each message, and can be in the form of one level or multi-levels (tree) each level separated by a slash (/) (.i.e: rooms/room1/sensors/temp ). This can be used to organize data in a handy way.
Each device want to get data on a certain topic, must “subscribe” to it by informing the broker (server). The subscription can be done to a certain topic or “pattern”. To accomplish this wildcards (+ and #) are used.
- ‘+’ sign means to subscribe to any topic in this level. I.e: rooms/+/sensors/temp this means to listen to data that come from temperature sensors from all rooms.
- ‘#’ sign means to subscribe to all topics in this level and child levels. I.e: rooms/room1/# this means to listen to all information related to room1.
MQTT protocol is based on TCP/IP. Not like HTTP, it’s a binary protocol not an ASCII (plain text) protocol where it uses bit/s as the basic units to control the protocol features while ASCII ones use characters. As a result, Binary protocols consumes less network bandwidth.
MQTT was designed for environments with limited resources in mind especially about network access, thus this protocol has many features and options related to message delivery from server and clients. QoS or Quality of Service is the term for the 3 options for message delivery levels:
- Level 0 (QoS = 0): At most once delivery. This means if the receiver missed the message it will not be sent again. In other words, the server (broker) sends the message and doesn’t expect an acknowledgment from the client.
- Level 1 (QoS = 1): At least once delivery. This means that the broker keeps sending the message to the subscriber until it sense an acknowledgment from it. This may lead to receive the message more than once at the subscriber side .
- Level 2 (QoS =2): Exactly once delivery. This level guarantees to deliver one message exactly to the subscriber.
The question now is, what if the client/subscriber was not connected at all? Will the messages be lost or received later when the subscriber connects again? The answer is “It depends” . It depends on the option called “Clean Session” specified in the connection packet. If the user set this bit, then each time the client (identified with an id number) connects, the server discard any previous Sessions (including messages) and start a new one, while if this bit is zero, then the server will store QoS 1 and QoS 2 messages that match any subscriptions that the subscriber had while it was disconnected.
More features like retained message and last will are going to be discussed more in the next section. For now, It’s enough to say that MQTT can define a message for each topic to be sent whenever a subscriber subscribed to the topic. This messages is called the “retained message”, while the “last will” is a message published on a specific topic when the broker loses the connection with the client. The will message is defined for each client independently.
Hands-on with MQTT
To exercise the fundamentals of MQTT, we will use Eclipse Mosquitto broker which is available for many platforms. First, download and install the broker.
After installation, start the broker on your localhost by running the mosquitto command. You can check using netstat -an command to see the port 1883 (the MQQT port).
Now, run 2 terminals (for linux) or CMDs (for windows). One of them will be used to publish messages and the other to subscribe and get messages.
Eclipse Mosquitto comes with mosquitto_pub and mosquitto_sub which are used to publish and subscribe via topics.
Let’s first use this command to subscribe to “rooms/room1/sensors/temp” topic, using this command:
mosquitto_sub -t rooms/room1/sensors/temp
On the other terminal, let’s publish a message on that topic, using this command:
mosquitto_pub -t rooms/room1/sensors/temp -m 25
‘-m’ is use to set the message value.
QoS & Clean Session
Now, let’s see when the QoS comes into action, but first we need to assign an ID to the subscriber using -i option, thus when the client is disconnected the session is saved for the specific ID. The other thing is to add is the -c option which disables the ‘clean session’ feature described in the previous section..
After the client (subscriber with ID = 2) was disconnected, the publisher published 3 messages. But as we can see, the client (ID = 2) received them once it became connected again. The 3 messages are with QoS level 2 using ‘-q’ argument which sets the QoS level.
Let’s try now to send 3 messages (21, 22 and 23) while the client (ID = 2) is disconnected, but this time only one of them is with QoS>0.
Retained Message and Last Will
Retained message is a message for each topic to be sent whenever a subscriber subscribed to the topic. For example, for the ‘rooms/room1/sensors/temp topic’, if the temperature sensor stopped working properly, a special value like NaN can indicate to every new subscriber that this sensor is not working. So whenever the publisher detects malfunctioning in the sensor, it can set NaN message as a retained message. The ‘-r option’ sets the message as a retained message.
Back to MQTT protocol bits, the retained message is a bit field in the publish packet header.
Now, what if the sensor device was tempered by someone not authorized which lead to disconnection. How will the subscriper know? Here the ‘last will’ come into play! Last will is a message published on a specific topic when the broker losses the connection with the client.
References & Read More
After this introduction, scanning the protocol specification should be in your priorities. You can review the HiveMQ – MQTT essentials series and this paper Tutorial: MQTT (Message Queuing Telemetry Transport) too. Also , the Building Smarter Planet Solutions with MQTT and IBM WebSphere MQ Telemetry is a good book talking about MQTT. Last but not least, you can read more about security using TLS and MQTT and MQTT over websockets, and if you’re looking to use this protocol in you device, then you need to choose one of many, many available implementations. In a coming article we’ll see this protocol in action between ESP32 and an MQTT online server.