Message structure checking not working as I thought

Ok, sorry, but this is confusing me.

I've recently been down the message structure trip and have learnt a couple of things.

So, I get a message from openweathermap node.

The rain fall is given in the message as: msg.data.rain["1h"]
Well, that's what is seems like when it is raining in the place.

So it has now raised the problem/question if there is no rain.

That part of the message doesn't exist.

So I wrote this:

node.warn(msg.data.rain["1h"]);

var x = msg.data.rain["1h"];

node.warn(x);

(Just to be sure)

Nothing.

No undefined messages.... No messages at all.

Why?

If that part of the message doesn't exist, why am I not getting an undefined message from it?

Does the msg.data part exist?
Does the msg.data.rain part exist?

are you getting an error?

Perhaps you should check before accessing...


// disable this to avoid an error when data or data.rain are undefined
// node.warn(msg.data.rain["1h"]);  

//if msg.data && msg.data.rain are SOMETHING, 
//  then       set x to msg.data.rain["1h"]  
//  otherwise  set x to null
var x = (msg.data && msg.data.rain) ?  msg.data.rain["1h"] : null;

node.warn(x);

EDIT

A tip for when you use node.warn - it can be dificult to see what the node.warn is warning you about when its just a number. Also, when its an object, you dont get to expand it etc.

When doing node.warn, I always do this....

node.warn(["rain value",x])

And you can even do this....

node.warn( [ "check the msg object value for msg.data.rain.1h should be same as x",  msg,  x ] );

... and see both the msg and the item of interest in the same warn message at the same time (no more guessing which msg was used to get x)

If there is no rain, msg.data.rain doesn't exist.

So I'm not sure that would work.

Got this working though.

if (msg.data.rain === undefined)
{
    msg.payload = "clear";
} else
{
    msg.payload = msg.data.rain["1h"];
}
return msg;

Sorry Steve,

I got a bit confused. But thanks for helping with checking the structure.

I'm guessing that the [1] part was not helping. So checking that the part before that existed seems to do the trick.

Yeah - and?

//if msg.data && msg.data.rain are SOMETHING, 
//  then       set x to msg.data.rain["1h"]  
//  otherwise  set x to null
var x = (msg.data && msg.data.rain) ?  msg.data.rain["1h"] : null;

^ do you not understand what that is doing? What happens is...

  • if msg.data is undefined - x gets set to null (or "clear" or whatever you want)
  • if msg.data is present BUT msg.data.rain is undefined - x gets set to null (or "clear" or whatever you want)
  • if msg.data is present AND msg.data.rain is present - x gets set to msg.data.rain["1h"]



Yes it will - you didnt try did you!



And what if msg.data is empty? You WILL get an error in your version!

No, I have never been good with that sort of stuff. So, no: I didn't try it. I don't understand how it works.

I may have to sit down and learn it one day, but it really just blows my socks off with the iterations (or what ever it is called.)

Back in 1980 I may have understood it but only if it was written in BASIC.

I'm guessing that if it exists, there will be a value. If there is no value, it is undefined.
As I have got two places showing rain and no rain and where there is no rain, the path/structure doesn't exist.

and I used msg.data.rain.... not just msg.data.

var x = (msg.data && msg.data.rain) ?  msg.data.rain["1h"] : null;

2 constructs exist her...

  1. ternary operator : something == a_value ? true_value: otherwise_value
    or in english : if something equals a_value return true_value otherwise return otherwise_value

  2. short circuits : (msg.data && msg.data.rain)

    • msg.data.rain will NOT be evaluated if msg.data is falsey

So again...

var x = (msg.data && msg.data.rain) ?  msg.data.rain["1h"] : "clear";
// if msg.data is undefined/null/false - set x to "clear" - STOP 
// if msg.data.rain is undefined/null/false - set x to "clear" - STOP 
// if msg.data && msg.data.rain are SOMETHING set x to msg.data.rain["1h"]  

Andrew - guessing is why you have so many problems.

In your version, if msg.data is undefined - your function node will throw an error.

why? - because you try to evaluate msg.data.rain

look at the first line of your "working" function...

if (msg.data.rain === undefined)

This will instantly throw an error if msg.data is missing.

where as the version i provided will NOT throw an error.


Any how, you crack on asking for answers then ignore them.

I pull the rain data like this if undefined it returns 0

[{"id":"ffc02d8f.5c58c8","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"payload.ChargeState","v":"11","vt":"num"},{"p":"msg.data","v":"{\"coord\":{\"lon\":0.28,\"lat\":50.77},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"base\":\"stations\",\"main\":{\"temp\":285.29,\"feels_like\":283.19,\"temp_min\":284.26,\"temp_max\":285.93,\"pressure\":1000,\"humidity\":81},\"visibility\":10000,\"wind\":{\"speed\":2.68,\"deg\":279,\"gust\":7.15},\"rain\":{\"1h\":0.44},\"clouds\":{\"all\":87},\"dt\":1603706880,\"sys\":{\"type\":3,\"id\":2012607,\"country\":\"GB\",\"sunrise\":1603694438,\"sunset\":1603730684},\"timezone\":0,\"id\":2650497,\"name\":\"Eastbourne\",\"cod\":200}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":2140,"wires":[["1d751194.60f8de"]]},{"id":"1632356d.a64dc3","type":"inject","z":"8d22ae29.7df6d","name":"","props":[{"p":"payload.ChargeState","v":"11","vt":"num"},{"p":"msg.data","v":"{\"coord\":{\"lon\":0.28,\"lat\":50.77},\"weather\":[{\"id\":500,\"main\":\"Rain\",\"description\":\"light rain\",\"icon\":\"10d\"}],\"base\":\"stations\",\"main\":{\"temp\":285.29,\"feels_like\":283.19,\"temp_min\":284.26,\"temp_max\":285.93,\"pressure\":1000,\"humidity\":81},\"visibility\":10000,\"wind\":{\"speed\":2.68,\"deg\":279,\"gust\":7.15},\"clouds\":{\"all\":87},\"dt\":1603706880,\"sys\":{\"type\":3,\"id\":2012607,\"country\":\"GB\",\"sunrise\":1603694438,\"sunset\":1603730684},\"timezone\":0,\"id\":2650497,\"name\":\"Eastbourne\",\"cod\":200}","vt":"json"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","x":110,"y":2200,"wires":[["1d751194.60f8de"]]},{"id":"1d751194.60f8de","type":"function","z":"8d22ae29.7df6d","name":"","func":"msg.rain = msg.data.rain || {\"1h\":0};\nmsg.rain = Object.values(msg.rain)[0];\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":280,"y":2180,"wires":[["49952583.65b3fc"]]},{"id":"49952583.65b3fc","type":"debug","z":"8d22ae29.7df6d","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":470,"y":2160,"wires":[]}]

Ok, I used the wrong word.

I have seen two places. When one place has rain, the path in the message payload exists.
If there is no rain, the path in the message payload doesn't.

So I guess that what I said is true: if there is rain, the path exists, and if there is no rain, the path doesn't.

By my original inclusion of the ["1"] messed up the checking.
Dunno why.
But if I only check the path to msg.data.rain and not msg.data.rain["1"] the check works.

I know in all my examples it was msg.data.rain and not msg.data.
So the rest of your reply is ..... void?

msg.data always exists in all tests / messages received from the node.
It is just msg.data.rain may not.

It isn't that I ignore answers.
It is more I ask a question and don't sit here/there expecting an answer.
I try to nut it out in the mean time myself.

I sometimes need to ask it on the forum to help myself get my head around the problem.
I'm sure I have mentioned this and declared it many times.

Sorry. It may not be a nice way, but it is the only way I seem to be able to get things done.

Yes that is fair enough. But I wanted to return Clear so in the field which says "Rain" it displays "Clear".

change value from 0 to clear in function node.

msg.rain = msg.data.rain || {"1h":"Clear"};
msg.rain = Object.values(msg.rain)[0];
return msg;

And that statement is why you have bugs as far as I am concerned.

Programmers should NEVER assume anything.

I can't prove that is true.
I am not that smart a programmer.
I admit that.

I can only say that all the messages comply (obey?) this theory.

So until it isn't disproved I can't see why it can't be true at this point.