How do I create a flexible sleep timer?

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

I really can’t see what in that could turn the AC back on, which makes me think it must be something with your AC integration, or that you have multiple AC. Are you controlling the AC through an IR blaster or something?

Maybe try disabling two of your AC units and doing all testing with just one unit, to isolate some interaction between them?

For now I’ve only looked at this on mobile. My work above has worked fine for me without any intervention for over a year so I’d need to sit down and get familiar with it again. We are in the lovely mild period of year where we don’t need to heat or cool, so I’ve got no recent traces to refer to.

no alex, i control my climate entities trough toshiba integration in HA via wifi so i doubt it can be an interference between the 3 AC(static ip for each!)
when i’ve tested the automation the powered on Ac was just one.

here in south italy we have too a lovely temperature in this period, but i’m working to automate my AC for the hot summer that will come!

1 Like

That’s curious. There must be a simple explanation but I can’t see the cause in what you’ve provided above.

Next suggestion, disable the scripts and automation for now and make a very simple automation that turns off the AC when the timer finishes. Manually reset, start and end the timer from the developer > states page to trigger the automation and see if it still turns back on.

edit: i’ve tryed your suggestion, and it works! (started a configured 1 min timer via developer option. the timer finish event trigger this test automation(created via UI and not in yaml):

alias: test_ac_off_automation
description: ""
trigger:
  - platform: event
    event_type: timer.finished
    event_data:
      entity_id: timer.test_timer_ac
condition: []
action:
  - service: climate.turn_off
    metadata: {}
    data: {}
    target:
      entity_id: climate.haori_letto
mode: single

The powered on AC power off correctly and doesn’t revert on!
So i assume the problem in some conditions of automation! or script


original post:

thanks alex, i give it a try!
yesterday i’ve done a simle test in the automation, changing the service invoked by the event timer.finished from

action:
  - service: climate.turn_off
    data: {}
    target:
      entity_id: climate.haori_letto # your AC entity here
mode: single

to

action:
  - service: climate.set_hvac_mode
    target:
      entity_id:
        - climate.haori_letto
    data:
      hvac_mode: "off"
mode: single

both service power off correctly the AC if launched in developer option, but non by the automation.
In logbook i can see that each power off and successive power on are activated by the event timer.finished in air off automation!

Btw i’ll try to make a simple auotmation for power off with no condition after timer finishes, starting and stopping the timer via developer as you suggested!

Sorry for the slow reply - didn’t see your update. Have you made any other breakthroughs?

Great that you’ve been able to confirm that a simple timer and automation can turn off the AC and it stays off. That means it has to be something specific to your other timer and automation set up. Do you have any other automation or triggers related to that timer entity? I think you just need to step through each part of the automation one by one to isolate where this behaviour is coming from. You could try disabling the increment script, and testing the main timer when it ends, to isolate the script from the issue.

I know it’s not a great help, I’m not able to see the cause from my end though, so all we can do is search!

hi @alexeiw123 ,
i’ve done some other test! i’f i turn on the climate via lovelace climate card, and after 30 mins i call climate.turn_off service via developer tools the AC turn off and after a second come back on like with the automation!
This not happen when i call the service after a minute!

So i double the climate.turn_off call in my automation and now work!