This Jinja template generates automations, groups and schedules for my heating system at home. I use Bosch Radiator Thermostat II valves and Zigbee temperature sensors.
The end result is generated automatically using the ha-jinja2config addon.
This Jinja template generates automations, groups and schedules for my heating system at home. I use Bosch Radiator Thermostat II valves and Zigbee temperature sensors.
The end result is generated automatically using the ha-jinja2config addon.
| {% set rooms = [ | |
| { | |
| 'name': 'Living Room', | |
| 'external_source': 'living_room_climate_temperature', | |
| 'radiators': [ 'living_room_radiator' ], | |
| 'temperature': { | |
| 'off': 14, | |
| 'on': 17 | |
| }, | |
| 'schedule': { | |
| 'weekdays': [ | |
| { 'from': '07:15', 'to': '22:00' } | |
| ], | |
| 'weekend': [ | |
| { 'from': '09:00', 'to': '23:00' } | |
| ] | |
| } | |
| }, | |
| { | |
| 'name': 'Bedroom', | |
| 'external_source': 'bedroom_climate_temperature', | |
| 'radiators': [ 'bedroom_radiator' ], | |
| 'temperature': { | |
| 'off': 14, | |
| 'on': 17 | |
| }, | |
| 'schedule': { | |
| 'weekdays': [ | |
| { 'from': '07:00', 'to': '08:00' }, | |
| { 'from': '22:00', 'to': '23:00' } | |
| ], | |
| 'friday': [ | |
| { 'from': '07:00', 'to': '08:00' }, | |
| { 'from': '22:30', 'to': '23:30' } | |
| ], | |
| 'weekend': [ | |
| { 'from': '09:00', 'to': '10:00' }, | |
| { 'from': '22:30', 'to': '23:30' } | |
| ], | |
| 'sunday': [ | |
| { 'from': '09:00', 'to': '10:00' }, | |
| { 'from': '22:00', 'to': '23:30' } | |
| ] | |
| } | |
| } | |
| ] %} | |
| {%- set ns = namespace(radiators=[]) -%} | |
| {%- for room in rooms -%} | |
| {%- set ns.radiators = ns.radiators + room.radiators -%} | |
| {%- endfor -%} | |
| automation heating: | |
| - alias: "Heating - Control" | |
| id: "heating_control" | |
| description: > | |
| Control the thermostats based on the schedule and home state. | |
| mode: restart | |
| triggers: | |
| - trigger: state | |
| entity_id: | |
| - binary_sensor.home_state_nearby_anyone | |
| {%- for room in rooms %} | |
| - schedule.{{ room.name|lower|replace(' ', '_') }}_heating{% endfor %} | |
| actions: | |
| {% for room in rooms %} | |
| - if: | |
| - condition: and | |
| conditions: | |
| - condition: state | |
| entity_id: binary_sensor.home_state_nearby_anyone | |
| state: "on" | |
| - condition: state | |
| entity_id: schedule.{{ room.name|lower|replace(' ', '_') }}_heating | |
| state: "on" | |
| then: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: "{{ "{{" }} state_attr('schedule.{{ room.name|lower|replace(' ', '_') }}_heating', 'temperature') {{ "}}" }}" | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.{{ room.name|lower|replace(' ', '_') }}_thermostat | |
| else: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: {{ room.temperature.off }} | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.{{ room.name|lower|replace(' ', '_') }}_thermostat | |
| {% endfor %} | |
| - alias: "Heating - External Temperature" | |
| id: "heating_set_external_temperature" | |
| description: > | |
| This will sync the temperature on the radiator valves to the external sensors. | |
| mode: restart | |
| triggers: | |
| {% for room in rooms %} | |
| - trigger: state | |
| entity_id: | |
| - "sensor.{{ room.external_source }}" | |
| variables: | |
| room: "{{ room.name|lower|replace(' ', '_') }}" | |
| radiators: {{ room.radiators }} | |
| external_source: "{{ room.external_source }}" | |
| external_sensor: "{{ "sensor." + room.external_source }}" | |
| schedule: "{{ room.name|lower|replace(' ', '_') }}_heating" | |
| - trigger: time | |
| at: input_datetime.{{ room.name|lower|replace(' ', '_') }}_heating_next_update | |
| variables: | |
| room: "{{ room.name|lower|replace(' ', '_') }}" | |
| radiators: {{ room.radiators }} | |
| external_source: "{{ room.external_source }}" | |
| external_sensor: "{{ "sensor." + room.external_source }}" | |
| schedule: "schedule.{{ room.name|lower|replace(' ', '_') }}_heating" | |
| {% endfor %} | |
| conditions: | |
| - condition: template | |
| value_template: > | |
| {{ "{{" }} (as_timestamp(now()) - as_timestamp(states.sensor[external_source].last_changed)) < 5400 {{ "}}" }} | |
| actions: | |
| - action: input_datetime.set_datetime | |
| target: | |
| entity_id: "{{ "{{" }} 'input_datetime.' + room + '_heating_next_update' {{ "}}" }}" | |
| data: | |
| timestamp: "{{ "{{" }} as_timestamp(now() + timedelta(minutes=29)) {{ "}}" }}" | |
| - action: number.set_value | |
| data: | |
| value: "{{ "{{" }} states(external_sensor) {{ "}}" }}" | |
| target: | |
| entity_id: "{{ "{{" }} radiators|map('regex_replace', '^', 'number.')|map('regex_replace', '$', '_remote_temperature')|list {{ "}}" }}" | |
| - alias: "Heating - Calibration" | |
| id: "heating_calibration" | |
| description: > | |
| When a radiator valve has reconnected and is waiting for a calbration, | |
| start the calibration process automatically. | |
| initial_state: true | |
| mode: restart | |
| triggers: | |
| {% for radiator in ns.radiators %} | |
| - trigger: state | |
| entity_id: sensor.{{ radiator }}_valve_adapt_status | |
| to: ready_to_calibrate | |
| {%- endfor %} | |
| actions: | |
| - action: switch.turn_on | |
| target: | |
| entity_id: "{{ "{{" }} trigger.entity_id|regex_replace('^sensor.', 'switch.')|regex_replace('_status$', '_process') {{ "}}" }}" | |
| - alias: "Heating - Error state" | |
| id: "heating_error" | |
| description: > | |
| Notify people whenever a radiator valve is in error state | |
| mode: restart | |
| triggers: | |
| {% for radiator in ns.radiators %} | |
| - trigger: state | |
| entity_id: sensor.{{ radiator }}_valve_adapt_status | |
| to: error | |
| {%- endfor %} | |
| actions: | |
| - action: notify.notify | |
| data: | |
| title: "Radiator valve error: {{ "{{" }} trigger.entity_id|regex_replace('^sensor.', '')|regex_replace('_status$', '') {{ "}}" }}" | |
| message: Please check the valve | |
| data: | |
| push: | |
| sound: | |
| critical: 1 | |
| group: | |
| {% for room in rooms %} | |
| {{ room.name|lower|replace(' ', '_') }}_thermostat: | |
| name: "{{ room.name }} Thermostat" | |
| entities: | |
| {% for radiator in room.radiators %} | |
| - climate.{{ radiator }}{% endfor %} | |
| {% endfor %} | |
| schedule: | |
| {% for room in rooms %} | |
| {{ room.name|lower|replace(' ', '_') }}_heating: | |
| name: "{{ room.name }}: Heating Schedule" | |
| {%- for day in ["monday", "tuesday", "wednesday", "thursday", "friday"] %} | |
| {{ day }}: | |
| {% for _block in room.schedule[day]|default(room.schedule.weekdays) %} | |
| - from: "{{ _block.from }}" | |
| to: "{{ _block.to }}" | |
| data: | |
| temperature: {{ _block.temperature|default(room.temperature.on) }}{% endfor %} | |
| {%- endfor %} | |
| {%- for day in ["saturday", "sunday"] %} | |
| {{ day }}: | |
| {% for _block in room.schedule[day]|default(room.schedule.weekend) %} | |
| - from: "{{ _block.from }}" | |
| to: "{{ _block.to }}" | |
| data: | |
| temperature: {{ _block.temperature|default(room.temperature.on) }}{% endfor %} | |
| {%- endfor %} | |
| {% endfor %} | |
| input_datetime: | |
| {% for room in rooms %} | |
| {{ room.name|lower|replace(' ', '_') }}_heating_next_update: | |
| name: "{{ room.name }}: Heating - Next forced update" | |
| has_date: true | |
| has_time: true | |
| {% endfor %} |
| automation heating: | |
| - alias: "Heating - Control" | |
| id: "heating_control" | |
| description: > | |
| Control the thermostats based on the schedule and home state. | |
| mode: restart | |
| triggers: | |
| - trigger: state | |
| entity_id: | |
| - binary_sensor.home_state_nearby_anyone | |
| - schedule.living_room_heating | |
| - schedule.bedroom_heating | |
| actions: | |
| - if: | |
| - condition: and | |
| conditions: | |
| - condition: state | |
| entity_id: binary_sensor.home_state_nearby_anyone | |
| state: "on" | |
| - condition: state | |
| entity_id: schedule.living_room_heating | |
| state: "on" | |
| then: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: "{{ state_attr('schedule.living_room_heating', 'temperature') }}" | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.living_room_thermostat | |
| else: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: 14 | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.living_room_thermostat | |
| - if: | |
| - condition: and | |
| conditions: | |
| - condition: state | |
| entity_id: binary_sensor.home_state_nearby_anyone | |
| state: "on" | |
| - condition: state | |
| entity_id: schedule.bedroom_heating | |
| state: "on" | |
| then: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: "{{ state_attr('schedule.bedroom_heating', 'temperature') }}" | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.bedroom_thermostat | |
| else: | |
| - action: climate.set_temperature | |
| data: | |
| temperature: 14 | |
| hvac_mode: heat | |
| target: | |
| entity_id: group.bedroom_thermostat | |
| - alias: "Heating - External Temperature" | |
| id: "heating_set_external_temperature" | |
| description: > | |
| This will sync the temperature on the radiator valves to the external sensors. | |
| mode: restart | |
| triggers: | |
| - trigger: state | |
| entity_id: | |
| - "sensor.living_room_climate_temperature" | |
| variables: | |
| room: "living_room" | |
| radiators: ["living_room_radiator"] | |
| external_source: "living_room_climate_temperature" | |
| external_sensor: "sensor.living_room_climate_temperature" | |
| schedule: "living_room_heating" | |
| - trigger: time | |
| at: input_datetime.living_room_heating_next_update | |
| variables: | |
| room: "living_room" | |
| radiators: ["living_room_radiator"] | |
| external_source: "living_room_climate_temperature" | |
| external_sensor: "sensor.living_room_climate_temperature" | |
| schedule: "schedule.living_room_heating" | |
| - trigger: state | |
| entity_id: | |
| - "sensor.bedroom_climate_temperature" | |
| variables: | |
| room: "bedroom" | |
| radiators: ["bedroom_radiator"] | |
| external_source: "bedroom_climate_temperature" | |
| external_sensor: "sensor.bedroom_climate_temperature" | |
| schedule: "bedroom_heating" | |
| - trigger: time | |
| at: input_datetime.bedroom_heating_next_update | |
| variables: | |
| room: "bedroom" | |
| radiators: ["bedroom_radiator"] | |
| external_source: "bedroom_climate_temperature" | |
| external_sensor: "sensor.bedroom_climate_temperature" | |
| schedule: "schedule.bedroom_heating" | |
| conditions: | |
| - condition: template | |
| value_template: > | |
| {{ (as_timestamp(now()) - as_timestamp(states.sensor[external_source].last_changed)) < 5400 }} | |
| actions: | |
| - action: input_datetime.set_datetime | |
| target: | |
| entity_id: "{{ 'input_datetime.' + room + '_heating_next_update' }}" | |
| data: | |
| timestamp: "{{ as_timestamp(now() + timedelta(minutes=29)) }}" | |
| - action: number.set_value | |
| data: | |
| value: "{{ states(external_sensor) }}" | |
| target: | |
| entity_id: "{{ radiators|map('regex_replace', '^', 'number.')|map('regex_replace', '$', '_remote_temperature')|list }}" | |
| - alias: "Heating - Calibration" | |
| id: "heating_calibration" | |
| description: > | |
| When a radiator valve has reconnected and is waiting for a calbration, | |
| start the calibration process automatically. | |
| initial_state: true | |
| mode: restart | |
| triggers: | |
| - trigger: state | |
| entity_id: sensor.living_room_radiator_valve_adapt_status | |
| to: ready_to_calibrate | |
| - trigger: state | |
| entity_id: sensor.bedroom_radiator_valve_adapt_status | |
| to: ready_to_calibrate | |
| actions: | |
| - action: switch.turn_on | |
| target: | |
| entity_id: "{{ trigger.entity_id|regex_replace('^sensor.', 'switch.')|regex_replace('_status$', '_process') }}" | |
| - alias: "Heating - Error state" | |
| id: "heating_error" | |
| description: > | |
| Notify people whenever a radiator valve is in error state | |
| mode: restart | |
| triggers: | |
| - trigger: state | |
| entity_id: sensor.living_room_radiator_valve_adapt_status | |
| to: error | |
| - trigger: state | |
| entity_id: sensor.bedroom_radiator_valve_adapt_status | |
| to: error | |
| actions: | |
| - action: notify.notify | |
| data: | |
| title: "Radiator valve error: {{ trigger.entity_id|regex_replace('^sensor.', '')|regex_replace('_status$', '') }}" | |
| message: Please check the valve | |
| data: | |
| push: | |
| sound: | |
| critical: 1 | |
| group: | |
| living_room_thermostat: | |
| name: "Living Room Thermostat" | |
| entities: | |
| - climate.living_room_radiator | |
| bedroom_thermostat: | |
| name: "Bedroom Thermostat" | |
| entities: | |
| - climate.bedroom_radiator | |
| schedule: | |
| living_room_heating: | |
| name: "Living Room: Heating Schedule" | |
| monday: | |
| - from: "07:15" | |
| to: "22:00" | |
| data: | |
| temperature: 17 | |
| tuesday: | |
| - from: "07:15" | |
| to: "22:00" | |
| data: | |
| temperature: 17 | |
| wednesday: | |
| - from: "07:15" | |
| to: "22:00" | |
| data: | |
| temperature: 17 | |
| thursday: | |
| - from: "07:15" | |
| to: "22:00" | |
| data: | |
| temperature: 17 | |
| friday: | |
| - from: "07:15" | |
| to: "22:00" | |
| data: | |
| temperature: 17 | |
| saturday: | |
| - from: "09:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| sunday: | |
| - from: "09:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| bedroom_heating: | |
| name: "Bedroom: Heating Schedule" | |
| monday: | |
| - from: "07:00" | |
| to: "08:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| tuesday: | |
| - from: "07:00" | |
| to: "08:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| wednesday: | |
| - from: "07:00" | |
| to: "08:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| thursday: | |
| - from: "07:00" | |
| to: "08:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:00" | |
| to: "23:00" | |
| data: | |
| temperature: 17 | |
| friday: | |
| - from: "07:00" | |
| to: "08:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:30" | |
| to: "23:30" | |
| data: | |
| temperature: 17 | |
| saturday: | |
| - from: "09:00" | |
| to: "10:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:30" | |
| to: "23:30" | |
| data: | |
| temperature: 17 | |
| sunday: | |
| - from: "09:00" | |
| to: "10:00" | |
| data: | |
| temperature: 17 | |
| - from: "22:00" | |
| to: "23:30" | |
| data: | |
| temperature: 17 | |
| input_datetime: | |
| living_room_heating_next_update: | |
| name: "Living Room: Heating - Next forced update" | |
| has_date: true | |
| has_time: true | |
| bedroom_heating_next_update: | |
| name: "Bedroom: Heating - Next forced update" | |
| has_date: true | |
| has_time: true |