Home Assistant Ampel‐Logik für Verbrauchersteuerung - Kieft-C/Zendure-BKW-PV GitHub Wiki

Home Assistant Ampel-Logik für Verbrauchersteuerung

(Zendure Hyper 2000 + Shelly 3EM + Solcast Forecast)

Diese Konfiguration erstellt eine visuelle Ampelanzeige (grün / orange / rot) in Home Assistant, um zu entscheiden:

„Kann ich zusätzliche Verbraucher einschalten?“

Die Entscheidung basiert auf:

  • aktueller Leistungsaufnahme
  • verfügbarer Energie
  • Batteriestand (SOC)
  • PV-Ertragsprognose der nächsten Tage

Voraussetzungen

Diese Karte benötigt zwingend folgende Custom Components:


⚙️ Lovelace Konfiguration

Wichtig:
Alle YOUR_... Entitäten müssen an dein System angepasst werden

type: entities
entities:
  - entity: sensor.YOUR_POWER_SENSOR
    type: custom:multiple-entity-row
    name: Verbraucher einschalten?
    secondary_info: false
    show_state: false
    entities:
      - icon: mdi:circle
      - icon: mdi:circle
      - icon: mdi:circle
    card_mod:
      style:
        .: >
          {% set power = states('sensor.YOUR_POWER_SENSOR') | int(0) %}

          {% set energie =
            (states('sensor.YOUR_BATTERY_KWH') | float(0)) +
            (states('sensor.YOUR_PV_FORECAST_TODAY') | float(0)) %}

          {% set soc_a = states('sensor.YOUR_SOC_A') | float(0) %}
          {% set min_soc_a = states('number.YOUR_MIN_SOC_A') | float(0) %}

          {% set soc_b = states('sensor.YOUR_SOC_B') | float(0) %}
          {% set min_soc_b = states('number.YOUR_MIN_SOC_B') | float(0) %}

          {% set puffer = 15 %}

          {% if min_soc_a > 0 %}
            {% set orange_a = min_soc_a + puffer * ((100 / min_soc_a) | log) %}
            {% set rot_a    = min_soc_a + (puffer / 2) * ((100 / min_soc_a) | log) %}
          {% else %}
            {% set orange_a = 0 %}
            {% set rot_a    = 0 %}
          {% endif %}

          {% if min_soc_b > 0 %}
            {% set orange_b = min_soc_b + puffer * ((100 / min_soc_b) | log) %}
            {% set rot_b    = min_soc_b + (puffer / 2) * ((100 / min_soc_b) | log) %}
          {% else %}
            {% set orange_b = 0 %}
            {% set rot_b    = 0 %}
          {% endif %}

          {% set soc_rot    = soc_a < rot_a or soc_b < rot_b %}
          {% set soc_orange = soc_a < orange_a or soc_b < orange_b %}

          {% set tagesverbrauch = 2.5 %}
          {% set akku_max = 5.0 %}

          {% set min_reserve =
            (min_soc_a / 100 * 3) +
            (min_soc_b / 100 * 2) %}

          {% set akku_start = states('sensor.YOUR_BATTERY_KWH') | float(0) %}
          {% set forecast_morgen = states('sensor.YOUR_FORECAST_DAY_2') | float(0) %}
          {% set forecast_tag3   = states('sensor.YOUR_FORECAST_DAY_3') | float(0) %}

          {% set akku_tag1 = [akku_start + forecast_morgen - tagesverbrauch, akku_max] | min %}
          {% set akku_tag2 = [akku_tag1 + forecast_tag3 - tagesverbrauch, akku_max] | min %}

          {% set forecast_rot =
            akku_tag1 < min_reserve or
            akku_tag2 < min_reserve %}

          {% set forecast_orange =
            akku_tag1 < (min_reserve * 1.5) or
            akku_tag2 < (min_reserve * 1.5) %}

          {% if power > 1200 or energie < 2 or soc_rot or forecast_rot %}
            {% set ampel = 'red' %}
          {% elif power > 600 or energie < 3 or soc_orange or forecast_orange %}
            {% set ampel = 'orange' %}
          {% else %}
            {% set ampel = 'green' %}
          {% endif %}

          div.entity:nth-child(1) state-badge {
            color: {{ '#00ff00' if ampel == 'green' else '#143d00' }};
            transform: scale(1.9);
            margin: 0 15px;
          }

          div.entity:nth-child(2) state-badge {
            color: {{ '#ffaa00' if ampel == 'orange' else '#3d1f00' }};
            transform: scale(1.9);
            margin: 0 15px;
          }

          div.entity:nth-child(3) state-badge {
            color: {{ '#ff0000' if ampel == 'red' else '#3d0000' }};
            transform: scale(1.9);
            margin: 0 15px;
          }

          .entities-row {
            justify-content: center;
          }