# Diagnose: Battery Charging nicht funktioniert ## Problem-Beschreibung Heute Nacht wurde nicht geladen, obwohl: - Der Speicher von INTERNAL auf REMOTE geschaltet wurde - `goodwe_manual_control` aktiviert wurde - Nach ein paar Sekunden wurde es wieder deaktiviert ## Wahrscheinliche Ursachen ### 1. Stündliche Ausführung stoppt das Laden **Problem**: Die Automation "Batterie Optimierung: Stündliche Ausführung" läuft **jede Stunde** um xx:05 und prüft den Schedule für die aktuelle Stunde. **Verhalten**: - Stunde mit `action='charge'` → Laden wird aktiviert - Stunde mit `action='auto'` → Laden wird deaktiviert **Szenario**: ``` 23:05 → Schedule sagt "charge" → Laden startet 00:05 → Schedule sagt "auto" → Laden stoppt ``` **Mögliche Ursachen**: - Schedule enthält nur 1 Ladestunde statt mehrere - Zeitzone-Problem: Falsche Stunde wird geprüft - Tomorrow-Daten fehlen im Schedule ### 2. Schedule wurde nicht richtig erstellt **Problem**: Die tägliche Berechnung um 14:05 hat keinen sinnvollen Ladeplan erstellt. **Mögliche Ursachen**: - Batterie war schon voll (kein Ladebedarf) - Tomorrow-Preise waren noch nicht verfügbar - Alle Nachtstunden waren nicht unter den N günstigsten ### 3. Zeitzone-Problem in execute_charging_schedule **Problem**: Der Vergleich zwischen aktueller Zeit und Schedule-Einträgen schlägt fehl. Code in Zeile 593-606: ```python entry_dt = datetime.fromisoformat(entry['datetime']) if entry_dt.tzinfo is None: entry_dt = entry_dt.replace(tzinfo=TIMEZONE) entry_date = entry_dt.date() entry_hour = entry_dt.hour if entry_date == current_date and entry_hour == current_hour: current_entry = entry ``` **Mögliches Problem**: Die Datetimes im Schedule sind nicht korrekt timezone-aware. ## Debug-Schritte ### Schritt 1: Schedule prüfen Gehe zu **Developer Tools → States** und suche nach: ``` pyscript.battery_charging_schedule ``` **Was zu prüfen**: 1. Wann wurde `last_update` zuletzt aktualisiert? 2. Wie viele `num_charges` sind geplant? 3. Wie viele `num_charges_tomorrow` für die Nacht? 4. Schau dir das `schedule` Array in den Attributen an **Interpretation**: - `num_charges = 0` → Keine Ladungen geplant (Batterie war voll?) - `num_charges_tomorrow = 0` → Keine Nachtstunden geplant - `has_tomorrow_data = false` → Morgen-Preise fehlen ### Schritt 2: Home Assistant Logs prüfen Öffne die Home Assistant Logs und suche nach PyScript-Ausgaben: **Für die tägliche Berechnung** (sollte um 14:05 laufen): ``` === Batterie-Optimierung gestartet (v3.2 - FIXED Timezones) === Konfiguration geladen: SOC 20-100%, Max 5000W Strompreise geladen: X Stunden (Tomorrow: true/false) Benötigte Ladestunden: X (bei 5000W pro Stunde) Top X günstigste Stunden ausgewählt ``` **Für die stündliche Ausführung** (läuft jede Stunde um xx:05): ``` Suche Ladeplan für YYYY-MM-DD HH:00 Uhr (lokal) ✓ Gefunden: YYYY-MM-DDTHH:00:00+01:00 ⚡ Stunde HH:00 [heute/morgen]: action=charge/auto, power=XW, price=X.XXct ``` **Kritische Warnungen zu suchen**: ``` ⚠ Keine Daten für YYYY-MM-DD HH:00 Keine zukünftigen Preise verfügbar ``` ### Schritt 3: Zeitzone-Verifikation Führe manuell den Schedule aus und beobachte die Logs: **Developer Tools → Services**: ```yaml service: pyscript.execute_charging_schedule data: {} ``` **Was zu beobachten**: 1. Welche Zeit wird gesucht? "Suche Ladeplan für ..." 2. Wird ein Eintrag gefunden? "✓ Gefunden: ..." 3. Welche Aktion wird ausgeführt? "action=charge" oder "action=auto" ### Schritt 4: Manuellen Test durchführen Um zu verifizieren, dass das Laden grundsätzlich funktioniert: **Developer Tools → Services**: ```yaml service: input_number.set_value target: entity_id: input_number.charge_power_battery data: value: -5000 ``` Dann: ```yaml service: input_boolean.turn_on target: entity_id: input_boolean.goodwe_manual_control ``` **Erwartetes Verhalten**: 1. ESS schaltet auf REMOTE 2. Keep-Alive Automation startet (alle 30s) 3. Batterie beginnt zu laden **Wenn das funktioniert**: Problem liegt im Schedule/Optimizer **Wenn das nicht funktioniert**: Problem liegt in den Automations/OpenEMS ### Schritt 5: Schedule-Berechnung triggern Führe eine neue Berechnung aus: **Developer Tools → Services**: ```yaml service: pyscript.calculate_charging_schedule data: {} ``` Dann prüfe: 1. Die Logs für die Berechnung 2. Den neuen Schedule in `pyscript.battery_charging_schedule` 3. Ob Ladestunden für heute Nacht geplant sind ## Typische Probleme und Lösungen ### Problem A: "Keine Ladung nötig (Batterie voll)" **Symptom**: `num_charges = 0` im Schedule **Ursache**: `current_soc >= max_soc - reserve` **Lösung**: Normal, wenn Batterie voll ist. Warte bis SOC sinkt. ### Problem B: "Tomorrow-Daten fehlen" **Symptom**: `has_tomorrow_data = false`, nur wenige Stunden im Schedule **Ursache**: Berechnung lief vor 14:00, als Preise für morgen noch nicht verfügbar waren **Lösung**: Warte bis nach 14:00, dann läuft automatische Neuberechnung ### Problem C: "Zeitzone-Mismatch" **Symptom**: "⚠ Keine Daten für YYYY-MM-DD HH:00" obwohl Schedule existiert **Ursache**: Zeitvergleich matcht nicht **Lösung**: Siehe Code-Fix unten ### Problem D: "Keep-Alive Automation läuft nicht" **Symptom**: ESS ist auf REMOTE, aber keine Modbus-Befehle werden gesendet **Ursache**: Automation "Speicher manuell laden" ist deaktiviert oder fehlerhaft **Lösung**: Prüfe ob Automation aktiviert ist und läuft ## Code-Verbesserungsvorschläge ### Fix 1: Logging verbessern in execute_charging_schedule Füge mehr Debug-Output hinzu in Zeile 587: ```python log.info(f"=== Stündliche Ausführung gestartet ===") log.info(f"Lokale Zeit: {now.strftime('%Y-%m-%d %H:%M:%S %Z')}") log.info(f"Suche Ladeplan für {current_date} {current_hour}:00 Uhr (lokal)") log.info(f"Schedule hat {len(schedule)} Einträge") # Zeige alle Schedule-Einträge für Debugging for i, entry in enumerate(schedule): entry_dt = datetime.fromisoformat(entry['datetime']) if entry_dt.tzinfo is None: entry_dt = entry_dt.replace(tzinfo=TIMEZONE) log.debug(f" [{i}] {entry_dt} → {entry['action']}") ``` ### Fix 2: Robusteres Datetime-Matching Ersetze den exakten Stunden-Match durch ein Zeitfenster (Zeile 603): ```python # Statt exaktem Match: if entry_date == current_date and entry_hour == current_hour: # Verwende Zeitfenster (z.B. ±5 Minuten): entry_start = entry_dt.replace(minute=0, second=0) entry_end = entry_start + timedelta(hours=1) if entry_start <= now < entry_end: current_entry = entry log.info(f"✓ Match gefunden für Zeitfenster {entry_start} - {entry_end}") break ``` ### Fix 3: Fallback für fehlende Matches Nach der Schleife (Zeile 608): ```python if not current_entry: log.warning(f"⚠ Keine Daten für {current_date} {current_hour}:00") # Debug: Zeige nächsten verfügbaren Eintrag future_entries = [] for entry in schedule: entry_dt = datetime.fromisoformat(entry['datetime']) if entry_dt.tzinfo is None: entry_dt = entry_dt.replace(tzinfo=TIMEZONE) if entry_dt > now: future_entries.append((entry_dt, entry['action'])) if future_entries: next_entry = min(future_entries, key=lambda x: x[0]) log.info(f"ℹ Nächster Schedule-Eintrag: {next_entry[0]} → {next_entry[1]}") else: log.warning("⚠ Keine zukünftigen Schedule-Einträge gefunden!") return ``` ## Nächste Schritte 1. **JETZT**: Führe Debug-Schritte 1-3 aus und notiere die Ergebnisse 2. **Prüfe**: Wie sieht der aktuelle Schedule aus? 3. **Teste**: Funktioniert manuelles Laden (Schritt 4)? 4. **Entscheide**: Basierend auf den Ergebnissen, welche Fix-Strategie anzuwenden ist ## Monitoring für die nächste Nacht Um zu sehen, was heute Nacht passiert: 1. **Prüfe Schedule um 14:05**: Nach der täglichen Berechnung 2. **Setze Benachrichtigung**: Für 23:05 (erste mögliche Ladestunde) 3. **Überwache Logs**: Live während der Ladestunden 4. **Prüfe OpenEMS**: Logs auf dem BeagleBone für Controller-Aktivität ```bash # Auf BeagleBone tail -f /var/log/openems/openems.log | grep -i "active.*power" ```