Wild card or variable attribute in javascript object as payload?

Wild card or variable attribute in JavaScript object as payload? Crazy question... right? Let me explain, I have an MQTT message I want to 'parse' the payload in a unique way, but I suspect I will need to use a function node rather than a switch node? Below is the payload structure:

(parent object attribute)
(child attribute)
(child attribute)

The message payload data structure can be one or more elements of an array, as a parent object in an object. I only need to test one of the attributes in the child object as an item in the array.

So msg.payload.., for example msg.payload.23.1 or msg.payload.23.0, or payload.22.0, or msg.payload.21.0. But the MQTT message the first is variable. So if I use a typical switch node, I need a test for each value, then forward the message to an additional switch node to handle the 0,1 values.

If msg.payload.* or even payload.+ could be the defined property (name or string) then I could do something like payload.+.1 or payload.+.0 or payload..1 or payload..0 and avoid the additional switch node? But I think that is not possible in some way or is it?

Hi, unfortunately due to some of the terms you are using the explanation isn't totally clear.

Perhaps you could post a screenshot and also use the copy value button that appears when you hover over payload in the debug window and paste that in the reply so we can see more clearly what the structure of the data is.

Also point out which values of the payload would you are interested in testing and what you want to compare them to.

Yeah, this may illustrate it better...

object

topic: "status/irrigation/TestListener/control/23"

payload: object

23: object
mode: 0
state: 1
qos: 2
retain: false
_msgid: "ddae436e.a32f"

The 23 is an index (really a hash key) but can act as an index where there are more than one response in the same MQTT message. So one message may have 23 as key to a child object, the next message may have 23, 24, 25, each with its respective child object.

Each associated child object has various attributes, but the one I need to switch for is the 'state' value. In a typical flow, you could switch on the parent object, or index, say 23,24, or 25. Fortunately, the values are known. So branch the flow on the state value, could be done as msg.payload.23.state = 0 or 1. But this hardcodes the 23, where if there was a wildcard option, then the switch could just test msg.payload.*.state = 0 or 1. It is definitely a specific use case of a sort. A function node could handle it, but I was thinking there might be some way to do it with a switch node?

Hi sorry no that's not really much more clear as it's not valid json. Can you please use the copy value button that appears under your mouse cursor when you hover over the payload. Also a screenshot with one or two of the objects expanded fully so I can see the types of object and values that are present in your data.

Lastly when you paste the Data please make sure it is correctly formatted using the code button or three backticks above and below the pasted value.

LOL! Seems clear to me! Just kidding. Here is the raw JSON for payload, with a single element...

{"23":{"mode":0,"state":0}}

Multiple elements...

[
{"23":{"mode":0,"state":0}},
{"24":{"mode":0,"state":0}},
{"25":{"mode":0,"state":0}}
]

I can't see the top-level payload object. I need to know if it's an array or an object or something else. About that screenshot with the payload expanded out.

Ah... This better?
image

would be simple using JSONata. In javascript you would need to use Object.keys() to look up the payload keys, this become more difficult if the payload has more than one key.

here is a simple example if payload has one key

[{"id":"c28b4791.fbe9e","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{\"23\":{\"mode\":0,\"state\":1}}","payloadType":"json","x":140,"y":3600,"wires":[["3855bddf.df6552"]]},{"id":"3855bddf.df6552","type":"function","z":"c74669a0.6a34f8","name":"","func":"let key = Object.keys(msg.payload)[0];\n//node.warn(key)\nif(msg.payload[key].state === 1){\n    msg.payload = 1;\n}\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":330,"y":3640,"wires":[["38c4f39.bf58c0c"]]},{"id":"4cd0507b.f8073","type":"inject","z":"c74669a0.6a34f8","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"{     \"26\": {         \"mode\": 0,         \"state\": 1     } }","payloadType":"json","x":160,"y":3660,"wires":[["3855bddf.df6552"]]},{"id":"38c4f39.bf58c0c","type":"debug","z":"c74669a0.6a34f8","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":580,"y":3640,"wires":[]}]

So using a function node is the realistic option. That is what I suspected. :slight_smile: The message will often have just 1 key, but many are possible depending on what the sensors return. The sensors are in clusters and one or more fire based on the circumstances. I just need to determine if one of many has changed state in the flow, hence the idea of payload.*.state = 0 or 1. As I said it is a unique use case.

What I really need to do is rewrite the TestListener python script to return data in a manner that is a bit easier for NR to handle. But the TestListener script works, is rather complex. Might be easier to just add another publisher in the TestListener script that fires when 1 of many sensors fires... then NR would just get a simple state message as the state changes. :slight_smile:

It is hard to understand what will be the practical use case. The properties 23 and 24 are different things. Most probably in the equipment too. So the child properties will loose their meaning if you treat them by ignoring the source.

You could use a change node with expression like
payload.*.state as JSONata allows wildcards

@hotNipi, yes... that is true. Given the known source in this case I can avoid that specific issue. But your point is valid and well noted.

@E1cid, yeah, that is basically the realistic option, or I just hide all the details in a function node. Or I could add a new publisher from the source, that is summaries the sensor cluster state, rather than the source returning the state of each sensor that just fired, when I don't really need the per sensor state for the flow.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.