Multi Zone Heating now with 7day scheduling

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