Files
battery-charging-optimizer/HOTFIX_PRICE_THRESHOLD_v3.5.1.md
Felix Zösch 5b305b7653 HOTFIX v3.5.1: Preisschwelle wird jetzt korrekt angewendet (KRITISCH)
## Problem
Die price_threshold wurde geladen aber NIE verwendet!
- System lud auch bei Preisen ÜBER der Schwelle
- Beispiel: Schwelle 25ct, aber Ladung bei 25.93ct
- User-Erwartung komplett ignoriert

## Root Cause
```python
# Zeile 110: Geladen ✓
'price_threshold': float(state.get(...) or 25)

# Zeile 317-340: Aber nie verwendet! ✗
for p in future_price_data:
    charging_candidates.append({...})  # Keine threshold-Prüfung!
```

## Fix (v3.5.1)

### 1. Filter VOR Ranking
- Filtere alle Stunden in affordable_hours (≤ threshold)
- Ignoriere teure Stunden komplett
- Wenn keine bezahlbaren Stunden: Keine Ladung (Auto-Modus)

### 2. Besseres Logging
```
💶 Preisschwelle: 25.0 ct/kWh
  - Stunden unter Schwelle: 18
  - Stunden über Schwelle: 12 (werden ignoriert)
```

### 3. Warnung bei Teilladung
Wenn nicht genug günstige Stunden für volle Ladung

## Verhalten

**VORHER (v3.5.0):**
- Alle Preise 25-30ct, Schwelle 25ct
- → Lädt bei 25.93ct ✗

**NACHHER (v3.5.1):**
- Alle Preise 25-30ct, Schwelle 25ct
- → Keine Ladung, Auto-Modus ✓

## Impact
Severity: 🔴 CRITICAL
- Ungewollte Ladevorgänge bei zu teuren Preisen
- Kosteneinsparungen nicht realisiert
- SOFORT updaten empfohlen!

## Dateien
- battery_charging_optimizer.py: Filter + Logging
- CHANGELOG.md: v3.5.1 Eintrag
- HOTFIX_PRICE_THRESHOLD_v3.5.1.md: Detaillierte Analyse

Danke an Felix für sofortiges Bug-Melden! 🙏

---

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-28 17:14:49 +01:00

5.6 KiB

Hotfix: Preisschwelle wurde nicht angewendet (v3.5.1)

Problem

Die Preisschwelle (price_threshold) wurde zwar aus den Input Helpern geladen, aber nie im Code verwendet. Das führte dazu, dass:

  • System lud auch bei Preisen ÜBER der Schwelle
  • Beispiel: Schwelle 25ct, aber Ladung bei 25.93ct geplant
  • User-Erwartung: Keine Ladung wenn alle Preise über Schwelle

Analyse

# battery_charging_optimizer.py:110
'price_threshold': float(state.get('input_number.battery_optimizer_price_threshold') or 25),
# ✅ Wurde geladen

# battery_charging_optimizer.py:317-340 (ALT)
for p in future_price_data:
    charging_candidates.append({...})  # ❌ Keine Prüfung gegen threshold!

Resultat: Alle zukünftigen Stunden wurden in die Ranking-Liste aufgenommen, unabhängig vom Preis.

Lösung (v3.5.1)

1. Filter VOR dem Ranking

# Zeile 315-334: Neuer Filter
price_threshold = config['price_threshold']
affordable_hours = []
expensive_hours = []

for p in future_price_data:
    if p['price'] <= price_threshold:
        affordable_hours.append(p)
    else:
        expensive_hours.append(p)

# Wenn keine bezahlbaren Stunden verfügbar
if not affordable_hours:
    log.warning(f"⚠️ Keine Stunden unter Preisschwelle {price_threshold} ct/kWh")
    return create_auto_only_schedule(future_price_data)  # Keine Ladung!

2. Ranking nur mit bezahlbaren Stunden

# Zeile 341: Nur affordable_hours verwenden
for p in affordable_hours:  # Statt future_price_data
    charging_candidates.append({...})

3. Besseres Logging

log.info(f"💶 Preisschwelle: {price_threshold} ct/kWh")
log.info(f"  - Stunden unter Schwelle: {len(affordable_hours)}")
log.info(f"  - Stunden über Schwelle: {len(expensive_hours)} (werden ignoriert)")

# Im Schedule:
reason = f"Zu teuer: {p['price']:.2f}ct (Schwelle: {price_threshold}ct)"

4. Warnung bei Teilladung

if actual_hours_needed < needed_hours:
    log.warning(f"⚠️ Nur {actual_hours_needed} von {needed_hours} benötigten Stunden unter Preisschwelle")
    log.warning(f"   Batterie wird nur teilweise geladen")

Verhalten vorher vs. nachher

Szenario: Schwelle 25ct, alle Preise 25-30ct

VORHER (v3.5.0):

Preis-Array: [25.93, 26.45, 27.12, 28.50, ...]
→ Ranking: Sortiere alle nach Preis
→ Wähle günstigste: 25.93ct (Rang 1)
→ ✗ LÄDT bei 25.93ct (über Schwelle 25ct!)

NACHHER (v3.5.1):

Preis-Array: [25.93, 26.45, 27.12, 28.50, ...]
→ Filter: Alle über 25ct → affordable_hours = []
→ ⚠️ Keine Stunden unter Preisschwelle 25ct
→ ✓ KEINE LADUNG (Auto-Modus)

Szenario: Schwelle 25ct, Preise 20-30ct

VORHER (v3.5.0):

Preis-Array: [20.50, 24.80, 25.93, 26.45, ...]
→ Ranking: [20.50, 24.80, 25.93, 26.45, ...]
→ Wähle Top 3: [20.50, 24.80, 25.93]
→ ✗ LÄDT auch bei 25.93ct (über Schwelle!)

NACHHER (v3.5.1):

Preis-Array: [20.50, 24.80, 25.93, 26.45, ...]
→ Filter: affordable_hours = [20.50, 24.80]
→ Ranking: [20.50, 24.80]
→ Wähle Top 2: [20.50, 24.80]
→ ✓ NUR unter Schwelle, 25.93ct ignoriert
→ Warnung: "Nur 2 von 3 benötigten Stunden"

Log-Ausgaben neu (v3.5.1)

=== Batterie-Optimierung gestartet (v3.5.1 - Preisschwelle aktiv) ===
Preise: Min=20.50, Max=30.45, Avg=25.67 ct/kWh
Verfügbare Ladekapazität: 5.00 kWh (bis 100% SOC)
🎯 Benötigte Ladestunden: 1 (bei 8000W pro Stunde)
💶 Preisschwelle: 25.0 ct/kWh
  - Stunden unter Schwelle: 18
  - Stunden über Schwelle: 12 (werden ignoriert)
✓ Top 1 günstigste Stunden ausgewählt:
  - Preise: 20.50 - 20.50 ct/kWh

Oder wenn KEINE günstigen Stunden:

💶 Preisschwelle: 25.0 ct/kWh
  - Stunden unter Schwelle: 0
  - Stunden über Schwelle: 30 (werden ignoriert)
⚠️ Keine Stunden unter Preisschwelle 25.0 ct/kWh gefunden!
   Günstigster Preis: 25.93 ct/kWh
   → Keine Ladung, bleibe im Auto-Modus

Impact

Severity: 🔴 CRITICAL

  • Führte zu ungewollten Ladevorgängen bei zu teuren Preisen
  • Kosteneinsparungen wurden nicht realisiert
  • User-Erwartung komplett ignoriert

Betroffene Versionen:

  • v3.5.0 (heute released)
  • Wahrscheinlich auch v3.0.0 - v3.4.0 (zu prüfen)

Fix-Priorität: SOFORT

  • Hotfix v3.5.1 released
  • User sollten SOFORT updaten

Migration 3.5.0 → 3.5.1

  1. Update battery_charging_optimizer.py (v3.5.1)
  2. PyScript neu laden
  3. Neuberechnung: pyscript.calculate_charging_schedule
  4. Log prüfen: Sollte "Preisschwelle: X ct/kWh" zeigen

Keine Breaking Changes - Nur Bugfix.

Testing

Test-Szenarien:

  1. Alle Preise über Schwelle:

    • Setze price_threshold auf 20ct
    • Wenn alle Preise > 20ct → Keine Ladung
    • Log: "Keine Stunden unter Preisschwelle"
  2. Mix aus günstigen/teuren Stunden:

    • Setze price_threshold auf 25ct
    • Nur Stunden ≤ 25ct sollten im Plan sein
    • Log: "X Stunden unter Schwelle, Y über Schwelle"
  3. Alle Preise unter Schwelle:

    • Setze price_threshold auf 50ct
    • Normales Verhalten wie bisher
    • Log: "30 Stunden unter Schwelle, 0 über Schwelle"

Lessons Learned

  1. Configuration muss verwendet werden:

    • Laden von Config ≠ Verwenden von Config
    • Code-Review: Prüfe ob alle Config-Werte auch benutzt werden
  2. User-Feedback ernst nehmen:

    • User hat Bug sofort entdeckt beim ersten Test
    • Ohne User-Test wäre Bug unentdeckt geblieben
  3. Logging ist essentiell:

    • Mit neuem Logging ist sofort ersichtlich was passiert
    • "X Stunden unter Schwelle" macht Verhalten transparent

Danke

Großes Dankeschön an Felix für das sofortige Melden des Bugs! 🙏


Version: 3.5.1
Datum: 2025-12-28
Severity: Critical
Status: Fixed