221 lines
7.1 KiB
Markdown
221 lines
7.1 KiB
Markdown
# OpenEMS Battery Charging Optimizer für Home Assistant
|
||
|
||
Intelligente Batterieladesteuerung für Home Assistant mit OpenEMS und GoodWe Hardware. Das System optimiert die Batterieladung basierend auf dynamischen Strompreisen (haStrom FLEX PRO) und Solarprognosen.
|
||
|
||
[](CHANGELOG.md)
|
||
[](https://www.home-assistant.io/)
|
||
[](LICENSE)
|
||
|
||
## Features
|
||
|
||
- **Dynamische Preisoptimierung**: Lädt die Batterie während der günstigsten Strompreis-Stunden
|
||
- **Solar-Integration**: Berücksichtigt PV-Prognosen (Forecast.Solar)
|
||
- **Cross-Midnight Optimierung**: Findet die günstigsten Stunden über Tagesgrenzen hinweg
|
||
- **Tomorrow-Support**: Nutzt morgige Strompreise für 48h-Vorausplanung (ab 14:00)
|
||
- **Automatische Modbus-Steuerung**: Direkte Batteriesteuerung via OpenEMS Modbus TCP
|
||
- **Intelligente Keep-Alive**: Erhält Ladebefehle automatisch alle 30 Sekunden aufrecht
|
||
- **Restart-Safe**: Automatische Neuberechnung nach Home Assistant Neustart
|
||
|
||
## Hardware-Voraussetzungen
|
||
|
||
- **Batterie**: GoodWe Lynx Home U (10 kWh)
|
||
- **Inverter**: GoodWe GW10K-ET Plus+ (10 kW)
|
||
- **PV-Anlage**: 9.2 kWp (Ost-West auf Flachdach)
|
||
- **EMS**: BeagleBone mit OpenEMS
|
||
- **Kommunikation**: Modbus TCP (Port 502) + JSON-RPC (Port 8074)
|
||
|
||
## Software-Voraussetzungen
|
||
|
||
- Home Assistant 2024.2 oder neuer
|
||
- PyScript Integration
|
||
- Custom Components:
|
||
- Mushroom Cards (HACS)
|
||
- Bubble Card (HACS)
|
||
- Plotly Graph Card (HACS)
|
||
- Power Flow Card Plus (HACS)
|
||
|
||
## Schnellstart
|
||
|
||
1. **Installation**: Siehe [INSTALLATION.md](INSTALLATION.md)
|
||
2. **Konfiguration**: Passe `battery_optimizer_config.yaml` an deine Hardware an
|
||
3. **Erste Schritte**: Aktiviere `input_boolean.battery_optimizer_enabled`
|
||
4. **Dashboard**: Importiere eines der Dashboards aus `dashboards/`
|
||
|
||
## Architektur
|
||
|
||
```
|
||
14:05 täglich → calculate_charging_schedule → Erstellt Ladeplan
|
||
↓
|
||
xx:05 stündlich → execute_charging_schedule → Führt Plan aus
|
||
↓
|
||
Bei Laden → goodwe_manual_control ON → Triggert Automationen
|
||
↓
|
||
Automation aktivieren → ESS REMOTE-Modus → Enables Keep-Alive
|
||
↓
|
||
Keep-Alive (30s) → ess_set_power → Modbus Befehl an Batterie
|
||
```
|
||
|
||
## Repository-Struktur
|
||
|
||
```
|
||
.
|
||
├── pyscripts/
|
||
│ ├── battery_charging_optimizer.py # Haupt-Optimierer (v3.3.1)
|
||
│ ├── hastrom_flex_extended.py # Strompreis-Integration
|
||
│ └── ess_set_power.py # Modbus Batteriesteuerung
|
||
├── config/
|
||
│ ├── battery_optimizer_config.yaml # Input Helper Konfiguration
|
||
│ └── rest_requests.yaml # ESS Modus-Umschaltung
|
||
├── automations/
|
||
│ ├── battery_optimizer_automations.yaml # Optimizer Automationen
|
||
│ ├── speicher_manuell_laden.yaml # Keep-Alive
|
||
│ ├── manuelle_speicherbeladung_aktivieren.yaml # ESS → REMOTE
|
||
│ └── manuelle_speicherbeladung_deaktivieren.yaml # ESS → INTERNAL
|
||
├── dashboards/
|
||
│ ├── battery_optimizer_sections_standard.yaml # Empfohlenes Dashboard
|
||
│ ├── battery_optimizer_sections_compact.yaml # Kompakte Variante
|
||
│ └── battery_optimizer_sections_minimal.yaml # Minimal-Ansicht
|
||
├── docs/
|
||
│ ├── EMS_OpenEMS_HomeAssistant_Dokumentation.md # Technische Details
|
||
│ ├── INSTALLATION.md # Installationsanleitung
|
||
│ └── TROUBLESHOOTING.md # Fehlerbehebung
|
||
├── legacy/
|
||
│ ├── v1/ # Erste Implementation (threshold-based)
|
||
│ ├── v2/ # Verbesserte Version
|
||
│ └── v3/ # Ranking-based (Basis für v3.3.1)
|
||
└── README.md
|
||
```
|
||
|
||
## Algorithmus
|
||
|
||
**Ranking-Based Optimization** (v3.x):
|
||
|
||
1. Berechne benötigte Ladestunden: `(Ziel-SOC - aktueller SOC) × Kapazität ÷ Ladeleistung`
|
||
2. Kombiniere Heute + Morgen Preisdaten in ein Dataset
|
||
3. Score jede Stunde: `Preis - (PV-Prognose / 1000)`
|
||
4. Sortiere nach Score (niedrigster = best)
|
||
5. Wähle die N günstigsten Stunden
|
||
6. Führe chronologisch aus
|
||
|
||
**Beispiel**: Bei 10 kWh Batterie, 50% SOC, 5 kW Ladeleistung:
|
||
- Benötigt: (100% - 50%) × 10 kWh ÷ 5 kW = 10 Stunden
|
||
- Wählt die 10 günstigsten Stunden aus den nächsten 48h
|
||
|
||
## Wichtige Konzepte
|
||
|
||
### Timezone-Handling
|
||
|
||
PyScript läuft in UTC, Home Assistant speichert in `Europe/Berlin`:
|
||
|
||
```python
|
||
from zoneinfo import ZoneInfo
|
||
TIMEZONE = ZoneInfo("Europe/Berlin")
|
||
|
||
def get_local_now():
|
||
return datetime.now(TIMEZONE)
|
||
```
|
||
|
||
### Power Value Convention
|
||
|
||
**Negativ = Laden, Positiv = Entladen**
|
||
|
||
```python
|
||
input_number.charge_power_battery = -5000 # Lädt mit 5000W
|
||
input_number.charge_power_battery = +3000 # Entlädt mit 3000W
|
||
```
|
||
|
||
### Controller Priority (OpenEMS)
|
||
|
||
Controller führen in **alphabetischer Reihenfolge** aus. Spätere Controller können frühere überschreiben.
|
||
|
||
Lösung: `ctrlBalancing0` mit `SET_GRID_ACTIVE_POWER` für höchste Priorität verwenden.
|
||
|
||
## Konfiguration
|
||
|
||
Passe diese Werte in `battery_optimizer_config.yaml` an:
|
||
|
||
```yaml
|
||
input_number:
|
||
battery_capacity_kwh:
|
||
initial: 10 # Deine Batteriekapazität in kWh
|
||
|
||
battery_optimizer_max_charge_power:
|
||
initial: 5000 # Maximale Ladeleistung in W
|
||
|
||
battery_optimizer_min_soc:
|
||
initial: 20 # Minimum SOC in %
|
||
|
||
battery_optimizer_max_soc:
|
||
initial: 100 # Maximum SOC in %
|
||
```
|
||
|
||
## Entwicklung
|
||
|
||
### Version History
|
||
|
||
- **v3.3.1** (aktuell): SOC-Plausibilitäts-Check, negative Power-Values
|
||
- **v3.2.0**: Timezone-Fixes durchgehend
|
||
- **v3.1.0**: Ranking-based Optimization, Tomorrow-Support
|
||
- **v2.x**: Verbesserte Dashboards, Error Handling
|
||
- **v1.x**: Initial Release, Threshold-based
|
||
|
||
Siehe [CHANGELOG.md](CHANGELOG.md) für Details.
|
||
|
||
### Testing
|
||
|
||
```bash
|
||
# In Home Assistant Developer Tools → Services:
|
||
|
||
# Schedule berechnen
|
||
service: pyscript.calculate_charging_schedule
|
||
|
||
# Aktuellen Plan ausführen
|
||
service: pyscript.execute_charging_schedule
|
||
|
||
# PyScript neu laden
|
||
service: pyscript.reload
|
||
```
|
||
|
||
### Debugging
|
||
|
||
```bash
|
||
# Logs anzeigen (Home Assistant)
|
||
tail -f /config/home-assistant.log | grep -i battery
|
||
|
||
# OpenEMS Logs (BeagleBone)
|
||
tail -f /var/log/openems/openems.log
|
||
```
|
||
|
||
## Datenquellen
|
||
|
||
- **haStrom FLEX PRO**: `http://eex.stwhas.de/api/spotprices/flexpro`
|
||
- **Forecast.Solar**: Automatisch via Home Assistant Integration
|
||
- **OpenEMS Modbus**: `192.168.89.144:502`
|
||
- **OpenEMS JSON-RPC**: `192.168.89.144:8074`
|
||
|
||
## Beitragende
|
||
|
||
Entwickelt von Felix für das eigene Heimenergiesystem.
|
||
|
||
Contributions sind willkommen! Bitte erstelle ein Issue oder Pull Request.
|
||
|
||
## Lizenz
|
||
|
||
MIT License - siehe [LICENSE](LICENSE) für Details.
|
||
|
||
## Support
|
||
|
||
Bei Fragen oder Problemen:
|
||
|
||
1. Prüfe [TROUBLESHOOTING.md](docs/TROUBLESHOOTING.md)
|
||
2. Schaue in die [Issues](https://gitea.ges4.net/felix/openems-battery-optimizer/issues)
|
||
3. Erstelle ein neues Issue mit Logs und Konfiguration
|
||
|
||
## Danksagungen
|
||
|
||
- [Home Assistant](https://www.home-assistant.io/) Community
|
||
- [PyScript](https://github.com/custom-components/pyscript) Integration
|
||
- [OpenEMS](https://openems.io/) Projekt
|
||
- [haStrom](https://www.has-strom.de/) für die API
|
||
- [Forecast.Solar](https://forecast.solar/) für PV-Prognosen
|