MQTT is a lightweight publish/subscribe messaging transport designed for machine-to-machine “Internet of Things” connectivity. It’s been used in all sorts of industries from home automation and Facebook Messenger mobile app to health care and remote monitoring over satellite links. Its ideal for mobile apps and IoT because of it’s small footprint, low power usage and small data packets. You can connect to a MQTT Broker over standard TCP/IP ports with or without TLS or over Web Sockets. There are many cloud based MQTT services such as OpenSensors, CloudMQTT, HiveMQ, AWS IoT or Azure IoT Hub but where is the fun in that?
There’s a few message brokers that support MQTT in Fedora including RabbitMQ or ActiveMQ (the version in Fedora is old but it would be nice if someone did update it to the latest version!) but for this I’ll be using Mosquitto as it’s small and relatively straight forward for home and demo usage.
I’ve tested this on a Digital Ocean Fedora 23 VM but for this I’ll be using a Beagle Bone Black with a Fedora 24 Beta minimal image but of course you can run it on any recent Fedora release on any supported device, ARM or otherwise.
After installing Fedora and getting it running on the network install and configure mosquitto:
dnf install -y mosquitto screen mv /etc/mosquitto/mosquitto.conf.example /etc/mosquitto/mosquitto.conf firewall-cmd --permanent --add-port=1883/tcp firewall-cmd --permanent --add-port=1883/udp firewall-cmd --permanent --add-port=8883/tcp firewall-cmd --permanent --add-port=8883/udp systemctl enable mosquitto.service systemctl start mosquitto.service
By default the default settings are relatively straight forward, it runs under the mosquitto user, listens on all interfaces, with config options in /etc/mosquitto. In there is a well documented example config file called mosquitto.conf.example which contains all the default settings. Above we rename it to mosquitto.conf to use as a base config for us to modify. There’s details on using the Let’s Encrypt service on the mosquitto site. If you’re using it on the public internet I’d strongly suggest you configure TLS.
Testing it works
Now that we have a basic install done lets make sure it works and get a basic idea of how MQTT works. Included in the mosquitto package is a couple of client utilities useful for testing the MQTT broker pub/sub functionality. Start up a screen session and in a window run the following commands which subscribes us to the “test/topic” topic to the MQTT broker running on localhost:
mosquitto_sub -h localhost -t "test/topic"
Now lets publish some data to that topic. In another screen tab run the following command which will publish a string of text to the topic:
mosquitto_pub -h localhost -t "test/topic" -m "Hello World!"
You can run multiple subscribers either from the screen session or remote from a different host but remember to change the “-h localhost” to appropriate hostname/IP if you’re testing remotely.
MQTT can also use two types of wild cards when subscribing to topic names. So to be able to read all temperature sensors publishing to a root topic you could use “home/+/temp” which would provide “home/bedroom/temp” and “home/livingroom/temp”. The “+” will match one hierarchical level where as “#” stands for everything deeper so “home/garden/#” would provide all sensors from the garden. When using wild cards you’ll need to know which topic is reporting so use mosquitto_sub in verbose mode:
mosquitto_sub -h localhost -v -t "test/#"
Quality of Service
One of the killer features of MQTT for low power IoT sensor networks is that it’s a “store and forward” protocol with a couple of options for quality of service (QoS) guarantees. Once the node has registered with the broker any time it sleeps the broker will queue messages and take care of delivering that message to the node as soon as it reconnects. This means the node can sleep as long as needed to preserve battery life and just wake up and connect when it has data to send or at a predetermined interval without ever missing a message.
There’s three things needed to support QoS: 1) The subscriber needs to be registered by ID with the broker 2) The subscriber needs to disable clean-slate behavior (the default is enabled) 3) Both the publisher and subscriber need to be using quality-of-service level one or two so the broker knows it needs to store the messages. More details on QoS levels are covered here.
Here’s a small demo to play with QoS basics. First connect a subscriber to the broker supplying an ID, disable clean slate and enabling QoS level 1:
mosquitto_sub -h localhost -v -t "test/#" -c -q 1 -i "PotPlant"
Then send the following two messages, one each with and without QoS. You should see them both show up on the subscriber:
mosquitto_pub -h localhost -t "test/topic" -m "foo" -q 1 mosquitto_pub -h localhost -t "test/topic" -m "bar"
Now stop the subscriber (Ctrl+c) and while it’s stopped send both of the messages again before restarting the subscriber. When it reconnects you should just receive the “foo” message because it’s the only one specifying a QoS level.
There’s a lot of information about MQTT on the web. The MQTT Essentials page from HiveMQ is a good place to start for further information and Awesome-MQTT is a curated list of MQTT related stuff with everything from language bindings to gateways/plugins for integration with various projects whether they be home audio or enterprise products.