How do I access property in nested object?

I am trying to understand how to access the boolean match:true in the object in the picture. I tried using:
sensor.double_take_cliff.data.attributes.match.match = true in a events:state node but it does not seam to trigger. What am I doing wrong ?

There’s a great page in the docs that will explain how to use the debug panel to find the right path to any data item.

Pay particular attention to the part about the buttons that appear under your mouse pointer when you over hover a debug message property in the sidebar.

BX00Cy7yHi

https://nodered.org/docs/user-guide/messages

It certainly looks like that is the right path to the property you want.

So I think this is more a question about the poll state node you are using - I assume that's a Home Assistant node?

Do you know which package of HA nodes you have installed?

The debug shows the path to the boolean as msg.data.attributes.match.match

I am using a "Event: State"-node for the automation. But I screenshotted the wrong node.

I tried that path to without success

Please show us how you tried, maybe post you attempt flow example.

I am asking which npm module that node comes from. There are quite a few home assistant sets of nodes. It is hard to check the node if we don't know which node it is.

If you open the Manage Palette dialog from the main menu, you should be able to find the name of the module you have installed that provides that node.

As we don't have much experience with the HA nodes here, I cannot say with any certainty whether that particular field supports entering a message property path, or if it expects a value to be hardcoded in.

Or maybe the node lets you pass that property in under a specific named msg property.

I am using "node-red-contrib-home-assistant-websocket" and the "server-state-changed" -node

This is the flow:

[{"id":"618b61471754e56b","type":"server-state-changed","z":"dd19e2e7.f72b4","name":"DoubleTake Cliff","server":"80866131.268ee","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.double_take_cliff.msg.data.attributes.match.match","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"true","halt_if_type":"bool","halt_if_compare":"is","outputs":2,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":480,"y":60,"wires":[["12909d7d1fe1704f"],[]]},{"id":"12909d7d1fe1704f","type":"api-call-service","z":"dd19e2e7.f72b4","name":"Google Mini Kök","server":"80866131.268ee","version":1,"debugenabled":false,"service_domain":"tts","service":"google_cloud_say","entityId":"media_player.google_home_mini_kok","data":"{\"message\":\"Hello Cliff\"}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":820,"y":40,"wires":[[]]},{"id":"80866131.268ee","type":"server","name":"Home Assistant","legacy":false,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true}]

Debug info:

{"topic":"sensor.double_take_cliff","payload":"kok","data":{"entity_id":"sensor.double_take_cliff","state":"kok","attributes":{"id":"1633680887.180206-njdtl2","duration":3.43,"timestamp":"2021-10-08T08:14:51.103Z","attempts":9,"camera":"kok","zones":[],"misses":[],"match":{"name":"cliff","confidence":98.26,"match":true,"box":{"top":73,"left":300,"width":87,"height":104},"age":{"probability":99.95,"high":32,"low":25},"gender":{"probability":100,"value":"male"},"mask":{"probability":99.77,"value":"without_mask"},"type":"latest","duration":0.41,"detector":"compreface","filename":"16fd2f46-f0b2-4332-910e-6747968547a3.jpg"},"friendly_name":"double_take_cliff","icon":"mdi:account"},"last_changed":"2021-10-08T05:35:38.119744+00:00","last_updated":"2021-10-08T08:14:51.113273+00:00","context":{"id":"5c8ee7515fa373b6e4d0bf15a9ba250b","parent_id":null,"user_id":null},"timeSinceChanged":"3 hours ago","timeSinceChangedMs":10558847,"original_state":"kok"},"_msgid":"5e9644c073a04827"}

I think our lack of experience with HA is showing.

From what I understand, the entityid field is used to identify the HA entity you want the node to emit the value of when it changes.

That field has to be hardcoded to a value. Some of the replies here (including my own) assumed you wanted to dynamically set that value of that field using the msg property you showed us in the Debug sidebar.

But I don't think that is what you mean. I think you have an entity in HA with a name of sensor.double_take_cliff.data.attributes.match.match that you want the node to monitor.

But the question is whether that is the right entityid to access that value from HA.

My guess, based on 5 minutes of poking around the node's repo, is you'd have sensor.double_take_cliff as the entityid and then you'd use a Change node after that to access the specific property you want to access - rather than try to address it directly in the HA node.

Does that make sense?

1 Like

I tried a new approach but could not get this to work either.

[{"id":"12909d7d1fe1704f","type":"api-call-service","z":"dd19e2e7.f72b4","name":"Google Mini Kök","server":"80866131.268ee","version":1,"debugenabled":false,"service_domain":"tts","service":"google_cloud_say","entityId":"media_player.home_mini_datorrum","data":"{\"message\":\"{{msg.payload.match.name}}\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":980,"y":500,"wires":[[]]},{"id":"7e185784378bc006","type":"api-call-service","z":"dd19e2e7.f72b4","name":"","server":"80866131.268ee","version":1,"debugenabled":false,"service_domain":"notify","service":"mobile_app_vog_l29","entityId":"","data":"{\"message\":\"Hej {{msg.payload.match.name}}\",\"title\":\"{{msg.payload.match.name}} Detekterad\"}","dataType":"json","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1010,"y":620,"wires":[[]]},{"id":"36ca1a7af08c8fa4","type":"mqtt in","z":"dd19e2e7.f72b4","name":"","topic":"double-take/matches/#","qos":"2","datatype":"auto","broker":"20094a2fb671b0c7","nl":false,"rap":true,"rh":0,"x":460,"y":560,"wires":[["a61c1f414436da28"]]},{"id":"a61c1f414436da28","type":"json","z":"dd19e2e7.f72b4","name":"","property":"payload","action":"","pretty":false,"x":710,"y":560,"wires":[["12909d7d1fe1704f","7e185784378bc006"]]},{"id":"80866131.268ee","type":"server","name":"Home Assistant","legacy":false,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true},{"id":"20094a2fb671b0c7","type":"mqtt-broker","name":"mqtt","broker":"192.168.0.5","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

But no I get the error-message: "Call-Service attempted without connection to server". But if I just use a "Inject-node" there is no errors. Do I need any additional nodes before triggering the HA-services ?

Never mind it seams to work. But I noticed another problem. Most often I get several triggers a few seconds apart. I would like to wait for atleast 5 minutes before triggering again.
I tried inserting a function-node with this code:

let timestamp = new Date(msg.payload.timestamp)
let name = msg.payload.name
fiveMin = 10 * 60 * 5
if(typeof flow.get("double_take") == undefined || typeof flow.get("double_take")[name] == undefined){
    flow.set("double_take", {[name]:{timestamp}})
}
if (typeof flow.get("double_take")[msg.payload.name] !== undefined && timestamp.getTime() > flow.get("double_take")[name].timestamp.getTime() + fiveMin ) {
   let updated = flow.get("double_take")
   updated[name].timestamp = timestamp
   flow.set("double_take", updated)
   return msg;
}

What am I doing wrong this time ?

[{"id":"7e185784378bc006","type":"api-call-service","z":"dd19e2e7.f72b4","name":"","server":"80866131.268ee","version":1,"debugenabled":false,"service_domain":"notify","service":"mobile_app_vog_l29","entityId":"","data":"{\t   \"message\":msg.payload.name,\t   \"title\":msg.payload.name & \" Detekterad\"\t}","dataType":"jsonata","mergecontext":"","output_location":"","output_location_type":"none","mustacheAltTags":false,"x":1130,"y":640,"wires":[[]]},{"id":"36ca1a7af08c8fa4","type":"mqtt in","z":"dd19e2e7.f72b4","name":"","topic":"double-take/matches/#","qos":"2","datatype":"json","broker":"20094a2fb671b0c7","nl":false,"rap":true,"rh":0,"x":340,"y":660,"wires":[["12909d7d1fe1704f","a506f74570e66e54"]]},{"id":"a506f74570e66e54","type":"change","z":"dd19e2e7.f72b4","name":"Change","rules":[{"t":"set","p":"payload.name","pt":"msg","to":"payload.match.name","tot":"msg"},{"t":"set","p":"payload.timestamp","pt":"msg","to":"payload.timestamp","tot":"msg"}],"action":"","property":"","from":"","to":"","reg":false,"x":560,"y":660,"wires":[["370ac7544b842cc8"]]},{"id":"370ac7544b842cc8","type":"function","z":"dd19e2e7.f72b4","name":"Time function","func":"let timestamp = new Date(msg.payload.timestamp)\nlet name = msg.payload.name\nfiveMin = 10 * 60 * 5\nif(typeof flow.get(\"double_take\") == undefined || typeof flow.get(\"double_take\")[name] == undefined){\n    flow.set(\"double_take\", {[name]:{timestamp}})\n}\nif (typeof flow.get(\"double_take\")[msg.payload.name] !== undefined && timestamp.getTime() > flow.get(\"double_take\")[name].timestamp.getTime() + fiveMin ) {\n   return msg;\n}","outputs":1,"noerr":0,"initialize":"\n","finalize":"","libs":[],"x":820,"y":680,"wires":[["7e185784378bc006","d81ea5829cb25afd"]]},{"id":"80866131.268ee","type":"server","name":"Home Assistant","legacy":false,"addon":false,"rejectUnauthorizedCerts":true,"ha_boolean":"y|yes|true|on|home|open","connectionDelay":true,"cacheJson":true},{"id":"20094a2fb671b0c7","type":"mqtt-broker","name":"mqtt","broker":"192.168.0.5","port":"1883","clientid":"","usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]

Debug-object:

{"id":"887824b1-a4df-4d41-835f-8fe3baf8022f","duration":0.47,"timestamp":"2021-10-10T09:36:39.730Z","attempts":1,"camera":"kok","zones":[],"misses":[],"match":{"name":"nova","confidence":91.83,"match":true,"box":{"top":46,"left":81,"width":56,"height":62},"age":{"probability":99.27,"high":32,"low":25},"gender":{"probability":100,"value":"female"},"mask":{"probability":100,"value":"without_mask"},"type":"mqtt","duration":0.45,"detector":"compreface","filename":"5d03a32d-07e7-434c-8572-eafa527602a1.jpg"},"name":"nova"}

Hi @burton666,
You get the property "name" from the double_take variable, which you have never set to flow memory. You could use:
var double_take = flow.get("double_take") || {};
To get an empty object, when it has never been set to flow memory before...

You get the error double_take is not defined on line 4 because in the original version of the code you shared you had:

flow.get(double_take)

But you have edited your post to add the missing double quotes:

flow.get("double_take")

Which will have fixed the error you are asking about.

So are you still getting that error or is something else not working?

I updated my last post with correct information, I also noticed that I had reversed the logic for checking for undefined.
But my problem is that I still get this error:
"TypeError: Cannot read property 'timestamp' of undefined"

Add node.warn statements to work out what is going on. Remember that once you have something in context it will not go away unless you overwrite it (or restart node-red if it is not in persistent memory). So if you have something bad in flow double_take then it will not get corrected by the code in the undefined test, as it isn't undefined.

I must be missing something. I don't get any information in the node.warn statements. Even if I just add node.warn("Message before function", msg.payload) at the top of my function I just get: "Message before function", nothing more.

Thats not how you use node.warn.

try node.warn(["msg.payload", msg.payload])

or

node.warn( {"msg.payload": msg.payload} )

or

node.warn(`msg.payload is ${msg.payload}` )

node.warn("Message before function" + msg.payload)

or, possibly better

node.warn(`Message before function ${msg.payload}`)