MQTT essentials – Publishing messages

Editor’s Note: The MQTT lightweight messaging protocol is a fundamental part of the technical foundation of most IoT applications and their underlying services. Taken from the book, MQTT Essentials – A Lightweight IoT Protocol by Gastón C. Hillar, this series of articles walks developers through MQTT fundamentals and shows how to get started with this essential protocol.

In this installment of the series, the author shows how developers can generate MQTT messages and publish them to an MQTT topic. 

Adapted from MQTT Essentials – A Lightweight IoT Protocol, by Gastón C. Hillar.


Chapter 1. Lightweight Messaging with MQTT 3.1.1 and Mosquitto (Continued)
By Gastón C. Hillar

For the previous installments in this series, see:

  1. MQTT essentials – Scenarios and the pub-sub pattern 
  2. MQTT essentials – Clients, servers, and connections 
  3. MQTT essentials – Subscribing to topics 

Publishing messages

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. 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/drone01/altitude -m  "10 f" -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/drone01/altitude. We specify the payload for the message after the -m option: “10 f“. We specify the version of the MQTT protocol that we want to use when the client establishes the connection with -V mqttv311. This way, we indicate the MQTT server that we want to use MQTT version 3.1.1. We specify the -d option to enable debug messages that will allow us to understand what happens under the hoods.

We will analyze additional options for the connection and the publication later.

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/5303-Gastons-Ma. After publishing the message, the client disconnects.

Client mosqpub/5308-Gastons-Ma sending CONNECT 
Client mosqpub/5308-Gastons-Ma received CONNACK
Client mosqpub/5308-Gastons-Ma sending PUBLISH (d0, q0, r0, m1, 'drones/altitude',... (5 bytes))
Client mosqpub/5308-Gastons-Ma sending DISCONNECT

Now, we will use the MQTT.fx GUI utility to generate another MQTT client that publishes another message to the same topic, sensors/drone01/altitude. Follow the next steps:

  1. Go to the MQTT.fx window in which you established a connection and subscribed to a
  2. Click Publish and enter sensors/drone01/altitude in the dropdown at the left-hand side of the Publish button.
  3. Enter the following text in the textbox below the Publish button: 20 f, as shown in the following screenshot:

  1. Then, click the Publish button. MQTT.fx will publish the entered text to the specified topic.

In case you don’t want to work with the MQTT.fx utility, you can run another mosquitto_pub command to generate another MQTT client that publishes a message to the topic. You just need to open another Terminal in macOS or Linux, or another Command Prompt in Windows, go to the directory in which Mosquitto is installed and run the following command.

mosquitto_pub -V mqttv311 -t sensors/drone01/altitude -m "20 f"

Now, go back to the Terminal or Command Prompt window in which you executed the mosquitto_sub command and subscribed to the sensors/drone01/atitude topic. You will see lines similar to the following ones:

Client mosqsub/5532-Gastons-Ma received PUBLISH (d0, q0, r0, m0, 'sensors/drone01/altitude',... (4 bytes))
10 f
Client mosqsub/5532-Gastons-Ma received PUBLISH (d0, q0, r0, m0, 'sensors/drone01/altitude',... (4 bytes))
20 f

If we clean up the debug messages that start with the Client prefix, we will see just the next two lines. These lines show the payloads for the two messages that we received as a result of our subscription to the sensors/drone01/altitude topic.

10 f
20 f

Go to the MQTT.fx window and click Subscribe. You will see 2at the right-hand side of the title for the topic filter used to subscribe in the panel located at the left-hand side of the window. MQTT.fx is telling you that you have received two messages in the sensors/drone01/altitude topic. Click on this panel and MQTT.fx will display all the received messages at the right-hand side of the panel. MQTT.fx will display a number at the right-hand side of each message to specify the message number since we started the subscription to the topic filter. Click on each message and MQTT.fx will display the QoS level for the message (0), the date and time that it was received and the payload for the message in the default plain string format. The following picture shows the payload for the second message that has been received by the subscriber generated by MQTT.fx.

We created two publishers and each of them published a message to the same topic: sensors/drone01/altitude. The two subscribers for this topic received both messages. Now, we will understand what happens under the hoods when a client publishes a message to a topic.

The MQTT client that has already established a connection sends a PUBLISH packet to the MQTT server with a header that includes the following fields and flags. We want to understand the meaning of these fields and flags because we will be able to specify some of their values when we work with MQTT tools and MQTT client libraries.

  • PacketId: If the QoS level is equal to 0, the value for this field will be 0 or it won’t be present. In case the QoS level is equal to 1 or 2, the packet identifier will have a number value to identify the packet and make it possible to identify the responses related to this packet.
  • Dup: If the QoS level is equal to 0, the value for this field will be 0. In case the QoS level is equal to 1 or 2, the MQTT client library or the MQTT server can resend a message that was previously published by the client when the subscribers haven’t ackowledged the first message. Whenever there is an attempt to resend a message that has already been published, the value for the Dup flag must be 1 or true.
  • QoS: Specifies the QoS level for the message. We will dive deep on the quality of service level for the messages and their relationship with many other flags later. So far, we have been working with QoS level 0.
  • Retain: If the value for this flag is set to 1 or true, the MQTT server will store the message with its specified QoS level. Whenever new MQTT clients subscribers to a topic filter that matches the topic for the stored or retained message, the last stored message for this topic will be sent to the new subscriber. If the value for this flag is set to 0 or false, the MQTT server won’t store the message and won’t replace a retained message with the same topic in case there is one message retained for this topic.
  • TopicName: A string with the topic name to which the message must be published. Topic names have a hierarchy structure where slashes (/) are used as delimiters. In our examples, the value for TopicName was “sensors/drone01/altitude“. We will analyze best practices for topic names later.
The payload contains the actual message that the MQTT client wants the MQTT server to publish. MQTT is data agnostic, and therefore, we can send any binary data and we don’t have restrictions such as those imposed by JSON or XML. Of course, we can use these or others to organize the payloads if we wish. In our examples, we sent a string that included a number that represented the altitude followed by a space and an “f” that indicates the unit of measure is feet.

The MQTT server will read a valid PUBLISH packet and it will respond with a packet only for QoS levels greater than 0. In case the QoS level is 0, the MQTT will not respond. The MQTT server will determine all the subscribers whose subscribed topic matches the topic name specified for the message and the server will publish the message to these clients.

The following diagram shows the interaction between an MQTT client and an MQTT server to publish a message with a QoS level of 0.

The other QoS levels have a different flow with additional interaction between the publisher and the MQTT server and increased overheads that we will analyze later.

Unsubscribing from topics

Whenever we don’t want a subscriber to receive more messages whose destination topic name matches one or more topic filters, the subscriber can send a request to unsubscribe to a list of topic filters to the MQTT server. Obviously, unsubscribing from topic filters is the opposite operation of subscribing to topic filters. We will use the MQTT.fx GUI utility to unsubscribe the MQTT client from the sensors/drone01/altitude topic. Follow the next steps:

  1. Go to the MQTT.fx window in which you established a connection and subscribed to a topic.
  2. Click Subscribe.
  1. Click on the panel that displays the sensors/drone01/altitude topic name at the left-hand side of the window. Then, click on the Unsubscribebutton located in this panel. The following screenshot shows this

  1. fx will unsubscribe the client from the sensors/drone01/altitude topic, and therefore, the client won’t receive any new message published to the sensors/drone01/altitude topic.

Now, we will use the MQTT.fx GUI utility to use the MQTT client to publish another message to the sensors/drone01/altitude topic. Follow the next steps:

  1. Go to the MQTT.fx window in which you established a connection and subscribed to a topic.
  2. Click Publish and enter sensors/drone01/altitude in the dropdown at the left-hand side of the Publish button.
  3. Then, click the Publish button. MQTT.fx will publish the entered text to the specified topic.
  4. Enter the following text in the textbox below the Publish button: 30 f, as shown in the following screenshot:

In case you don’t want to work with the MQTT.fx utility, you can run a mosquitto_pub command to generate another MQTT client that publishes a message to the topic. You just need to open another Terminal in macOS or Linux, or another Command Prompt in Windows, go to the directory in which Mosquitto is installed and run the following command.

mosquitto_pub -V mqttv311 -t sensors/drone01/altitude -m "30 f"

Now, go back to the MQTT.fx window and click Subscribe. The client has unsubscribed from the sensors/drone01/altitude topic before we published a new message to this topic, and therefore, this published message isn’t displayed.

Go back to the Terminal or Command Prompt window in which you executed the mosquitto_sub command and subscribed to the sensors/drone01/atitude topic. You will see lines similar to the following ones:

Client mosqsub/5532-Gastons-Ma received PUBLISH (d0, q0, r0, m0, 'sensors/drone01/altitude',... (4 bytes))
30 f

This client is still subscribed to the sensors/drone01/altitude topic, and therefore, it received the message with the payload of “30 f“.

The MQTT client sends an UNSUBSCRIBE packet to the MQTT server with a packet identifier (PacketId) in the header and one or more topic filters in the payload. The main difference with a SUBSCRIBE packet is that it isn’t necessary to include the QoS level for each topic filter because the MQTT client just wants to unsubscribe.

After an MQTT client unsubscribes from one or more topic filters, the MQTTserver still keeps the connection opened and the subscriptions to the topic filters that don’t match the topic filters specified in the UNSUBSCRIBE packet payload will continue working.

Hence, a single UNSUBSCRIBE packet can request the MQTT server to unsubscribe a client from many topics. The UNSUBSCRIBE packet must include at least one topic filter in the payload to comply with the protocol.

In the previous example in which we requested the MQTT server to unsubscribe, we used a specific topic name as the value for the topic filter, and therefore, we requested the MQTT server to unsubscribe from a single topic. As previously mentioned, we will learn about the usage of wildcards in topic filters later.

The packet identifier will have a number value to identify the packet and make it possible to identify the response related to this UNSUBSCRIBE packet. The MQTT server will process a valid UNSUBSCRIBE packet and it will respond with an UNSUBACK packet that indicates the unsubscribe acknowledgement and confirms the receipt and processing of the UNSUBSCRIBE packet. The UNSUBACK packet will include the same packet identifier (PacketId) in the header that was received in the UNSUBSCRIBE packet.

The MQTT will remove any topic filter that matches exactly any of the specified topic filters in the UNSUBSCRIBE packet’s payload for the specific client that sent the packet. The topic filter match must be exact to be deleted. After the MQTT server deletes a topic filter from the subscription list for the client, the server stops adding new messages to be published to the client. Only messages that have already started delivery to the client with QoS levels of 1 or 2 will be published to the client. In addition, the server might publish existing messages that have been buffered for their distribution to the subscriber.

The following diagram shows the interaction between an MQTT client and an MQTT server to unsubscribe from one or many topic filters.


Gastón C. Hillar has a bachelor’s degree in computer science (graduated with honors), and an MBA (graduated with an outstanding thesis). At present, Gastón is an independent IT consultant and freelance author who is always looking for new adventures around the world. He has been a senior contributing editor at Dr. Dobb’s and has written more than a hundred articles on software development topics. Gastón was also a former Microsoft MVP in technical computing. He has received the prestigious Intel Black Belt Software Developer award eight times. Gastón’s blog is http://csharpmulticore.blogspot.com.

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.