Node Red Initialisation

There have been various conversations about Node-Red initialisation of variables recently. Here’s a solution.

So firstly – what’s the problem? Well, because of the asynchronous nature of Node-Red, it seems to be that sometimes you find yourself using a global variable before it has been defined. No lectures on using global variables please. I can see in my own systems, in the log, incidences of uninitialized variables.

My own solution to the issue of non-volatile storage has been to save global variables as a single object, into a file – and restore said on power up (thermostat settings etc.) – you could store them in MQTT, in a database, anywhere – doesn’t matter. The issue is restoring them.

On power up one assumes the left most tab in Node-Red will run first and that is generally true – but where anything asynchronous is happening – like getting a file for example (hint) there could be delays and other code could run using one of your variables before you’ve actually set it up. This usually does NOT result in Node-Red crashing but you can get rubbish results. Of course you can check every time you use a variable if it exists but that can get messy REAL quick.

A conversation started in the Node-Red discussion groups recently – one of many - and I just latched onto an idea and ran with it.  Of course my first few attempts resulted in suicidal feelings as they failed time after time – but just mid- morning it all started to come together.

So, first things first – the Node-Red settings.js (created when Node-Red is installed and could be for example at /home/pi/.node-red/settings.js)  file runs BEFORE Node-Red comes online – so you know that if you initialise stuff in there, it will be set up in time for you to use – but messing with that file from within Node-Red could be dangerous and you could kill the whole installation. It also  defeats the object of having everything in one nice visual interface.

Here’s another way

Within settings.js there is “functionGlobalContext” which sets up any globals you might need for example – fs object for using files. Here is that section (typically) with one line added into settings.js

functionGlobalContext: {

os:require('os'),

moment:require('moment'),

fs:require('fs'),

mySettings:require("/home/pi/.node-red/redvars.js")

    },

See that last line with “mySettings” -  you can call that what you like.

In (for example) your /home/pi directory, create a simple file called redvars.js (or anything you like really). In there you could put this..

and thanks to Nick O’Leary for the specifics…

module.exports = {

    "fred": 1,

    "brian": 2

}

However, what happens if the redvars.js file is corrupt for any reason – answer? Node-Red crashes..

Here then is a better way:  

At the VERY START of setting.js add this..

var mySettings;

try {

mySettings = require("/home/pi/.node-red/redvars.js");

    } catch(err) {

mySettings = {};

    }

So mySettings is either populated or made empty. No crashing. Now you only need to add ONE line to the functionGlobalContext – here it is in my case… yours might be different…

functionGlobalContext: {

os:require('os'),

moment:require('moment'),

fs:require('fs'),

mySettings:mySettings

    },

As you can see, with an additional comma then one line, a foolproof version of mySettings has been added.

Run Node-Red and you will now find that (for example)  global.get(“mySettings.fred”)  returns 1.  SO – now all you have to do is to put what you need in that file redvars.js – and if you need to update them you can do that within Node-Red. 

In my case I have a variable called counter in there.   Every time I update something, I update that counter to 10;   I have a little timer job running that checks that var and if not zero, decrements it – if it is now zero, it updates the file… see how I did that below.

If you look at my original article on this subject – all seemed well, simply stringify the object and save it to disk – and that’s really how I’d like it to be - but my mechanism for RETRIEVING the object on power-up failed miserably because of the async nature of the file read – often resulting in use of the variables before they existed. This way, that won’t happen and all it needs is to stringify the object and add “module exports-“ at the start.

In the unlikely event that the redvars.file is corrupt, on power-up, mySettings will be undefined – easy to check and if necessary overwrite.

So one simple change on initial setup of Node-Red – and from there on you can create or amend non-volatile global variables from within Node-Red.  You could expand on this of course – that is up to you.

Update 26/03/2017 - This modification is now in the script!

Facebooktwittergoogle_pluspinterestlinkedin

4 thoughts on “Node Red Initialisation

  1. Hi Peter
    Very good idea! I used your newest script and created a file called redvars.js with a copy-paste content of your "fred - brian" example above. I had to place the file in the node-red folder (not in the /home/pi directory). But still, I cannot access the variable with the statement
    var over=global.get('mySettings.fred');
    node.status({fill:"blue",shape:"ring",text:"Override: "+over});
    I always get: Override undefined. Where is my mistake?

  2. Not relevant to this post but.....
    Can anyone tell me where to find the logs created eg

    console.log("buf["+i+"] = "+buf[i]+" = "+buf[i].toString(2)+" b");
    thanks
    John

  3. Hi Peter!
    Please do you have a sample from using the "node-red-contrib-google" node for speech API on the node-red? thanks a lot! Linda

Leave a Reply

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