Professional Documents
Culture Documents
2
Using the switch node to handle a
JSON object
This example continues to use the MQTT node we setup in Example 3.1. If you aren’t
following these examples sequentially you may want to review example 3.1 as it
shows how to use the free MQTT broker, HiveMQ which is needed for the MQTT
node.
One of the nice features of having a JSON object is that you can easily act on its
properties. A useful node for this is the switch node. Its role is to ‘switch’ or route
messages depending on the incoming message properties. For example, you can
check the msg.payload.analyze property and, depending on its value (true/false),
decide to route a message to one of the switch node’s outputs.
Drag a switch node and double-click on it. Configure it to evaluate the property
“msg.payload.analyze”. If true, send the message to the first output; if false, send it to
the second output as shown in in Fig 3.4.
Figure 3.4 Configuring the switch node to route based on a message property
Now you can connect two debug nodes as shown in Fig 3.5 – when you set up
multiple outputs for a node, they are numbered from the top, so output 1 is the top
output and output 2 is at the bottom in Fig. 3.5.
If you now go back to the HiveMQ input page and send the MQTT message
{“analyze”:true, “value”:6}, you will see that the first (top) output is activated and the
incoming messages is routed, or ‘switched’, to output 1. If you send the original
message {“analyze”:false, “value”:10}, the switch node will activate output 2 and the
original debug node will fire. Hovering the pointer over the debug message will show
which debug node is printing out the message as shown in Fig. 3.6.
As you can see, this provides you with a built-in Node-RED node that allows you to
quickly determine the contents of incoming messages and direct the message
through to different parts of the flow depending on the input.
Node RED Programming Guide
Programming the IoT
In this example, you’ll continue with your MQTT theme and see how, now that you
have successfully ‘switched’ the message flow based on the incoming MQTT message,
you can add a new message property msg.payload.note.
If you aren’t following these examples sequentially, you may want to review Example
3.1 to see how to setup a free MQTT service and configure the incoming MQTT node
used in these examples.
First, let’s drag and drop a change node and connect it to the second output of the
switch node (Fig 3.7). As you will remember, this is the output that fires when
msg.payload.analyze is set to false.
Now configure it to set the property msg.payload.note to “this is not being analyzed”
as shown in Fig 3.8.
Figure 3.8 Using a change node to add a new message property
When you receive a message that the switch node sends on the 2nd output, it will be
modified to contain a “note” element with the string “this is not being analyzed”. If
you deploy and test the flow by sending the MQTT message from HiveMQ, you’ll see
the output as shown in Fig 3.9.
Figure 3.9 The result of switching and then changing the message
https://raw.githubusercontent.com/SenseTecnic/nrguideflows/master/lesson3/3-
3_changenode.json
Node RED Programming Guide
Programming the IoT
If you aren’t following these examples sequentially, you may want to take a look
at example 3.1 to see how to create a free MQTT account and then use the credentials
to setup the MQTT node used in this example. Example 3.2 explains the switch node
and Example 3.3 explains the change node.
You’ll start by adding in another change node which you’ll connect to output 1 of the
switch node. You’ll then connect an rbe node to the switch node as shown in Fig 3.10.
Let’s connect a change node, and an rbe node like this. To remind us that this output
deals with the flag “analyze”, add a comment node and write “Analyze = true”.
Comments are useful when writing complex flows.
Figure 3.10 Adding an rbe node to check if our input data has changed by more than
20%
Edit the change node to set the msg.payload to msg.payload.value. This will set the
output of this node to the value found in the msg.payload.value element of the input
received (Fig 3.11).
Since you want to determine if this value has changed by 20% or more, you’ll need to
double-click on the rbe node and configure it to block unless the value changes by
more than 20%.
Fig 3.12 Setting the rbe node to check msg.payload.value
To test the flow, deploy this flow and then return to the HiveMQ page and send a
series of messages. Firstly, you’ll need to set the analyze value to true so that the
switch node sends through a message on output 1. If you use the original message
value of 6, this will fail to pass the rbe node. If you then send a second message of
value 10, the rbe node will evaluate the difference between 6 and 10, see it is greater
than 20%, and send on a message to the final debug node which will print on the
debug pane as shown in Fig 3.13.
Fig 3.13 Confirming that 10 is more than 20% larger than 6 using an rbe node.
This example continues our theme of manipulating MQTT input data. If you aren’t
familiar with how to setup an MQTT node then refer to Example 3.1. Examples 3.2-4
explain the rest of the nodes in this flow.
Let’s assume you want to scale your value (originally in the range 0-10) to a range (0-
255) when you aren’t doing any analysis. This means we are dealing with the lower
part of the flow fired when the switch node evaluates the Analyze property as false.
To do this, select the change node you configured above (set msg.payload) and copy
it with ctrl+c, then ctrl+v. Attach a range node as shown in Fig 3.14.
Double-click on it, and configure it to map the input from 0-10 to 0-255 as shown in
Fig 3.15.
The scale node has three options set by the action field. The default will scale
according to the mapping given but will happily scale values outside the given ranges,
using the same mapping. Scale and limit to target range means that the result will
never be outside the range specified within the result range. A third option, Scale and
wrap within the target range means that the result will essentially be a “modulo-
style” wrap-around within the result range.
Then return to the HiveMQ test page and post {“analyze”:false, “value”:10} as a new
MQTT message to the same topic.
Figure 3.15 Setting the scaling ranges for input and output of the scale node
If you return to your Node-RED window, you will see that the debug node associated
with the lower part of the flow has fired, showing that the msg.payload.value
property that you set as 10 when you published it to MQTT, has been scaled up 255
as shown in Fig 3.16.
Figure 3.16 Final scaled output when analysis is turned off
If you’ve not been following these examples sequentially and the MQTT nodes are
not familiar to you, take a look at Example 3.1 to see how to setup and provision the
MQTT node.
To try that, drag and drop three inject nodes and an mqtt output node as shown in
Fig 3.17, and configure and wire up as shown
You can now test the flow you created to analyze the MQTT message directly from
the workspace by clicking on the three inject nodes in sequence. The first will
exercise the part of the flow handling the case when analysis is turned off; the 2nd
two messages will cause the path with the rbe node to be exercised.
https://raw.githubusercontent.com/SenseTecnic/nrguideflows/master/lesson3/3-
6_mqqtout.json
Node RED Programming Guide
Programming the IoT
The websocket node comes in two flavours, input and output, allowing you to listen
for incoming data (input) or to send (output) on a websocket. The output version is
designed to check to see if the output payload originated at a websocket in a node, in
which case it responds to the original sender. Otherwise it will broadcast the payload
to all connected websockets.
In addition, both input and output websocket nodes can be configured as either
server or client – in server mode they ‘listen on’ a URL, and in client mode they
connect to a specified IP address.
To see how the websocket nodes work, you’ll use a public websockets echo server
which runs on the public site: (https://www.websocket.org/echo.html).
Drag an inject, websocket in, websocket out and a debug node onto the workspace
and connect them as shown in figure 3.18.
Configure the inject node to send a string payload of “Hello There” (Fig 3.19)
Figure 3.19 Configuring an inject node to send on a websocket
Deploy. When you click on the inject node you will see the message printed out as
shown in Fig 3.21
https://raw.githubusercontent.com/SenseTecnic/nrguideflows/master/lesson3/3-
7_websockets.json
Node RED Programming Guide
Programming the IoT
This example shows the use of the tcp node. It could equally be configured with the
udp or http nodes in a similar manner.
To get started, let’s connect an inject, function, tcp request, and debug nodes as
shown in Fig 3.22.
Figure 3.22 building a TCP request and sending on a tcp output node
Edit the first function node to add a function that sets the string “GET /
HTTP/1.1\r\n\r\nHost: www.google.com” as payload as shown in Fig 3.23.
This string is a standard HTTP request, indicating it is a GET request, the protocol is
HTTP 1.1 and the host is www.google.com. The \r\n\r\n is two return/newline pairs
which is required in the HTTP protocol.
Figure 3.23 Building a TCP request in a function node
Configure the tcp request node to connect to the www.google.com server, on port 80.
Configure it to close the connection after 1 second (1000 ms) as shown in Fig 3.24.
If you deploy the flow and click on inject, you will make a request to Google and will
get a TCP response. The debug node will print the response as a string as shown in
Fig 3.26.
Figure 3.26 Printing out the response to a well formed HTTP request sent over a TCP
connection.
Some of you may be wondering why you need to use a function node to build the
HTTP request that we sent over TCP. Why not just use the inject node to input the
string? The reason is that the inject node ‘escapes’ the string it uses, causing the
return/newline you inserted to be removed. This in turn confuses the receiving
server (Google) into not returning a response as it waits for the missing
return/newlines. So instead, you build the string in a function node. This is one of
those ‘gotchas’ that trips up even experienced Node-RED programmers, so always
read the info pane for nodes to make sure you understand any limitations or
constraints.
https://raw.githubusercontent.com/SenseTecnic/nrguideflows/master/lesson3/3-
8_tcp.json
Node RED Programming Guide
Programming the IoT
For each node, you’ll see a brief overview of its functionality and an indication of
which example in this lecture series uses the node, so you can look in more detail at
how to work with the node. This lecture is mostly a reference section. However, it is
worth looking quickly through the nodes, so that you have an idea of the basic
functionality available to you as you begin to craft your own flows.
Input nodes
There are 7 basic input nodes installed by default. They cover the basic
communications mechanisms that IoT applications are likely to use. Ranging from
lower-level internet protocols such as UDP and TCP through to the higher-level
HTTP and the publish/subscribe MQTT.
Node
Description Examples
name
Node
Description Examples
name
Node
Description Examples
name
Node
Description Examples
name
Social nodes
The basic social media nodes support interaction with email and with Twitter. They
enable flows to send or receive email, or to send or receives tweets.
Node
Description Examples
name
twitter Tweets the msg.payload on the configured account. Can send direct Example
out messages and will send binary data as an image. 2.2
Storage nodes
The default node set for storage, because it is targeted at devices such as the
Raspberry Pi are quite limited and focus on file based storage.
Figure 4.2 The default storage, analysis, advanced and Raspberry Pi nodes.
You should note that FRED, because it’s a cloud service, doesn’t support the basic file
nodes. Instead it replaces these with a variety of storage nodes ranging from Mongo
to Dropbox. However, for completeness the default nodes are covered here, so that
you can use them, if you install Node-RED yourself (see lecture 7).
Node
Description Examples
name
Reads the specified file and sends the content as msg.payload, and the
filename as msg.filename.
file in The filename can be configured in the node. If left blank, it should be Examples
set on msg.filename in an incoming message.
Node
Description Examples
name
Advanced nodes
A set of miscellaneous nodes offering various types of functionality.
Node
Description Examples
name
The full filename of the file that actually changed is put into
watch
msg.payload, while a stringified version of the watch list is Examples
returned in msg.topic.
msg.file contains just the short filename of the file that changed.
msg.type has the type changed, usually file or directory, while
msg.size holds the file size in bytes.
This node monitors an RSS/atom feed for new entries and delivers
feedparse new entries as messages. It can be configured to query the feed at Examples
a specific interval.
Calls out to a system command and provides 3 outputs: stdout,
stderr, and return code. By default uses exec(), which calls the
exec Examples
command, blocks while waiting for completion, and then returns
the complete result in one go, along with any errors.
Raspberry Pi nodes
Node
Description Examples
name
Note: these nodes are available in FRED by installing them using the FRED
installation panel. For a quick example of how to install nodes check out this tutorial.
As you will see, the majority of these additional nodes focus on services and
capabilities that match well with FRED’s nature, i.e. a cloud-based service. In many
cases they focus on using Node-RED for web based integration or to access
enterprise level services.
Figure 4.3 The extended FRED nodes
Node
Description Examples
name
pushbullet Allows you to send Pushbullet messages to all devices that have
Examples
out the Pushbullet app installed.
XMPP out Sends messages to an XMPP instant messaging server. Uses Examples
topics to send to rooms (channels) and supports presence
notification.
Node
Description Examples
name
By default all file events are reported, but the filename pattern
can be supplied to limit the events to files which have full
dropbox
filenames that match the glob pattern.
watch Examples
MongoDB
Aggregate provides access to the aggregation pipeline using the Examples
in
msg.payload as the pipeline array.
You can either set the collection method in the node config or on
msg.collection. Setting it in the node will override
msg.collection.
wotkit
out The message.payload must contain an object of key-value pairs
Examples
matching the sensor fields. The node is configured with WoTKit
user credentials.The sensor name should be in the form
{username}.{sensorname}, or you can use the numeric sensor id.
Node
Description Examples
name
smooth A simple but flexible node to provide various functions across Examples
several previous values, including max, min, mean, high and low
pass filters. Only works on numbers and will fail if it can’t convert
the input to a number.
Node
Description Examples
name
Other nodes
The following nodes are available in FRED and don’t fit into the basic categories that
vanilla Node-RED provides. These include nodes to access and control Google
services, enterprise nodes such as Salesforce access, nodes for accessing
transportation API (e.g. Transport for London) and other miscellaneous nodes for
access to weather services, etc.
Google nodes
FRED supports several Google nodes to interact with a range of Google services.
Fitness nodes
The FRED fitness nodes cover a number of popular fitness devices.
Node
Description Examples
name
strava This node returns the most recent activity in the authenticated
Examples
user’s account whenever it receives a message. Returns the
activity, location and time when available.
Weather nodes
FRED adds a set of nodes to give access to a variety of weather services.
Node
Description Examples
name
Transport nodes
Node name Description Examples
Get live bus departure/arrival info for London (UK) buses and
river buses.
TfL bus This node enables the user to get bus or river bus arrival
Examples
information for selected lines arriving at selected stops. The
node returns the first vehicle/vessel to arrive at a particular
stop. The data is provided by Transport for London.
Formatting nodes
Node
Description Examples
name
Summary
In this lecture, you were presented with a summary of the default Node-RED nodes
available on installation, and the extended set of nodes that FRED adds. As you have
seen, there is a wide variety of nodes allowing you to build complex flows with little
or no programming.
You’ve also seen that not all nodes are always available, for example the Raspberry Pi
nodes don’t work unless you are actually running Node-RED on a Pi. So it always
pays to check that you can run the nodes you need in your environment.
However, given the large number of nodes available, and the fact that the community
is creating new nodes on a daily basis, you are likely to be able to find a node that
meets your needs. If not, you can fall back on the flexible function node, or even
create your own, something that will be discussed in the advanced lectures.
Node RED Programming Guide
Programming the IoT
Home
List of examples
In this lecture, you’ll take a more detailed look at Node-RED’s programming model
and some of its key concepts and explore the details of the message flow model that
underlies Node-RED. Then you’ll dive into how to program your own function nodes
using JavaScript and create reusable sub flows to add your own functionality to the
set of nodes supplied with Node-RED.
We use a cloud hosted version of Node-RED for these lectures called FRED. Sign up for a
free account at FRED. Examples in the early lectures will work with other installations of
Node-RED, later lectures use nodes you will need to install yourself if you don’t use
FRED.
Examples
Example 5.1 Creating and returning a new message in a function node
Key Concepts
As you’ve learned so far, when you program with Node-RED, you create flows that
are networks of lightweight components, called nodes, that exchange messages along
pre-defined connections or wires. Let’s look at these concepts in a bit more detail.
Flows
Node-RED programs or flows are a collection of nodes wired together to exchange
messages. Under the hood, a flow consists of a list of JavaScript objects that describe
the nodes and their configurations, as well as the list of downstream nodes they are
connected to, the wires.
Messages
As discussed in Lecture 2, messages passed between nodes in Node-RED are, by
convention, JavaScript Objects called msg, consisting of a set of named
properties[2]. These messages often contain a msg.payload property with, you
guessed it, the payload of the message. Nodes may attach other properties to a
message, which can be used to carry other information onto the next node in the
flow. When this happens, these extra properties will be documented in the node
documentation that appears in the node info pane when you select a node in the
Node-RED workspace.
Messages are the primary data structure used in Node-RED and are, in most cases,
the only data that a node has to work with when it is activated. This ensures that a
Node-RED flow is conceptually clean and stateless – each node is self-contained,
working with input messages and creating output messages. Apart from the use of
context data (see later in this lecture), this means that the effect of a node’s
processing is either contained in its output messages, or caused by internal node
logic that changes external things such as files, IO pins on the Raspberry Pi or
Dropbox files; there are no side effects that could affect the behaviour of other nodes
or subsequent calls to the same node.
This is one of the key advantages of a flow-based language. Because nodes are self
contained and typically only interact with other nodes using messages, you can be
sure that they have no unintended side effects and so can be safely re-used when you
create new flows. This ‘safe’ code reuse is exactly what you are doing each time you
drag and drop a node onto your workspace.
Nodes
Nodes are the primary building block of Node-RED flows. When a flow is running,
messages are generated, consumed and processed by nodes. Nodes consist of code
that runs in the Node-RED service (javascript .js file), and an HTML file consisting of
a description of the node, so that it appears in the node pane with a category, colour,
name and an icon, code to configure the node, and help text. Nodes can have at most
one input, and zero or more outputs[3].
During the initialization process, the node is loaded into the Node RED
service. When the browser accesses the Node RED editor, the code for the installed
nodes is loaded into the editor page as illustrated in Fig. 5.1.
Figure 5.1 Node RED loads both HTML for the editor and JavaScript for the server
from the node packages.
As you saw in Lecture 2 (Figure 2.2), there are three core node types:
Wires
Wires define the connections between node input and output endpoints in a flow.
They (typically) connect the output endpoints of nodes to inputs of downstream
nodes indicating that messages generated by one node should be processed by the
connected node next. Note that it is possible to connect more than one node to an
endpoint using wires. When multiple nodes are connected to an output endpoint,
messages are sent to each connected node in turn in the order they were wired to the
output. When more than one node output is connected to an input endpoint,
messages from any of those nodes will be processed by the connected node when
they arrive. It is also possible to connect downstream nodes to upstream nodes to
form loops. (You’ll see an example of wiring a node to an upstream node in example
6.5 in Lecture 6).
Context
So far, you have learnt that messages are the only way to get data into and out of
nodes. While this is generally true, there is one exception to this rule which is
available to function nodes. function nodes have access to a special object called
context that is used to hold data in memory that lasts from one message arriving to
the next[4]. This is important for nodes that need to maintain an index or count or
sum data in messages. In addition to this local context, a global context
context.global is available for sharing data between all of the function nodes of a
flow. Some use cases for context will be covered when the function node is discussed
in more detail.
Function Nodes
The function node is the ‘Swiss Army knife’ of nodes that you can use when there is
no existing node dedicated to your task at hand. It’s great for doing specialized data
processing or formatting for example. As the name implies, a function node exposes
a single JavaScript function. Using the function node, you can write your own
JavaScript code that runs against the messages passed in and returns zero or more
messages to downstream nodes for processing. To write function nodes, you write a
JavaScript function using the built-in code editor as shown in Fig. 5.2.
Figure 5.2 The function code editor.
If you are already familiar with writing JavaScript, then you can skip the next
section, which is a very quick primer on JavaScript, which is used when you are
writing your own function nodes.
JavaScript Primer
While we don’t have enough space here to cover JavaScript completely, we’ve written
a short primer for those familiar with other programming languages to get started
writing your own nodes. To experiment with JavaScript, you can use the JavaScript
console supplied with your favourite browser or startup node.js to run the Read-
Eval-Print-Loop (REPL) on your machine.
The most simple function node just returns null. When you return null, no message
is passed on to downstream nodes and the flow ends here. To create a node that
passes the message “as is”, you can simply return the message itself. This is the
default code in a function node.
1. return msg;
Neither of these cases are very interesting, so let’s add some content to the payload.
In this example, and the next set of examples that explore writing JavaScript code for
the function node, you will use the same flow (i.e that shown in Fig 5.3) and you’ll
edit the function node to change the JavaScript using the function node editor as
shown in Fig 5.2.
1 msg.payload += “world”;
2 return msg;
In this example (listing 5.12), a simple string concatenation operator is used to add
the string “world” to the incoming message payload (line 1). This updated payload is
then sent, using return, as the output message (line 2) to the next node in the flow.
If you edit the function node you’ve just created and type in the code from listing 5.12
when you deploy and test the flow, you will see in the debug pane the timestamp for
the inject node and the text “world” appended.
Obviously, if you now edit the inject node to inject a string instead of the timestamp,
and set the injected string to “hello”,you will see “hello world” in the debug pane,
when you deploy and test.
If you modify the test function node you set up as shown in Figure 5.2 and use the
code from Listing 5.13 when you deploy the flow and hit the inject button, the new
message you created is output when it arrives at the debug node.
First, let’s edit the function node to tell Node-RED that the node will have three
outputs, using the node configuration window (Fig. 5.4).
Figure 5.4 Setting the number of outputs that a function node provides
Listing 5.14 illustrates how to send a message to one of three different outputs based
on a message payload value ‘high’, ‘med’ or ‘low’:
1. if (msg.payload == “high”) {
2. return [ msg, null, null ];
3. } else if (msg.payload == “med”) {
4. return [ null, msg, null ];
5. } else {
6. return [null, null, msg];
7. }
Line 1 checks the incoming payload to see if it is set as “high”. If yes, then it passes on
the message on the first output and null messages on the 2nd and 3rd output at line 2
by returning an array with three elements, [msg, null, null]. A “med” message causes
a message to be returned on output 2 (line 4). Anything else returns a message on
output 3 (line 6).
To try it out, wire it up to three inject nodes and three output nodes as shown in
Figure 5.5. Set the different inject nodes to inject a text string of either low, med,
high, edit the test function and use listing 5.14, and then deploy. As you select the
different inject nodes, you will see the appropriate debug node fire in the debug pane.
Listing 5.15 Returning multiple messages on one output using an array of messages
1. var msgList = [];
2. for (var i=0; i<10; i++) {
3. msgList.push({payload:i});
4. }
5. return [msgList];
Node functions
Your function node code has access to a few utility functions from the built-in
node module. These allow you to log text to the console or debug output and send
messages from callback functions rather than returning them from the function node
itself.
In FRED, the Node-RED console can be viewed by going to the landing page, then
clicking on the “Status” menu in the drop down menu under your name. Since it can
be a bit cumbersome to switch back and forth between the NR editor and the console,
you can open the status dialog in a separate tab, then hit the refresh button to see
updates to the console. Since the node.warn and node.error functions also output to
the debug pane, it is sometimes useful to utilize these functions for debugging when
the console is not available.
In addition to these logging and debugging functions, the node.send() function can
be used to send messages to downstream nodes in a callback function, rather than
returning the message(s). Listing 5.16 illustrates how to use node.send() in a function
node that sends a message after a specific amount of time.
Other modules that are available to function nodes include the following:
console – while the Node.js console module is available, node.log() is the preferred
method of logging
util – the Node.js util module. This module provides useful utilities such as string
formatting functions and generating string representations of objects. For more
informaton on the util module see the Node.js documentaiton at
https://nodejs.org/api/util.html
Buffer – the Node.js Buffer module is for handling raw binary data from TCP streams
or from files. For more informaiton on the Buffer module, see the Node.js
documentation at https://nodejs.org/api/buffer.html.
1. if (!context.value) {
2. context.value = 0;
3. }
4. context.value +=1;
5. msg.count = context.value;
6. return msg;
It can be wired up, as usual based on that shown in Figure 5.3), to give it a try. Be
sure to change the debug node to display the ‘complete msg object’ so you can see
your count property. You’ll probably notice that context is reset every time the
function node is deployed. If you need to save state between deployments, you’ll need
to use some external storage such as a file or a database.
Figure 5.6 Flow to calculate the time elapsed for a message to go through the delay
node.
The code for the function node called save the start time is shown in Listing 5.18.
Listing 5.18 Code to save the start time of the flow in a global context property.
Another function node, called time elapsed (see Listing 5.19), generates a message
containing the time elapsed since a message passe through the save the start
time function.
Add and configure a delay node to delay the message for 2 seconds, click on the inject
node, and wait about 2 seconds. If all goes well, the debug output should indicate the
time elapsed was close to 2 seconds.
The advantage of this approach is that we need not have a message that carries the
start time. The disadvantage is that, if another message arrives at save start
time before time elapsed, the context.global.startTime variable will be overwritten.
To save your code in the function library, click on the Book icon in the function node
configuration dialog to the right of the name text edit box, and select “Save to
Library”. You can then provide a folder name and a file name to save your code as
shown in Fig. 5.7.
Figure 5.7 Save to library dialog
To make use of your code you can create a new function node, click on the book icon,
then click on “Open Library…” then choose your saved library code. The code will be
loaded in the dialog. If that’s the code you want, click OK, and it will be added to your
function node. You can then edit it as needed.
Sub-Flows
Sub-flows are a way to reuse useful flow segments in Node-RED as fully fledged
nodes in the node pane that you can drag into your flows. While it’s possible to save
flow segments using the flow library (as described at the end of lecture 2), having
flow segments in the node pane provides a level of encapsulation and information
hiding that importing saved flows doesn’t offer. Encapsulation means that it is
organized into a single item (node) that can be referred to using a single name;
information hiding means that the inner workings of the sub-flow are hidden – you
can change how the sub-flow does its job and the flows that use it will not change.
They can be created in two ways: either by selecting parts of your flow and creating
the sub-flow from the selection, or from scratch. To create one from a selection,
select the nodes in the sub-flow, click on the menu > Subflows> Selection to
Subflows. This will immediately create a new, numbered sub-flow in the node pane
under the “sub-flows” category.
You can also create a new sub-flow from scratch by clicking on the menu > Subflows
> Create Subflow menu. After creating a new sub-flow, or editing an existing sub-
flow by double-clicking on it in the node pane, a sub-flow tab will appear in the main
pane. Unlike a regular tab, this tab has four buttons in the top left: “edit name”, “+
input”, “+ output” and “delete subflow”. In this pane, you can edit the sub-flow, add
nodes by dragging and dropping them to the sub-flow pane, and wire them up as
needed. To connect this sub-flow to the flows that use it, you can add a single input
node and any number of output nodes, using the +input and +output buttons.
To edit the name of the sub-flow, click on ‘edit name’ in the pane and call it
something like Sentiment Switch. You will see your new node in the sub-flows
section in the node pane.
Figure 5.10 Flow using sentiment switch sub-flow to display positive tweets about
hockey and the canucks.
Let’s use this to output only the positive messages about hockey from a Twitter
feed. Add a new tab, drag in a Twitter node, the new Sentiment Switch sub-flow
node you created and a debug node, as shown in Fig. 5.10. Wire up Twitter to the
input and debug to the third output node of your new Sentiment Switch. After a
minute or so, hopefully, someone will tweet something positive about hockey, and
you’ll see some output in the debug pane!
To test out our new flow, drive it from an inject node and set up a debug node, as
shown in Figure 5.12. Be sure to show ‘complete msg object’ in your debug node to
see the counter message property that was added.
Now you have a ‘Counter’ sub-flow node you can drag in any time you like and use it
in multiple locations in a flow.
Openweathermap is a platform that provides weather forecast data from all over the
world. By using the APIs of the website, we are able to query any location in Slack.
You will need to setup a developer account on Openweathermap in order to use the
openweathermap node on FRED.
This example will show you how to build a Slack integration that allows a slack user
to query the openweathermap platform and returns weather data based on the
simple query term.
For this example you will need to create what Slack calls a Slack Bot User
(https://api.slack.com/bot-users) that will serve as a virtual user in your Slack
application. So go ahead and create new bot
(https://my.slack.com/services/new/bot), see Fig 5.13. If you don’t already have a
Slack account, you will be guided through the account creation before you can return
to the bot service.
Figure 5.13 Creating a new Slack Bot
After creating your Slack Bot you will be given an API Token in the form (Fig. 5.14):
1. xoxb-6816691748-vkIsdfsafE1RgF251yjPSm90WAAsadfSDF1
Which you should note down as you will need this token when you set up your flow.
Figure 5.14 Slack returns a new API token for access to the Bot
Next, you will need to have the openweathermap node installed on your FRED
instance. Simply install openweathermap node in “Add or Remove Nodes” from
the side bar.
To do that, you should log into your FRED account and set up a new canvas for the
flow. Drag and drop a Slack Bot In node into your canvas. Double click on it and
configure by adding your Slack Bot API Token (Fig. 5.15). By default it will only listen
into the #general channel (you can change this).
Figure 5.15 Configuring the Slack node with API token and channel
Now connect a function node and double click on it. You will need to set the function
node with 2 outputs. Copy and paste the following function (Listing 5.20, Fig. 5.16):
if (query.length == 2){
msg.location={
city:query[0],
country:query[1]
} else {
msg.payload="invalid search";
return [null,msg]
Figure 5.16 Writing some function code to parse for queries on a slack channel
All this function does is parse the messages received by our Bot. If the
message contains two words and the words are separated by “,”, it will slice the string
and create a query parameter in the output message. This will become handy in the
next step.
Next, connect an openweathermap node to your function node and don’t forget to
add the API key in the configuration tab.
Then, you need to add a function node after the openweathermap node to parse the
output response.
msg.payload.detail+". "+
return newMsg;
Finally, you’ll need to add a new slack bot out node and configure it with your Bot
API Token and Channel. The final flow will look like this (Fig 5.17).
Now, to test that the flow work, return to your slack home page and either select the
bot you created from the panel on the left. You’ll be presented with an input box, so
type in:
1 Vancouver, Canada
The bot will query weather data from openweathermap and parse the weather
forecast data back to the slack bot (Fig 5.18).
Figure 5.18 Results of querying ‘weather’ via your new slack bot
You are welcome to developer your own query features to find out all other possible
functions you can have with FRED!
Summary
This lecture reviewed some of the key concepts behind Node-RED and introduced
the context and global context objects used to share and maintain state between
messages received by function nodes. The JavaScript overview in this lecture should
enable you to start programming your own function nodes. Through some additional
examples, you’ve seen how function nodes are an important and powerful aspect of
Node-Red, allowing you to extend it as needed when a built-in node doesn’t quite do
the job. This lecture also gave an introduction to sub-flows, demonstrating how they
can be used to reuse flow segments and package up function nodes for easier reuse in
your flows. Finally you’ve seen the use of the function node to develop a flow that
uses a Slack Bot to make general queries to get data from public APIs.
Edit the function node and add the following code (See Fig. 6.29). This code is quite
simple; it contains a loop that calls “node.send” 5 times. node.send was introduced in
Lecture 5 at the end of example 5.2. It allows a function node to output messages to
its output independently of its return value. Note how the function itself returns null.
The expected output of this function will be a series of messages with the payloads:
0,1,2,3 and 4.
Figure 6.29 Code to send multiple messages using the node.send() command
To make the example ressemble a counter more closely, you can edit the delay node
and configure it to limit the rate of messages to 1 per second, as shown in Fig 6.30.
Figure 6.30 Configure the delay node to limit its output rate to 1 message per second
The flow can now be deployed. Press the button left of the inject node and inspect the
debug tab (See Fig 6.31) and you will see the messages arriving every second:
Home
List of examples
We will use a free cloud service called “mongolab”. It allows you to create “sandbox”
databases you can use to prototype your applications. Head over
to https://mongolab.com. Register for an account. You will then be able to create a
database. Click on “Create New” in your home dashboard.
Fill out the form to create a new MongoDB deployment. Select Amazon, Single-node
and select the FREE size of 500mb.
Figure 6.33 Choosing the free MongoDB
Scroll down and name your database. We are naming it “mycontent”. Now click on
Create new MongoDB deployment:
Finally, you will need a user to connect to that database. Add a new database user.
We will name it “freduser” but you should use a name that makes sense to you.
Figure 6.36 Adding a user to your MongoDB
Finally, note how this page also gives you important information on how to connect
to your MongoDB database. We will need the URI (in our case
ds037234.mongolab.com), the port (37234 in our case) and your newly created user
and password.
Figure 6.37 Note down the connection info for your new MongoDB
Now, head over to Node-RED and wire up a http-in, mongodb-in, a template, and an
http-out node as shown in Fig. 6.38.
Figure 6.38 The basic flow for the micro-blog
Edit the http-in node to accept GET request on the URL “/public/posts” (Fig 6.39)
We will now configure our mongodb in node. Double click on the node and create a
new server connection. Here is where you will use the information from your
mongolab instance:
Figure 6.40 Configuring the mongodb node using the MongoDB account info
Click on Create/Update and configure your node to use the “posts” collection you
created. Configure it to do a “find” operation, which will find all documents in that
collection. We will now name it “find posts”.
Figure 6.41 Configuring the mongodb node with the collection and the find operation
Once you have the http node and the mongodb nodes configured you can edit the
html template node to handle the data returned by the mongodb node (Listing. 6.9):
1. <!DOCTYPE html>
2. <html lang=”en”>
3. <head>
4. </head>
5. <body>
6. <h1>My Micro Blog</h1>
7. <form action=”posts” method=”post”>
8. <label for=”title”>Title</label>
9. <input type=”text” class=”form-control” name=”title” placeholder=”Title…” />
10. <label for=”post”>Post Content</label>
11. <input type=”text” class=”form-control” name=”post” placeholder=”Say
something…” />
12. <button type=”submit” class=”btn btn-default”>Submit</button>
13. </form>
14. <div>
15. {{#payload}}
16. <div class=”post”>
17. <h3>{{title}}</h3>
18. <p>{{post}}</p>
19. </div>
20. {{/payload}}
21. </div>
22. </body>
23. </html>
This code, while long, is very simple. You will be using Bootstrap to style your
website (http://getbootstrap.com/) and provide a responsive layout. If you now
visit http://{your user name}.fred.senstecnic.com/api/public/posts you will be able
to see your new blog site (Fig 6.42). However there is no content yet.
So far, you’ve created the flow needed to display posts. Now you need to create the
other side of the blog service, a flow to create posts and save them to your MongoDB
collection. Connect an http-in, a function, mongodb-out, and http-out nodes as
shown in the bottom part of Fig 6.43.
Figure 6.43 Setting up a flow to allow you to post blog entries and store them in
MongoDB
Edit the http-in node to accept PUT requests at /public/posts (Fig 6.44)
Figure 6.44 Setting up the end point for posts for the micro blog service
Now let’s edit the function node and add the following code (listing 6.10). This builds
a simple http msg.header which your flow will pass to the http node.
1. msg.headers = {
2. “Location” : “https://{your username}.fred.sensetecnic.com/api/public/posts”
3. };
4. msg.statusCode = 302;
5. return msg;
Note that at line 2 you set the address to be the end point for your service. This will
use your user name in place of ‘guides’.
Finally, you will need to edit the mongodb-out node and select your previously
configured server. Configure it to use the collection “posts” and an “insert” operation.
Make sure to check “only store msg.payload object”, this will make sure we only store
the data in the message payload, not the whole message object (fig 6.45).
Figure 6.45 Configuring the mongodb node to store the incoming blog postings
That’s it! You can now go to your url and use your micro blog site where you’ll see
something similar to Fig 6.46.
Node RED Programming Guide
Programming the IoT
Home
List of examples
Part 2 (Using the default Node-RED dashboard nodes)
We use a cloud hosted version of Node-RED for these lectures called FRED. Sign up for a
free account at FRED.sensetecnic.com. Examples in the early lectures will work with
other installations of Node-RED, later lectures use nodes you will need to install yourself
if you don’t use FRED.
Now, double click on the openweathermap node to configure it. Enter your API
Key from OpenWeatherMap, configure a location you’re interested in, and name
your Node:
Click on Deploy on the top right corner of the Node-RED UI. You will see on the right
pane, under “debug” the data that OpenWeatherMap provides us with a variety of
information about the location including temperature (in C and K), humidity,
windspeed etc:
As you can see, the data is already in JSON format; so we can use any of the values
very easily. Let’s build a dashboard to visualize our data using the node that allows
you to create visualizations very easily. Find the freeboard node in the left pane by
either browsing through the nodes or searching for it using “filter nodes”. Add it to
the flow. Double click on it to give it a name, like so.
Click on Deploy. This will prompt the openweathermap to get data and send it to
both the debug and freeboard nodes. The freeboard node is quite smart and will
do its best to parse the data you send it and figure out how to make it available using
the FreeBoard UI. We’ll look at that in a moment. If you inspect the “info” tab in the
right panel you will see more information about the “freeboard” node:
Visit the link provided in the info panel, or at
https://{username}.fred.sensetecnic.com/api/freeboard/
This tab will allow you to create visualization in FreeBoards, save them and load
them. Let’s create a visualization of our weather data. We first need to add a
datasource to our freeboard. Click on “Add” under “DATASOURCES”. Under “type”
select the name of the “freeboard” node we configured above. In our case we named
it “freeboard”. This will allow us to access ANY data we connect to the “freeboard”
node in Node RED.
We will now add a Pane. Click on “ADD PANE”, this will add a new empty pane:
Now, we will add a “Widget”, click on the “+” (plus) sign in the new pane. Select
“Gauge”. Under “DATASOURCE” select the “freeboard” node and select “tempc”. As
you can see, all of the different data fields in the openweathermap JSON structure
are available for you to visualize. FreeBoard essentially takes the JSON structure you
pass it and breaks out any fields. If you can’t see this in the dropdown, go back to
Node RED and click on “Deploy” again. So that the “freeboard” node can get some
data and store the data it has received. Your configuration should look something
like this:
Click on OK. Which will build your widget and add it to the pane you created!
To save your dashboard click on “save”, and select [pretty] or [minify] which will save
it in FRED and will show you the URL to access the Dashboard. You need to save the
URL used to access the dashboard, e.g. as a dashboard. From now on you can access
your saved dashboard by accessing the saved url, which will be similar to the one
below.
https://{username}.fred.sensetecnic.com/api/freeboard/#start-16091
Home
List of examples
To start, let’s wire up a simple flow that sends a random number between 0 and 99 to
a simple chart. For that you’ll need an inject node to repeatedly fire every few
seconds, a function node to generate the random number and one of the node-red-
dashboard nodes – in this case the chart node.
Before we look a how the chart node works, let’s configure the inject node to send a
timestamp every 5 seconds by setting the payload to timestamp and
the repeat field to an interval of 5 seconds.
This will act as our repeating trigger. Now we need to set up the function node to
generate a random number – we’ll use a simple JS math function to do this:
msg.payload = Math.round(Math.random()*100);
return msg;
This will generate a random number between 0 ~ 99 which is passed to the chart
node.
So now let’s take a look at the chart node. When you double click it, you’ll see it’s
configuration options:
If you click on the button of the Group field, you will be prompted to configure the
tabs of the UI.
The Tab option allows you to specify which tab of the UI page you will see the UI
element on – in this case our chart. The default tab is Home – which we are using
here. If you select the edit button to the right of the Tab field you can create a new tab
and then select that. However, we’ll use the default home for now.
The Name field is the standard Node-RED node name – by default this is chart but
you can set it to anything you like.
The Group field allows you to group UI elements – we’ll show you how that works
when we add another UI element so let’s use group “Default[Home]” for now – of
course, you can use any string you like.
The X-axis field allows you to tell the chart how much data it should store and
display – the longer the ‘last‘ filed is set to, the more data is stored and displayed by
the chart. Let’s use a short 5 mins which will start to throw away the data that is 5
minutes old.
Lastly the Interpolate field defines how the chart will interpolate values in between
actual data values it receives, you can select between linear, step, b-spline and
cardinal – which are standard interpolation algorithms. We’ll use the default linear.
Wire these nodes up, hit the deploy button – check that your debug node is showing
that random values are showing. Then head over to your default dashboard page to
see the results. By default, under FRED, you’ll see your UI at:
https://{your username}.fred.sensetecnic.com/api/ui/
When you visit that page you’ll see your initial chart as shown below:
As you can see, you get a nice line chart, scaled for your data values (X axis) and the
time they arrived (y axis). You can also see “Default” at the top left of the chart,
indicating this is UI group “Default” – which is the group name we set in the
configuration fields for the chart node.
If you look at the top left of the web page, you can see that we are, by default, on the
home tab. If you had created your own tab then when you click the selector top left
you’ll get a pull down menu of your tab options:
That was pretty simple, let’s add a few other UI elements to our dashboard. Firstly
let’s create a gauge to show the last data value sent. Drag a Gauge node from the UI
palette and wire it to the Random Number function node.
We’ll us the same Tab, home and we’ll also add it to the same group –
“Default[Home]”. The Min and Max fields allow you to set the min and max values
the gauge will shown. Make sure the max is set to 100 which is the most that the
random number function node will generate. You can also change the Colour
gradient to show different colours on the widget, but we will leave it as default for
now.
Hit deploy and then head over to your dashboard and you’ll see that the chart and
gauge are displayed in a group with the chart now showing the last 5 minutes of data
and the gauge the latest value.
As a last example, let’s use a couple of the other UI nodes, a slider node and
a text node to show the same data on a slider and as a text string.
For these two nodes, configure them to use the same tab – “Home” but
use group name “anotherWidget”(You will need to click “Add new UI_group” from
the drop down menu of the Group field, and then click the edit button). You will
also need to change the min and max value for the slider node to show the
correct position of the slider. Deploy those and let’s take a look at your dashboard. As
you can see, we now have two widget groups, group “Default” with a chart and a
gauge, group “anotherWidget” with a text filed and a slider. Simple eh?
In the dashboard tab beside your debug tab, you can also set the theme and order
of the elements. If you don’t see the dashboard tab, click the menu button at top right
corner, then select “View” -> “Dashboard”. You can see all the widgets and tabs
showing in a tree structure, and you can easily drag the elements to change the
orders that they are presented in the dashboard.
Now you’ve got the basics sorted out, play around with the different
dashboard elements to build your own dashboards using some real world data – have
fun!
Sticking with the openweathermap node, let’s use it to generate a simple JSON
structure that we then visualize using the popular Morris.JS chart library (). The
library supports 4 basic chart types line charts, area charts, bar charts and the donut
chart. We’ll be using the donut chart but the approach is the same for all the chart
types.
The flow is shown below and consists of 4 nodes. The first and final nodes
are http input and output nodes that work together to listen for HTTP requests and
send HTTP responses. This flow listens for a HTTP request from any source, but let’s
assume a regular browser here. When it arrives, it queries the weather using
your openweathermap node, then uses a template node to build a HTTP page
using the weather data, and passes that to the http output node which sends back
the webpage to the browser.
Figure. A simple web server example to graph weather data using a pi chart
Double click on the http input node and configure it with your URL, e.g.
/public/weather. Remember, to access it, you will need to use,
https://{user name}.fred.sensetecnic.com/api/public/weather
where {user name} is replaced by your own FRED user name. Obviously /weather is
because that’s how you configured it, if you’d used another name, e.g. /public/test,
then the URL would end /public/test
When a HTTP request comes in, the http input node creates a message to trigger
the openweathermap node, which is the next node in the flow.
The openweather node gets the current statistics for the location you configured it
for, and then passes those statistics, as a JSON structure in the usual message
payload field, to a template node. The html template node is another pre-built
node in Node-RED, which, like the function node, allows you to build arbitrary
code. However, rather than using JavaScript like the function node,
the template node works with text such as HTML.
The HTML code in the template node is shown in the listing below. As you can see,
the code is a standard HTML structure with the <head> structure defining the
external script libraries that we use. These are all required for the Morris.JS chart
library and should be copied exactly.
Note, we are combining all the page elements into the one file (or node) which works
for simple web pages but is not considered good practice.
Line 10 sets up a <div> and sets the name and height. Then the morris.js chart
code script begins at line 11 by defining a Morris.Donut element.
Lines 15, 16 and 17 define the donut elements, you are using 3 to display the
temperature, the humidity and the wind speed. The values from the
openweathermap JSON structure can be used directly, i.e. payload.tempc,
payload.humidity and payload.windspeed.
Once the template node has generated the HTML file, it passes it as a message to the
final node, which is a http response node. This node packages up the HTML as a
HTTP response which it sends back to the browser that made the original request.
If you deploy this flow and then point your browser to the URL you configured in
the http input node, in your case should be:
https://{user name}.fred.sensetecnic.com/api/public/weather
You will then see a simple donut chart which you can mouse over to see the
temperature, humidity and windspeed for the city you configured in
the openweathermap node – all built and served by a simple Node-RED flow!
Figure: A donut chart, served up by Node-RED showing Temperature for the
configured city
Summary
In this lecture you have looked at three approaches to building simple dashboards
and UIs. The FreeBoard node is a one stop shop allowing you to feed complex data
as JSON structures to the Freeboard node and then using the powerful FreeBoard
dashboard to configure and show the data.
With the nodered.contrib.ui nodes you have to do a little more work by having to
build the UI elements into your flows. This approach gives you more control, and
makes the UI elements part of your Node-RED flow, but requires a little more
thought and work.
The final approach, using the html template node and a generic JavaScript charting
library is the most flexible, but requires you know how to write simple html/css and
JavaScript.