Node-RED Global Flow and Context

There’s a mouthful. This short article is about the various kinds of variables used in Node-Red and more importantly how to initialise them and how to view them.

So in Node-Red when you want to use variables – there are three basic types as well as local variables.

So for example – you’ve opened up a FUNCTION block and you want to use some variables. VAR is always a good start.

var fred=1;

A way to get a variable to PERSIST behind that simply function invocation to the next time around, use this;

context.set(“fred”,1);

If you’d like that var to be available to any other function in that flow (or page if you like) – use:

flow.set(“fred”,1);

and if you need a global variable that can be accessed anywhere within Node-Red including other flows  – I use them all the time for things like thermostat objects etc… use global.

global.set(“fred”,1);

Of course you can recall said variables as global.get(“fred”); etc. Don’t use the old method (example global.context.fred) – there’s a reason the Node-Red guys are steering us in this direction.

This is not meant as a course on programming – you can read all about this on the Node-Red site – just look up variables.

So three useful types of variable.

But there’s a problem. Node-Red runs asynchronously and in my first efforts I would have an INIT tab and initialise my global variables there. Once in a blue moon I would see a non-destructive failure with the logs showing that I’d tried to use a variable before it had been initialised (created, even).  So in a platform where everything is running asynchronously how do you ensure (without checking every single time you use it) that a variable has been initialised…. especially important for globals.

One way which I don’t really like is to ensure that the variable is initialised in the left most tab. as that runs first… ok… kind of….

Well it turns out “there’s a node for that”.  Node-Red-Contrib-Config does that – you can set up a variable – which could be a whole object – an no matter where you put this node – it will run BEFORE the main flows start up – I tested it, it works. My only niggle might be that the VALUE field needs to be expandable – a single line is not much use for large objects.

npm install node-red-contrib-config

So that’s one side of it.

The other side is – would it not be nice if you could have a tab to show you the current status, names and values of all of your global variables – and more. Well, now you can.

This needs a SLIGHT mod to Node-Red so if you’re new you might want to back stuff up.

In the directory you normally (hopefully locally) npm install stuff –

https://www.npmjs.com/package/node-red-contrib-contextbrowser

So the install is:

npm install node-red-contrib-contextbrowser

Stop Node-Red and in (in my case) and make a slight edit

nano /usr/lib/node_modules/node-red/red/runtime/nodes/context.js

This is the function you need to alter – very carefully add one line as I have in bold. That’s it – don’t make any other changes.….and this IS case-sensitive.

function createContext(id,seed) {
var data = seed || {};
var obj = seed || {};
obj.get = function get(key) {
return util.getMessageProperty(data,key);
};
obj.set = function set(key, value) {
util.setMessageProperty(data,key,value);
}
  obj.getKeys = function() { return Object.getOwnPropertyNames(data); }
return obj;
}

If you’re something that does not show bold, the line starting “obj.getKeys” is the addition.

(NODE RED GUYS – any chance of making the above standard???)

Start up Node-Red (this works even if you use HTTPS and have password on Node-Red)

And lo – you should have a new tab on the right… click in the editor on a node or function you know has variables initialised…

and then use the refresh in that new tab..

My test..

tmp6E51

The contents of that orange function

tmpD029

 

And..

tmp65A3

As you can see, you must select the particular node or function with the mouse first – then hit the little refresh in the contextbrowser tab – you then see above freddy and the value in the tab – along with any others you’ve defined in that node or function. Ok it’s not quite debugging but better than nothing.

Now moving to the Global tab is another matter as I have several globals including some big objects – if they are very big – you might have to hit the little … indicator to expand them.

tmp3C87

So for me this is marvellous – I can now set up global vars with the confidence that they will be initialised properly at the start – and I can also get a nice overall view of the globals I’ve used – something I could not easily do before.


If you like this post – please share a link to it by social media, by email with friends or on your website.
More readers means more feedback means more answers for all of us. Thank you!

45 thoughts on “Node-RED Global Flow and Context

  1. Can I ask what is the purpose for modifying that function? (it’s not in the install instructions of contextbrowser)

    I addition to that, I don’t have a (/node-red/red/runtime/nodes/context.js) in my node_modules (Windows)

  2. new issues on node-red, but they seem fixed, i hope…

  3. Probably due to node.js version 8, but installing this today it deleted all my other packages from node-red

    + node-red-contrib-contextbrowser@0.0.4
    added 1 package and removed 1097 packages in 66.499s

    Fortunately I had backed up the SD card just before I installed this.

    1. you can use NCU to generate a package.json file with all your nodes and easily reinstall/update them with this:

      cd ~/.node-red
      sudo npm i -g npm-check-updates
      ncu -u
      npm install

        1. I too have had issues on PI recently where adding in a new node took out other packages. The NODE or NODE-RED guys need to get a handle on this flaky behaviour.

        2. NCU is npm-check-updates, installed and run by those commands 🙂
          https://github.com/tjunnone/npm-check-updates

          it’s used in my “full system upgrade script”, too, which updates EVERYTHING on a setup done by your script, plus home-assistant in latest lines (which you can remove if not used):
          https://gist.github.com/fragolinux/412aa50683eb32bb879a120c73110938

          i use it from months now, without issues: it just does what you do by hand when you update your system via apt or your nodes via whatever method you use 🙂

          ALWAYS save a copy of your packages.json file, this way reinstalling every of them is just a “npm install” in its same folder… well, really, save EVERY json file in your .node-red folder, it’s even better 😀

  4. Hi Peter, thanks for your effort in all things you do and share!

    I got a problem that i dont know how to delete global variables which are listed in the contextbrowser. anyone know a solution ?

  5. I did get caught out once where I had the global set inside some logic, which was never evaluating to true, and therefore, the variable never was set. So I was getting an error when trying to get the variable.
    Maybe not your issue though

  6. How can one “undefine” a context variable?

    I’m holding some data and getting other messages in. When I’ve decided I have what I need, I return a msg object. But before I return, I need to delete/clear/undefine/unset the context variable I was holding stuff in.

  7. This has been working beautifully but now I get “Exception getting context data” whenever I press the refresh button (flow,global and node tabs). The following is logged in syslog:
    “28 Nov 00:25:29 – [warn] [contextbrowser] /contextbrowser/flow/:id TypeError: context.keys is not a function”

    I have updated the system a couple of times (apt-get update/upgrade) and npm outdated says everything is up to date.

    The edit to context.js is still there (i.e. it hasn’t been overwritten by any updating). As the edit makes no reference to context.keys, I have no idea where to start looking . Does anyone recognise this problem? Any solutions known?

    1. No response. ok, everything was working so I wasn’t stuck. Now I want to change the functionality and this is relevant again. I updated everything, went through the ‘installation’ but it fails at the first test of creating and viewing a global(/flow/node) variable.
      I get an error in the log which says
      “[warn] [contextbrowser] /contextbrowser/global TypeError: context.keys is not a function”
      I have no idea where to start looking. Any tips?

      gary

      1. Thanks for replying, Patrick. I will go through the article again, but I haven’t used global.context . I only use the global.set/get and flow.set function calls.

  8. > My only niggle might be that the VALUE field needs to be expandable – a single line is not much use for large objects.

    In node-red-contrib-config, if you select the JSON type, you can click on the three dots on the right hand side of the field to open up a JSON editor window.

    This is a standard feature provided by the Node Red node editor framework.

  9. I should think that this note should scare off most people other than the utterly brave: http://nodered.org/docs/getting-started/installation

    “Note: Node.js 7.x is under active development and is not recommended for a stable base. Many 3rd party node packages may not yet fully support Node 7.x and later, especially if they contain a binary component. Check with the author of the package if you are not sure.”

  10. Greetings Pete. I am having some odd restart issues with node-red and I thought I would blame it on node.js 6. I decided to try upgrading to node.js 7x which seems to “break” this amazing feature – settings.js is completely different. (Perhaps it was a bad idea to move to 7. I am going to see if the restart issues is cleared up. If not I will drop back to 6.)

    1. Yes I had issues too moving to node 7 etc… thankfully moving back sorted it – I guess tackling the guys at Node-Red for a “clean” solution to this might be good.

  11. I was reading one of your posts about making variables persist a reboot by writing them to a file, I’m trying to do that but I had a thought, what about sending them as an MQTT topic to an external server with the retain flag set and then get them back after a reboot.
    Do you think this would work, obviously if the network fails then it won’t work.

    1. Hi Phil

      That has been suggested and of course that is a perfectly good alternative – other than an external MQTT server being another potential source of failure…

      Personally – given that we’re talking – what, 1k of data MAX in my case, simply dumping the lot as JSON in a text file is as good as anything and has the advantage that if you needed to you can easily go into the file and make an amendment. As I keep everything in an object and simply write out the object, any changes made – like adding new variables – don’t involve any change of coding – as long as I SAVE the state of things after making the change so that the file reflects the new structure.

      As they say – works for me.

  12. I’m sure this has come up elsewhere, but a zero-footprint way of making global variables (and objects, and libraries etc.) visible to any flow can be achieved by editing the settings.js file in the .node-red directory.

    if you search for functionGlobalContext, adding members to that structure allows you to subsequently access them with global.get(‘MyKeyName’)

    This extends to libraries such as underscore/lodash which you can include with entries like this:

    functionGlobalContext: {
    lodash:require(‘lodash’),
    moment:require(‘moment’),
    localDbUrl:’http://192.168.1.227:5984/my_secret_db’
    },

    and can pull out of the global context with

    var _ = global.get(‘lodash’);
    _.each(…..)

    You need to restart node-red but i don’t find this sort of stuff changes much

    1. Iv’;e avoided that as it completely negates the idea of the visual environment – so now instead of editing anywhere from a brower, you need to be able to get to files – a mistake could stop Node-Red from running etc… that does not appeal…. but if it works for you..

  13. Excellent tips, Pete.

    On a whim I checked out the node-red website, the blog has release notes for versions 0.15 and 0.16 that were new to me. Many useful improvements. The animated GIFs showing how to use new UI features is particularly helpful – check out the new quick add node/wires in 0.16.

    http://nodered.org/blog/

    This note down in the Node Updates for 0.16 caught my eye:

    “The template node can now reference global and flow context properties – check its updated info tab for an example”

  14. I’d be interested to learn if there’s any log file maintained by node-red by default because right now I’m of the opinion that there isn’t one at all by default and the existence of a log file is dependent on how node-red is configured to start up.

    Node-red runs as a nodeJS application that squirts it’s output to the nodeJS console / the window that started the application. So basically if you were to start /usr/local/bin/node-red manually at the CLI and watch what happens in the CLI window with node-red running, you’d probably see output appear in fairly short order if your flow functions are setup to send debug / warn type output messages.

    I don’t know what Pete’s script does because I don’t have a compatible box to run it on but it’s easy enough to pipe the output of node-red to a file. In my setup I use an init.d script similar to this one that ensures node-red is automatically started at machine boot time and the output from node-red is squirted to a file:

    https://gist.github.com/Belphemur/cf91100f81f2b37b3e94

    See the logging section here for details about node-red supported log levels:

    https://nodered.org/docs/configuration

    For a raspberry Pi running on an SD card, I guess this is one of those areas that would need careful consideration..

      1. That looks very nice.

        It might be good to qualify this with a little bit of context though because there seems to be a tendency to assume that everyone is running node-red on a systemd based distro / a raspberry PI.

        I know that might be the case for a lot of people around here but for me at least that’s not the case (yet ;)).

        * journalctl is a systemd only tool / feature
        * As mentioned here: http://nodered.org/docs/hardware/raspberrypi.html systemd uses the /var/log/system.log for logging which is where node-red log contents will end up when node-red is setup on a RPI when configured as per this page (which I believe is the process that Pete’s setup script follows)

        Other operating system flavours hosting node-red may / may not work like this and they might support node-red logging in other ways

        1. take a look at the flow i linked in my gist, (the original flow, i stripped out that part…): it contains a node that will create a /var/log/node-red.log file, which you can then “tail” as you want (i pipe it to ccze to have it coloured)…

          1. Yes I’ve already taken a look at the flow in your linked gist here https://gist.github.com/fragolinux/3081ff65c420a329f95b1e4e38f3e771.

            It might help some people but to be clear, what the JS code in your function in this flow does is basically call console.log which I guess in your case just happens to end up logging into whatever log file you have configured.

            This flow code does no more than this, it does not create any log file and if the intention is for whatever that’s being logged via the console.log call to be logged to a file then it must depend on some log file already having been configured elsewhere.

            For the record calling console.log has the effect of achieving absolutely nothing here whereas node.warn and node.error do work for me and do have the effect of what I believe you’re trying to describe: custom messages into the node-red log.

            So I think you’ve described something that works for you in your particular setup or perhaps again described something that works in node-red when running on a raspberry PI but this is something that might not actually work in node-red in other O/S setups.

  15. Pete,

    I noticed that in this post that you made reference to “non-destructive failure with the logs”. This has been a long standing question I have and occasionally spend 30 minutes on every time it comes to mind.

    Where does node-red store it’s log(s) and how does one access it/them.

    I used the script to do an install on a pi3.

    I have seen the write-ups talking about what gets logged, but I cant find a reference to where they are stored and if some command interface is required to see them.
    I used the phpliteadmin just to look at what I could see from that viewpoint. Have tables but only 1 record has ever been stored and is in the pins table.

    1. You are asking the wrong man as I am anything but a Linux whiz… however – a good starting point is /var/logs

  16. Thanks for the insights Peter.

    Talking about debugging in Node-Red, I found a tool recently that helps if you attach Node-Red to other services in the net or if you create a WebService with Node-Red:
    https://insomnia.rest/. It’s a bit like Postman but can do more in my opinion.

    Just in case if you have some time to look into it and maybe make a Blogpost about it. Might help other followers of your great site!

  17. Peter, for me browser, or better wordpress, doen’t seem to highlight in bold the line you are talking about… just looking at code, i found it is:
    obj.getKeys = function() { return Object.getOwnPropertyNames(data); }

      1. Hi sir,
        I would like to assign statuses of 45 variables to false and then use them later in the program..I would like to know if we can set global variables in an array

  18. Nice one pete!.. Ive been fumbling around with this and all the time wishing there was a way to see the values without 1000 debug outputs….

    this is great!

Comments are closed.