Working with at least once delivery
First, we will use wildcards to subscribe to a topic filter with QoS level 1 and then we will publish one message to a topic name that will match the topic filter with QoS level 1. This way, we will analyze how both publishing and subscription work with QoS level 1.
We will use the mosquitto_sub
command-line utility included in Mosquitto to generate a simple MQTT client that subscribes to a topic filter with QoS level 1and prints all the messages it receives. Open a Terminal in macOS or Linux, or a Command Prompt in Windows, go to the directory in which Mosquitto is installed and run the following command:
mosquitto_sub -V mqttv311 -t sensors/+/altitude -q1 -d
The previous command will create an MQTT client that will establish a connection with the local MQTT server and then will make the client subscribe to the topic filter specified after the -t
option: sensors/+/altitude
. We specify that we want to use QoS level 1 to subscribe to the topic filter with the -q 1
option. We specify the -d
option to enable debug messages that will allow us to understand what happens under the hoods and the differences with publishing a message with QoS level 0.
The Terminal or Command Prompt window will display debug messages similar to the following lines. Take into account that the generated ClientId
will be different from the one shown after Client mosqsub/1795-Gastons-Ma
. Notice that QoS: 1
indicates that the subscription is done with QoS level 1.
Client mosqsub/1795-Gastons-Ma sending CONNECT Client mosqsub/1795-Gastons-Ma received CONNACK Client mosqsub/1795-Gastons-Ma sending SUBSCRIBE (Mid: 1, Topic: sensors/+/altitude, QoS: 1) Client mosqsub/1795-Gastons-Ma received SUBACK Subscribed (mid: 1): 1
We will use the mosquitto_pub
command-line utility included in Mosquitto to generate a simple MQTT client that publishes a message to a topic with QoS level 1 instead of the QoS level 0 that we used when we published messages before. Open a Terminal in macOS or Linux, or a Command Prompt in Windows, go to the directory in which Mosquitto is installed and run the following command:
mosquitto_pub -V mqttv311 -t sensors/drone02/altitude -m "65 f" -q 1 -d
The previous command will create an MQTT client that will establish a connection with the local MQTT server and then will make the client publish a message to the topic specified after the -t
option: sensors/drone02/altitude
. We specify the payload for the message after the -m
option:"65 f"
. We specify that we want to use QoS level 1 to publish the message with the -q 1
option. We specify the -d
option to enable debug messages that will allow us to understand what happens under the hoods and the differences with publishing a message with QoS level 0.
The Terminal or Command Prompt window will display debug messages similar to the following lines. Take into account that the generated ClientId
will be different from the one shown after Client
: mosqpub/1516-Gastons-Ma
. After publishing the message, the client disconnects.
Client mosqpub/1516-Gastons-Ma sending CONNECT Client mosqpub/1516-Gastons-Ma received CONNACK Client mosqpub/1516-Gastons-Ma sending PUBLISH (d0, q1, r0, m1, 'sensors/drone02/altitude', ... (4 bytes)) Client mosqpub/1516-Gastons-Ma received PUBACK (Mid: 1) Client mosqpub/1516-Gastons-Ma sending DISCONNECT
The previous lines show that the generated MQTT client sends a PUBLISH
packet to the MQTT server and then receives a PUBACK
package from the server.
Now, go back to the Terminal or Command Prompt window in which you executed the mosquitto_sub
command and subscribed to the sensors/+/atitude
topic filter. You will see lines similar to the following ones:
Client mosqsub/1795-Gastons-Ma received PUBLISH (d0, q1, r0, m1, 'sensors/drone02/altitude', ... (4 bytes)) Client mosqsub/1795-Gastons-Ma sending PUBACK (Mid: 1) 65 f
The previous lines show that the generated MQTT client, that is, the subscriber, received a PUBLISH
packet from the MQTT server and then sent a PUBACK
package to the server to acknowledge the message. If we clean up the debug messages that start with the Client
prefix, we will see just the last line that shows the payloads for the message that we received as a result of our subscription to the sensors/+/altitude
topic filter: 65 f
.
The MQTT client that has already established a connection, that is, the publisher, sends a PUBLISH
packet to the MQTT server with the header we have already described, QoS
set to 1
, and including a PacketId
numeric value that will be unique for this client. At this time, the publisher will consider the PUBLISH
packet identified with the PacketId
as an unacknowledged PUBLISH
packet.
The MQTT server reads a valid PUBLISH
packet and it will respond to the publisher with a PUBACK
packet with the same PacketId
value that has been used for the PUBLISH
packet. Once the publisher receives the PUBACK
packet, it discards the message and the MQTT server is responsible of publishing it to the appropriate subscribers.
The following diagram shows the interaction between a publisher and an MQTT server to publish a message with a QoS level of 1.
The MQTT server can start publishing messages to the appropriate subscribers before it sends the PUBACK
packet to the publisher. Hence, when the publisher receives the PUBACK
packet from the MQTT server, it doesn't mean that all the subscribers have received the message. It is very important to understand the meaning of this PUBACK
packet.
For each subscriber to which the message has to be published, the MQTT server will send a PUBLISH
packet and the subscriber must acknowledge the reception of the message by sending a PUBACK
packet to the MQTT server. The following diagram shows the interaction between an MQTT server and the subscribers when a message is published with a QoS level of 1.
If the application is able to tolerate duplicates and we have to make sure that the messages arrive at least once to the subscribers, QoS level 1 is an excellent choice. In case there is no way to handle duplicates, we have to use QoS level 2.