Automations (again..)

Afternoon All

As you may have noticed from recent posts I’m spending some time on my automations.

I’m trying to do some housing keeping and reduce text where possible.

At the moment I have two automations linked to an input boolean (for a fan). One for on and one for off.

I’m trying to join these but I’m having an issue:

- alias: "ib_Bed Fan (smart)"
  id: '90000000000123'
  trigger:
    platform: state
    entity_id: input_boolean.bed_fan
  action:
    - service_template: >
        {% if is_state('input_boolean.bed_fan', 'off') %}
          switch.turn_off
        {% else %}
          switch.turn_on
        {% endif %}
      entity_id: switch.plug_005b
    - delay: '00:30:00' 
    - service: switch.turn_off
      entity_id: switch.plug_005b

What I’m trying to achieve is when I turn on the input boolean to turn on the fan for 30 minutes then off. When I turn off the input boolean turn off the fan (and as it doesn’t matter, turns it “off” again 30 minutes later, leave that in so I can group them together rather than have 2 automations as I do now).

If I don’t add the extra actions (ie delay and switch turn off) it works great:

- alias: "ib_Bed Fan (smart)"
  id: '90000000000123'
  trigger:
    platform: state
    entity_id: input_boolean.bed_fan
  action:
    service_template: >
      {% if is_state('input_boolean.bed_fan', 'off') %}
        switch.turn_off
      {% else %}
        switch.turn_on
      {% endif %}
    entity_id: switch.plug_005b

For reference this is the two part I have working:

- alias: "ib_Bed Fan (smart on)"
  id: '90000000000123'
  trigger:
    platform: state
    to: 'on'
    entity_id: input_boolean.bed_fan
  action:
    - service: switch.turn_on
      entity_id: switch.plug_005b
    - delay: '00:30:00' 
    - service: switch.turn_off
      entity_id: switch.plug_005b
    - service: input_boolean.turn_off
      entity_id: input_boolean.bed_fan
- alias: "ib_Bed Fan (smart off)"
  id: '90000000000124'
  trigger:
    platform: state
    to: 'off'
    entity_id: input_boolean.bed_fan
  action:
    - service: switch.turn_off
      entity_id: switch.plug_005b

The “problem” is that during your 30 min delay, that automation is “running” so it can’t run again until the 30 min is up. I’m not sure if you can ‘abort’ an automation in the middle … but that’s why you can’t get it to work all as one.

If that were the case then it wouldn’t work when I have it split out (which does work, see second post above).

If I’m misinterpreted what you’ve said sorry.

Edit: Bad / Confusing English, double negative changed.

it works when you split it out because the “turn off” is a separate automation.

When you have it all-in-one: You turn on the boolean, it starts automation, the automation continues to run for 30 min (because it’s “executing” the delay statement). So when you turn off of the boolean before the 30 min is up, it tries to enter the automation again, but can’t because it’s still executing from when you turned it on.

Automations are not reentrant. They execute from top to bottom and cannot be triggered again until they complete.

1 Like

Right, I’m with you. I’ll tackle it from the script end then. Thank you.

If it isn’t broken, don’t fix it.

Ha! 100% agree. If I was @Knottyboy, I’d leave it as two automations. Not sure you can do much better than that anyway

As someone else mentioned, the “delay” is a blocking function, thus why it’s hanging up when you have it all in a single automation.

I don’t know if it’s too much cleaner, but I think you could do it with one automation and a timer.

- alias: "ib_Bed Fan (smart)"
  id: '90000000000123'
  trigger:
    - platform: state
      entity_id: input_boolean.bed_fan
    - platform: event
      event_type: timer.finished
      event_data:
        entity_id: timer.fan_auto_off
  action:
    - service_template: >
        {% if is_state('input_boolean.bed_fan', 'off') %}
          switch.turn_on
        {% else %}
          switch.turn_off
        {% endif %}
      entity_id: switch.plug_005b
    - service: timer.cancel
      data:
        entity_id: timer.fan_auto_off
    - condition: state
      entity_id: 'switch.plug_005b'
      state: 'on'
    - service: timer.start
      data:
        entity_id: timer.fan_auto_off

I haven’t ran this, so I’m not sure the syntax is 100% correct, but the idea is that your input boolean simply toggles the state of the fan in the first action (reverse of your original code). This toggling is also triggered by a timer finishing. The last 2 actions: the conditional check checks if you just turned it on, and if you did, it starts the timer which will re-trigger the same automation and toggle it off. If it’s already running when you activate it, it will just turn it off and not start the timer.

The timer.cancel is to first cancel the timer, so if you turned it on, then off manually, the timer won’t keep running, which is needed because now the action only toggles the fan’s state, and does not directly act on it. If it was off and you turned it on, it will pass the conditional check and start the timer again.

You’ll also have to add the timer to your config though, so it’s still kind of 2 configurations to manage, and their not both automations so it might complicate things even more.

timer:
  fan_auto_off:
    name: Time remaining
    duration: 1800 # Update this to the number of seconds you wish

Like I said, I didn’t check this on my own system, so you might have to debug it.

1 Like