SmartMesh IP and Node-RED, revisited
Node-RED is a fun tool from IBM Research to "wire up the IoT". We show how the JsonServer
application allows you to interface Node-RED to your SmartMesh IP network without writing a line of code!
This recipe updates the previously published "SmartMesh IP and Node-RED" recipe. In this recipe, we use the JsonServer
SmartMesh SDK application; it's now even simpler to interface with Node-RED!
Overview of Node-RED
Node-REDĀ is a fun tool from IBM Research to "wire up the IoT". It's a program you launch on your computer, which allowing you to link inputs (sensors, etc.) to outputs (actuators, files, Twitter feeds, etc.)Ā through a web-based graphical interface.
SmartMesh IP and Node-RED are a perfect match. I'll show you a couple of examples in this recipe. You will be using the brand newĀ JsonServer
Ā application from the SmartMesh SDK; you won't even have to write a line of code!
Requirements
To complete this tutorial, you need to have:
- a SmartMesh IP starter kit
- a computer
We assume the motes are running the default firmware, in master mode.
We assume that the manager is connected to your computer over USB, that all the motes are switched on, and that all motes have joined the network.
We assume you have downloaded the SmartMesh SDK, and are comfortable enough with it that you can launch different applications.
Setup
Installing Node-RED
The first step is toĀ install Node-RED.
- First, install Node.js. There a number of options. On my Windows machine, it just means downloading an installer and clicking through the default installation options.
- You can verify Node.js is installed by entering the following command (
npm
is the "node package manager", part of Node.js)
C:\Users\twatteyne>npm --version 2.15.9
- You install Node-RED through
npm:
npm install -g --unsafe-perm node-red
- Finally, you can start Node-RED:
C:\Users\twatteyne>node-red Welcome to Node-RED =================== 1 Sep 15:02:04 - [info] Node-RED version: v0.14.6 1 Sep 15:02:04 - [info] Node.js version: v4.5.0 1 Sep 15:02:04 - [info] Windows_NT 6.1.7601 x64 LE 1 Sep 15:02:04 - [info] Loading palette nodes 1 Sep 15:02:05 - [warn] ------------------------------------------------------ 1 Sep 15:02:05 - [warn] [rpi-gpio] Info : Ignoring Raspberry Pi specific node 1 Sep 15:02:05 - [warn] [tail] Not currently supported on Windows. 1 Sep 15:02:05 - [warn] ------------------------------------------------------ 1 Sep 15:02:05 - [info] Settings file : C:\Users\twatteyne\AppData\Roaming\npm\ node_modules\node-red\settings.js 1 Sep 15:02:05 - [info] User directory : \Users\twatteyne\.node-red 1 Sep 15:02:05 - [info] Flows file : \Users\twatteyne\.node-red\flows_HDC_SW 01.json 1 Sep 15:02:05 - [info] Creating new flow file 1 Sep 15:02:05 - [info] Starting flows 1 Sep 15:02:05 - [info] Started flows 1 Sep 15:02:05 - [info] Server now running at http://127.0.0.1:1880/
Point your browser to http://localhost:1880/ to see the Node-RED web interface:
Geeky details
As you can see from the URL above, the Node-RED application starts a web server which listens on port 1880.
Following the excellent Getting Started guide if you want to learn more about Node-RED.
Running theĀ JsonServer
Ā application
This application is part of theĀ SmartMesh SDK. To start it, double-click onĀ JsonServer.py
.
Starting your network
We assume that you have a SmartMesh IP manager connected to the computer which runs theĀ JsonServer
Ā application, and a couple of motes already in the network.
Interact with your SmartMesh IP nodes using Node-RED!
In this section, we will create a number of Node-RED flows to interact with your SmartMesh IP network directly from Node-RED!
Retrieve the status of theĀ JsonServer
Use Node-RED to issue the following HTTP request:
method | GET |
---|---|
URI | http://127.0.0.1:8080/api/v1/status |
body | none |
To do so, in Node-RED, create a flow called "status" with the following contents:
JSON version of the flow
[{"id":"3eb439e9.a16146","type":"inject","z":"8c6d627b.da73c","name":"click to get status","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":146.5908966064453,"y":65.63638305664062,"wires":[["97cbb847.431838"]]},{"id":"97cbb847.431838","type":"http request","z":"8c6d627b.da73c","name":"","method":"GET","ret":"txt","url":"http://127.0.0.1:8080/api/v1/status","tls":"","x":271.59088134765625,"y":161.8182144165039,"wires":[["a459d098.1a269"]]},{"id":"a459d098.1a269","type":"debug","z":"8c6d627b.da73c","name":"","active":true,"console":"false","complete":"false","x":366.5908660888672,"y":261.72728729248047,"wires":[]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
List the available serial ports
Use Node-RED to issueĀ the following HTTP request:
method | GET |
---|---|
URI | http://127.0.0.1:8080/api/v1/helpers/serialports |
body | none |
To do so, in Node-RED, create a flow called "serialports" with the following contents:
JSON version of the flow
[{"id":"83b5eea0.77e04","type":"inject","z":"1815fc03.041354","name":"click to get serialports","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":249,"y":123,"wires":[["802c15cd.802598"]]},{"id":"802c15cd.802598","type":"http request","z":"1815fc03.041354","name":"","method":"GET","ret":"txt","url":"http://127.0.0.1:8080/api/v1/helpers/serialports","tls":"","x":353.99998474121094,"y":219.18183135986328,"wires":[["e13a0a2c.06ff08"]]},{"id":"e13a0a2c.06ff08","type":"debug","z":"1815fc03.041354","name":"","active":true,"console":"false","complete":"false","x":448.9999694824219,"y":319.09090423583984,"wires":[]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
Connect to your SmartMesh IP Manager
Use Node-RED to issueĀ the following HTTP request:
method | PUT |
---|---|
URI | http://127.0.0.1:8080/api/v1/config/managers |
body | { "managers": ["COM10"] } |
To do so, in Node-RED, create a flow called "managers" with the following contents:
JSON version of the flow
[{"id":"352ac77f.320e08","type":"inject","z":"4b63067f.9288b8","name":"click to add manager","topic":"","payload":"{\"managers\": [\"COM10\"]}","payloadType":"json","repeat":"","crontab":"","once":false,"x":138.27272033691406,"y":65.2727279663086,"wires":[["43b23a3b.2c0014"]]},{"id":"43b23a3b.2c0014","type":"http request","z":"4b63067f.9288b8","name":"","method":"PUT","ret":"txt","url":"http://127.0.0.1:8080/api/v1/config/managers","tls":"","x":253.272705078125,"y":161.45455932617188,"wires":[["8632b0e3.e632c"]]},{"id":"8632b0e3.e632c","type":"debug","z":"4b63067f.9288b8","name":"","active":true,"console":"false","complete":"false","x":348.27268981933594,"y":261.36363220214844,"wires":[]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
List operational motes
Use Node-RED to issueĀ the following HTTP request:
method | GET |
---|---|
URI | http://127.0.0.1:8080/api/v1/helpers/motes |
body | none |
To do so, in Node-RED, create a flow called "motes" with the following contents:
JSON version of the flow
[{"id":"6ab6af4f.8f30d","type":"inject","z":"4a64780f.dc05f8","name":"click to list motes","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":117.272705078125,"y":50.272727966308594,"wires":[["5aee536b.ed093c"]]},{"id":"5aee536b.ed093c","type":"http request","z":"4a64780f.dc05f8","name":"","method":"GET","ret":"txt","url":"http://127.0.0.1:8080/api/v1/helpers/motes","tls":"","x":254.272705078125,"y":138.4545669555664,"wires":[["c57e64d9.733608"]]},{"id":"c57e64d9.733608","type":"debug","z":"4a64780f.dc05f8","name":"","active":true,"console":"false","complete":"false","x":338.2726593017578,"y":246.36363983154297,"wires":[]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
Blink LEDs on motes
Use Node-RED to issueĀ the following HTTP request:
method | PUT |
---|---|
URI | http://127.0.0.1:8080/api/v1/oap/00-17-0d-00-00-38-06-45/digital_out/INDICATOR_0 |
body | { "value": 1 } |
To do so, in Node-RED, create a flow called "LED" with the following contents:
JSON version of the flow
[{"id":"88f5a22c.e5996","type":"inject","z":"a1220086.57409","name":"LED on","topic":"","payload":"{ \"value\": 1 }","payloadType":"json","repeat":"","crontab":"","once":false,"x":97.27272033691406,"y":70.2727279663086,"wires":[["b4734888.410a58"]]},{"id":"b4734888.410a58","type":"http request","z":"a1220086.57409","name":"","method":"PUT","ret":"txt","url":"http://127.0.0.1:8080/api/v1/oap/00-17-0d-00-00-38-06-45/digital_out/INDICATOR_0","tls":"","x":266.27268981933594,"y":103.4545669555664,"wires":[["622cfc89.bccb74"]]},{"id":"622cfc89.bccb74","type":"debug","z":"a1220086.57409","name":"","active":true,"console":"false","complete":"false","x":389.2726593017578,"y":179.3636703491211,"wires":[]},{"id":"22d76ea2.ebe1b2","type":"inject","z":"a1220086.57409","name":"LED off","topic":"","payload":"{ \"value\": 0 }","payloadType":"json","repeat":"","crontab":"","once":false,"x":93.27272033691406,"y":150.27274322509766,"wires":[["b4734888.410a58"]]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
Display temperature readings
Use Node-RED to receive the following HTTP requests:
method | POST |
---|---|
URI | /oap |
Geeky details
The JsonServer application continuously receives notifications from the SmartMesh IP manager over its serial port. This includes data notifications.
Its default behavior is to issue an HTTP POST request to url http://localhost:1880/<notification_type>
. When it receives a valid OAP notification, ithe full URL is http://localhost:1880/oap.
Port 1880 is precisely the port Node-RED runs on by default. This means that, by simply listening for HTTP requests on URI /oap
, Node-RED receives the notifications sent by the JsonServer application.
Add a function so the debug console prints only the temperature values received, in C.
JSON version of the flow
[{"id":"3ed8596b.547296","type":"http in","z":"a94e61b2.59c9f","name":"","url":"/oap","method":"post","swaggerDoc":"","x":75.59091186523438,"y":178.00005340576172,"wires":[["d98c9170.75e3f","8c49b10f.e5449"]]},{"id":"593ab632.17cff8","type":"debug","z":"a94e61b2.59c9f","name":"","active":true,"console":"false","complete":"payload","x":358.5908660888672,"y":204.7273178100586,"wires":[]},{"id":"d98c9170.75e3f","type":"http response","z":"a94e61b2.59c9f","name":"","x":192.5908966064453,"y":267.2727737426758,"wires":[]},{"id":"8c49b10f.e5449","type":"function","z":"a94e61b2.59c9f","name":"","func":"if (msg.payload.name==\"oap\" && msg.payload.fields.channel_str==\"temperature\") {\n return {\n payload: msg.payload.fields.samples[0]/100.0\n };\n}","outputs":1,"noerr":0,"x":239.59088134765625,"y":151.2727813720703,"wires":[["593ab632.17cff8"]]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
A little control loop!
You can install the following very simple control loop: set the LED of one mote if the temperature measured by the other mote is larger than 20C
JSON version of the flow
[{"id":"4be45ab5.008614","type":"http in","z":"f37f1253.7cbce","name":"","url":"/oap","method":"post","swaggerDoc":"","x":86.27272033691406,"y":177.27275848388672,"wires":[["5300f7fb.2b2618","750a3d82.d1d3f4"]]},{"id":"5300f7fb.2b2618","type":"http response","z":"f37f1253.7cbce","name":"","x":194.272705078125,"y":265.5454788208008,"wires":[]},{"id":"750a3d82.d1d3f4","type":"function","z":"f37f1253.7cbce","name":"get temp","func":"if (msg.payload.name==\"oap\" && msg.payload.fields.channel_str==\"temperature\") {\n return {\n payload: msg.payload.fields.samples[0]/100.0\n };\n}","outputs":1,"noerr":0,"x":228.27267456054688,"y":129.54547882080078,"wires":[["8ec13b2c.38b8b8"]]},{"id":"8ec13b2c.38b8b8","type":"switch","z":"f37f1253.7cbce","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"20","vt":"num"},{"t":"else"}],"checkall":"true","outputs":2,"x":372.59092712402344,"y":121.54546356201172,"wires":[["a9b1b0ae.6d48b"],["9524e4f7.a34af8"]]},{"id":"a9b1b0ae.6d48b","type":"function","z":"f37f1253.7cbce","name":"LED on","func":"return {\n payload: {\n value: 1,\n }\n};","outputs":1,"noerr":0,"x":519.5908966064453,"y":88.0909194946289,"wires":[["c46fce89.b1fff"]]},{"id":"9524e4f7.a34af8","type":"function","z":"f37f1253.7cbce","name":"LED off","func":"return {\n payload: {\n value: 0,\n }\n};","outputs":1,"noerr":0,"x":519.2726898193359,"y":162.27277374267578,"wires":[["c46fce89.b1fff"]]},{"id":"c46fce89.b1fff","type":"http request","z":"f37f1253.7cbce","name":"","method":"PUT","ret":"txt","url":"http://127.0.0.1:8080/api/v1/oap/00-17-0d-00-00-38-06-45/digital_out/INDICATOR_0","tls":"","x":697.2726898193359,"y":115.2727279663086,"wires":[["6e33ca8f.b4c504"]]},{"id":"6e33ca8f.b4c504","type":"debug","z":"f37f1253.7cbce","name":"","active":true,"console":"false","complete":"false","x":753.2726898193359,"y":215.18183135986328,"wires":[]}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
MQTT integration!
MQTT allows you to coordinate two independent flows, possibly running on different computers.
For that, create two flows:
The first flow publishes the temperature to the HiveMQ MQTT broker on topicĀ DustAcademy/temperature
:
JSON version of the flow
[{"id":"4be45ab5.008614","type":"http in","z":"f37f1253.7cbce","name":"","url":"/oap","method":"post","swaggerDoc":"","x":86.27272033691406,"y":177.27275848388672,"wires":[["5300f7fb.2b2618","750a3d82.d1d3f4"]]},{"id":"5300f7fb.2b2618","type":"http response","z":"f37f1253.7cbce","name":"","x":194.272705078125,"y":265.5454788208008,"wires":[]},{"id":"750a3d82.d1d3f4","type":"function","z":"f37f1253.7cbce","name":"get temp","func":"if (msg.payload.name==\"oap\" && msg.payload.fields.channel_str==\"temperature\") {\n return {\n payload: msg.payload.fields.samples[0]/100.0\n };\n}","outputs":1,"noerr":0,"x":228.27267456054688,"y":129.54547882080078,"wires":[["880dd1ce.39589","1d25b4cd.160dfb"]]},{"id":"880dd1ce.39589","type":"mqtt out","z":"f37f1253.7cbce","name":"","topic":"DustAcademy/temperature","qos":"","retain":"","broker":"a2abf4c8.553448","x":491.5908966064453,"y":149.63638305664062,"wires":[]},{"id":"1d25b4cd.160dfb","type":"debug","z":"f37f1253.7cbce","name":"","active":true,"console":"false","complete":"false","x":395.5908966064453,"y":83.54546356201172,"wires":[]},{"id":"a2abf4c8.553448","type":"mqtt-broker","z":"f37f1253.7cbce","broker":"broker.hivemq.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button
The second flow subscribes to this broker and topic, and switches the LED on/off depending on the temperature value:
JSON version of the flow
[{"id":"6ec61e8a.7e5e4","type":"http request","z":"645a4adb.41c354","name":"","method":"PUT","ret":"txt","url":"http://127.0.0.1:8080/api/v1/oap/00-17-0d-00-00-38-06-45/digital_out/INDICATOR_0","tls":"","x":633.2726898193359,"y":218.27277374267578,"wires":[["ff6f5c0a.fe394"]]},{"id":"ff6f5c0a.fe394","type":"debug","z":"645a4adb.41c354","name":"","active":true,"console":"false","complete":"false","x":753.2726898193359,"y":314.1818313598633,"wires":[]},{"id":"bb7ef7a3.204e38","type":"function","z":"645a4adb.41c354","name":"LED on","func":"return {\n payload: {\n value: 1,\n }\n};","outputs":1,"noerr":0,"x":430.272705078125,"y":182.27276611328125,"wires":[["6ec61e8a.7e5e4"]]},{"id":"22b77e36.fddbd2","type":"function","z":"645a4adb.41c354","name":"LED off","func":"return {\n payload: {\n value: 0,\n }\n};","outputs":1,"noerr":0,"x":444.27268981933594,"y":297.2727737426758,"wires":[["6ec61e8a.7e5e4"]]},{"id":"82b2b938.4af6a8","type":"switch","z":"645a4adb.41c354","name":"","property":"payload","propertyType":"msg","rules":[{"t":"gt","v":"22","vt":"num"},{"t":"else"}],"checkall":"true","outputs":2,"x":298.27272033691406,"y":227.27275848388672,"wires":[["bb7ef7a3.204e38"],["22b77e36.fddbd2"]]},{"id":"f0944028.b9fb1","type":"mqtt in","z":"645a4adb.41c354","name":"","topic":"DustAcademy/temperature","qos":"2","broker":"d510485.da0c1b8","x":155.59091186523438,"y":147.4545669555664,"wires":[["82b2b938.4af6a8"]]},{"id":"d510485.da0c1b8","type":"mqtt-broker","z":"645a4adb.41c354","broker":"broker.hivemq.com","port":"1883","clientid":"","usetls":false,"compatmode":true,"keepalive":"60","cleansession":true,"willTopic":"","willQos":"0","willPayload":"","birthTopic":"","birthQos":"0","birthPayload":""}]
To import the flow above in your Node-RED instance:
- copy the string above (triple-click to select, then copy with Ctrl+C)
- in your Node-RED editor, on the hamburger menu on the upper right, select "Import" > "Clipboard"
- paste the string (Ctrl+V) and click "Import"
- activate the flow by clicking on the "Deploy" button