Node RED and Raspberry PI 101 - langanjp/PI-NodeRED GitHub Wiki

JavaScript

  • Case sensitive
  • End of statement is semi-colon (;)
  • Comparison operators (see http://www.w3schools.com/js/js_comparisons.asp)
    • == is Equality (variable type does not matter)
    • === is Strict Equality (variable type does matter)
    • a reference to 2 different objects (even if those objects contain the same value) will never be equal
  • // and /*, */ are single line and multi-line comments, respectively
  • ' or " can be used as string delimiter. Also ' or " can be used if embedding in a variable
  • node.js based upon Chrome V8 JavaScript - also not yet fully ECMAScript 2015 (ES6) compliant
  • not all JavaScript features will work as expected or as googled due to differences in javascript
  • Tons of resources to google - one that I find myself using a lot: http://www.w3schools.com/js
  • JavaScript objects (name: value pairs)

Sample objects:

var jsobj = {foo: bar, foo2: bar3};

    jsobj.foo --> bar  (this is known as dot notation)
    jsobj["foo"] --> bar  (this is known as bracket notation) (note: dot and bracket can be combined)
    jsobj[0] --> bar

var attribute = "foo2";

    jsobj.foo2 --> bar3
    jsobj[attribute] --> bar3 (in bracket notation, you can use either a string or a variable) 
  • JSON = JavaScript Object Notation is a text representation of data like xml or csv. JSON object is not a JavaScript object, but can typically be easily read (de-serialized) into a JavaScript object

Visual Editor

Palette - contains the "nodes":

  • Inputs
  • Outputs
  • Functions

Canvas

  • Click on the + sign to add a new tab ("flow")
  • Drop and drag palette objects ("nodes") to the screen
    • You select by clicking and holding the mouse button. Let the mouse button when you want to drop
  • Draw lines between nodes
  • Click on node to get configuration info
  • Double click to edit a node
  • Once you are done editing, click the Deploy button

Info / Debug

  • Info: Can view info on a node (instructions on how to use node)
  • Debug: View information from a debug node

Node-RED url

To access the web based editor, you will need to know the hostname or IP address of your RaspberryPI. In my case, my hostname is raspberrypi and the IP address in 192.168.1.101 so the url is at that address on port 1880:

http://192.168.1.101:1880 or http://raspberrypi:1880

Hello World

Insert an "inject" node (gray box on the left) and a Sense HAT output node (light blue box on right), drawing a line between them

Double click on the inject node (it has defaulted to "timestamp"), select a string Payload, type Hello World and click done

Click the button on the left hand side of the Hello World node to run this flow. This will display a scrolling Hello World on your PI Sense HAT

Another example

Insert a new inject mode and connect to the existing Sense HAT output node.

  • For the inject mode:
    • Payload: select string and leave blank
    • Name: Clear
    • Click Done

This will clear / reset the PI Sense HAT display. Try clicking Hello World, than Clear right after - it will clear the current message

Using a function node


Insert (as pictured above)

  • inject node
    • Payload: string: Aquamarine (click Done)
  • function node (connected as shown above)
    • double click the node and replace text inside with this:
var val = msg.payload.toString();  
msg.color = val;

return msg;

Click the Aquamarine inject node. This will send the "Aquamarine" payload to the PI Sense HAT and use the function to change the color property to aquamarine

Node-RED message "msg" object

When you click on an inject node (or use another type of input) a message object is created. This message object is what moves through the different nodes. The messages can be switched, split, combined or be used to spawn entirely new single or multiple messages into the flow. Some of the more common message attributes that you will use:

  • msg.payload - main body - contains the data - often a JSON object, but can be any object type. Most of what we work on here will be around the msg.payload
  • msg.title
  • msg.topic
  • msg._msgid - Node-RED identifier of message
  • msg.whateveryouwanttoaddforwhateverreason - you can add attributes and objects to the msg and the msg.payload in anyway you want

Multiple inputs to a function


Insert and connect (as pictured above)

  • input node
    • Payload: string: Aggies
  • input node
    • Payload: string: Texas
  • input node
    • Payload: string: (leave blank)
  • function node (connected as shown above)
    • Name: color
    • Double click the node and replace text inside with this:
 var val = msg.payload.toString();
 switch (val) {
     case 'Aggies':
         msg.background = "#500000"; //Aggies Maroon
         msg.color = "White";
         msg.payload = "Gaggies";
         break;
     case 'Texas':
         msg.background = "191,87,0";
         msg.color = "White";
         msg.payload = "t.u.";
         break;
     default:
         msg.background = "10,89,168"; //osisoft blue
         msg.color = "#FOEFEB"; //almost white
         msg.payload = "Coach Yung";
 }
 
 return msg;

Click on any of the 3 new inject nodes. Each one will change the message and color as programmed in the color function node

Practice with Sense HAT output (switch json messages based upon message topic)

Insert and connect (as pictured above)

  • PI Sense HAT (input - look in Raspberry_Pi section of palette)
  • switch (function)
    • Property: msg.topic
    • == String: environment --> 1
    • == String: joystick --> 2
    • == String: motion --> 3
  • delay (function)
    • Action: Limit rate to
    • Rate '6' msg(s) per '1' 'Minute'
    • checked: drop intermediate messages
  • debug (output)
    • will automatically default to msg.payload. Can change output to entire msg or pick any part of the msg object

First, click on the debug node on the far left (while looking at the debug pane on the right). You will notice huge amounts of messages rapidly coming from the PI Sense HAT, covering the 3 topics (environment, joystick and motion). Un-click the debug when you are ready to move on to the next step.

Next, click on the debug node on the top right to show its output in the debug pane. This is showing the filtered (switched) output from the "environment" topic only, with a new message every 10 seconds. Un-click the debug when you are ready to move to the next step.

Now, click on the middle right debug node and move the joystick (msg.topic == "joystick"). You will see the different messages depending upon joystick direction and whether you are holding it in that direction. Un-click the debug when you are ready to move to the next step.

Finally, take (drag with your mouse) the purple delay node at that bottom that is not connected and slide it slowly to the line right above, until it you see a dotted line. Drop it and it will now be inserted into the existing line. Feel free to check with the bottom right debug node to see the "motion" messages (and un-check when you are done).

Function or Split? Either works. Plus accessing OS commands for more data

Insert and connect (as pictured above)

  • inject node:
    • Payload: String: (leave blank)
  • function node (top)
    • Double click the node and replace text inside with this:
 var timestamp = new Date().toISOString();
 msg.timestamp = timestamp;
 
 var piinfo = {}; // this is a (empty) javascript object
 // note for both js and linux both " and ' can denote string, so you can use them wisely 
 piinfo.freemem = 'cat /proc/meminfo | grep MemFree | cut -d ":" -f 2 | cut -d "k" -f 1';
 // the cpu temp get a little harder - we need to use a \' for the '
 piinfo.cputemp = 'vcgencmd measure_temp |cut -d "=" -f 2 | cut -d "\'" -f 1';
 
 // could use javascript to split into 2 messages or use a "split" node
 var newmsg = {payload:{}};
 var timestamp = new Date().toISOString();
 newmsg.timestamp = timestamp;
 for(var prop in piinfo) {
     newmsg.payload = piinfo[prop];
 node.send(newmsg);
 }
 
 //return msg;  // notice this is commented out - as we created new messages above with the node.send
  • function node (bottom)
    • Double click the node and replace text inside with this:
 var timestamp = new Date().toISOString();
 msg.timestamp = timestamp;
 
 var piinfo = {}; // this is a (empty) javascript object
 // note for both js and linux both " and ' can denote string, so you can use them wisely 
 piinfo.freemem = 'cat /proc/meminfo | grep MemFree | cut -d ":" -f 2 | cut -d "k" -f 1';
 // the cpu temp get a little harder - we need to use a \' for the '
 piinfo.cputemp = 'vcgencmd measure_temp |cut -d "=" -f 2 | cut -d "\'" -f 1';
 
 msg.payload = piinfo;
 
 return msg;  
  • split (function)
    • Leave /n (new line) as default Split
  • exec (advanced)
    • Name: os commands
    • leave + Append: as default (msg.payload checked)
  • debug (msg)
    • Output: complete msg object
  • debug (msg.payload)
    • leave Output as default to msg.payload

This shows an example of 2 different ways to split the payload of a message. In this case we want to split the input to allow for 2 different OS commands to be run, using the same flow. Check the debug from the split to compare the 2 sets of 2 messages. While the split node message has an additional "parts" object to allow you to easily combine later on, the main payload is still the same and will result in the same output when put through the OS commands node. Also notice that the output of the inject node triggers 2 independent flows. Un-click debug when you are done looking at the difference.

Next, check the msg.payload debug and click inject. This will display the free memory (mb) and the cpu temperature (°C). Un-check debug when finished.

Problems?

If something isn't working quite right here, see the next page for directions on how to import these and the other flows that you will need for the rest of this tutorial. (It is the flow saved as 101.json)

Next Section:

Importing Node-RED flows and PI Asset Framework (AF)