Help with how to do this (JSON parsing of msg.payload)

I am still working on the idea, but this is the "problem" as of now.

I have 'n' machines tasked with pinging two addresses.

All machines:
Say: Address 1 and address 2.
If Address 1 is not ping-able, address 2 is Unknown.
Address status is ONLINE, OFFLINE, UNKNOWN.

I sort of have how each device does this, but I am not 100% sure just yet. It is still "work in progress".

All three devices then send their data back to a device. (One of the three, but I don't think that has any bearing on the problem, so to keep things separated, I'll say another machine.)

This other machine gets the 3 lots of messages from the devices and needs to then pick the "best" one and display it.

So, say:
Machine 1: ONLINE, OFFLINE
Machine 2: OFFLINE, UNKNOWN
Machine 3 ONLINE, UNKNOWN

I want to see Machine 1's messge.
I think it is something like (either) assigning a priority or weight to the messages.
As I see it, it is like this: ONLINE - Highest weight. OFFLINE - second. UNKNOWN - third.

Also - yeah, I know.... - I want to save any message in the event any of the machines can't send their message back to the main one.

I've seen this msg.queue node (this one) but I am not quite getting how it works.
I am not understand how the connected and disconnected parts are detected.

So back to what I want to do.
I just thought that rather than all machines send two messages of the state, the messages are combined into one and sent, making it a bit easier (?well....) on the fourth.
It only needs to parse one message to determine the weight of that one to then compare to the others.

Then there is the case of two or three have the same weight. Who gets priority?
In that case I guess it can be the first one in the list of received messages.

Thanks in advance.

Sorry man. I'll delete that post. I was inappropriate.

Don't worry. I know I am not the easiest to understand.

That is a normal day for me.

Yes, it would be nice if I could explain things better, but then I wouldn't be me.

I'm working on it now, but am now stuck with the && function to detect two variables being set at the same time.

I found this as a base line:
if (var1 ==1 ) && (var2==1)

So I am wanting to use it with this:
if (context.get("Modem") == 1) && (context.get("Uplink") == 1)

But I am seeing an error:
Screenshot%20from%202019-06-22%2011-13-46

I really must be clocking up the stupid points.

Well if you actually wrote that, you would get an error.

Basic syntax is ...
if(something)

Or in your case ...
if((something) && (somethingElse))

Bottom line is the if must be contained by parenthesis.

I.e. if(X) && (Y) is illegal.

if((X) && (Y)) is valid.

Btw, glad you could see the funny side :slight_smile:

Ok. Thanks.

This is where I found it:

It isn't worth getting upset.

I accept I am stupid.

I've been told that all my life.

I am trying to learn (thus the name) new things.

Ya gotta go through the bad stuff to get to the good stuff.

Just I seem to have a knack of find just the bad stuff.

Ah man, I didn't mean to imply that. Sorry. I don't think you're stupid. Eccentric hell yeah. A bit mad. Yup. But no, not stupid. You try, you give things a shot, and that is half the battle.

Good luck fella.

You didn't.

I just know I am.

I just seem to have this inability to explain things and it really makes it difficult to explai...

Yeah, anyway.

So, I hope you can understand how I feel when I am trying to ask a question but am unable to word it in a way that anyone else can understand.

That isn't just here. It is every where, every day with every one.

This is where I am at now with working on this problem:

Message 1:
{"payload":"Modem Online 11:31:54","device":"Modem","who":"TelePi","time":"11:31:54","_msgid":"c9c140f7.dd8fa","condition":"Online"}
Message 2:
{"payload":"UpLink Online 11:31:54","device":"UpLink","who":"TelePi","time":"11:31:54","_msgid":"c9c140f7.dd8fa","condition":"Online"}

Flow code:

if (msg.device == "Modem")
{
    //
    //  Modem detected.
    //
    node.warn("Modem message arrived");
    context.set("Modem",1)
    context.set("Modem_status",msg.condition);
} else
if (msg.device == "UpLink")
{
    //
    //  UpLink detected.
    //
    node.warn("UpLink message arrived");
    context.set("UpLink",1)
    context.set("UpLink_status",msg.condition);
}
//  if (var1 ==1 ) && (var2==1)

if ((context.get("Modem") == 1) && (context.get("Uplink") == 1))
{
    //
    //  both messages received.
    //
    node.status({fill:"yellow",shape:"dot",text:"message"});
    context.set("Modem",0);
    context.set("UpLink",0);
    msg = {device1: context.get("Modem_status"), device2: context.get("UpLink_status")};
    return msg;
}

I am seeing both contexts being set, but I am not getting to the // both messages received. part.

Confused.

Yeah, ok.

UpLink vs Uplink.

Moving on.

Also found the other mistakes.

But still can't get that last if working.

So I split it into 2 lines.

if (context.get("Modem") == 1)
{
    //
    if (context.get("UpLink") == 1)
    {

It looks good TBH.

I spot no obvious error.

You have added node.warns() to help debug this so I assume you have witnessed the "Uplink" and "Modem message arrived" messages in the debug side-bar & therefore the next part should work.

All I can suggest it you put debug nodes before and after this function node to ensure its called with the parameters you expect .

NOTE (an observation)...
I rarely create a new msg I often just set properties of the existing msg as there is often other info in the msg that helps me determine cause of unknown issues or at least give me a clue since it will contain the original values.

For example, instead of

msg = {device1: context.get("Modem_status"), device2: context.get("UpLink_status")};
return msg;

I would do...

msg.device1 = context.get("Modem_status")
msg.device2 = context.get("UpLink_status");
return msg;

...so as not to lose the original contents of msg that may prove useful.

Doing this instead means if I attach a debug AFTER the function node, it still has the original payload and other properties that help me determine where it came from etc.
Additionally, I often do temp calcs or store other 'info' vars in the msg object (instead of creating local vars or local lets, as it permits me to see them in the debug output if i made any obvious errors.

e.g...

if (msg.device == "Modem") {
    //
    //  Modem detected.
    //
    msg.info = "Modem message arrived";
    node.warn(msg.info);
    msg.modem = 1;
    context.set("Modem",msg.modem)
    context.set("Modem_status",msg.condition);
} else if (msg.device == "UpLink") {
    //
    //  UpLink detected.
    //
    msg.info = "UpLink message arrived";
    node.warn(msg.info);
    msg.uplink = 1;
    context.set("UpLink",msg.uplink)
    context.set("UpLink_status",msg.condition);
}

if ((context.get("Modem") == 1) && (context.get("Uplink") == 1))
{
    //
    //  both messages received.
    //
    msg.info2 = "both messages received";
    node.status({fill:"yellow",shape:"dot",text:"message"});
    context.set("Modem",0);
    context.set("UpLink",0);
    msg.device1 = context.get("Modem_status"); 
    msg.device2 = context.get("UpLink_status");
    return msg;
}
//lastly, if we reach here, then one of the context vars are not set! output a Warn()...
node.warn(`msg.device : '${msg.device}' may not match either 'Modem' or 'Uplink'.  Select this node & check context values in the side-bar to ensure context.Modem and context.Uplink have a value`); 

...by not replacing the original msg and adding aditional info to it, the debug side-bar can provide even better diagnostics.

Hope that helps somewhat (even if I cant see the issue in your code).




Ps, one bit of additional advice... better titles.

This topic would have possibly been better having a tile like "error in function node - expected identify and instead saw &&"

It permits potential helpers to know if it's something they are capable of assisting with.

E.g. if I see a post titled "Alexa isn't responding", I just bypass it as I don't have any Alexa experience (and hate Amazons dodgy sales practices with a passion).

However if I see a title "get value from JSON" I know I can help.

1 Like

Yeah, we kinda got off track a bit.

The other thing that was (note: was) killing me was the syntax.

msg = {"Who":msg.who,"device1": context.get("Modem_status"), "device2": context.get("UpLink_status")};

The "device1" and "device2" need the quotes around them.
I for got that and so the whole thing just died.

I may adopt that idea of how to create the messages that way as it is a bit easier to see/read/understand what is going on.

Thanks.

I'm still stuck. But further along the time line.

This time it is to do with JSON stuff I think, and sending the message to MQTT.

I usually have no problems, but there again: I seem to be good at making my own life difficult.

So:
I have the message and it is working fine.
This is the message which I made:
{"topic":"TelePi","Who":"TelePi","Modem":"Online","Uplink":"Online","_msgid":"c9c140f7.dd8fa"}

But what I forgot to declare was that is going into MQTT.

From memory, MQTT only deals with msg.topic and msg.payload.

So, if I want to get other things through, I have to put them as part of msg.payload.
Like:
msg.payload.who
msg.payload.modem
msg.payload.uplink

for instance.

But editing the function node and prefixing the names with payload doesn't seem to work.

I get a nice looking thing being sent to MQTT, but it doesn't get through.

The message becomes this:
{"topic":"TelePi","payload.Who":"TelePi","payload.Modem":"Online","payload.Uplink":"Online","_msgid":"c9c140f7.dd8fa"}

But it isn't getting through MQTT for some reason.

Sussed it out
I need to make the line:
`msg.payload = {"part 1":blah, "part 2": blahblah};

But yes, as Steve said, please go back and edit the title of this topic to be more descriptive

Recon that applies to just about all of us here :crazy_face: