Single flow to turn off lights in multiple locations based on no motion for location-specific time periods

Hi

I tried to use an Events: State node as the trigger for a single flow to turn off lights in multiple locations based on no motion for location-specific time periods, as per the screenshot:

image

I defined the entity that detects motion using regex as follows:
binary_sensor.motion_(bathroom|bedroom1|bedroom1wir|bedroom2|bedroom3|bedroom4|bedroom4wir|dining|ensuite|ensuiteshower|ensuitetoilet|gym|kitchen|laundry|living|rearhallway|scullery|theatre|toilet)

I created a helper entity for each location to specify the timeout period to wait after no motion has been detected before turning off lights. They are in the format:

input_number.motion_light_timeout_[location]

e.g. input_number.motion_light_timeout_bedroom1.

I tried to put the following expression for the ‘for’ value:

$entities("input_number.motion_light_timeout_" & $split($entity().entity_id,"_")[-1]).state

But I get an error: “Invalid value for ‘for’: undefined”. It seems that $entity() can’t be used in the ‘for’ expression.

Is there another way I can do what I’m trying to do without creating one flow per location?

Yes I believe so.

What an interesting (and challenging) problem.

I spent ages looking at this and came to the same conclusion - the $entities() function is not working correctly / at all in the ‘For’ field. Strangely it works everywhere else I have used it.

Debugging this is quite a nightmare: using a JSONata code block to step through each stage of your expression (get entity/id/end string/build input id/get entities/state/number) and then using a conditional to predicate test each part against its expected result, so as to output a literal of either 1 or 5, and then seeing if the ‘for’ delay is 1 second (true) or 5 seconds (false). Yes, it all works but for the $entities(entity id).

I am inclined to think that this is most likely a JSONata execution bug specific to this one field, definitely something for @Kermit to look at.

So, in the mean time how to get around this?

Since the output property fields are working correctly (I tested your expression there first) my thought is to

  • use the ‘is’ state test so as to output only on ‘off’, but not use the ‘for’ period delay - node will trigger immediately
  • use JSONata expression as you have it in an output property field, to obtain the timer delay for the input_number associated with the location - that works
  • place this value into output property msg.delay
  • use a standard delay node, with settings so that the delay period is taken from the incoming msg.delay.

The only change I have made is to add $number() to your expression. The $entities(id).state returns the state which HA always keeps as a string.

I have tested this as best I can - certainly the JSONata works in that field, and the delay node works with msg.delay.

The nice thing about the delay node is that each message is individually delayed for the time set by the incoming msg.delay value, and thus multiple event triggers would still work by delaying each individual motion-off message by the corresponding period.

I hope this helps!

Extra: Problems with using JSONata expressions in the ‘For’ field of events:state node.

In testing the ‘For’ field using your JSONata expression I (as expected) had the same error messages “Invalid value for ‘for’: undefined”. Oddly, the second time I changed and tested the expression, I got two error messages, then three…

Moving on from that I removed the JSONata expression, but the error messages persisted. Later I disabled and re-enabled the node. The error messages in debug window eventually stopped, but I have just checked my Node-RED log (in HA) and found

3 Apr 17:15:45 - [error] [server-state-changed:b5419c1c8ae6966f] Invalid value for 'for': undefined
3 Apr 17:15:45 - [error] [server-state-changed:b5419c1c8ae6966f] Invalid value for 'for': undefined
3 Apr 17:15:45 - [error] [server-state-changed:b5419c1c8ae6966f] Invalid value for 'for': undefined
3 Apr 17:15:45 - [error] [server-state-changed:b5419c1c8ae6966f] Invalid value for 'for': undefined
3 Apr 17:15:45 - [error] [server-state-changed:a9d8c9422bb3556c] Invalid value for 'for': undefined
3 Apr 17:15:45 - [error] [server-state-changed:a9d8c9422bb3556c] Expected ")", got "c"

This has been running all day, generated errors every 20 seconds (every time the originally used sensor updated) even though the offending code has long since been removed and the node has been disabled, and then deleted. I have just restarted Node-RED and the log error messages have finally stopped. Clearly something rather amiss with this as it appears to be leaving orphaned JSONata code running in the background.

Makes me wonder how much orphaned ‘stuff’ is out there running in the background not doing anything but not generating an error message!

Yes, looks like the trigger entity is not passed to the JSONata service.

https://github.com/zachowj/node-red-contrib-home-assistant-websocket/blob/6165209f224af511bc99fb33460aaa53270857a6/src/nodes/wait-until/WaitUntilController.ts#LL177-L191C10

I was wrong the for value gets set at the time of input so the trigger entity is never going to be able to be used inside the JSONata expression.

Hi @Biscuit and @Kermit. Thanks for looking into this.

I’ve been using $entity() in output property fields for many other flows so I can’t believe I didn’t think of trying to add a delay node!

I also had to add a check after the delay to ensure the flow only progressed further if motion wasn’t subsequently detected again during the delay period.

It seems to be working as expected. Thanks!