Im Übersichtsartikel zum Amortisations-Dashboard in Home Assistant ging es um das große Ganze: PV, Wärmepumpe und Akku zusammen, mit derselben Kachel-Logik für alle drei. In diesem Artikel schaue ich mir die PV-Amortisation genauer an – die Formel dahinter, warum sich die Rechnung im Laufe der Zeit verändert hat, und wie ich einen hartnäckigen Bug bei den Monatswerten gefunden und behoben habe.
Drei Ströme, eine Formel
Die PV-Ersparnis setzt sich aus drei Energieflüssen zusammen, die ich in Home Assistant bewusst als getrennte Entitäten führe, statt sie in einer einzigen Berechnung zu vermischen:
- Eigenverbrauch – der PV-Strom, den ich direkt im Haus nutze, statt ihn aus dem Netz zu beziehen
- Einspeisung – der PV-Strom, den ich ins öffentliche Netz einspeise
- Akku-Ladung – der PV-Strom, der in den Batteriespeicher fließt
Aus diesen drei Werten ergibt sich die Kernformel:
Ersparnis = Eigenverbrauch × 0,25 €/kWh + Einspeisung × 0,08 €/kWh − Akku-Ladung × 0,17 €/kWh
Die getrennte Führung der drei Entitäten hat einen praktischen Vorteil: Ich kann jeden Energiefluss einzeln plausibilisieren. Stimmt die Summe aus Eigenverbrauch, Einspeisung und Akku-Ladung mit der PV-Gesamterzeugung überein? Wenn ja, weiß ich, dass keine Energie „verschwindet“ oder doppelt gezählt wird. Genau diese Prüfung half mir später, den in diesem Artikel beschriebenen Bug überhaupt zu finden.
Zwei Phasen: Nulleinspeisung und Überschusseinspeisung
Ein Detail, das die Formel über die Zeit hinweg verändert hat: Meine Anlage lief zunächst eine Weile mit Nulleinspeisung, bevor die Überschusseinspeisung freigeschaltet wurde. In der Nulleinspeisungs-Phase ging überschüssiger PV-Strom, den ich weder selbst verbrauchte noch in den Akku laden konnte, schlicht verloren – er wurde weder vergütet noch anderweitig genutzt.
Für die Ersparnisrechnung bedeutet das: In dieser Phase war der Einspeisungs-Term der Formel praktisch immer null. Erst mit der Freischaltung der Überschusseinspeisung begann die Einspeisevergütung tatsächlich einen Beitrag zur Ersparnis zu leisten. Wer die Formel 1:1 aus einem Tutorial übernimmt, ohne diese Phasenumstellung zu berücksichtigen, wird sich wundern, warum die berechnete Ersparnis in den ersten Monaten niedriger ausfällt, als es die reine PV-Erzeugung vermuten lässt. Bei mir war das kein Fehler, sondern schlicht die Realität der Anlage in dieser Zeit.
Vom Platzhalter zum Live-Wert: der Bug bei den Monatswerten
Das Dashboard zeigt eine Balken-Card mit der PV-Ersparnis pro Monat. Bei einer Plausibilitätsprüfung fiel mir auf: Für die zurückliegenden Monate stimmten die Werte grob mit der Formel überein – die letzten Monate im Diagramm dagegen zeigten Zahlen, die sich nie veränderten, egal wie viel PV-Strom tatsächlich floss. Der Grund: Beim ursprünglichen Aufbau hatte ich für diese noch nicht erreichten Monate feste Schätzwerte eingetragen, als Platzhalter, bis echte Daten vorliegen würden. Diesen Schritt – die Platzhalter durch echte Berechnungen zu ersetzen, sobald der jeweilige Monat beginnt – hatte ich schlicht vergessen.
Die Lösung: ein „guarded“ Template-Muster
Statt die Platzhalter einfach zu löschen, habe ich eine Architektur gebaut, die sich künftig von selbst korrekt verhält – auch ohne dass ich manuell eingreifen muss. Sie besteht aus drei Teilen:
- Ein Helper
input_number.pv_ersparnis_basis_vormonathält den Ersparnis-Stand zu Beginn des jeweils laufenden Monats fest. Er dient als Nullpunkt für die Live-Berechnung des aktuellen Monats. - Für jeden abgeschlossenen Monat gibt es einen eigenen „Frozen-Value“-Helper (z. B.
input_number.pv_ersparnis_august_final), der den finalen Monatswert dauerhaft speichert, sobald der Monat vorbei ist. - Das Template für jede Monats-Kachel prüft zuerst: Ist dieser Monat der aktuell laufende? Dann berechnet es live. Ist der Monat bereits vorbei? Dann zeigt es den eingefrorenen Wert. Liegt der Monat noch in der Zukunft? Dann zeigt es 0 €.
Diese dritte Regel ist der eigentliche Kern des „guarded“ Musters: Das Template rechnet nie „blind“ für jeden Monat, sondern fragt sich zuerst, ob es das überhaupt darf. Nur der laufende Monat bekommt eine Live-Rechnung, alles andere ist entweder fest eingefroren oder bewusst auf null gesetzt.
Die Automation für den Monatswechsel
Damit niemand – auch nicht ich selbst – händisch am Monatsersten die Helper umschalten muss, übernimmt das eine tägliche Automation. Sie läuft jeden Tag um 00:15 Uhr, prüft aber zuerst, ob heute überhaupt der erste Tag eines Monats ist. Nur dann wird sie aktiv:
alias: PV Ersparnis Monatswechsel
trigger:
- platform: time
at: "00:15:00"
condition:
- condition: template
value_template: "{{ now().day == 1 }}"
action:
- service: input_number.set_value
target:
entity_id: input_number.pv_ersparnis_august_final
data:
value: "{{ states('sensor.pv_ersparnis_august') | float }}"
- service: input_number.set_value
target:
entity_id: input_number.pv_ersparnis_basis_vormonat
data:
value: "{{ states('sensor.pv_ersparnis_gesamt') | float }}"
mode: singleCode-Sprache: JavaScript (javascript)
Das Beispiel ist vereinfacht – in der echten Automation entscheidet ein zusätzliches Template, welcher Frozen-Helper gerade „dran“ ist, je nachdem welcher Monat gerade zu Ende gegangen ist. Das Prinzip bleibt aber gleich: Einfrieren, dann die Basis für den neuen Monat zurücksetzen.
Einen Tag nach dem Fix bestätigte ein einfacher Test, dass die Architektur funktioniert: Der gerade abgelaufene Monat blieb korrekt bei seinem eingefrorenen Live-Wert stehen, während der neue Monat sauber bei 0 € startete – statt weiter die alte, viel zu hohe Platzhalterschätzung anzuzeigen.
Meine Home-Assistant-Instanz läuft auf einem Raspberry Pi 4. Weil bei diesem Dashboard langfristige Verlaufs- und Monatsdaten eine wichtige Rolle spielen, nutze ich zusätzlich eine externe SSD statt einer dauerhaft beschriebenen microSD-Karte.
Meine Home-Assistant-Hardware: Raspberry Pi 4* · externe SSD*
* Affiliate-Link: Wenn du über einen entsprechend gekennzeichneten Link etwas kaufst, erhalte ich möglicherweise eine Provision. Für dich ändert sich der Preis dadurch nicht. Als Amazon-Partner verdiene ich an qualifizierten Verkäufen.
Was noch fehlt: die Verbindung zur Wärmepumpe
Ein Teil des PV-Stroms deckt nicht den Hausverbrauch, sondern läuft direkt in die Wärmepumpe. Wie viel genau, lässt sich erst seit Kurzem live über einen eigenen Sensor messen – für die Monate davor bleibt nur eine Schätzung auf Basis eines Gewichtungsmodells aus PV-Erzeugung und WP-Verbrauch. Weil diese Schätzung eng mit der Fernwärme-Vergleichsrechnung der Wärmepumpe zusammenhängt, gehe ich im WP-Detailartikel ausführlich darauf ein, statt sie hier zu verdoppeln.
Lehren aus dem PV-Teil des Dashboards
Zwei Dinge nehme ich aus diesem Teilprojekt mit, die sich auf jedes ähnliche Home-Assistant-Tracking übertragen lassen:
- Platzhalter sind Technik-Schulden. Jeder feste Wert, den ich „nur vorübergehend“ einsetze, sollte von Anfang an mit einer klaren Regel versehen sein, wann und wie er durch echte Daten ersetzt wird – sonst bleibt er stehen, bis ihn jemand zufällig entdeckt.
- Plausibilitätsprüfungen zahlen sich aus. Dass die Summe aus Eigenverbrauch, Einspeisung und Akku-Ladung der PV-Gesamterzeugung entsprechen muss, ist eine einfache Kontrollrechnung – aber genau sie deckte am Ende auf, dass mit den Monatswerten etwas nicht stimmte.
Im nächsten Artikel geht es um die Wärmepumpe: Warum der Vergleich hier nicht gegen „kein Netzstrom“ läuft, sondern gegen die vorher tatsächlich gezahlten Fernwärmekosten – und wie aus einer einzigen Jahressumme ein realistischer saisonaler Monatsverlauf wird.