LIVE
Loading live headlines…
Home Trending World Technology Entertainment Gaming Sports Music Science Lifestyle Business About Contact
c/energie by u/favstarmafia 3w ago

Mach deine PV-Anlage mit Home Assistant netzdienlich: Prognosebasierte Einspeisespitzenkappung statt einfachem Peak-Shaving

13 upvotes 0 comments
# Mach deine PV-Anlage mit Home Assistant netzdienlich: Prognosebasierte Einspeisespitzenkappung statt einfachem Peak-Shaving

## Was mich dazu gebracht hat

An sonnigen Sommertagen läuft meine PV-Anlage mittags auf Hochtouren. Der Akku ist längst voll, und der Rest fließt ins Netz — genau dann, wenn tausende andere Anlagen dasselbe tun. Ich habe mich irgendwann gefragt: Ist das wirklich das Beste, was ich mit meiner Anlage und Home Assistant machen kann?

Die Antwort ist nein. Und dieser Artikel beschreibt, was ich stattdessen gebaut habe.

Es geht nicht darum, Geld zu sparen — das tue ich damit nicht, zumindest nicht direkt. Es geht darum zu verstehen, was möglich wäre, wenn das viele täten. Denn die Kosten für den Netzausbau, den diese Mittagsspitzen erzwingen, zahlen am Ende alle Haushalte über die Netzentgelte.

## Was ist der Unterschied zu kommerziellem Peak-Shaving?

Hersteller wie SENEC bewerben ihre Speicher gerne mit dem Begriff "Peak-Shaving" oder "netzdienlichem Laden". Was dahinter steckt, ist allerdings bescheidener als der Name vermuten lässt: Der Akku wird morgens nicht sofort geladen, sondern der Überschuss wird zunächst eingespeist. Erst wenn die Produktion mittags ihren Höhepunkt erreicht, beginnt die Ladung des Akkus.

Das ist im Kern eine kleine Verschiebung der normalen Eigenverbrauchsoptimierung. Morgens speist die Anlage trotzdem ein, und es gibt keine garantierte freie Kapazität zum eigentlichen Mittagspeak. Der Netzeffekt ist entsprechend gering.

Mein Ansatz funktioniert anders, weshalb ich ihn bewusst **prognosebasierte Einspeisespitzenkappung** nenne:

Ich berechne jeden Morgen, wie viel die Anlage noch produzieren wird. Daraus ergibt sich, wie viel freie Kapazität ich im Akku brauche, um den Mittagspeak vollständig aufzunehmen. Ist der Akku zu voll, wird er **aktiv entladen** — bevor der Peak kommt. Der Produktionspeak fließt dann in den Akku statt ins Netz.

Kein Reagieren, sondern Planen.

## Warum das trotzdem niemand macht

Weil es sich finanziell nicht lohnt. Der Akku wird mehr belastet, man verzichtet auf einen Teil der frühen Eigenverbrauchsoptimierung, und es gibt keine Vergütung dafür. Die Einsparung bei den Netzentgelten kommt bei allen an — auch bei denen, die nichts dazu beitragen.

Klassisches Kollektivgut-Problem.

Ich mache es trotzdem, weil ich verstehen will wie es geht und weil ich hoffe, dass andere die Idee aufgreifen. Wenn das zum Standard für Heimspeicher würde, könnten die Mittagsspitzen im Niederspannungsnetz erheblich reduziert werden — ohne dass dafür ein einziger Meter Kabel neu verlegt werden müsste.

## Wie der Algorithmus funktioniert

*Dieser Abschnitt richtet sich an alle — auch ohne technisches Vorwissen.*

### Die Grundidee

Zwei Fragen stehen im Mittelpunkt:

1. Wie viel wird die Anlage heute noch produzieren?
2. Wie viel freie Kapazität brauche ich dafür im Akku?

Aus diesen beiden Werten ergibt sich ein **Ziel-SOC** — also ein Zielwert für den Ladezustand kurz vor dem Fenster der maximalen Einspeisung, also der Phase, in der die Anlage am meisten produziert und ohne Steuerung am stärksten ins Netz einspeisen würde. Ist der Akku voller als dieser Zielwert, entlädt die Steuerung ihn aktiv: Zu diesem Zeitpunkt ist die PV-Produktion noch gering, der Akku übernimmt die Hausversorgung und wird dabei auf den Zielwert entladen. Ist er schon leer genug, passiert nichts.

Ein Beispiel: Die Prognose sagt 8 kWh für den Rest des Tages. Der Akku fasst 10 kWh. Dann sollte der Ladezustand vor dem Fenster der maximalen Einspeisung bei etwa 20 % liegen. Steht er gerade bei 75 %, muss er vorher entladen werden.

### Wann genau?

Die Steuerung berechnet aus dem Fenster der maximalen Einspeisung und der Ladegeschwindigkeit des Akkus zwei Zeitpunkte:

- **Startzeit**: Genau so früh wie nötig, damit der Akku rechtzeitig den Ziel-SOC erreicht — nicht früher. Bei sich verschlechternder Prognose verschiebt sich der Start automatisch nach hinten oder entfällt ganz.
- **Stoppzeit**: So gewählt, dass die anschließende Ladephase symmetrisch um den prognostizierten Peak liegt — also etwa eine halbe Ladezeit vor dem Peak. Der Stopp greift wenn beide Bedingungen erfüllt sind: die berechnete Stoppzeit ist erreicht UND der SOC liegt innerhalb von 10 Prozentpunkten über dem Zielwert. Das verhindert, dass die Entladung stoppt obwohl der Akku noch deutlich zu voll ist.

Das Startfenster ist bewusst schmal (30 Minuten), damit die Steuerung nicht zu früh reagiert und bei wechselhaftem Wetter keine unnötigen Entladezyklen entstehen.

### Woher kommt das Fenster der maximalen Einspeisung — besonders bei Ost-West-Anlagen

Bei einer reinen Südausrichtung ist das Fenster der maximalen Einspeisung leicht zu bestimmen: irgendwann kurz nach Mittag. Bei einer Ost-West-Anlage wie meiner ist es komplizierter: Morgens produziert die Ostseite, abends die Westseite — das Gesamtmaximum liegt irgendwo dazwischen und verschiebt sich je nach Jahreszeit und Wetter.

Die Lösung ist ein **gewichteter Mittelwert** aus den Peakzeiten beider Seiten, wobei die installierte Leistung als Gewicht dient:

> Peakzeit = (Peakzeit Ost × kWp Ost + Peakzeit West × kWp West) ÷ (kWp Ost + kWp West)

Bei meiner Anlage mit 3,6 kWp Ost und 2,0 kWp West fließt die Ostseite also stärker in die Berechnung ein. Wer eine andere Aufteilung hat, passt die Zahlen entsprechend an — das Prinzip funktioniert für jede Kombination.

### Zwei Prognosequellen

Ich verwende zwei Wetterdienste parallel:

- **Forecast.Solar** liefert die Energiemenge (kWh) für heute und den Restanteil — diese Werte fließen direkt in die Berechnung des Ziel-SOC ein.
- **OpenMeteo** liefert die Peakzeiten für Ost- und Westseite getrennt.

Beide verhalten sich merklich unterschiedlich — Forecast.Solar ist in meiner Erfahrung deutlich konservativer als OpenMeteo. Da die Prognosequalität direkt die Steuerung beeinflusst, gibt es einen einstellbaren **Korrekturfaktor**, mit dem man die Prognose nach oben oder unten skalieren kann. Nach einigen Wochen Daten lässt sich dieser Wert auf die eigene Anlage kalibrieren.

### Kein Netzbezug — oberstes Ziel, keine Garantie

Wenn die Steuerung den Akku entlädt, soll das nicht dazu führen, dass später Strom aus dem Netz bezogen werden muss. Das ist das oberste Ziel — aber keine Garantie. Bei einer zu optimistischen Prognose kann der Akku zu stark entladen werden, die PV liefert weniger als erwartet, und es entsteht trotzdem Netzbezug für mehrere Stunden. Dafür gibt es zwei Schutzebenen:

Ein konfigurierbarer **Mindest-SOC** (Standard: 15 %) sorgt dafür, dass der Akku nie vollständig leer entladen wird. Und sobald die Steuerung erkennt, dass trotzdem Netzbezug entsteht — etwa weil ein Verbraucher kurz viel zieht — schaltet sie sofort zurück in den normalen Eigenverbrauchsmodus.

### Ein ehrlicher Hinweis zur Akkubelastung

Durch das aktive Entladen vor dem Peak durchläuft der Akku täglich einen zusätzlichen Lade- und Entladevorgang — je nach Prognose mit unterschiedlicher Tiefe. An einem typischen Sommertag bedeutet das eine Entladung von z.B. 75 % auf 20 % vor dem Peak und anschließend eine Volladung durch die PV. Das entspricht annähernd einem zusätzlichen Vollzyklus pro Tag. Da die Steuerung nur im Sommer aktiv ist, landet man über das Jahr bei grob geschätzt 40–60 % mehr Vollzyklen als ohne diese Steuerung — der genaue Wert hängt stark von Wetter, Anlagengröße und Eigenverbrauch ab. Moderne LFP-Akkus sind für sehr viele tausend Zyklen ausgelegt — aber wer einen älteren oder kleineren Akku hat, sollte das einkalkulieren.

---

## Die Umsetzung mit Home Assistant

*Ab hier wird es technischer. Dieser Abschnitt richtet sich an Nutzer, die sich mit Home Assistant bereits auskennen und schon mit Automatisierungen und Blueprints gearbeitet haben.*

### Meine Komponenten

- **PV-Anlage**: Ost-West, 3,6 kWp Ost (Azimut 90°, 25° Neigung) + 2,0 kWp West (Azimut 270°, 25° Neigung)
- **Wechselrichter**: Huawei SUN2000-5KTL-M1 mit Huawei Solar Custom Integration
- **Heimspeicher**: 10 kWh LUNA 2000, Entladeleistung 3,4 kW
- **Prognosedienste**: Forecast.Solar Integration und OpenMeteo Solar Forecast Integration

### Wie die Teile zusammenspielen

Die Steuerung besteht aus drei Bausteinen:

**Template-Sensoren** berechnen die gewichteten Peakzeiten aus den Rohdaten beider Prognosedienste. Diese Sensoren sind die Grundlage für die Zeitplanung im Blueprint und müssen einmalig in der `configuration.yaml` angelegt werden (siehe Anhang).

**Das Blueprint** enthält die eigentliche Steuerungslogik: Ziel-SOC berechnen, Start- und Stoppzeiten bestimmen, und den Betriebsmodus des Wechselrichters schalten. Es läuft als normaler HA-Trigger alle 5 Minuten sowie bei bestimmten Ereignissen.

**Der Wechselrichter** kennt verschiedene Betriebsmodi. Im Modus `maximise_self_consumption` optimiert er den Eigenverbrauch normal. Im Modus `fully_fed_to_grid` entlädt der Akku aktiv ins Hausnetz. Zwischen diesen beiden Modi schaltet das Blueprint hin und her. Wer einen anderen Wechselrichter hat, braucht entsprechende Schaltmöglichkeiten — das Prinzip ist übertragbar, die konkreten Entitätsnamen müssen angepasst werden. Ein LLM kann dabei gut helfen.

### Was zwingend erforderlich ist

Wer das Blueprint adaptieren möchte, braucht diese Bausteine — unabhängig vom Hersteller:

**Sensoren (lesend):**
- Aktueller Ladezustand des Akkus in Prozent
- Aktuelle PV-Produktion in Watt
- Aktuelle Lade- oder Entladeleistung des Akkus in Watt (mit Vorzeichen — positiv = laden, negativ = entladen)
- Netzbezug in kW (live)
- Heutige Gesamtprognose in kWh
- Restprognose für heute in kWh
- Gewichteter Peakzeit-Sensor in HH:MM (Template-Sensor, siehe Anhang)

**Steuerung (schreibend):**
- Schaltbarer Betriebsmodus des Wechselrichters oder Speichers — mindestens Eigenverbrauch und aktive Entladung

**Hilfs-Entität:**
- Ein `input_text` für den zuletzt ausgeführten Fall — wird vom Blueprint beschrieben und hilft bei der Fehlersuche

### Optionale Erweiterung: Akku-Richtung als Sensor

Nützlich für die Beobachtung des Systems ist ein einfacher Template-Sensor, der den aktuellen Akkuzustand als lesbaren Text darstellt: `laden`, `entladen` oder `idle`. Mit einer 100W-Schwelle werden kurze Schwankungen herausgefiltert. Dieser Sensor lässt sich auch als Trigger für ein erweitertes Logging verwenden — immer wenn der Akku die Richtung wechselt, wird ein Datensatz geschrieben. Das macht den Tagesverlauf später gut auswertbar.

---

## Aktueller Stand und Ausblick

Die Steuerung läuft seit kurzem und ich beobachte die ersten Ergebnisse. Der Korrekturfaktor steht noch auf dem Standardwert 1,0 — nach ausreichend Vergleichsdaten zwischen Prognose und tatsächlichem Ertrag werde ich ihn kalibrieren. Was ich dabei lerne, werde ich direkt in diesen Artikel einfließen lassen.

Fragen, Erfahrungen aus anderen Anlagen und Anpassungen für andere Wechselrichter sind sehr willkommen.

*Dieser Artikel wird aktiv weiterentwickelt. Die Steuerung läuft seit kurzem, Daten zur Prognosequalität und Kalibrierung des Korrekturfaktors folgen in einigen Wochen. Wer das Blueprint bereits adaptiert oder Erfahrungen mit ähnlichen Ansätzen hat, ist eingeladen das hier zu diskutieren — das hilft dabei, den Artikel zu verbessern.*

---

## Anhang: Code

### Template-Sensor: Gewichtete Peakzeit (OpenMeteo)

Dieser Sensor berechnet die gewichtete Peakzeit aus den OpenMeteo-Peakzeiten für Ost- und Westseite. Die Gewichte (3600 und 2000) entsprechen den installierten Watt-Peak — diese Werte müssen auf die eigene Anlage angepasst werden. Der Divisor (5600) ist die Summe beider Werte.

In der `configuration.yaml` unter dem `template:` Block einfügen:

```yaml
- name: "PV Peak Zeit Gewichtet"
unique_id: pv_peak_zeit_gewichtet
icon: mdi:clock-outline
state: >
{% set t_ost = states('sensor.solar_ost_power_highest_peak_time_today') %}
{% set t_west = states('sensor.solar_west_power_highest_peak_time_today') %}
{% if t_ost not in ['unknown', 'unavailable', ''] and t_west not in ['unknown', 'unavailable', ''] %}
{% set ost_min = (t_ost | as_timestamp | timestamp_custom('%H:%M', true))[0:2] | int * 60
+ (t_ost | as_timestamp | timestamp_custom('%H:%M', true))[3:5] | int %}
{% set west_min = (t_west | as_timestamp | timestamp_custom('%H:%M', true))[0:2] | int * 60
+ (t_west | as_timestamp | timestamp_custom('%H:%M', true))[3:5] | int %}
{% set peak = (ost_min * 3600 + west_min * 2000) / 5600 %}
{{ '%02d:%02d' | format((peak // 60) | int, (peak % 60) | int) }}
{% else %}
unknown
{% endif %}
```

### Template-Sensor: Gewichtete Peakzeit (Forecast.Solar, optional)

Wer beide Prognosedienste vergleichen möchte, kann zusätzlich diesen Sensor anlegen. Die Sensornamen `sensor.power_highest_peak_time_today` und `sensor.power_highest_peak_time_today_2` stammen aus der Forecast.Solar Integration — `_2` bezeichnet die zweite konfigurierte Anlagenausrichtung.

```yaml
- name: "PV Peak Zeit Gewichtet Forecast Solar"
unique_id: pv_peak_zeit_gewichtet_forecast_solar
icon: mdi:clock-outline
state: >
{% set t_ost = states('sensor.power_highest_peak_time_today') %}
{% set t_west = states('sensor.power_highest_peak_time_today_2') %}
{% if t_ost not in ['unknown', 'unavailable', ''] and t_west not in ['unknown', 'unavailable', ''] %}
{% set ost_min = (t_ost | as_timestamp | timestamp_custom('%H:%M', true))[0:2] | int * 60
+ (t_ost | as_timestamp | timestamp_custom('%H:%M', true))[3:5] | int %}
{% set west_min = (t_west | as_timestamp | timestamp_custom('%H:%M', true))[0:2] | int * 60
+ (t_west | as_timestamp | timestamp_custom('%H:%M', true))[3:5] | int %}
{% set peak = (ost_min * 3600 + west_min * 2000) / 5600 %}
{{ '%02d:%02d' | format((peak // 60) | int, (peak % 60) | int) }}
{% else %}
unknown
{% endif %}
```

### Template-Sensor: Akku-Richtung (optional, für Logging)

```yaml
- name: "Akku Richtung"
unique_id: akku_richtung
icon: mdi:battery-arrow-up
state: >
{% set w = states('sensor.batterien_lade_entladeleistung') | float(0) %}
{% if w > 100 %}
laden
{% elif w < -100 %}
entladen
{% else %}
idle
{% endif %}
```

### Das Blueprint

Die Sensornamen (`sensor.batterien_batterieladung`, `sensor.energy_production_today_remaining` etc.) und Betriebsmodi (`maximise_self_consumption`, `fully_fed_to_grid`) stammen aus der Huawei Solar Integration und müssen für andere Systeme angepasst werden. Die Steuerungslogik selbst ist herstellerunabhängig.

```yaml
blueprint:
name: "PV Peak-Shave v2 (Akku symmetrisch um Peak)"
description: >
Entlädt den Akku rechtzeitig vor dem PV-Peak ins Netz, sodass die
verfügbare Akku-Kapazität symmetrisch um den prognostizierten
Peak-Zeitpunkt herum geladen werden kann. Der Ziel-SOC wird dynamisch
aus der verbleibenden PV-Restprognose berechnet.

Anker für die Berechnung: sensor.pv_peak_zeit_gewichtet
(gewichteter Mittelwert OpenMeteo Ost/West).

Höchste Priorität: kein Netzbezug.
domain: automation

input:

min_ziel_soc:
name: Min Ziel-SOC beim Entladen (%)
description: >
Sicherheitspuffer – der Akku wird nie unter diesen SOC entladen,
auch wenn die Restprognose eine tiefere Entladung erlauben würde.
default: 15
selector:
number:
min: 5
max: 50
step: 5
unit_of_measurement: "%"

prognose_korrekturfaktor:
name: Prognose-Korrekturfaktor
description: >
Multiplikator auf die Forecast.Solar Restprognose.
1.0 = keine Korrektur, 0.8 = 20% Abschlag.
Nach einigen Wochen Daten anpassen.
default: 1.0
selector:
number:
min: 0.5
max: 1.5
step: 0.05

netzbezug_schwelle:
name: Netzbezugs-Schwelle (W)
description: >
Wenn der Netzbezug diesen Wert überschreitet, wird sofort auf
Maximaler Eigenverbrauch zurückgeschaltet.
default: 500
selector:
number:
min: 100
max: 2000
step: 50
unit_of_measurement: W

netzbezug_dauer:
name: Netzbezugs-Dauer vor Abbruch (s)
description: >
Der Netzbezug muss diese Zeit lang über der Schwelle liegen,
bevor abgebrochen wird (verhindert kurze Spitzen).
default: 60
selector:
number:
min: 10
max: 300
step: 10
unit_of_measurement: s

mode: single
max_exceeded: silent

trigger:
- platform: time_pattern
minutes: "/5"
id: "tick"

- platform: numeric_state
entity_id: sensor.batterien_batterieladung
below: !input min_ziel_soc
id: "min_soc_unterschritten"

- platform: numeric_state
entity_id: sensor.netzbezug_live
above: !input netzbezug_schwelle
for:
seconds: !input netzbezug_dauer
id: "netzbezug_alarm"

variables:
min_ziel_soc_var: !input min_ziel_soc
prognose_korrekturfaktor_var: !input prognose_korrekturfaktor
netzbezug_schwelle_var: !input netzbezug_schwelle

# Anlagen-Konstanten – auf eigene Anlage anpassen
# Hier die kleinere der beiden Leistungen (Laden/Entladen) eintragen –
# bei asymmetrischen Speichern ergibt das einen konservativeren, also früheren Stoppzeitpunkt.
speicher_kwh: 10
entladeleistung_kw: 3.4
ladeleistung_kw: 3.4

# Dynamischer Ziel-SOC aus Restprognose
restprognose_kwh: >
{{ (states('sensor.energy_production_today_remaining') | float(0)
+ states('sensor.energy_production_today_remaining_2') | float(0))
* prognose_korrekturfaktor_var }}
ziel_soc_var: >
{{ [100 - (restprognose_kwh / speicher_kwh * 100) | int, min_ziel_soc_var] | max }}

# Peak-Zeit aus gewichtetem Sensor
peak_str: "{{ states('sensor.pv_peak_zeit_gewichtet') }}"
peak_ts: >
{% if peak_str not in ['unknown', 'unavailable', ''] %}
{{ today_at(peak_str) | as_timestamp(0) }}
{% else %}
0
{% endif %}

# Berechnete Zeiten
aufnahme_kwh: "{{ (100 - ziel_soc_var) / 100 * speicher_kwh }}"
halbe_ladezeit_min: "{{ (aufnahme_kwh / ladeleistung_kw * 60 / 2) | int }}"
stopp_ts: "{{ peak_ts - halbe_ladezeit_min * 60 if peak_ts > 0 else 0 }}"
soc_aktuell: "{{ states('sensor.batterien_batterieladung') | float(0) }}"
entladbar_kwh: "{{ (soc_aktuell - ziel_soc_var) / 100 * speicher_kwh }}"
entladezeit_min: "{{ (entladbar_kwh / entladeleistung_kw * 60) | int }}"
start_ts: "{{ stopp_ts - entladezeit_min * 60 if stopp_ts > 0 else 0 }}"

action:
- choose:

# ══════════════════════════════════════════════════════════════
# FALL A: Notabbruch – Netzbezug zu hoch
# ══════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "netzbezug_alarm"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
sequence:
- action: input_text.set_value
target:
entity_id: input_text.peakshave_letzter_fall
data:
value: >
A|{{ peak_str }}|{{ stopp_ts | timestamp_custom('%H:%M', true) if stopp_ts > 0 else 'n/a' }}|{{ start_ts | timestamp_custom('%H:%M', true) if start_ts > 0 else 'n/a' }}|{{ entladezeit_min }}|{{ halbe_ladezeit_min }}|{{ ziel_soc_var | round(0) }}|{{ restprognose_kwh | round(1) }}
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption

# ══════════════════════════════════════════════════════════════
# FALL B: Sicherheitsstopp – Min-SOC unterschritten
# ══════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "min_soc_unterschritten"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
sequence:
- action: input_text.set_value
target:
entity_id: input_text.peakshave_letzter_fall
data:
value: >
B|{{ peak_str }}|{{ stopp_ts | timestamp_custom('%H:%M', true) if stopp_ts > 0 else 'n/a' }}|{{ start_ts | timestamp_custom('%H:%M', true) if start_ts > 0 else 'n/a' }}|{{ entladezeit_min }}|{{ halbe_ladezeit_min }}|{{ ziel_soc_var | round(0) }}|{{ restprognose_kwh | round(1) }}
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption

# ══════════════════════════════════════════════════════════════
# FALL D: Geplanter Stopp – Stoppzeit erreicht UND SOC nahe Zielwert
# Beide Bedingungen müssen erfüllt sein: now >= stopp_ts
# und soc_aktuell <= ziel_soc_var + 10 (Toleranzpuffer)
# ══════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "tick"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
- condition: template
value_template: >
{% if peak_ts == 0 %}
false
{% else %}
{{ now().timestamp() >= stopp_ts and soc_aktuell <= ziel_soc_var + 10 }}
{% endif %}
sequence:
- action: input_text.set_value
target:
entity_id: input_text.peakshave_letzter_fall
data:
value: >
D|{{ peak_str }}|{{ stopp_ts | timestamp_custom('%H:%M', true) if stopp_ts > 0 else 'n/a' }}|{{ start_ts | timestamp_custom('%H:%M', true) if start_ts > 0 else 'n/a' }}|{{ entladezeit_min }}|{{ halbe_ladezeit_min }}|{{ ziel_soc_var | round(0) }}|{{ restprognose_kwh | round(1) }}
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption

# ══════════════════════════════════════════════════════════════
# FALL E: Geplanter Start
# ══════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "tick"
- condition: not
conditions:
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
- condition: state
entity_id: sun.sun
state: "above_horizon"
- condition: template
value_template: >
{{ restprognose_kwh >= (100 - ziel_soc_var) / 100 * speicher_kwh }}
- condition: template
value_template: >
{{ soc_aktuell > ziel_soc_var + 5 }}
- condition: template
value_template: >
{% if peak_ts == 0 %}
false
{% else %}
{% set jetzt = now().timestamp() %}
{{ jetzt >= start_ts and jetzt < (start_ts + 1800) }}
{% endif %}
sequence:
- action: input_text.set_value
target:
entity_id: input_text.peakshave_letzter_fall
data:
value: >
E|{{ peak_str }}|{{ stopp_ts | timestamp_custom('%H:%M', true) if stopp_ts > 0 else 'n/a' }}|{{ start_ts | timestamp_custom('%H:%M', true) if start_ts > 0 else 'n/a' }}|{{ entladezeit_min }}|{{ halbe_ladezeit_min }}|{{ ziel_soc_var | round(0) }}|{{ restprognose_kwh | round(1) }}
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: fully_fed_to_grid
```
Open discussion