PV-Peak-Shave mit Home Assistant und Huawei LUNA2000 (Grünspeicher selbst gebaut)
PV-Peak-Shave mit Home Assistant und Huawei LUNA2000 (Grünspeicher selbst gebaut)
Was ist das hier?
Eine Home Assistant Automation (Blueprint) die meinen Hausakku vor der solaren Mittagsspitze gezielt ins Netz entlädt - damit der Akku leer ist wenn die PV-Spitze kommt und diese vollständig aufgenommen werden kann, statt ins Netz zu drücken. Das Ziel ist Netzdienlichkeit, nicht Gewinnmaximierung.
Warum Peak-Shave?
Das Stromnetz hat täglich ein massives Problem: Zwischen 11 und 14 Uhr speisen Millionen PV-Anlagen gleichzeitig ins Netz ein. Die Netzfrequenz steigt, Regelenergie wird teuer, im Extremfall müssen Anlagen abgeregelt werden.
Ein Hausakku könnte helfen — aber nur wenn er zur richtigen Zeit leer ist. Im Normalbetrieb lädt der Akku am Morgen und ist zur Mittagsspitze bereits voll. Er kann dann die PV-Spitze nicht mehr aufnehmen und die überschüssige Energie geht trotzdem ins Netz.
Die Idee: Den Akku vor dem Peak aktiv entladen, damit er die Spitze aufnehmen kann. Der Akku verhält sich dann wie ein Grünspeicher — er verschiebt Energie zeitlich statt sie zu verschleiern.
Voraussetzungen
Hardware:
- Huawei SUN2000 Wechselrichter (M1 oder MB0 Serie)
- Huawei LUNA2000 Batteriespeicher
- Huawei Smart Dongle (WLAN-FE oder 4G)
Software:
- Home Assistant (aktuell)
- huawei_solar Integration v1.6.0 oder neuer
- Schreibzugriff auf den Wechselrichter aktiviert (in der Integration unter "Berechtigungen erhöhen")
- Forecast.Solar Integration für Tagesprognose
Benötigte Entitäten:
select.batterien_betriebsmodus— Betriebsmodus umschaltensensor.batterien_batterieladung— aktueller SOC in %sensor.netzbezug_live— aktueller Netzbezug in Wsensor.sun_next_noon— Zeitpunkt des nächsten Sonnenhöchststandssensor.energy_production_today— Tagesprognose Ost-Dach (Forecast.Solar)sensor.energy_production_today_2— Tagesprognose West-Dach (Forecast.Solar)sensor.energy_production_today_remaining— Restprognose ab jetztsensor.energy_production_today_remaining_2— Restprognose ab jetzt (zweiter String)
Die Entity-IDs können bei eurer Installation abweichen — bitte anpassen.
Die Logik in einfacher Sprache
Wann startet die Automation?
Einmal täglich wird geprüft ob Peak-Shave heute sinnvoll ist:
- Die Tagesprognose muss über einem einstellbaren Schwellwert liegen (Standard 15 kWh)
- Der Akku muss genug Ladung haben (mehr als Ziel-SOC + 5%)
- Die Sonne muss aufgegangen sein
- Es muss noch genug Zeit bis zum Sonnenhöchststand sein
Wann genau startet sie?
Der Startzeitpunkt wird dynamisch berechnet:
Startzeit = Solar-Noon − Puffer (90 Min.) − Entladezeit − 10 Min. Sicherheit
Die Entladezeit hängt vom aktuellen SOC ab — je voller der Akku, desto früher startet die Automation. Bei SOC 80% und 5 kW Entladeleistung dauert es etwa 100 Minuten den Akku auf 20% zu entladen. Die Automation startet dann entsprechend früher.
Was passiert während des Entladens?
Der Wechselrichter wird auf fully_fed_to_grid gesetzt — PV-Strom und Akkustrom gehen ins Netz. Die Automation läuft still im Hintergrund und überwacht drei Stopp-Bedingungen.
Fünf Fälle — klare Prioritäten
Fall A — Kein Netzbezug (höchste Priorität) Wenn der Netzbezug über 500 W für 60 Sekunden steigt, wird Peak-Shave sofort abgebrochen. Eigenverbrauch hat immer Vorrang. Die 60-Sekunden-Verzögerung verhindert Abbrüche durch kurze Leistungsspitzen.
Fall B — SOC-Ziel erreicht Wenn der Akku den eingestellten Mindest-SOC (Standard 20%) erreicht, wird zurück auf Eigenverbrauch geschaltet. Der Akku behält einen Sicherheitspuffer.
Fall C — Noon-Stopp Spätestens 90 Minuten vor dem Sonnenhöchststand wird gestoppt — damit genug Zeit bleibt den Akku von der PV-Spitze wieder vollzuladen.
Fall D — Startzeit-Check Alle 5 Minuten wird geprüft ob die berechnete Startzeit erreicht ist. Das 6-Minuten-Startfenster stellt sicher dass die Automation nicht mehrfach startet.
Fall E — Restprognose-Wächter Während des Entladens wird alle 5 Minuten geprüft ob die verbleibende PV-Prognose noch ausreicht um den Akku wieder vollzuladen. Wenn nicht — sofortiger Stopp. Das verhindert dass der Akku abends zu leer ist weil Wolken die Prognose zunichte gemacht haben.
Stopp wenn: Restprognose < (10 kWh − Akku aktuell in kWh)
Wirtschaftlichkeit
Das Ergebnis ist wirtschaftlich knapp negativ — das ist beabsichtigt:
- Einspeisevergütung: ~8,5 ct/kWh
- Zusätzlicher Akkuverschleiß: ~1,08 € pro Vollzyklus (6.500 € Akku ÷ 6.000 Zyklen)
- Ca. 100 Peak-Shave Tage pro Jahr × 0,58 Extra-Zyklen = ~63 € Verschleiß
- Ca. 100 Tage × 10 kWh × 8,5 ct = ~85 € Einnahmen
- Ergebnis: ~22 € Gewinn pro Jahr — kaum über Break-even
Wer Peak-Shave wirtschaftlich betreiben will braucht eine höhere Einspeisevergütung oder dynamische Tarife. Das hier ist bewusst ein Beitrag zur Netzdienlichkeit — kein Geschäftsmodell.
Einstellbare Parameter
| Parameter | Standard | Beschreibung |
|---|---|---|
| Prognose-Schwelle | 15 kWh | Mindest-Tagesprognose für Start |
| Ziel-SOC | 20% | Mindest-SOC beim Entladen |
| Stopp vor Solar-Noon | 90 Min. | Sicherheitspuffer für Nachladen |
| Netzbezugs-Schwelle | 500 W | Ab wann wird abgebrochen |
| Netzbezugs-Dauer | 60 Sek. | Wie lange muss Netzbezug anliegen |
Hinweis zur Prognose-Schwelle: Forecast.Solar liegt in meiner Erfahrung systematisch 20-30% zu niedrig. Ich habe die Schwelle deshalb von 15 auf 12 kWh gesenkt. Wer genaue Prognosedaten hat kann höher ansetzen.
Hinweis zum Ziel-SOC: Mit Fall E als Sicherheitsnetz kann der Ziel-SOC aggressiver eingestellt werden — z.B. 10%. Fall E stoppt die Entladung automatisch wenn danach nicht mehr genug PV kommt um den Akku wieder vollzuladen.
Das Blueprint YAML
yaml
blueprint:
name: "PV Peak-Shave Einspeisung (Grünspeicher)"
description: >
Entlädt den Akku vor dem solaren Höchststand gezielt ins Netz (fully_fed_to_grid),
damit der Akku zur PV-Spitze leer ist und wieder vollgeladen werden kann.
Verhält sich wie ein Grünspeicher mit Peak-Shave.
Höchste Priorität: kein Netzbezug.
domain: automation
input:
prognose_schwelle:
name: Prognose-Schwelle (kWh)
description: >
Mindest-Tagesprognose damit die Automation überhaupt startet.
Unter diesem Wert passiert nichts.
default: 15
selector:
number:
min: 5
max: 40
step: 0.5
unit_of_measurement: kWh
ziel_soc:
name: Ziel-SOC beim Entladen (%)
description: >
Bis auf diesen SOC wird der Akku vor dem PV-Peak entladen.
20% = 2 kWh Sicherheitspuffer bei 10 kWh Akku.
default: 20
selector:
number:
min: 5
max: 50
step: 5
unit_of_measurement: "%"
minuten_vor_noon:
name: Stopp vor Solar-Noon (Minuten)
description: >
Spätestens so viele Minuten vor dem solaren Höchststand wird
auf Maximaler Eigenverbrauch zurückgeschaltet.
default: 90
selector:
number:
min: 30
max: 180
step: 15
unit_of_measurement: min
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 (Sekunden)
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: queued
max: 2
max_exceeded: silent
trigger:
- platform: time_pattern
minutes: "/5"
id: "check_startzeit"
- platform: numeric_state
entity_id: sensor.batterien_batterieladung
below: !input ziel_soc
id: "soc_ziel_erreicht"
- platform: numeric_state
entity_id: sensor.netzbezug_live
above: !input netzbezug_schwelle
for:
seconds: 60
id: "netzbezug_alarm"
- platform: time_pattern
minutes: "/5"
id: "check_noon_stopp"
variables:
prognose_schwelle_var: !input prognose_schwelle
ziel_soc_var: !input ziel_soc
minuten_vor_noon_var: !input minuten_vor_noon
netzbezug_schwelle_var: !input netzbezug_schwelle
action:
- choose:
# ══════════════════════════════════════════════════════════════════
# FALL A: Notfall-Abbruch – Netzbezug zu hoch (höchste Priorität)
# ══════════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "netzbezug_alarm"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
sequence:
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption
- action: system_log.write
data:
message: >
PV Peak-Shave: ABBRUCH – Netzbezug
{{ states('sensor.netzbezug_live') | round(0) }} W
über Schwelle {{ netzbezug_schwelle_var }} W.
level: warning
# ══════════════════════════════════════════════════════════════════
# FALL B: SOC-Ziel erreicht
# ══════════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "soc_ziel_erreicht"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
sequence:
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption
- action: system_log.write
data:
message: >
PV Peak-Shave: SOC {{ states('sensor.batterien_batterieladung') | round(0) }} %
<= Ziel {{ ziel_soc_var }} %. Zurück auf Eigenverbrauch.
level: info
# ══════════════════════════════════════════════════════════════════
# FALL C: Solar-Noon naht – Noon-Stopp
# ══════════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "check_noon_stopp"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
- condition: template
value_template: >
{% set noon_ts = states('sensor.sun_next_noon') | as_timestamp(0) %}
{% set now_ts = now().timestamp() %}
{% set minuten_bis_noon = (noon_ts - now_ts) / 60 %}
{{ minuten_bis_noon <= minuten_vor_noon_var and minuten_bis_noon >= 0 }}
sequence:
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption
- action: system_log.write
data:
message: >
PV Peak-Shave: Noon-Stopp –
{{ ((states('sensor.sun_next_noon') | as_timestamp(0) - now().timestamp()) / 60) | round(0) }}
Min. bis Solar-Noon.
level: info
# ══════════════════════════════════════════════════════════════════
# FALL E: Restprognose reicht nicht mehr für vollen Akku
# ══════════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "check_noon_stopp"
- condition: state
entity_id: select.batterien_betriebsmodus
state: "fully_fed_to_grid"
- condition: template
value_template: >
{% set verbleibend = states('sensor.energy_production_today_remaining') | float(0)
+ states('sensor.energy_production_today_remaining_2') | float(0) %}
{% set akku_kwh = (states('sensor.batterien_batterieladung') | float(0) / 100) * 10 %}
{{ verbleibend < (10 - akku_kwh) }}
sequence:
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: maximise_self_consumption
- action: system_log.write
data:
message: >
PV Peak-Shave: Stopp – Restprognose
{{ (states('sensor.energy_production_today_remaining') | float(0) +
states('sensor.energy_production_today_remaining_2') | float(0)) | round(1) }} kWh
reicht nicht für vollen Akku
(aktuell {{ (states('sensor.batterien_batterieladung') | float(0) / 100 * 10) | round(1) }} kWh).
level: info
# ══════════════════════════════════════════════════════════════════
# FALL D: Startzeit-Check – Peak-Shave starten
# ══════════════════════════════════════════════════════════════════
- conditions:
- condition: trigger
id: "check_startzeit"
- 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: >
{% set noon_ts = states('sensor.sun_next_noon') | as_timestamp(0) %}
{% set now_ts = now().timestamp() %}
{% set minuten_bis_noon = (noon_ts - now_ts) / 60 %}
{{ minuten_bis_noon > minuten_vor_noon_var }}
- condition: template
value_template: >
{% set akku_kwh = (states('sensor.batterien_batterieladung') | float(0) / 100) * 10 %}
{% set akku_min_kwh = (ziel_soc_var | float(20) / 100) * 10 %}
{% set entladbar_kwh = [akku_kwh - akku_min_kwh, 0] | max %}
{% set entladeleistung_kw = 3.5 %}
{% set entladezeit_min = (entladbar_kwh / entladeleistung_kw * 60) | int %}
{% set noon_ts = states('sensor.sun_next_noon') | as_timestamp(0) %}
{% set start_ts = noon_ts - (minuten_vor_noon_var * 60) - (entladezeit_min * 60) - 600 %}
{% set now_ts = now().timestamp() %}
{{ now_ts >= start_ts and now_ts < (start_ts + 360) }}
- condition: template
value_template: >
{% set prognose = states('sensor.energy_production_today') | float(0)
+ states('sensor.energy_production_today_2') | float(0) %}
{{ prognose >= prognose_schwelle_var }}
- condition: template
value_template: >
{{ states('sensor.batterien_batterieladung') | float(0) > ziel_soc_var | float(20) + 5 }}
sequence:
- action: select.select_option
target:
entity_id: select.batterien_betriebsmodus
data:
option: fully_fed_to_grid
- action: system_log.write
data:
message: >
PV Peak-Shave: START –
Prognose {{ (states('sensor.energy_production_today') | float(0) +
states('sensor.energy_production_today_2') | float(0)) | round(1) }} kWh,
SOC {{ states('sensor.batterien_batterieladung') | round(0) }} %,
Solar-Noon in {{ ((states('sensor.sun_next_noon') | as_timestamp(0) -
now().timestamp()) / 60) | round(0) }} Min.
level: info
Installation
- YAML-Datei als
pv_peak_shave_einspeisung.yamlin den Ordnerconfig/blueprints/automation/kopieren - Home Assistant neu laden oder Entwicklerwerkzeuge → YAML → Blueprints neu laden
- Einstellungen → Automationen → Automation erstellen → Blueprint auswählen
- Entity-IDs anpassen falls sie bei eurer Installation abweichen
- Parameter nach eurer Anlage einstellen
- Automation speichern und aktivieren
Hinweise und Einschränkungen
Akkugröße: Das Blueprint ist auf 10 kWh ausgelegt (Huawei LUNA2000-10kWh). Wer eine andere Akkugröße hat muss in Fall E den Wert 10 durch die eigene Kapazität in kWh ersetzen.
Entladeleistung: Im Blueprint ist 3,5 kW Entladeleistung hardcodiert (Zeile entladeleistung_kw = 3.5). Bitte an die eigene Anlage anpassen.
Forecast.Solar: Die Prognosegenauigkeit variiert stark je nach Standort und Dachausrichtung. Die Prognose-Schwelle sollte nach ein paar Wochen Beobachtung kalibriert werden.
Manueller Eingriff: Wenn Peak-Shave manuell abgebrochen wird, startet die Automation an diesem Tag nicht mehr automatisch neu — das Startfenster ist dann verpasst. Ein manueller Neustart ist möglich.
Was diese Automation nicht ist
Das ist kein wirtschaftliches Optimierungssystem. Es gibt elegantere Ansätze um den Akkuverschleiß zu minimieren — z.B. Ladestart verzögern statt aktiv entladen. Aber diese Ansätze erreichen kein echtes Peak-Shave weil der Akku beim solaren Höchststand nicht leer genug ist.
Wer primär den Akku schonen will und Netzdienlichkeit als Nebenziel hat sollte einen anderen Ansatz wählen.
Getestet mit: Huawei SUN2000-4KTL-M1, SUN2000-5KTL-M1, LUNA2000-10kWh, huawei_solar v1.6.0, Home Assistant 2026.4