When I wrote about the HiveMQ MQTT broker I said it had a killer-feature: support for Websockets. I’ll admit to have been pestering Roger Light, creator of Mosquitto, so much that to shut me up (I think) he’s been adding support for Websockets into the Mosquitto broker!
This makes using MQTT even more fun.
Websocket support must be explicitly enabled when building Mosquitto, and
building requires libwebsockets.
Once enabled, we can add listeners with the websocket
protocol. For
example, this mosquitto.conf
provides a default MQTT listener on port 1883,
and two Websocket listeners, one with TLS, one without:
autosave_interval 1800
persistence true
persistence_file m2.db
persistence_location /var/mosquitto/
connection_messages true
log_timestamp true
acl_file /etc/mosquitto/jp.acl
password_file /etc/mosquitto/jp.pw
listener 1883
listener 9001 127.0.0.1
protocol websockets
listener 9002 127.0.0.1
protocol websockets
cafile /etc/mosquitto/tls/ca.crt
certfile /etc/mosquitto/tls/tiggr.ww.mens.de.crt
keyfile /etc/mosquitto/tls/tiggr.ww.mens.de.key
(In case you’re interested, I create the X.509 certificates for TLS using generate-CA.sh from the OwnTracks project.)
Mosquitto ACLs work for Websockets just as they do for MQTT publishes & subscribes; when accessing the broker via Websockets a different TCP transport channel is used – everthing else remains the same.
Using the Paho MQTT JavaScript client, we can create something like this which shows messages published to the Mosquitto broker as soon as they’re received.
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Mosquitto Websockets</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="mqttws31.js" type="text/javascript"></script>
<script src="jquery.min.js" type="text/javascript"></script>
<script src="config.js" type="text/javascript"></script>
<script type="text/javascript">
var mqtt;
var reconnectTimeout = 2000;
function MQTTconnect() {
mqtt = new Messaging.Client(
host,
port,
"web_" + parseInt(Math.random() * 100,
10));
var options = {
timeout: 3,
useSSL: useTLS,
cleanSession: cleansession,
onSuccess: onConnect,
onFailure: function (message) {
$('#status').val("Connection failed: " + message.errorMessage + "Retrying");
setTimeout(MQTTconnect, reconnectTimeout);
}
};
mqtt.onConnectionLost = onConnectionLost;
mqtt.onMessageArrived = onMessageArrived;
if (username != null) {
options.userName = username;
options.password = password;
}
console.log("Host="+ host + ", port=" + port + " TLS = " + useTLS + " username=" + username + " password=" + password);
mqtt.connect(options);
}
function onConnect() {
$('#status').val('Connected to ' + host + ':' + port);
// Connection succeeded; subscribe to our topic
mqtt.subscribe(topic, {qos: 0});
$('#topic').val(topic);
}
function onConnectionLost(response) {
setTimeout(MQTTconnect, reconnectTimeout);
$('#status').val("connection lost: " + responseObject.errorMessage + ". Reconnecting");
};
function onMessageArrived(message) {
var topic = message.destinationName;
var payload = message.payloadString;
$('#ws').prepend('<li>' + topic + ' = ' + payload + '</li>');
};
$(document).ready(function() {
MQTTconnect();
});
</script>
</head>
<body>
<h1>Mosquitto Websockets</h1>
<div>
<div>Subscribed to <input type='text' id='topic' disabled />
Status: <input type='text' id='status' size="80" disabled /></div>
<ul id='ws' style="font-family: 'Courier New', Courier, monospace;"></ul>
</div>
</body>
</html>
I’ve put the source to this simple example on Github, and I’ve verified it works with Safari, Chrome, and FireFox.
Instead of writing your own Web application, you can easily use the mqtt.io
or the HiveMQ Websocket clients; configure them to use the host name and TCP port number (from the listener
directive) of your Mosquitto broker.
Mosquitto with Websocket support should be with you very soon, and I hope you’ll agree with me, that this is very good news. :-)