Wie ich meine Photovoltaikerzeugung Tracke – Und prognostiziere

Wie viele Leute hatte ich das Problem: Ich habe einen Wechselrichter von Firma 1 (in meinem Fall Solax), eine Wallbox von Firma 2 (In meinem Fall go-e) und diverse Verbraucher von vielen anderen Herstellern. Letztere sind vielfach noch nicht einmal Smart Home Devices. Hinzu kommt noch der Netzbetreiber, von dem ich ebenfalls Daten brauche, wenn ich meinen Stromverbrauch usw. vernünftig tracken möchte.

Lange Zeit habe ich das alles mittels Exceltabelle gemacht und die Daten jeweils aus den Portalen herausgesucht, eingetragen und Excel dann rechnen lassen. Das war erstens Zeitaufwendig, da ich Daten aus mehreren Apps und dem Webportal der Netze Oberösterreich holen musste, zum anderen eben auch fehleranfällig, weil Tippfehler leider schnell gehen. Zudem war das nächste Problem, dass die Daten Zum Zeitpunkt des Ablesens meinerseits nicht immer zur gleichen Zeit erfasst wurden. Während die Solax App mir immer die „Jetzt“ Daten anzeigt, zeigt die go-e-App pro Ladevorgang an und die Netze Oberösterreich geben mir die Daten immer jeweils zum Stichpunkt Mitternacht bis zum Vortag.

Während die logische Antwort vermutlich „Homeassistant“ gewesen wäre, bin ich eben auch ein bisschen verrückt und lernbegierig. Also beschloss ich, das System in Python selber aufzusetzen. Zwar konnte ich als ich mit dem Projekt begonnen habe noch kein Python, aber die Wunder moderner KI-Technik in Form von Github Copilot helfen einem dabei ja enorm.

Aufbau meines Stromanschlusses

Als mein Haus 2003 gebaut wurde waren PV-Anlagen und E-Autos noch keine Standardausstattung. Und niemand sah wohl voraus, dass sie es in den nächsten 25 Jahren werden würden. Bei unserer Reihenhaussiedlung wurde daher immer für die 4-5 zusammenhängenden Häuser je ein Zählerkasten errichtet. Dieser steht draußen, neben den Garagen. Von dort gehen die Leitungen jeweils einphasig zu den Garagen und dreiphasig in die Häuser. Lediglich der Erstbesitzer eines der drei übrigen Häuser ließ von Anfang an dreiphasig in die Garage legen, leider nicht der meines Hauses

Bei der Errichtung der PV-Anlage hätte das dann bedeutet, dass eigentlich ein Datenkabel zum Zählerkasten hätte geführt werden müssen, was mit Erdarbeiten und Asphaltarbeiten verbunden gewesen wäre. Dafür hätte man die Garage korrekt mit zu erfasst und ich könnte die Wallbox direkt in meinen Verbrauchsdaten sehen. Stattdessen wurde der SmartMeter für den PV-Wechselrichter eben in der Unterverteilung im Haus eingebaut. Das bedeutet, für die PV-Anlage ist die Garage eben schon „Netz“, auch wenn sie in Wahrheit hinter dem Netzanschluss ist.

Aus demselben Grund lade ich derzeit noch 1-phasig. Ich verliere relativ wenig, da ich lediglich in den Mittagsstunden des Sommer überhaupt mehr als 2,3 kW exportieren könnte und der Aufwand für die Erdarbeiten steht einfach nicht dafür. 5×2,5mm² durch Lehrrohre zu ziehen, durch die derzeit 3x 1.5mm² laufen ist einfach nicht drin.

Prinzipskizze zum Aufbau des Stromanschlusses und der PV-Anlage, Das Reihenhaus mit der Photovoltaikanlage am Dach, wird über einen außenliegenden Zählerkasten versorgt, die PV-Leistung aber am Hausausgang gemessen. Die Garage erscheint für die PV-Anlage als "Netz"

Prinzipskizze zum Aufbau des Stromanschlusses und der PV-Anlage

Das System in einem Satz

Day.py erfasst eine Fünf-Minuten-Momentaufnahme, month.py wandelt kumulierte Zählerstände in Tages- und Monatswerte um, year.py fasst diese Werte zu Jahresgesamtsummen zusammen, und die Prognose- und Finanzskripte bereichern dieselbe Datenbank mit Vorhersagen und monetären Berechnungen.

Datenquellen: Woher kommen die Rohdaten?

Solax-Wechselrichter

Get_Solax_Data.py ruft die Solax-Cloud-Echtzeit-API auf. Es extrahiert:

  • Gesamtstromerzeugung
  • Einspeiseenergie
  • Netzstromverbrauch
  • Eigenverbrauch
  • Gesamtverbrauch
  • Batteriezustand
  • DC-String-Leistung
  • Einspeiseleistung
  • AC-Leistung

Das Modul stellt das Ergebnis als In-Memory-Dictionary Solax_data bereit.

Die API wird abgefragt, wenn Day.py das Modul importiert. Da die Anfrage auf Modulebene erfolgt, führt das Importieren von Get_Solax_Data.py die Netzwerkanfrage sofort aus.

Eigentlich würde ich mir wünschen, dass ich die Daten direkt innerhalb meines lokalen Netzwerks abrufen könnte, aber Solax hat diese Möglichkeit leider gesperrt. Auch kann ich viele Einstellungen, die ich mittels Handyapp vornehme nicht über die CloudAPI vornehmen. Da ich das für die Zukunft durchaus will, steht der direkte Anschluss mittels RS485 Kabel und Modbusintegration für den Raspberry Pi noch auf meiner To-Do-Liste.

go-e-Ladegerät

Anders als Solax bietet meine go-e-Wallbox eine lokale API. Mein Skript Get_Charger_Data.py fragt den HTTP-Endpunkt des Ladegeräts ab und liest:

  • Gesamt geladene Energie
  • Aktuelle Ladeleistung
  • Ladestrom

und stellt diese als Charger_data bereit. Hier könnte ich auch noch weitere Daten abrufen und kann theoretisch sogar den Ladestrom, die Anzahl der Phasen (wenn ich dreiphasig angeschlossen wäre) usw. einstellen. So stelle ich mir SmartHome-Komponenten vor.

Netze OÖ

Ursprünglich wollte ich die Daten für Verbrauch und Bezug in Echtzeit mit einem Infrarot-Lesekopf ermitteln. Das scheiterte jedoch: Der Zählerkasten steht nicht nur draußen (was für WLAN kein Problem wäre), sondern besteht auch aus Metall. Eine Antenne nach außen zu verlegen, wäre nur mit Zustimmung der Nachbarn möglich – und selbst dann bestünde die Gefahr von Vandalismus oder dass die Nachbarskatzen die Antenne als Spielzeug entdecken.

Daher baute ich eben zwei andere Skripte:

Get_NETZOOE_Eispeisen.py lädt Einspeisedaten von den Netzen OÖ herunter.
Get_NETZOOE_Bezug.py lädt Bezugsdaten herunter.

Beide Skripte:

  • Verwenden Benutzername/Passwort für die Anmeldung.
  • Speichern die Daten in CSV-Dateien
  • Werden von month.py aufgerufen, um die monatlichen Aggregationen zu vervollständigen.

Ich hole mir die Daten jeweils täglich um kurz nach 8, nachdem ich zuvor die Erfahrung gemacht habe, dass bei früherem Abruf die Vortagesdaten oftmals noch nicht eingepflegt sind. Insbesondere für die Einspeisedaten war es in der Vergangenheit oft so, dass diese manchmal mit einem Tag Verspätung erst eingespielt wurden. Mit einem Update im Juli wurde dies aber seitens der Netze Oberösterreich korrigiert.

Wetterdaten

Historische Wetterdaten, sprich Durchschnittstemperatur und Sonnenscheindauer (monatsweise) lade ich über das offizielle Spartacus-Portal der Geosphere Austria herunter. Diese werden im Kilometerraster zur Verfügung gestellt.

In die Zukunft schauende Daten lade ich mir hingegen über die API von Open Meteo herunter. Allerdings will ich hier noch einmal schauen, ob es nicht doch bessere Quellen gibt, weil mir die Prognose der Sonnenscheindauer dort doch sehr optimistisch erscheint. Für Tipps meiner Leser wäre ich hier sehr dankbar.

Tarifinformationen

Da sich die Netzgebühren nur 1x Jährlich und mein Stromtarif auch eher selten ändert, betrifft dies am meisten den Einspeisetarif. Dieser wird von der OeMAG einmal im Monat im Nachhinein festgelegt. Um hier unnötige Komplexität zu reduzieren pflege ich hier händisch eine .csv-Datei, welche ich dann jeweils Anfang eines Monats, vor Erstellung der Monatsberichte mittels eines Skripts einpflege.

Datenverarbeitung: Wie ich Ordnung ins Rohdatenchaos bekomme

Datenquellen und Datenverarbeitungsskripte

Tagesdaten (Day.py)

Beispielhafter Verlauf der Leistungsflüsse aus der PV-Anlage über einen Tag

Ich erfasse hier alle 5 Minuten die Wechselrichterleistung (AC/DC), die Leistung der einzelnen Strings, die aktuelle Ladeleistung, den aktuellen Hausverbrauch usw. und speichere alle Daten auf der Tabelle day_data in der SQLite-Datenbank. Eine zeitlich genauere Auflösung gibt die Hardware, also vor allem der WLAN-Dongle von Solax nicht her

Diese Daten werden aktuell noch nicht aktiv genutzt, bilden aber die Grundlage für alles was danach kommt.

Wird auf dem Raspberry Pi alle 5 Minuten automatisch ausgeführt.

Monatsdaten (month.py)

Beispielhafter Auszug aus den Monatsdaten der PV-Anlage für einen Monat

Hier vergleiche ich die 0-Uhr-Daten des Vortags mit denen des aktuellen Tags, um die täglichen Verbräuche und Erträge zu berechnen. Anschließend ruft das Skript die Netze-OÖ-Skripte auf, um die monatlichen Daten zu vervollständigen. Die Ergebnisse werden in der Tabelle month_data gespeichert.

Eine kleine Besonderheit dieses Skripts ist, dass ich aufgrund vereinzelt fehlender Daten (manchmal geht die Abfrage der 5-Minuten-Daten schief) hier eine Fehlertoleranz eingebaut habe. Wenn die 0-Uhr-Daten fehlen, werden automatisch die nächsten verfügbaren früheren Daten herangezogen.

Die hier erzeugten Daten fließen teilweise in die Monatsberichte ein, sind vielfach aber auch vor allem ein „Nice to know“ für mich selber.

Das Skript wird jeden Tag um 08:15 Uhr automatisch ausgeführt.

Jahresdaten (year.py)

Beispielhafte Darstellung von Jahresdaten meiner PV-Anlage

Dieses Skript berechnet aus den Rohdaten die monatlichen Verbräuche und Erträge. Nur die Daten von Netze Oberösterreich werden direkt aus der Monats-Tabelle gelesen. Anschließend wird das Vorhersageskript für das kommende Jahr aufgerufen (dazu später mehr).

Zudem Aggregiert dieses Skript dann auch schon direkt die Jahresdaten, sowohl für vergangene Jahre, als eben auch für das laufende Jahr.

Die Speicherung der Daten erfolgt dann auf den Tabellen year_data und total_data.

Das Skript wird jeden Monatsersten um 08:30 automatisch ausgeführt.

Beispielhafter Auszug der gesammelten Totaldaten

Prognosen (Month_Predictor.py, Daily_Predictor.py)

Der Month Predictor benutzt zwei Datenquellen:
Zum einen die Daten zu Sonnenscheindauer aus Spartacus, welche ich per API herunterlade. Zum anderen die historischen Daten aus mittlerweile 2 Jahren Photovoltaik auf meinem Dach aus der Datenbank.
Damit rechnet das Skript zunächst einmal den fiktiven Wert „kWh pro Sonnenstunde“ für jeden Monat. Anschließend wird diesen Wert mit der durchschnittlichen Anzahl der Sonnenstunden für die letzten 5 Jahre multipliziert. Der 5 Jahreszeitraum kam, weil die Sonnenstunden in den letzten Jahren vor allem für April und Juni zugenommen haben.
Auf diese Art prognostiziert das Skript den erwarteten Ertrag für 12 Monate im Voraus.
Für den Verbrauch setze ich jeweils für Auto und Haus getrennt den Durchschnittsverbrauch pro Monat der letzten bis zu 5 Jahre an.
Für die Berechnung des erwarteten Eigenverbrauchs benutze ich die Durchschnittliche Eigenverbrauchsquote der letzten ebenfalls bis zu 5 Jahre, jeweils monatsfein. Hier scheint noch ein Schwachpunkt zu sein. Aufgrund des sehr geringen Ertrags im Dezember bis Februar dieses Jahres, war der Ertrag und damit auch der Eigenverbrauch unterdurchschnittlich. Mit einem durchschnittlichen Ertrag berechnet das Skript also eine Einspeisung, die es real nicht geben wird. Hier hoffe ich auf das „Selbstlernen“ des Systems, wenn die Daten über mehr als ein Jahr (So lange habe ich das Auto erst) zur Verfügung stehen.
Die Einspeisung errechne ich dann aus erwartetem Ertrag – erwartetem Eigenverbrauch.

Dieses Skript wird wie beschrieben von „year.py“ aufgerufen

Der Daily Predictor setzt darauf auf. Er ruft zunächst von Open-Meteo den Wetterbericht und die Sonnenstunden für die nächsten 16 Tage ab und füllt dann bis Monatsende auf. Anschließend multipliziert er die Sonnenstunden mit dem „kWh pro Sonnenstunde“ Wert aus der monatlichen Vorhersage und addiert ihn zu den bereits erzeugten kWh.
Die Werte für Verbrauch, Eigenverbrauch und Einspeisung werden analog zur Monatsvorhersage berechnet.

Die Daten werden jeweils auf den Monats- bzw. Jahrestabellen gespeichert.

Aufgerufen wird das Skript automatisch jeden Tag um 08:35

Finanzielle Berechnungen (Finance.py)

Dieses Skript importiert die neueste „Finance.csv“ Datei, welche wie schon gesagt händisch gepflegt wird, und berechnet dann für den Vergangenen Monat die Einnahmen aus dem Stromverkauf, die Stromkosten und die Ersparnis durch Eigenverbrauch. Diese Daten nutze ich dann immer in den Monatsberichten, außerdem dienen sie meinem internen Controlling.

Übersicht über die Speicherorte

SchichtSkripteHauptspeicherBedeutung
Live-ErfassungDay.pyday_dataFünf-Minuten-Roh- und berechnete Messwerte
Tages-/Monatsdatenmonth.pymonth_dataAbgeschlossene Tages- und kumulative Monatswerte
Jahresdatenyear.pyyear_data, total_dataMonats-/Jahresenergie und kumulative Gesamtsummen
PrognosenMonth_Predictor.py, Daily_Predictor.pyyear_data, month_data, JSONErwartete Erzeugung und Energieflüsse
FinanzenFinance.pyyear_data, total_dataKosten, Einnahmen, Einsparungen, jährliche Finanzsummen
Externe Staging-DatenNetze-OÖ-Skripteconsumption_*.csvTemporärer Download der Netzstromzählerstände
Klimadaten-ArtefaktePrognoseskriptespartacus_output/*.json, weather_forecast_16_days.jsonReproduzierbare API-Ergebnisse und Vorhersagen

Zusammenfassende Betrachtung

Das System lässt sich am besten als ein gemeinsames SQLite-Datenmodell mit mehreren Schreib- und Lesezugriffen verstehen:

  • Day.py ist die Zeitreihen-Erfassungsschnittstelle.
  • month.py und year.py sind deterministische Aggregationsschichten, die auf kumulierten Zählerständen basieren.
  • Prognoseskripte fügen den tatsächlichen Werten erwartete Werte hinzu.
  • Finance.py fügt die monetäre Interpretation hinzu.

Hätte ich das alles einfacher haben können? Sicher. Homeassistant und ähnliche Systeme sind genau dafür gemacht und bieten teilweise noch mehr Funktionen. Aber mir macht eben auch das selber machen und das tüfteln, die Fehlersuche und generell die Arbeit mit Daten Spaß. Auch das erarbeiten von Modellen aus zur Verfügung stehenden Daten und deren langsame Anpassung an die Realität sind für mich eine Art Hobby. Und vielleicht sind derartige Skills in Zeiten in denen Wissen durch Google und KI übernommen werden auch für uns als Gesellschaft wichtig.

Ausblick

Derzeit habe ich noch einige Baustellen, an die ich bei Gelegenheit heranmuss.

  1. Wie ich schon in der graphischen Repräsentation der Daten in meiner PV-App gesehen habe, haben einige meiner Haushaltsgeräte eine sehr individuelle Signatur. Damit meine ich, wie sich der 5-Minuten-Wert ändert wenn sie sich ein- und ausschalten. Schon lange war der Plan, daraus eine Art virtueller Sensoren zu kreieren und damit den Verbrauch einzelnen Haushaltsgeräten zuordnen zu können. Ich hoffe damit zum Beispiel auch meine Vorhersagegenauigkeit zu erhöhen indem ich anhand von Wetterbericht und Temperatur insbesondere die Verbräuche der Wärmepumpe gezielter vorhersagen kann.
  2. Ein Frontend zur Datenvisualisierung. Derzeit besteht mein Frontend darin, dass ich selbst in die Datenbank schaue oder Tabellen als CSV exportiere. Mein Ziel ist eine Website im Heimnetzwerk, die die Daten direkt aus der Datenbank liest und anzeigt. Ja, das könnte auch ein Home-Assistant-Dashboard – aber ich bastle nun mal gerne selbst
  3. Umstellung der Prognosen auf Globalstrahlungsmodelle. Da die PV-Erzeugung nämlich mit dieser zusammenhängt, nicht mit den Sonnenstunden. Allerdings fehlt mir hier noch eine vernünftige Quelle und die Berechnungen dahinter sind komplexer.
    Wenn mir hier jemand eine gute Quelle hat, bitte nur her damit!
  4. Eine zumindest Stündliche Vorhersage des Ertrags für den nächsten oder besser die nächsten 2 Tage und eine Tagesgenaue Vorhersage für mindestens eine Woche. Damit kann ich dann die Ladeplanung für das E-Auto und auch größere Verbräuche wie die Waschmaschine, den Trockner und die Spülmaschine hoffentlich etwas besser planen.

Danke an alle, die es bis hier durchgelesen haben.

Wie macht ihr das? Nutzt ihr Home Assistant, oder gar proprietäre Lösungen? Oder habt ihr euch auch selber hingesetzt? Ich bin gespannt auf eure Erfahrungen – schreibt sie in die Kommentare!

Falls euch der Artikel geholfen hat, freue ich mich über eine Weiterempfehlung. Wer meine Arbeit unterstützen möchte, findet Spendenmöglichkeiten im Footer der Seite.

1 Kommentar zu „Wie ich meine Photovoltaikerzeugung Tracke – Und prognostiziere“

Schreibe einen Kommentar