Automation loop on/off

Hi everybody,

I currently need to turn on an infrared heater every x minutes, then turn it off for y minutes, then turn it back on for x minutes, and so forth.

As I haven’t changed my Home Assistant configuration in quite a while, I don’t know what’s currently the best way to do this (as some things that used to be difficult have seemed to improve a lot!).

I thought of creating

  • input_boolean.onofftimer => use this entity’s state to trigger the automation
  • input_datetime.onoff_durationon => how long should the switch be on off
  • input_datetime.onoff_durationoff => how long should the switch be off for

Whether or not the switch is currently off can be determined via switch.onofftimer. This is the tasmota smart outlet I use to control the infrared heater.

I just don’t know how to write the automation in order to

  • IF input_boolean.onofftimer is on, then
  • turn on switch.onofftimer
  • delay for time defined via input_datetime.onoff_durationon
  • turn off switch.onofftimer
  • delay for time defined via input_datetime.onoff_durationoff
  • repeat until input_boolean.onofftimer is switched off

The automation itself is easy, but I don’t know how to loop it until input_boolean.onofftimer is switched off.

I thought of calling the automation itself at the very end (after the “off” delay)… but if I do this, it will constantly run, even when input_boolean.onofftimer is switched off, correct? Because once the loop starts, it will no longer check whether or not the boolean is still switched on.

Can you please help me create this automation? There is moisture in a brick wall in my house and I need to manually do this at the moment. Which is fine, but automating it without having to worry that I leave it on too long (or forgot to turn it back on at all) would be really nice.

Thank you in advance for your ideas :slight_smile:

The simplest way is with two input numbers that hold the on/off durations you want and two automations:

- alias: heater_on
  trigger: 
    platform: state
    entity_id: switch.onofftimer
    state: 'off'
    for:
      minutes: input_number.off_time
  action:
    service: switch.turn_on
    entity_id: switch.onofftimer

- alias: heater_off
  trigger: 
    platform: state
    entity_id: switch.onofftimer
    state: 'on'
    for:
      minutes: input_number.on_time
  action:
    service: switch.turn_off
    entity_id: switch.onofftimer

This will repeat for ever. To disable it from running, turn off automation.heater_on, no need for an input boolean. You can schedule the automation state a number of ways if you have known times you want this to run. Or just do it manually from a Lovelace card.

Put automation.heater_on and the two input numbers in an entities card. You can make it pretty with icons and friendly names directly in the Lovelace card, or the entity configuration (for the input numbers) or by using customize.

1 Like

I created something similar for another community member. You may want to adapt it for your requirements.

It operates a towel warmer during two time periods: 06:00-9:00 and 19:00-00:00. It turns on the towel warmer for 15 minutes and then turns it off for 10 minutes. It repeats this pattern continuously during each of the two time periods.

- alias: Towel_warmer_morning_and_evening
  trigger:
  - platform: time
    at:
    - 06:00:00
    - 09:00:00
    - 19:00:00
    - 00:00:00
  action:
  - choose:
    - conditions: '{{ trigger.now.hour == 6 or trigger.now.hour == 19 }}'
      sequence:
      - repeat:
          while: '{{ 6 <= now().hour < 9 or 19 <= now().hour <= 23 }}'
          sequence:
          - service: switch.turn_on
            entity_id: switch.towel_warmer
          - delay: 00:15:00
          - service: switch.turn_on
            entity_id: switch.towel_warmer
          - delay: 00:10:00
    default:
    - service: switch.turn_off
      entity_id: switch.towel_warmer

Let me know if you need help modifying it.

1 Like

Thank you both for your solutions @tom_l @123 :100:

I will test the first solution, because it is easier. I always have trouble with the jinja2 scripting, but will take the second solution as an opportunity to understand the syntax better :slight_smile:

Go with what works for you.

The automation I posted not only cycles the heater on/off but also schedules when this cycling should occur. Let me know if you need any part of it explained.

1 Like

Could someone please help me with this automation. I can’t figure out where the “service: switch.turn_off” is coming from and also the “state: ‘off’” is confusing me, since there is only From and To available in the state trigger type?
This is what I have from creating via gui:

- id: '1628182722088'
  alias: 'on'
  description: ''
  trigger:
  - platform: state
    entity_id: switch.bugzap
    to: 'off'
    for: 'minutes: input_number.on_time'
  condition: []
  action:
  - type: turn_on
    device_id: fa3c9776825c102e498a58625a406253
    entity_id: switch.bugzap
    domain: switch
  mode: single

It’s a typo. state should be to.

For some reason I couldn’t get tom_l’s code to work with input_number.on_time and input_number.off_time . I had to use jinja variable format. I’m posting my code below if anyone runs into the same issue.

- id: '0000000000002'
  alias: heater_on
  trigger:
  - platform: state
    entity_id: switch.onofftimer
    to: 'off'
    for: 
      minutes:  "{{ states('input_number.off_time')|int }}"    
  condition: []
  action:
  - service: switch.turn_on
    target:
      entity_id: switch.onofftimer
  mode: single
- id: '0000000000001'
  alias: heater_off
  trigger:
  - platform: state
    entity_id: switch.onofftimer
    to: 'on'
    for: 
      minutes:  "{{ states('input_number.on_time')|int }}"
  condition: []
  action:
  - service: switch.turn_off
    target:
      entity_id: switch.onofftimer
  mode: single

The only issue I have now is that this loop doesn’t start until I manually toggle the switch. Once the switch is toggled it runs fine.

Actually, the simplest solution is to sit there with a stopwatch. The next simplest … that actually worked for me … was to build a couple of timers (ucontroller, opto-isolator and triac) and connect this to a standard Zigbee power switch.

This lets me keep a light bulb on under my hummingbird feeders without the feeder getting too hot. (Without the heat source, the sugar water will freeze and the little guys will starve.)

I surely didn’t want to go this route. After all, I already have a running microcontroller here … a Raspberry PI! SURELY, I thought, I can use the timers inherent in HA.

Only I was never able to.

I copied and pasted all the various “solutions” in this thread, substituting my device names for the ones in the suggestions. Then I went so far as to systematically removing a device and adding it back using the names in the suggestions. I also removed the “input_number.on_time” variable and replaced it with a simple value.

Every change was followed by a reboot, as that’s the only reliable way that I’ve discovered of getting a manually changed automation to run. (It’s a pretty frustrating process, BTW, waiting many many minutes for HA to come back.)

Universally, one of two things would happen. HA would choose to run in safe mode, or (much more commonly), HA would declare “This entity is currently unavailable and is an orphan to a removed, changed or dysfunctional integration or device.”

So I just built some timers using an ESP8266 and using the update over WiFi feature, I can change the timer values without going outside.

I think it’s NUTS that it’s so hard hard to get a computer to go “On for 10 minutes, Off for 20, On for 10 minutes, Off for 20”, but with HA, that seems to be the case.

I also had problems trying to get a script to work but I managed to do it.
First of all there was a typo, ‘state’ was supposed to be ‘to’. I also hard set the input number when diagnosing but I have a feeling this bit from konradmt might work, worth a try :

"{{ states('input_number.on_time')|int }}"

I also learned that I must switch it off manually after configuration reload to trigger it. I’m not good enough in HA to know why.
Actually, I was in a big hurry to make this script work for my basement which was flooding.
At least it is confirmed working!
Here it is :

automation pump:        
    - alias: pump_on
      trigger: 
        platform: state
        entity_id: switch.sonoff_s31_4_relay
        to: 'off'
        for:
          seconds: 50
      action:
        service: switch.turn_on
        entity_id: switch.sonoff_s31_4_relay
    
    - alias: pump_off
      trigger: 
        platform: state
        entity_id: switch.sonoff_s31_4_relay
        to: 'on'
        for:
          seconds: 7
      action:
        service: switch.turn_off
        entity_id: switch.sonoff_s31_4_relay

I used the normal way of using the automation possibilities with a thermostat in idle or heating state.
In heating state I create a loop which switches on smart power plug on and off every 1 minute. When the state is idle, switch off my smart power plug.

id: ‘1665141338435’
alias: Turn IR heating on and loop
description: ‘’
trigger:

  • platform: state
    entity_id:
    • sensor.thermostaat_tiny_house_thermostathvacaction
      from: idle
      to: heating
      condition: []
      action:
  • repeat:
    while:
    - condition: state
    entity_id: sensor.thermostaat_tiny_house_thermostathvacaction
    state: heating
    sequence:
    - type: turn_on
    device_id: 68b9f8b2c3b3a5669b52324007dcb840
    entity_id: switch.smart_power_plug_switch
    domain: switch
    - delay:
    hours: 0
    minutes: 1
    seconds: 0
    milliseconds: 0
    - type: turn_off
    device_id: 68b9f8b2c3b3a5669b52324007dcb840
    entity_id: switch.smart_power_plug_switch
    domain: switch
    - delay:
    hours: 0
    minutes: 1
    seconds: 0
    milliseconds: 0
  • if:
    • condition: state
      entity_id: sensor.thermostaat_tiny_house_thermostathvacaction
      state: idle
      then:
    • type: turn_off
      device_id: 68b9f8b2c3b3a5669b52324007dcb840
      entity_id: switch.smart_power_plug_switch
      domain: switch
      mode: single