How to delay an automation until a device is off for at least a certain amount of time?

I am working on perfecting my timer automation described here:

In short, I am running a circulating timer that will turn on a switch for 2 minutes, then turn off for 20 minutes, and repeat.

I have several time periods, each set up as a separate automation, to implement this automation. Some of them are back to back.

The issue I have is that sometimes the switch will turn on+off near the end of one time period. And when the next time period starts, the switch will turn on much sooner than it needs to be.

I tried putting in a ā€œwait for triggerā€ right before starting the circulation. The screenshot below shows how it is currently set. We wait for the hot water circulator to be off for 18 minutes. I donā€™t think this is working as I imagined.

What I really want is for it to proceed if it has been off for at least 18 minutes. Or, if it is less than 18 minutes, wait until it has been 18 minutes before proceeding.

If the switch has been off for >18 minutes when the automation runs, I think it just endlessly waits? I am probably using this trigger wrong.

please post code using this instead of screenshots:

lots of ways to solve your problem. but some of them will have different behaviors.

one way to do this to have an 18 minute timer thatā€™s triggered when the pump turns off (or 20 minute when it turns on depending on what you want in the boundary conditions).

then in your code, if the timer is running, wait for the timer to finish otherwise donā€™t waitā€¦ then turn on the pump.

you canā€™t do what youā€™re doing because your wait will, starting from when that code is hit, look for the hot water circulator to turn off then wait 18 minutes after it sees it turn off. it wonā€™t go back in time.

Thank you for your response. Iā€™m new to modern coding in general (PASCAL anyone?) but I will post code going forward.

The timer idea sounds good and simple. Hereā€™s what Iā€™ve made so far.

The code for one of the automations, for mid-day.

alias: Midday water circulation
description: Turn on circulation when home during midday
trigger:
  - platform: time
    at: "10:15:00"
  - platform: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
    event: enter
  - platform: homeassistant
    event: start
condition:
  - condition: time
    after: "10:15:00"
    before: "17:00:00"
    weekday:
      - sat
      - fri
      - thu
      - wed
      - tue
      - mon
      - sun
  - condition: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
action:
  - service: notify.mobile_app_sm_g970u1
    metadata: {}
    data:
      message: We ready to turn on circulation now?
  - repeat:
      sequence:
        - service: scene.turn_on
          metadata: {}
          target:
            entity_id: scene.hot_water_switch_1_on
        - delay:
            hours: 0
            minutes: 22
            seconds: 0
            milliseconds: 0
      while:
        - condition: time
          after: "10:15:00"
          before: "17:00:00"
          weekday:
            - sat
            - fri
            - thu
            - wed
            - tue
            - mon
            - sun
        - condition: zone
          entity_id: device_tracker.sm_g970u1
          zone: zone.home
mode: single

I made a separate timer automation. I believe Iā€™ll be querying for the IDLE state which indicates the timer is done?

alias: Time since hot water off
description: Use to limit hot water turning back on
trigger:
  - platform: device
    type: turned_off
    device_id: 32dd54355a2471d7f10f05c07c63125a
    entity_id: 671a0a417a33671f6d707e4a5a85f05b
    domain: switch
condition: []
action:
  - service: timer.start
    metadata: {}
    data:
      duration: "00:18:00"
    target:
      entity_id: timer.hot_water_off_timer
mode: single

Putting the two together is where I lose it.

The loop should wait to start until the timer is confirmed IDLE. I thought ā€œWait for triggerā€ would work, but again, that only looks for a change in state, not if the timer is IDLE already.

iā€™m not exactly positive what you want to do where, but iā€™m taking some guesses.

look through this code before you try it. see if the logic is what you want:

alias: Midday water circulation
description: Turn on circulation when home during midday
trigger:
  - platform: time
    at: "10:15:00"
  - platform: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
    event: enter
  - platform: homeassistant
    event: start
condition:
  - condition: time
    after: "10:15:00"
    before: "17:00:00"
  - condition: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
action:
  - service: notify.mobile_app_sm_g970u1
    data:
      message: We ready to turn on circulation now?
  - repeat:
      sequence:
        - if:
            - condition: state
              entity_id: timer.hot_water_off_timer
              state: active
          then:
            - wait_for_trigger:
                - platform: state
                  entity_id:
                    - timer.hot_water_off_timer
                  to: idle
        - service: scene.turn_on
          target:
            entity_id: scene.hot_water_switch_1_on
          data: {}
        - delay:
            hours: 0
            minutes: 22
            seconds: 0
            milliseconds: 0
      while:
        - condition: time
          after: "10:15:00"
          before: "17:00:00"
        - condition: zone
          entity_id: device_tracker.sm_g970u1
          zone: zone.home
mode: single

i did nuke all your days of the week. if you want every day, you can omit that.

and hereā€™s the timer trigger code:

alias: Time since hot water off
description: Use to limit hot water turning back on
trigger:
  - platform: state
    entity_id:
      - switch.hot_water
    to: "off"
condition: []
action:
  - service: timer.start
    data:
      duration: "00:18:00"
    target:
      entity_id: timer.hot_water_off_timer
mode: single

replace the switch.hot_water with the correct entity_id. donā€™t use device_idā€™s.
also make sure you have created the timer.hot_water_off_timer helper, and you should make it restore on restart.

holler if any of this code doesnā€™t make sense.

by the way, if the time you want the water pump on to be 2 minutes, personally i would make the timer be 20 minutes and make it start when the water turns onā€¦ because if you donā€™t, when this code runs, if the water was just turned yon 1 minute ago, it will try to turn the water on right away while itā€™s still onā€¦ but i donā€™t know your use case so i donā€™t know if thatā€™s what you want or not.

So many thanks!

Your code mods were enlightening. Iā€™ve made changes to the automation and think your additions will accomplish what I need. Apparently I have a weakness thinking up how to place and phrase IF/THEN commands.

Good suggestion setting the timer to start when hot water turns ON, as opposed to OFF. I was playing the probability game that most likely the water wouldnā€™t be just turned on when the separate automations handoff from one time period to the next.

Just one question to aid me in the future.

I was using the visual editor when constructing the timer and just saw it pulled in numerical device_id and entity_id instead of actual text. Any reason why it would do that? Wouldnā€™t I just need one anyway?

Itā€™s because it lists all the possible choices in alpha orderā€¦ You chose device. I chose state.

I think the UI should be changed to discourage device_id.

hereā€™s more info if you wantā€¦

1 Like

wellā€¦ i hope itā€™s working for you now. and if so, in complete violation of the principle of ā€œdonā€™t fix whatā€™s not brokenā€ā€¦ and perhaps just more for learning purposes since you seem interested not just in ā€œgetting it doneā€ā€¦ consider this:

alias: Midday water circulation
description: Turn on circulation when home during midday
trigger:
  - platform: time
    at: "10:15:00"
    id: notify
  - platform: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
    event: enter
    id: notify
  - platform: homeassistant
    event: start
    id: notify
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.hot_water_off_timer
    id: timer
condition:
  - condition: time
    after: "10:15:00"
    before: "17:00:00"
  - condition: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
action:
  - if:
      - condition: trigger
        id:
          - notify
    then:
      - service: notify.mobile_app_sm_g970u1
        data:
          message: We ready to turn on circulation now?
          sequence: null
  - if:
      - condition: not
        conditions:
          - condition: state
            entity_id: timer.hot_water_off_timer
            state: active
    then:
      - service: scene.turn_on
        target:
          entity_id: scene.hot_water_switch_1_on
        data: {}
mode: single

since you have the timer now that is turned on whenever the water starts, i think you can now get rid of your while loop and the wait for ā€¦ and instead add a trigger for whenever the timer finishes.

the reason is that if the timer is going already then you donā€™t need a waitā€¦ because when it finishes, it will trigger this automation. you also donā€™t need a while loop because when you turn on the hot water, it will set a timer that will eventually hit this automationā€¦ turn on the water which will set your timerā€¦ which will eventually fire and ā€¦ and it will keep doing this until it violates your conditionā€¦

i didnā€™t really understand the conditions when you want to be notified, so i put some code in to notify on the 3 cases you were being notified before and not on the case of every 20 minutes (the timer event).

i am not setup to test this code, so all caution as appropriateā€¦ no refundsā€¦ but maybe the concept is helpful to you to simplify your codeā€¦

Appreciate the fine tuning!

I tried streamlining it as you suggested, and logicallly it should work. But I ran into this problem though. It will run once, but then maybe because the timer state check happens so frequently afterwards, the automation times out:

Error: While condition [{ā€˜conditionā€™: ā€˜timeā€™, ā€˜afterā€™: datetime.time(10, 15), ā€˜beforeā€™: datetime.time(17, 0), ā€˜weekdayā€™: [ā€˜satā€™, ā€˜friā€™, ā€˜thuā€™, ā€˜wedā€™, ā€˜tueā€™, ā€˜monā€™, ā€˜sunā€™]}, {ā€˜conditionā€™: ā€˜zoneā€™, ā€˜entity_idā€™: [ā€˜device_tracker.sm_g970u1ā€™], ā€˜zoneā€™: [ā€˜zone.homeā€™]}] terminated because it looped 10000 times

A separate question regarding timer + helpersā€“the 2 are linked and the helper is created when I create the timer? I could have sworn when I first created the timer automation, it automatically created the helper and input the duration?

However, if I edit the timer duration in my automation, the duration in the helper does not change. Is that normal behavior, that editing the timer automation afterwards will not sync the duration in the helper? What issues will this cause if the two are different durations?

strange that it would have looped 10000ā€¦ since thereā€™s a delay 22mins there and youā€™re breaking the condition after 5pmā€¦ seems like it should stop each day and never loop more than 100 times a day.

can you post your very final automation and let me see? to help avoid any misunderstanding, post all related codeā€¦ your latest of your main circulation as well as the timer getting triggered. letā€™s just look at the whole thing to make sure itā€™s all set.

all the more reason to do the final solution thoughā€¦ it has no loops whatsoeverā€¦

to answer your other questionā€¦

you asked:

helper is created when I create the timer? 

iā€™m not sure what you mean. the timer helper IS the timer. they are one and the same. the timer automation starts the timer helperā€¦ you should do that whenever the water pump turns on. you donā€™t create helpers in code.

when you start the timer helper, you have the option to specify the duration. if you specify the duration, that duration will be used that time the timer is runā€¦ it will not change the default. if you do not specify a duration, the default duration is used.

in the example i gave, there is only 1 timer. the timer is an entity. so if you call to start the timer twice in short succession , the second call will restart the timerā€¦ essentially nullifying the first call.

hopefully that was all clear. holler if iā€™ve confused things!

Ahh, I see where I went wrong. I misread your last comments entirely on not needing a loop and didnā€™t see that you removed the loop entirely and added the timer.finished event to the initial triggers.

For laughs, hereā€™s the bad frankenstein code I was running:

alias: Bad midday code
description: Turn on circulation when home during midday
trigger:
  - platform: time
    at: "10:15:00"
  - platform: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
    event: enter
  - platform: homeassistant
    event: start
condition:
  - condition: time
    after: "10:15:00"
    before: "17:00:00"
    weekday:
      - sat
      - fri
      - thu
      - wed
      - tue
      - mon
      - sun
  - condition: zone
    entity_id: device_tracker.sm_g970u1
    zone: zone.home
action:
  - service: notify.mobile_app_sm_g970u1
    metadata: {}
    data:
      message: We ready to turn on circulation now?
  - repeat:
      sequence:
        - if:
            - condition: not
              conditions:
                - condition: state
                  entity_id: timer.hot_water_on_timer
                  state: active
          then:
            - service: scene.turn_on
              metadata: {}
              target:
                entity_id: scene.hot_water_switch_1_on
      while:
        - condition: time
          after: "10:15:00"
          before: "17:00:00"
        - condition: zone
          entity_id: device_tracker.sm_g970u1
          zone: zone.home
mode: single

So as long as the timer was active, it kept looping thousands of times waiting for it to turn idle.

Regarding my timer/helper question, I found that if I edit the timer duration here (19 min):

alias: Time since hot water on
description: Use to limit hot water turning back on
trigger:
  - platform: state
    entity_id:
      - switch.hot_water_socket_1
    from: "off"
    to: "on"
condition: []
action:
  - service: timer.start
    metadata: {}
    data:
      duration: "00:19:00"
    target:
      entity_id:
        - timer.hot_water_on_timer
mode: single

The duration here under the helper settings (19 min) did not always match:

ah rightā€¦ if you use the thing i did at the end, you need to both remove the loop, but add the time ending as one of the triggers. doing one without the other doesnā€™t work :slight_smile: