WTH can't an automation run every X days?

There doesn’t seem to be an easy way to have an automation run let’s say every 2 days at a certain time of day. The only solutions I found involved templates and/or timers. Especially for irrigation it would be useful easily change the intervals depending on the weather.

Regularly recurring events, like the “every 2 days” example you posed, can be easily created in a calendar, which can then be used as an automation condition.

If the interval is going to be dynamic based on outside factors why set a static reoccurance in the first place? Maybe what is needed is a way to set an Input datetime using relative terms… maybe something like what is used when setting for options on State and Device triggers (it’d be a bonus if it accepted negative values as well)…

- service: input_datetime.set_datetime
  target:
    entity_id: input_datetime.next_irrigation
  data:
    relative: 
      days: 2

Just so I get this right, the calendar would be an external calendar like “Google Calendar” and with the events I can trigger automations, right? With this integration for example: Google Calendar - Home Assistant

This would be really easy to do with a cron expression, which I just made a WTH about

Agreed! My workaround for this is successful, but also painful:

  • Set up counter helper (counter.automation_days_tracker)
  • Set up automation to increment counter daily (at midnight)
  • Set up automation to trigger when counter exceeds X days (and include counter reset in actions)

So with cron to make it run every second day I would set it to /2 for the day of month? That would mean that on months with uneven numbers it would run two days in a row, wouldn’t it? Or if it runs only on even days it might have a 3 day interval once a month.

Until the Time Trigger is enhanced (if ever), you can do this:

alias: Example 1
trigger:
  - platform: time
    at: '08:00:00'
condition: "{{ (now() - as_datetime('19700101T00Z')).days % 2 == 0 }}"
action:
  ... your actions ...

The Template Condition determines if the number of days, since the Unix epoch, is evenly divisible by 2. This technique ensures the condition is fulfilled exclusively every other day (i.e. every 2 days). Change the 2 to 3 if you want every third day.

2 Likes

It could be, but there are more local options. Community member @allenporter is working on a local calendar integration. It’s function is pretty basic right now, but it’s easy to set up and it works. Another option is to host your own CalDav server through an add-on like Radicale. Radicale can be frustrating to setup, but once done, it can be accessed and used just like any other CalDav-based calendar…

Yeah Google Calendar and CalDav can already handle recurring events, and you can use calendar events to power any automation you want – see for examples Calendar - Home Assistant

Local calendar is in progress, but I think the main point is that home assistant already has everything necessary to run automations on a recurring schedule via calendar integrations

1 Like

I’m seeing suggestions to use a calendar, but that doesn’t really work for me. My current use case is an injection I have to take every 3 days, but there is leeway. My only solution so far is a daily alarm that ticks a counter up at noon. If it’s 3 or greater then it turns on an input boolean. When I turn off the input boolean it resets the counter to 0.

This way if I miss day 3 and do it on day 4, the schedule resets immediately to the 3 day interval. Resetting a recurring event in a gcal would be a lot more work.

You could have an automation that looks at a google calendar for the event then triggers a notification for you.

Then, when you have your injection have a button or NFC or dashboard button (or persistent notification?) that you press that calls a script to insert the next reminder for 3 days time.
If you can’t have it today then you could have a second button/script that inserts the reminder for day+1 so you get that tomorrow.

e.g. 3 Day reminder script

alias: Injection Reminder in 3 days
sequence:
  - service: google.create_event
    data:
      summary: Injection
      description: "#injection"
      start_date_time: >-
        {{ (as_timestamp(now()) + (3*24*3600))| timestamp_custom('%Y-%m-%d', True) }} 12:00:00
      end_date_time: >-
        {{ (as_timestamp(now()) + (3*24*3600))| timestamp_custom('%Y-%m-%d', True) }} 12:05:00
    target:
      entity_id: calendar.nbm_scheduler
  - delay:
      hours: 0
      minutes: 0
      seconds: 5
      milliseconds: 0
mode: single
icon: mdi:needle

Thanks for writing that up, but that seems way more complex than what I’ve already made with helpers and an automation.

Try this excellent custom component:

I would do this all with a trigger-based template binary sensor. No need to have a way to trigger every 3 days, you just need to trigger 3 days after your last dose. You can have the sensor turn on at a certain time during the day if it’s been at least 3 days, and you can fire an event to turn it off:

template:
  - trigger:
      - platform: time
        at: "12:00:00"
      - platform: event
        event_type: dose_taken
    binary_sensor:
      - name: Dose Required
        unique_id: 59cdfe65-3495-476a-8672-eb8dca769dfd
        state: >
          {{ 'on' if trigger.platform == 'time' and  today_at().date() - (this.attributes.last_dose_datetime | default(0) | as_datetime).date() >= timedelta(days=3) else 'off' }}
        attributes:
          last_dose_datetime: "{{ now() if trigger.platform=='event' else this.attributes.last_dose_datetime | default(0) | as_datetime }}"

You’d then set up a button on your dashboard that, when pressed, fires an event named dose_taken and that will turn the sensor back off and it will also set the last_dose_datetime attribute. If you want a reminder when it’s time to take a dose, then you create an automation that triggers when this sensor goes from off to on