- Python 43.8%
- JavaScript 37.7%
- HTML 11.8%
- CSS 6.5%
- Dockerfile 0.2%
| app | ||
| static | ||
| tests | ||
| .dockerignore | ||
| .env.example | ||
| .gitignore | ||
| docker-compose.yml | ||
| Dockerfile | ||
| README.md | ||
| requirements.txt | ||
DEYE Solar Monitor
Vollständige Web-Applikation zur Überwachung und Steuerung eines DEYE-Wechselrichters (SUN SG05LP3-EU) über Modbus, mit OCPP-Wallbox-Integration für Go-e Gemini.
Features
- Solar Monitor mit animiertem Energiefluss-Diagramm (Solar → WR → Batterie/Netz/Haus)
- Live-Daten mit 1-Sekunden-Refresh: Spannung, Strom, Leistung, Temperatur für alle Komponenten
- Verlaufs-Charts mit Plotly (interaktiv, Zoom, Pan, Hover-Tooltips)
- Energie-Logging: Kumulative Zähler als Delta, Live-Werte als Mittelwert
- Selbstbaubare Dashboards mit Widgets (Karte, Radial, Balken, Säule, Text)
- Rohe Modbus-Daten in Echtzeit mit Register-Naming
- OCPP 1.6 Server für Go-e Gemini Wallbox
- Wallbox-Steuerung: Solarladen, Chip-basierte Regeln, Ladestrombegrenzung
- API mit Rollen-basiertem Key-Schutz (Admin vs. Limited)
- PostgreSQL als externe Datenbank
- 5 GB Log-Limit mit automatischer Bereinigung
- Passwortschutz nur bei externem Zugriff (Heimnetz = frei)
Architektur
┌────────────────────────────────────────────────────────┐
│ Browser (Heimnetz oder extern) │
│ ┌──────────────────────────────────────────────────┐ │
│ │ Frontend (vanilla JS + Plotly, Single-Page) │ │
│ │ • Solar Monitor (Flow-Diagramm + Detail-Karten) │ │
│ │ • Dashboards (selbstbaubar) │ │
│ │ • Verlauf (Plotly-Charts) │ │
│ │ • Rohdaten (Modbus Register) │ │
│ │ • Wallbox (Status, Transaktionen, Regeln) │ │
│ │ • Admin (Felder, Keys, Modbus, Logging) │ │
│ │ • API-Dokumentation │ │
│ └──────────────────────────────────────────────────┘ │
└────────────────────────┬───────────────────────────────┘
│ HTTP / WebSocket
┌────────────────────────▼───────────────────────────────┐
│ FastAPI Backend (Port 8000) │
│ ┌──────────┐ ┌──────────┐ ┌───────────────────────┐ │
│ │ Auth-MW │ │ Modbus │ │ Logger-Service │ │
│ │ IP/Passw.│ │ Reader │ │ (Background, 2s) │ │
│ │ API-Keys │ │ real/mock│ │ Live→Mittelwert │ │
│ │ Rollen │ └──────────┘ │ Cumul→Delta/Running │ │
│ └──────────┘ └───────────┬───────────┘ │
│ ┌──────────────────┐ ┌──────────────┐ │ │
│ │ OCPP 1.6 Server │ │ Maintenance │ │ │
│ │ (Port 9000, WS) │ │ (5GB Limit) │ │ │
│ └──────────────────┘ └──────────────┘ │ │
│ ┌─────────────▼─────────────┐ │
│ │ asyncpg Connection-Pool │ │
│ └─────────────┬─────────────┘ │
└─────────────────────────────────────────┼───────────────┘
│
┌─────────────────────────────────────────▼───────────────┐
│ PostgreSQL 16 (externer Docker-Container) │
│ • log_entries, readings, external_data │
│ • api_keys, dashboards, settings_kv │
│ • ocpp_transactions, ocpp_id_tags, ocpp_charging_rules │
│ • wallbox_state, register_names │
└─────────────────────────────────────────────────────────┘
Modbus-Mapping
Das Feld-Mapping basiert auf der V6.2-Konfiguration [1]. Es umfasst:
- Batterie: SOC, Spannung, Strom, Leistung, Ladung/Entladung (Heute/Gesamt), Health, Temperatur
- Netz: Spannung/Leistung L1-L3, Bezug/Einspeisung (Heute/Gesamt), Frequenz
- Solar: Leistung/Spannung/Strom String 1+2, Erzeugung (Heute/Gesamt)
- Haus: Verbrauch L1-L3, Gesamt, Frequenz (Heute/Gesamt)
- Temperatur: Transformator, Kühlkörper, Batterie (Rohwert − 100 °C)
- Konfiguration: Lademodi, Mindestladung, Batteriekapazität, max. Lade-/Entladestrom
- Status: Invertertyp, Status, On/Off, Battery Info
Faktor-Korrekturen
Einige Faktoren aus dem Mapping [1] wurden korrigiert, da sie in der Originaldatei nicht stimmten:
| Feld | Original-Faktor | Korrigierter Faktor | Bemerkung | |
|---|---|---|---|---|
| Batterie Ausgangsleistung | 10 | 10 | DataType 5 (signed), bereits korrekt | |
| Batterie Ausgangsstrom | 0.01 | 0.01 | DataType 5 (signed), bereits korrekt | |
| Solarerzeugung String 1 Heute | 0.01 | 0.01 | Bereits korrekt | |
| Einspeisung Gesamt | 0.01 | 0.01 | Bereits korrekt | |
| Netzbezug aktuell L1-L3 | 0 | 1 | Factor 0 → 1 (Watt.I Profil) | |
| Hausverbrauch L1-L3 | 0 | 1 | Factor 0 → 1 (Watt.I Profil) | |
| Solarleistung String 1/2 | 0 | 1 | Factor 0 → 1 (Watt.I Profil) |
Virtuelle Felder
Temperaturen werden aus Rohregistern berechnet (Rohwert − 100 °C), Zeitpunkte aus Integer HHMM zu "HH:MM" formatiert.
Logging-Logik
Der Logger liest alle 2 Sekunden (einstellbar) die Modbus-Werte:
- Live-Felder (
type: "live"): Werte werden über ein Intervall gepuffert und als Mittelwert gespeichert. - Kumulative Felder (
type: "cumulative"): Werte werden als Delta zum letzten Lesevorgang gespeichert. - Total-Zähler (Felder mit "Total" im Namen): Deltas werden zu einem fortlaufenden Stand kumuliert. Das verhindert Spikes bei geringer Zählerauflösung (z. B. 0 → 1 → 0 → 1).
Reset-Erkennung: Wenn ein kumulativer Zähler zurückgesetzt wird (Tageswechsel), wird kein negativer Delta geloggt.
Docker-Deployment
Mit docker-compose (empfohlen)
cd deye
docker compose up --build -d
Das startet automatisch:
- PostgreSQL (Port 5432, persistentes Volume)
- DEYE App (Port 8002, Modbus + OCPP)
- OCPP-Server (Port 9000, WebSocket)
Konfiguration
Alle Einstellungen über Umgebungsvariablen (Prefix DEYE_):
| Variable | Standard | Beschreibung |
|---|---|---|
DEYE_MODBUS_MODE |
mock |
real oder mock (Test) |
DEYE_ADMIN_PASSWORD |
admin |
Passwort für externen Zugriff |
DEYE_MODBUS_PORT |
/dev/ttyUSB0 |
Serial-Port |
DEYE_MODBUS_BAUDRATE |
9600 |
Baudrate |
DEYE_MODBUS_DEVICE_ID |
1 |
Modbus Geräte-ID |
DEYE_LOG_INTERVAL |
2 |
Logging-Intervall (Sekunden) |
DEYE_DB_HOST |
localhost |
PostgreSQL Host |
DEYE_DB_PORT |
5432 |
PostgreSQL Port |
DEYE_DB_NAME |
deye |
Datenbankname |
DEYE_DB_USER |
deye |
DB-Benutzer |
DEYE_DB_PASSWORD |
deye |
DB-Passwort |
DEYE_OCPP_ENABLED |
true |
OCPP-Server aktivieren |
DEYE_OCPP_PORT |
9000 |
OCPP WebSocket-Port |
DEYE_WALLBOX_CP_ID |
goe |
ChargePoint ID der Wallbox |
Zugriff
- Web-UI:
http://<raspberry-pi-ip>:8002– im Heimnetz ohne Passwort - OCPP:
ws://<raspberry-pi-ip>:9000/goe– in der Go-e Gemini als OCPP-URL eintragen - API-Doku:
http://<raspberry-pi-ip>:8002/docs(Swagger)
Go-e Gemini einrichten
- In der Go-e App unter Experte → OCPP aktivieren
- OCPP-URL eintragen:
ws://<raspberry-pi-ip>:9000/goe - Protokoll: OCPP 1.6
- Die Wallbox verbindet sich automatisch und erscheint im Wallbox-Tab
API-Endpunkte
Interne API (Browser-Session oder lokal)
| Route | Methode | Beschreibung |
|---|---|---|
/api/live |
GET | Live-Daten aller Felder |
/api/live/{field} |
GET | Ein einzelnes Feld |
/api/raw |
GET | Rohe Modbus-Register (mit Namen) |
/api/log |
GET | Log-Einträge (filterbar) |
/api/log/batch |
GET | Log-Daten für mehrere Felder in einem Request |
/api/log |
DELETE | Log-Einträge löschen (optional pro Feld) |
/api/admin/fields |
GET/PUT/POST/DELETE | Felder verwalten |
/api/admin/modbus |
GET/PUT | Modbus-Settings |
/api/admin/modbus/write |
POST | Modbus-Register schreiben |
/api/admin/interval |
GET/PUT | Log-Intervall |
/api/admin/apikeys |
GET/POST/DELETE | API-Keys verwalten (mit Rollen) |
/api/admin/dashboards |
GET/POST/DELETE | Dashboards verwalten |
/api/admin/db/size |
GET | Datenbankgröße |
/api/admin/db/cleanup |
POST | Log-Bereinigung auslösen |
Wallbox-API
| Route | Methode | Beschreibung |
|---|---|---|
/api/wallbox/status |
GET | Wallbox-Status (Leistung, Strom, Energie) |
/api/wallbox/transactions |
GET | Ladehistorie |
/api/wallbox/id-tags |
GET/POST/DELETE | RFID-Chips verwalten |
/api/wallbox/rules |
GET/POST/DELETE | Laderegeln verwalten |
/api/wallbox/control |
POST | Wallbox steuern (Start/Stop/Strom setzen) |
Externe API (API-Key nötig, Header: X-API-Key)
| Route | Methode | Beschreibung |
|---|---|---|
/api/external/live |
GET | Live-Daten (gefiltert nach Key-Rechten) |
/api/external/log |
GET | Log-Daten (gefiltert nach Key-Rechten) |
/api/external/raw |
GET | Rohdaten (nur Admin-Keys) |
/api/external/write |
POST | Modbus schreiben (nur Admin-Keys) |
API-Key-Rollen
- Admin: Voller Zugriff inkl. Schreibrechte, Rohdaten, Wallbox-Steuerung
- Limited: Nur Lesen, auf ausgewählte Felder beschränkt
Beispiel
# Live-Daten mit API-Key
curl -H "X-API-Key: <key>" http://pi:8002/api/external/live
# Log-Daten für mehrere Felder (Batch)
curl "http://pi:8002/api/log/batch?fields=BatSOC,PV1_P&limit=5000"
# Wallbox Ladestrom setzen
curl -X POST -H "Content-Type: application/json" \
-d '{"action":"set_current","current_a":10}' \
http://pi:8002/api/wallbox/control
Wallbox-Regeln
Drei Regel-Typen stehen zur Verfügung:
- Solarladen: Nutzt PV-Überschuss (PV-Leistung − Hausverbrauch) zum Laden. Bei ausreichendem Überschuss wird der Ladestrom automatisch berechnet (230V × 3-phasig).
- Solarladen (Chip-basiert): Wie Solarladen, aber nur für bestimmte RFID-Tags aktivierbar.
- Ladestrombegrenzung: Setzt einen festen Maximalstrom unabhängig vom PV-Überschuss.
Regeln werden im Wallbox-Tab erstellt und angewendet, sobald die Wallbox lädt.
Felder-Definition
Jedes Feld hat folgende Eigenschaften:
| Feld | Typ | Beschreibung |
|---|---|---|
name |
string | Eindeutiger Name (z.B. BatV) |
realname |
string | Anzeigename (z.B. Batterie Spannung) |
address |
int | Absolute Modbus-Register-Adresse |
factor |
float | Skalierungsfaktor (Wert × factor) |
unit |
string | Einheit (z.B. V, W, %, kWh) |
signed |
bool | Vorzeichenbehaftet (für negative Werte) |
type |
string | live (Mittelwert) oder cumulative (Delta) |
log |
bool | Soll dieses Feld geloggt werden? |
Entwicklung / Test
Für Tests ohne echten Modbus-Adapter: DEYE_MODBUS_MODE=mock setzen.
Der Mock generiert realistische sinusförmige Werte.
# PostgreSQL starten (oder extern nutzen)
docker run -d --name deye-pg -e POSTGRES_DB=deye -e POSTGRES_USER=deye \
-e POSTGRES_PASSWORD=deye -p 5432:5432 postgres:16-alpine
# Lokal starten (Testmodus)
DEYE_MODBUS_MODE=mock DEYE_DB_HOST=localhost uvicorn app.main:app --port 8080
Dateistruktur
deye/
├── app/
│ ├── __init__.py
│ ├── config.py # Konfiguration (Modbus, DB, OCPP)
│ ├── database.py # PostgreSQL-Schema & Queries (asyncpg)
│ ├── modbus_reader.py # Modbus-Reader (real + mock, V6.2-Mapping)
│ ├── logger_service.py # Logger-Background-Service
│ ├── ocpp_server.py # OCPP 1.6 WebSocket-Server
│ ├── auth.py # Auth-Middleware & API-Key-Rollen
│ └── main.py # FastAPI-Routen
├── static/
│ ├── index.html # Haupt-App (Single-Page)
│ ├── login.html # Login-Seite
│ └── js/
│ ├── api.js # API-Wrapper mit Deduplication
│ ├── app.js # Haupt-App, Navigation, Live-Polling
│ ├── widgets.js # Widget-Engine (Card, Radial, Balken, Säule)
│ ├── view-solar.js # Solar Monitor (Flow-Diagramm)
│ ├── view-dashboard.js # Dashboard Builder
│ ├── view-log.js # Verlauf (Plotly-Charts)
│ ├── view-raw.js # Rohdaten (Modbus Register)
│ ├── view-wallbox.js # Wallbox (Status, Regeln, Transaktionen)
│ ├── view-admin.js # Admin (Modbus, Felder, Keys, Logging)
│ └── view-api-docs.js # API-Dokumentation
├── Dockerfile
├── docker-compose.yml # PostgreSQL + DEYE App
├── requirements.txt
└── .env.example