Files
battery-charging-optimizer/DIAGNOSE_LADE_PROBLEM.md

8.0 KiB
Raw Blame History

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:

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:

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:

service: input_number.set_value
target:
  entity_id: input_number.charge_power_battery
data:
  value: -5000

Dann:

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:

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:

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):

# 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):

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
# Auf BeagleBone
tail -f /var/log/openems/openems.log | grep -i "active.*power"