Update ha-thermostat-calibration.yaml

new robust method
This commit is contained in:
Andreas Gammelgaard Damsbo 2025-12-08 21:41:45 +01:00
parent 266279c152
commit f59e0b9977

View file

@ -105,50 +105,57 @@ action:
climate_device: "{{ device_id(climate_entity) }}"
external_temp: "{{ states(external_sensor) | float(0) }}"
valve_temp: "{{ state_attr(climate_entity, 'current_temperature') | float(0) }}"
# Skip if climate entity is unavailable or has no valid temperature
hvac_action: "{{ state_attr(climate_entity, 'hvac_action') }}" # Get valve state (heating/idle)
target_temp: "{{ state_attr(climate_entity, 'temperature') | float(0) }}" # Get setpoint
# 1. Standard Skip Conditions
- condition: template
value_template: >
{{ states(climate_entity) not in ['unknown', 'unavailable'] and valve_temp > 0 and external_temp > 0 }}
# Find offset entity for this device
# 2. **CRITICAL STABILITY CONDITION**
# Only calibrate if the valve is not actively heating and the setpoint is close to external temp
- condition: template
value_template: >
{{ hvac_action != 'heating' and (target_temp - external_temp) < 0.5 }}
# Find offset entity for this device (unchanged)
- variables:
offset_entity: >
{% set entities = device_entities(climate_device) if climate_device else [] %}
{% set offset_entities = entities | select('match', '^number\.') | select('search', offset_entity_suffix) | list %}
{{ offset_entities[0] if offset_entities else '' }}
# Skip if no offset entity found or is unavailable
# 3. Skip if no offset entity found (unchanged)
- condition: template
value_template: "{{ offset_entity != '' and states(offset_entity) not in ['unknown', 'unavailable'] }}"
# Calculate and set new offset
# 4. Calculate New Offset using Differential Method
- variables:
current_offset: "{{ states(offset_entity) | float(0) }}"
# 1. Calculate the required offset based on the difference
# Required Offset = External Temp - (Valve Internal Temp - Current Offset) + Manual Correction
raw_offset_required: "{{ external_temp - (valve_temp - current_offset) + manual_correction }}"
# The new required offset is the difference between the external (ground truth)
# and the uncompensated internal sensor reading.
raw_offset_required: "{{ external_temp - valve_temp + manual_correction }}"
# 2. Round the raw offset to the nearest rounding_step
# Safely scale, round, and scale back to minimize floating point errors
# Round the raw offset to the nearest rounding_step (unchanged rounding logic)
new_offset: >
{% set step = rounding_step | float(1.0) %}
{% set scale = (1 / step) | round(0) %}
{{ (raw_offset_required * scale) | round(0) / scale }}
# Only update if the calculated value is different from the current value
# 5. Only update if the calculated value is different from the current value (unchanged)
- condition: template
value_template: "{{ new_offset | round(3) != current_offset | round(3) }}"
# Set new offset
# 6. Set new offset (unchanged)
- service: number.set_value
target:
entity_id: "{{ offset_entity }}"
data:
value: "{{ new_offset }}"
# Small delay between updates to avoid overwhelming the system
# Small delay between updates (unchanged)
- delay:
milliseconds: 100