# blueprints/automation/slimme_warmtebron_sturing.yaml blueprint: name: Slimme Warmtebron Sturing (Airco / Gas + Koeling) description: > Schakel automatisch tussen airco (warmtepomp) en gasverwarming op basis van nettovermogen en een zelf te kiezen temperatuursensor. Ondersteunt verwarmen, koelen én automatische seizoenswisseling. Inclusief hysterese. domain: automation input: # ── Bedrijfsmodus ────────────────────────────────────────────────────────── operation_mode: name: Bedrijfsmodus description: > Verwarmen: alleen verwarmingslogica actief. Koelen: alleen koellogica actief. Automatisch: verwarm als temp onder doel, koel als temp boven doel. default: "auto" selector: select: options: - label: "🔥 Verwarmen" value: "heating" - label: "❄️ Koelen" value: "cooling" - label: "🔄 Automatisch" value: "auto" # ── Vermogen ─────────────────────────────────────────────────────────────── power_sensor: name: Nettovermogen sensor description: > Sensor in Watt. Negatief = injectie naar net (zonne-overschot), positief = afname van net. selector: entity: domain: sensor device_class: power solar_surplus_threshold: name: Zonne-overschot drempel – verwarmen (W) description: > Minimale injectie (absoluut) vooraleer de airco als warmtebron gekozen wordt boven gas. Bv. 500 = airco start bij ≥ 500 W injectie. default: 500 selector: number: min: 0 max: 5000 step: 50 unit_of_measurement: "W" mode: slider grid_threshold: name: Netstroom drempel → gasverwarming (W) description: > Afname boven deze waarde schakelt over naar gas (goedkoper bij hoge elektriciteitsprijs). Stem af op actuele gas/elektriciteitsverhouding. default: 1000 selector: number: min: 0 max: 5000 step: 50 unit_of_measurement: "W" mode: slider solar_surplus_threshold_cooling: name: Zonne-overschot drempel – koelen (W) description: > Minimale injectie om de airco in koelmodus te starten. Zet lager dan de verwarmingsdrempel want koelen verbruikt doorgaans minder. Bv. 300 W. default: 300 selector: number: min: 0 max: 5000 step: 50 unit_of_measurement: "W" mode: slider cool_on_grid: name: Koelen ook bij netstroom? description: > Er is geen alternatief voor de airco bij koeling. Als dit aan staat, koelt de airco ook wanneer er stroom van het net wordt afgenomen. Zet uit als je stroomkosten wilt vermijden en hitte verdraagbaar is. default: true selector: boolean: cool_grid_threshold: name: Max. netstroom bij koelen (W) description: > Enkel zichtbaar als "Koelen ook bij netstroom" aan staat. Boven deze netstroom wordt koeling onderdrukt (piekuur-logica). 0 = geen limiet. default: 2000 selector: number: min: 0 max: 6000 step: 50 unit_of_measurement: "W" mode: slider # ── Temperatuur ──────────────────────────────────────────────────────────── temperature_sensor: name: Temperatuursensor (referentie) description: > Gebruik bij voorkeur de Tado wandthermostaat — de airco-sensor leest doorgaans 1–2 °C hoger door stralingswarmte van de unit. selector: entity: domain: sensor device_class: temperature target_temperature: name: Doeltemperatuur (°C) default: 20 selector: number: min: 10 max: 30 step: 0.5 unit_of_measurement: "°C" mode: slider hysteresis: name: Hysterese (°C) description: > Marge rond de doeltemperatuur om pendelen te voorkomen. Verwarming start onder (doel − hysterese), koeling boven (doel + hysterese). default: 0.5 selector: number: min: 0.1 max: 3 step: 0.1 unit_of_measurement: "°C" # ── Klimaatentiteiten ────────────────────────────────────────────────────── airco_climate: name: Airco (climate entiteit) selector: entity: domain: climate tado_climate: name: Tado gasverwarming (climate entiteit) selector: entity: domain: climate tado_off_temperature: name: Tado rusttemperatuur (°C) description: > Temperatuur die Tado krijgt wanneer gas niet nodig is (vorstbeveiliging). Tado gaat zelden echt "uit" — stel dit laag in (bv. 5 °C). default: 5 selector: number: min: 5 max: 15 step: 0.5 unit_of_measurement: "°C" # ── Variabelen ───────────────────────────────────────────────────────────────── variables: _power_sensor: !input power_sensor _temp_sensor: !input temperature_sensor _solar_heat: !input solar_surplus_threshold _grid_thresh: !input grid_threshold _solar_cool: !input solar_surplus_threshold_cooling _cool_on_grid: !input cool_on_grid _cool_grid_max: !input cool_grid_threshold _target: !input target_temperature _hyst: !input hysteresis _tado_off: !input tado_off_temperature _mode: !input operation_mode current_power: "{{ states(_power_sensor) | float(0) }}" current_temp: "{{ states(_temp_sensor) | float(0) }}" # Verwarmingslogica needs_heat: "{{ current_temp < (_target | float - _hyst | float) }}" solar_heat_ok: "{{ current_power <= (_solar_heat | float * -1) }}" grid_high: "{{ current_power >= (_grid_thresh | float) }}" # Koelingslogica needs_cool: "{{ current_temp > (_target | float + _hyst | float) }}" solar_cool_ok: "{{ current_power <= (_solar_cool | float * -1) }}" grid_cool_ok: > {{ _cool_on_grid and (_cool_grid_max == 0 or current_power < _cool_grid_max | float) }} # Gecombineerde modus checks do_heat: > {{ ((_mode == 'heating') or (_mode == 'auto' and needs_heat)) and not needs_cool }} do_cool: > {{ ((_mode == 'cooling') or (_mode == 'auto' and needs_cool)) and not needs_heat }} at_target: > {{ current_temp >= (_target | float - _hyst | float) and current_temp <= (_target | float + _hyst | float) }} # ── Trigger ──────────────────────────────────────────────────────────────────── trigger: - platform: time_pattern minutes: "/5" - platform: state entity_id: !input temperature_sensor mode: single max_exceeded: silent # ── Acties ───────────────────────────────────────────────────────────────────── action: - choose: # ── VERWARMEN ───────────────────────────────────────────────────────────── # V1: Genoeg zonne-overschot → airco verwarmt, Tado op rust - conditions: - condition: template value_template: "{{ do_heat and solar_heat_ok }}" sequence: - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "heat" - service: climate.set_temperature target: entity_id: !input airco_climate data: temperature: "{{ _target }}" - service: climate.set_temperature target: entity_id: !input tado_climate data: temperature: "{{ _tado_off }}" # V2: Te veel netstroom → gas verwarmt, airco uit - conditions: - condition: template value_template: "{{ do_heat and grid_high }}" sequence: - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "off" - service: climate.set_temperature target: entity_id: !input tado_climate data: temperature: "{{ _target }}" # ── KOELEN ──────────────────────────────────────────────────────────────── # K1: Koelen met zonne-overschot → airco koel modus - conditions: - condition: template value_template: "{{ do_cool and solar_cool_ok }}" sequence: - service: climate.set_temperature target: entity_id: !input tado_climate data: temperature: "{{ _tado_off }}" - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "cool" - service: climate.set_temperature target: entity_id: !input airco_climate data: temperature: "{{ _target }}" # K2: Koelen zonder overschot maar netstroom toegestaan - conditions: - condition: template value_template: "{{ do_cool and not solar_cool_ok and grid_cool_ok }}" sequence: - service: climate.set_temperature target: entity_id: !input tado_climate data: temperature: "{{ _tado_off }}" - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "cool" - service: climate.set_temperature target: entity_id: !input airco_climate data: temperature: "{{ _target }}" # K3: Koelen gewenst maar te duur / uitgeschakeld → airco uit, wachten - conditions: - condition: template value_template: "{{ do_cool and not solar_cool_ok and not grid_cool_ok }}" sequence: - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "off" # ── DOELTEMPERATUUR BEREIKT → alles op minimum ──────────────────────────── - conditions: - condition: template value_template: "{{ at_target }}" sequence: - service: climate.set_hvac_mode target: entity_id: !input airco_climate data: hvac_mode: "off" - service: climate.set_temperature target: entity_id: !input tado_climate data: temperature: "{{ _tado_off }}"