Bosch Wärmepumpe in Home Assistant integrieren und steuern dieser mit Leistungsüberschuss der PV-Anlage

:high_voltage: Energy Manager Update – zuverlässiger Sommer/Winter-Modus + neues Admin UI

Weil ich gerade dabei war, habe noch eine Sommer-/Winterumschaltung eingebaut**.**


:counterclockwise_arrows_button: Was wurde verbessert?

:check_mark: 1. Zuverlässiger Moduswechsel

Der Sommer-/Wintermodus wird jetzt:

  • über den input_select.energy_manager_mode gesteuert

  • zentral über das Script script.em_set_mode

  • automatisch bei Änderung des Selects ausgelöst

:backhand_index_pointing_right: Dadurch ist sichergestellt:

  • keine „halb aktiven“ Zustände

  • vollständiges Ein-/Ausschalten aller relevanten Automationen


:check_mark: 2. Klare Systemlogik pro Modus

:snowflake: Wintermodus

  • Energy Manager aktiv

  • Temperaturprüfung aktiv

  • alle Automationen eingeschaltet:

    • Vorlaufregelung

    • DHW Steuerung

    • Aux-Heater Steuerung

:sun: Sommermodus

  • Energy Manager deaktiviert

  • DHW & Aux-Heater AUS

  • Automationen deaktiviert

  • System wird in definierten Grundzustand zurückgesetzt


:check_mark: 3. Reset-Funktion verbessert

Beim Wechsel in den Sommermodus erfolgt jetzt ein kompletter Reset:

  • alle Input-Booleans zurückgesetzt

  • alle relevanten Input-Numbers auf Default

  • Wärmepumpe geht in definierten Ausgangszustand

  • sichere Abschaltung aller Verbraucher


:brain: Neue Automation: Moduswechsel

Zusätzlich gibt es jetzt eine dedizierte Automation:

  • reagiert direkt auf input_select.energy_manager_mode

  • ruft automatisch script.em_set_mode auf

  • keine manuelle Script-Auslösung mehr notwendig


:control_knobs: Neues UI – Mode Button

Der neue Button zeigt jetzt klar den aktuellen Status und erlaubt direkten Wechsel:

  • :snowflake: Winter = blau

  • :sun: Sommer = rot

  • visuelle Rückmeldung + klare Zustandsanzeige

:camera_with_flash: Screenshots:

  • Screenshot Wintermodus

  • Screenshot Sommermodus


:package: Komplettes aktualisiertes Package

# config/packages/energy_manager.yaml

# --- Helpers / Controls ---
input_boolean:
  energy_manager_enabled:
    name: "Energy Manager aktiv"
    initial: on

  energy_manager_temp_ok:
    name: "Energy Manager: Temp OK"
    initial: on

  energy_manager_force_zero:
    name: "Energy Manager: Force smoothed zero"
    initial: off
    icon: mdi:power-off

  em_allow_aux:
    name: "EM: Aux-Heater erlauben"
    initial: off

  em_dhw_charging:
    name: "EM DHW Ladung aktiv"
    initial: off

  em_safe_mode:
    name: "EM Safe Mode"
    initial: off
    icon: mdi:shield-alert


input_select:
  energy_manager_mode:
    name: "Energy Manager Modus"
    options:
      - "Sommer"
      - "Winter"


input_number:
  pw_max_charge:
    name: "Powerwall max Ladeleistung (kW)"
    initial: 4.6
    min: 0
    max: 11.0
    step: 0.1
    unit_of_measurement: kW

  energy_manager_temp_start:
    name: "EM Temp Start (°C)"
    initial: 14
    min: -40
    max: 40
    step: 0.5

  energy_manager_temp_stop:
    name: "EM Temp Stop (°C)"
    initial: 17
    min: -40
    max: 40
    step: 0.5

  em_flow_temp_min:
    name: "EM Vorlauf Minimum (°C)"
    initial: 38
    min: 20
    max: 45
    step: 0.5

  em_flow_temp_max:
    name: "EM Vorlauf Maximum (°C)"
    initial: 50
    min: 40
    max: 60
    step: 0.5

  em_flow_temp_step_k:
    name: "EM Vorlauf Änderung pro Intervall (°C)"
    initial: 0.5
    min: 0.1
    max: 2
    step: 0.1

  em_min_runtime:
    name: "EM Kompressor Mindestlaufzeit (Minuten)"
    initial: 15
    min: 5
    max: 60
    step: 1

  em_pv_threshold_start:
    name: "EM PV Überschuss Startschwelle (kW)"
    initial: 3
    min: 0
    max: 5
    step: 0.1

  em_pv_threshold_stop:
    name: "EM PV Überschuss Stoppschwelle (kW)"
    initial: 1
    min: 0
    max: 5
    step: 0.1

  em_dhw_max_temp:
    name: "EM DHW Max Temperatur (°C)"
    initial: 55
    min: 45
    max: 70
    step: 0.5

  em_dhw_min_temp:
    name: "EM DHW Min Temperatur (°C)"
    initial: 45
    min: 35
    max: 55
    step: 0.5

  em_dhw_charge_min_duration:
    name: "EM DHW Mindestladezeit (Minuten)"
    initial: 20
    min: 5
    max: 60
    step: 1

  em_avail_start:
    name: "EM Avail Start (kW)"
    initial: 0.6
    min: 0
    max: 10
    step: 0.1

  em_avail_stop:
    name: "EM Avail Stop (kW)"
    initial: 0.4
    min: 0
    max: 10
    step: 0.1


# --- Scripts ---
script:

  em_set_mode:
    alias: "EM: Modus anwenden"
    mode: single
    sequence:

      - variables:
          mode: "{{ states('input_select.energy_manager_mode') }}"

      - choose:

          - conditions:
              - condition: template
                value_template: "{{ mode == 'Winter' }}"
            sequence:
              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.energy_manager_enabled

              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.energy_manager_temp_ok

              - service: input_boolean.turn_off
                target:
                  entity_id: input_boolean.em_safe_mode

              - service: number.set_value
                target:
                  entity_id: number.boiler_selected_flow_temperature
                data:
                  value: "{{ states('input_number.em_flow_temp_min') | float(38) }}"
              
              - delay: "00:00:02"
              
              - service: automation.turn_on
                target:
                  entity_id:
                    - automation.em_vorlauftemperatur_regeln
                    - automation.em_dhw_ladung_steuern
                    - automation.em_aux_heater_steuerung

              - service: system_log.write
                data:
                  message: "EM: Wintermodus aktiviert"
                  level: info

          - conditions:
              - condition: template
                value_template: "{{ mode == 'Sommer' }}"
            sequence:
              - service: input_boolean.turn_off
                target:
                  entity_id:
                    - input_boolean.energy_manager_enabled
                    - input_boolean.em_dhw_charging
                    - input_boolean.em_allow_aux

              - service: automation.turn_off
                target:
                  entity_id:
                    - automation.em_vorlauftemperatur_regeln
                    - automation.em_dhw_ladung_steuern
                    - automation.em_aux_heater_steuerung

              - service: script.em_reset_to_defaults

              - service: system_log.write
                data:
                  message: "EM: Sommermodus aktiviert"
                  level: warning

  em_toggle_mode:
    alias: "EM: Modus umschalten"
    mode: single
    sequence:
      - variables:
          current: "{{ states('input_select.energy_manager_mode') }}"

      - service: input_select.select_option
        target:
          entity_id: input_select.energy_manager_mode
        data:
          option: >
            {% if current == 'Winter' %}
              Sommer
            {% else %}
              Winter
            {% endif %}
            
  em_reset_to_defaults:
    alias: "EM: Reset auf Standardwerte"
    mode: single
    sequence:

      # 🛡 Safe Mode aktivieren (verhindert Zwischenzustände)
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.em_safe_mode

      - delay: "00:00:01"

      # 🧹 Grundsystem deaktivieren
      - service: input_boolean.turn_off
        target:
          entity_id:
            - input_boolean.energy_manager_enabled
            - input_boolean.energy_manager_force_zero
            - input_boolean.em_allow_aux
            - input_boolean.em_dhw_charging

      # ✔ Temp Status initialisieren
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.energy_manager_temp_ok

      # 🔧 Input Numbers Reset
      - service: input_number.set_value
        data:
          entity_id: input_number.pw_max_charge
          value: 4.6

      - service: input_number.set_value
        data:
          entity_id: input_number.energy_manager_temp_start
          value: 14

      - service: input_number.set_value
        data:
          entity_id: input_number.energy_manager_temp_stop
          value: 17

      - service: input_number.set_value
        data:
          entity_id: input_number.em_flow_temp_min
          value: 38

      - service: input_number.set_value
        data:
          entity_id: input_number.em_flow_temp_max
          value: 50

      - service: input_number.set_value
        data:
          entity_id: input_number.em_flow_temp_step_k
          value: 0.5

      - service: input_number.set_value
        data:
          entity_id: input_number.em_min_runtime
          value: 15

      - service: input_number.set_value
        data:
          entity_id: input_number.em_pv_threshold_start
          value: 3

      - service: input_number.set_value
        data:
          entity_id: input_number.em_pv_threshold_stop
          value: 1

      - service: input_number.set_value
        data:
          entity_id: input_number.em_dhw_max_temp
          value: 55

      - service: input_number.set_value
        data:
          entity_id: input_number.em_dhw_min_temp
          value: 45

      - service: input_number.set_value
        data:
          entity_id: input_number.em_dhw_charge_min_duration
          value: 20

      - service: input_number.set_value
        data:
          entity_id: input_number.em_avail_start
          value: 0.6

      - service: input_number.set_value
        data:
          entity_id: input_number.em_avail_stop
          value: 0.4

      # 🌡 Boiler Startwert setzen
      - service: number.set_value
        data:
          entity_id: number.boiler_selected_flow_temperature
          value: "{{ states('input_number.em_flow_temp_min') | float(38) }}"

      # 🔌 Aktoren sicher aus
      - service: switch.turn_off
        target:
          entity_id:
            - switch.boiler_dhw_one_time_charging
            - switch.boiler_aux_heater_only

      # 📣 Feedback
      - service: notify.persistent_notification
        data:
          title: "EM Reset"
          message: "System wurde vollständig zurückgesetzt und in Wintermodus initialisiert"
          
# --- Filter Sensoren (Glättung) ---
sensor:
  - platform: filter
    name: "em_pv_power_smoothed"
    entity_id: sensor.my_home_solar_energie
    filters:
      - filter: lowpass
        time_constant: 2
        precision: 2

  - platform: filter
    name: "em_home_load_smoothed"
    entity_id: sensor.my_home_last_leistung
    filters:
      - filter: time_simple_moving_average
        window_size: 3
        precision: 2

  - platform: filter
    name: "em_powerwall_battery_power_smoothed"
    entity_id: sensor.my_home_batterie_leistung
    filters:
      - filter: lowpass
        time_constant: 6
        precision: 2

# --- Template Sensors & Binary Sensors ---
template:
  - sensor:
      - name: "em_pv_power_corrected"
        unit_of_measurement: "kW"
        state: >-
          {% set force = is_state('input_boolean.energy_manager_force_zero', 'on') %}
          {% set raw = states('sensor.my_home_solar_energie') | float(0) %}
          {% set sm = states('sensor.em_pv_power_smoothed') | float(0) %}
          {% if force or raw < 0.02 %}
            0
          {% else %}
            {{ sm | round(2) }}
          {% endif %}

      - name: "em_home_load_corrected"
        unit_of_measurement: "kW"
        state: >-
          {% set force = is_state('input_boolean.energy_manager_force_zero', 'on') %}
          {% set raw = states('sensor.my_home_last_leistung') | float(0) %}
          {% set sm = states('sensor.em_home_load_smoothed') | float(0) %}
          {% if force or raw < 0.02 %}
            0
          {% else %}
            {{ sm | round(2) }}
          {% endif %}

      - name: "em_powerwall_charge_corrected"
        unit_of_measurement: "kW"
        state: >-
          {% set force = is_state('input_boolean.energy_manager_force_zero', 'on') %}
          {% set raw = states('sensor.my_home_batterie_leistung') | float(0) %}
          {% set sm = states('sensor.em_powerwall_battery_power_smoothed') | float(0) %}
          {% if force or (raw | abs) < 0.02 %}
            0
          {% else %}
            {{ sm | round(2) }}
          {% endif %}

      - name: "em_energy_surplus"
        unit_of_measurement: "kW"
        state: >-
          {{ (states('sensor.em_pv_power_corrected') | float(0) - states('sensor.em_home_load_corrected') | float(0)) | round(2) }}

      - name: "em_pw_max_charge"
        unit_of_measurement: "kW"
        state: >-
          {{ states('input_number.pw_max_charge') | float(4.6) }}

      - name: "em_pw_current_charge"
        unit_of_measurement: "kW"
        state: >-
          {{ (states('sensor.em_powerwall_charge_corrected') | float(0)) | abs | round(2) }}

      - name: "em_available_for_heatpump"
        unit_of_measurement: "kW"
        state: >-
          {% set surplus = states('sensor.em_energy_surplus') | float(0) %}
          {% set pw_curr = states('sensor.em_pw_current_charge') | float(0) %}
          {% set threshold = 0.02 %}
          {% if surplus > 0 %}
            {% set used = pw_curr if pw_curr > threshold else 0 %}
            {{ [surplus - used, 0] | max | round(2) }}
          {% else %}
            0
          {% endif %}
        attributes:
          note: "Surplus minus current battery charge (threshold 0.02 kW)"

      - name: "em_target_flow_temp"
        unit_of_measurement: "°C"
        state: >-
          {% set min_t = states('input_number.em_flow_temp_min') | float(0) %}
          {% set max_t = states('input_number.em_flow_temp_max') | float(0) %}
          {% set avail = states('sensor.em_available_for_heatpump') | float(0) %}
          {% set max_power = 6 %}
          {% set ratio = (avail / max_power) | float(0) %}
          {% set ratio = [ratio, 0] | max %}
          {% set ratio = [ratio, 1] | min %}
          {% set target = min_t + (max_t - min_t) * ratio %}
          {{ target | round(1) }}

      - name: "em_current_flow_temp"
        unit_of_measurement: "°C"
        state: "{{ states('sensor.boiler_current_flow_temperature') | float(0) }}"

      - name: "em_dhw_boiler_temp"
        unit_of_measurement: "°C"
        state: "{{ states('sensor.boiler_heat_carrier_forward_tc1') | float(0) }}"

      - name: "em_dhw_charge_state"
        state: >-
          {{ 'on' if is_state('input_boolean.em_dhw_charging', 'on') else 'off' }}

  - binary_sensor:
    - name: "wp_laufzeit_startbedingung"
      unique_id: wp_laufzeit_startbedingung
      device_class: running
      state: >-
        {% set enabled    = is_state('input_boolean.energy_manager_enabled','on') %}
        {% set temp_ok    = is_state('input_boolean.energy_manager_temp_ok','on') %}
        {% set safe_off   = is_state('input_boolean.em_safe_mode','off') %}
        {% set avail      = states('sensor.em_available_for_heatpump') | float(0) %}
        {% set start_th   = states('input_number.em_avail_start') | float(0) %}
        {% set target_t   = states('sensor.em_target_flow_temp') | float(0) %}
        {% set current_t  = states('sensor.em_current_flow_temp') | float(0) %}
        {% set hysteresis = 0.2 %}
        {{ enabled and temp_ok and safe_off and (avail > start_th) and (target_t > current_t + hysteresis) }}
        {# Optional zusätzlich: or is_state('input_boolean.em_dhw_charging','on') #}
      attributes:
        em_enabled: "{{ states('input_boolean.energy_manager_enabled') }}"
        em_temp_ok: "{{ states('input_boolean.energy_manager_temp_ok') }}"
        em_safe_mode: "{{ states('input_boolean.em_safe_mode') }}"
        avail_for_hp_kW: "{{ states('sensor.em_available_for_heatpump') }}"
        avail_start_kW: "{{ states('input_number.em_avail_start') }}"
        target_flow_temp_C: "{{ states('sensor.em_target_flow_temp') }}"
        current_flow_temp_C: "{{ states('sensor.em_current_flow_temp') }}"
        would_set_to_C: >-
          {% set step  = states('input_number.em_flow_temp_step_k') | float(0.5) %}
          {% set max_t = states('input_number.em_flow_temp_max')   | float(50) %}
          {% set cand  = (states('sensor.em_current_flow_temp') | float(0)) + step %}
          {% set tgt   = states('sensor.em_target_flow_temp')  | float(0) %}
          {% set capped = [cand, tgt, max_t] | min %}
          {{ capped | round(1) }}
        reason: >-
          {# Variablen in Attribut-Template erneut setzen, da separat gerendert #}
          {% set enabled    = is_state('input_boolean.energy_manager_enabled','on') %}
          {% set temp_ok    = is_state('input_boolean.energy_manager_temp_ok','on') %}
          {% set safe_off   = is_state('input_boolean.em_safe_mode','off') %}
          {% set avail      = states('sensor.em_available_for_heatpump') | float(0) %}
          {% set start_th   = states('input_number.em_avail_start') | float(0) %}
          {% set target_t   = states('sensor.em_target_flow_temp') | float(0) %}
          {% set current_t  = states('sensor.em_current_flow_temp') | float(0) %}
          {% set hysteresis = 0.2 %}
          {% set reasons = [] %}
          {% if not enabled %}{% set reasons = reasons + ['disabled'] %}{% endif %}
          {% if not temp_ok %}{% set reasons = reasons + ['temp_not_ok'] %}{% endif %}
          {% if not safe_off %}{% set reasons = reasons + ['safe_mode_on'] %}{% endif %}
          {% if not (avail > start_th) %}{% set reasons = reasons + ['avail_below_start'] %}{% endif %}
          {% if not (target_t > current_t + hysteresis) %}{% set reasons = reasons + ['target_not_above_current'] %}{% endif %}
          {{ 'all_conditions_met' if reasons|length == 0 else reasons|join(',') }}
      availability: >-
        {{
          (states('sensor.em_available_for_heatpump') not in ['unknown','unavailable','']) and
          (states('sensor.em_target_flow_temp') not in ['unknown','unavailable','']) and
          (states('sensor.em_current_flow_temp') not in ['unknown','unavailable',''])
        }}

# --- Automationen (alle in einem Block) ---
automation:
  - alias: "EM Temp OK Status aktualisieren"
    description: "Setzt input_boolean.energy_manager_temp_ok basierend auf Temperatur mit Debounce 60s"
    mode: restart
    trigger:
      - platform: state
        entity_id: sensor.boiler_air_inlet_temperature_tl2
    condition: []
    action:
      - choose:
          - conditions:
              - condition: template
                value_template: >-
                  {% set temp = states('sensor.boiler_air_inlet_temperature_tl2') %}
                  {% set start = states('input_number.energy_manager_temp_start') %}
                  {{ temp not in ['unavailable', 'unknown', ''] and
                     start not in ['unavailable', 'unknown', ''] and
                     (temp | float(0)) < (start | float(0)) }}
            sequence:
              - delay: "00:01:00"
              - condition: template
                value_template: >-
                  {% set temp = states('sensor.boiler_air_inlet_temperature_tl2') %}
                  {% set start = states('input_number.energy_manager_temp_start') %}
                  {{ temp not in ['unavailable', 'unknown', ''] and
                     start not in ['unavailable', 'unknown', ''] and
                     (temp | float(0)) < (start | float(0)) }}
              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.energy_manager_temp_ok
          - conditions:
              - condition: template
                value_template: >-
                  {% set temp = states('sensor.boiler_air_inlet_temperature_tl2') %}
                  {% set stop = states('input_number.energy_manager_temp_stop') %}
                  {{ temp not in ['unavailable', 'unknown', ''] and
                     stop not in ['unavailable', 'unknown', ''] and
                     (temp | float(0)) > (stop | float(0)) }}
            sequence:
              - delay: "00:01:00"
              - condition: template
                value_template: >-
                  {% set temp = states('sensor.boiler_air_inlet_temperature_tl2') %}
                  {% set stop = states('input_number.energy_manager_temp_stop') %}
                  {{ temp not in ['unavailable', 'unknown', ''] and
                     stop not in ['unavailable', 'unknown', ''] and
                     (temp | float(0)) > (stop | float(0)) }}
              - service: input_boolean.turn_off
                target:
                  entity_id: input_boolean.energy_manager_temp_ok

  # Automation: EM: Vorlauftemperatur regeln (nur Erhöhungen, kein Absenken)
  - alias: "EM: Vorlauftemperatur regeln"
    description: "Erhöht Selected flow temperature stufenlos mit Ramping (nur Anheben, kein aktives Absenken)"
    trigger:
      - platform: state
        entity_id:
          - sensor.em_available_for_heatpump
          - sensor.em_current_flow_temp
          - input_boolean.energy_manager_enabled
          - input_boolean.energy_manager_temp_ok
    condition:
      - condition: state
        entity_id: input_boolean.energy_manager_enabled
        state: 'on'
      - condition: state
        entity_id: input_boolean.energy_manager_temp_ok
        state: 'on'
      - condition: state
        entity_id: input_boolean.em_safe_mode
        state: 'off'
      # Hysterese-Bedingung: nur wenn verfügbar > Start-Schwelle
      - condition: template
        value_template: >-
          {{ (states('sensor.em_available_for_heatpump') | float(0)) > (states('input_number.em_avail_start') | float(0)) }}
    action:
      - variables:
          target_temp_raw: "{{ states('sensor.em_target_flow_temp') | float(0) }}"
          current_temp: "{{ states('sensor.em_current_flow_temp') | float(0) }}"
          step: "{{ states('input_number.em_flow_temp_step_k') | float(0) }}"
          max_t: "{{ states('input_number.em_flow_temp_max') | float(0) }}"
          last_change: "{{ state_attr('number.boiler_selected_flow_temperature', 'last_changed') }}"
          time_since_change_min: >-
            {% if last_change is none %}
              9999
            {% else %}
              ((as_timestamp(now()) - as_timestamp(last_change)) / 60)
            {% endif %}
      - choose:
          - conditions:
              # Nur erhöhen, wenn Ziel > Ist
              - condition: template
                value_template: >-
                  {{ target_temp_raw > current_temp }}
            sequence:
              - variables:
                  # Kandidat ist Ist + Schritt, aber nicht über Ziel
                  candidate_temp: >-
                    {% set cand = current_temp + step %}
                    {% if cand > target_temp_raw %}
                      {{ target_temp_raw }}
                    {% else %}
                      {{ cand }}
                    {% endif %}
                  # Kappe auf maximalen erlaubten Wert
                  new_temp_capped: >-
                    {{ [ (candidate_temp | float), (max_t | float) ] | min | round(1) }}
              - service: number.set_value
                data:
                  entity_id: number.boiler_selected_flow_temperature
                  value: "{{ new_temp_capped }}"
              - service: system_log.write
                data:
                  message: "EM: Vorlaufregelung erhöht von {{ current_temp }}°C auf {{ new_temp_capped }}°C (Ziel {{ target_temp_raw }}°C, Max {{ max_t }}°C)"
                  level: info
        default: []

  - alias: "EM: DHW Ladung steuern"
    description: "Steuert DHW Charging basierend auf PV Überschuss und Boiler Temperatur, mit Hysterese"
    trigger:
      - platform: state
        entity_id:
          - sensor.em_available_for_heatpump
          - sensor.em_dhw_boiler_temp
          - input_boolean.energy_manager_enabled
          - input_boolean.energy_manager_temp_ok
          - input_boolean.em_dhw_charging
    condition:
      - condition: state
        entity_id: input_boolean.energy_manager_enabled
        state: 'on'
      - condition: state
        entity_id: input_boolean.energy_manager_temp_ok
        state: 'on'
      - condition: state
        entity_id: input_boolean.em_safe_mode
        state: 'off'
    action:
      - variables:
          pv_avail: "{{ states('sensor.em_available_for_heatpump') | float(0) }}"
          boiler_temp: "{{ states('sensor.boiler_heat_carrier_forward_tc1') | float(0) }}"
          dhw_charging: "{{ is_state('input_boolean.em_dhw_charging', 'on') }}"
          max_temp: "{{ states('input_number.em_dhw_max_temp') | float(0) }}"
          min_temp: "{{ states('input_number.em_dhw_min_temp') | float(0) }}"
          min_duration: "{{ states('input_number.em_dhw_charge_min_duration') | int }}"
          last_on: "{{ state_attr('input_boolean.em_dhw_charging', 'last_changed') }}"
          time_on_min: >-
            {% if last_on is none %}
              9999
            {% else %}
              ((as_timestamp(now()) - as_timestamp(last_on)) / 60)
            {% endif %}
          start_thresh: "{{ states('input_number.em_avail_start') | float(0) }}"
          stop_thresh: "{{ states('input_number.em_avail_stop') | float(0) }}"
      - choose:
          # Start DHW Charging wenn PV Überschuss über Startschwelle und Boiler Temp < max_temp
          - conditions:
              - condition: template
                value_template: >-
                  {{ pv_avail > start_thresh }}
              - condition: template
                value_template: >-
                  {{ boiler_temp < max_temp }}
              - condition: template
                value_template: >-
                  {{ not dhw_charging or (dhw_charging and time_on_min > min_duration) }}
            sequence:
              - service: input_boolean.turn_on
                target:
                  entity_id: input_boolean.em_dhw_charging
              - service: switch.turn_on
                target:
                  entity_id: switch.boiler_dhw_one_time_charging
              - service: system_log.write
                data:
                  message: "EM: DHW Charging gestartet (Boiler {{ boiler_temp }}°C, PV Überschuss {{ pv_avail }} kW)"
                  level: info

          # Stop DHW Charging wenn PV unter Stop-Schwelle oder Boiler Temp >= max_temp und Mindestladezeit erfüllt
          - conditions:
              - condition: template
                value_template: >-
                  {{ (boiler_temp >= max_temp) or (pv_avail < stop_thresh) }}
              - condition: template
                value_template: >-
                  {{ dhw_charging and time_on_min > min_duration }}
            sequence:
              - service: input_boolean.turn_off
                target:
                  entity_id: input_boolean.em_dhw_charging
              - service: switch.turn_off
                target:
                  entity_id: switch.boiler_dhw_one_time_charging
              - service: system_log.write
                data:
                  message: "EM: DHW Charging gestoppt (Boiler {{ boiler_temp }}°C, PV Überschuss {{ pv_avail }} kW)"
                  level: info

  - alias: "EM: Aux-Heater Steuerung"
    description: "Blockiert Aux-Heater wenn nicht erlaubt oder Boiler Temp ausreichend, mit Hysterese"
    trigger:
      - platform: state
        entity_id:
          - input_boolean.em_allow_aux
          - sensor.boiler_heat_carrier_forward_tc1
          - input_boolean.em_dhw_charging
          - sensor.em_available_for_heatpump
    condition:
      - condition: state
        entity_id: input_boolean.em_safe_mode
        state: 'off'
    action:
      - variables:
          allow_aux: "{{ is_state('input_boolean.em_allow_aux', 'on') }}"
          boiler_temp: "{{ states('sensor.boiler_heat_carrier_forward_tc1') | float(0) }}"
          min_temp: "{{ states('input_number.em_dhw_min_temp') | float(0) }}"
          dhw_charging: "{{ is_state('input_boolean.em_dhw_charging', 'on') }}"
          pv_avail: "{{ states('sensor.em_available_for_heatpump') | float(0) }}"
          start_thresh: "{{ states('input_number.em_avail_start') | float(0) }}"
          stop_thresh: "{{ states('input_number.em_avail_stop') | float(0) }}"
      - choose:
          - conditions:
              - condition: template
                value_template: >-
                  {{ not allow_aux and boiler_temp > min_temp and dhw_charging and pv_avail > stop_thresh }}
            sequence:
              - service: switch.turn_off
                target:
                  entity_id: switch.boiler_aux_heater_only
              - service: system_log.write
                data:
                  message: "EM: Aux-Heater deaktiviert wegen Energiemanager"
                  level: info

          - conditions:
              - condition: template
                value_template: "{{ allow_aux }}"
            sequence:
              - service: switch.turn_on
                target:
                  entity_id: switch.boiler_aux_heater_only
              - service: system_log.write
                data:
                  message: "EM: Aux-Heater erlaubt durch Energiemanager"
                  level: info

  - alias: "EM: Force smoothed zero on startup"
    description: "Setzt beim HA-Start kurzzeitig das Force-Zero-Flag, bis Rohsensoren initialisiert sind"
    mode: single
    trigger:
      - platform: homeassistant
        event: start
    action:
      - service: input_boolean.turn_on
        target:
          entity_id: input_boolean.energy_manager_force_zero
      - wait_for_trigger:
          - platform: template
            value_template: >-
              {% set s1 = states('sensor.my_home_solar_energie') %}
              {% set s2 = states('sensor.my_home_last_leistung') %}
              {% set s3 = states('sensor.my_home_batterie_leistung') %}
              {{ [s1, s2, s3] | select('match', '^(?!unknown$|^unavailable$|^$).+') | list | count > 0 }}
        timeout: "00:00:20"
      - delay: "00:00:02"
      - service: homeassistant.update_entity
        target:
          entity_id:
            - sensor.em_pv_power_smoothed
            - sensor.em_home_load_smoothed
            - sensor.em_powerwall_battery_power_smoothed
            - sensor.em_pv_power_corrected
            - sensor.em_home_load_corrected
            - sensor.em_powerwall_charge_corrected
            - sensor.em_energy_surplus
            - sensor.em_available_for_heatpump
            - sensor.em_pw_current_charge
            - sensor.em_pw_max_charge
            - sensor.em_target_flow_temp
            - sensor.em_current_flow_temp
            - sensor.boiler_heat_carrier_forward_tc1
      - delay: "00:00:01"
      - service: input_boolean.turn_off
        target:
          entity_id: input_boolean.energy_manager_force_zero

  - alias: "EM: Aux-Heater max Laufzeit"
    description: "Schaltet den Aux-Heater automatisch nach definierter Zeit wieder aus (Failsafe)"
    mode: restart
    trigger:
      - platform: state
        entity_id: switch.boiler_aux_heater_only
        to: "on"
        for: "00:20:00"
    condition: []
    action:
      - service: switch.turn_off
        target:
          entity_id: switch.boiler_aux_heater_only
      - service: system_log.write
        data:
          message: "EM: Aux-Heater wurde nach 20 Minuten automatisch abgeschaltet (Failsafe)"
          level: warning

  - alias: "EM: Aux-Heater aus bei keinem PV-Überschuss"
    description: "Schaltet den Aux-Heater aus, wenn kein ausreichender PV-Überschuss vorhanden ist"
    mode: restart
    trigger:
      - platform: numeric_state
        entity_id: sensor.em_available_for_heatpump
        below: 0.3
        for: "00:02:00"
    condition: []
    action:
      - condition: state
        entity_id: switch.boiler_aux_heater_only
        state: "on"
      - service: switch.turn_off
        target:
          entity_id: switch.boiler_aux_heater_only
      - service: system_log.write
        data:
          message: "EM: Aux-Heater deaktiviert wegen fehlendem PV-Überschuss"
          level: warning
          
  - alias: "EM: Moduswechsel ausführen"
    mode: single
    trigger:
      - platform: state
        entity_id: input_select.energy_manager_mode
    action:
      - service: script.em_set_mode
      
  - alias: "EM: HARD Restore Modus nach Neustart"
    mode: single

    trigger:
      - platform: homeassistant
        event: start

    action:
      # ⏱ wirklich warten bis alles stabil ist
      - delay: "00:00:20"

      # 🧠 Modus hart lesen (mit Fallback!)
      - variables:
          mode: "{{ states('input_select.energy_manager_mode') | default('Winter') }}"

      # 🧯 Debug zur Kontrolle
      - service: system_log.write
        data:
          message: "EM START: gespeicherter Modus = {{ mode }}"
          level: warning

      # 🔥 HARTE WIEDERHERSTELLUNG
      - choose:
          - conditions:
              - condition: template
                value_template: "{{ mode == 'Sommer' }}"
            sequence:
              - service: script.em_set_mode

          - conditions:
              - condition: template
                value_template: "{{ mode == 'Winter' }}"
            sequence:
              - service: script.em_set_mode