Time trigger with repeat

Hello,

Is it possible to to do a repeating pattern in a time trigger that starts at a certain time and ends after x runs? My use case is having an automation run at 6:30am and re-trigger every 30 minutes:

This is my inelegant solution:

  trigger:
    - platform: time
      at:
        - '06:30:00'
        - '07:00:00'
        - '07:30:00'
        - '08:00:00'
        - '08:30:00'
        - '09:00:00'
        - '09:30:00'

Is there a more elegant solution that just listing out the times?

I do this personally:

trigger:
  platform: template
  value_template: >-
    {{ is_state('switch.some_switch', 'on')
        and now() >= today_at('06:30')
        and now().minute % 30 == 0 and now().second == 0 }}
action:
  service: switch.turn_on
  data:
    entity_id: switch.some_switch

Replace the some_switch bit with whatever your condition is. Runs the automation at your specified time and then every half an hour for the rest of the day until the switch changes.

EDIT: OH “after x runs”, duh. I thought x meant an entity, like a retry loop to ensure an entity turns on :man_facepalming:

I had considered that solution. However, I decided against it because it introduces code obfuscation - you have to now look at two spots to understand what is happening.

That’s an interesting approach. Would this work?

trigger:
  platform: template
  value_template: >-
    {{ ( as_timestamp( now() ) | timestamp_custom("%H%M", True) | int >= 630 and as_timestamp( now() ) | timestamp_custom("%H%M", True) | int <= 930 )
        and now().minute % 30 == 0 and now().second == 0 }}

This would use the time as the trigger vs a light switch.

Fair point :slight_smile:

I’m just trying to see if there is a solution that can be in one spot vs multiple.

Hm so after X runs. Well you could do this I suppose:

trigger:
  platform: template
  value_template: >-
    {{ now() >= today_at('06:30') and now() <= today_at('09:30')
      and now().minute % 30 == 0 and now().second == 0 }}

Although it depends if you actually mean x runs or not. Like this should run 7 times between 6:30 and 9:30. But if your HA is restarting at the half hour or hour mark then it will miss a run. Does that matter to you or is this good enough?

2 Likes
trigger:
  platform: template
  value_template: >-
    {% set t = now() %}
    {{ today_at("6:30") <= t <= today_at("9:30") and not t.minute % 30 and not t.second }}
1 Like

I’m also not a fan of time_pattern + condition personally but for a different reason. I don’t like that when the trigger occurs but the condition fails it still generates a trace. I suppose with a half hour time pattern its probably fine. But if you have a 5 minute time pattern like that then if you don’t notice something is wrong for an hour then your trace is already gone and its difficult to debug (or you have to keep a whole lot of traces). This is the main reason I prefer a template trigger over time pattern for stuff like this.

But both work fine. And if the automation is very simple traceability doesn’t really matter.

but it won’t trigger a trace, trade-off

@petro & @CentralCommand

Thank you, that’s an elegant solution.

I’m running an ancient version of HA (2021.6.6) so I don’t have access to the today_at function but I modified the code to work with legacy.

{% set t = as_timestamp( now() ) |timestamp_custom("%H%M", True) | int %}
{{ 630 <= t <= 930 and not now().minute % 30 and not now().second }}

Once I get my system upgraded I’ll use the today_at function as it clearly shows intent.

{% set t = now().strftime('%H%M') | int %}

1 Like

@petro - will HA evaluate the trigger every minute and only once every minute?

If so, would having a check for the second being 0 possibly prevent the trigger from firing properly if HA doesn’t get to checking the trigger until after 1 second has passed?

now() inside templates will resolve once a minute a few microseconds past the minute (like ~15 microseconds, i.e. 0.015 seconds past the minute).

Honestly its not necessary to do second == 0 in this case, that’s just my pattern so I put it in.

It is necessary in my retry pattern as shown here which is why I include it (I’m usually doing that). Because that one will also evaluate the template when the state of some_switch changes. Which means it can occur more then once a minute and not necessarily at the top of the minute.

But for triggering every half an hour on time only it shouldn’t matter. The only time it would even come up is possibly on restart of HA or reload of automations (templates triggers are also evaluated when they are first added). But template triggers only trigger when the template was evaluating to false and now is evaluating to true. If HA starts at like 07:30:30 then that trigger will start true so it shouldn’t trigger.