How to parse message parts to variables

Sorry folks, I'm stuck again.

Story:
I have a message (with a LOT of extra stuff added on to save me using flow context.) and want to use one part to point to another part of the message.

eg:

So:
msg.payload.who gives me S21. I then want to translate that to what that part of the message is. In this case msg.S21

But I can't remember the trick needed to do that.

Someone - please.
I know it is easy, but I can't remember.

node.warn(`LED ${ msg.payload[ msg.payload.who ] }`)
1 Like

(Ok, I won't repost the screen shot.)

I saw the mistake there.

But it doesn't solve the problem.

I really must have pissed the gods off.

That is right - yes?
(But not getting the right result.)

Can you share the input object please - makes it a lot easier to come up with correct code.

And to prove the point, I didn't see in the original message that it needs to be msg[msg.payload.who]

Sorry...

Here's the code. (Cut down)

[{"id":"cbce6faf1a990d00","type":"inject","z":"a1911aa3.c45be8","name":"Request 2","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"request","payloadType":"str","x":1680,"y":3140,"wires":[["aa56b0127f924373"]]},{"id":"aa56b0127f924373","type":"change","z":"a1911aa3.c45be8","name":"","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"who\":\"S21\",\"power\":\"REQUEST2\"}","tot":"json"}],"action":"","property":"","from":"","to":"","reg":false,"x":1795,"y":3140,"wires":[["5cb9d1e4615b4047"]],"l":false},{"id":"2d11cf195d61c08d","type":"change","z":"a1911aa3.c45be8","name":"POWER Colours","rules":[{"t":"set","p":"REQUEST","pt":"msg","to":"REQUEST","tot":"flow"},{"t":"set","p":"REQUEST2","pt":"msg","to":"REQUEST2","tot":"flow"},{"t":"set","p":"DETECTED","pt":"msg","to":"DETECTED","tot":"flow"},{"t":"set","p":"FULL","pt":"msg","to":"FULL","tot":"flow"},{"t":"set","p":"REMOVED","pt":"msg","to":"REMOVED","tot":"flow"},{"t":"set","p":"S21","pt":"msg","to":"2","tot":"num"},{"t":"set","p":"S5","pt":"msg","to":"3","tot":"num"},{"t":"set","p":"other","pt":"msg","to":"4","tot":"num"}],"action":"","property":"","from":"","to":"","reg":false,"x":1860,"y":3450,"wires":[["f1e91ce466ceef93","796148bfb7573c9f","430a11c880744cea"]]},{"id":"5cb9d1e4615b4047","type":"junction","z":"a1911aa3.c45be8","x":1720,"y":3450,"wires":[["2d11cf195d61c08d"]]},{"id":"430a11c880744cea","type":"function","z":"a1911aa3.c45be8","name":"function 14","func":"node.warn(\"Who \" + msg.payload.who);\n\nnode.warn(`LED ${msg.payload[msg.payload.who]}`)\n\n\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":2000,"y":3570,"wires":[[]]}]

But I think it is something to do with the msg.S21 is NOT msg.payload.S21

Yup, saw it in the 2nd image.

When I trim down what you offered from:
node.warn(`LED ${msg.payload[msg.payload.who]}`)

to

node.warn(`LED ${msg.payload[msg.who]}`)

It doesn't work either.

Unless I have missed another elephant.

Wrong way round!

node.warn(`LED ${msg[msg.payload.who]}`)

I'm so sorry.

Thanks.

That's it.

It would be nicer - for both you and me - if I could get my head around the structure.

I understand the square brackets to reference the value of msg.payload,who

But can you explain the ${ } and backticks?

node.warn(`LED ${msg[msg.payload.who]}`)

and

node.warn("LED   " + msg[msg.payload.who])

seem to be equivalents?

Sure, the backticks define a JavaScript template literal string. Such strings are allowed to contain JavaScript code inside a ${...}.

This is actually more efficient than "string " + something. And often neater code as well. Part of ES6. Template literals allow multi-line strings too.

They are! Other than the fact that the JavaScript JIT can pre-compile much of the string making the whole thing more efficient.

For some extra fun, here is a simple JS function that lets you put HTML into a string. Used in VScode, you get syntax highlighting inside the string. :slight_smile: Some libraries have similar extended string template functions. This is called a "tagged template".

function html(strings, ...keys) {
    return strings.map( (s, i) => {
        return s + (keys[i] || '')
    }).join('')
}

// https://www.makeuseof.com/responsive-navigation-bar-using-html-and-css/
const myHtml = html`
    <style>
        :host {
            width: 100%;
            background-color: black;
            color: white;
            padding: 0;
            margin: 0 0 0.8rem 0;
            /* border: 2px solid silver; */
        }
    </style>
`

This is a snippet from one of my example HTML Components.

Template literals (Template strings) - JavaScript | MDN (mozilla.org)

Though I now see an even simpler version of the above from the MDN example:

const html = (strings, ...values) => String.raw({ raw: strings }, ...values)

Thanks! :face_with_spiral_eyes:

Haha. Well, the tagged template may be a bit esoteric. But template strings are really useful and greatly simplify a lot of code where you are combining strings and variables which is a very common requirement.

(I hear you @jbudd )

I am still not getting it for some reason.

Going back to this:

node.warn(`LED ${msg.payload[msg.who]}`)

(Ok, why am I not getting the colours?)

That will put a node.warn message out.

There is a pointer which is msg.payload.who.
This points to the part of the msg I want to get.

So I use the pointer of msg.payload.who to construct the new msg
Ok, pointer is the wrong word I fear..... but for now.

ARGH! This is doing my nut it.

Maybe made worse because I don't know the correct terms to use.

Ok:
The contents of msg.payload.who (S21).
So I need to get the contents of msg.S21 (2)

I am really missing something.
The payload in there.... I thought the pointer (index?) was msg.payload.who I am not getting how the msg.payload[msg.who] bit works. Because it is msg.payload.who according to the picture I posted - and I am sure that is the message structure I have since adopted.

If it isn't too difficult......

Good enough term.

Really, you are using the value of the who property of msg.payload as the reference to a property of msg.

That's because IT DOESN'T! You need msg[msg.payload.who] as I've said!

Sorry....

I am really not keeping up.
(My fault.)

I was a bit distracted with getting that stuff on the subflow working and that was a bit painful.
But it now works.

So I thought I would catch up on the help you gave me and (obviously) stumbled at the get go.

Ok, I'll go back and look at it again.

Bedtime in the UK. Catch you tomorrow.

1 Like

Apologies, I had msg.who and msg.payload.who confused above. I've edited it.

Restating this to solidify my own understanding...

These are all different ways to obtain the value of msg.S21
(in the above example msg.payload.who = "S21" and msg.S21 = 2)

node.warn("LED " + msg.S21)
node.warn("LED " + msg["S21"])
node.warn("LED " + msg[msg.payload.who])

And I can get the same thing using a template literal (i.e. enclosed in backticks)
Except that inside the backticks, any javascript must be wrapped in ${ and }

node.warn(`LED ${msg[msg.payload.who]}`)