6 - Flow Control Node-RED
6 - Flow Control Node-RED
You want to trigger a flow whenever Node-RED starts. This could be used to initialise context variables,
or to send a notification that Node-RED has been restarted.
2. Solution
Use an Inject node configured to fire once on start. Double click the inject node to open it - scroll down
and tick the checkbox
Example
Flows:
[{"id":"e60b12c1.93bb3","type":"inject","z":"535331d8.55c1f","name":"","topic":"","payload":"Start
ed!","payloadType":"str","repeat":"","crontab":"","once":true,"x":140,"y":540,"wires":[["9b1d7727.5
6d0f8"]]},{"id":"9b1d7727.56d0f8","type":"debug","z":"535331d8.55c1f","name":"","active":true,"co
nsole":"false","complete":"false","x":410,"y":540,"wires":[]}]
3. Discussion
When configured to fire on start, the Inject node will be automatically triggered a few hundred
milliseconds after it is deployed. This delay is used to help ensure the rest of the flows have been
created and Started by this point.
You want to trigger a flow at regular intervals. For example, to periodically call an api to retrieve its
current state.
2. Solution
To stop - you must re-configure the node and set Repeat to none. Click done to save the change and
deploy.
Example
Flows:
[{"id":"372cfc32.bcd244","type":"inject","z":"535331d8.55c1f","name":"","topic":"","payload":"","pa
yloadType":"date","repeat":"5","crontab":"","once":false,"x":150,"y":600,"wires":[["6c63c499.ce3ad
c"]]},{"id":"6c63c499.ce3adc","type":"debug","z":"535331d8.55c1f","name":"","active":true,"console
":"false","complete":"false","x":410,"y":600,"wires":[]}]
3. Discussion
The Inject node can be configured to repeat at a fixed interval. If desired, it can also be constrained to
do so between certain times on certain days.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to trigger a flow at a specific time, such as at 4pm every weekday.
2. Solution
Example
Flows:
[{"id":"24579bcb.5c9814","type":"inject","z":"535331d8.55c1f","name":"","topic":"","payload":"It is
4pm on a weekday!","payloadType":"str","repeat":"","crontab":"00 16 * *
1,2,3,4,5","once":false,"x":190,"y":660,"wires":[["145b508a.f3325f"]]},{"id":"145b508a.f3325f","type
":"debug","z":"535331d8.55c1f","name":"","active":true,"console":"false","complete":"false","x":41
0,"y":660,"wires":[]}]
3. Discussion
The Inject node can be configured to trigger at a specific time on specific days of the week. If multiple
different times are required, multiple Inject nodes should be used.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to route a message to different flows according to the value of the msg.topic property. For
example, you have an MQTT node subscribed to multiple sensors and you want to pass the messages
to different Dashboard ui_gauge nodes.
2. Solution
Use the Switch node to check the value of the property against different values corresponding to
different outputs of the node.
Example
Flows:
[{"id":"3bc8e1d2.744abe","type":"switch","z":"ac14500e.2c57d","name":"Route
","property":"topic","propertyType":"msg","rules":[{"t":"eq","v":"temperature","vt":"str"},{"t":"eq","
v":"humidity","vt":"str"},{"t":"eq","v":"pressure","vt":"str"}],"checkall":"true","repair":false,"outputs"
:3,"x":330,"y":420,"wires":[["907bf3b8.def45"],["fe425938.926838"],["ec261304.52f73"]]},{"id":"be3
da36c.1c142","type":"inject","z":"ac14500e.2c57d","name":"","topic":"temperature","payload":"27"
,"payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":140,"y":380,"wires"
:[["3bc8e1d2.744abe"]]},{"id":"f271ceef.172b3","type":"inject","z":"ac14500e.2c57d","name":"","top
ic":"humidity","payload":"45","payloadType":"num","repeat":"","crontab":"","once":false,"onceDela
y":0.1,"x":130,"y":420,"wires":[["3bc8e1d2.744abe"]]},{"id":"907bf3b8.def45","type":"debug","z":"a
c14500e.2c57d","name":"Temperature","active":true,"tosidebar":true,"console":false,"tostatus":fals
e,"complete":"payload","targetType":"msg","x":510,"y":380,"wires":[]},{"id":"fe425938.926838","ty
pe":"debug","z":"ac14500e.2c57d","name":"Humidity","active":true,"tosidebar":true,"console":false,
"tostatus":false,"complete":"payload","targetType":"msg","x":500,"y":420,"wires":[]},{"id":"ec26130
4.52f73","type":"debug","z":"ac14500e.2c57d","name":"Pressure","active":true,"tosidebar":true,"co
nsole":false,"tostatus":false,"complete":"payload","targetType":"msg","x":500,"y":460,"wires":[]},{"i
d":"fca957dd.9d8078","type":"inject","z":"ac14500e.2c57d","name":"","topic":"pressure","payload":
"1001","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":130,"y":460,
"wires":[["3bc8e1d2.744abe"]]}]
3. Discussion
The Switch node will send on messages it receives on the outputs that corresponding to rules that
match.
It can be configured to send on all rules that match, or only on the first one that matches..
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to route a message to different flows, or stop it entirely, according to the current value of
another variable.
2. Solution
Save the switching variable into a flow context variable, and then use a Switch node to check the value
of that flow context property against different values corresponding to different outputs of the node.
Example
Flows:
[{"id":"a62d8cdf.1bd82","type":"inject","z":"9138b11f.f64d5","name":"Inject","props":[{"p":"payload
"},{"p":"topic","vt":"str"}],"repeat":"2","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload
":"","payloadType":"date","x":140,"y":585,"wires":[["b8bbbc41.f272"]]},{"id":"b8bbbc41.f272","type
":"switch","z":"9138b11f.f64d5","name":"Context based
routing","property":"state","propertyType":"flow","rules":[{"t":"eq","v":"1","vt":"num"},{"t":"eq","v"
:"2","vt":"num"},{"t":"eq","v":"3","vt":"num"}],"checkall":"true","repair":false,"outputs":3,"x":350,"y
":585,"wires":[["9aa9c6b2.18a8e8"],["6ba4ec46.476794"],["a2e806c8.ffa168"]]},{"id":"9aa9c6b2.18
a8e8","type":"debug","z":"9138b11f.f64d5","name":"Output
1","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"
msg","x":590,"y":525,"wires":[]},{"id":"6ba4ec46.476794","type":"debug","z":"9138b11f.f64d5","na
me":"Output
2","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"
msg","x":590,"y":585,"wires":[]},{"id":"a2e806c8.ffa168","type":"debug","z":"9138b11f.f64d5","nam
e":"Output
3","active":true,"tosidebar":true,"console":false,"tostatus":true,"complete":"payload","targetType":"
msg","x":590,"y":645,"wires":[]},{"id":"8aabdb51.e8b538","type":"inject","z":"9138b11f.f64d5","na
me":"Set state 0 - turn
off","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDela
y":0.1,"topic":"","payload":"0","payloadType":"num","x":180,"y":675,"wires":[["e46083e4.1f17b"]]},{
"id":"d1722dee.48db4","type":"inject","z":"9138b11f.f64d5","name":"Set state 1 - send to output
Flow Control Node-RED | Ahmad Fauzi Firmansyah
1","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay
":0.1,"topic":"","payload":"1","payloadType":"num","x":210,"y":720,"wires":[["e46083e4.1f17b"]]},{"
id":"4bdb08de.706328","type":"inject","z":"9138b11f.f64d5","name":"Set state 2 - send to output
2","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay
":0.1,"topic":"","payload":"2","payloadType":"num","x":210,"y":765,"wires":[["e46083e4.1f17b"]]},{"
id":"220ce0a6.cf81e","type":"inject","z":"9138b11f.f64d5","name":"Set state 3 - send to output
3","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay
":0.1,"topic":"","payload":"3","payloadType":"num","x":210,"y":810,"wires":[["e46083e4.1f17b"]]},{"
id":"e46083e4.1f17b","type":"change","z":"9138b11f.f64d5","name":"Set
flow.state","rules":[{"t":"set","p":"state","pt":"flow","to":"payload","tot":"msg"}],"action":"","proper
ty":"","from":"","to":"","reg":false,"x":470,"y":720,"wires":[[]]}]
3. Discussion
In the example flow, the top flow represents the stream of messages that can be stopped or routed
to one of the three outputs by the Switch node.
The bottom flow provides a set of Inject nodes to change the current value of the flow.state context
property.
This can be used as a simple gate like function - based on the value of some other input, that you store
into the flow.state context property.
This shows how the routing in one flow can be changed by a separate flow.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to perform an operation on every element in an array. For example, given an array of
numbers, you want to round each value to the nearest integer.
2. Solution
The Split node can be used to send a message for every element in the array. It can be followed by the
nodes needed to operate on the individual elements, followed by a Join node to recombine them back
into a single array.
Example
Flows:
[{"id":"3149f240.c0e25e","type":"inject","z":"ac14500e.2c57d","name":"Array of
decimals","topic":"","payload":"[1.67,2.98,3.12,4.99,5.50]","payloadType":"json","repeat":"","cronta
b":"","once":false,"onceDelay":0.1,"x":120,"y":960,"wires":[["bd57baa6.00f998"]]},{"id":"bd57baa6.
00f998","type":"split","z":"ac14500e.2c57d","name":"Split
array","splt":"\\n","spltType":"str","arraySplt":"1","arraySpltType":"len","stream":false,"addname":"
","x":200,"y":1020,"wires":[["7ab9e9ed.d514b8"]]},{"id":"7ab9e9ed.d514b8","type":"range","z":"ac1
4500e.2c57d","minin":"0","maxin":"10","minout":"0","maxout":"10","action":"scale","round":true,"
property":"payload","name":"Round
value","x":350,"y":1020,"wires":[["f26660ab.007b3"]]},{"id":"f26660ab.007b3","type":"join","z":"ac1
4500e.2c57d","name":"","mode":"auto","build":"string","property":"payload","propertyType":"msg"
,"key":"topic","joiner":"\\n","joinerType":"str","accumulate":"false","timeout":"","count":"","reduce
Right":false,"x":490,"y":1020,"wires":[["f9b5abac.f13828"]]},{"id":"f9b5abac.f13828","type":"debug"
,"z":"ac14500e.2c57d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"com
plete":"false","x":550,"y":1080,"wires":[]}]
3. Discussion
In other programming environments, this task would be accomplished by creating a loop over the
elements of the array.
In Node-RED, the way to achieve the same thing is to turn the single message containing the array into
a stream of messages that can be processed individually and finally recombine them back into one
message.
The Split/Join node pair are commonly used together to achieve this. The Split node adds the
msg.parts property to each message in the stream which allows the Join node to properly reassemble
the original message.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want a flow to be triggered if a message is not received after a defined time. For example, you
expect to receive a sensor reading every 5 seconds and need to know if it fails to arrive.
2. Solution
Use the Trigger node to detect when a message has not arrived after a defined interval.
Example
Flows:
[{"id":"6ea53ad8.2362a4","type":"debug","z":"ac14500e.2c57d","name":"","active":true,"tosidebar"
:true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":450,"y":1160,"wi
res":[]},{"id":"3da6946e.184a5c","type":"inject","z":"ac14500e.2c57d","name":"","topic":"","payload
":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":1160,"
wires":[["38caaff4.03f6d","6ea53ad8.2362a4"]]},{"id":"38caaff4.03f6d","type":"trigger","z":"ac1450
0e.2c57d","op1":"","op2":"timeout","op1type":"nul","op2type":"str","duration":"5","extend":true,"u
nits":"s","reset":"","bytopic":"all","name":"Watchdog","x":270,"y":1200,"wires":[["ae477709.01608
8"]]},{"id":"ae477709.016088","type":"debug","z":"ac14500e.2c57d","name":"","active":true,"toside
bar":true,"console":false,"tostatus":false,"complete":"false","x":450,"y":1200,"wires":[]}]
3. Discussion
In the example flow, the top branch represents the normal flow of the messages. They also get passed
to the Trigger node on a second branch of the flow.
The Trigger node is configured to initially send nothing, then to wait for 5 seconds before sending a
"timeout" message. The option to extend the delay if new messages arrive is also selected. This means
as long as messages continue to arrive, the node will not do anything. Once 5 seconds passes after the
last message to arrive, it will send on the "timeout" message.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You have a stream of messages coming from a sensor at regular intervals. If the sensor stops sending
messages, you want to send placeholder messages at the same rate.
For example, the sensor data may be feeding a Dashboard chart. If the sensor stops sending, the chart
will stop updating. So placeholder messages are needed for the chart to update with a 0 value to
highlight the sensor has stopped.
2. Solution
Use the Trigger node to detect when a message has not arrived after a defined interval and a second
Trigger node to send the placeholder messages at a regular interval.
Example
Flows:
[{"id":"9ccdf268.c96ff","type":"inject","z":"ac14500e.2c57d","name":"","topic":"","payload":"","payl
oadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":100,"y":1660,"wires":[["3
8950a5.28d15f6","2c532f67.0330e"]]},{"id":"38950a5.28d15f6","type":"debug","z":"ac14500e.2c57
d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":61
0,"y":1660,"wires":[]},{"id":"2c532f67.0330e","type":"trigger","z":"ac14500e.2c57d","op1":"reset","
op2":"true","op1type":"str","op2type":"bool","duration":"2","extend":true,"units":"s","reset":"","byt
opic":"all","name":"","x":260,"y":1700,"wires":[["e4e42b96.97a338"]]},{"id":"e4e42b96.97a338","ty
pe":"trigger","z":"ac14500e.2c57d","op1":"0","op2":"0","op1type":"num","op2type":"str","duration"
:"-
2","extend":false,"units":"s","reset":"reset","bytopic":"all","name":"","x":420,"y":1700,"wires":[["38
950a5.28d15f6"]]}]
3. Discussion
In the example flow, the top branch represents the normal flow of the messages, from the Inject node
to the Debug node. The messages also get passed to the first Trigger node on a second branch of the
flow. That node is configured to initially send a payload of "reset", then to wait for 2 seconds before
sending a timeout message. The option to extend the delay if new messages arrive is also selected.
This means as long as messages continue to arrive, the node will not do anything. Once 2 seconds
passes after the last message to arrive, it will send on the timeout message.
The timeout message feeds into a second Trigger node. This node is configured to send on 0 every two
seconds and feeds back into the top branch. The node is also configured to stop sending if it receives
a msg.payload of "reset". As this is the initial message sent by the first Trigger node when it receives
a sensor message, this will cause the second Trigger node to be reset when the sensor resumes
sending its own messages..
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to slow down the messages passing through a flow. For example, you have a message
containing an array of values that you split into a stream of messages and want to process each
message in that stream at a rate of one per second.
2. Solution
Use a Delay node configured to rate limit the messages passing through it.
Example
Flows:
[{"id":"1fccc223.7ba87e","type":"inject","z":"ac14500e.2c57d","name":"Inject
Array","topic":"","payload":"[0,1,2,3,4,5,6,7,8,9]","payloadType":"json","repeat":"","crontab":"","on
ce":false,"onceDelay":0.1,"x":110,"y":1280,"wires":[["b2837466.e02a38"]]},{"id":"b2837466.e02a38"
,"type":"split","z":"ac14500e.2c57d","name":"","splt":"\\n","spltType":"str","arraySplt":1,"arraySpltT
ype":"len","stream":false,"addname":"","x":250,"y":1280,"wires":[["bd97c8ed.a5c8d8"]]},{"id":"bd9
7c8ed.a5c8d8","type":"delay","z":"ac14500e.2c57d","name":"","pauseType":"rate","timeout":"5","ti
meoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","rando
mLast":"5","randomUnits":"seconds","drop":false,"x":390,"y":1280,"wires":[["bd66f03e.bdf0c"]]},{"i
d":"bd66f03e.bdf0c","type":"debug","z":"ac14500e.2c57d","name":"Debug","active":true,"tosidebar
":true,"console":false,"tostatus":false,"complete":"payload","targetType":"msg","x":530,"y":1280,"w
ires":[]}]
3. Discussion
The rate limiting mode of the Delay node can be used to change the rate of messages passing through
it. It is configured with the desired number of messages to pass through the node per time interval. It
will evenly spread the delivery of messages across the time period.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to handle messages at a regular rate, ignoring messages that arrive too quickly. For example,
you have a sensor sending data every second but you only want to handle an update every 5 seconds.
The messages you handle must be the most recent.
2. Solution
Use a Delay node configured to rate limit the messages passing through it with the option to drop
intermediate messages enabled.
Example
Flows:
[{"id":"8a1bcd7d.f6b67","type":"inject","z":"ac14500e.2c57d","name":"Inject
Array","topic":"","payload":"[0,1,2,3,4,5,6,7,8,9]","payloadType":"json","repeat":"","crontab":"","on
ce":false,"onceDelay":0.1,"x":110,"y":1380,"wires":[["bd4bdd42.bd1b"]]},{"id":"bd4bdd42.bd1b","ty
pe":"delay","z":"ac14500e.2c57d","name":"","pauseType":"rate","timeout":"5","timeoutUnits":"seco
nds","rate":"1","nbRateUnits":"5","rateUnits":"second","randomFirst":"1","randomLast":"5","rando
mUnits":"seconds","drop":true,"x":320,"y":1380,"wires":[["be20c513.237c78"]]},{"id":"be20c513.237
c78","type":"debug","z":"ac14500e.2c57d","name":"Debug","active":true,"tosidebar":true,"console"
:false,"tostatus":false,"complete":"payload","targetType":"msg","x":510,"y":1380,"wires":[]}]
3. Discussion
The rate limiting mode of the Delay node can be used to change the rate of messages passing through
it. With the option to drop intermediate messages enabled, it will discard any message that arrives
within the rate limit interval.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You want to drop a message if the value of its payload has not changed since the last message. For
example, you have a sensor sending the state of a switch at regular intervals and you only want to
know when the value has changed.
2. Solution
Use the RBE node (Report By Exception) to block messages unless its value has changed.
Example
Flows:
[{"id":"6079638d.df403c","type":"inject","z":"ac14500e.2c57d","name":"","topic":"","payload":"0","
payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":90,"y":1500,"wires":[
["87129503.c7b358"]]},{"id":"87129503.c7b358","type":"rbe","z":"ac14500e.2c57d","name":"report-
by-
exception","func":"deadband","gap":"","start":"","inout":"out","property":"payload","x":300,"y":152
0,"wires":[["5e2ffc27.c61dd4"]]},{"id":"5e2ffc27.c61dd4","type":"debug","z":"ac14500e.2c57d","na
me":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"payload","targetT
ype":"msg","x":510,"y":1520,"wires":[]},{"id":"2dc49f96.3070c","type":"inject","z":"ac14500e.2c57d"
,"name":"","topic":"","payload":"1","payloadType":"num","repeat":"","crontab":"","once":false,"onc
eDelay":0.1,"x":90,"y":1540,"wires":[["87129503.c7b358"]]}]
3. Discussion
The RBE can be used to drop messages unless their value has changed. This is useful for detecting
changes.
If the property being checked is a number, the node can also be configured with a threshold for how
much the value must change for the message to be passed on..
Flow Control Node-RED | Ahmad Fauzi Firmansyah
You have messages arriving from different sources that you need to combine into a single message.
For example, you have three different sensors publishing values and you want to insert them into a
database as a single entry.
2. Solution
Give each stream a unique msg.topic value and use the Join node to group them into a single message.
Example
Flows:
[{"id":"8ccddb9a.a55f38","type":"inject","z":"ac14500e.2c57d","name":"temperature","topic":"temp
erature","payload":"10","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1
,"x":110,"y":1760,"wires":[["47b769c5.cb0e28"]]},{"id":"47b769c5.cb0e28","type":"join","z":"ac1450
0e.2c57d","name":"","mode":"custom","build":"object","property":"payload","propertyType":"msg",
"key":"topic","joiner":"\\n","joinerType":"str","accumulate":false,"timeout":"","count":"3","reduceRi
ght":false,"reduceExp":"","reduceInit":"","reduceInitType":"","reduceFixup":"","x":310,"y":1800,"wir
es":[["f9afb265.b11b7"]]},{"id":"f9afb265.b11b7","type":"debug","z":"ac14500e.2c57d","name":"","
active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","x":470,"y":1800,"wi
res":[]},{"id":"2d269127.4f04ce","type":"inject","z":"ac14500e.2c57d","name":"humidity","topic":"h
umidity","payload":"","payloadType":"num","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x
":100,"y":1800,"wires":[["47b769c5.cb0e28"]]},{"id":"d6fbe805.0e4628","type":"inject","z":"ac14500
e.2c57d","name":"pressure","topic":"pressure","payload":"999","payloadType":"num","repeat":"","c
rontab":"","once":false,"onceDelay":0.1,"x":100,"y":1840,"wires":[["47b769c5.cb0e28"]]}]
3. Discussion
In the example flow, each Inject node represents a different source of messages. They each set a
unique msg.topic value so they can be identified later in the flow.
The Join node has been configured in manual mode to create a key/value object using msg.topic as
the key name. As we know there are three separate streams of messages to join, the node has been
to configure to send on a message when it receives that number of parts.
This means it will send on a message each time it receives at least one message from three different
topics - using the most recent value from each topic.
Flow Control Node-RED | Ahmad Fauzi Firmansyah
The node has further options to change its behaviour that have not been used in this recipe. For
example, a timeout can be set to ensure it sends something in case one of the sensors stops sending
values. If that is a concern, you may consider this recipe for providing a placeholder value.