This post offers an introduction to the MQTT (Message Queuing Telemetry Transport) protocol [1] and also demonstrates its usage with an example in Python (Just for info: telemetry means the collection of measurement data from a remote location and its transmission wiki-link.
What is MQTT?
MQTT is a communication protocol which is actually developed for low-energy devices to transmit data with the low-bandwidth network.
It is a lightweight protocol built on the top of TCP/IP.
Lightweight: In software/programs, lightweight specify the characteristic of low memory and CPU usage.
MQTT allows simple and efficient data transmission from sensors to IoT (Internet of Things) networks. Additionally, it also enables the easy integration of new sensors to the IoT network.
MQTT Terminology
In MQTT, there are five main terminology
- Broker: It is the middleware between data sender (publisher) and data receiver (subscriber). You can consider it as a server which receives data from sender and forward it to the receiver.
- Publisher: In simple terms, you can think of a device which needs to send data to other parties. This device could be a sensor, laptop, and Raspberry pi board.
- Subscriber: It is the receiver of data sent by the publisher.
- Topic: Publisher and Subscriber do not know each other directly. When the publisher sends some data to Broker, it associates that data with a topic . The topic is a string in the format of hierarchy e.g. sensor/room-1/temprature (it is just an example) where ‘/’ is level separator and each string represents a level. You can define it as per your requirement. When the subscriber connects to the Broker, it specifies the topic in which it is interested in. Then, broker forward published messages to their corresponding subscribers on the basis of the topic. Here, you need to understand two operators + and #. Before jumping to these operators, let’s assume a scenario where we have four temperature sensors in four rooms. These sensors are sending their data with the following topics
- home/bedroom/temperature
- home/kitchen/temperature
- home/dining-room/temperature
-
home/study-room/temperature
Now, in order to receive data from all four rooms, subscribers need to subscribe to the above topics. One way of doing that is to subscribe to each topic separately. Another way is to use
Some examples+
operator and simply subscribe to the topichome\+\temprature
. + operator here matches any single level ( + is known as a single-level wildcard). Therefore, home+will match any topic with three-level hierarchy starting with home and ending with .
Coming to second operator#
which matches multiple levels in the topic. For instance,home\#
will match all the aforementioned four topics.
Let’s say we have multiple sensors which are transmitting data with following topics
school\class-1\group-1\audio
school\class-1\group-2\audio
school\class-2\group-1\audio
school\class-2\group-2\audio
Which topic to subscribe to receive all data from class-1 ? school\class-1\#
Which topic to subscribe to receive data from group-1? school\+\group-1\audio
Which topic to subscribe to receive data from entire school? school\#
#
operator can appear only once in a topic expression e.g. school## is invalid. A topic expression # matches every topic hence subscriber to this topic will receive every message.
- Message: It is simply the data which needs to be sent.
Demonstration of MQTT in Python
Now, we will see a python example of using MQTT protocol for transmitting data. We will use a python package [paho-mqtt](https://pypi.org/project/paho-mqtt/ “” target = ““_blank) for creating publisher and subcriber. You can install it using following command
pip install paho-mqtt
Next, we need to set up a Broker. There are numerous option of this. You can either use a cloud-based broker or you can install a broker on a server in your network. There are multiple cloud services are available with can be used ([Complete list of broker servers](https://github.com/mqtt/mqtt.github.io/wiki/servers “” target = ““_blank)). I would like to mention [MaqiaTTo](https://www.maqiatto.com “” target = ““_blank) which is a free cloud-based MQTT broker. It can be used for testing purpose. In this tutorial, however, we are going to set-up a broker in the network. We will use [Mosquitto](https://mosquitto.org/ “” target = ““_blank) broker server.
Setting up Mosquitto Broker
Mosquitto is an open-source MQTT message broker. Following are the instructions for installing it on your systems.
- Windows users: Download and install 64bit-version, 32bit-version(If you are not sure then install 32bit-version)
-
Ubuntu Users: Run following commands
sudo apt-add-repository ppa:mosquitto- dev/mosquitto-ppa sudo apt-get update
-
Mac Users: First install brew package manager using following command
/usr/bin/ruby \ -e ""$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)""
Next, install Mosquitto
brew install mosquitto
Starting Mosquitto Server
Now, we are going to start our MQTT broker.
Run the following command [Mac users]
/usr/local/sbin/mosquitto -c /usr/local/etc/mosquitto/mosquitto.conf
On ubuntu following command can be used to start or stop Mosquitto
sudo systemctl (start|stop) mosquitto
Writing Publisher and Subscriber codes
Now, we will develop our publisher and subscriber. Following are the steps for developing publisher and subscriber in Python.
- Create client
- Connect to broker
- Publish/subscribe message
- Connect callback function
- Run the loop
- Disconnect
Let’s understand these steps in details. The first step is to create a client. For this, we will create a Client
object from paho-MQTT
python package.
The second step connects to the broker. In our case, we are running the broker on the same machine, therefore, we specify the broker’s IP as 127.0.0.1
and port as 1883
(default port for Mosquitto broker).
In third step, you can publish or subcribe using publish() and subscribe() function.
Next, we need to write callback functions. It needs a bit of explanation. Callback functions are functions which are executed on the occurrence of particular events. Followings are the table showing the event and their corresponding callback function
Event | Callback Function |
Connection ACK | on_connect |
Dis-connection ACK | on_disconnect |
Publish ACK | on_publish |
Subcription ACK | on_subcribe |
Un-subcription ACK | on_unsubcribe |
Message received | on_message |
Let’s take one example to understand it. When a client connects to the broker, the broker sends an ACK (acknowledgment) to the client. This event triggers the execution of a callback function on_connect
.
Running a loop: Why we need to start a loop?
When a publisher sends messages to the broker or subscriber receive messages from the broker, these messages are first stored in the buffer. Now, in order to process all messages (either for sending or receiving), we need to write a loop manually. Thanks to paho-MQTT
, it provides three functions for the same purpose, therefore, we don’t need to write message processing loop. These functions are as following
- loop(): When you call this function, it will process any pending message sending or receiving action. This function waits for a particular time (you can specify using timeout parameter) for processing buffer for reading or sending a message. After, that its execution completes. Therefore, if you plan to use this function you need to call it regularly.
- loop_forever(): This function call results in indefinite execution of your program. This function automatically reconnects to the broker in case of disconnection. This function is blocking type function (you can understand it as an infinite for loop) and it returns when you disconnect with the broker.
- loop_start() & loop_stop(): loop_start() function starts a new background thread and that thread regularly execute loop() function. You can stop this background thread using loop_stop() function.
Coding Publisher
As we have setup our broker server, now we move towards writing publisher code.
import paho.mqtt.client as MQTT
# function
def connect_msg():
print('Connected to Broker')
# function
def publish_msg():
print('Message Published')
# Creating client
= mqtt.Client(client_id='publisher-1')
client
# Connecting callback functions
= connect_msg
client.on_connect = publish_msg
client.on_publish
# Connect to broker
connect(""127.0.0.1"",1883)
client.
# if you experience Socket error then replace above statement with following one
# client.connect(""127.0.0.1"",1883,60)
# Publish a message with topic
= client.publish(""house/light"",""on"")
ret
# Run a loop
client.loop()
The above code publishes a message on with topic house/light
. In this code, we have written two functions connect_msg and publish_msg (you can use any names for functions). We connected these functions to callback functions using client.on_connect = connect_msg . We specified that connect_msg function is callback function and it will be called when the Connection ACK event occurs (events and their callbacks are given in the above table). In this program, we used the loop function which process pending action (sending or receiving) and then returns.
Coding Subscriber
As we have our publisher with topic housetopic, we now develop our subscriber for the same topic.
import paho.mqtt.client as MQTT #import the client
# Function to process recieved message
def process_message(client, userdata, message):
print(""message received "" ,str(message.payload.decode(""utf-8"")))
print(""message topic="",message.topic)
print(""message qos="",message.qos)
print(""message retain flag="",message.retain)
# Create client
= mqtt.Client(client_id=""subscriber-1"")
client
# Assign callback function
= process_message
client.on_message
# Connect to broker
connect(broker_address,1883,60)
client.
# Subscriber to topic
""house/light"")
client.subscribe(
# Run loop
client.loop_forever()
Execution Results
References
- MQTT Version 5.0. Edited by Andrew Banks, Ed Briggs, Ken Borgendale, and Rahul Gupta. 07 March 2019. OASIS Standard. https://docs.oasis-open.org/mqtt/mqtt/v5.0/os/mqtt-v5.0-os.html. Latest version: https://docs.oasis-open.org/mqtt/mqtt/v5.0/mqtt-v5.0.html.
”