Error in a function in Node-Re 2.2 not present in previous versoins

Hi

I have a flow, part of my heating system - and in there is a function which has worked for maybe years... called process-heat - it has never failed - this afternoon I upgraded from v2.1.3 to v2.2. Node Red and received an error message - a number...... of undefined...

This is the code in the function. Thankfully I'd cloned the RPi before upgrading to v2.2. so I've gone back to v2.1.3 and there are no errors showing.

var timing=global.get("timing");
var now = new Date();
msg.payload=timing[(now.getDay()*24)+now.getHours()];
msg.away=timing[169];

msg.temperature=flow.get("incomingTemperature");
msg.humidity=flow.get("incomingHumidity");
msg.set=msg.payload;
if (flow.get("manualTimer")) flow.set("manualTimer",flow.get("manualTimer")-1);
else flow.set("manual",0);
msg.desired=msg.set;
flow.set("setTemperature",msg.desired);
msg.desired+=flow.get("manual");
// fixed local away to global away on jan 17 2020
if (global.get("away"))   msg.desired=global.get("timing")[169];  
if (msg.desired>msg.temperature) { msg.relay=1; } else { msg.relay=0; }

msg.payload=flow.get("incomingTemperature");

node.status({fill:"blue",shape:"dot",text:"Set point " + msg.desired + "c - Actual " + msg.temperature +"c"});

msg.topic="processHeat";
if (msg.temperature<msg.desired) msg.colour="#ff5555";
node.send([msg,null]);
msg.payload=msg.relay;
node.send([null,msg]);

image

Regards

Pete

What is the exact error message please, and where and when are you seeing it? If it is as a result of receiving a message show us what is going into the node.

I'll do my best Colin. I just cloned my working NR and took a screenshot - nothing in debug. I'll take the clone - do the NR upgrade on it - and run that and do a screenshot - to make sure I can reliably replicate the issue. I will come back on this regardless. Ta.

The function assumes a lot of variables exist (else = undefined), do they (all) exist ?

if the error is related to a "number of undifined" I would suspect flow.get("manual") results in an undefined in msg.desired+=flow.get("manual") because the += operator might expect a number

to debug I would try msg.desired+=flow.get("manual") || 0; or a if (flow.get("manual")===undefined) node.warn('upsi!'); before.

1 Like

When you move to a new install - you potentially lost context values.

This is what @bakman2 is refering to in that "The function assumes a lot of variables exist"

You should be checking the flow variables have some value.

e.g - here is the first 10 lines with comments...

var timing = global.get("timing"); //here you get   timing  but is it valid?
var now = new Date();
msg.payload = timing[(now.getDay() * 24) + now.getHours()]; //using  timing  without verifying is is an array
msg.away = timing[169]; //using  timing  without verifying is is an array


msg.temperature = flow.get("incomingTemperature"); //here you get   temperature   but is it valid?
msg.humidity = flow.get("incomingHumidity"); //here you get   humidity   but is it valid?
msg.set = msg.payload;  //no sanity check on msg.payload - is it a number? is it a valid number?
if (flow.get("manualTimer")) 
    flow.set("manualTimer", flow.get("manualTimer") - 1); //here you set manualTimer to manualTimer-1. but does manualTimer actually contain a number?

You should use things like

if(Array.isArray(msg.timing) == false) { 
  node.warn("timing is not an array - check global variables are set up!")
  return null; //halt flow of messages
}

and

if(typeof msg.temperature !== "number") { 
  node.warn("temperature is not a number - check flow variables are set up!")
  return null; //halt flow of messages
}
1 Like

You guys are SO helpful - I am just about to do the upgrade script on a clone (if the phone will leave me alone)... I'll come back soon - this seems like great info.

1 Like

Right - no changes - not even stopping Node-Red before the upgrade - just the upgrade script (including the usual option to include pi-specific nodes)... I checked, no debug messages even JUST before the upgrade.

I hit node-red-start and watched the debug...

All was well until:

[function process heat] TypeError: Cannot read propert '128' of undefined.

24 times in a row - identical message over a several minutes.. I left the SSH windows open this time.

Thing is I'm not seeing any reference in that code to 128....
It seems to have no problem getting timing[169] near the start...
This has me at a loss.

Finally after 10 mins it has moved on to griping about 129 ??!!??

So, this has never happened before so NR must now be checking something it wasn't before. Timing array is defined if not existing - on power up of NR.

If there was a way to narrow this to which line....

Yes, use node.warn everywhere to verify values.

See examples I provided before.

another example (without checking type)...

var timing = global.get("timing"); 
node.warn(["timing is -->", timing]);
var now = new Date();
msg.payload = timing[(now.getDay() * 24) + now.getHours()]; 
node.warn(["msg.payload is now -->", msg.payload]);
msg.away = timing[169]; 
node.warn(["msg.away is -->", msg.away]);

msg.temperature = flow.get("incomingTemperature"); 
node.warn(["msg.temperature is -->", msg.temperature]);

//and so on

The very first one Steve..

function : (warn)

[ "timing is -->", undefined ]

The problem with THAT is....

I have a function called at start up which I can manually trigger and just did... moade no difference- is there now something wrong with my check?

if ( typeof context.global.timing == 'undefined' ) 
    {
        context.global.timing=[
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        8,14
                        ];
        context.saving=0;
        msg.payload="anything";  msg.foryou="Restoring"; return([null,null,msg]);
    }

I should stress this has been in use for many months - it is only showing this error now with th new Node-Red update. Thoughts?

Yes.

let timing = global.get("timing");
if (!timing || !Array.isArray(timing))  {
       timing=[
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,
                        8,14
        ];
        context.saving=0;
        global.set("timing",timing);
        msg.payload="anything";  msg.foryou="Restoring"; return([null,null,msg]);
}

Yes, the context was likely setup (with values) before you had this ↑ issue.

When you upgraded node-red and no longer had the array of values in context, 2.2.0 fails due to it being empty/undefined. As the initialisation function was not setting context back up, your timing data is/was missing & not re-created.

Steve

No, still get:

[ "timing is -->", undefined ]

after making your changes and running my check...

Did you run the code and ensure global.timing had a value in the context viewer?

note

If global.timing is an empty array (or is corrupt), you might want to either delete it (use the delete button) or in fact just remove the if checks and let global.timing be initialised regardless of its state.

Whats the context viewer? I can indeed looking at my NR Dahboard stat see there are no values in that timing array - never happened before...

image

I showed it here ↓

Right.. no sign of timing at all. SO in my powerup checker inject (manual override) I removed the check and just initialised timing - it's STILL not there...

Can you show me that part of the flow and the code as it is now please?

Absolutely - give me a tick...

PS - did you press the refresh button

image

1 Like