Storing Data in Node-Red Variables

Node-red nodes pass the msg object between nodes.

However this object is replaced by the next msg object. So how do you store data between node calls?

Node-Red provides three mechanisms:

  • The context object -stores data for a node
  • The Flow object – stores data for a flow
  • The global object -stores data for the canvas





I will illustrate these methods using a simple flow like the one below.simple-node-flow

The inject node is used to start the flow , then function node implements the counter and the debug node displays the result.

The idea is to count the number of times the message was injected.

The actual message that gets injected isn’t important.

Note: There is a video to accompany this tutorial as it is easy to demonstrate the interaction between variables using video. You may want to read quickly through the text and then go to the video. Here is the video

Using the Context Object

This is used for storing function variables.

The process for retrieving and storing is to use the get method of the object for retrieving value and the set method to store values.:

x =context.get(name); //to retrieve a variable  
context.set(name)=x; // to store a variable

A variable stored for function 1 in the context object is not available to function 2 and vice versa.

context-variables-node-red-flow

Initialising the Variable

The standard way is to include this code at the top of the script:

var count=context.get('count') || 0;

Which means- If count doesn’t exist in the context object then make our local variable count zero; otherwise assign the stored value to our local variable count.

You can use multiple variables e.g.

var count=context.get('count') || 0;
var count2=context.get('count2') || 0;

You can also use an object e.g

var local=context.get('data') || {};
if (local.count===undefined) //test exists
{
  local.count=0;
}

In the code above data is an object stored in the context object and local is our local object.

Here is an example script that uses a single variable as a counter in function 1:

var count=context.get('count') || 0;
count +=1;
msg.payload="F1 "+msg.payload+" "+count;
context.set('count',count);
return msg;

Here is an example script that uses a object variable as a counter in function 2::

var local=context.get('data') || {};
if (local.count===undefined)//test exists
{
  local.count=0;
}
local.count +=1;
msg.payload="F2 "+msg.payload+" "+local.count;
context.set('data',local);
return msg;

If look at the code for function 1 and function 2 you will see that they use the same counter variable..

However when you click the inject node for function 1 you see the counter value is 1 and then the inject node for function 2 then counter is also 1.

This shows that the counters are local to each function and not shared between functions.

Note: Currently if you restart the flow the variables are reset but this is likely to change

Using the Flow Object

You use the flow object in the same way as the context object.

To retrieve values stored in the flow object use:

var count=flow.get('count') || 0;

and to store values use:

flow.set('count',count);

This time you should notice that the functions can share variables stored in flow objects. See video

Using the Global Object

You use the flow object in the same way as the context object.

To retrieve values stored in the flow object use:

var count=global.get('count') || 0;

and to store values use:

global.set('count',gcount);

This time you should notice that the functions can share variables stored in the global object even across flows.

 Video -How to Store Data in Node-Red Variables

Flows Used in the video

Exchange Data Between Nodes Without Wires

With node-red messages are usually passed between nodes using wires.

However it is possible to pass data between nodes with them being wired together using flow and global objects.



Related tutorials

Please rate? And use Comments to let me know more
[Total: 12    Average: 4.4/5]

15 comments

  1. Once again: Steve to the rescue.
    I have a NR flow that gets local weather info from the National Weather Service, packages it into a web page and FTPs it to a page that is served on my domain (why? learning new stuff). I installed a Sonoff TH16 to turn my porch fairy lights on/off and also to sense very local temp/humidity re-flashed with Tasmota and MQTT’d to my RPi broker. How to get the local temps into the web page when the weather NWS data pull and temp sampling are asynchronous? Use a flow variable! And you showed me how they worked.
    Every minute I get temp/humidity and stick it in a flow variable. Every minute I get data from NWS and incorporate the flow variable into the web page. It’s like magic.
    I have your page bookmarked because there is so much stuff here, all explained well. Thanks.
    –Jeff

  2. Hi Steve,
    thank you for your detailed explanations.
    To initialize an undefined flow variable, i have been using the syntax “var count=flow.get(‘count’) || 0;” without a problem for some time.
    But just now i have a flow where my flow-variable is always set to the initialized value, rather than the saved value. Leaving off the “|| 0” will return the saved value. Testing with “undefined” is also working correctly.
    So i am wondering if this syntax with the “|| 0” is really reliable? It is just an OR – how can i be sure that node-red takes the left side first?
    Regards,
    Peter

    1. Peter
      I’ve experienced similar problems and hope to put together a short tutorial on it as it can be very confusing.
      It is related to how Javascript evaluates true and false.
      What I prefer to do is use an init function that runs at the start and creates the variables with known initial values.
      Also using
      var var1=flow.get(‘var1’);
      if (var1===undefined){
      set initial values
      }
      I think works better

      rgds
      steve

  3. In the case of variables in flow scope, what happens if a second message arrives and updates the same flow scope variable, before the first message has been fully processed? Can arrival of second message impact flow of first message because of a variable value change?

    1. I haven’t tested it but I would think not. When the first message arrives, unless it does some asynchronously, then it is processed to the end before node can pick up the other message.
      Node might be receiving messages from MQTT in the background but they are processed by the flow in order.
      Do you a particular example in mind?

  4. Hi could you cc me that flow ? i’m working on a battery temp sensor arrangement to warn if i get overheating . using 4 sensors trying to figure out how to use a global array variable to store the values in.
    thx

  5. Hi Steve,

    I’ve read through your tutorial on how to store data, and I think part of this will apply to my project. What I need to do is store and compare temperature data. I am already receiving temperature data from a sensor (about every 10 seconds) which is then fed into Node-Red (via MQTT connection), changed, and then inserted into a database. I want to receive an alert if the rate of change is X (say if temps rise by 1 degree per minute). I’m new to programming and Node-Red specifically and would appreciate guidance/help on this matter. Have done the alert/notification part via email, but have no idea how to go about setting up a flow that will store and compare temp changes.

    Regards
    Riaan

Leave a Reply

Your email address will not be published. Required fields are marked *