Lab-46: MQTT protocol

1.0 Introduction

MQTT stands from Message Queue Telemetry Transport. MQTT is a publish/subscribe messaging transport protocol. It is a lightweight, open, simple, and designed so as to be easy to implement. These characteristics make it ideal for use in many situations, including constrained environments such as for communication in Machine to Machine (M2M) and Internet of Things (IoT) contexts where a small code footprint is required and/or network bandwidth is at a premium. The protocol runs over TCP/IP, or over other network protocols that provide ordered, lossless, bidirectional connections.

You can find MQTT standard here

2.0 How does MQTT work

MQTT is a relatively simple protocol, it works on publish and subscribe  paradigm. A client publishes topics to broker and broker forwards  message to all clients who subscribed for that topic. If no client subscribed to topic broker discards the message. A topic is a subject of interest for example a temperature sensor publishes temperature reading in a temperature topic.

A subscriber can subscribe to multiple topics and multiple subscribers can subscriber to a topic.

In the below picture we have a publisher client (Temp sensor) which publishes temperature topic to broker and two clients (Client-1 & Client-2) which subscribed to temperature topic. Broker simply pushes messages from temp sensor to client-1 & client-2. Broker job is to relay message from publisher client to subscriber client

mqtt_15

3.0 Key concepts of MQTT

These are the main concepts of MQTT

Broker: The broker accepts messages from clients and then delivers them to any interested clients. Messages belong to a topic. (Sometimes brokers are called “servers.”)

Broker or Server is a program or device that acts as an intermediary between Clients which publish Application Messages and Clients which have made Subscriptions. A Server:

– Accepts Network Connections from Clients.
– Accepts Application Messages published by Clients.

– Processes Subscribe and Unsubscribe requests from Clients.
– Forwards Application Messages that match Client Subscriptions

Client: A “device” that either publishes a message to a topic, subscribes to a topic, or both.

Client is a program or device that uses MQTT. A Client always establishes the Network Connection to the Server or broker. It can:

-Publish Application Messages that other Clients might be interested in.

– Subscribe to request Application Messages that it is interested in receiving.
– Unsubscribe to remove a request for Application Messages.
– Disconnect from the Server.

Topic: A namespace (or place) for messages on the broker. Clients subscribe and publish to a topic.

Publish: A client sending a message to the broker, using a topic name.

Subscribe: A client tells the broker which topics interest it. Once subscribed, the broker sends messages published to that topic. (In some configurations the broker sends “missed” messages.) A client can subscribe to multiple topics.

Unsubscribe: Tell the broker you are bored with this topic. In other words, the broker will stop sending messages on this topic.

4.0 QOS (Quality of service)

MQTT QOS is part of fixed header, bits 1 & 2. MQTT supports three types of quality of service QOS 0, QOS 1 and QOS 2.

QOS is implemented between sender and receiver. A sender can be a client which is publishing a topic or it can be a broker. A receiver can be a broker or client subscribed to a topic. So the end to end QOS between a publishing client and subscribing client can be broken down into two segments 1) between publishing client and broker and 2) between broker and subscribing client. Both segments are independent so segment 1 can be QOS 1 and segment 2 can be QOS 0.

mqtt_9

QOS 0: At most one delivery

QOS 0 is a best effort delivery. In this QOS receiver doesn’t acknowledge sender message. As soon as receiver receives message it delivers it onward. This QOS has lowest overhead

mqtt_10

mqtt_qos0

QOS 1: At least once delivery

This quality of service ensures that the message arrives at the receiver at least once. A QOS 1 PUBLISH Packet has a Packet Identifier in its variable header and is acknowledged by receiver using PUBACK message

If no acknowledgement received by sender it waits for certain time and then retransmit message with DUP flag =1. So in this QOS a subscribing client can receive duplicate message

mqtt_11

mqtt_qos1

QOS 2: Exactly once delivery

This is the highest quality of service, for use when neither loss nor duplication of messages are acceptable. There is an increased overhead associated with this quality of service.

This QOS guarantee that message received only once. It employs two step acknowledgement process and receiver doesn’t deliver message onwards until bidirectional acknowledgement completedmqtt_14

As can be seen from picture below only one message delivered to Client-1

mqtt_qos2

5.0 Wildcards

What if you need to subscribe to multiple topics it is not efficient to generate subscription message for each topic. MQTT support wildcards to subscribe multiple topics. There are two types of wildcards

  • Single level wildcard

The plus sign (‘+’ U+002B) is a wildcard character that matches only one topic level. For example, “sport/tennis/+” matches “sport/tennis/player1” and “sport/tennis/player2”, but not  “sport/tennis/player1/ranking”.

  • Multi-level wildcard

The hash sign (‘#’) is a wildcard character that matches multiple topic level. For example, “sport/#” matches “sport/tennis/player1” and “sport/tennis/player2

6.0 MQTT Packets

MQTT runs over TCP transport layer on port 1883. MQTT Control Packet consists of three parts, always in the following order as illustrated, 1) Fixed header 2) Variable header 3) Payload

mqtt_6

Fixed Header

Each MQTT Control Packet contains a fixed header. Fixed header is divided into MQTT control packet type and flags associated with control packet

mqtt_1

Control Packet type

Control Packet type represented by 4 bits in first byte. These are the MQTT Control Packet types

mqtt_2

mqtt_3

Flags

The remaining bits [3-0] of byte 1 in the fixed header contain flags specific to each MQTT Control Packet. As you can see QoS is applicable to PUBLISH packets only

mqtt_4

mqtt_5

Remaining Length

The Remaining Length is the number of bytes remaining within the current packet, including data in the variable header and the payload

Variable Header

Some types of MQTT Control Packets contain a variable header component. It resides between the fixed header and the payload. The content of the variable header varies depending on the Packet type. Packet Identifier field of variable header is common in several packet types

Variable header contains packet identifier

mqtt_7

The variable header component of many of the Control Packet types includes a 2 byte Packet Identifier field. These Control Packets are PUBLISH (where QoS > 0), PUBACK, PUBREC, PUBREL, PUBCOMP, SUBSCRIBE, SUBACK, UNSUBSCRIBE, UNSUBACK

Payload

Some MQTT Control Packets contain a payload as the final part of the packet. In the case of the PUBLISH packet this is the Application Message.

Control Packets that require a Payload

mqtt_8

7.0 RETAIN and Last Will

RETAIN and Last Will are important concept in MQTT. Let’s take a closer look at them

RETAIN

RETAIN flag is associated with PUBLISH packet. If the RETAIN flag is set to 1, in a PUBLISH Packet sent by a Client to a Server, the Server MUST store the Application Message and its QoS, so that it can be delivered to future subscribers whose subscriptions match its topic name. When a new subscription is established, the last retained message, if any, on each matching topic name MUST be sent to the subscriber. If the Server receives a QoS 0 message with the RETAIN flag set to 1 it MUST discard any message previously retained for that topic.

Suppose you have a client which publishes temp every 1/2 hr with RETAIN flag set to 0. If a subscriber subscribe to temp topic it needs to wait for next cycle when client publishes the temp. But if client publishes with RETAIN flag set to 1 then broker stores the last temp message and as soon as new subscriber subscribe to temp topic broker delivers the last stored message

mqtt_17

Last Will

Last Will in MQTT  is used to notify other clients about an ungraceful disconnect of a client. If a client disconnects abruptly then broker notifies to all clients by sending Last Will.

Last Will by a client is specified when client first sends CONNECT message to broker. Below is an example of CONNECT message with Last Will. In this example client set the Last Will topic ‘/plano/temp’ and Last Will message as ‘Temp sensor offline’. The reasoning behind this is when client abruptly disconnected may to due to battery dies or some hw failure broker will send the message ‘Temp sensor offline’ to all clients subscribed to topic ‘/plano/temp’. This info can be used to generate alert that a device went offline and need attention

If client disconnect gracefully using DISCONNECT message broker clears the Last Will

mqtt_18

Situations in which the Will Message is published include, but are not limited to:

  1. An I/O error or network failure detected by the Server.
  2. The Client fails to communicate within the Keep Alive time.
  3. The Client closes the Network Connection without first sending a DISCONNECT Packet.
  4. The Server closes the Network Connection because of a protocol error.

 

8.0 Keepalive

MQTT clients sends Control message to broker every Keepalive time interval. MQTT negotiate Keepalive time with broker in CONNECT message. Keepalive time measured in seconds.  If client doesn’t have Control message to send it can send PINGREQ message to broker just to keep the connection alive

If broker doesn’t receive any message from client for more than Keepalive interval it closes the network connect with client. If client doesn’t receive response to PINGREQ for more than reasonable time it closes connection with Server

A Keep Alive value of zero (0) has the effect of turning off the keep alive mechanism. This means that, in this case, the Server is not required to disconnect the Client on the grounds of inactivity

Below CONNECT message has Keepalive of 60 secs

mqtt_20

9.0 Demo of MQTT in Ubuntu

Let’s try out MQTT client & broker in Linux . I have Ubuntu 16.04 VM running in Virtual box

  • Install mosquitto broker and client

$sudo apt-get install mosquitto mosquitto-clients

  • Open two terminal windows. On one terminal publish topics for temperature and humidity

$mosquitto_pub -h localhost -t /plano/temperature -m “100 degree Celsius” $mosquitto_pub -h localhost -t /plano/humidity -m “50 percent”

  • On second terminal subscriber to topics. temperature and humidity reading displayed on terminal
$mosquitto_sub -h localhost -t /plano/#

There are many brokers available in public domain. Instead of local broker you can try iot.eclipse.org broker, replace localhost with iot.eclipse.org in above example

Example of RETAIN

Publish using RETAIN flag set -r.

$mosquitto_pub -h localhost -r -t /plano/temp -m "100 degree celsius"

Subscribe to topic /plano/temp and you will get the message retain by broker

$mosquitto_sub -h localhost -t /plano/temp

Example of Last Will

On first terminal run below command. This command will subscribe to topic /plano/temp  with Last Will

$mosquitto_sub -h localhost -t /plano/temp --will-topic /plano/temp --will-qos 1 --will-payload "Plano Temp sensor is offline" --will-retain

On second terminal run below command

$mosquitto_sub -h localhost -t /plano/temp

Now on first terminal enter ctrl+c to terminate program abruptly. A message ‘Plano Temp sensor is offline’ will be seen on second terminal

9.0 MQTT Python support

If you want to use MQTT programmatically then use paho MQTT library for Python. You can read more about Paho library here 

Install Paho Python library in Ubuntu 16.04

>pip install paho-mqtt

Paho is based on callback functions. Here is the summary of callback functions

mqtt_19

Below sample Python script to publish and subscribe. Code located here

https://github.com/sunnynetwork/mqtt

import paho.mqtt.client as mqtt
import time

# on_connect callback function called when CONNACK received from broker
def on_connect(client, userdata, flags, rc):
 print("Connected with result code"+ " " +str(rc))
 
# on_message callback function called when a PUBLISH message received from broker 
def on_message(client, userdata, message):
 print("'Received message ' "+ str(message.payload) + " ' on topic ' " + message.topic + "' with qos '" + str(message.qos))

#on_subscribe callback function called when SUBACK received from broker
def on_subscribe(client, userdata, mid, granted_qos):
 print("Subscribe_ack: " + str(mid) + " " + str(granted_qos))

# on_publish callback function called when PUBACK received from broker
def on_publish(client, userdata, mid):
 print("Publish_ack: " + str(mid))

broker_address = "iot.eclipse.org"
client = mqtt.Client("temp sensor")

# initialize callback functions
client.on_connect = on_connect
client.on_subscribe = on_subscribe
client.on_message = on_message
client.on_publish = on_publish

# connect with broker, default_port=1883, keepalive =60 sec 
client.connect(broker_address, 1883, 60)

# PUBLISH a topic to broker with qos=1, retain=True
client.publish("/plano/temperature/", "100 Degree Celsius", 1, True)
client.publish("/plano/humidity/", "70%", 1, True)
#print("Publish rc: " + str(rc))

# start loop
client.loop_start()
client.subscribe("/plano/#")
time.sleep(5)
client.loop_stop()

This is the result

Connected with result code 0
Publish_ack: 1
Publish_ack: 2
Subscribe_ack: 3 (0,)
'Received message ' 100 Degree Celsius ' on topic ' /plano/temperature/' with qos '0
'Received message ' 70% ' on topic ' /plano/humidity/' with qos '0

 

Resources

Beginners Guide To The MQTT Protocol

http://www.hivemq.com/mqtt-essentials/