Function node with excape for undefined variable?

Hi

I’m doing a function script in node-red, where I want to check if a variable is set…
Trying to use:

var intCurrentLux = (typeof msg.data.attributes.lightlevel !== undefined) ? msg.data.attributes.lightlevel : 0;

It dosn’t work, is there another way?
I really thought all javascipt was useable.

Right of the bat, i’d think about trying to put the variable in quotes. Did you try that?

I will try that tomorrow!

But you might be right :rofl:

Thanks for the tip!

Hi

So I did a little more testing.

var test = typeof msg.payload.data;
var strOffMsg = {payload: test};

Gives output:

{“payload”:“undefined”,"_msgid":“22fd74eb.c38bec”}

test = typeof msg.payload.data.test;
strOffMsg = {payload: test};

Gives output:

TypeError: Cannot read property ‘test’ of undefined

Any ideas how to solve this?

[{"id":"451dcf85.3c916","type":"debug","z":"b5a4f9b1.de8f78","name":"Test","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2510,"y":1420,"wires":[]},{"id":"d312e9d6.098228","type":"function","z":"b5a4f9b1.de8f78","name":"TestFunc","func":"\n\nvar strOffMsg = {payload: \"test\"};\n\nif (typeof msg !== \"undefined\"){\n    strOffMsg = {payload: \"test1\"};\n    if (typeof msg.payload !== \"undefined\"){\n        strOffMsg = {payload: \"test2\"};\n        if (typeof msg.payload.data !== \"undefined\"){\n            strOffMsg = {payload: \"test3\"};\n            if (typeof msg.payload.data,forcedkelvin !== \"undefined\"){\n                strOffMsg = {payload: \"test4\"};\n            }    \n        }    \n    }\n}\n\nreturn strOffMsg;\n","outputs":1,"noerr":0,"x":2220,"y":1460,"wires":[["451dcf85.3c916"]]},{"id":"544fb256.76bdbc","type":"inject","z":"b5a4f9b1.de8f78","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":2080,"y":1420,"wires":[["d312e9d6.098228","451dcf85.3c916"]]}]

Gives output

31

Still haven’t found a simpler solution :frowning:

usually the test is

if (“lightlevel” in msg.data.attributes) {
Code
}

Ii also done this in jsonata I simply convert the whole object to string and check for a substring in there, in this case lightlevel

Can’t follow you anymore… basically all you want is to check a specific message for the value undefined correct?

Can you post the debug output of where this message appears?

Hi

I want to see if my payload contains specific data, but if i was going too far in, it wouldn’t allow me to use typeof, if the preceding key wasnt there.

Ill use this and try writing something up and post later.

I dont know what your payload looks like, but have you tried the json node to convert the message?

if ( “data” in msg ) {
strMsg = {payload:"test"}    
} else { strMsg = {payload:"fail"} }

This comes with error

function : (error)

"SyntaxError: Invalid or unexpected token"

Yeah i wrote that from my phone is using “smart” quotes.

if ( "data" in msg ) {
strMsg = {payload:"test"}    
} else { strMsg = {payload:"fail"} }

Hi

To follow up on this, I’ve been testing a little and found your solution to fail for me as the typeof function.

This one can fail critically for a node in my experience
if ( typeof msg.data.attributes.rgb_color !== “undefined” ) {

Where following line fails the same way
if ( “rgb_color” in msg.data.attributes ) {

{"payload":"on","data":{"entity_id":"light.spisestue","state":"on","attributes":{"min_mireds":153,"max_mireds":500,"effect_list":["colorloop","random"],"brightness":254,"color_temp":433,"is_hue_group":true,"friendly_name":"Spisestue","supported_features":63},"last_changed":"2019-11-09T21:10:10.139638+00:00","last_updated":"2019-11-09T21:10:10.139638+00:00","context":{"id":"279422faf5fb47128afbdd98b6eb5c0e","parent_id":null,"user_id":null},"timeSinceChangedMs":291879},"_msgid":"fc58c36e.72efb"}

“TypeError: Cannot read property ‘attributes’ of undefined”

It works for me, your paste shows smart quotes

[{"id":"fdeca4fa.a98e28","type":"debug","z":"44b7dcf.3c61024","name":"on","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":1710,"y":120,"wires":[]},{"id":"629229ff.43db88","type":"function","z":"44b7dcf.3c61024","name":"","func":"if ( typeof msg.data.attributes.rgb_color !== \"undefined\" ) {\n    msg.test = true\n} else {\n    msg.test = false\n}\nreturn msg;","outputs":1,"noerr":0,"x":1540,"y":120,"wires":[["fdeca4fa.a98e28"]]},{"id":"58255d63.576c24","type":"inject","z":"44b7dcf.3c61024","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":1220,"y":120,"wires":[["3bcc3503.95775a"]]},{"id":"3bcc3503.95775a","type":"api-current-state","z":"44b7dcf.3c61024","name":"","server":"d5ce5cec.92bc8","version":1,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"light.dining_table","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":1390,"y":260,"wires":[["629229ff.43db88"],[]]},{"id":"d5ce5cec.92bc8","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true}]

I’m not sure where they came from, I just looked at my script, and couldn’t them there.

Can you make a test, for a key that isn’t in the object? Eg. typeof msg.data.attributes.unknown ?
Because, when the key is there, I don’t get an error, only when it’s missing.

At the moment I’m working towards either converting the msg object to an javascript array and search for the key, og just convert to json string, and search for the specific text.

I am not js ninja, but In my flow it works for example i change to this

if ( typeof msg.data.attributes.rgb_clr !== "undefined" ) {
    msg.test = true
} else {
    msg.test = false
}
return msg;

and returns false

That could work also

edit: in the first example it will only work if msg.data.attributes exists, if it doesn’t it fails with ‘cannot read property…’

I just made this work

[{"id":"cffcd46d.778228","type":"debug","z":"b7656499.b2541","name":"on","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","x":2890,"y":800,"wires":[]},{"id":"946fcc7.9574c3","type":"function","z":"b7656499.b2541","name":"Known","func":"if ( typeof msg.data.attributes !== \"undefined\" ) {\n    msg.test = true\n} else {\n    msg.test = false\n}\nreturn msg;","outputs":1,"noerr":0,"x":2720,"y":780,"wires":[["cffcd46d.778228"]]},{"id":"4e2cf74.88ae908","type":"inject","z":"b7656499.b2541","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"onceDelay":0.1,"x":2400,"y":780,"wires":[["bb4b5ae2.9a6ce8"]]},{"id":"bb4b5ae2.9a6ce8","type":"api-current-state","z":"b7656499.b2541","name":"* Light Already On?","server":"468387c0.b24028","version":1,"outputs":2,"halt_if":"on","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"light.hue_color_candle_2","state_type":"str","state_location":"payload","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":2570,"y":880,"wires":[["946fcc7.9574c3","95f17bdd.5beef8"],[]]},{"id":"95f17bdd.5beef8","type":"function","z":"b7656499.b2541","name":"Unknown","func":"if ( typeof msg.data.attributes.unknown !== \"undefined\" ) {\n    msg.test = true\n} else {\n    msg.test = false\n}\nreturn msg;","outputs":1,"noerr":0,"x":2740,"y":820,"wires":[["cffcd46d.778228"]]},{"id":"468387c0.b24028","type":"server","z":"","name":"Home Assistant","legacy":false,"hassio":true,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":false}]

If the state node only allows to pass when the light is on, then it shouldn’t fail to check the rgb_color property should always be there if that’s the only light you are checking, if is a binary simple light with no attributes it will fail of course

I am jus ttesting if I by accident overwrite the msg object inside my function…

So i changed all msg = to new_msg =

Maybe it did the trick, checking now.

var MyLight = "diningroom";
var OldSettings = global.get("OldSettings");
var msg1 = "msg1";
var msg2 = "msg2";


if ( typeof msg !== "undefined" ) {
    if ( typeof msg.data !== "undefined" ) {
        if ( typeof msg.data.attributes !== "undefined" ) {
            if ( typeof msg.data.attributes.rgb_color !== "undefined" ) {
                OldSettings[ MyLight + 'lightcolorr' ] = msg.data.attributes.rgb_color[0];
                OldSettings[ MyLight + 'lightcolorg'] = msg.data.attributes.rgb_color[1];
                OldSettings[ MyLight + 'lightcolorb'] = msg.data.attributes.rgb_color[2];
                msg1 = "Saved following as default for " + MyLight + ": " + msg.data.attributes.rgb_color;
            } else { new_msg = {payload: "fail4"} }
            if ( "brightness" in msg.data.attributes ) {
                OldSettings[ MyLight + 'brightness'] = msg.data.attributes.brightness;
                msg2 = " ::: Set int" + MyLight + "Brightness = " + OldSettings[ MyLight + 'brightness' ];
            } else { new_msg = {payload: "fail5"} }
            new_msg = {payload: msg1 + msg2 };
        } else { new_msg = {payload:"fail3"} }
    } else { new_msg = {payload:"fail2"} }
} else { new_msg = {payload:"fail1"} }

global.set("OldSettings", OldSettings);

new_msg.payload.oldsettings = OldSettings;

return new_msg;

image

I was so focused on the function and not so much on what I data I used it on… Sorry for all this confusion!

When faced with a similar situation I tested a bunch of methods before settling on .hasOwnProperty.

I.E. if (msg.hasOwnProperty (‘meta’)) { }

You still need to start at the “root” of the msg and iterate in to the value much like you’ve done above.

Hi

Yes, this is some of the code that I’ve used

if ( typeof msg !== "undefined" ) {
    if ( typeof msg.data !== "undefined" ) {
        if ( typeof msg.data.attributes !== "undefined" ) {
            if ( typeof msg.data.attributes.rgb_color !== "undefined" ) {
...
            } else if ( typeof msg.data.attributes.color_temp !== "undefined" ){ 
...
            } else { new_msg = {payload: "fail4"} }
            if ( "brightness" in msg.data.attributes ) {
...
            } else { new_msg = {payload: "fail5"} }
        } else { new_msg = {payload:"fail3"} }
    } else { new_msg = {payload:"fail2"} }
} else { new_msg = {payload:"fail1"} }

Main problem being that if I set a philips hue color lamp to the white ambiance from the app, it dosn’t show the rgb color, and the other way around too…