Bathroom Ventilation based on multiple set periods of time multiple fans at once

Hi there,

I recently (24 hours ago!) setup home assistant to migrate all my Zwave devices ( dimmers, switches, thermostats ect ) for more accurate control and actually be able to tell when lights were on/off!

I was easily able to setup all my 4 bathroom fans to run 3 separate times of the day (7am-10am, 2pm-5pm and 9pm to 11:59pm) using the UI and have them functioning properly using 3 different on scripts and 3 different off scripts. All the ON scripts also take into account if homeassistant was down and check on startup to start the fans.

Fast forward 24 hours and Iā€™ve spent last 8 hours attempting to merge the 3 ON scripts into 1. I have the logic of the timing for if/elif statements and tested in template editor and it all works fine, but no matter what I try I can not even add a single fan to be turned on as I get Error: Template rendered invalid service:

Iā€™ve read so many forum posts and documentation that Iā€™m now completely confused and have absolutely no idea why when I add anything at all ( light.turn_on, switch.turn_on, turn_on ) the automation errors out.

Below is the snippet of code with the logic under the action. Iā€™ve removed the turn_on ect portions on my hundreds of tests as even copying/pasting from examples of similar I canā€™t get them to work.

alias: BATH FANS ON FOR VENTILATION
description: >-
  Turn all bathroom fans ON at trigger times, run if HA is down/restarted
  during to confirm ON.
trigger:
  - platform: homeassistant
    event: start
  - platform: template
    value_template: '{{ states(''sensor.time'') == ''7:00'' }}'
  - platform: template
    value_template: '{{ states(''sensor.time'') == ''14:00'' }}'
  - platform: template
    value_template: '{{ states(''sensor.time'') == ''21:00'' }}'
condition: []
action:
  - service: >
      {% if states('sensor.time') >= '7:00' and states('sensor.time') < '10:00'
      %}

      {% elif states('sensor.time') >= '14:00' and states('sensor.time') <
      '17:00' %}

      {% elif states('sensor.time') >= '21:00' and states('sensor.time') <
      '23:59' %}

      {% endif %}
mode: single

As mentioned the logic in the if/elif statement works as it should. Iā€™ve tested it in the template editor. Unfortunately once I add anything to be run when a condition of the if statements are met, I get the error

Using the UI to create the original ON script that works for the 4 devices lists the devices in it as follows

  - type: turn_on
    device_id: 166183b1511f5375140f22764e7b5c61
    entity_id: switch.scene_capable_switch_on_off
    domain: switch
  - type: turn_on
    device_id: 7f0fd1d6ece308b998dff9e47e05294d
    entity_id: switch.scene_capable_switch_on_off_2
    domain: switch
  - type: turn_on
    device_id: 1807344899ee43e16cfc480d73330ead
    entity_id: switch.scene_capable_switch_on_off_3
    domain: switch
  - type: turn_on
    device_id: b800352ff2c40b63df11c132882fa876
    entity_id: switch.scene_capable_switch_on_off_4
    domain: switch

Any/all help appreciated

First, in order to simplify turning on/off all 4 switch, create a group-

group:
  bathroom_switch:
    name: Bathroom Switch
    all: true
    entities:
      - switch.scene_capable_switch_on_off
      - switch.scene_capable_switch_on_off_2
      - switch.scene_capable_switch_on_off_3
      - switch.scene_capable_switch_on_off_4

Next, try to use the automation below-

trigger:
  - platform: time
    at: '07:00:00'
  - platform: time
    at: '10:00:00'
  - platform: time
    at: '14:00:00'
  - platform: time
    at: '17:00:00'
  - platform: time
    at: '21:00:00'
  - platform: time
    at: '23:59:00'
  - platform: homeassistant
    event: start
condition: []
action:
  - choose:
      - conditions:
          - condition: time
            after: '07:00:00'
            before: '10:00:00'
          - condition: state
            entity_id: group.bathroom_switch
            state: 'off'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '14:00:00'
            before: '17:00:00'
          - condition: state
            entity_id: group.bathroom_switch
            state: 'off'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '21:00:00'
            before: '23:59:00'
          - condition: state
            entity_id: group.bathroom_switch
            state: 'off'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
    default:
      - service: homeassistant.turn_off
        target:
          entity_id: group.bathroom_switch

Thanks, Iā€™ll take a look at this again in the morning as my better half not enjoying the clicking on the switch on/off at 2am!

I do notice that if switch is on when script run ie if home assistant restarted during those times and someone manually turned switch on it turns it off. As it goes to default since no conditions are met. Setting the default action to null would fix that obviously.

You can read about config variable here-

By adding all: true, the group state should only turn on if all grouped entities are on .

Thanks again Ardy

I guess I should of just tried to keep things simple and used conditions as laid out instead of trying to be all fancy!

At any rate modified what you posted above and tested to make sure all scenarios worked.

I ultimately ended up removing the ā€œall: trueā€ from groups as well as removed the condition of the state being off on each as if one fan is already turned on none of the fans will turn on which would mean ventilation not happening properly. Also removed default action of turning off when no condition met

alias: BATH FANS ON FOR VENTILATION
description: >-
  Run bathroom fans based on start and stop timing - includes coding to check if
  action missed due to HA restarting
trigger:
  - platform: homeassistant
    event: start
  - platform: time
    at: '07:00:00'
  - platform: time
    at: '14:00:00'
  - platform: time
    at: '21:00:00'
condition: []
action:
  - choose:
      - conditions:
          - condition: time
            after: '07:00:00'
            before: '10:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '14:00:00'
            before: '17:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '21:00:00'
            before: '23:59:59'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
mode: single

Your revised version no longer has the three end times (10:00, 17:00, 23:59) when the group should be turned off (so it will trigger only at the three start times ā€¦ and on startup of course). How do you envision the automation will turn off the group at the desired end times?

ā€¦ or are you now using a separate automation to turn off the group at the desired times?

Thanks Taras!

Was thinking of a second automation to deal with the other trigger times, but after reading your post I realize that when I remove the state condition inside the conditions, I can actually use default as it meant to be to turn off the fans.

With state condition removed, if time meet and regardless if a fan is on, itā€™ll match, and obviously if time isnā€™t matched then default to turn off. Adding back in the triggers at the top for the other times.

alias: BATH FANS ON/OFF FOR VENTILATION
description: >-
  Run bathroom fans based on start and stop timing - includes coding to check if
  action missed due to HA restarting
trigger:
  - platform: homeassistant
    event: start
  - platform: time
    at: '07:00:00'
  - platform: time
    at: '10:00:00'
  - platform: time
    at: '14:00:00'
  - platform: time
    at: '17:00:00'
  - platform: time
    at: '21:00:00'
  - platform: time
    at: '23:59:59'
condition: []
action:
  - choose:
      - conditions:
          - condition: time
            after: '07:00:00'
            before: '10:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '14:00:00'
            before: '17:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
      - conditions:
          - condition: time
            after: '21:00:00'
            before: '23:59:59'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
    default:
      - service: homeassistant.turn_off
        target:
          entity_id: group.bathroom_switch
mode: single

I also created a automation individually for each light when state is changed to OFF it uses the on time from above and then condition time as above to see if they should be on and turns switch back on.

alias: Ensuite Bath Fan - CHECK if Switched OFF during Ventilation
description: >-
  Detects when switch for bathroom fan turned off, then checks if the bath fan
  is supposed to be on ventilation mode
trigger:
  - platform: device
    type: turned_off
    device_id: 7f0fd1d6ece308b998dff9e47e05294d
    entity_id: switch.scene_capable_switch_on_off_2
    domain: switch
condition: []
action:
  - delay:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - choose:
      - conditions:
          - condition: time
            after: '07:00:00'
            before: '10:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: switch.scene_capable_switch_on_off_2
      - conditions:
          - condition: time
            after: '14:00:00'
            before: '17:00:00'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: switch.scene_capable_switch_on_off_2
      - conditions:
          - condition: time
            after: '21:00:00'
            before: '23:59:59'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: switch.scene_capable_switch_on_off_2
mode: single

Last Iā€™ll be creating a script when state changes to ON outside of those ON hours that bath fan runs for 30 minutes. Will post that when I have time to do it tonight.

The only scenario that isnā€™t covered will be if the switch is pushed while the original ventilation ON is running. So if it is say 9:50am and someone starting a shower and the ventilation turns off at 10am, during part of the shower there will be no fan until they hit button. I have zwave Leviton DZ15S switches and DZ6HD hooked up through Aeotec Zstick using zwave2mqtt inside home assistant. Based on reading I see other makers of switches send how many times switch was clicked, but only finding theories of how to capture that with other switches nothing so far on actual method

If you wish, that first automation can be reduced to this:

alias: BATH FANS ON/OFF FOR VENTILATION
description: >-
  Run bathroom fans based on start and stop timing - includes coding to check if
  action missed due to HA restarting
trigger:
  - platform: time
    at:
      - '07:00:00'
      - '10:00:00'
      - '14:00:00'
      - '17:00:00'
      - '21:00:00'
      - '23:59:00'
  - platform: homeassistant
    event: start
action:
  - variables:
      hr: "{{ now().hour }}"
  - choose:
      - conditions:
          - "{{ 7 <= hr < 10 or 14 <= hr < 17 or (21,0) <= (hr,now().minute) < (23,59) }}"
          - "{{ is_state('group.bathroom_switch', 'off') }}"
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
    default:
      - service: homeassistant.turn_off
        target:
          entity_id: group.bathroom_switch

FWIW, the template could be a touch shorter if the final turn off time was 00:00:00.

reduction in lines to edit for each definitely a good thing!

alias: BATH FANS ON/OFF FOR VENTILATION - NEW
description: >-
  Run bathroom fans based on start and stop timing - includes coding to check if
  action missed due to HA restarting
trigger:
  - platform: time
    at:
      - '07:00:00'
      - '10:00:00'
      - '14:00:00'
      - '17:00:00'
      - '21:00:00'
      - '00:00:00'
  - platform: homeassistant
    event: start
condition: []
action:
  - variables:
      hmin: '{{ now().strftime(''%H:%M'') }}'
  - choose:
      - conditions:
          - condition: template
            value_template: >-
              {{ '07:00' <= hmin < '10:00' or '14:00' <= hmin < '17:00' or
              '21:00' <= hmin < '00:00' }}
          - condition: template
            value_template: '{{ is_state(''group.bathroom_switch'', ''off'') }}'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: group.bathroom_switch
    default:
      - service: homeassistant.turn_off
        target:
          entity_id: group.bathroom_switch
mode: single

I slightly changed the hr variable setting to get minutes as well incase I decide to do say 7:15 ect and changed my times accordingly.

The last part where it is now 00:00 for hour:min at the end is that correct? All my testing correctly turns on/off when should, just not sure about the midnight portion. I had read a few times about ā€œfunkynessā€ at ā€œ00:00ā€ but it was probably on older posting, only reason I set original to 23:59.

Is there any particular reason you chose to make the example I provided more verbose? The original contained Template Conditions in shorthand notation and you replaced them all with the longer version.

What time value would make this evaluate to true?

I copied and pasted what you did and only changed the variable and h to hmin to reflect it not just hour and added :00.

Just checked, when I save through the automation editor it automatically adds in the ā€œvalue_template: >-ā€ and template references to the codeā€¦ should the automation editor be doing that automatically?

hmin < ā€˜00:00ā€™ I would like to confirm that it evaluates to true at 12am

The Automation Editor imposes its own style of coding and sometimes that doesnā€™t mean an improvement. 'nuf said.


When you do this:

'10:00' < '12:00'

itā€™s not actually comparing two times but two strings. Itā€™s no different than doing this:

'bat' < 'cat'

Why it works has to do with numeric ordering in the ASCII table (the ASCII value for 1 is less than the ASCII value for 2) along with careful formatting of the time so itā€™s always four characters long.

Your hmin variable will never produce a time string less than 00:00.

My own preference for comparing times is to express then as tuples (but thatā€™s a discussion for another time).


The fact is that you donā€™t really have to check the minutes portion. Under normal circumstances, the automation will trigger exclusively at the specified times and, since they all have different hours, a simple comparison of hours is sufficient to ensure the appropriate action is performed. If the trigger is due to a restart then the consequence of not checking the minutes is hardly consequential (the action will be off by a few minutes). All this to say that the juice isnā€™t worth the squeeze ā€¦ but squeeze away if you want.

Thanks Tara and Ardy,

Had to upgrade my network equipment in between doing this and 20 other things. Have everything setup and working and multiple ways to skin the same cat that I was trying to overly complicate above. Much appreciated!

Have been using above without issue for 3-4 days now and added in a check so if any of those fans are turned off during the ventilation defined times it waits 10 seconds and automatically turns on the specific fan. Working great and thanks again!

New hurdle

I have 2 sets of logic automations that Iā€™m attempting to add in as well but even though the zwave log file shows that the information is being received so one scenario of triggers arenā€™t being met.

The idea:

When fan switch is pushed on ( regardless if fan is on already ) take action based on the following.

  1. ON from OFF
    • Set delay to turn off after 30 minutes
  2. ON from ON
    • Check against timing based on what I set in previous ventilation automation. If it is 25 minutes or less before the end of the ventilation turning off, set a delay of 30 minutes so if fan is on and supposed to end at 10am but ON button pushed at 9:35am it delays turning off until 10:05am.
    • Additionally ( I have looked but not tried as canā€™t get ON to ON to work ) Iā€™ll need to figure out how to on the original ventilation script to not turn off if this delay is on. Looking I should be able to use a input on this scenario that the original script can check for being ON to accomplish?

#1 above triggers and works properly, but #2 doesnā€™t seem to pass the ON press when switch is ON already to HA even though it shows in the zwave event logs the state updates. Is it just being ignored because the state doesnā€™t actually change?

This is the code:

alias: Testing fan push timer
description: >-
  Detects when switch for bathroom fan turned ON, then checks against
  ventilation times to decide whether set 30min delay
trigger:
  - platform: state
    from: 'on'
    to: 'on'
    entity_id: switch.scene_capable_switch_on_off_4
  - platform: state
    from: 'off'
    to: 'on'
    entity_id: switch.scene_capable_switch_on_off_4
condition: []
action:
  - variables:
      hmin: '{{ now().strftime(''%H:%M'') }}'
  - choose:
      - conditions:
          - condition: template
            value_template: '{{ ''01:10'' <= hmin < ''15:59'' }}'
        sequence:
          - service: homeassistant.turn_on
            target:
              entity_id: script.scriptupstairs_bathroom_manual_on
mode: single

Code for the scripts used in the above automation

alias: upstairs_bathroom_fan_manual_on
sequence:
  - service: script.turn_off
    data: {}
    target:
      entity_id: script.script_upstairs_bathroom_manual_timer
  - service: switch.turn_on
    data:
      entity_id: switch.scene_capable_switch_on_off_4
  - service: script.turn_on
    data: {}
    target:
      entity_id: script.script_upstairs_bathroom_manual_timer
mode: single

alias: upstairs_bathroom_fan_manual_on_timer
sequence:
  - delay:
      minutes: 30
  - service: switch.turn_off
    data:
      entity_id: switch.scene_capable_switch_on_off_4
mode: single

zwave logs:

Original button push

2021-09-04T20:58:24.293Z CNTRLR [Node 018] Hail received from node, refreshing actuator and sensor values...
2021-09-04T20:58:24.295Z CNTRLR Ā» [Node 018] querying Binary Switch state...
2021-09-04 13:58:24.495 INFO ZWAVE: Node 18: value updated: 37-0-currentValue false => true
2021-09-04T20:58:24.518Z CNTRLR Ā« [Node 018] received Binary Switch state:
current value: true
2021-09-04 13:58:24.647 INFO ZWAVE: Node 18: value updated: 37-0-currentValue true => true
2021-09-04T20:58:24.721Z CNTRLR [Node 018] Hail received from node, refreshing actuator and sensor values...
2021-09-04T20:58:24.724Z CNTRLR Ā» [Node 018] querying Binary Switch state...
2021-09-04 13:58:24.926 INFO ZWAVE: Node 18: value updated: 37-0-currentValue true => true
2021-09-04T20:58:24.936Z CNTRLR Ā« [Node 018] received Binary Switch state:
current value: true


Second button push when ON already

2021-09-04T20:58:48.493Z CNTRLR [Node 018] Hail received from node, refreshing actuator and sensor values...
2021-09-04T20:58:48.497Z CNTRLR Ā» [Node 018] querying Binary Switch state...
2021-09-04 13:58:48.695 INFO ZWAVE: Node 18: value updated: 37-0-currentValue true => true
2021-09-04T20:58:48.708Z CNTRLR Ā« [Node 018] received Binary Switch state:
current value: true

The trigger wonā€™t fire when the state change is the same. It needs to be evaluated as false at the begininng, then change state and evaluated as true. Only then the automation will be triggered.

As the values are being updated in the zwave portion is there any way to recognize this push on when it already on since it canā€™t be done with state as it isnā€™t actually changing?

I am unfamiliar with Z-Wave switches. You can take a look at this thread-

Basically you need an event data to know if the switch is manually pressed. The event data can then be used as an automation trigger.

Thanks, gone through that and others plus links from it.

After much testing I canā€™t seem to find anything thatā€™ll register the second push that is showing in the zwave log when in debug mode on these leviton switches. Or at least everything I tried seemed to not work at all

Ardy,

I took a break, had a nap and then came back and started toying again.

I should of just tried through the UI as I mustnā€™t of been entering something correct on copy/paste and modifying things through yaml. But was able to use event data of the device properly as per your suggestion above. Every push of the on button actually triggers the automation which will allow me to set input booleans ect to achieve what I want!

Thanks, I finally found the water!

1 Like

Thought Iā€™d post my final scripts here. Not the prettiest, but they work and accomplish everything in all scenarios that I could think of.

Idea: Control multiple bathroom fans, to all turn on/off at set times. Monitor the switch presses for on/off and depending when in ventilation or outside of ventilation timing act accordingly.

  • If Ventilation OFF
    ā€“ Turns fan on, with 30 minute delay, then turns off. When pushed while already on restarts so delay another 30 minutes before turning off

  • If Ventilation ON
    ā€“ switch OFF ā€“ delay 10 seconds turn back on
    ā€“ switch ON ā€“ checks against a input.boolean to see if fan is in last 25 minutes of ventilation. If not, button push is ignored. If it is, the individual fan status is set to ON and delay of 30 minutes before turning off set. Additional presses of on restart delay

When ventilation turning off, it checks each individual fan to see if the status is ON. If they are on it doesnā€™t turn them off. If fan status is OFF it turns them off at end of ventilation.

Original automation to turn fans on/off during ventilation times:

- id: '1630215220100'
  alias: 001 - 1 BATH FANS ON/OFF FOR VENTILATION
  description: Run bathroom fans based on start and stop timing - includes coding
    to check if action missed due to HA restarting
  trigger:
  - platform: time
    at:
    - 07:00:00
    - '10:00:00'
    - '14:00:00'
    - '17:00:00'
    - '21:00:00'
    - '23:59:00'
  - platform: homeassistant
    event: start
  condition: []
  action:
  - variables:
      hmin: '{{ now().strftime(''%H:%M'') }}'
  - choose:
    - conditions:
      - condition: template
        value_template: '{{ ''07:00'' <= hmin < ''10:00'' or ''14:00'' <= hmin < ''17:00''
          or ''21:00'' <= hmin < ''23:59'' }}'
      - condition: template
        value_template: '{{ is_state(''group.bathroom_switch'', ''off'') }}'
      sequence:
      - service: homeassistant.turn_on
        target:
          entity_id: group.bathroom_switch
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.001_01_ventilation_status_bath_fans
      - service: input_boolean.turn_off
        target:
          entity_id:
          - input_boolean.main_bath_fan_status
          - input_boolean.ensuite_bath_fan_status
          - input_boolean.upstairs_bath_fan_status
          - input_boolean.tenant_bath_fan_status
    default:
    - service: input_boolean.turn_off
      target:
        entity_id:
        - input_boolean.001_01_ventilation_status_bath_fans
        - input_boolean.001_01_ventilation_status_bath_fans_under_30_min
    - service: script.ensuite_bathroom_fan_check_status_on_turn_off
    - service: script.main_bathroom_fan_check_status_on_turn_off
    - service: script.upstairs_bathroom_fan_check_status_on_turn_off
    - service: script.tenant_bathroom_fan_check_status_on_turn_off
  mode: single

input.boolean is set 25 minutes prior to ventilation off for use elsewhere:

- id: '1630224742314'
  alias: 001 - 1 BATH FANS VENTILATION Final 25 Minutes
  description: Sets input.boolean for other automations to check if in final 25 minutes
    of ventilation run.
  trigger:
  - platform: time
    at:
    - 09:35:00
    - '16:35:00'
    - '23:35:00'
  condition: []
  action:
  - service: input_boolean.turn_on
    target:
      entity_id: input_boolean.001_01_ventilation_status_bath_fans_under_30_min
  mode: single

Each fan has it switch push OFF automation:

- id: '1630222032781'
  alias: 001 - 1c Upstairs Bath Fan check if Switched OFF during Ventilation
  description: Detects when switch for bathroom fan turned off, then checks if the
    bath fan is supposed to be on ventilation mode
  trigger:
  - platform: device
    type: turned_off
    device_id: b800352ff2c40b63df11c132882fa876
    entity_id: switch.scene_capable_switch_on_off_4
    domain: switch
  condition: []
  action:
  - delay:
      hours: 0
      minutes: 0
      seconds: 10
      milliseconds: 0
  - choose:
    - conditions:
      - condition: state
        entity_id: input_boolean.001_01_ventilation_status_bath_fans
        state: 'on'
      sequence:
      - service: homeassistant.turn_on
        target:
          entity_id: switch.scene_capable_switch_on_off_4
    default:
    - service: input_boolean.turn_off
      target:
        entity_id: input_boolean.upstairs_bath_fan_status
  mode: single

Each fan has its switch push ON automation:

- id: '1630224708508'
  alias: 001 - 1c Upstairs Bath Fan check Switch ON
  description: Detects when switch for bathroom fan turned ON
  trigger:
  - platform: device
    device_id: 31dd04856b40eced6b6b56888fcff826
    domain: zwave_js
    type: zwave_js.value_updated.value
    command_class: 37
    to: 'on'
    property: currentValue
    from: ''
    endpoint: ''
    property_key: ''
  condition: []
  action:
  - choose:
    - conditions:
      - condition: state
        entity_id: input_boolean.001_01_ventilation_status_bath_fans
        state: 'off'
      sequence:
      - service: script.upstairs_bathroom_fan_delay
    - conditions:
      - condition: state
        entity_id: input_boolean.001_01_ventilation_status_bath_fans_under_30_min
        state: 'on'
      sequence:
      - service: script.upstairs_bathroom_fan_delay
    default: []
  mode: restart

Each switch as a scripted called from switch OFF automation:

alias: 001 - 1c Upstairs Bath Fan Ventilation OFF check
sequence:
  - condition: state
    entity_id: input_boolean.upstairs_bath_fan_status
    state: 'off'
  - type: turn_off
    device_id: 31dd04856b40eced6b6b56888fcff826
    entity_id: switch.scene_capable_switch_on_off_4
    domain: switch
mode: single

Each switch has a script called when it is turned on to do the delay:

alias: 001 - 1c Upstairs Bath Fan Delay on ON
sequence:
  - service: input_boolean.turn_on
    target:
      entity_id: input_boolean.upstairs_bath_fan_status
  - delay:
      hours: 0
      minutes: 30
      seconds: 0
      milliseconds: 0
  - type: turn_off
    device_id: 31dd04856b40eced6b6b56888fcff826
    entity_id: switch.scene_capable_switch_on_off_4
    domain: switch
  - service: input_boolean.turn_off
    target:
      entity_id: input_boolean.upstairs_bath_fan_status
mode: restart

This is all done using Leviton DS15Z on/off switches. They do not have multiple button press actions but by using conditions and input.booleans set I was able to make them act like it did. It rethinking the logic and conditions it would be possible using this to actually turn these switches into multiple action based on amount of times the switch is hit on to trigger difference scenarios. ie if you walked into the room, you could have different items turned on depending on how many button presses. Just would take more effort then having the state change available like certain other switches with that capability have built in!