How to reliably design making an announcement every 5 mins until a binary sensor is OFF

I have an automation that reminds me to move if I haven’t left the desk area for X minutes.

I want to add an optional feature where it will keep nagging me every 5 minutes, up to 3 times, as long as the presence binary sensor remains TRUE (the sensor has debouncing built in so if it temporarily thinks I’m away due to unreliability, or I just quickly go to grab something, it won’t consider me to have left).

My first (wrong) thought was to do the following.
Pseudo code.

- trigger: binary sensor has been ON for X minutes 
- condition: [main automation switch is ON, whatever]
- sequence 
   - repeat 3 times
     - condition binary sensor ON
     - issue warning to move via speakers
     - delay 5 mins

However, this is kind of naive in case the sensor moves to OFF and then back ON while the 5-min delay is happening (if my timeout period is < 5mins).

This is not surprising since HA is event based so delays always make me suspicious about bad design.

So the only proper way that I can think of is inside the sequence for me to kick off another automation (or script) whose only responsibility is to make an announcement up to N times every M minute (configurable).

Then inside my main automation, I have a second trigger for when the sensor goes to OFF for X minutes. Then if that trigger is what… triggered, I turn off the announcer script.

I don’t know if this is a standard pattern creating coupling across automations/scripts like that but it feels like the only way that I can reliably implement the requirements.

Would love some feedback from the experts!

Instead of a repeat, your automation can make the announcement, then start a 5 minute timer.

Add a second trigger to the automation on the timer.finished event with the entity id of your timer. This will trigger the announcement again and start the timer again.

Finally, in another automation or in the same (using trigger ids and a Choose), trigger on the binary sensor going to off with the Action to cancel the timer.

Using your pseudo code format, this might look like:

- trigger: 
  - binary sensor has been ON for X minutes (trigger id: announce)
  - timer finished (trigger id: announce)
  - binary sensor is off (trigger id: cancel)
- condition: []
- sequence 
   - choose
    - trigger id: announce
     - issue warning to move via speakers
     - start timer
    - trigger id: cancel
     - cancel timer

Oh I don’t know anything about timers, that’s effectively the same thing as it’s another ‘thread’ (what I’m loosely modeling by kicking off another automation) that can be interrupted by the event of the trigger of binary sensor going OFF for X minutes. Let me read up on timers.

Ya I like it. Basically same as my script idea but you can co-locate the code inside the original automation (at the expense of a bit more complexity in the same spot but in this case I prefer it all in one place). Instead of a dependency on another script you have a dependency on a timer. Thanks for introducing me to timers :).

This will fire every five minutes:

  trigger:
    - platform: time_pattern
      minutes: "/5"

Thanks but this won’t help.

I realized the one downside to your suggestion compared to mine is that you cannot easily keep track of which iteration of the ‘nagging timer’ you are on. I was hoping to make that configurable as part of the automation (backed by a blueprint since I need to do it for a number of areas). In my idea where I delegate the reminder to a script (which runs independently and I can kill when the binary sensor becomes OFF), the script knows how many times it needs to repeat as that’s passed as an input and since it uses delays internally it can keep that state and update it until it dies (or is killed). In the timer solution, you cannot track that state easily since each time you are in a new instance of the triggered automation.
Of course I could use an input boolean but that’s yet another sensor that could also technically be modified externally by anything. So with the timer solution I need to create two entities (a timer and an input boolean) and in the script solution only entity (the script). Not sure if I’ll change my implementation, the script definitely feels clunkier somehow but I kind of don’t like depending on an input boolean that isn’t “private” to the automation.