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)