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.

Version Home Assistant 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
  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:

from zoneinfo import ZoneInfo
TIMEZONE = ZoneInfo("Europe/Berlin")

def get_local_now():
    return datetime.now(TIMEZONE)

Power Value Convention

Negativ = Laden, Positiv = Entladen

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:

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 für Details.

Testing

# 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

# 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 für Details.

Support

Bei Fragen oder Problemen:

  1. Prüfe TROUBLESHOOTING.md
  2. Schaue in die Issues
  3. Erstelle ein neues Issue mit Logs und Konfiguration

Danksagungen

Description
No description provided
Readme MIT 250 KiB
Languages
Python 100%