Adjustable timer

My hot water cylinder is heated using a schedule, but sometimes I need to heat it up for an additional period. I wanted something that emulates the traditional “+1 hour” button that simple Sundial (or similar) controllers have.

After a lot of trial end error, I came up with the following solution:

image

Or when running:

image

Each press on +10 / +30 adds 10 / 30 minutes to the timer, the right most button cancels the timer. Obviously this can also work for lights, or anything really.

The frontend uses Paper Buttons Row, the backend uses a simple timer which is manipulated as inspired by Add time to an already running timer - #4 by 123.

Lovelace yaml:

type: entities
entities:
  - entity: timer.manual_hot_water
    name: Boost Hot Water
    extend_paper_buttons_row:
      buttons:
        - entity: script.manual_hot_water_add_time
          icon: mdi:timer-plus
          name: 10m
          tap_action:
            action: call-service
            service: script.manual_hot_water_add_time
            service_data:
              time: 10
          preset: mushroom
        - entity: script.manual_hot_water_add_time
          name: 30m
          icon: mdi:timer-plus
          tap_action:
            action: call-service
            service: script.manual_hot_water_add_time
            service_data:
              time: 30
          preset: mushroom
        - entity: script.manual_hot_water_add_time
          name: false
          icon: mdi:timer-cancel
          tap_action:
            action: call-service
            service: script.manual_hot_water_add_time
            service_data:
              time: 0
          preset: mushroom
          styles:
            button:
              margin-right: 0px
title: Heating
show_header_toggle: false

heating.yaml package:

timer:
  manual_hot_water:
    restore: true

automation heating:
  - id: hot_water_boost_off
    alias: Turn hot water off as boost requires
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.manual_hot_water
    action:
      - service: switch.turn_off
        target:
          entity_id: switch.boiler_l2

  - id: hot_water_boost_on
    alias: Turn hot water on as boost requires
    trigger:
    - platform: event
      event_type: timer.start
      event_data:
        entity_id: timer.manual_hot_water
    action: 
      - service: switch.turn_on
        target:
          entity_id: switch.boiler_l2

script:
  manual_hot_water_add_time:
    description: "Add x minutes to hot water timer, or cancel it by adding 0 minutes"
    fields:
      time:
        description: "How much time?"
        default: "30"
        selector:
          number:
            min: 0
            max: 120
    mode: queued
    sequence:
    - choose:
      - conditions:
        - condition: template
          value_template: "{{int(time) == 0}}"
        sequence:
          - service: timer.cancel
            target:
              entity_id: timer.manual_hot_water
          - service: automation.trigger
            target:
              entity_id: automation.turn_hot_water_off_as_boost_requires
      default:
        - service: timer.start
          data_template:
            entity_id: timer.manual_hot_water
            duration: >-
              {% set f = state_attr('timer.manual_hot_water', 'finishes_at') %}
              {{ int(time)*60 if f == none else (as_datetime(f) - now()).total_seconds() + int(time)*60 }}
        - service: automation.trigger
          target:
            entity_id: automation.turn_hot_water_on_as_boost_requires

I am also using this for heating our living room (which we only occasionally use, and therefore we don’t have a set schedule):

image

heating_living_room.yaml package:

input_number:
  living_room_heating_temperature:
    name: Living Room Heating Target Temperature
    min: 17
    max: 22
    step: 1
  living_room_min_temperature:
    name: Living Room Minimum Temperature
    min: 8
    max: 16
    step: 1

timer:
  living_room_heated:
    restore: true

automation:
  - id: living_room_heating_update_min
    alias: Update Living Room Heating Min Temp
    trigger:
      platform: state
      entity_id: input_number.living_room_min_temperature
    condition:
      condition: state
      entity_id: timer.living_room_heated
      state: "idle"
    action:
      - service: climate.set_temperature
        target:
          entity_id: climate.thermostat_living_room
        data:
          temperature: "{{ states('input_number.living_room_min_temperature') | int }}"

  - id: living_room_heating_update_heated
    alias: Update Living Room Heating Heated Temperature
    trigger:
      platform: state
      entity_id: input_number.living_room_heating_temperature
    condition:
      condition: state
      entity_id: timer.living_room_heated
      state: "active"
    action:
      - service: climate.set_temperature
        target:
          entity_id: climate.thermostat_living_room
        data:
          temperature: "{{ states('input_number.living_room_heating_temperature') | int }}"

  - id: living_room_heating_off
    alias: Turn Living Room Heating Off
    trigger:
      - platform: event
        event_type: timer.finished
        event_data:
          entity_id: timer.living_room_heated
    action:
      - service: climate.set_temperature
        target:
          entity_id: climate.thermostat_living_room
        data:
          temperature: "{{ states('input_number.living_room_min_temperature') | int }}"

  - id: living_room_heating_on
    alias: Turn Living Room Heating On
    trigger:
    - platform: event
      event_type: timer.start
      event_data:
        entity_id: timer.living_room_heated
    action: 
      - service: climate.set_temperature
        target:
          entity_id: climate.thermostat_living_room
        data:
          temperature: "{{ states('input_number.living_room_heating_temperature') | int }}"

script:
  update_living_room_heating_timer:
    description: "Add x minutes to timer, or cancel it by adding 0 minutes"
    fields:
      time:
        description: "How much time?"
        default: "30"
        selector:
          number:
            min: 0
            max: 120
    mode: queued
    sequence:
    - choose:
      - conditions:
        - condition: template
          value_template: "{{int(time) == 0}}"
        sequence:
          - service: timer.cancel
            target:
              entity_id: timer.living_room_heated
          - service: automation.trigger
            target:
              entity_id: automation.turn_living_room_heating_off
      default:
        - service: timer.start
          data_template:
            entity_id: timer.living_room_heated
            duration: >-
              {% set f = state_attr('timer.living_room_heated', 'finishes_at') %}
              {{ int(time)*60 if f == none else (as_datetime(f) - now()).total_seconds() + int(time)*60 }}
        - service: automation.trigger
          target:
            entity_id: automation.turn_living_room_heating_on

This works very well for me - let me know what you think and how it could be improved even further!

2 Likes