MQTT support - overthesun/simoc-sam GitHub Wiki
This page includes notes about setting up, testing, and using MQTT.
Mosquitto can be installed with the following commands:
sudo apt install mosquitto # installs the broker
sudo apt install mosquitto-clients # client support -- useful for testing
This will install and run a background service for the mosquitto broker. In order to see the broker logs (useful for debugging), the service can be stopped and relaunched manually:
service mosquitto status
sudo service mosquitto stop
mosquitto -v
A test subscriber (listening client) can be created with:
$ mosquitto_sub -v -h localhost -t 'sam/#'
This will keep the process running waiting for incoming message on the sam/ topic. From a different shell we can send a message using a test publisher:
$ mosquitto_pub -h localhost -t 'sam/humidity/greenhouse' -m 80
and sam/humidity/greenhouse 80 will appear in the shell where mosquitto_sub is running.
Note that in order to establish connections from different hosts, the following lines should be added at the end of /etc/mosquitto/mosquitto.conf on the machine where the broker is running (this might be a bit too open though -- see different authentication methods):
listener 1883
allow_anonymous true
The same can be achieved with Python and paho-mqtt. First create a venv, install paho-mqtt and start Python:
$ python3 -m venv mqtt-test
$ source mqtt-test/bin/activate
$ pip install paho-mqtt
...
$ python3
Then create a subscriber (equivalent to the mosquitto_sub above):
>>> import paho.mqtt.client as mqtt
>>> client = mqtt.Client()
>>> client.on_connect = lambda client, userdata, flags, rc: client.subscribe("sam/#")
>>> client.on_message = lambda client, userdata, msg: print(f'{msg.topic}: {msg.payload}')
>>> client.connect("localhost", 1883, 60)
0
>>> client.loop_forever()
This will loop forever waiting for messages on the sam/ topic and print them once they are received.
To create a simple publisher (this needs to be updated to handle disconnections):
>>> import paho.mqtt.client as mqtt
>>> client = mqtt.Client()
>>> client.connect("localhost", 1883, 60)
0
>>> client.publish('sam/greenhouse/temperature', 20)
<paho.mqtt.client.MQTTMessageInfo object at 0x7fe4f565df30>
>>>
After publishing this message, the Python subscriber will print sam/greenhouse/temperature: b'20' and the mosquitto_sub will print sam/greenhouse/temperature 20.
Set Up a Mosquitto MQTT Broker Securely via Certificates
Step 1: Install OpenSSL
We’ll use OpenSSL to create our certificates. It’s probably already installed, but if not, you can install it with:
sudo apt-get install openssl -y
Step 2: Create the Certificate Authority
We’ll start by creating a directory to store our certificates, and then move into that directory:
mkdir ~/certs
cd ~/certs
Now we’ll generate our CA private key:
openssl genrsa -out ca.key 2048
With the private key, we’ll generate the root certificate:
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
You’ll be asked for some information, which will be included in the certificate. The most important part is “Common Name”. It should be a name that identifies the CA.
Step 3: Create the Server Certificates
First, create the server private key:
openssl genrsa -out server.key 2048
Now create a certificate signing request (CSR) with that key:
openssl req -new -key server.key -out server.csr
Again, you’ll be asked for some information. For the common name, you MUST use the IP address or hostname of the MQTT server (for example: mqtt.simoc.space). Certificates will not work if the mqtt server ip address or hostname is not the one specified into the common name.
Now, sign the CSR with the CA’s private key:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 3650
Then copy the generated files into the standard certificates mosquito directory and set the right permission:
sudo cp * /etc/mosquitto/certs/
sudo chmod 644 /etc/mosquitto/certs/*
Step 4: Create the Client Certificates
We’ll repeat a similar process for the client certificates:
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr
Make sure the common name is different from the one you used for the server.
Now, sign the client CSR:
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 3650
Then copy the generated client files to the remote machine (via scp for example) and put them again under the standard certificates mosquito directory, ex:
scp ca.* client.* pi@samrpi2:/etc/mosquitto/certs/
Step 5: Configure Mosquitto
Now, we’ll tell Mosquitto to use these certificates for TLS. Open the Mosquitto configuration file:
vi /etc/mosquitto/mosquitto.conf
And add the following lines:
listener 8883 0.0.0.0
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
use_identity_as_username true
tls_version tlsv1.3
Restart Mosquitto:
sudo systemctl restart mosquitto
Step 6: Test the Configuration
Now, you can test the configuration:
On the remote machine (ex: samrpi2)
mosquitto_pub -h mqtt.simoc.space -p 8883 --cafile /etc/mosquitto/certs/ca.crt --cert /etc/mosquitto/certs/client.crt --key /etc/mosquitto/certs/client.key -t test/topic -m "hello tls" -d
On the local machine:
mosquitto_sub -h mqtt.simoc.space -p 8883 --cafile /etc/mosquitto/certs/ca.crt --cert /etc/mosquitto/certs/client.crt --key /etc/mosquitto/certs/client.key -t test/topic -d
Set Up a Mosquitto MQTT Broker for direct websocket connection
It is possible to connect directly to a mosquitto brocker via websocket The configuration must be done as:
listener 8081
protocol websockets
allow_anonymous true
in the /etc/mosquitto/mosquitto.conf file
So far only the unsecure connection was working Then restart the server as usual.
For testing mosquitto cannot be used. You need to install the mqtt cli this way:
wget https://github.com/hivemq/mqtt-cli/releases/download/v4.34.0/mqtt-cli-4.34.0.deb
sudo apt install ./mqtt-cli-4.34.0.deb
then you can use a command like this for testing:
mqtt sub -t lunares/# -h localhost -p 8081 -v -ws