Node.js, MQTT and Websockets
For a while I’ve been looking at how to bridge the MQTT protocol and websockets to make it easier to build web applications using data broadcast in MQTT streams. In the past I used python and mod_pywebsocket along with mosquitto python libraries however this was cumbersome and difficult to install. Here I present a simple solution using node.js to interact with mosquitto MQTT clients. Node.js lends itself to working well with messaging systems like MQTT and websockets due to its event driven nature. I’m also in love with node.js at the moment!
This is much simpler than previous attempts and I put the initial test together in less than ten minutes.
Prerequisites
Obviously you’ll need to have node.js and mosquitto installed and also the node library node-websocket-server (which can easily be installed using npm). All my work was tested under ubuntu but there is no reason why it wouldn’t work on OSX or even cygwin. To test you’ll need a websocket compatible browser such as recent versions of chrome.
System Structure
mosquitto_pub and mosquitto_sub are command line MQTT clients supplied with the mosquitto MQTT broker, here mosquitto_sub will be called using node.js as child processes, events are generated on output from the process. The data is then captured and broadcast over a websocket. In this case a simple jquery page is used to display the broadcast messages but in a real application there would be more client side processing to make a useful application.
Simple Server Side Subscriber Code
This example subscribes to the topic “test” and broadcasts all messages on this topic over the websocket on port 8000.
/* Include required libraries */
var util = require('util'),
sys = require("sys"),
ws = require("websocket-server"),
spawn = require('child_process').spawn,
/* Create websocket server */
server = ws.createServer({debug: true}),
/*
* Ceate call to mosquitto_sub cli client
* to subscribe on topic "test"
*/
mosq = spawn('mosquitto_sub',['-t','test']);
/*
* Bind an event to stdout which occurs when
* mosquitto_sub outputs anything
*/
mosq.stdout.on('data', function (data) {
/*
* Brodcast the MQTT message straight back
* out on the websocket
*/
server.broadcast(data);
/* Log the message to the console */
console.log('' + data);
});
/*
* Bind an event to stderr so we can see any
* errors that cause mosquitto_sub to crash
*/
mosq.stderr.on('data', function (data) {
console.log('error: ' + data);
});
/* Start the websocket server listening on port 8000 */
server.listen(8000);
Demonstration Client
This is a bare bones page which prints out messages received over the websocket.
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<div id="debug"></div>
<div id="msg"></div>
<script src='http://code.jquery.com/jquery-1.4.4.min.js'></script>
<script>
$(document).ready(function() {
function debug(str) {
$("#debug").append("<p>"+str+"</p>");
};
ws = new WebSocket("ws://<your ip address>:8000");
/* Define websocket handlers */
ws.onmessage = function(evt) {
$("#msg").append("<p>"+evt.data+"</p>");
};
ws.onclose = function() {
debug("socket closed");
};
ws.onopen = function() {
debug("connected...");
};
});
</script>
</body>
</html>
Further Development
This example is of little practical use on its own however it could easily be the basis of a flashy home monitoring system. Publishing MQTT messages could be easily achieved by calling mosquitto_pub in the child process.
Tags: html5, Internet, javascript, linux, mqtt, node.js, Programming, ubuntu, web sockets
Thanks Oliver,
This is really interesting, I will play with this when I get some spare time on my hands!
Cheers
Hi, Oliver.
Good post, i have a quick question irrelevant to this topic: how did u add codes like above to ur post?
I used a WordPress plugin called Syntax Highlighter Evolved.
how do u execute the cliemt hmtl part, does it have any browser specific issue
It requires a browser which supports websockets….
Hey Oliver,
I ran the server side code using node (v0.6.14) but when I try to access the same from Chrome the server logs the following exception while the client ran the ws.onclose function:
/Users/sureshsaggar/Documents/workspace/NodeJS/src/node_modules/websocket-server/lib/ws/connection.js:51
process.stdout.flush();
^
TypeError: Object # has no method ‘flush’
at /Users/sureshsaggar/Documents/workspace/NodeJS/src/node_modules/websocket-server/lib/ws/connection.js:51:22
at new Connection (/Users/sureshsaggar/Documents/workspace/NodeJS/src/node_modules/websocket-server/lib/ws/connection.js:100:5)
at Server. (/Users/sureshsaggar/Documents/workspace/NodeJS/src/node_modules/websocket-server/lib/ws/server.js:72:7)
at Server.emit (events.js:88:20)
at Socket. (http.js:1425:14)
at TCP.onread (net.js:374:27)
Any idea how this could be resolved? TIA!
I’m also hitting the same problems as saggar. Tried both node-v0.6.15 and node-v0.8.2 but both are giving this same error:
/home/pi/scripts/node_modules/websocket-server/lib/ws/connection.js:51
process.stdout.flush();
^
TypeError: Object # has no method ‘flush’
at debug (/home/pi/scripts/node_modules/websocket-server/lib/ws/connection.js:51:22)
at new Connection (/home/pi/scripts/node_modules/websocket-server/lib/ws/connection.js:99:5)
at Server. (/home/pi/scripts/node_modules/websocket-server/lib/ws/server.js:72:7)
at Server.EventEmitter.emit (events.js:115:20)
at Socket.socket.ondata (http.js:170
Any ideas??
The development of node moves fast, I wrote this post 18 months ago, I suspect the API has probably changed and broken compatibility with this example somewhere, I’ve not tried it for a while, more recently I’ve used socket.io for websocket connections
We did something like this at mqtt.io, but implemented the ability to subscribe and publish based on a custom string-based protocol. Pretty cool stuff
Thx for this Oliver. Will try it shortly.
However, this https://npmjs.org/package/mqttjs (also came u pin my serach) may be a better solution. I’ll also try that and come back with any conclusions.
Paul
Yes you’ve probably right, this post is getting a little old now with the pace this area is moving