Multi Zone Heating now with 7day scheduling

Features

  • 7 Day timer
  • 8 Time Slots per day
  • Min Temperature / night temperature.
  • Multi Zone Heating
  • Boost timer for Central Heatring and Hot Water Immersion Heater
  • Solar Hot Water Monitoring
  • Auto Immersion Boost if shorfall in hot water from solar / CH at selected time

This is a continuation of my previous project found here: https://community.home-assistant.io/t/multi-zone-heating-with-scheduling/160280

I’d welcome any suggestions on improvments that could be made to this project.

6 Likes

LoveLace raw Code, depends on custom card, button-card.js https://github.com/custom-cards/button-card/blob/master/README.md

resources:
  - type: module
    url: /local/button-card.js
title: Home
views:
  - badges:
      - entity: sun.sun
        name: Day Light
      - entity: sensor.weather_temperature
        name: Outside °C
      - entity: sensor.time
    cards:
      - cards:
          - entity: climate.ha_thermo
            name: Boiler
            type: thermostat
          - entities:
              - entity: input_boolean.switch_boiler_timer
                name: Boost Central Heating
              - entity: input_number.boiler_timer
                name: Minutes 10 - 120
              - entity: input_number.temp_boost
                name: Boost Temperature °C
            type: entities
        type: vertical-stack
      - cards:
          - entity: sensor.upstairs_temp
            max: 30
            min: 0
            name: Upstairs Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
            unit: °C
          - entity: sensor.current_temp
            max: 30
            min: 0
            name: Downstairs Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
            unit: °C
          - entities:
              - entity: input_boolean.heating_master
                name: Heating Schedule On/Off
              - entity: input_number.t0_temp
                name: Min Night Temperature °C
            show_header_toggle: false
            type: entities
          - entities:
              - entity: switch.700574032462ab3b7e49
                icon: 'mdi:fire'
              - entity: sensor.current_temp
                icon: 'mdi:home-thermometer-outline'
                name: Downstairs
              - entity: sensor.upstairs_temp
                icon: 'mdi:home-thermometer-outline'
                name: Upstairs
              - entity: switch.bfd019f305520a0591hgke
                icon: 'mdi:hot-tub'
            name: Immersion
            show_name: true
            show_state: true
            type: glance
        type: vertical-stack
    icon: 'mdi:fire'
    path: default_view
    title: Central Heating
  - badges: []
    cards:
      - entity: climate.bf0dca95cb90411960fl8n
        name: Upstairs
        type: thermostat
      - entity: climate.ha_thermo
        name: Downstairs
        type: thermostat
      - cards:
          - entity: sensor.upstairs_temp
            max: 30
            min: 0
            name: Upstairs Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
            unit: °C
          - entity: sensor.current_temp
            max: 30
            min: 0
            name: Downstairs Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
            unit: °C
          - entity: sensor.temperature_sensor_20_0
            max: 30
            min: 0
            name: Kitchen Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
          - entity: sensor.temperature_sensor_21_0
            max: 30
            min: 0
            name: Front Room Temp
            severity:
              green: 18
              red: 23
              yellow: 20
            theme: default
            type: gauge
        title: Room Temperature
        type: vertical-stack
      - entity: climate.sitting_room_thermostat
        name: Sitting Room
        type: thermostat
    icon: 'mdi:home-thermometer'
    panel: false
    path: zones
    title: Zone Temperatures
  - badges: []
    cards:
      - entity: climate.hw_thermostat
        name: Immersion Heater
        type: thermostat
      - entities:
          - entity: input_boolean.switch_immersion_timer
          - entity: input_number.immersion_timer
            name: Minutes 10 - 120
          - entity: automation.immersion_on_time
            icon: 'mdi:hot-tub'
            name: Immersion Auto On
          - entity: input_datetime.immersion_auto_on
            icon: 'mdi:clock-outline'
            name: Immersion Auto On Time
          - entity: input_number.immersion_temp
            icon: 'mdi:thermometer'
        show_header_toggle: false
        type: entities
      - Name: Water Temp Sensors
        cards:
          - entity: sensor.temperature_sensor_32_0
            max: 100
            min: 0
            name: HW Taps Temp
            severity:
              green: 35
              red: 55
              yellow: 45
            theme: default
            type: gauge
          - entity: sensor.temperature_sensor_31_0
            max: 100
            min: 0
            name: HW Boiler Temp
            severity:
              green: 35
              red: 55
              yellow: 45
            theme: default
            type: gauge
          - entity: sensor.temperature_sensor_30_0
            max: 100
            min: 0
            name: HW Solar Temp
            severity:
              green: 35
              red: 55
              yellow: 45
            theme: default
            type: gauge
        title: Hot Water Temperature
        type: vertical-stack
      - entity: climate.hw_zone_thermostat
        type: thermostat
    path: hw
    title: HW
  - badges: []
    cards:
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p1
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p1
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p1
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p1
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p1
                icon: 'mdi:calendar-today'
                name: Thur
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p1
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p1
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p1_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t1_upstairs
                name: Upstairs Temp
              - entity: input_number.t1_temp
                name: Downstairs Temp
              - entity: input_number.t1_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t1_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p2_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 1
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p2
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p2
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p2
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p2
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p2
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p2
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p2
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p2_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t2_upstairs
                name: Upstairs Temp
              - entity: input_number.t2_temp
                name: Downstairs Temp
              - entity: input_number.t2_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t2_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p3_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 2
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p3
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p3
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p3
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p3
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p3
                icon: 'mdi:calendar-today'
                name: ThurS
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p3
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p3
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p3_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t3_upstairs
                name: Upstairs Temp
              - entity: input_number.t3_temp
                name: Downstairs Temp
              - entity: input_number.t3_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t3_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p4_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 3
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p4
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p4
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p4
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p4
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p4
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p4
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p4
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p4_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t4_upstairs
                name: Upstairs Temp
              - entity: input_number.t4_temp
                name: Downstairs Temp
              - entity: input_number.t4_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t4_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p5_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 4
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p5
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p5
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p5
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p5
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p5
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p5
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p5
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p5_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t5_upstairs
                name: Upstairs Temp
              - entity: input_number.t5_temp
                name: Downstairs Temp
              - entity: input_number.t5_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t5_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p6_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 5
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p6
                icon: 'mdi:calendar-today'
                name: Sunday
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p6
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p6
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p6
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p6
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p6
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p6
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p6_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t6_upstairs
                name: Upstairs Temp
              - entity: input_number.t6_temp
                name: Downstairs Temp
              - entity: input_number.t6_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t6_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p7_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 6
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p7
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p7
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p7
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p7
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p7
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p7
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p7
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p7_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t7_upstairs
                name: Upstairs Temp
              - entity: input_number.t7_temp
                name: Downstairs Temp
              - entity: input_number.t7_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t7_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
              - entity: input_datetime.p8_on
                name: End
            show_header_toggle: false
            type: entities
        title: Heating Schedule 7
        type: vertical-stack
      - cards:
          - cards:
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_sunday_p8
                icon: 'mdi:calendar-today'
                name: Sun
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_monday_p8
                icon: 'mdi:calendar-today'
                name: Mon
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_tuesday_p8
                icon: 'mdi:calendar-today'
                name: Tues
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_wednesday_p8
                icon: 'mdi:calendar-today'
                name: Wed
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_thursday_p8
                icon: 'mdi:calendar-today'
                name: Thurs
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_friday_p8
                icon: 'mdi:calendar-today'
                name: Fri
                type: 'custom:button-card'
              - color: 'rgb(66, 134, 244)'
                color_type: card
                entity: input_boolean.switch_saturday_p8
                icon: 'mdi:calendar-today'
                name: Sat
                type: 'custom:button-card'
            type: horizontal-stack
          - entities:
              - entity: input_datetime.p8_on
                icon: 'mdi:clock-start'
                name: Begin
              - entity: input_number.t8_upstairs
                name: Upstairs Temp
              - entity: input_number.t8_temp
                name: Downstairs Temp
              - entity: input_number.t8_sitting_room
                name: Sitting Room Temp
              - entity: input_number.t8_hot_water
                icon: 'mdi:thermometer'
                name: Hot Water Temp
            show_header_toggle: false
            type: entities
        title: Heating Schedule 8
        type: vertical-stack
    icon: 'mdi:clock'
    path: ''
    title: schedule
  - badges: []
    cards:
      - entities:
          - entity: sensor.temperature_sensor_30_0
            name: Solar Temperature
          - entity: sensor.temperature_sensor_31_0
            name: Boiler Temperature
          - entity: sensor.temperature_sensor_32_0
            name: Taps Temperature
          - entity: switch.bfd019f305520a0591hgke
          - entity: switch.206012432cf432d22b78
        hours_to_show: 24
        refresh_interval: 0
        title: Hot Water
        type: history-graph
      - entities:
          - entity: switch.700574032462ab3b7e49
          - entity: sensor.current_temp
            name: Downstairs
          - entity: sensor.upstairs_temp
            name: Upstairs
        hours_to_show: 24
        refresh_interval: 0
        title: Zone Temperature
        type: history-graph
      - entities:
          - entity: sensor.temperature_sensor_20_0
            name: Kitchen
          - entity: sensor.temperature_sensor_21_0
            name: Sitting Room
          - entity: group.sitting_room
        hours_to_show: 24
        refresh_interval: 0
        title: Room Temperatures
        type: history-graph
      - entities:
          - entity: sensor.weather_temperature
        hours_to_show: 24
        refresh_interval: 0
        title: Outside Temperature
        type: history-graph
    icon: 'mdi:chart-areaspline'
    path: graphs
    title: Graphs




Configuration.yaml is now getting quite big!

#--------------============-Heating Schedule version 2.1-----------------------------------------    


#--------------Create Boiler thermostat-------------------------------
#virtual thermostat using sensor value from downstairs thermostat and boiler switch.
climate:
- platform: generic_thermostat
  name: HA thermo
  heater: switch.700574032462ab3b7e49 #Boiler Switch
  target_sensor: sensor.current_temp #Boiler room sensor currently reading downstairs zone thermostat
  min_temp: 10
  max_temp: 24
  ac_mode: false
  # target_temp: 17
  cold_tolerance: 0.3
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  # initial_hvac_mode: "off"
  # away_temp: 12
  precision: 0.1
  
  
#Immersion Thermostat
- platform: generic_thermostat
  name: HW thermostat
  heater: switch.bfd019f305520a0591hgke #Immersion Switch
  target_sensor: sensor.temperature_sensor_31_0 #HW Boiler sensor
  min_temp: 0
  max_temp: 65
  ac_mode: false
  # target_temp: 17
  cold_tolerance: 0.3
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  # initial_hvac_mode: "off"
  # away_temp: 12
  precision: 0.1
  
  #HW Zone Thermostat
- platform: generic_thermostat
  name: HW zone thermostat
  heater: switch.206012432cf432d22b78
  target_sensor: sensor.temperature_sensor_31_0 #HW Boiler sensor
  min_temp: 0
  max_temp: 65
  ac_mode: false
  # target_temp: 17
  cold_tolerance: 0.3
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  # initial_hvac_mode: "off"
  # away_temp: 12
  precision: 0.1
  
    #Sitting Room Thermostat
- platform: generic_thermostat
  name: Sitting Room thermostat
  heater: group.sitting_room
  target_sensor: sensor.temperature_sensor_21_0 #Sitting Room temp Sensor
  min_temp: 0
  max_temp: 24
  ac_mode: false
  # target_temp: 17
  cold_tolerance: 0.3
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  # initial_hvac_mode: "off"
  # away_temp: 12
  precision: 0.1
  
binary_sensor:  
  - platform: workday
    country: 'IE'
    name: 'workday_today'
    workdays: [mon, tue, wed, thu, fri, sat]
    excludes: [sun, holiday]

#---------------------------input temperatures--------------------------
input_number:  # input number 

#-------------------------Zone Temperatures---------------------------------
  t1_upstairs:
    name: T1 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 20
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t1_sitting_room:
    name: T1 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline 
    
  t1_hot_water:
    name: T1 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t2_upstairs:
    name: T2 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t2_sitting_room:
    name: T2 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t2_hot_water:
    name: T2 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t3_upstairs:
    name: T3 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t3_sitting_room:
    name: T3 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t3_hot_water:
    name: T3 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t4_upstairs:
    name: T4 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t4_sitting_room:
    name: T4 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t4_hot_water:
    name: T4 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t5_upstairs:
    name: T5 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t5_sitting_room:
    name: T5 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t5_hot_water:
    name: T5 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t6_upstairs:
    name: T^ Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t6_sitting_room:
    name: T6 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t6_hot_water:
    name: T6 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t7_upstairs:
    name: T7 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 20
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t7_sitting_room:
    name: T7 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t7_hot_water:
    name: T7 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  

  t8_upstairs:
    name: T8 Upstairs
    min: 10
    max: 24
    step: 0.5
    #initial: 19
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t8_sitting_room:
    name: T8 Sitting Room
    min: 10
    max: 24
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t8_hot_water:
    name: T8 Hot Water
    min: 10
    max: 55
    step: 0.5
    #initial: 47
    mode: box
    icon: mdi:home-thermometer-outline  


#----------------night temp/ min temp----------------------------------------
  t0_temp:  
    name: T night
    min: 10
    max: 24
    step: 0.5
    #initial: 16
    mode: box
    icon: mdi:home-thermometer     
    
#-----------------Boiler Program Temperatures---------------------------------
  t1_temp:  # temperature preset T1
    name: °C
    min: 10
    max: 25
    step: 0.5 
    #initial: 20
    mode: box
    icon: mdi:home-thermometer-outline
    
  t2_temp:  # temperature preset T2
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 18
    mode: box
    icon: mdi:home-thermometer-outline

  t3_temp:  # temperature preset T3
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 20
    mode: box
    icon: mdi:home-thermometer-outline

  t4_temp:  # temperature preset T4
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 18
    mode: box
    icon: mdi:home-thermometer-outline
    
  t5_temp:  # temperature preset T5
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 20 
    mode: box
    icon: mdi:home-thermometer-outline
    
  t6_temp:  # temperature preset T6
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 18
    mode: box
    icon: mdi:home-thermometer-outline
    
  t7_temp:  # temperature preset T7
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 21
    mode: box
    icon: mdi:home-thermometer-outline
    
  t8_temp:  # temperature preset T8
    name: °C
    min: 10
    max: 25
    step: 0.5
    #initial: 18
    mode: box
    icon: mdi:home-thermometer-outline    
    
    
#---------------------immersion heater--------------------------------
  immersion_temp:
    name: Immersion °C
    min: 30
    max: 65
    step: 0.5
    #initial: 45
    mode: box
    icon: mdi:hot-tub
    
  immersion_timer:  # set time for immersion heater
    name: Minutes
    #initial: 60
    min: 10
    max: 120
    step: 1 
    mode: box
    icon: mdi:timer-sand


#--------------------Boost timer settings-----------------------------------
  boiler_timer:  # set time for boost heating start
    name: Minutes
    #initial: 60
    min: 10
    max: 120
    step: 1 
    mode: box
    icon: mdi:timer-sand
    
  temp_boost:  # temperature preset boost
    name: Temp Boost
    min: 10
    max: 25
    step: 0.5
    #initial: 20
    mode: box
    icon: mdi:home-thermometer-outline
    
#-----------------boolean switches-------------    
input_boolean:
  heating_master: # if ON enable heating week timer
    name: Heating Auto timer
    icon: mdi:av-timer
    
  switch_boiler_timer: # if ON start heating for xxx minutes (input_number.boiler_timer). Override week timer.
    name: Boost Timer
    initial: off
    icon: mdi:radiator
    
  switch_immersion_timer:
    name: Immersion timer
    initial: off
    icon: mdi:hot-tub
    
#-----------------boolean weekday/weekend switches-------------    

  switch_monday_p1:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p1:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p1:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p1:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p1:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p1:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p1:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p2:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p2:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p2:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p2:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p2:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p2:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p2:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p3:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p3:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p3:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p3:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p3:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p3:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p3:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p4:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p4:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p4:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p4:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p4:
    name: Friday
    #initial: on
    icon: mdi:calendar-today

  switch_saturday_p4:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p4:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p5:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p5:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p5:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p5:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p5:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p5:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p5:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p6:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p6:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p6:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p6:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p6:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p6:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p6:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
 
  switch_monday_p7:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p7:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p7:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p7:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p7:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p7:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p7:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
  switch_monday_p8:
    name: Monday
    #initial: on
    icon: mdi:calendar-today

  switch_tuesday_p8:
    name: Tuesday
    #initial: on
    icon: mdi:calendar-today

  switch_wednesday_p8:
    name: Wednesday
    #initial: on
    icon: mdi:calendar-today

  switch_thursday_p8:
    name: Thursday
    #initial: on
    icon: mdi:calendar-today

  switch_friday_p8:
    name: Friday
    #initial: on
    icon: mdi:calendar-today
    
  switch_saturday_p8:
    name: Saturday
    #initial: on
    icon: mdi:calendar-today
    
  switch_sunday_p8:
    name: Sunday
    #initial: on
    icon: mdi:calendar-today
    
#-----------------------------sensors----------------------------------------------------------------
#weather sensor    
sensor:
  - platform: yr
    name: Weather
    forecast: 0
    monitored_conditions:
      - temperature
#time sensor
  - platform: time_date
    display_options:
      - 'time'
      - 'date'
      - 'date_time'
      - 'date_time_iso'
      - 'time_date'
      - 'time_utc'
      - 'beat'

#program 8 time slots for weekday, saturday and sunday/holiday
  - platform: template
    sensors:
      heating_program:
        friendly_name: "Heating Program"
        value_template: >-  # ok 141119
         {% set t = states('sensor.time') %}
            {% if is_state('binary_sensor.workday_today', 'on') %}
              {% if now().weekday() in (0,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_monday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_monday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_monday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_monday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_monday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_monday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_monday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_monday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (1,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_tuesday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_tuesday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_tuesday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_tuesday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_tuesday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_tuesday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_tuesday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_tuesday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (2,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_wednesday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_wednesday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_wednesday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_wednesday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_wednesday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_wednesday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_wednesday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_wednesday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (3,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_thursday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_thursday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_thursday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_thursday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_thursday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_thursday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_thursday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_thursday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (4,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_friday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_friday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_friday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_friday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_friday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_friday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_friday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_friday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% else %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_saturday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_saturday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_saturday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_saturday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_saturday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_saturday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_saturday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_saturday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% endif %}
            {% else %}
              {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_sunday_p1', 'on')  %} p1
              {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_sunday_p2', 'on')  %} p2
              {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_sunday_p3', 'on')  %} p3 
              {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_sunday_p4', 'on')  %} p4
              {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_sunday_p5', 'on')  %} p5
              {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_sunday_p6', 'on')  %} p6
              {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_sunday_p7', 'on')  %} p7
              {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_sunday_p8', 'on') %} p8
              {% else %} p0
              {% endif %}
            {% endif %}         



#define temperature sensors                
  - platform: template  
    sensors:
      current_temp:
        value_template: "{{ states.climate.bfb4fbcb25305e7371a3yn.attributes.current_temperature }}" #read downstairs temp as a sensor
        unit_of_measurement: '°C'
      upstairs_temp:
        value_template: "{{ states.climate.bf0dca95cb90411960fl8n.attributes.current_temperature }}" #read upstairs temp as a sensor
        unit_of_measurement: '°C'
      hvac_temperature_knob:
        value_template: "{{ states.climate.ha_thermo.attributes.temperature }}" #read boler stat temp as a sensor
        unit_of_measurement: '°C'
        

        
#---------------------------------Time inputs------------------------------------------------------        
input_datetime:
  p1_on:
    name: P1
    has_time: true
    #initial: '06:00:00'
    icon: mdi:clock-start   
    
  p2_on:
    name: P2
    has_time: true
    #initial: '09:00:00'
    icon: mdi:clock-end     
    
  p3_on:
    name: P3
    has_time: true
    #initial: '11:00:00'
    icon: mdi:clock-end       
  
  p4_on:
    name: P4
    has_time: true
    #initial: '13:00:00'
    icon: mdi:clock-end
    
  p5_on:
    name: P5
    has_time: true
    #initial: '15:00:00'
    icon: mdi:clock-end  
    
  p6_on:
    name: P6
    has_time: true
    #initial: '17:00:00'
    icon: mdi:clock-end  
    
  p7_on:
    name: P6
    has_time: true
    #initial: '19:00:00'
    icon: mdi:clock-end 
    
  p8_on:
    name: P6
    has_time: true
    #initial: '22:00:00'
    icon: mdi:clock-end     


  immersion_auto_on:
    name: Imerrsion Auto On 
    has_time: true
    #initial: '19:00:00'
    icon: mdi:clock-end

Automations.yaml

#-------------------Boost Automation-------------------------
- alias: boiler timed on
  trigger:
  - platform: state
    entity_id: input_boolean.switch_boiler_timer
    to: 'on'
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: '{{ states.input_number.temp_boost.state }}'
  id: 26cdd0087f934e38b4cdf050e6df5031
- alias: boiler timed off
  trigger:
  - platform: state
    entity_id: input_boolean.switch_boiler_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_boiler_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.boiler_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_boiler_timer
  - service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: '{{ states.input_number.t0_temp.state }}'
  id: e08c0d734ef24fcc97e04643a71b60b1
#---------------------------Week timer Automation----------------------
- alias: weektimer_program
  trigger:
  - platform: state
    entity_id: sensor.heating_program
  condition:
  - condition: state
    entity_id: input_boolean.heating_master
    state: 'on'
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: >-
           {% if is_state('sensor.heating_program', 'p1') %} {{ states.input_number.t1_temp.state }}
           {% elif is_state('sensor.heating_program', 'p2') %} {{ states.input_number.t2_temp.state }}
           {% elif is_state('sensor.heating_program', 'p3') %} {{ states.input_number.t3_temp.state }}
           {% elif is_state('sensor.heating_program', 'p4') %} {{ states.input_number.t4_temp.state }}
           {% elif is_state('sensor.heating_program', 'p5') %} {{ states.input_number.t5_temp.state }}
           {% elif is_state('sensor.heating_program', 'p6') %} {{ states.input_number.t6_temp.state }}
           {% elif is_state('sensor.heating_program', 'p7') %} {{ states.input_number.t7_temp.state }}
           {% elif is_state('sensor.heating_program', 'p8') %} {{ states.input_number.t8_temp.state }}
           {% elif is_state('sensor.heating_program', 'p0') %} {{ states.input_number.t0_temp.state }}
           {% endif %}  
  - service: climate.set_temperature
    data_template:           
      entity_id: climate.hw_zone_thermostat
      temperature: >-
           {% if is_state('sensor.heating_program', 'p1') %} {{ states.input_number.t1_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p2') %} {{ states.input_number.t2_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p3') %} {{ states.input_number.t3_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p4') %} {{ states.input_number.t4_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p5') %} {{ states.input_number.t5_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p6') %} {{ states.input_number.t6_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p7') %} {{ states.input_number.t7_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p8') %} {{ states.input_number.t8_hot_water.state }}
           {% elif is_state('sensor.heating_program', 'p0') %} {{ states.input_number.t0_temp.state }}
           {% endif %}
  - service: climate.set_temperature
    data_template:           
      entity_id: climate.sitting_room_thermostat
      temperature: >-
           {% if is_state('sensor.heating_program', 'p1') %} {{ states.input_number.t1_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p2') %} {{ states.input_number.t2_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p3') %} {{ states.input_number.t3_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p4') %} {{ states.input_number.t4_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p5') %} {{ states.input_number.t5_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p6') %} {{ states.input_number.t6_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p7') %} {{ states.input_number.t7_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p8') %} {{ states.input_number.t8_sitting_room.state }}
           {% elif is_state('sensor.heating_program', 'p0') %} {{ states.input_number.t0_temp.state }}
           {% endif %}
  id: 47141d0a7f8d420885cd15bc3cbb5888
- alias: temp_lock
  trigger:
  - platform: state
    entity_id: sensor.hvac_temperature_knob
  - platform: state
    entity_id: input_boolean.heating_master
    to: 'on'
  condition:
  - condition: state
    entity_id: input_boolean.switch_boiler_timer
    state: 'off'
  - condition: state
    entity_id: input_boolean.heating_master
    state: 'on'
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: >-
           {% if is_state('sensor.heating_program', 'p1') %} {{ states.input_number.t1_temp.state }}
           {% elif is_state('sensor.heating_program', 'p2') %} {{ states.input_number.t2_temp.state }}
           {% elif is_state('sensor.heating_program', 'p3') %} {{ states.input_number.t3_temp.state }}
           {% elif is_state('sensor.heating_program', 'p4') %} {{ states.input_number.t4_temp.state }}
           {% elif is_state('sensor.heating_program', 'p5') %} {{ states.input_number.t5_temp.state }}
           {% elif is_state('sensor.heating_program', 'p6') %} {{ states.input_number.t6_temp.state }}
           {% elif is_state('sensor.heating_program', 'p7') %} {{ states.input_number.t7_temp.state }}
           {% elif is_state('sensor.heating_program', 'p8') %} {{ states.input_number.t8_temp.state }}
           {% elif is_state('sensor.heating_program', 'p0') %} {{ states.input_number.t0_temp.state }}
           {% endif %}  
  id: 47141d0a7f8d420885cd15bc3cbb5889
#-------------------------------zone valve protection---------------------------------------
#------------Zone valves Deenergize when heat is off to prolong life of valves---------------
- id: '1577612881345'
  alias: valves on
  description: ''
  trigger:
  - entity_id: switch.700574032462ab3b7e49
    from: 'off'
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.bf0dca95cb90411960fl8n
      temperature: >-
           {% if is_state('sensor.heating_program', 'p1') %} {{ states.input_number.t1_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p2') %} {{ states.input_number.t2_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p3') %} {{ states.input_number.t3_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p4') %} {{ states.input_number.t4_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p5') %} {{ states.input_number.t5_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p6') %} {{ states.input_number.t6_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p7') %} {{ states.input_number.t7_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p8') %} {{ states.input_number.t8_upstairs.state }}
           {% elif is_state('sensor.heating_program', 'p0') %} {{ states.input_number.t0_temp.state }}
           {% endif %}  
  - service: climate.set_temperature
    data_template:
      entity_id: climate.bfb4fbcb25305e7371a3yn
      temperature: '23'
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data:
      hvac_mode: "heat"
  - service: climate.set_hvac_mode
    entity_id: climate.sitting_room_thermostat
    data:
      hvac_mode: "heat"
- id: '1577612972092'
  alias: valves off
  description: ''
  trigger:
  - entity_id: switch.700574032462ab3b7e49
    from: 'on'
    platform: state
    to: 'off'
  condition: []
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.bf0dca95cb90411960fl8n
      temperature: '{{ states.input_number.t0_temp.state }}'
  - service: climate.set_temperature
    data_template:
      entity_id: climate.bfb4fbcb25305e7371a3yn
      temperature: '{{ states.input_number.t0_temp.state }}'
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data:
      hvac_mode: "off"
  - service: climate.set_hvac_mode
    entity_id: climate.sitting_room_thermostat
    data:
      hvac_mode: "off"
      
#---------------------Immersion Timer Automation------------------------------------
- id: '1578520268091'
  alias: Immersion Timer
  description: ''
  trigger:
  - entity_id: input_boolean.switch_immersion_timer
    platform: state
    to: 'on'
  condition: []
  action:
    - service: climate.set_hvac_mode
      entity_id: climate.hw_thermostat
      data_template:
        hvac_mode: "heat"
    - service: climate.set_temperature
      data_template:
        entity_id: climate.hw_thermostat
        temperature: '{{ states.input_number.immersion_temp.state }}'

- id: '1578521662871'
  alias: Immersion timed off
  trigger:
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.immersion_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_immersion_timer
  - service: climate.set_hvac_mode
    entity_id: climate.hw_thermostat
    data:
      hvac_mode: "off"
- id: '1578653513704'
  alias: Immersion On Time
  description: ''
  trigger:
  - platform: template
    value_template: "{{ states.sensor.time.state == states.input_datetime.immersion_auto_on.state[0:5] }}"
  condition: []
  action:
  - entity_id: input_boolean.switch_immersion_timer
    service: input_boolean.turn_on

Great project @emaherx, thanks for sharing it.
It’s exactly what I’m after and now being summer (well irish summer :slight_smile: ) I have have necessary time to gather all the components and program it before autumn/winter gets here.

The house like yours, is very well insulated (150mm insulation on external walls and air tight) so I would like to achieve a better temperature regulation rather that cost savings, but that’s a bonus.
The heating is split into 3 zones: downstairs, upstairs and hot water controlled by Horstmann H37XL 3 channel programmer and 2 dumb thermostats. Currently the programmer has 3 schedules / day for heating with the thermostats adjusting the temperature. The hot water is set to come on with 2 schedules: 40 minutes in the morning and 1 hour in the evening to create the necessary hot water.
The only thing I did so far was to install a Sonoff TH16 with 4 temp sensors on the water tank to monitor temperature, in future I would like to use this to control the water heating.

Do you mind sharing what hardware components you used in your setup i.e. controller, thermostats, TRV’s etc. ?

Thanks,
Julian

@yulasinio I’m glad you like it. I’m some what familiar with the Irish Summer :smiley:

I’ve nearly lost track at this stage as to what hardware I have.

Raspberry Pi 3 running HA off of a USB thumb drive. (SD cards are a disaster)
Initial build used mostly Cheap Tuya Devices Smart Thermostats and generic Switches. These Devices controlled the Upstairs and Downstairs Zones and the boiler, later I added one for Immersion Heater

But at this stage I’m moving away from anything that requires cloud connections, There seems to have been an API change this week which is causing havok with the responsiveness of anything Tuya based. Thankfully its summer time or the wife would probably kill me.

As the system has expanded, I’ve changed to using Sensors and relays based on MySensors.org, first ones I purchased from PiHome.eu including their gateway. I’ve also beeen experimenting with ESPHome based sensors and have made a Sensor to meassure the oil in the oil tank.

I’m going to replace all of the Tuya Devices with either MySensors.org relay switches or shelly switches.

I use these for TRV’s along with a shelly switch

1 Like

Did you replace the programmer or you are bypassing using the relays?
Think I’ll go for Z-wave 3 channel controller, 2 x Z-wave thermostats and Z-wave TRV’s. Will be more expensive but I hope will be a stable setup to keep the family happy :slight_smile:

I had no programmer only a mechanical time switch and 3 separate thermostats for zones and hot water. So I replaced them with similar WiFi enabled devices. Funny enough the DIY parts of my setup have been rock solid, the weak link is cloud dependence on the commercial products.

It really doesn’t matter what devices you go with in the end, you can still take whatever parts of my project or anyone elses that you like which is the great thing about Home Assistant. Z wave based products are ideal as there is no cloud dependence.

Great job, but why is end time fx on schedule 1 the same as start time on next schedule (schedule 2)

br Thyge.

Thanks,

The end time of any schedule is by definition the start of the next.
If I change either then they both change.
I thought it makes each schedule easier to read by having a beginning and an end .

It would be easy just to remove the end time altogether, if you’d prefer a similar layout with just start times.

I’ve simplified the controls with just heating thermostats and system stats on the first page

I’ve added all hot water controls and scheduling to a single page. (Battery is gone in solar sensor, which is why it has flat lined in the picture :smiley: )

I’ve removed hot water from schedule and just added a single auto on time per day, as this suits the solar system better, I heat water in the morning during the winter, using solar to maintain temp as much as possible during the day, and in the summer months do the opposite with hot water heating only coming on if there hasn’t been enough solar during the day.

The biggest changes I’ve made is assigning more stats that can call the boiler. If the main upstairs, downstairs or hot water stats call for heat then the boiler will start and if none are calling for heat then the boiler stops.

- id: '1594755819541'
  alias: Boiler On
  description: Turn On Boiler If any master thermostat calls for heat
  trigger:
  - entity_id: input_boolean.switch_upstairs
    from: 'off'
    platform: state
    to: 'on'
  - entity_id: input_boolean.switch_downstairs
    from: 'off'
    platform: state
    to: 'on'
  - entity_id: switch.hw_zone_valve
    from: 'off'
    platform: state
    to: 'on'
  condition: []
  action:
  - data: {}
    entity_id: switch.boiler
    service: switch.turn_on
    
    
- id: '1594756361977'
  alias: Boiler off
  description: Turn Off Boiler if no master stat is calling for heat
  trigger:
  - entity_id: input_boolean.switch_downstairs
    from: 'on'
    platform: state
    to: 'off'
  - entity_id: input_boolean.switch_upstairs
    from: 'on'
    platform: state
    to: 'off'
  - entity_id: switch.hw_zone_valve
    from: 'on'
    platform: state
    to: 'off'
  condition:
  - condition: and
    conditions:
    - condition: state
      entity_id: input_boolean.switch_upstairs
      state: 'off'
    - condition: state
      entity_id: input_boolean.switch_downstairs
      state: 'off'
    - condition: state
      entity_id: switch.hw_zone_valve
      state: 'off'
  action:
  - data: {}
    entity_id: switch.boiler
    service: switch.turn_off

I could add all stats to this process, but I would have to break how my system can still work manually in the event of a Home Assistant failure.

I’ve also gotten all Tuya Devices, 2 thermostats and a number of switches working with LocalTuya custom component. So there is no cloud dependence in any part of my Heating.

My current Hot Water Automations for both the Boiler and Immersion Heater, includes Auto on time and boost function. The auto on time essentially just calls the boost function.

id: '1578520268091'
  alias: Immersion Timer
  description: Immersion Boost on for preset time
  trigger:
  - entity_id: input_boolean.switch_immersion_timer
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.hw_thermostat
    data_template:
      hvac_mode: heat
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hw_thermostat
      temperature: '{{ states.input_number.immersion_temp.state }}'
      
- id: '1578521662871'
  alias: Immersion timed off
  description: Immersion Boost off after preset time
  trigger:
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.immersion_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_immersion_timer
  - service: climate.set_hvac_mode
    entity_id: climate.hw_thermostat
    data:
      hvac_mode: 'off'
      
      
- id: '1578520268092'
  alias: HW Boiler Timer 
  description: HW Boiler Boost on for preset time
  trigger:
  - entity_id: input_boolean.switch_hw_timer
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data_template:
      hvac_mode: heat
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hw_zone_thermostat
      temperature: '{{ states.input_number.immersion_temp.state }}'
      
- id: '1578521662872'
  alias: HW Boiler timed off after preset time
  description: HW Boiler Boost off
  trigger:
  - platform: state
    entity_id: input_boolean.switch_hw_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_hw_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.immersion_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_hw_timer
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data:
      hvac_mode: 'off'
      
- id: '1578653513704'
  alias: Immersion On Time
  description: Immersion Automatic On Time
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.immersion_auto_on.state[0:5]
      }}'
  condition: []
  action:
  - entity_id: input_boolean.switch_immersion_timer
    service: input_boolean.turn_on
    
- id: '1578653513705'
  alias: HW On Time
  description: HW Automatic On Time
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.immersion_auto_on.state[0:5]
      }}'
  condition: []
  action:
  - entity_id: input_boolean.switch_hw_timer
    service: input_boolean.turn_on

Automation to turn on/off TRV’s when boiler is on/off.

- id: '1577612881345'
  alias: valves on
  description: TRV valves on, energise where nessacery on boiler start
  trigger:
  - entity_id: switch.boiler
    from: 'off'
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.sitting_room_thermostat
    data:
      hvac_mode: heat
      
- id: '1577612972092'
  alias: valves off
  description: TRV Valves off to save being energised unnecessarily
  trigger:
  - entity_id: switch.boiler
    from: 'on'
    platform: state
    to: 'off'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.sitting_room_thermostat
    data:
      hvac_mode: 'off'

current heating schedule automation

- alias: weektimer_program
  description: read values from weekt schedule and apply to zone thermostats
  trigger:
  - platform: state
    entity_id: sensor.heating_program
  condition:
  - condition: state
    entity_id: input_boolean.heating_master
    state: 'on'
  action:
  - service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: '{% if is_state(''sensor.heating_program'', ''p1'') %} {{ states.input_number.t1_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p2'') %} {{ states.input_number.t2_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p3'') %} {{ states.input_number.t3_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p4'') %} {{ states.input_number.t4_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p5'') %} {{ states.input_number.t5_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p6'') %} {{ states.input_number.t6_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p7'') %} {{ states.input_number.t7_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p8'') %} {{ states.input_number.t8_temp.state
        }} {% elif is_state(''sensor.heating_program'', ''p0'') %} {{ states.input_number.t0_temp.state
        }} {% endif %}  '
  - service: climate.set_temperature
    data_template:
      entity_id: climate.sitting_room_thermostat
      temperature: '{% if is_state(''sensor.heating_program'', ''p1'') %} {{ states.input_number.t1_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p2'') %} {{ states.input_number.t2_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p3'') %} {{ states.input_number.t3_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p4'') %} {{ states.input_number.t4_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p5'') %} {{ states.input_number.t5_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p6'') %} {{ states.input_number.t6_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p7'') %} {{ states.input_number.t7_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p8'') %} {{ states.input_number.t8_sitting_room.state
        }} {% elif is_state(''sensor.heating_program'', ''p0'') %} {{ states.input_number.t0_temp.state
        }} {% endif %}'
  - service: climate.set_temperature
    data_template:
      entity_id: climate.upstairs
      temperature: '{% if is_state(''sensor.heating_program'', ''p1'') %} {{ states.input_number.t1_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p2'') %} {{ states.input_number.t2_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p3'') %} {{ states.input_number.t3_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p4'') %} {{ states.input_number.t4_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p5'') %} {{ states.input_number.t5_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p6'') %} {{ states.input_number.t6_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p7'') %} {{ states.input_number.t7_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p8'') %} {{ states.input_number.t8_upstairs.state
        }} {% elif is_state(''sensor.heating_program'', ''p0'') %} {{ states.input_number.t0_temp.state
        }} {% endif %}  '
  id: 47141d0a7f8d420885cd15bc3cbb5888

This Automation I needed to create in order to get my Tuya Thermostats to display correctly. It basically maps the buggy Tuya stats to 2 Virtual Generic thermostats. Probably won’t be required for most people but I’ll include it anyway just in case it helps some one else out.
Thermostats are Saswell T19WHB-7-RF-WIFI(TY)

They were setup with LocalTuya https://github.com/rospogrigio/localtuya
Also need additional Climate file climate.py saved in the same folder as the localtuya custom component. https://github.com/renat85/localtuya_thermostat/tree/master/localtuya

- id: '1593289562360'
  alias: Downstairs Stat to virtual map
  description: map physical controls onto virtual thermostat
  trigger:
  - entity_id: sensor.downstairs_target_temp
    platform: state
  condition: []
  action:
  - data: {}
    service: climate.set_temperature
    data_template:
      entity_id: climate.ha_thermo
      temperature: '{{ states.climate.downstairs.attributes.temperature }}'
      
- id: '1593289562361'
  alias: virtual stat to Downstairs map
  description: map virtual controls onto physical thermostat
  trigger:
  - entity_id: sensor.hvac_temperature_knob
    platform: state
  condition: []
  action:
  - data: {}
    service: climate.set_temperature
    data_template:
      entity_id: climate.downstairs
      temperature: '{{ states.climate.ha_thermo.attributes.temperature }}'
      
- id: '1593289562362'
  alias: Upstairs Stat to virtual map
  description: map physical controls onto virtual thermostat
  trigger:
  - entity_id: sensor.upstairs_target_temp
    platform: state
  condition: []
  action:
  - data: {}
    service: climate.set_temperature
    data_template:
      entity_id: climate.ha_upstairs
      temperature: '{{ states.climate.upstairs.attributes.temperature }}'
      
- id: '1593289562363'
  alias: virtual stat to Upstairs map
  description: map virtual controls onto physical thermostat
  trigger:
  - entity_id: sensor.ha_upstairs_temperature_knob
    platform: state
  condition: []
  action:
  - data: {}
    service: climate.set_temperature
    data_template:
      entity_id: climate.upstairs
      temperature: '{{ states.climate.ha_upstairs.attributes.temperature }}'

The climate.py file also needed some minor modification.
I think it was just /2 needed to be changed to /10 to display temp correctly, but I’ll include the whole thing just in case.

"""
Simple platform to control **SOME** Tuya switch devices.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.tuya/
"""

import logging
import asyncio

from homeassistant.components.climate.const import (
    ATTR_PRESET_MODE,
    ATTR_PRESET_MODES,
    SUPPORT_TARGET_TEMPERATURE,
    SUPPORT_PRESET_MODE,
    HVAC_MODE_HEAT,
    HVAC_MODE_OFF,
    HVAC_MODE_AUTO,
    PRESET_AWAY,
    PRESET_NONE
)


from homeassistant.components.climate import (PLATFORM_SCHEMA,  ENTITY_ID_FORMAT, ClimateEntity)

from homeassistant.const import (CONF_NAME, CONF_HOST, CONF_ID, PRECISION_WHOLE, TEMP_CELSIUS, TEMP_FAHRENHEIT , ATTR_TEMPERATURE)

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from time import time
from time import sleep
from threading import Lock

REQUIREMENTS = ['pytuya==7.0.4']

_LOGGER = logging.getLogger(__name__)

CONF_DEVICE_ID = 'device_id'
CONF_LOCAL_KEY = 'local_key'
CONF_MIN_TEMP = 'min_temp'
CONF_MAX_TEMP = 'max_temp'
CONF_PROTOCOL_VERSION = 'protocol_version'

DEVICE_TYPE = 'climate'

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
    vol.Optional(CONF_NAME): cv.string,
    vol.Required(CONF_HOST): cv.string,
    vol.Required(CONF_DEVICE_ID): cv.string,
    vol.Required(CONF_LOCAL_KEY): cv.string,
    vol.Optional(CONF_MIN_TEMP): vol.Coerce(float),
    vol.Optional(CONF_MAX_TEMP): vol.Coerce(float),
    vol.Optional(CONF_PROTOCOL_VERSION): vol.Coerce(float)
})

async def async_setup_platform(hass, config, async_add_entities, discovery_info=None):
    """Set up of the Tuya switch."""
    from . import pytuya
    
    name = config.get(CONF_NAME)
    dev_id = config.get(CONF_DEVICE_ID)
    host = config.get(CONF_HOST)
    local_key = config.get(CONF_LOCAL_KEY)
    min_temp = config.get(CONF_MIN_TEMP)
    max_temp = config.get(CONF_MAX_TEMP)
    protocol_version = config.get(CONF_PROTOCOL_VERSION)
    
    climate = []
    
    climate_device = TuyaCache(
        pytuya.OutletDevice(
            config.get(CONF_DEVICE_ID),
            config.get(CONF_HOST),
            config.get(CONF_LOCAL_KEY) 
        ),
        protocol_version
    )
    
    climate.append(
        TuyaClimate(
            climate_device,
            config.get(CONF_NAME),
            None, 
            None, 
            None,
            None, 
            TEMP_CELSIUS, 
            min_temp, 
            max_temp,
            protocol_version
        )
    )


    async_add_entities(climate)

class TuyaCache:
    
    def __init__(self, device, protocol_version):
        """Initialize the cache."""
        self._cached_status = ''
        self._cached_status_time = 0
        self._device = device
        self._protocol_version = protocol_version
        self._lock = Lock()

    def __get_status(self):
        for i in range(5):
            try:
                self._device.set_version(self._protocol_version)
                status = self._device.status()
                _LOGGER.debug("Debug LocalTuya: " + str(status))
                return status
            except ConnectionError:
                if i+1 == 5:
                    _LOGGER.warning("Failed to update status")
                    raise ConnectionError("Failed to update status.")

    def set_status(self, state, switchid):
        self._cached_status = ''
        self._cached_status_time = 0
        return self._device.set_status(state, switchid)

    def status(self):
        """Get state of Tuya switch and cache the results."""
        self._lock.acquire()
        try:
           now = time()
           _LOGGER.debug("UPDATING status")
           self._device.set_version(self._protocol_version)
           self._cached_status = self.__get_status()
           self._cached_status_time = time()
           return self._cached_status
        finally:
            self._lock.release()



class TuyaClimate(ClimateEntity):
    """Representation of a Tuya switch."""

    def __init__(self, device, name, target_temperature, current_temperature, hvac_mode, preset_mode, unit_of_measurement, min_temp, max_temp, protocol_version):
        """Initialize the Tuya switch."""
        self._device = device
        self._name = name
        self._lock = Lock()
        self._target_temperature = target_temperature
        self._current_temperature = current_temperature
        self._hvac_mode = hvac_mode
        self._preset_mode = preset_mode
        self._unit_of_measurement = unit_of_measurement
        self._min_temp = min_temp
        self._max_temp = max_temp
        self._support_flags = SUPPORT_TARGET_TEMPERATURE | SUPPORT_PRESET_MODE
        self._temp_precision = 0.5
        self._hvac_modes = [HVAC_MODE_HEAT, HVAC_MODE_AUTO, HVAC_MODE_OFF]
        self._preset_modes = [PRESET_AWAY, PRESET_NONE]
        status = self._device.status()

    @property
    def min_temp(self):
        """Return the minimum temperature."""
        if self._min_temp:
            return self._min_temp

        # get default temp from super class
        return super().min_temp

    @property
    def max_temp(self):
        """Return the maximum temperature."""
        if self._max_temp:
            return self._max_temp

        # Get default temp from super class
        return super().max_temp

    @property
    def hvac_modes(self):
        """Return the list of available operation modes."""
        return self._hvac_modes
        
    @property
    def name(self):
        """Get name of Tuya switch."""
        return self._name

    @property
    def current_temperature(self):
        """Return the sensor temperature."""
        return self._current_temperature

    @property
    def hvac_mode(self):
        """Return current operation."""
        return self._hvac_mode

    @property
    def preset_modes(self):
        """Return the list of available preset modes."""
        return self._preset_modes

    @property
    def preset_mode(self):
        """Return preset status."""
        return self._preset_mode

    @property
    def target_temperature(self):
        """Return the temperature we try to reach."""
        return self._target_temperature
        
    @property
    def temperature_unit(self):
        """Return the unit of measurement."""
        return self._unit_of_measurement
        
    @property
    def supported_features(self):
        """Return the list of supported features."""
        return self._support_flags

    async def async_turn_on(self, **kwargs):
        """Turn Tuya switch on."""
        self._lock.acquire()
        self._device.set_status(True, '1')
        self._lock.release()

    async def async_turn_off(self, **kwargs):
        """Turn Tuya switch off."""
        self._lock.acquire()
        self._device.set_status(False, '1')
        self._lock.release()
    
    async def async_set_temperature(self, **kwargs):
        while True:
           try:
               self._lock.acquire()
               temperature = int(float(kwargs[ATTR_TEMPERATURE])*10)
               _LOGGER.debug("Set Temperature: " + str(temperature))
               if ATTR_TEMPERATURE in kwargs:
                   self._device.set_status(temperature, '2')
                   sleep(1)
               self._lock.release()
           except:
               _LOGGER.warning("Set Temperature Retry")
               continue
           break
             
    async def async_set_hvac_mode(self, hvac_mode):
        """Set operation mode."""
        self._lock.acquire()
        if hvac_mode == HVAC_MODE_HEAT:
            self._device.set_status(True, '1') 
        elif hvac_mode == HVAC_MODE_OFF:
            self._device.set_status(False, '1') 
        else:
            _LOGGER.error("Unrecognized operation mode: %s", hvac_mode)
            return
        sleep(1)
        self.schedule_update_ha_state()
        self._lock.release()
    

    async def async_update(self):
        """Get state of Tuya switch."""
        _LOGGER.debug("UPDATING")
        try:
           status = self._device.status()
           self._target_temperature = float(status['dps']['2']) /10
           self._current_temperature = float(status['dps']['3']) /10
           self._state = status['dps']['1']
           
           auto_manual = status['dps']['126']
           eco_mode = status['dps']['101']
           on_off = status['dps']['1']
           _LOGGER.debug("Device: " + str(status['devId']))
           
           if on_off == False:
              self._hvac_mode = HVAC_MODE_OFF
           if on_off == True and auto_manual == '0':
              self._hvac_mode = HVAC_MODE_AUTO
           if on_off == True and auto_manual == '1':
              self._hvac_mode = HVAC_MODE_HEAT
           if eco_mode == True:
              self._preset_mode = HVAC_MODE_HEAT
           else:
              self._preset_mode = HVAC_MODE_HEAT
        except:
            _LOGGER.debug("Update Fail, maybe device busy")

This is the heating configuration yaml

#-------------------------Heating Schedule version 3.0-----------------------------------------    


#--------------Create Boiler thermostat-------------------------------
#virtual thermostat using sensor value from downstairs thermostat and boiler switch.
climate:
- platform: generic_thermostat
  name: HA thermo
  heater: input_boolean.switch_downstairs #Boiler Switch
  target_sensor: sensor.current_temp #Boiler room sensor currently reading downstairs zone thermostat
  min_temp: 10
  max_temp: 24
  ac_mode: false
  cold_tolerance: 0.8
  hot_tolerance: 0.5
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  precision: 0.1
  
#upstairs virtual stat
- platform: generic_thermostat
  name: HA upstairs
  heater: input_boolean.switch_upstairs #Boiler Switch
  target_sensor: sensor.upstairs_temp #Boiler room sensor currently reading downstairs zone thermostat
  min_temp: 10
  max_temp: 24
  ac_mode: false
  cold_tolerance: 0.8
  hot_tolerance: 0.5
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  precision: 0.1
  
#Immersion Thermostat
- platform: generic_thermostat
  name: HW thermostat
  heater: switch.immersion #Immersion Switch
  target_sensor: sensor.temperature_sensor_31_0 #HW Boiler sensor
  min_temp: 0
  max_temp: 65
  ac_mode: false
  cold_tolerance: 1
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  initial_hvac_mode: "off"
  precision: 0.1
  
  #HW Zone Thermostat
- platform: generic_thermostat
  name: HW zone thermostat
  heater: switch.hw_zone_valve
  target_sensor: sensor.temperature_sensor_31_0 #HW Boiler sensor
  min_temp: 0
  max_temp: 65
  ac_mode: false
  cold_tolerance: 1
  hot_tolerance: 0
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  initial_hvac_mode: "off"
  precision: 0.1
  
    #Sitting Room Thermostat
- platform: generic_thermostat
  name: Sitting Room thermostat
  heater: group.sitting_room
  target_sensor: sensor.temperature_sensor_21_0 #Sitting Room temp Sensor
  min_temp: 0
  max_temp: 24
  ac_mode: false
  cold_tolerance: 0.3
  hot_tolerance: 0.3
  min_cycle_duration:
    seconds: 5
  keep_alive:
    minutes: 1
  precision: 0.1
  
binary_sensor:  
  - platform: workday
    country: 'IE'
    name: 'workday_today'
    workdays: [mon, tue, wed, thu, fri, sat]
    excludes: [sun, holiday]

#---------------------------input temperatures--------------------------
input_number:  # input number 

#-------------------------Zone Temperatures---------------------------------
  t1_upstairs:
    name: T1 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t1_sitting_room:
    name: T1 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline 
    
  t2_upstairs:
    name: T2 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t2_sitting_room:
    name: T2 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t3_upstairs:
    name: T3 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t3_sitting_room:
    name: T3 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t4_upstairs:
    name: T4 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t4_sitting_room:
    name: T4 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t5_upstairs:
    name: T5 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t5_sitting_room:
    name: T5 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t6_upstairs:
    name: T^ Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t6_sitting_room:
    name: T6 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t7_upstairs:
    name: T7 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  

  t7_sitting_room:
    name: T7 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t8_upstairs:
    name: T8 Upstairs
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    
  t8_sitting_room:
    name: T8 Sitting Room
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline  
    

#----------------night temp/ min temp----------------------------------------
  t0_temp:  
    name: T night
    min: 10
    max: 24
    step: 0.5
    mode: box
    icon: mdi:home-thermometer     
    
#-----------------Boiler Program Temperatures---------------------------------
  t1_temp:  # temperature preset T1
    name: °C
    min: 10
    max: 25
    step: 0.5 
    mode: box
    icon: mdi:home-thermometer-outline
    
  t2_temp:  # temperature preset T2
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline

  t3_temp:  # temperature preset T3
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline

  t4_temp:  # temperature preset T4
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline
    
  t5_temp:  # temperature preset T5
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline
    
  t6_temp:  # temperature preset T6
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline
    
  t7_temp:  # temperature preset T7
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline
    
  t8_temp:  # temperature preset T8
    name: °C
    min: 10
    max: 25
    step: 0.5
    mode: box
    icon: mdi:home-thermometer-outline    
    
    
#---------------------immersion heater--------------------------------
  immersion_temp:
    name: Immersion °C
    min: 30
    max: 65
    step: 0.5
    mode: box
    icon: mdi:hot-tub
    
  immersion_timer:  # set time for immersion heater
    name: Minutes
    min: 10
    max: 120
    step: 1 
    mode: box
    icon: mdi:timer-sand


#-----------------boolean switches-------------    
input_boolean:
  heating_master: # if ON enable heating week timer
    name: Heating Auto timer
    icon: mdi:av-timer
    
    
  switch_immersion_timer:
    name: Immersion timer
    initial: off
    icon: mdi:hot-tub
    
  switch_hw_timer:
    name: HW timer
    initial: off
    icon: mdi:hot-tub
    
  switch_upstairs:
    name: upstairs boolean
  
  switch_downstairs:
    name: downstsirs boolean  
    
#-----------------boolean weekday/weekend switches-------------    

  switch_monday_p1:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p1:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p1:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p1:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p1:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p1:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p1:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p2:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p2:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p2:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p2:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p2:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p2:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p2:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p3:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p3:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p3:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p3:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p3:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p3:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p3:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p4:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p4:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p4:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p4:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p4:
    name: Friday
    icon: mdi:calendar-today

  switch_saturday_p4:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p4:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p5:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p5:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p5:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p5:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p5:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p5:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p5:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p6:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p6:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p6:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p6:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p6:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p6:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p6:
    name: Sunday
    icon: mdi:calendar-today
 
  switch_monday_p7:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p7:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p7:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p7:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p7:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p7:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p7:
    name: Sunday
    icon: mdi:calendar-today
    
  switch_monday_p8:
    name: Monday
    icon: mdi:calendar-today

  switch_tuesday_p8:
    name: Tuesday
    icon: mdi:calendar-today

  switch_wednesday_p8:
    name: Wednesday
    icon: mdi:calendar-today

  switch_thursday_p8:
    name: Thursday
    icon: mdi:calendar-today

  switch_friday_p8:
    name: Friday
    icon: mdi:calendar-today
    
  switch_saturday_p8:
    name: Saturday
    icon: mdi:calendar-today
    
  switch_sunday_p8:
    name: Sunday
    icon: mdi:calendar-today
    
#-----------------------------sensors----------------------------------------------------------------
#weather sensor    
sensor:
  - platform: template
    sensors:
      outside_temperature:
        friendly_name: "Outside Temperature"
        unit_of_measurement: '°C'
        value_template: "{{ state_attr('weather.home', 'temperature') }}"
#time sensor
  - platform: time_date
    display_options:
      - 'time'
      - 'date'
      - 'date_time'
      - 'date_time_iso'
      - 'time_date'
      - 'time_utc'
      - 'beat'

#program 8 time slots for weekday, saturday and sunday/holiday
  - platform: template
    sensors:
      heating_program:
        friendly_name: "Heating Program"
        value_template: >-  # ok 141119
         {% set t = states('sensor.time') %}
            {% if is_state('binary_sensor.workday_today', 'on') %}
              {% if now().weekday() in (0,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_monday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_monday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_monday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_monday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_monday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_monday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_monday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_monday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (1,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_tuesday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_tuesday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_tuesday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_tuesday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_tuesday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_tuesday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_tuesday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_tuesday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (2,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_wednesday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_wednesday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_wednesday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_wednesday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_wednesday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_wednesday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_wednesday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_wednesday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (3,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_thursday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_thursday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_thursday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_thursday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_thursday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_thursday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_thursday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_thursday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% elif now().weekday() in (4,) %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_friday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_friday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_friday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_friday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_friday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_friday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_friday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_friday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% else %}
                {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_saturday_p1', 'on')  %} p1
                {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_saturday_p2', 'on')  %} p2
                {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_saturday_p3', 'on')  %} p3 
                {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_saturday_p4', 'on')  %} p4
                {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_saturday_p5', 'on')  %} p5
                {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_saturday_p6', 'on')  %} p6
                {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_saturday_p7', 'on')  %} p7
                {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_saturday_p8', 'on') %} p8
                {% else %} p0
                {% endif %}
              {% endif %}
            {% else %}
              {%   if states('input_datetime.p1_on') <= t <= states('input_datetime.p2_on') and is_state('input_boolean.switch_sunday_p1', 'on')  %} p1
              {% elif states('input_datetime.p2_on') <= t <= states('input_datetime.p3_on') and is_state('input_boolean.switch_sunday_p2', 'on')  %} p2
              {% elif states('input_datetime.p3_on') <= t <= states('input_datetime.p4_on') and is_state('input_boolean.switch_sunday_p3', 'on')  %} p3 
              {% elif states('input_datetime.p4_on') <= t <= states('input_datetime.p5_on') and is_state('input_boolean.switch_sunday_p4', 'on')  %} p4
              {% elif states('input_datetime.p5_on') <= t <= states('input_datetime.p6_on') and is_state('input_boolean.switch_sunday_p5', 'on')  %} p5
              {% elif states('input_datetime.p6_on') <= t <= states('input_datetime.p7_on') and is_state('input_boolean.switch_sunday_p6', 'on')  %} p6
              {% elif states('input_datetime.p7_on') <= t <= states('input_datetime.p8_on') and is_state('input_boolean.switch_sunday_p7', 'on')  %} p7
              {% elif states('input_datetime.p8_on') <= t < '23:59' and is_state('input_boolean.switch_sunday_p8', 'on') %} p8
              {% else %} p0
              {% endif %}
            {% endif %}         



#define temperature sensors                
  - platform: template  
    sensors:
      current_temp:
        value_template: "{{ states.climate.downstairs.attributes.current_temperature }}" #read downstairs temp as a sensor
        unit_of_measurement: '°C'
      downstairs_target_temp:
        value_template: "{{ states.climate.downstairs.attributes.temperature }}" #read downstairs temp as a sensor
        unit_of_measurement: '°C'
      upstairs_temp:
        value_template: "{{ states.climate.upstairs.attributes.current_temperature }}" #read upstairs temp as a sensor
        unit_of_measurement: '°C'
      upstairs_target_temp:
        value_template: "{{ states.climate.upstairs.attributes.temperature }}" #read upstairs set temp as a sensor
        unit_of_measurement: '°C'
      hvac_temperature_knob:
        value_template: "{{ states.climate.ha_thermo.attributes.temperature }}" #read boiler stat temp as a sensor
        unit_of_measurement: '°C'
      ha_upstairs_temperature_knob:
        value_template: "{{ states.climate.ha_upstairs.attributes.temperature }}" #read upstairs stat temp as a sensor
        unit_of_measurement: '°C'
              
#define oil sensors                
  - platform: template  
    sensors:
      oil_level:
        unit_of_measurement: '%'
        value_template: "{{ 120-states('sensor.distance_sensor_44_1')|float}}"


        
#---------------------------------Time inputs------------------------------------------------------        
input_datetime:
  p1_on:
    name: P1
    has_time: true
    icon: mdi:clock-start   
    
  p2_on:
    name: P2
    has_time: true
    icon: mdi:clock-end     
    
  p3_on:
    name: P3
    has_time: true
    icon: mdi:clock-end       
  
  p4_on:
    name: P4
    has_time: true
    icon: mdi:clock-end
    
  p5_on:
    name: P5
    has_time: true
    icon: mdi:clock-end  
    
  p6_on:
    name: P6
    has_time: true
    icon: mdi:clock-end  
    
  p7_on:
    name: P6
    has_time: true
    icon: mdi:clock-end 
    
  p8_on:
    name: P6
    has_time: true
    icon: mdi:clock-end     


  immersion_auto_on:
    name: Imerrsion Auto On 
    has_time: true
    icon: mdi:clock-end
1 Like

I’ve recently changed electricity plans and now use night rate electricity for the immersion so I’m working on a weather forecast automation to limit immersion heater use if the following day will be sunny to maximise benefit from solar panels. I have also put my complete HA config on GitHub.

Weather Configuration yaml

#---------------------weather sensors----------------------------------------------------------
sensor:
  - platform: template
    sensors:
      outside_temperature:
        friendly_name: "Outside Temperature"
        unit_of_measurement: '°C'
        value_template: "{{ state_attr('weather.home_2', 'temperature') }}"
        
        
        
#--------------------------Read Weather Data from Open Weather Map API---------------------------------
  - platform: rest
    name: openweather_report
    json_attributes:
      - current
      - daily
      - hourly
    value_template: "{{ value_json['current']['dt'] | timestamp_custom('%Y-%m-%d %H:%M', true) }}"
    #https://api.openweathermap.org/data/2.5/onecall?lat=my_latitude=my_longitude=MY_API_KEY&units=metric&lang=en
    resource: !secret openweather
    scan_interval: 3600
  - platform: template
    sensors:
#--------------------------------------------Today/Tonight Temp---------------------------------
      openweather_temp_day_today:
        value_template: "{{ state_attr('sensor.openweather_report', 'daily')[0].temp.max }}"
        friendly_name: "Today Max Temperature"
        unit_of_measurement: '°C'
      openweather_temp_night_today:
        value_template: "{{ state_attr('sensor.openweather_report', 'daily')[0].temp.night }}"
        friendly_name: "Tonight Min Temperature"
        unit_of_measurement: '°C'
#--------------------------------------------Cloud cover Hourly-----------------------------------
      openweather_cloud_cover_now:
        friendly_name: "Current Cloud Cover"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[0].clouds }}"
      openweather_cloud_cover_1:
        friendly_name: "Cloud Cover in 1 Hour"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[1].clouds }}"
      openweather_cloud_cover_2:
        friendly_name: "Cloud Cover in 2 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[2].clouds }}"
      openweather_cloud_cover_3:
        friendly_name: "Cloud Cover in 3 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[3].clouds }}"
      openweather_cloud_cover_4:
        friendly_name: "Cloud Cover in 4 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[4].clouds }}"
      openweather_cloud_cover_5:
        friendly_name: "Cloud Cover in 5 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[5].clouds }}"
      openweather_cloud_cover_6:
        friendly_name: "Cloud Cover in 6 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[6].clouds }}"
      openweather_cloud_cover_7:
        friendly_name: "Cloud Cover in 7 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[7].clouds }}"
      openweather_cloud_cover_8:
        friendly_name: "Cloud Cover in 8 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[8].clouds }}"
      openweather_cloud_cover_9:
        friendly_name: "Cloud Cover in 9 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[9].clouds }}"
      openweather_cloud_cover_10:
        friendly_name: "Cloud Cover in 10 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[10].clouds }}"
      openweather_cloud_cover_11:
        friendly_name: "Cloud Cover in 11 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[11].clouds }}"
      openweather_cloud_cover_12:
        friendly_name: "Cloud Cover in 12 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[12].clouds }}"
      openweather_cloud_cover_13:
        friendly_name: "Cloud Cover in 13 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[13].clouds }}"
      openweather_cloud_cover_14:
        friendly_name: "Cloud Cover in 14 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[14].clouds }}"
      openweather_cloud_cover_15:
        friendly_name: "Cloud Cover in 15 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[15].clouds }}"
      openweather_cloud_cover_16:
        friendly_name: "Cloud Cover in 16 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[16].clouds }}"
      openweather_cloud_cover_17:
        friendly_name: "Cloud Cover in 17 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[17].clouds }}"
      openweather_cloud_cover_18:
        friendly_name: "Cloud Cover in 18 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[18].clouds }}"
      openweather_cloud_cover_19:
        friendly_name: "Cloud Cover in 19 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[19].clouds }}"
      openweather_cloud_cover_20:
        friendly_name: "Cloud Cover in 20 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[20].clouds }}"
      openweather_cloud_cover_21:
        friendly_name: "Cloud Cover in 21 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[21].clouds }}"
      openweather_cloud_cover_22:
        friendly_name: "Cloud Cover in 22 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[22].clouds }}"
      openweather_cloud_cover_23:
        friendly_name: "Cloud Cover in 23 Hours"
        unit_of_measurement: '%'
        value_template: "{{ state_attr('sensor.openweather_report', 'hourly')[23].clouds }}"
#----------------------------------Wind Today Tomorrow------------------------------------------
      openweather_wind_today:
        friendly_name: "Wind Speed Today"
        unit_of_measurement: 'mps'
        value_template: "{{ state_attr('sensor.openweather_report', 'daily')[0].wind_speed }}"
      openweather_wind_tomorrow:
        friendly_name: "Wind Speed Tomorrow"
        unit_of_measurement: 'mps'
        value_template: "{{ state_attr('sensor.openweather_report', 'daily')[1].wind_speed }}"
        
        
        
template:
  - sensor:
      - name: "Cloud forecast Average"
        unit_of_measurement: "%"
        state: >
          
          {% set plus9h = states('sensor.openweather_cloud_cover_9') | float %}
          {% set plus10h = states('sensor.openweather_cloud_cover_10') | float %}
          {% set plus11h = states('sensor.openweather_cloud_cover_11') | float %}
          {% set plus12h = states('sensor.openweather_cloud_cover_12') | float %}
          {% set plus13h = states('sensor.openweather_cloud_cover_13') | float %}
          {% set plus14h = states('sensor.openweather_cloud_cover_14') | float %}
          {% set plus15h = states('sensor.openweather_cloud_cover_15') | float %}
          {% set plus16h = states('sensor.openweather_cloud_cover_16') | float %}
          
          {{ ((plus9h + plus10h + plus11h + plus12h + plus13h + plus14h + plus15h + plus16h ) / 8) | round(0, default=0) }}
          

Hot Water Automation yaml

#--------------------------------Hot Water from Boiler and Immersion------------------
#------------------------------------ Immersion Boost Timer----------------------------
- id: 'immersion boost 1'
  alias: Immersion Timer
  description: Immersion Boost on for preset time
  trigger:
  - entity_id: input_boolean.switch_immersion_timer
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.hw_thermostat
    data_template:
      hvac_mode: heat
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hw_thermostat
      temperature: '{{ states.input_number.immersion_temp.state }}'
      
- id: 'immersion boost 2'
  alias: Immersion timed off
  description: Immersion Boost off after preset time
  trigger:
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_immersion_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.immersion_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_immersion_timer
  - service: climate.set_hvac_mode
    entity_id: climate.hw_thermostat
    data:
      hvac_mode: 'off'

#---------------------------Boiler Hot Water Boost Timer --------------------------
- id: 'hot water boost 1'
  alias: HW Boiler Timer
  description: HW Boiler Boost on for preset time
  trigger:
  - entity_id: input_boolean.switch_hw_timer
    platform: state
    to: 'on'
  condition: []
  action:
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data_template:
      hvac_mode: heat
  - service: climate.set_temperature
    data_template:
      entity_id: climate.hw_zone_thermostat
      temperature: '{{ states.input_number.immersion_temp.state }}'
      
- id: 'hot water boost 2'
  alias: HW Boiler timed off after preset time
  description: HW Boiler Boost off
  trigger:
  - platform: state
    entity_id: input_boolean.switch_hw_timer
    to: 'off'
  - platform: state
    entity_id: input_boolean.switch_hw_timer
    to: 'on'
    for:
      minutes: '{{ states.input_number.immersion_timer.state | int }}'
  action:
  - service: input_boolean.turn_off
    entity_id: input_boolean.switch_hw_timer
  - service: climate.set_hvac_mode
    entity_id: climate.hw_zone_thermostat
    data:
      hvac_mode: 'off'
      
      
#----------------Imersion automatic on time, calls boost automation at selected time----------------
- id: 'immersion on'
  alias: Immersion On Time
  description: Immersion Automatic On Time
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.immersion_auto_on.state[0:5]
      }}'
  condition: []
  action:
  - entity_id: input_boolean.switch_immersion_timer
    service: input_boolean.turn_on

#------------Boiler Hot Water automatic on time, calls boost automation at selected time-----------------
- id: 'hot water on'
  alias: HW On Time
  description: HW Automatic On Time
  trigger:
  - platform: template
    value_template: '{{ states.sensor.time.state == states.input_datetime.hw_auto_on.state[0:5]
      }}'
  condition: []
  action:
  - entity_id: input_boolean.switch_hw_timer
    service: input_boolean.turn_on
  mode: single


#--------Work in progress, skip immersion Auto on, if forecast for clear skys, optimise solar water heating-------
- id: 'weather based immersion'
  alias: Smart Weather Based Immersion On
  description: ''
  trigger:
  - platform: time
    at: 00:10:00
  condition: []
  action:
  - service_template: "{% if states('sensor.cloud_forecast_average') | float < 20\
      \ %}\n  homeassistant.turn_off\n{% else %}\n  homeassistant.turn_on\n{% endif\
      \ %}\n"
    entity_id: automation.immersion_on_time
  mode: single

Automation and Config yaml files have also been broken down into smaller easier to read files.

1 Like