Files
battery-charging-optimizer/DIAGNOSE_LADE_PROBLEM.md

256 lines
8.0 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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"
```