Skip to main content

Building an MQTT enabled application with Cylon.js

title

Integrating an Intel Edison sensor node with Node-RED running on a Raspberry Pi 2.

In this post, we will connect an infra-red distance sensor to an Intel Edison and publish readings to an MQTT topic. We will use a Raspberry Pi 2 running Node-RED to subscribe to this topic, process the data and publish a boolean to a new topic.

As covered in a previous post, MQTT or 'Message Queueing Telemetry Transport' is a Machine-to-Machine (M2M) or Internet of Things (IoT) connectivity protocol. We can use MQTT to send messages between different platforms, including the Raspberry Pi and Intel Edison as we will in this post. We will make use of the Mosquitto MQTT broker we set up previously.

We will assume that you are using the Edison Arduino breakout board, have the latest Yocto image installed and can login over the network via SSH. We will also assume you have Mosquitto and Node-RED installed on a Raspberry Pi 2.

Setting up Cylon.js on the Edison

We will use the Cylon.js JavaScript framework to create a simple application to read the sensor and connect to our MQTT broker. We have used Cylon.js on the Edison before. We need to install the MRAA library first. Log in to your Edison terminal and execute the following commands:

$ echo “src mraa-upm http://iotdk.intel.com/repos/1.1/intelgalactic" > /etc/opkg/mraa-upm.conf

$ opkg update

$ opkg install libmraa0

Once the MRAA library is installed we can install cylon-intel-iot, the Cylon.js adaptor for the Intel Edison and Galileo platforms.

$ npm install cylon-intel-iot

Next test that the install is working correctly by blinking the onboard LED:

  • Create a file called blinkTest.js
  • Copy the sample code from the Cylon tutorial page (under the heading 'Blinking the built in LED') into your blinkTest.js file
  • Save the file
  • Execute the file on the Edison:
  • $ node blinkTest.js
  • You should see confirmation in the console window and the onboard LED blinking
  • Press ctrl-c to stop

Setting up MQTT

Next let's get MQTT running on the Edison. Start by installing the cylon-mqtt module:

$ npm install cylon-mqtt

Now we will create a test script to publish to an MQTT topic. Open a new browser window, head to the Node-RED install running on your Pi (). Find the flow we made that contained MQTT input and output nodes (see the flow we created in this post for detail on how to set this up). We will refer to this flow to test the following MQTT messages.

On the Edison, create a file named testMQTT.js and paste in the following code:

var Cylon = require('cylon');

Cylon.robot({

connections: {

server: { adaptor: 'mqtt', host: 'mqtt://:1883', username: '', password: '' }

},

work: function(my) {

// below 4 lines are for subscribing to chosen topic

// my.server.subscribe('topic/test');

// my.server.on('message', function (topic, data) {

// console.log(topic + ": " + data);

// });

// below 4 lines are for publishing to topic

every((5).seconds(), function() {

console.log("Saying hello...");

my.server.publish('topic/test', 'hi there');

});

}

}).start();

Notice that the above includes code for both subscribing and publishing to an MQTT topic – for now we have the subscribing part commented out and are just interested in testing the publishing part. Change the server details in the . Save the file and execute it:

$ node testMQTT.js

title

You should see something similar to the screenshot above. Now go to Node-RED flow on the Pi and watch the debug panel. As our existing MQTT input node is subscribed to the 'topic/test' topic, messages from the Edison should be displayed in the Node-RED debug console.

Next, let's test the subscribe function in the previous code. Open the editor again, uncomment the 4 lines for subscribing and comment out the 4 lines for publishing. Save and execute your code. Now you will have to publish test messages to your topic, we can use the test inject node that we created in Node-RED previously. When clicking the button on the inject node in Node-RED you should see the messages echoed in the terminal window on the Edison running the testMQTT.js file.

title

Adding a distance sensor

title

Now we have our Edison successfully publishing and subscribing to MQTT topics, let's use sensor data rather than test messages. We will connect a Sharp reflective infra-red sensor to the Edison and use Cylon.js to read the data, format it and publish it to an MQTT topic.

Hardware used:

Connect the sensor to the Edison as shown in the above diagram. Create a file named distMQTT.js and paste in the following code:

var Cylon = require('cylon');

Cylon.robot({

connections: {

edison: { adaptor: 'intel-iot' },

server: { adaptor: 'mqtt', host: 'mqtt://:1883',

username: '', password: '' },

},

devices: {

sensor: { driver: 'ir-range-sensor', pin: 0, model: 'gp2y0a41sk0f' }

},

work: function(my) {

every((5).seconds(), function() {

var range = my.sensor.range();

var ra = range.toFixed(2);

var r = ra.toString();

console.log("Publishing range");

my.server.publish('topic/test', r);

});

}

}).start();

Remember to change the necessary fields in the . Save the file and execute it on the Edison:

$ node distMQTT.js

title

You should see several lines output to the terminal as above before regular 'Publishing range' messages. You should now be able to switch back to your Node-RED install that is subscribed to the same MQTT topic and see the messages from the Edison appearing in the debug window.

Now that we have data coming into Node-RED we can process this (in this case on a Raspberry Pi) before sending messages back to the sensor node. This is useful where we might want to deploy many lightweight sensor nodes and use a single more powerful central node to do the processing. We can then return the output to the sensor nodes or other nodes as needed. Note that the Edison would be more than capable of performing this particular task and this is to demonstrate one possible configuration and the flexibility of this architecture.

To do this we will set up another Node-RED flow that subscribes to the topic that the distance sensor is publishing to and returns a boolean depending on it's value.

First find the line in the distMQTT.js file that determines the topic we are publishing to:

my.server.publish('topic/test', r);

Change the topic to 'dist':

my.server.publish('topic/dist', r);

Save the file and go to your Node-RED flow editor. Start a new flow and drag in an MQTT input node. Double-click the MQTT node and add the topic 'topic/dist' in the topic field. Your broker details should have been saved from earlier use, if not add those too. Close the node edit window and drag in a debug node. Connect the two nodes together and deploy. Switch back to your Edison terminal and execute the distMQTT.js file as before. You should see the distance data appearing in the debug window in Node-RED.

title

Now we can evaluate the sensor data and publish a boolean to a topic. Disconnect the two nodes in your flow and drag in a function node. Double-click it to open the editor window and paste in the following code:

var n = parseInt(msg.payload);

msg.payload = n;

return msg;

This converts our incoming message into an integer that we can pass to the next node for evaluation. Close the editor window and drag in a switch node. Double-click it and add the conditions as below.

title

Next drag in 2 trigger nodes and edit one as below and the second in a similar way except changing the output from '1' to '0' and the name from 'tooClose' to 'safeDistance'. Now drag in an MQTT output node, double-click it and give it a topic of 'topic/distReturn'. Name the node 'distReturn' and close the editor panel.

title

Connect the nodes up as above and deploy your flow. You should now see either a 0 or 1 appear in your debug window depending on the value passed from the distance sensor and the value (4 in above example) in our switch node.

Now we simply need to modify our distMQTT.js file to subscribe the Edison to the correct topic. Edit the file, delete the existing contents and copy in the code below:

var Cylon = require('cylon');

Cylon.robot({

connections: {

edison: { adaptor: 'intel-iot' },

server: { adaptor: 'mqtt', host: 'mqtt://:1883',

username: '', password: '' },

},

devices: {

sensor: { driver: 'ir-range-sensor', pin: 0, model: 'gp2y0a41sk0f' }

},

work: function(my) {

my.server.subscribe('topic/distReturn');

my.server.on('message', function (topic, data) {

console.log(topic + ": " + data);

});

every((5).seconds(), function() {

var range = my.sensor.range();

var ra = range.toFixed(2);

var r = ra.toString();

console.log("Publishing range");

my.server.publish('topic/dist', r);

});

}

}).start();

title

Save the file and execute it on the Edison. You should now see messages being published and subscribed in both the Edison terminal and Node-RED debug window as above.

Final thoughts

This example shows how we can use MQTT to send data between different hardware and software platforms. Instead of the Edison we could be using an Arduino Ethernet, a BeagleBone Black or even another Raspberry Pi. We could also be using applications written in Python or other languages as well as those based on Cylon.js and Node-RED.

maker, hacker, doer
DesignSpark Electrical Logolinkedin