Button Options for Timer Duration

My goal is to have an option to continue running a fan for 3 different durations. To easily select the times I’d like to display the choices as buttons. These should be like an input_select in that it makes sense to only have 1 option (or none) selected at a time. I believe I’ve got the UI somewhat how I want it using this for the card:

- type: "custom:hui-entities-card"
        title: Garage AFS
        show_header_toggle: false
        entities:
          - entity: switch.garage_fan
          - entity: fan.garage_afs
            type: custom:fan-control-entity-row
            name: Garage Air Filter
            customTheme: false
          - type: "custom:button-entity-row"
            buttons:
              - entity: input_boolean.timer_30min
                name: 30
                service: script.afs_30
                #service_data:
                #  entity_id: 
                style:
                - flex-direction: column
                icon_style:
                  - padding-right: 0 !important
                  - '--iron-icon-height': 2.5em
                  - '--iron-icon-width': 2.5em
                state_styles:
                  "off":
                    font-weight: normal
                  "on":
                    color: green
                    font-weight: bold
              - entity: input_boolean.timer_60min
                name: 60
                service: script.garage_afs_off
                state_styles:
                  "off":
                    font-weight: normal
                  "on":
                    color: green
                    font-weight: bold
              - entity: input_boolean.timer_90min
                name: 90
                service: script.garage_afs_off

I just have booleans for the buttons defined as:

timer_30min:
  name: 30min
  icon: mdi:timer
  initial: off

timer_60min:
  name: 60min
  icon: mdi:timer
  initial: off

timer_90min:
  name: 90min
  icon: mdi:timer
  initial: off

and then the script is currently this:

afs_30:
  alias: AFS OFF After 30min
  sequence:
  - entity_id: input_boolean.timer_30min
    service: input_boolean.toggle
  - entity_id: input_boolean.timer_60min
    service: input_boolean.turn_off
  - entity_id: input_boolean.timer_90min
    service: input_boolean.turn_off
  - condition: state
    entity_id: input_boolean.timer_30min
    state: 'on'
  - delay: 00:30:00
  - entity_id: script.garage_afs_off
    service: homeassistant.turn_on
  - entity_id: input_boolean.timer_30min
    service: input_boolean.turn_off

I’m still in the testing phase as well as trying to determine if I’m even going about this the best way seems it seems rather convoluted to me. I do get this error thrown when I try the “30 minute timer” so with this code it’s not working properly yet.

AttributeError: 'NoneType' object has no attribute 'is_on'
2020-02-10 17:27:30 ERROR (MainThread) [homeassistant.components.websocket_api.http.connection.140600466809040] 'NoneType' object has no attribute 'is_on'
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/components/websocket_api/commands.py", line 134, in handle_call_service
    connection.context(msg),
  File "/usr/src/homeassistant/homeassistant/core.py", line 1226, in async_call
    await asyncio.shield(self._execute_service(handler, service_call))
  File "/usr/src/homeassistant/homeassistant/core.py", line 1251, in _execute_service
    await handler.func(service_call)
  File "/usr/src/homeassistant/homeassistant/components/script/__init__.py", line 202, in service_handler
    if script.is_on:

I initially tried using a timer and passing the duration based on which button was pressed but I couldn’t get that to work but I’m a little stuck on how to clean up this mess and get it to work.

I can suggest the following automation for changing the timer dynamically.

you need to create an input_number which you’ll add to your lovelace allowing you to change the timer.

- id: lights_on_automation
  alias: Lights on automation
  initial_state: true
  trigger:
  - platform: state
    entity_id:
    - input_number.timer_pir7_guesttoilet
    
  action:   
  - service_template: timer.start
    data_template:
      entity_id:  timer.pir7_guesttoilet
      duration: >  
          {% set a = states.input_number.timer_pir7_guesttoilet.state | int * 60 %} {{ a }}

Not sure I fully understand the use case here.

Continue running a fan…as in “when you click it, it will just off after X minutes”? Or “Adds X minutes to the current fan timer?” Or maybe this will turn on a fan for X minutes.

I think I would still create an input_select. Then, I would have the state change of that do other things.

# In configuration.yaml
input_select:
    fan_time_select:
      name: Garage Fan On Time Minutes
      options:
        - "OFF"
        - "30"
        - "60"
        - "90"
      icon: mdi:timer

I would also create a timer.

fan_timer:
  laundry:
    duration: '00:30:00'

The reason I would use a timer is because calling an automation that is currently waiting in a delay state will cause the automation to finish. It will skip the current and all future delays and execute everything in order, then trigger again and start over. So if you were to press the button again, it would finish, turn off the fan, then turn it right back on. The timer solution is better and gives you the ability to see a countdown timer for free!

Now you want to tie the main functionality to this input_select.

automation:
  - alias: Update Fan Timer
    trigger:
      # Trigger whenever the input_select state changes. 
      platform: state
      entity_id: input_select.fan_time_select
    condition:
      platform: template
      entity_id: input_select.fan_time_select
      # Ignore state changes to '0', or 'OFF', or whatever we want to set the off state. 
      value_template: "{{ not is_state('input_select.fan_time_select', 'OFF') }}"
    action:
      # In all cases, the fan needs to turn on. If it's already on....this wont affect anything.
      - service: switch.turn_on
        entity_id: switch.fan_entity_id
      # The fan will turn itself off when the timer reaches 0. So all we have to do 
      # is start (or restart) the timer with the new duration.
      - service: timer.start
        entity_id: timer.fan_timer
        # Sets the duration to the time select. This must be in '00:00:00' format.
        duration: "00:{{ states('input_select.fan_time_select') }}:00"

 - alias: Fan Timer Expired
   trigger:
   # Turns off the fan only when timer expires normally.
   - platform: event
     event_type: timer.finished
     event_data:
       entity_id: timer.fan_timer
   action:
   - service: switch.turn_off
     entity_id: switch.fan_entity_id
   # Now that fan is off, reset the select to 'off' position.
   - service: input_select.select_option
     data:
       entity_id: input_select.fan_time_select
       option: "OFF"

Now if you want to keep your crazy button setup, just have them call input_select.select_option as the service. This will now only set the input_select state which will fire the automation. We don’t have all of these corner cases to handle who or what started the fan. If you start it with the input select, it will turn off after X minutes.

1 Like

Hi and thanks for responding. I just wanted to clarify what I have and what I’m trying to do. I have an air filtration system in the garage for woodworking. It is a 3 speed fan that I’ve replaced the controller with a Sonoff 4Ch Pro running Tasmota firmware. On the 4th channel I have a separate regular fan which is the 1st element in this card:
GarageAFS

So I want to be able to select a speed and run the fan when I’m in the garage. When I’m done I want to set a timer that will turn off the fan after the selected amount of time. I’ve got a small 7" touch screen in the garage so I wanted to make the interface as slim and easy to use as possible which is why I wanted just buttons instead of drop down menus like input_select does.

I’ll have to re-read your solution to see if I understand what you’re suggesting. I definitely think the timer is a better solution but I’ve been struggling a bit just to get the card to look close to how I wanted and that limited what solutions I could use to pass information to scripts, automations, timers.

Is it possible to see the status and the time left in input_select?

Many thanks

@GeorgeIoak - Did you finally get that right? I’m trying to do a similar (but simpler) thing. I just want to run a timer by choosing from three different durations with a button for each.

I did but my method broke many versions ago and I’ve been staring at this on my home page ever since because I haven’t gotten around to figuring out how to make it work again!

image