Solar API
- Start
- März 2024
Überblick
Eine Ahoy DTU liest die Werte des Wechselrichters meiner Solaranlage aus und veröffentlicht sie laufend auf einem MQTT-Broker. Die Solar API abonniert diese Topics, schreibt jeden Messwert als Zeitreihenpunkt in eine InfluxDB und stellt die Daten über eine REST-API bereit: aktuelle Werte, Höchstwerte und beliebige Zeiträume, auf Wunsch zu Stunden- oder Tageswerten zusammengefasst.
Hauptnutzer ist die Papa App: Sie zeigt die Live-Daten der Anlage mit Tages- und Wochendiagramm an und greift dafür über einen aus der OpenAPI-Beschreibung generierten Swift-Client auf die API zu.
Meine Rolle
Konzeption und Umsetzung des gesamten Dienstes: der MQTT-Listener mit automatischem Wiederverbinden, das Datenmodell in InfluxDB, die REST-Endpunkte mit dynamisch erzeugten Flux-Abfragen, Monitoring und Logging sowie Containerisierung und Build-Pipelines.
Vom MQTT-Topic zur Zeitreihe
Die Ahoy DTU veröffentlicht jeden Wert als eigene Nachricht. Die Tiefe des Topics entscheidet, in welcher InfluxDB-Measurement der Wert landet:
- Zwei Ebenen: allgemeine Informationen des Geräts, gespeichert als
general. - Drei Ebenen: Gesamtwerte des Wechselrichters wie Leistung und Tagesertrag, gespeichert als
total. - Vier Ebenen: Werte einzelner Eingänge (Solarmodule), gespeichert als
channelsmit dem Kanal als Tag.
Retained-Nachrichten des Brokers und Werte, die keine Zahl sind, werden verworfen, damit beim Verbinden keine veralteten Messwerte doppelt gespeichert werden.
REST-API
- Gesamtwerte für einen relativen Zeitraum (etwa die letzten 24 Stunden) oder zwischen zwei festen Zeitpunkten, gefiltert auf einzelne Felder.
- Optionale Aggregation in frei wählbaren Zeitfenstern mit elf Funktionen, darunter Mittelwert, Median, Maximum, Summe und Spannweite — daraus entstehen direkt die Diagramme der App.
- Letzter Wert und Höchstwert über den gesamten Aufzeichnungszeitraum, außerdem die Liste aller verfügbaren Felder.
- Aktuelle Gleichstromleistung je Solarmodul.
- Versions-Endpunkt mit Build-Zeit und Commit-ID, die das Git-Plugin beim Build einbettet, sowie ein einfacher Ping.
Die Antworten sind einheitlich aufgebaut: pro Feld eine Liste aus Zeitstempel und Wert, dazu die tatsächlich verwendeten Parameter, damit der Client sieht, welche Standardwerte gegriffen haben.
Highlights
- Flux-Abfragen werden aus den Parametern zusammengesetzt: Feldfilter, Zeitraum und
aggregateWindowmit der gewählten Funktion. Zeitangaben werden vorher per regulärem Ausdruck geprüft. - Robuste MQTT-Verbindung.
- Problem: Ein Verbindungsabbruch zum Broker beendete die gesamte Anwendung.
- Lösung: automatisches Wiederverbinden mit erneutem Abonnieren der Topics. Beendet wird die Anwendung nur noch, wenn schon die erste Verbindung beim Start scheitert, dann mit eigenem Exit-Code.
- Der MQTT-Listener verbindet sich erst, wenn der Spring-Kontext vollständig gestartet ist, und meldet sich beim Herunterfahren sauber ab.
- Monitoring über Spring Boot Actuator mit Prometheus-Metriken, ergänzt um eine eigene Metrik, die den Health-Status als 1 oder 0 abbildet — so lässt sich direkt darauf alarmieren. Die Logs gehen zusätzlich an Grafana Loki.
- Getrennte Spring-Profile: Swagger UI und die OpenAPI-Beschreibung sind nur in der Entwicklung aktiv, in Produktion abgeschaltet.
- Containerisiert über ein mehrstufiges Docker-Build (Maven, dann ein schlankes Java-21-JRE-Image); je eine Azure-DevOps-Pipeline für Dev und Prod baut das Image auf einem eigenen Build-Agent und legt es in einer eigenen Container-Registry ab.
Mögliche Weiterentwicklung
- Live-Updates per WebSocket, als Nächstes geplant.
- Heute holt ein Client neue Werte über die REST-API ab. Die Messwerte kommen aber ohnehin laufend per MQTT beim Dienst an.
- Künftig soll der Dienst jeden neuen Messwert gleich nach dem Speichern in InfluxDB per WebSocket an alle verbundenen Clients weitergeben, etwa über STOMP mit eigenen Kanälen für Gesamtwerte und einzelne Solarmodule.
- So zeigt die Papa App Leistung und Ertrag ohne Verzögerung an, und der Dienst spart die wiederholten Abfragen.
- Umstieg auf InfluxDB 3: Flux wird dort nicht mehr weiterentwickelt; die Abfragen ließen sich auf SQL umstellen.
Zuletzt aktualisiert: