How to combine occupancy sensor states

Hello,
I have a room with two motion/occupancy sensors. I am writing a flow that will turn off the lights if both sensors are clear. In terms of state logic this is a simple AND:

if (sensor1.occupancy = Clear) AND (sensor2.occupancy = Clear) then turn off the lights.

image

But as Node Red / HA is event based I’m struggling to understand how best to handle this.

Concept:
events all node for entity_id = sensor 1,

feed into a change node to save the occupied / clear state.

feed into get entities node to read sensor 2 occupied / clear state.

feed into a function node to compare the two values and set clear or detected.

Duplicate all this for sensor2

I think that would work, but wondering if there is a more elegant solution?

Steve

1 Like

Elegant? Nope, it’s really complicated now unfortunately… :joy: Works for me? Yep

The part of my solution relevant to this looks like this:


Above, the ‘multisensor’ is an Aeotec 7 and the ‘light’ is a GE Motion Dimmer
The RoomIO filters are unique to my solution - but at the end of the day the important part here is i’m standardizing the output of the nodes and doing some stuff to prevent loops later.
Next I’m using the output of the BooleanLogicUltimate Node with 2 inputs to OR the sensors - at that point it looks like a standard device state output if either of the motions are on it will show on.

Now you have to do some stuff when you handle it - you may now sometimes VERY occasionally get very long ons or flappy signals as the motions temporarily dont agree… But it eventually became odd enough in the places I was using it - that I had to handle THAT… (see the subflow in the top right?)

Which is handling the delays and setting a flow variable back in its parent to use in case those things matter to the parent flow…

Finally, to also prevent flapping sensors - if your sensors support configurable ‘blind windows’ ( time to recover between motion events) do your best to align them in ways that prevents the problem above. (In my case, both sensors support a 15 second window, so I set the timeout in the subflow (that blue node) to double that - or 30 seconds.)

I have not tried this, and probably not thought this through completely, but could you use two wait until nodes in series (one for each sensor)? Example:

wait until sensor 1 is clear then wait until sensor 2 is clear

Edit: I see the error of my “solution.” This does not work if your room has sensors far enough apart that you are triggering them separately - one goes clear while the other continues to detect.

This is the way I handle it. If either sensor changes to ‘on’, the occupancy sensor goes on. Whenever one sensor goes to ‘off’, I check the current state of both sensors. If they are both off, The occupancy sensor goes off.
Screenshot 2023-09-05 135756

1 Like

3 Likes

This is pretty close to what I achieved yesterday:

Except that your’s has been optimised.

Steve

I thought there must have been a simpler way. I did look at the trigger: state node, but missed the Entity List setting allowing for multiple sensors.

The ‘blocked’ output connector gives me the output I need:
image

thanks’!

HI
Can you share the code? It looks very interesting in the way you create in Nod Red the diagram

Sorry no. It’s composed of 23 unique interconnected flows and not anywhere in public ready status. It works for me but it’s definitely boutique and would only confuse people. I can share portions if you have specific questions.

Im in process of refactoring it. Give me about 6months. There will be a series of videos coming in the future.

The short version is each ‘room’ has a state engine for the room state. It controls the ‘program’ each room runs by accepting various inputs which in turn updates room state. That in turn turns on and off scenes and automations based on a matrix of time/status/mode.

1 Like

How about using flow variables to store the state, combining the states whenever there is a change, filtering so it only does something the first time, testing if both are off and then switching your light?

image

[{“id”:“95e16713a2b71b2e”,“type”:“server-state-changed”,“z”:“b1509d67db32a5cf”,“name”:“occ1”,“server”:“dd8709036f041c5f”,“version”:5,“outputs”:2,“exposeAsEntityConfig”:“”,“entityId”:“binary_sensor.hallmovement_occupancy”,“entityIdType”:“exact”,“outputInitially”:true,“stateType”:“str”,“ifState”:“on”,“ifStateType”:“str”,“ifStateOperator”:“is”,“outputOnlyOnStateChange”:true,“for”:“0”,“forType”:“num”,“forUnits”:“minutes”,“ignorePrevStateNull”:false,“ignorePrevStateUnknown”:false,“ignorePrevStateUnavailable”:false,“ignoreCurrentStateUnknown”:false,“ignoreCurrentStateUnavailable”:false,“outputProperties”:[{“property”:“payload”,“propertyType”:“msg”,“value”:“”,“valueType”:“entityState”},{“property”:“data”,“propertyType”:“msg”,“value”:“”,“valueType”:“eventData”},{“property”:“topic”,“propertyType”:“msg”,“value”:“”,“valueType”:“triggerId”}],“x”:190,“y”:180,“wires”:[[“bd0efc1e79433c95”],[“bd0efc1e79433c95”]]},{“id”:“5e980c65e900acb7”,“type”:“server-state-changed”,“z”:“b1509d67db32a5cf”,“name”:“occ2”,“server”:“dd8709036f041c5f”,“version”:5,“outputs”:2,“exposeAsEntityConfig”:“”,“entityId”:“binary_sensor.hallmovement_occupancy”,“entityIdType”:“exact”,“outputInitially”:true,“stateType”:“str”,“ifState”:“on”,“ifStateType”:“str”,“ifStateOperator”:“is”,“outputOnlyOnStateChange”:true,“for”:“0”,“forType”:“num”,“forUnits”:“minutes”,“ignorePrevStateNull”:false,“ignorePrevStateUnknown”:false,“ignorePrevStateUnavailable”:false,“ignoreCurrentStateUnknown”:false,“ignoreCurrentStateUnavailable”:false,“outputProperties”:[{“property”:“payload”,“propertyType”:“msg”,“value”:“”,“valueType”:“entityState”},{“property”:“data”,“propertyType”:“msg”,“value”:“”,“valueType”:“eventData”},{“property”:“topic”,“propertyType”:“msg”,“value”:“”,“valueType”:“triggerId”}],“x”:190,“y”:220,“wires”:[[“39c43a200f8c6730”],[“39c43a200f8c6730”]]},{“id”:“bd0efc1e79433c95”,“type”:“change”,“z”:“b1509d67db32a5cf”,“name”:“store occ1”,“rules”:[{“t”:“set”,“p”:“occ1”,“pt”:“flow”,“to”:“payload”,“tot”:“msg”}],“action”:“”,“property”:“”,“from”:“”,“to”:“”,“reg”:false,“x”:340,“y”:180,“wires”:[[“fc84f038554d38ac”]]},{“id”:“39c43a200f8c6730”,“type”:“change”,“z”:“b1509d67db32a5cf”,“name”:“store occ2”,“rules”:[{“t”:“set”,“p”:“occ2”,“pt”:“flow”,“to”:“payload”,“tot”:“msg”}],“action”:“”,“property”:“”,“from”:“”,“to”:“”,“reg”:false,“x”:340,“y”:220,“wires”:[[“fc84f038554d38ac”]]},{“id”:“fc84f038554d38ac”,“type”:“string”,“z”:“b1509d67db32a5cf”,“name”:“concat”,“methods”:[{“name”:“append”,“params”:[{“type”:“flow”,“value”:“occ1”}]},{“name”:“append”,“params”:[{“type”:“flow”,“value”:“occ2”}]}],“prop”:“”,“propout”:“payload”,“object”:“str”,“objectout”:“msg”,“x”:490,“y”:200,“wires”:[[“4e3c1e6aaa32c592”]]},{“id”:“4e3c1e6aaa32c592”,“type”:“rbe”,“z”:“b1509d67db32a5cf”,“name”:“”,“func”:“rbe”,“gap”:“”,“start”:“”,“inout”:“out”,“septopics”:true,“property”:“payload”,“topi”:“topic”,“x”:610,“y”:200,“wires”:[[“1d6388d69a1a7ebf”]]},{“id”:“1d6388d69a1a7ebf”,“type”:“switch”,“z”:“b1509d67db32a5cf”,“name”:“both off?”,“property”:“payload”,“propertyType”:“msg”,“rules”:[{“t”:“eq”,“v”:“falsefalse”,“vt”:“str”}],“checkall”:“true”,“repair”:false,“outputs”:1,“x”:740,“y”:200,“wires”:[[“79aa5e62b18882ac”]]},{“id”:“79aa5e62b18882ac”,“type”:“api-call-service”,“z”:“b1509d67db32a5cf”,“name”:“lights”,“server”:“dd8709036f041c5f”,“version”:5,“debugenabled”:false,“domain”:“homeassistant”,“service”:“{{payload}}”,“areaId”:[“hallway”],“deviceId”:,“entityId”:,“data”:“”,“dataType”:“jsonata”,“mergeContext”:“”,“mustacheAltTags”:false,“outputProperties”:,“queue”:“none”,“x”:870,“y”:200,“wires”:[]},{“id”:“dd8709036f041c5f”,“type”:“server”,“name”:“Home Assistant”,“version”:5,“addon”:false,“rejectUnauthorizedCerts”:true,“ha_boolean”:“y|yes|true|on|home|open”,“connectionDelay”:true,“cacheJson”:true,“heartbeat”:false,“heartbeatInterval”:“30”,“areaSelector”:“friendlyName”,“deviceSelector”:“friendlyName”,“entitySelector”:“friendlyName”,“statusSeparator”:": ",“statusYear”:“hidden”,“statusMonth”:“short”,“statusDay”:“numeric”,“statusHourCycle”:“default”,“statusTimeFormat”:“h:m”,“enableGlobalContextStore”:false}]

HI,

Have you made progress on the subject? Can you share the code?

No real world has taken precedent…