Worksheet 5 - Experimenting with Mosquitto and MQTT using Python
Set up Virtual Environment for Python
Setting up Python programs in a virtual environment is a good practice, especially when working with Mosquitto and MQTT libraries like paho-mqtt. It ensures that your project dependencies remain isolated and don't conflict with other projects or system-wide packages.
Install virtualenv (if not already installed):
sudo apt install python3-venv
Create a Virtual Environment:
Navigate to your project directory and create a virtual environment:
python3 -m venv my_mqtt_env
Activate the Virtual Environment:
To start using the virtual environment, activate it:
source my_mqtt_env/bin/activate
Once activated, your shell prompt will change, indicating that you're now working inside the virtual environment.
Why Use a Virtual Environment?
- Isolation: Keeps dependencies specific to your project and avoids conflicts with system-wide packages.
- Control: You can install and manage different versions of libraries for different projects.
- Portability: Makes it easier to share your project with others without worrying about dependency issues.
- Remember, every time you work on this project, you’ll need to activate the virtual environment using:
source my_mqtt_env/bin/activate
When you're done, you can deactivate it with:
deactivate
Install Required Python Packages:
After activating the virtual environment, install necessary packages like paho-mqtt:
- Paho-MQTT is a Python library that provides a client class for implementing MQTT (Message Queuing Telemetry Transport) protocol.
- This protocol is used for lightweight, low-bandwidth, and real-time communication, making it ideal for Internet of Things (IoT) applications.
- Paho-MQTT allows Python developers to easily publish and subscribe to MQTT topics, manage message transfers, and interact with an MQTT broker.
- It supports all the key MQTT features like QoS levels, last will messages, and persistent sessions, enabling seamless communication between devices and services over networks like the Raspberry Pi or cloud platforms.
pip install paho-mqtt
You can also install other dependencies as needed.
Verify the Installation:
Check that the necessary libraries are installed by running:
pip list
Publishing and Subscribing Using Python
Task: Write a Python script to publish a message to a topic using the paho-mqtt library.
If copying code, use the Right-Mouse-button click to copy and paste in nano.
import paho.mqtt.client as mqtt
client = mqtt.Client()
client.connect("localhost", 1883, 60)
client.publish("home/livingroom", "Lights turned ON")
client.disconnect()
- localhost: This is the address of the MQTT broker the client is connecting to. In this case, "localhost" refers to the local machine where the broker is running. It could also be an IP address or a hostname if connecting to a remote broker.
- 1883: This is the port number that the client will use to connect to the broker. Port 1883 is the default port for MQTT communication.
- 60: This is the "keepalive" time in seconds. It defines the maximum period the client will wait without communication with the broker before sending a ping to keep the connection alive. If no data or ping is sent within 60 seconds, the connection may be closed.
Challenge: Modify the script to send the current time as a message.
Subscribing Using Python
Task: Write a Python script to subscribe to a topic using paho-mqtt.
import paho.mqtt.client as mqtt
def on_message(client, userdata, message):
print(f"Received message: {message.payload.decode()} on topic {message.topic}")
client = mqtt.Client()
client.connect("localhost", 1883, 60)
client.subscribe("home/livingroom")
client.on_message = on_message
client.loop_forever()
Subscribing to Multiple Topics
Task: Modify the Python script to subscribe to multiple topics at once.
def on_message(client, userdata, message):
print(f"Received message: {message.payload.decode()} on topic {message.topic}")
client = mqtt.Client()
client.connect("localhost", 1883, 60)
client.subscribe([("home/livingroom"), ("home/kitchen")])
client.on_message = on_message
client.loop_forever()
Challenge: Use the terminal to publish to both topics and observe the output from the Python script.
Filter Messages Based on Topic
Task: Modify the script to process messages only from specific topics and perform different actions.
def on_message(client, userdata, message):
if message.topic == "home/livingroom":
print(f"Living room message: {message.payload.decode()}")
elif message.topic == "home/kitchen":
print(f"Kitchen message: {message.payload.decode()}")
else:
print(f"Unknown topic: {message.payload.decode()}")
Challenge: Publish messages to different topics and verify that the script processes each one correctly.
Logging Received Messages to a File
Task: Enhance the script to log all incoming messages to a text file for later analysis.
Note that the file name will need a path. eg. /home/pi/mqtt_test/<file_name>
def on_message(client, userdata, message):
with open("mqtt_messages.log", "a") as logfile:
logfile.write(f"{message.topic}: {message.payload.decode()}\n")
print(f"Message logged: {message.payload.decode()}")
Challenge: Publish multiple messages and check that the log file is correctly updated.
Using Wildcards for Subscriptions
Task: Modify the script to use MQTT wildcards to subscribe to a broader range of topics.
client.subscribe("home/#") # This will subscribe to all topics under 'home/'
Challenge: Publish to different topics like home/bedroom, home/garden, and verify that all are received under the wildcard subscription.
Publishing Sensor Data
Task: Simulate a sensor (e.g., temperature or humidity) by having your Python script publish random values periodically.
import time
import random
def publish_sensor_data():
while True:
temperature = random.uniform(15.0, 30.0)
client.publish("home/sensors/temperature", f"{temperature:.2f}")
time.sleep(5)
client = mqtt.Client()
client.connect("localhost", 1883, 60)
client.loop_start()
publish_sensor_data()
Challenge: Run a subscriber script and verify that the temperature data is being received periodically.
Send an Alert Based on a Threshold
Task: Set up the script to send an alert if a temperature value exceeds a certain threshold.
def on_message(client, userdata, message):
temp = float(message.payload.decode())
if temp > 25.0:
print(f"Alert! High temperature: {temp}")
Challenge: Publish a temperature value above 25°C and verify that the alert is triggered.
MQTT between two Raspberry Pi computers
MQTT Communication Between Two Raspberry Pis, you need to configure both devices for MQTT communication, one acting as the publisher and the other as the subscriber. Here's how to set up the activity:
1. Install Mosquitto Broker on Raspberry Pi 1 (or a third-party broker)
- One Raspberry Pi should be set up to act as the broker on a local network (e.g. old WiFi router).
- Note the IP address of this Raspberry Pi.
- This will be called (Raspberry Pi 1).
2. Set Up the Publisher Script (Raspberry Pi 1)
This Pi will be responsible for publishing messages to the MQTT broker. The script below will simulate temperature sensor data being sent every 5 seconds.
Publisher Script:
import paho.mqtt.client as mqtt
import time
import random
# Define the broker address (localhost if running on the same device as the broker)
broker_address = "192.168.1.20" # Replace this IP address with (Raspberry Pi 1) IP on the local WiFi network.
# Initialize MQTT Client
client = mqtt.Client()
client.connect(broker_address)
def publish_temperature():
while True:
temp = round(random.uniform(20.0, 30.0), 2) # Random temperature between 20°C and 30°C
client.publish("home/temperature", f"{temp}")
print(f"Published: {temp}°C")
time.sleep(5)
# Start publishing temperature
publish_temperature()
Explanation: This script connects to the broker and publishes a random temperature to the topic home/temperature every 5 seconds.
Command to Run:
python3 publisher.py
3. Set Up the Subscriber Script (Raspberry Pi 2)
This Pi will subscribe to the home/temperature topic and display any received temperature messages.
Subscriber Script:
import paho.mqtt.client as mqtt
# Define the broker address (IP address of the Pi running the broker or localhost if the same Pi)
broker_address = "BROKER_PI_IP" # Replace with Pi's IP
def on_message(client, userdata, message):
print(f"Received message: {message.payload.decode()} on topic {message.topic}")
# Initialize MQTT Client
client = mqtt.Client()
client.connect(broker_address)
# Subscribe to the temperature topic
client.subscribe("home/temperature")
client.on_message = on_message
# Keep the connection open
client.loop_forever()
Explanation: This script connects to the broker and subscribes to the topic home/temperature, printing any messages it receives.
Command to Run:
python3 subscriber.py
4. Testing the MQTT Communication
- Step 1: Ensure both Raspberry Pis are connected to the same network.
- Step 2: Run the Mosquitto broker on Pi 1 or use an external broker.
- Step 3: Execute the publisher script on Raspberry Pi 1 to start publishing temperature data.
- Step 4: Execute the subscriber script on Raspberry Pi 2 to listen for and display the published temperature messages.
5. Challenge:
- Publish more data: Modify the publisher script to send multiple types of data (e.g., humidity, pressure) and set up the subscriber to handle multiple topics.
- Task: Extend the subscriber to process messages from different topics and print different alerts based on the data received.