by Ponlakshmi
MQTT Protocol (Message Queuing Telemetry Transport) is a TCP-based messaging protocol specifically designed for transferring telemetry data from edge devices to a central server. It follows a Publish/Subscribe model, enabling MQTT clients to efficiently send and receive data through a central MQTT broker. Since its invention in 1999, MQTT has become the most widely adopted protocol for IoT implementations due to its lightweight nature and reliability. On the other hand, MQTT-SN (Sensor Network) extends the protocol for edge or peripheral devices, allowing communication between devices and gateways over low-power connectivity mediums like Bluetooth. Despite its potential, MQTT-SN hasn’t gained widespread adoption like the core MQTT protocol. While many MQTT implementations are readily available in the market, having a deeper understanding of the underlying concepts is crucial. This knowledge empowers you to leverage these implementations effectively, enabling you to build high-performance, fault-tolerant IoT applications.
The publish-subscribe interaction between MQTT devices and the MQTT server is facilitated through a set of predefined messages. For simplicity, both outgoing and incoming messages follow the same standard. At a high level, MQTT protocol packets can be categorized into two types for better understanding
Beyond the MQTT Protocol packets, there are a few other specifications that takes care of how to handle sessions, retaining the last message and the disconnections which will be covered as well in this article as it is very important to understand that for the MQTT Implementation.
Data Packets help transfer the actual data between the MQTT Broker and the MQTT Client. Publish and Subscribe are the main data packets where the MQTT client sends its intentions to listen to a topic and the server publishes the data based on the requirement. We want to add the Connect packet as well to this list as a set of data is being sent as part of it.
MQTT Packet Format structure for all the above three messages contains Fixed Header, Variable Header, and Payload.
Control packets are crucial for ensuring the success of data transfer in MQTT Protocol. A clear understanding of control packets and MQTT Quality of Service (QoS) levels is essential for effective implementation. While most control packets are managed at the core implementation layer depending on the MQTT client or server used, tasks like storing delivery states, handling acknowledgments, and resending messages need to be managed at the application level.
MQTT Packets can be broadly divided into three parts namely Fixed Header, Variable Header, and payload. If you are starting your implementation over a standard MQTT Clients, then this information may not be much needed. However, for understanding how to use the right APIs to use the client, you can have this hands-on. The fixed header field comprises the control flags; the variable header contains the packet length; the payload will be equal to the length set in the variable header. The minimum size of a packet length field is 1 byte, which is for messages less than 127 bytes.
The minimum packet size is 2 bytes, which has only the control field and a single packet length field, while the maximum packet size is 256 MB. Smaller packets less than 127 bytes have a 1-byte packet length field. The Packets greater than 127 and less than 16383 use 2 bytes, and so on. 7-bits that are used with the 8th bit is the continuation bit.
The 8-bit control field is the principal byte of the 2-byte fixed header. It is divided into two 4 bit fields and contains all protocol commands and responses. The first four most important bits are the command or message type field, while the remaining 4 bits are used as control flags.
While there are 16 possible flags, a limited set of bits are still used. The Publish message makes the most use of these flags.
The Remaining Length is the number of bytes left in the current packet, including variable header and payload data. The Remaining length does exclude the bytes used to encode the Remaining Length. The Remaining Length is encoded using a variable-length encoding scheme that uses one byte for values up to 127. The least seven important bits of each byte encode the data, and the most important bit is used to indicate there are following bytes in the representation. Thus, each byte encodes 128 values and one “continuation bit”. The greatest number of bytes in the remaining length field is four.
Some types of MQTT control packets have a variable header component. Variable-length header fields are not always present in MQTT messages. Some MQTT message types or commands require this field to carry additional control information. It remains between the Fixed Header and the Payload. The Variable Header will vary depending on the packet type.
As an example, let’s take a look at the details of the MQTT Client CONNECT message.
After establishing the TCP level connection with an MQTT Platform, the first packet must be a CONNECT packet. The CONNECT packet only needs to be sent once over the network connection. The second CONNECT packet sent by the MQTT client is ignored and disconnected.
The variable header sits next to the Fixed header and has four major parts as part of the header. They are the protocol name bytes, protocol level, connect flags, and keep-alive. Each of these parts has a predefined byte size and the order in which they are present.
These bytes store the Protocol name. The protocol name is stored as MQTT in 4 bytes. Any other characters in any of these fields will lead to disconnection of the client from the server.
This defines the protocol version. The protocol level for MQTT broker is 4 for the MQTT 3.1/3.1.1 and 5 for the MQTT 5 version. Sending other values will lead to disconnection. The MQTT Broker can also disconnect the client based on the version it supports.
This is a single byte field and represents the presence or absence of data in the payload for MQTT Authentication (username and password), Will message. The other fields like Will retain and clean session will be either true or false and the QoS field specifies the QoS level to be followed for WILL Message.
MQTT Keep alive is a 2 byte packet, and the maximum time you can set for the keep alive is 65535 seconds (18 Hours). However, it is better to keep it around 30 seconds or a minute based on your requirements. The MQTT client should send control packet (PINGREQ) at an interval that does not exceed the value of the defined Keep Alive. The Keep Alive value depends on the duration of transmission of the control packet by the client.
The payload contains the MQTT Client credentials (username, and password). The client ID must be unique for each client. The broker responds with a unique client ID for each client if the client does not specify a client ID. If you send a client ID in an empty field, the client will be rejected. The fields must be filled in the following order: Client ID, Will Topic, Will message, username, and password.
All the fields in the Connect packet should be in the string format. After establishing the TCP level connection, the client should send the MQTT Connect within a reasonable time. If the connect packet is not received, the MQTT Broker will disconnect the client. After successful validation, the broker will either respond with a CONNACK packet with zero payload or with the disconnection if there are some errors in connection. After successful connection, the broker will add the new client to the connected list, and the session will be maintained and monitored for the data packets as well as the keep alive.
If you are building from scratch, follow the Complete MQTT Client Developer Guide and the specifications to understand and implement it better.
For a very successful MQTT Application, Do read additional article beyond the MQTT Protocol.
Deploy Ready to use MQTT Applications
Secure MQTT Broker with in built dashboards - On premise & Cloud