Introduction
IoT devices often use MQTT protocol to communicate to one another. It’s very important to understand the way they communicate to write your own MQTT clients and safely manage your devices’ communication.
MQTT protocol
Message Queue Telemetry Transport is a TCP-based protocol relying on the publish-subscribe model. It suits for devices that have low bandwidth and low power requirements, so it’s becoming widely diffuse for communication in IoT applications.
Multiple clients interact with each other without having any direct connection. All clients communicate with other clients only via third party called broker. Clients publish messages on different topics to broker. The broker is the central server that receives these messages and filters them based on their topics. It then sends these messages to respective clients that have subscribed to those topics.
The topics act like rooms where publisher and subscriber are virtually located.
Mosquitto broker
Mosquitto is an open source message broker that implements the MQTT protocol versions 5.0
, 3.1.1
and 3.1
.
You can install choose different installation types: local or on a Docker, which allows you to run it regardless of the underling OS and environment.
Local Mosquitto broker
Let’s install local MQTT Mosquitto broker:
sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt update -y
sudo apt install -y mosquitto mosquitto-clients
sudo apt clean
Allow external IPs
Starting with the release of mosquitto version 2.0.0
, the default configuration will only bind to localhost
because of secure default settings.
If you want to access the broker from other machines on the same network, you will need to explicitly edit the configuration files: add a new listener that binds to the external IP address or add a bind entry for the default listener.
In /etc/mosquitto/mosquitto.conf
set:
listener 1883
allow_anonymous true
Then, start the broker:
sudo mosquitto -c /etc/mosquitto/mosquitto.conf
You can now communicate through the mosquitto broker using default 1883
port of your local IP address.
# check process status
sudo systemctl status mosquitto
# stop the broker execution
sudo systemctl stop mosquitto
Please Note: On Linux (Debian-based, I guess) machines, you can either enable or disable mosquitto service (or any service) on boot by using those commands:
# enable the service to run at startup
sudo systemctl enable mosquitto
# disable the "run on startup" behavior
sudo systemctl disable mosquitto
Security
You can protect your broker with a login to prevent unwanted clients to consume your data nor to produce malicious messages.
# sudo mosquitto_passwd -c [pwd_file] [user]
sudo mosquitto_passwd -c /etc/mosquitto/mqtt_pwd nicla
# first, prompt your sudo password
# then, the mosquitto user's password
# then again, reenter the mosquitto user's password
Please Note: For security reason, the password won’t be shown but do not worry: it will be correctly accepted.
In /etc/mosquitto/mosquitto.conf
add the reference to the password file and comment-out the line that allow any client to connect:
listener 1883
password_file /etc/mosquitto/mqtt_pwd
# allow_anonymous true
Mosquitto broker on Docker
The official Mosquitto docker image is eclipse-mosquitto.
After Docker Desktop installation you can easily configure the containers thanks to thelebster’s Mosquitto authenticated Docker open source project, which inspired me to write authenticated-eclipse-mosquitto subdirectory from my mqtt project.
Let’s clone the GitLab repository I made to build and run this docker with docker compose.
Run the broker with Docker Compose command
cd ~ && git clone git@gitlab.com:PitPietro/mqtt.git
cd ~/mqtt/docker/authenticated-eclipse-mosquitto/
# copy the .env sample and edit username, password and mosquitto version
cp .env.txt .env
# build the docker image
docker compose build
# run the docker container
docker compose up -d
If the commands don’t work, run them with docker-compose
in place of docker compose
.
Run the broker with Docker command
You can also run the broker with docker
commands as well.
Having sensitive information hardcoded into the commands is a very huge security issue and has lots of disadvantages when scaling a project.
To overcome those issues, you should import .env
variables directly into your opened terminal window.
# clone the project and navigate to the directory
cd ~ && git clone git@gitlab.com:PitPietro/mqtt.git
cd ~/mqtt/docker/authenticated-eclipse-mosquitto/
# run the commands above only if you didn't run them before
# copy the .env template and create the actual .env file
cp .env.txt .env
# >>> edit .env according to your settings: username, password and mosquitto version <<<
# export .env variables into the shell
source set-env.sh
sudo docker build --build-arg MOSQUITTO_VERSION=${MOSQUITTO_VERSION} -t mosquitto:${MOSQUITTO_VERSION} .
sudo docker run --name my-mosquitto-container -d \
--restart=always \
--publish 1883:1883 -p 2222:22 \
-e MOSQUITTO_USERNAME=${MOSQUITTO_USERNAME} \
-e MOSQUITTO_PASSWORD=${MOSQUITTO_PASSWORD} \
--volume "$(pwd)"/data:/mosquitto/data \
--volume "$(pwd)"/log:/mosquitto/log \
mosquitto:${MOSQUITTO_VERSION}
The most easy way to test the broker is by using shell-based mosquitto_sub
and mosquitto_pub
commands.
The slice below has all the clients I have implemented so far
It is currently under update (even if the post has been published), so come back here sometimes to see if your favorite client has been added.
MQTT clients
To avoid writing to many installation guides, the GitLab project is provided with many README.md
files which are linked under the clients descriptions.
Android
MQTT_Samples Android application provides you with Material 3 samples for Subscriber and Publisher activities that communicates through both String
-based and JSON
-based payloads.
In the future, it will also integrate and WearOS and Android TV samples.
You can customize the following settings through dedicated activities:
- Endpoint: host IP and port
- MQTT authentication: username and password
I am also working on a roadmap of the app using some screenshots to better understand the different parts.
Arduino
Take a look at arduino subdirectory from my mqtt project:
It also provides you an arduino-secrets.txt
template to store sensitive information: rename the extension into .h
(header file) and move it to the same directory of the Arduino sketch you want to upload to the board.
Please Note: to run the sketches above, you need a WiFi-compatible board like Nano RP2040 Connect or MKR WiFi 1010.
JavaScript
Node-RED
Take a look at Node-RED Introduction post I wrote!
Python
Follow the instruction on Python Paho MQTT’s README file.
Shell
Both the commands below supports TLS encrypted connections.
mosquitto_pub
mosquitto_sub
is a simple MQTT client that will publish a single message on a topic and exit. The most simple way to use it is:
# mosquitto_pub -t [topic] -m [message] -u [username] -P [password]
mosquitto_pub -t HELLO -m "Hello broker" -u mosquitto -P mosquitto
mosquitto_sub
mosquitto_sub
is a simple MQTT client that will subscribe to a set of topics and print all messages it receives.
It’s based on libmosquitto 2.0.15
.
In addition to subscribing, it can filter out received messages or unsubscribe from topics: it is useful for clients connecting with clean session set to false
.
The most simple way to use it is:
# mosquitto_sub -h [host] -t [topic] -u [username] -P [password]
mosquitto_sub -h 192.168.0.0 -t HELLO -u mosquitto -P mosquitto
Conclusion
Documentation
Here is the full list of links I used to write this article:
- mqtt.org
- mosquitto broker
- MQTT Arduino client
- C client
- Embedded C client
- Moquette Java client
- MQTT.js JavaScript client
- Node-RED MQTT broker
- Mosquitto-PHP PHP client
- Paho MQTT Python client
- mosquitto_pub and mosquitto_sub
- mqtt GitLab repository
- Docker authenticated-eclipse-mosquitto
- Android MQTT_Samples
- Install Docker Desktop
- Beginners Guide to systemctl
- zwbetz.com post about
.env
variables into shell scripts - ArduinoJson utility library