Hi all,
after nearly 2 weeks of reading, fixing, reading and fixing again, I want to try my luck here…
After a lot (I really mean A LOT) of troubleshooting, I finally wanted to create my own heating automation for my Aqara E1 TRVs. I managed to create a blueprint that creates an automation. However, I cannot get this automation to run.
My troubleshooting so far makes me believe, that something is wrong with the use of variables
in my blueprint. If I create an automation with this blueprint, and I test the if
conditions, all of them using variables seem to fail. But whatever I try, I cannot get it to work. I read so lot about blueprints, triggers, actions, inputs, variables and so on, but I have to admit that I have now reached the end of my knowledge.
I really hope someone can point me in the right direction… even ChatGPT and Gemini gave up already …
This is my blueprint so far:
blueprint:
name: "\U0001F525 Aqara E1 Heating"
author: veniplex
homeassistant:
min_version: 2024.9.3
description: "Set the current temperature on an Aqara E1 TRV from an external sensor."
domain: automation
### INPUTS
input:
radiator_section:
name: "Radiator"
icon: mdi:thermostat
input:
radiator:
name: "Aqara E1 Device"
description: "`climate`\n\nSelect the Aqara E1 device to be controlled."
selector:
entity:
multiple: false
filter:
- integration: mqtt
domain: climate
thermostat_section:
name: Thermostats
icon: mdi:thermometer
input:
room_thermostat:
name: Room Thermostat
description: "`sensor`\n\nSelect the thermostat that measures the temperature in the room."
selector:
entity:
multiple: false
filter:
- domain: sensor
device_class: temperature
outside_thermostat:
name: Outside Thermostat
description: "`sensor`\n\nSelect the thermostat (or `sensor` from a weather integration) that measures the outside temperature for your location."
selector:
entity:
multiple: false
filter:
- domain: sensor
device_class: temperature
temperature_section:
name: Temperatures
icon: mdi:home-thermometer-outline
input:
temperature_antifreeze:
name: "Static Frost Protection Temperature"
description: "`input_number`\n\nSet the minimum temperature to prevent the heaters from freezing (Recommended: min. 8 °C)."
default: 8
selector:
number:
min: 5
max: 30
unit_of_measurement: "°C"
mode: slider
temperature_antifreeze_helper:
name: "Frost Protection Temperature Helper"
description: "`input_number`\n\nSet the minimum temperature to prevent the heaters from freezing via a helper entity. This allows you to change the temperature from your dashboard. If no helper entity is selected, the static frost protection temperature will be used."
default:
selector:
entity:
multiple: false
filter:
- domain: input_number
temperature_eco:
name: "Static Eco Temperature"
description: "`input_number`\n\nSet the eco temperature to use when e.g. no one is at home (Recommended: 16 - 18 °C)."
default: 18
selector:
number:
min: 5
max: 30
unit_of_measurement: "°C"
mode: slider
temperature_eco_helper:
name: "Eco Temperature Helper"
description: "`input_number`\n\nSet the eco temperature to use when e.g. no one is at home. This allows you to change the temperature from your dashboard. If no helper entity is selected, the static eco temperature will be used."
default:
selector:
entity:
multiple: false
filter:
- domain: input_number
temperature_comfort:
name: "Static Comfort Temperature"
description: "`input_number`\n\nSet the comfort temperature to use when e.g. someone is at home (Recommended: 18 - 22 °C)."
default: 22
selector:
number:
min: 5
max: 30
unit_of_measurement: "°C"
mode: slider
temperature_comfort_helper:
name: "Comfort Temperature Helper"
description: "`input_number`\n\nSet the comfort temperature to use when e.g. someone is at home. This allows you to change the temperature from your dashboard. If no helper entity is selected, the static comfort temperature will be used."
default:
selector:
entity:
multiple: false
filter:
- domain: input_number
temperature_outside:
name: "Static Outside Temperature"
description: "`input_number`\n\nSet the outside temperature at which the radiator should be set to frost protection or turned off (see advanced settings)."
default: 22
selector:
number:
min: 5
max: 30
unit_of_measurement: "°C"
mode: slider
temperature_outside_helper:
name: "Outside Temperature Helper"
description: "`input_number`\n\nSet the outside temperature at which the radiator should be set to frost protection or turned off (see advanced settings). This allows you to change the target temperature from your dashboard. If no helper entity is selected, the static outside temperature will be used."
default:
selector:
entity:
multiple: false
filter:
- domain: input_number
schedule_section:
name: Schedules
icon: mdi:clock-outline
input:
schedule_eco:
name: Eco Schedule
description: "`schedule`\n\nSelect a schedule for heating to eco temperature."
selector:
entity:
multiple: false
filter:
- domain: schedule
schedule_comfort:
name: Comfort Schedule
description: "`schedule`\n\nSelect a schedule for heating to comfort temperature."
selector:
entity:
multiple: false
filter:
- domain: schedule
presence_section:
name: Presence
icon: mdi:location-enter
input:
presence_person:
name: "Person(s)"
description: "`person`\n\nSelect one or more person entities to activate comfort heating only if someone is at home. Otherwise heat on eco temperature."
default: []
selector:
entity:
multiple: true
filter:
- domain: person
presence_helper:
name: "Presence Helper"
description: "`input_boolean`\n\nSelect a helper entity of type `input_boolean` which represents the 'someone is at home' state. Make sure this helper is set to `on` if someone is at home and `off` if nobody is at home."
default:
selector:
entity:
multiple: false
filter:
- domain: input_boolean
window_section:
name: Window sensors
icon: mdi:blinds-vertical
input:
window_windows:
name: "Window(s)"
description: "`binary_sensor`\n\nSelect one or more window sensors. These are used to decide if heating should be turned on or off."
default: []
selector:
entity:
multiple: true
filter:
- domain: binary_sensor
advanced_section:
name: Advanced Settings
icon: mdi:tools
collapsed: true
input:
advanced_frost_protection:
name: "Frost Protection"
description: "`boolean`\n\nEnable (default) or disable frost protection. This will always use the frost protection temperature instead of turning the radiator completley off."
default: true
selector:
boolean:
advanced_window_detection:
name: Window Detection
description: "`boolean`\n\nEnable or disable (default) the window detection on the Aqara E1 device. It is recommended to only activate this if no window sensors are set."
default: false
selector:
boolean:
advanced_child_lock:
name: Child Lock
description: "`boolean`\n\nEnable (default) or disable child lock on the Aqara E1 device. This prevents accidental manual changes on the radiator itself. It can be disabled manually on the radiator or in the entity settings."
default: true
selector:
boolean:
advanced_valve_detection:
name: Valve Detection
description: "`boolean`\n\nEnable (default) or disable valve detection on the Aqara E1 device. This allows the device to detect problems with adjusting the valve."
default: true
selector:
boolean:
# advanced_update_interval:
# name: "Update Interval"
# description: "`input_number`\n\nSet the interval (in minutes) to update the radiator settings and current temperatures, not target temperatures, so a manual change is still possible (Recommended: 15 minutes)."
# default: 15
# selector:
# number:
# min: 1
# max: 60
# unit_of_measurement: "minutes"
# mode: slider
# advanced_calibration_interval:
# name: "Calibration Interval"
# description: "`input_number`\n\nSet the interval (in hours) to trigger a calibration on the radiator (Recommended: 168 hours / 7 days)."
# default: 23
# selector:
# number:
# min: 1
# max: 23
# unit_of_measurement: "hours"
# mode: slider
advanced_window_opened_interval:
name: "Windows Opened Interval"
description: "`input_number`\n\nSet the interval (in seconds) to trigger at opened windows. (Recommended: 15 seconds)."
default: 15
selector:
number:
min: 1
max: 60
unit_of_measurement: "seconds"
mode: slider
advanced_window_closed_interval:
name: "Windows Closed Interval"
description: "`input_number`\n\nSet the interval (in seconds) to trigger at closed windows. (Recommended: 15 seconds)."
default: 15
selector:
number:
min: 1
max: 60
unit_of_measurement: "seconds"
mode: slider
### VARIABLES
# see: https://www.home-assistant.io/docs/blueprint/schema/#blueprint-inputs-in-templates
trigger_variables:
radiator: !input radiator
room_thermostat: !input room_thermostat
outside_thermostat: !input outside_thermostat
temperature_antifreeze: !input temperature_antifreeze
temperature_antifreeze_helper: !input temperature_antifreeze_helper
temperature_eco: !input temperature_eco
temperature_eco_helper: !input temperature_eco_helper
temperature_comfort: !input temperature_comfort
temperature_comfort_helper: !input temperature_comfort_helper
temperature_outside: !input temperature_outside
temperature_outside_helper: !input temperature_outside_helper
presence_person: !input presence_person
advanced_frost_protection: !input advanced_frost_protection
advanced_window_detection: !input advanced_window_detection
advanced_child_lock: !input advanced_child_lock
advanced_valve_detection: !input advanced_valve_detection
advanced_window_opened_interval: !input advanced_window_opened_interval
advanced_window_closed_interval: !input advanced_window_closed_interval
### TRIGGERS
triggers:
# Trigger the automation at specified intervals for updates
- trigger: time_pattern
minutes: '/15'
alias: "Update temperature on radiator every 15 minutes"
id: "trigger_temperature"
- trigger: template
value_template: >
{{ now().day % 7|int == 0 }}
alias: "Calibrate radiator every 7 days"
id: "trigger_calibration"
# Trigger when any window sensor changes to open (on)
- trigger: state
entity_id: !input window_windows
to: "on"
for:
hours: 0
minutes: 0
seconds: !input advanced_window_opened_interval
alias: "A window was opened"
id: "trigger_all"
# Trigger when any window sensor changes to close (off)
- trigger: state
entity_id: !input window_windows
to: "off"
for:
hours: 0
minutes: 0
seconds: !input advanced_window_closed_interval
alias: "A window was closed"
id: "trigger_all"
# Trigger when someone enters home
- trigger: zone
entity_id: !input presence_person
zone: zone.home
event: enter
id: "trigger_all"
# Trigger when someone leaves home
- trigger: zone
entity_id: !input presence_person
zone: zone.home
event: leave
id: "trigger_all"
# Trigger when automations are reloaded
- trigger: event
event_type:
- automation_reloaded
- core_config_updated
alias: "The automation was reloaded or config was changed"
id: "trigger_all"
# Trigger when Home Assistant is started
- trigger: homeassistant
event: start
alias: "Home Assistant was started"
id: "trigger_all"
variables:
temperature_antifreeze_calculated: "{{ (temperature_antifreeze_helper | default(temperature_antifreeze)) | float }}"
temperature_eco_calculated: "{{ (temperature_eco_helper | default(temperature_eco)) | float }}"
temperature_comfort_: "{{ (temperature_comfort_helper | default(temperature_comfort)) | float }}"
temperature_outside_calculated: "{{ (temperature_outside_helper | default(temperature_outside)) | float }}"
### CONDITIONS
conditions: []
### ACTIONS
actions:
- sequence:
- if:
- condition: trigger
id: "trigger_all"
then:
- alias: "Wenn die Außentemperatur höher als die Außen-Zieltemperatur ist..."
if:
- condition: template
value_template: "{{ states(outside_thermostat) | float >= temperature_outside_calculated | float }}"
then:
- alias: "Und 'advanced_frost_protection' ist auf 'true' gesetzt ist..."
if:
- condition: template
value_template: "{{ is_state(advanced_frost_protection, 'true') }}"
then:
- alias: "Dann stelle die Heizung auf Frost-Protection-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_antifreeze_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst schalte die Heizung aus."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: off
- alias: "Wenn die Außentemperatur niedriger als die Außen-Zieltemperatur ist..."
if:
- condition: template
value_template: "{{ states(outside_thermostat) | float < temperature_outside_calculated | float }}"
then:
- alias: "Und der Komfortzeitplan eingeschaltet ist..."
if:
- condition: state
entity_id: !input schedule_comfort
state: "on"
then:
- alias: "Und jemand ist zuhause..."
if:
- condition: or
conditions:
- condition: state
entity_id: !input presence_person
state: "home"
- condition: state
entity_id: !input presence_helper
state: "on"
then:
- alias: "Und alle Fenster geschlossen sind..."
if:
- condition: state
entity_id: !input window_windows
state: "off"
then:
- alias: "Dann stelle die Heizung auf Komfort-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_comfort_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst, wenn 'advanced_frost_protection' ist auf 'true' gesetzt ist..."
if:
- condition: template
value_template: "{{ is_state(advanced_frost_protection, 'true') }}"
then:
- alias: "Dann stelle die Heizung auf Frost-Protection-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_antifreeze_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst schalte die Heizung aus."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: off
else:
- alias: "Und alle Fenster geschlossen sind..."
if:
- condition: state
entity_id: !input window_windows
state: "off"
then:
- alias: "Dann stelle die Heizung auf Eco-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_eco_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst, wenn 'advanced_frost_protection' ist auf 'true' gesetzt ist..."
if:
- condition: template
value_template: "{{ is_state(advanced_frost_protection, 'true') }}"
then:
- alias: "Dann stelle die Heizung auf Frost-Protection-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_antifreeze_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst schalte die Heizung aus."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: off
else:
- alias: "Sonst, wenn Eco-Zeitplan eingeschaltet ist..."
if:
- condition: state
entity_id: !input schedule_eco
state: "on"
then:
- alias: "Und alle Fenster geschlossen sind..."
if:
- condition: state
entity_id: !input window_windows
state: "off"
then:
- alias: "Dann stelle die Heizung auf Eco-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_eco_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst, wenn 'advanced_frost_protection' ist auf 'true' gesetzt ist..."
if:
- condition: template
value_template: "{{ is_state(advanced_frost_protection, 'true') }}"
then:
- alias: "Dann stelle die Heizung auf Frost-Protection-Temperatur"
action: climate.set_temperature
metadata: {}
data:
temperature: "{{ temperature_antifreeze_calculated | float }}"
target:
entity_id: !input radiator
- alias: "Und auf heizen."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: heat
else:
- alias: "Sonst schalte die Heizung aus."
action: climate.set_hvac_mode
target:
entity_id: !input radiator
data:
hvac_mode: off
else:
- alias: "Ansonsten, wenn die Automatisierung durch 'trigger_temperature' ausgelöst wurde..."
if:
- condition: trigger
id: "trigger_temperature"
then:
# - alias: "Dann setze den Sensor am Radiator auf 'external'"
# action: mqtt.publish
# data:
# topic: "zigbee2mqtt/{{ state_attr(variables.radiator, 'friendly_name') }}/set"
# payload: '{"sensor": "external"}'
# - alias: "Und setze die aktuelle Temperatur auf die Temperatur des Raumthermostats"
# action: mqtt.publish
# data:
# topic: "zigbee2mqtt/{{ state_attr(variables.radiator, 'friendly_name') }}/set"
# payload: '{"external_temperature_input": {{ states(variables.room_thermostat) }}}'
- alias: "Setze den Radiator und zusätzliche Einstellungen"
action: mqtt.publish
data:
topic: "zigbee2mqtt/{{ state_attr(radiator, 'friendly_name') }}/set"
payload: >
{
"sensor": "external",
"external_temperature_input": {{ states(room_thermostat) }},
"child_lock": {{ is_state(advanced_child_lock, 'true') | lower }},
"window_detection": {{ is_state(advanced_window_detection, 'true') | lower }},
"valve_detection": {{ is_state(advanced_valve_detection, 'true') | lower }}
}
else:
- alias: "Ansonsten, wenn die Automatisierung durch 'trigger_calibration' ausgelöst wurde..."
if:
- condition: trigger
id: "trigger_calibration"
then:
- alias: "Dann Kalibriere den Radiator."
action: mqtt.publish
data:
topic: "zigbee2mqtt/{{ state_attr(radiator, 'friendly_name') }}/set"
payload: '{"calibrate": "calibrate"}'