blueprint: name: Klima Demand Control (Soll/Ist Curve + Outdoor Boost + Overheat Protection) description: > Regelt den Demand einer Klimaanlage ausschließlich im Heizmodus basierend auf der Soll-Ist-Abweichung über eine linear interpolierte Kennlinie. Funktionen: - Soll/Ist Kennlinie - Überheizschutz über definierte Schwelle - Außentemperatur Boost - Rundung auf 5% Demand domain: automation input: hvac: name: Klimagerät selector: entity: domain: climate room_sensor: name: Raumtemperatur selector: entity: domain: sensor device_class: temperature outdoor_sensor: name: Außentemperatur selector: entity: domain: sensor device_class: temperature demand_entity: name: Demand Select selector: entity: domain: select demand_curve: name: Demand Kennlinie description: JSON Liste [Temperaturdifferenz, Demand] default: "[[0.2,30],[0.6,50],[1.0,80],[1.5,100]]" selector: text: demand_min: name: Minimaler Demand default: 30 selector: number: min: 0 max: 100 step: 5 overheat_threshold: name: Überheizschwelle description: Wenn Soll - Ist unter diesem Wert liegt → Demand Minimum default: -0.3 selector: number: min: -2 max: 0 step: 0.1 unit_of_measurement: "°C" outdoor_boost_threshold: name: Außentemperatur Boost Schwelle default: 0 selector: number: min: -20 max: 20 step: 1 unit_of_measurement: "°C" outdoor_boost_percent: name: Boost Prozent default: 10 selector: number: min: 0 max: 50 step: 5 unit_of_measurement: "%" mode: restart trigger: - platform: time_pattern minutes: "/2" - platform: state entity_id: - !input room_sensor - !input outdoor_sensor - !input hvac condition: - condition: state entity_id: !input hvac state: heat action: - variables: hvac_entity: !input hvac room_sensor_entity: !input room_sensor outdoor_sensor_entity: !input outdoor_sensor demand_entity_var: !input demand_entity curve_raw: !input demand_curve demand_min: !input demand_min overheat_threshold: !input overheat_threshold boost_temp: !input outdoor_boost_threshold boost_percent: !input outdoor_boost_percent - variables: curve: "{{ curve_raw | from_json }}" room: "{{ states(room_sensor_entity) | float(0) }}" target: "{{ state_attr(hvac_entity,'temperature') | float(0) }}" outdoor: "{{ states(outdoor_sensor_entity) | float(999) }}" diff: "{{ target - room }}" - variables: base_demand: > {% set pts = curve %} {% set d = diff %} {% if d <= pts[0][0] %} {{ pts[0][1] }} {% elif d >= pts[-1][0] %} {{ pts[-1][1] }} {% else %} {% set ns = namespace(val=pts[0][1]) %} {% for i in range(pts|length - 1) %} {% set a = pts[i] %} {% set b = pts[i+1] %} {% if d >= a[0] and d <= b[0] %} {% set ratio = (d - a[0]) / (b[0] - a[0]) %} {% set ns.val = a[1] + ratio * (b[1] - a[1]) %} {% endif %} {% endfor %} {{ ns.val }} {% endif %} - variables: demand_after_overheat: > {% if diff < overheat_threshold %} {{ demand_min }} {% else %} {{ base_demand | float }} {% endif %} - variables: boosted: > {% if outdoor < boost_temp %} {{ demand_after_overheat * (1 + boost_percent / 100) }} {% else %} {{ demand_after_overheat }} {% endif %} - variables: limited: "{{ [boosted,100] | min }}" rounded: "{{ (limited / 5) | round(0) * 5 }}" option: "{{ rounded | int }}" - condition: template value_template: "{{ states(demand_entity_var) | int != option }}" - service: select.select_option target: entity_id: "{{ demand_entity_var }}" data: option: "{{ option }}"