How do I create a flexible sleep timer?

I have a Honeywell thermostat and I’d like to create a dashboard button that functions as a sleep timer. When tapping on the button, I’d like to be presented with options for different amounts of time, such as 15 minutes, 30 minutes, 1 hour, 2 hours, and Custom (enter the of minutes). After the selected time had passed, I want the thermostat to turn off.

Is this something I can do in HA? I’m running it on an rPi3. I could see this being useful for other things such as lights, so it would be even better if I could configure the button with a list of devices, as well, and whichever is picked is what gets turned off after the elapsed time.

1 Like

You could if your thermostat integrates with HA (which you did not write) … and then you need a device with a HA screen too of course, this can be via some DIY with a simple wemosd1+nextion touchscreen (<30eur) or your phone, tablet, etc.
Possibly (guess not) the thermostat button may be able to use multi-click and send that to HA for action.

I dont know if you can do it with a button but you can set an input datetime from the dashboard and then create an automation to turn the thermostat off at that time. There is also time picker card custom plugin you can possibly use to “pretty it up” a bit.

As far as other devices you could do that with an input select drop down. But the problem is going to be that you can’t use the same input datetime for multiple entities at the same time.

You might be able to work something like that out but the code for setting the different entities and datetimes and storing them is going to be pretty complicated.

I have a nexttion screen which distinguishes between click and long click and even swipe One can also click a few times and if within a certain timeframe then this could trigger different things…options a plenty but you need a way to communicate to HA and have the thermo integrated

Sorry, I want to do this directly within the HA dashboard, which I would access from my computer and the HA mobile app. Yes, my thermostat is integrated with HA. Thanks.

This sounds like what I’m looking for. Could you explain how I would accomplish this? So far, I’ve only added some pretty simple cards to the dashboard. Thanks for helping me!

I’ve used a different approach for manually running my pool pump which you might like or be able to customize it.

alias: Pool Runtime Manual Start
description: ''
trigger:
  - platform: state
    entity_id:
      - input_number.pool_manual_runtime
    for:
      hours: 0
      minutes: 0
      seconds: 3
condition: []
action:
  - service: timer.start
    data:
      duration: '{{ states(''input_number.pool_manual_runtime'') | float(1) * 60 * 60  }}'
    target:
      entity_id: timer.pool_manual_runtime_timer
  - service: homeassistant.turn_on
    data: {}
    target:
      entity_id:
        - switch.pentair_f7_dc_7a_pool
  - service: input_number.set_value
    data:
      value: 0
    target:
      entity_id: input_number.pool_manual_runtime
mode: single
alias: Pool Shutoff After Manual Runtime
description: ''
trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.pool_manual_runtime_timer
  - platform: state
    entity_id: input_number.pool_manual_runtime
    to: '0'
    for:
      hours: 0
      minutes: 0
      seconds: 5
condition: []
action:
  - service: homeassistant.turn_off
    data: {}
    target:
      entity_id:
        - switch.pentair_f7_dc_7a_pool
mode: single

lovelace

type: custom:auto-entities
card:
  type: entities
  state_color: true
  title: Pool Summary
entities:
  - entity: input_number.pool_manual_runtime
    tap_action:
      action: call-service
      service: script.pool_manual_run_add
  - entity: timer.pool_manual_runtime_timer
title: Pool Summary
state_color: true
filter:
  exclude:
    - state: idle

If I manually add time to the pool_manual_runtime it will set the timer for that amount and run the pump. Or I have it set so I can click it and it’ll ‘add’ time to the existing amount so I can ‘increase it’ in steps of 10 minutes with a script.

add script:

alias: Pool Manual Run Add
sequence:
  - service: input_number.increment
    data: {}
    target:
      entity_id: input_number.pool_manual_runtime
mode: queued

Other but still similar
You can create a button that updates an input_number through a small script in steps of (say) 30 until your own max value is reached … the idea is to click through a cycle 0>30>60>90>120>0

  • if input_number < 120 add 30
  • if input_number =120 set 0
    Then add an automation that checks this value and controls the thermo.
  • trigger if input_number > 0 … for 30 sec…you might be clicking so no immediate response
  • action on thermo for now() + input_number
  • at the end set input_number to 0

You can use a select helper and define a few options there ('15min, 30 min, ‘off’). Selecting a value could trigger your script to actually start the timer. When it is finished, you can set the helper to ‘off’, and when the helper has the state ‘off’, you can actually set the thermostat off. Easy to use and clean…

input_datetime:
  thermostat_off_time:
    name: Turn thermostat Off At
automation:
  - alias: Turn Thermostat Off at Time
    trigger:
      - platform: time
        at: input_datetime.thermostat_off_time
    action:
       - service: whatever_you_will_use_turn_it_off
1 Like

A select helper is doable. But not for my use case. I use 10 minute intervals and I could want it to run for 30 minutes or 6 hours. I don’t want to have to pre-define such a list. I can add arbitrary values or I can simply click the lovelace icon 3 times to get it to run 30 minutes. But yes it all starts once the value is set just like your suggestion of the select helper.

The op didn’t really say what he’d like to do as far as intervals so he has another option.

1 Like

I’ve achieved this using a combination of a timer helper, script, automations and a conditional mushroom chip. I’m very happy with the outcome, although my YAML and jinja may be ugly as I figured out how to do this on the way and tripped up a few times.



timer code in configuration.yaml - you can do this through helpers UI if you prefer

timer:
  ac_off_countdown:
    name: "AC Off Countdown"
    restore: true

Script that can be called to start, increment or cancel the timer, depending on A/C conditions. This goes in scripts.yaml.

timer_increment_or_reset:
  alias: AC sleep increment or reset
  sequence:
    - choose:
        - conditions: # timer isn't running already and A/C is on
            - condition: not
              conditions:
                - condition: state
                  entity_id: timer.ac_off_countdown
                  state: active
            - condition: not
              conditions:
                - condition: state
                  entity_id: climate.xx # your AC entity here
                  state: 'off'
          sequence: # start timer
            - service: timer.start
              data:
                duration: '00:30:00'
              target:
                entity_id: timer.ac_off_countdown
        - conditions: # A/C is on and timer is less than 12 hours - 30 minutes)
            - condition: not
              conditions:
                - condition: state
                  entity_id: climate.xx # your AC entity here
                  state: 'off'
            - condition: template
              value_template: >-
                {{ (as_timestamp(state_attr('timer.ac_off_countdown', 'finishes_at')) - now().timestamp()) < 39600 }}
          sequence: # add 30 minutes to existing timer
            - service: timer.start
              data:
                duration: >
                  {% set s = as_timestamp(state_attr('timer.ac_off_countdown', 'finishes_at')) - now().timestamp() %} 00:00:{{ s | int + 1800 }}
                entity_id: timer.ac_off_countdown
      default: # cancel the timer
        - service: timer.cancel
          data: {}
          target:
            entity_id: timer.ac_off_countdown
  mode: restart
  icon: mdi:sleep

Automation to do something when the timer finishes

alias: Air off
description: Turn off AC
trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.ac_off_countdown
condition:
  - condition: not
    conditions:
      - condition: state
        state: "off"
        entity_id: climate.xx # your AC entity here
action:
  - service: climate.turn_off
    data: {}
    target:
      entity_id: climate.xx # your AC entity here
mode: single

This automation simply cancels a running timer if the A/C is turned off some other way

alias: Reset AC timer on AC off
description: ''
trigger:
  - platform: state
    entity_id:
      - climate.xx # your AC entity here
    to: 'off'
condition:
  - condition: state
    entity_id: timer.ac_off_countdown
    state: active
action:
  - service: timer.cancel
    data: {}
    target:
      entity_id: timer.ac_off_countdown
mode: single

Dashboard card, you can do this however. I’m using a mushroom conditional chip so the card is only there where needed.

type: custom:mushroom-chips-card
chips:
  - type: conditional
    conditions:
      - entity: climate.xx # your AC entity here
        state_not: 'off'
    chip: # chip contents either show 'sleep', seconds remaining, minutes remaining or hh:mm depending on context
      type: template
      icon: mdi:sleep
      content: |
            {% if states('timer.ac_off_countdown') != 'active'%}
              Sleep
            {% else %}
              {% set s = (as_timestamp(state_attr('timer.ac_off_countdown','finishes_at')) -  as_timestamp(now()) ) | int %}
              {% set m =  (s / 60) | round(0) %}
              {% if s < 60 %}
                {{s}} secs
              {% elif m > 60 %}
                {{ m // 60 }}:{{ '{:0>2d}'.format(m%60) }} hours
              {% else %}
                {{ m }} mins
              {% endif %}
            {% endif %}
      tap_action: # run the script when tapped
        action: call-service
        service: script.timer_increment_or_reset
        data: {}
        target: {}
      hold_action: # cancel the timer if held
        action: call-service
        service: timer.cancel
        data: {}
        target:
          entity_id: timer.ac_off_countdown
      double_tap_action:
        action: none
      entity: timer.ac_off_countdown
alignment: center
4 Likes

This is fantastic! Thank you for walking me through all this. I’ve got everything entered and customized with my entity/script/etc. It’s added to the dashboard now and looks good.

When I click on the Sleep chip, I get a message saying, “Failed to call service script/timer_increment_or_reset. Service not found.” Is there some sort of dependency I’m missing?

I would say that is because the YAML I shared for the script is from the script UI. If you’re pasting in to scripts.yaml then you need to have it all under the script name, like this:

timer_increment_or_reset:
  alias: AC sleep increment or reset
   ...

I’ve updated my post above to include this now

Ah, yes. I updated the card to point to the script properly. Thanks!

It looks to be functioning properly now. I’ll have some time tomorrow to test it out. Thanks again so much!

1 Like

Just wanted to thank you for this. Just used this for my AC and it’s spot on for what i needed.

1 Like

odd issue with this that hopefully someone can help with.

When i manually turn the device in question off, it DOES run the reset automation but it DOESNT actually reset the timer. So when i turn the device back on, the timer is active from the last time (unless time has run out of course).

If i manually run the automation the timer is reset fine
If i watch the automation while i manually turn off the device, i see it run the automation

hi @alexeiw123 ,
really thank for sharing your automation!
i’ve tried it on my 3 AC but 've a problem:if i turn on my AC and set the timer to shut off, it shut off properly, but after a second it come back on! i can see this behavior in the script trace as you can see here:


the only adjustment that i’ve made to your script is to redutce the max timer off from 39600 to 10800!

i’f i run the service climate turn off via developer setting the climate stay off, but if i activate the timer, at the end after power off it power on again in the last state!

No problem - is that screenshot from the automation trace or the script trace?

The script should only be controlling the timer entity and the timer triggers the automation that turns off the AC. I don’t think that I used any turn_on type services in my automation so my immediate though is that some other automation is doing the triggering, but then I wouldn’t have expected to see it in the trace.

If you look at your climate.entity under logbook, does it give any insight as to what turned the AC back on?

What does it show on the 4th tab there, which in english reads ‘related logbook entries’?

hi @alexeiw123
thanks for your reply!
the screenshot above is from the automation (the one that turn off the AC).
the logbook of the automation is this and seems that the climate entity back on was triggered by time.finished event!

here my timer, automation and script (i have 3 AC, i’ll post only one of theese).
the script and timer was configured in yaml files, and the automation in UI (in yaml mode)

timer in configuration.yaml:

#timer_ac_template_block
timer:
  ac_off_countdown_studio:
    name: "AC Off Countdown Studio"
    restore: true

script in script.yaml:

timer_increment_or_reset_studio:
  alias: AC sleep increment or reset haori_studio
  sequence:
    - choose:
        - conditions: # timer isn't running already and A/C is on
            - condition: not
              conditions:
                - condition: state
                  entity_id: timer.ac_off_countdown_studio
                  state: active
            - condition: not
              conditions:
                - condition: state
                  entity_id: climate.haori_studio # your AC entity here
                  state: 'off'
          sequence: # start timer
            - service: timer.start
              data:
                duration: '00:30:00'
              target:
                entity_id: timer.ac_off_countdown_studio
        - conditions: # A/C is on and timer is less than 12 hours - 30 minutes)
            - condition: not
              conditions:
                - condition: state
                  entity_id: climate.haori_studio # your AC entity here
                  state: 'off'
            - condition: template
              value_template: >-
                {{ (as_timestamp(state_attr('timer.ac_off_countdown_studio', 'finishes_at')) - now().timestamp()) < 10800 }}
          sequence: # add 30 minutes to existing timer
            - service: timer.start
              data:
                duration: >
                  {% set s = as_timestamp(state_attr('timer.ac_off_countdown_studio', 'finishes_at')) - now().timestamp() %} 00:00:{{ s | int + 1800 }}
                entity_id: timer.ac_off_countdown_studio
      default: # cancel the timer
        - service: timer.cancel
          data: {}
          target:
            entity_id: timer.ac_off_countdown_studio
  mode: restart
  icon: mdi:sleep

turn off AC automation (code was entered in the ui in yaml mode):

alias: Air off Studio
description: Turn off AC Studio
trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.ac_off_countdown_studio
condition:
  - condition: not
    conditions:
      - condition: state
        state: "off"
        entity_id: climate.haori_studio
action:
  - service: climate.turn_off
    data: {}
    target:
      entity_id: climate.haori_studio
mode: single

reset timer automation (code was entered in the ui in yaml mode):

alias: Reset AC timer on AC off Studio
description: ""
trigger:
  - platform: state
    entity_id:
      - climate.haori_studio
    to: "off"
condition:
  - condition: state
    entity_id: timer.ac_off_countdown_studio
    state: active
action:
  - service: timer.cancel
    data: {}
    target:
      entity_id: timer.ac_off_countdown_studio
mode: single