MQTT provides 3 QOS levels- QOS 0,1,2.
These QOS levels refer to the connection between a broker and a client.
In this two part tutorial we will look in detail at the message flow when publishing using all three QOS levels.
QOS 0 – Only Once
This is the fastest method and requires only 1 message. It is also the most unreliable transfer mode.
The message is not stored on the sender, and is not acknowledged.
The message will be delivered only once, or not at all.
Once the message has been sent by the client it is deleted from the outbound message queue.
Therefore with this QOS level there is no possibity of duplicate messages.
QOS 1 – At Least Once
This level guarantees that the message will be delivered at least once, but may be delivered more than once. (See Flow Diagram on right.)
Publishing with QOS of 1 requires 2 messages.
The sender sends a message and waits for an acknowledgement (PUBACK).
If it receives an acknowledgement then it notifies the client app, and deletes the message from the outbound queue..
If it doesn’t receive an acknowledgement it will resend the message with the DUP flag set.
The message will continue to be resent at regular intervals, until the sender receives an acknowledgement.
Therefore subscribers can receive the same message multiple times.
QOS 1 Example
For this example I have created a Python script to publish messages with a QOS of 1.
I have also hacked the Python Client Class so that I can suppress reception of the PUBACK message to simulate a network failure.
In addition I have a monitor subscribed to the topics that I’m publishing on, so I can see all published messages.
The example tries to illustrate:
- Message Flow for QOS 0 and QOS 1 Messages
- Normal QOS level 0 publish
- Normal QOS 1 publish and message deletion
- How Unacknowledged messages are handled
- Message re-sending on failure
- Duplicate Flag usage
- Message storage on Client in case of disconnection
- Duplicate messages with QOS level 1
To start we do a simple publish with QOS=1 and observe the PUBACK being received, the message being marked as delivered, and removed from the outbound message queue.
Then we simulate a network problem by blocking PUBACK message. Now you should notice that the message remains stuck in the outbound message queue.
Now we publish two more messages the first with QOS of 0. This message doesn’t have a PUBACK and is removed from the message queue once sent.The second message is sent with a QOS of 1 and remains stuck in the outbound queue even though it has been sent .
Now the client attempts to resend the message held in the queue (MID=2). Notice the Duplicate flag is now set.
Now will simulate a dropped connection by doing a disconnect and reconnect. You can see that the messages (m2 and m4) are still in the queue, and the client re-sends the messages with the duplicate flag set.
Now we change the setting to let the PUBACK messages come through.
After a short time the client republishes the messages again, but this time the PUBACK is received OK, and the messages finally get removed from the outbound queue.
Here is what is seen on the monitor notice the duplicate messages.
In Part 2 we look in detail at publishing using QOS 2.
Related Tutorials and Resources:
- Introduction to the Paho Python MQTT client
- MQTT Publish-Python MQTT Client Examples
- MQTT Subscribe-Python MQTT Client Examples
- Understanding MQTT Topics