Any two of multiple triggers, within a time?

Short version:
Looking to pass a payload when any two of (say) five triggers occur within a two minute window.

Long version:
I have BlueIris cctv connected to HA, and the AI verified person recognition set to trigger alerts. Its not foolproof though - spiders for example being an occasional issue at night when it’s on IR. I also have externa PIR motion detectors connected to HA. What i’m looking to build is a ‘someone is in my garden at night’ critical alert that will break through my phones do not disturb, but because it will wake me up i’d like some certainty in the form of needing two trigger from the pool of sensors within say 2 minutes. So someone triggers say the CCTV alert AND the outdoor motion sensor, or a 2nd CCTV motion sensor, for example.

Can’t quite figure out how to do it so any pointers would be appreciated.

I don’t use Node Red, but in HA automations I’d set up an input_number at 0, have:

  • an automation with all of your triggers that increments it by one;
  • another that decrements it by one (but not below 0) when its state hasn’t changed for two minutes;
  • and a third that sets off your action whenever the input_number hits 2.

I’m the other way round, I haven’t used built in automations much. I’ll keep this as a backstop though if I can’t solve it in Node Red, thanks for the input!

When any of the sensors change to the “on” state check the history of all sensors and count how many were in the “on” state in the time window.

[{"id":"6215009b42c12415","type":"server-state-changed","z":"c89d915bdff0f798","name":"sensors","server":"","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":["input_boolean.test","input_boolean.test2","input_boolean.test3"],"entityidfiltertype":"list","outputinitially":false,"state_type":"str","haltifstate":"on","halt_if_type":"str","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,"outputProperties":[{"property":"payload","propertyType":"msg","value":"entityidfilter","valueType":"config"}],"x":126,"y":2192,"wires":[["f3ad87b134efa38f"],[]]},{"id":"9278e9b0b5cee660","type":"api-get-history","z":"c89d915bdff0f798","name":"","server":"","version":0,"startdate":"","enddate":"","entityid":"","entityidtype":"is","useRelativeTime":true,"relativeTime":"10 seconds","flatten":false,"output_type":"array","output_location_type":"msg","output_location":"payload","x":442,"y":2192,"wires":[["dce924ae9b63e162"]]},{"id":"dce924ae9b63e162","type":"function","z":"c89d915bdff0f798","name":"check sensor states","func":"// loop through the different sensors\nconst activeSensors = msg.payload.map((sensor) => {\n    // check if atleast one history has the state \"on\"\n    return sensor.some((entity) => entity.state === \"on\");\n// count how many sensors had an \"on\" state\n}).filter((sensor) => sensor === true).length > 1;\n\n// if activeSensors is true than two sensor were active in the time window\nif(activeSensors) {\n    return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":644,"y":2192,"wires":[["8c93eb2647a7306b"]]},{"id":"8c93eb2647a7306b","type":"debug","z":"c89d915bdff0f798","name":"debug 101","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":838,"y":2192,"wires":[]},{"id":"f3ad87b134efa38f","type":"change","z":"c89d915bdff0f798","name":"set entity ids","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"entity_id\": payload ~> $join(\",\")}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":278,"y":2192,"wires":[["9278e9b0b5cee660"]]}]

I’ve had a good look at this now and i think i see how it works. I’ll have to try and implement it and see how it works out for me in practice, and might have to come back and ask a question! At the moment though i think i understand i think it looks like just what i need. Thanks for the help!

OK - that doesn’t work how it looks like (to me) it should work? I have brought it in an am using 2 toggles from a dashboard button for testing. Whats happening is if i hit toggle 1 on then off it is triggering ok, but then i need to hit toggle 2 on and off then turn 1 back on and off. Is that happening at your end? Wondering if i have accidentally altered something?

[{"id":"6215009b42c12415","type":"server-state-changed","z":"c89d915bdff0f798","name":"sensors","server":"","version":4,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":["input_boolean.test","input_boolean.test2","input_boolean.test3"],"entityidfiltertype":"list","outputinitially":false,"state_type":"str","haltifstate":"on","halt_if_type":"str","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,"outputProperties":[{"property":"payload","propertyType":"msg","value":"entityidfilter","valueType":"config"}],"x":126,"y":2192,"wires":[["f3ad87b134efa38f"],[]]},{"id":"9278e9b0b5cee660","type":"api-get-history","z":"c89d915bdff0f798","name":"","server":"","version":0,"startdate":"","enddate":"","entityid":"","entityidtype":"is","useRelativeTime":true,"relativeTime":"10 seconds","flatten":false,"output_type":"array","output_location_type":"msg","output_location":"payload","x":442,"y":2192,"wires":[["dce924ae9b63e162"]]},{"id":"dce924ae9b63e162","type":"function","z":"c89d915bdff0f798","name":"check sensor states","func":"// loop through the different sensors\nconst activeSensors = msg.payload.map((sensor) => {\n    // check if atleast one history has the state \"on\"\n    return sensor.some((entity) => entity.state === \"on\");\n// count how many sensors had an \"on\" state\n}).filter((sensor) => sensor === true).length > 1;\n\n// if activeSensors is true than two sensor were active in the time window\nif(activeSensors) {\n    return msg;\n}\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":644,"y":2192,"wires":[["8c93eb2647a7306b"]]},{"id":"8c93eb2647a7306b","type":"debug","z":"c89d915bdff0f798","name":"debug 101","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":838,"y":2192,"wires":[]},{"id":"f3ad87b134efa38f","type":"change","z":"c89d915bdff0f798","name":"set entity ids","rules":[{"t":"set","p":"payload","pt":"msg","to":"{\"entity_id\": payload ~> $join(\",\")}","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":278,"y":2192,"wires":[["9278e9b0b5cee660"]]}]

Looks like the history isn’t being written to the db instantly. Add a slight delay after entity change would probably help with this.

I think that has sorted it out, thanks!