MQTT Protocol for IoT

post hero image

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.

MQTT Protocol Scheme

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: