This article shares how to run a simple drawing application on your own MQTT server, and how to going with both VerneMQ and EMQTT using a real certificate from Letsencrypt.org.
In the preamble, I've tried using the more verbose MQTT.js instead of the Paho library I've used previously but I eventually gave up, simply because I just couldn’t get it to connect quickly enough. The Paho library is also about 5x smaller even when compared to the minified version, not to mention that the MQTT.js library is primarily written for NodeJS, so… at this point I conclude the Paho library is preferred.
If you want more background information on MQTT, you can read this article first, which also includes an IoT protocol overview. When searching I also found this presentation (PDF file) being highly informative and a good summary.
Let's get Going - letsencrypt!In order to set up our own server talking MQTT over Secure Websockets, we first need a proper SSL certificate, not a self-signed one. One can get one for free these days, for example from StartSSL, but the hip and cool way is to use the up and coming Letsencrypt service!
The official documentation probably works fine, but I ended up following this howto and it was really simple. I did this on my Debian 8 server:
First stop anything running on port 80 and 443. Then get letsencrypt:
git clone https://github.com/letsencrypt/letsencrypt
cd letsencrypt
Next we let it create our cert, it will ask us some questions, most importantly the IP name(s) we want the cert to be valid for. You can enter more than one name for your domain separated by spaces:
./letsencrypt-auto certonly
When all is done you should find your certificate files in /etc/letsencrypt/live/your.domain.com/. The certificate is good for 90 days, see instructions in the documentation for renewals.
Finally an easy and free way to get a proper cert!
Your own MQTT ServerSo we want to use our own MQTT server. There are plenty around and I ended up trying out both VerneMQ and EMQTT. They are very easy to get started with and both are written in Erlang which in my book means they are probably robust choices.
Let’s try EMQTT first. If you prefer VerneMQ, skip down to the next section, you only need one server :)
EMQTTJust follow these instructions to download and unzip in your regular user home directory. Now we need to configure it for secure websockets using our new certificate. Bring up the file emqttd/etc/emqtt.config in your favorite editor and edit it as follows:
- In the Listeners-section I skipped regular http support by simply removing the whole existing “HTTP and WebSocket Listener” section.
- Then after finding out how to use separate cert and chain files I uncommented the “WebSocket over HTTPS Listener” section and changed the certificate settings to look like this:
[
{certfile, "etc/ssl/cert.pem"},
{keyfile, "etc/ssl/privkey.pem"},
{cacertfile, "etc/ssl/chain.pem"}
]
- Save it!
The reason for this is that using only the fullchain/privkey files caused iOS to have connection issues, although Android handled it just fine…
Finish it by copying the certificate files (not sure why it didn’t work for me first with original paths):
cd emqttd/etc/ssl
cp
If all is well you can now start EMQTT by doing ./bin/emqttd start
. It should reply with“emqttd is started successfully!”.
Then you can use ./bin/emqttd_ctl --help
to find information on how to list clients, list topics, trace topics etc. Quite neat! To see that you have proper listeners running you can check with./bin/emqttd_ctl listeners
and of course you can also see the ports open by running sudo netstat -plnt
or similar.
Note that out-of-the-box the configuration allows anonymous connections, which is just fine for our testing of course.
VerneMQInstalling VerneMQ was also quite easy following the instructions. Then its time for configuration but if that page looks daunting this is what I ended up changing:
- Turn on anonymous access:
allow_anonymous = on
- Add a listener for secure web sockets:
listener.wss.default = 0.0.0.0:8083
- Add Letsencrypt certificate files:
listener.wss.cafile = /etc/vernemq/fullchain.pem
listener.wss.certfile = /etc/vernemq/cert.pem
listener.wss.keyfile = /etc/vernemq/privkey.pem
- Finally it turns out we need to increase a limit to cater for the longer iOS device
UUIDs:max_client_id_size = 40
Then we copy the cert files into /etc/vernemq/
and change owner to vernemq
. Using the original paths may work if you fix permissions so that vernemq
can read them, but I copied them to be sure:
cp /etc/letsencrypt/live/your.domain.name/*.pem /etc/vernemq/
chown vernemq:vernemq /etc/vernemq/*.pem
…and that should be it! Start it up using the proper service – it will not say anything if it succeeds so check with status afterwards to make sure its up:
root@padme:~# service vernemq start
root@padme:~# service vernemq statuspongvernemq is running
If you get a warning about ulimit
you probably need to raise your limits, but it still works for demo.
If you want to check if it works, you can try the online demo from HiveMQ. Just enter your hostname, port and check the SSL checkbox, then click Connect. If it connects (you get a green circle instead of a red one) you can also test a bit of publish/subscribe to make sure it works :)
Client libraryThere are two MQTT client implementations in JavaScript, the “Paho” library which lives in the Eclipse Paho project and MQTT.js hosted and maintained on github. Both support the latest version of MQTT 3.1.1 and thus also websockets.
Previously we used the Paho library but in this article I wanted to try out MQTT.js. After fiddling with browserify (or webpack) and rewriting the example code to fit the API etc – I utterly failed to connect using that library, kinda felt like this guy:
Obviously I must have missed some detail, but I really have no clue why it doesn’t want to connect. So for us, the Paho library is what we use and recommend. Paho is also much smaller and not primarily written for NodeJS, although I haven’t scrutinized the code quality of these two libraries.
The Painter ExampleOur example app is the same as before – a trivial interactive painting app where the paint operations are shared over MQTT. Each user connects and subscribes to the same topic – and when a user is painting with the finger on the canvas we publish a simple JSON payload describing a painted line from (x,y) to (x2,y2) in a specific color, for each touchmove event.
When the app receives messages it paints them. Note that even the original painter will only paint the line when it’s received as a message. This means as the active painter you get a sense of the latency involved.
Running the AppNow let’s get our app running. I presume you have gotten started with Evothings Workbench, then you just need to:
- Git clone our demo repository to your laptop, or just download and unzip it.
- Locate the folder mqtt-vernemq-emqtt-painter and drag the index.html file from there and drop it onto the “My Apps” tab in the Workbench. It should then be added to the list.
Before starting the app you need to edit it and enter your own host and port – you don’t need to change user/password since we do not use it. Open the app.js file and modify lines 10-11 in app.js with the correct settings:
var host = 'padme.krampe.se'; // Change this to your servervar port = 8083; // No need to change this if you configured your server as described
Now if your Workbench is connected with one or more devices you should be able to just click the RUN button to get the app started.
The app should hopefully say “Connected!” on your device. Feel free to use the “CONNECT” button to reconnect if you are disconnected, at the moment the example does not try to keep the connection alive via ping. You can also open up the Javascript Workbench using the top right Tools-button. This enables you to see what the app is logging when its running.
Now start painting e.g. with your finger, each connected device should paint using its own generated color (based on the UUID!).
ConclusionMQTT is very easy to get going with and both VerneMQ and EMQTT are easy to install. Letsencrypt also makes it trivial to get your own real certificate which is highly recommended since mobile hybrid apps refuse to deal with self signed certificates. For a whole range of mobile IoT applications MQTT should be a very logical choice for communication, both between devices (mobile or IoT) and between devices and servers.
Hope you found this article interesting, download Evothings Studio today and start hacking your own MQTT powered app!
Comments