Note: Nov. 27, 2015, this is a quick first draft. I will be adding more details over the next few days including code snippets.
Here are some insights gained from building an actual MQTT based UI.
Using a system consisting of a Raspberry Pi 2 with Raspbian Jessie installed on an 8GB class 10 SD card I wrote a simple Python program to control a seed germination system for my garden.
The system includes a temperature probe to measure soil temperature and controls for mains power for an LED light source and a plant propagation heating pad. It also has sensors for air temperature, humidity and soil moisture.
The program’s user interface is browser based consisting of a web page including controls for:
- The time for lights to turn on
- Duration of photoperiod
- Target soil temperature
- Manual control of power
- Restarting the software
- Rebooting the Pi
- Emergency stop
There are also live data displays for:
- Soil temperature
- Soil moisture
- Air temperature
- Pi’s CPU temperature
The system uses Mosquitto with websockets enabled as both MQTT message broker and web server and it works quite well. Bootstrap was used to make the mobile-first UI so it can be used on a large screen monitor, a phone or anything in between.
A simple messaging protocol
In developing the UI I had to create a messaging protocol (API) for my particular application.
There is no polling involved and messages are only sent when something actually changes. This results in very low network traffic and minimal bandwidth.
There are a couple of other things that need to happen to make it all work nicely.
- Mosquitto has the ability to retain messages so that any client that later subscribes to messages from Python will receive the latest status info without Python having to do anything. New messages replace older retained messages that have the same topic.
In the Python program there is a function that is used whenever the program needs to send a message to the UI. It includes an argument that tells mosquitto whether to retain the message or not.
When I first compiled mosquitto on the Jessie release of Raspbian (Debian) there were problems getting the program to start at system boot. Jessie uses a more efficient system for starting programs called systemd. In many cases the new system will work with older init scripts located in /etc/init.d. Not so with mosquitto. The solution was to write a new init file for use with systemd.
The new unit file is much simpler that the older init script and should be located at /etc/systemd/system/ with a file name of mosquitto.service. The mosquito.service file I am using is:
[Unit] Description=Mosquitto MQTT Broker daemon ConditionPathExists=/etc/mosquitto/mosquitto.conf After=network.target Requires=network.target [Service] Type=forking RemainAfterExit=no StartLimitInterval=0 PIDFile=/var/run/mosquitto.pid ExecStart=/usr/local/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf -d ExecReload=/bin/kill -HUP $MAINPID Restart=on-failure RestartSec=2 [Install] WantedBy=multi-user.target
Once this file is placed in /etc/systemd/system/ as mosquitto.service it can be enabled with:
sudo systemctl enable mosquitto.service
You can either reboot the system to load mosquitto or use the command:
sudo systemctl daemon-reload
Once mosquitto is running you can use the following commands:
sudo systemctl start mosquitto
sudo systemctl stop mosquitto
sudo systemctl status mosquitto
sudo systemctl restart mosquitto
Mosquitto as web server
Mosquitto can be used as a web server if a listener (client) is using the web-sockets protocol. This is great for serving pages of a browser based UI. It would not be practical for a high traffic production site of course.
I created a directory structure in /usr/share/mosquitto/www and placed the necessary CSS, fonts and JaveScript files in the following subdirectories:
The index.html and any other HTML files(s) for the UI are in the www directory.
To enable mosquitto as an HTTP server, edit the mosquitto config file, /etc/mosquitto/mosquitto.conf.
at ~line 301, in the Extra listeners section, uncomment http_dir and add the location of the web directory:
After saving the config file and restarting mosquitto:
sudo systemctl restart mosquitto
Pointing your favorite browser to the URL of your Raspi with the websockets port appended, e.g. 192.168.1.XXX:9001 should bring up the home page of the UI.