The MQTT protocol has historically been tailored for low-powered machine-to-machine (M2M) communications for the Broker/Server Publish-Subscribe model. A Broker/Server handles a queue of topics which machines can submit/post and subscribe to. The history of the MQTT protocol goes back to work in 1999 by Andy Stanford-Clark (IBM) and Arlen Nipper (then working for Eurotech, Inc.) – early architects of Pervasive Computing paradigms.
Why use MQTT? MQTT is low bandwidth and extremely efficient. If you have projects where you may have multiple machines which need to talk to one another, then Publish-Subscribe models may be a good option for common communications buses. Obviously the form factor doesn’t matter too much in these modern times as the principles may apply to all computing cluster sizes. You can have multiple producers presenting data to multiple consumers along the broker.
Each message is comprised of the following blocks:
Control Header | Packet Length | Variable length | Payload |
1 byte | 1 to 4 bytes | 0-y bytes | 0-x bytes |
Message Type (4) DUP (1) QoS (2) Retain (1) |
In the remainder of this post we’ll get setup with MQTT on Ubuntu and start using Python (version 3) programs to publish and subscribe data for a basic topic. For this project I’ll assume you have several Raspberry Pis with Ubuntu Server 20+ installed on them. We’ll be setting up MQTT without security credentials – it is suggested that you add security to your topics.
To install the MQTT Broker/Server on your relevant host/node, in Ubuntu, you’ll need to run the following commands:
# On Linux Terminal / Console
> sudo apt-get update && sudo apt-get upgrade
> sudo apt-get install mosquitto
> sudo apt-get install mosquitto-clients
# Check the service is running
> sudo systemctl status mosquitto
# Optional:
# Stop the service
> sudo systemctl stop mosquitto
# Start the service
> sudo systemctl start mosquitto
With the Mosquitto MQTT Brokers/Server now installed – the service should be running. By default the configuration of the MQTT Server will be blocking anonymous connections (i.e. anonymous topic creations and subscriptions). We need to modify the configuration slightly:
# edit the configuration
> sudo vi /etc/mosquitto/mosquitto.conf
# Option 1: add the following lines
allow_anonymous true
listener 1883
# Option 2: add for MQTT Server to listen to all interfaces on port 1883
allow_anonymous true
listener 1883 0.0.0.0
# write and close the file
# restart the service
> sudo systemctl start mosquitto
The Broker should now be configured and running correctly. To monitor and interact with the Broker manually I can suggest installing and using MQTTX. MQTTX acts as an explorer and GUI tool for submitting and receiving MQTT messages. Its a good means by which to test a setup manually.
Our next stage in development is the usage of a simple Publisher and Subscriber written in Python. The example code have the publisher select a number between 0 and 100 – construct a JSON string payload and publish that payload to the Broker. The Subscriber will listen for the topic announcement and print the payload locally. The code for both are below – we assume that the MQTT Broker is running on the IP/host 192.168.0.10.
# assuming you've installed Python 3 and PIP package manger
> pip3 install paho.mqtt
# publisher.py
import paho.mqtt.client as mqtt
import time
import random
import json
mqttBroker ="192.168.0.10"
client = mqtt.Client("Wheel of fortune")
client.connect(mqttBroker)
count = 1
while True:
randNumber = random.randint(0,100)
topic = "public/number"
j = {'count': count, 'payload': str(randNumber)}
client.publish(topic, json.dumps(j))
print(f"Just published {str(count)} to topic: {topic}")
time.sleep(1)
count = count + 1
# subscriber.py
import json
import paho.mqtt.client as mqtt
# callback handler
def handle_message(client, userdata, message):
payload = json.loads(str(message.payload.decode("utf-8")))
print(f"received message: {json.dumps(payload, indent=4)}")
mqttBroker ="192.168.0.10"
topic = "public/number"
client = mqtt.Client("Watcher")
client.connect(mqttBroker)
client.loop_start()
client.subscribe(topic)
client.on_message=handle_message
while True:
continue
Executing the publisher.py and subscriber.py code will generate a series of messages in the MQTT topic queue.
publisher.py | subscriber.py |
Just published 1391 to topic: public/number Just published 1392 to topic: public/number Just published 1393 to topic: public/number Just published 1394 to topic: public/number | received message: { “count”: 1391, “payload”: “90” } received message: { “count”: 1392, “payload”: “82” } received message: { “count”: 1393, “payload”: “71” } received message: { “count”: 1394, “payload”: “33” } |
The following has shown the basic creation of a publish-subscribe MQTT application with JSON payloads. This should code should help create a basic framework.