MQTT Programming
The Raspberry Pi, developed by the Raspberry Pi Foundation in the UK, is a microcomputer motherboard based on ARM architecture. This motherboard provides USB and Ethernet interfaces, allowing for the connection of keyboards, mice, and network cables. It has the basic functions of a PC, while also integrating Wi-Fi, Bluetooth, and a large number of GPIOs, making it widely used in education, home entertainment, IoT, and more.
MQTT is a lightweight IoT messaging protocol based on a publish/subscribe model, providing real-time and reliable messaging services for connected devices with minimal code and bandwidth. It is suitable for devices with limited hardware resources and networks with limited bandwidth. Therefore, the MQTT protocol is widely used in industries such as IoT, mobile internet, smart hardware, vehicle networking, and power energy.
In this project, we will develop a simple MQTT client using Python on the Raspberry Pi, implementing functions such as connecting to the MQTT server, subscribing, unsubscribing, and sending/receiving messages.
Environment Setup
Installing Python3
This project uses Python3 for development. Generally, the Raspberry Pi system comes with Python3 pre-installed. If you are unsure whether it is installed, you can use the following command to check.
python3 --version
If it shows Python 3.x.x (where x is a number), then it is installed. Otherwise, please use the apt command to install it (or follow the Python3 installation guide).
sudo apt install python3
Installing MQTT Client Library
To easily connect to the MQTT server, we need to install the paho-mqtt
library. You can choose one of the following two methods to install it.
Using Source Installation
git clone https://github.com/eclipse/paho.mqtt.python
cd paho.mqtt.python
python3 setup.py install
Using pip3 Installation
pip3 install paho-mqtt
Using MQTT
Connecting to MQTT Server
This article will use the free public MQTT server provided by EMQX, which is based on EMQX’s MQTT IoT cloud platform. The server connection information is as follows:
-
Broker: broker.emqx.io
-
TCP Port: 1883
-
Websocket Port: 8083
If needed, you can also quickly install the EMQX server locally using Docker.
docker run -d --name emqx -p 1883:1883 -p 8083:8083 -p 8084:8084 -p 18083:18083 emqx/emqx
Connection Example Code
# test_connect.py
import paho.mqtt.client as mqtt
# Callback function. This function is triggered when trying to connect to the MQTT broker.
# client is the client instance for this connection.
# userdata is user information, generally empty. But if needed, it can be set through the user_data_set function.
# flags stores the dictionary of server response flags.
# rc is the response code.
# Generally, we only need to focus on whether the rc response code is 0.
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected success")
else:
print(f"Connected fail with code {rc}")
client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)
client.loop_forever()
Save the above code as test_connect.py and run it.
python3 test_connect.py
In the on_connect function, we check the response code. If it is 0, we output Connected success
indicating a successful connection. If it returns another number, we need to refer to the response codes below.
0: Connection successful 1: Connection failed - incorrect protocol version 2: Connection failed - invalid client identifier 3: Connection failed - server unavailable 4: Connection failed - incorrect username or password 5: Connection failed - unauthorized 6-255: Undefined If there are other issues, you can check the network situation or confirm whether the `paho-mqtt` is installed.
In the concept of the MQTT protocol, messages are transmitted through topics. For example, if device A sends a message to topic T, only devices subscribed to topic T can receive it. Therefore, simply connecting to the MQTT server does not hold much significance. To fully utilize the MQTT service, we also need to know how to subscribe and publish messages.
Subscribing to Messages
Open any editor, enter the following code, and save it as subscriber.py:
# subscriber.py
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
# Subscribe, needs to be placed in on_connect
# If the connection to the broker is lost and reconnects, it will still continue to subscribe to the raspberry/topic topic
client.subscribe("raspberry/topic")
# Callback function, triggered when a message is received
def on_message(client, userdata, msg):
print(f"{msg.topic} {msg.payload}")
client = mqtt.Client()
client.on_connect = on_connect
client.on_message = on_message
# Set the will message, when the Raspberry Pi loses power or the network is interrupted, send the will message to other clients
client.will_set('raspberry/status', b'{"status": "Off"}')
# Create connection, the three parameters are the broker address, broker port number, and keep-alive time
client.connect("broker.emqx.io", 1883, 60)
# Set the network loop to block, it will not actively end the program before calling disconnect() or crashing
client.loop_forever()
Calling the subscribe()
function allows the Raspberry Pi to subscribe to a topic. In the above code, we used it to subscribe to the raspberry/topic
topic and listen for messages.
Additionally, we also used will_set()
to set the will message. The will message is a feature of MQTT, which sends a message to a specific topic when the device unexpectedly disconnects from the network. Through this feature, we can know whether the Raspberry Pi has lost power or encountered network issues.
Publishing Messages
Open any editor, enter the following code, and save it as publisher.py:
import paho.mqtt.client as mqtt
import time
def on_connect(client, userdata, flags, rc):
print(f"Connected with result code {rc}")
client = mqtt.Client()
client.on_connect = on_connect
client.connect("broker.emqx.io", 1883, 60)
# Every 1 second, send a message to raspberry/topic, sending a total of 5 times
for i in range(5):
# The four parameters are: topic, payload, QoS, whether to retain the message
client.publish('raspberry/topic', payload=i, qos=0, retain=False)
print(f"send {i} to raspberry/topic")
time.sleep(1)
client.loop_forever()
Calling the publish()
function allows sending messages to a topic. In the above code, we used it to send messages to the raspberry/topic
topic. The parameter QoS is another MQTT feature. If you want to learn more about QoS, you can check the MQTT QoS (Quality of Service) introduction; for now, we will set it to 0.
Testing
We will use the MQTT 5.0 client tool – MQTTX for the following tests.
Testing Subscription Messages
Run the Python code and actively send a message.
-
Open the terminal and run the Python code to listen for messages.
python3 subscriber.py
-
Use the MQTTX client to connect to the MQTT server and send a message to the topic
raspberry/topic
. -
Check the Raspberry Pi terminal information to see that the message published by MQTTX has been successfully received.
Testing Publishing Messages
-
In the MQTTX client, subscribe to the
raspberry/topic
topic. -
Run the Python code in the terminal.
-
In the MQTTX client, check the messages sent by the Raspberry Pi.
Testing Will Messages
Next, let’s test whether the will message is set successfully.
-
In the MQTTX client, subscribe to
raspberry/status
. -
Interrupt the program or disconnect the Raspberry Pi’s network.
-
In the MQTTX client, check the messages received in the
raspberry/status
topic.
Summary
We have completed the testing client using the Python MQTT client library paho-mqtt
on the Raspberry Pi, implementing functions such as connecting to the MQTT server, subscribing, unsubscribing, and sending/receiving messages.
By now, you have learned how to simply use the MQTT service. Although this is just a small part of the MQTT service, it is sufficient to accomplish many interesting tasks, such as:
-
Sending MQTT messages from a mobile phone to remotely control the Raspberry Pi.
-
Regularly sending the Raspberry Pi’s device information to the MQTT server and receiving messages on the mobile phone for 24/7 monitoring.
-
Connecting the Raspberry Pi to the MQTT server and creating many interesting IoT applications with various sensors and ESP modules.