8.9 KiB
Fix: SOC springt auf 65535% beim Modus-Wechsel
Problem
Wenn der ESS-Modus von INTERNAL auf REMOTE wechselt, zeigt sensor.esssoc kurzzeitig 65535% (0xFFFF = ungültiger Wert).
Die Automation "Batterie Optimierung: Stopp bei Max-SOC" triggert bei SOC > 99% und beendet das Laden sofort wieder.
Lösung 1: Debounce + Plausibilitäts-Check (EMPFOHLEN)
Ersetze die Automation in battery_optimizer_automations.yaml:
# Automatisierung 8: Laden stoppen wenn SOC erreicht (FIXED)
alias: "Batterie Optimierung: Stopp bei Max-SOC"
description: "Beendet manuelles Laden wenn maximaler SOC erreicht (mit Spike-Protection)"
trigger:
- platform: numeric_state
entity_id: sensor.esssoc
above: 99
condition:
# 1. Manual Control muss aktiv sein
- condition: state
entity_id: input_boolean.goodwe_manual_control
state: "on"
# 2. SOC muss plausibel sein (nicht über 105%)
- condition: numeric_state
entity_id: sensor.esssoc
below: 105
# 3. SOC muss für mindestens 30 Sekunden über 99% sein (Debounce)
- condition: template
value_template: >
{% set soc = states('sensor.esssoc') | float(0) %}
{% set last_changed = as_timestamp(states.sensor.esssoc.last_changed) %}
{% set now = as_timestamp(now()) %}
{% set duration = now - last_changed %}
{{ soc > 99 and soc < 105 and duration > 30 }}
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.goodwe_manual_control
# ESS-Modus wird durch manuelle_speicherbeladung_deaktivieren gesetzt
- service: notify.persistent_notification
data:
title: "Batterie-Optimierung"
message: "Manuelles Laden beendet - SOC {{ states('sensor.esssoc') }}% erreicht"
mode: single
Was das macht:
- Plausibilitäts-Check: SOC muss zwischen 99% und 105% liegen
- Debounce: SOC muss für mindestens 30 Sekunden über 99% sein
- Spike-Protection: 65535% wird ignoriert (liegt über 105%)
Lösung 2: Nur Debounce (Einfacher)
alias: "Batterie Optimierung: Stopp bei Max-SOC"
description: "Beendet manuelles Laden wenn maximaler SOC erreicht"
trigger:
- platform: numeric_state
entity_id: sensor.esssoc
above: 99
for:
seconds: 30 # Warte 30 Sekunden bevor getriggert wird
condition:
- condition: state
entity_id: input_boolean.goodwe_manual_control
state: "on"
# Plausibilitäts-Check
- condition: numeric_state
entity_id: sensor.esssoc
below: 105
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.goodwe_manual_control
- service: notify.persistent_notification
data:
title: "Batterie-Optimierung"
message: "Manuelles Laden beendet - SOC {{ states('sensor.esssoc') }}% erreicht"
mode: single
Vorteil: Einfacher, verwendet Home Assistant's eingebaute for: Funktion
Lösung 3: Initial Delay nach Manual Control Aktivierung
Ignoriere SOC-Änderungen in den ersten 60 Sekunden nach Aktivierung:
alias: "Batterie Optimierung: Stopp bei Max-SOC"
description: "Beendet manuelles Laden wenn maximaler SOC erreicht"
trigger:
- platform: numeric_state
entity_id: sensor.esssoc
above: 99
condition:
- condition: state
entity_id: input_boolean.goodwe_manual_control
state: "on"
# Plausibilitäts-Check
- condition: numeric_state
entity_id: sensor.esssoc
below: 105
# Manual Control muss mindestens 60 Sekunden aktiv sein
- condition: template
value_template: >
{% set last_changed = as_timestamp(states.input_boolean.goodwe_manual_control.last_changed) %}
{% set now = as_timestamp(now()) %}
{% set duration = now - last_changed %}
{{ duration > 60 }}
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.goodwe_manual_control
- service: notify.persistent_notification
data:
title: "Batterie-Optimierung"
message: "Manuelles Laden beendet - SOC {{ states('sensor.esssoc') }}% erreicht"
mode: single
Vorteil: Ignoriert alle Spikes in der ersten Minute nach Modus-Wechsel
Empfehlung: Kombination (Lösung 4)
Die robusteste Lösung kombiniert alle Ansätze:
alias: "Batterie Optimierung: Stopp bei Max-SOC"
description: "Beendet manuelles Laden wenn maximaler SOC erreicht (robust gegen Spikes)"
trigger:
- platform: numeric_state
entity_id: sensor.esssoc
above: 99
for:
seconds: 30 # Debounce: 30 Sekunden warten
condition:
# 1. Manual Control aktiv
- condition: state
entity_id: input_boolean.goodwe_manual_control
state: "on"
# 2. Plausibilitäts-Check: SOC zwischen 99% und 105%
- condition: numeric_state
entity_id: sensor.esssoc
above: 99
- condition: numeric_state
entity_id: sensor.esssoc
below: 105
# 3. Manual Control muss mindestens 60 Sekunden aktiv sein
- condition: template
value_template: >
{% set last_changed = as_timestamp(states.input_boolean.goodwe_manual_control.last_changed) %}
{% set now = as_timestamp(now()) %}
{% set duration = now - last_changed %}
{{ duration > 60 }}
# 4. Sensor muss verfügbar sein
- condition: template
value_template: >
{{ states('sensor.esssoc') not in ['unavailable', 'unknown', 'none'] }}
action:
- service: input_boolean.turn_off
target:
entity_id: input_boolean.goodwe_manual_control
- service: notify.persistent_notification
data:
title: "Batterie-Optimierung"
message: "Manuelles Laden beendet - SOC {{ states('sensor.esssoc') }}% erreicht"
# Logging für Debugging
- service: system_log.write
data:
message: "Battery charging stopped at SOC {{ states('sensor.esssoc') }}%"
level: info
mode: single
Schutz-Mechanismen:
- ✅ 30 Sekunden Debounce: Warte 30s nachdem SOC > 99%
- ✅ Plausibilitäts-Check: SOC muss < 105% sein
- ✅ Initial Delay: Manual Control muss mindestens 60s aktiv sein
- ✅ Availability Check: Sensor muss verfügbar sein
Installation
Option A: Via Home Assistant UI (Empfohlen für schnellen Test)
- Gehe zu Einstellungen → Automationen & Szenen
- Suche "Batterie Optimierung: Stopp bei Max-SOC"
- Bearbeite die Automation
- Ersetze den Inhalt mit einer der obigen Lösungen
- Speichern
Option B: Via YAML
- Öffne deine
automations.yamloder die entsprechende Datei - Finde die Automation (ID oder Alias)
- Ersetze sie mit der neuen Version
- Home Assistant neu laden oder Automationen neu laden
Testing
Test 1: Manuelles Laden ohne Spike-Problem
# Developer Tools → Services
service: input_boolean.turn_on
target:
entity_id: input_boolean.goodwe_manual_control
Warte 2 Minuten und prüfe:
- Bleibt Manual Control aktiv?
- Gibt es SOC-Spikes in den Logs?
Test 2: Simulation eines Spikes
# Developer Tools → States
# Suche sensor.esssoc und ändere temporär den Wert auf 65535
# (nur möglich wenn Sensor-Typ es erlaubt)
Test 3: Echtes Stoppen bei 100%
Warte bis Batterie wirklich bei 100% ist und prüfe ob das Laden dann korrekt gestoppt wird.
Alternative: Sensor-Filter
Wenn das Problem häufiger auftritt, kannst du auch einen gefilterten Sensor erstellen:
# In configuration.yaml
sensor:
- platform: filter
name: "ESS SOC Filtered"
entity_id: sensor.esssoc
filters:
# Entferne ungültige Werte
- filter: outlier
window_size: 4
radius: 10.0
# Entferne extreme Spikes
- filter: range
lower_bound: 0
upper_bound: 100
# Glättung
- filter: lowpass
time_constant: 10
Dann verwende sensor.ess_soc_filtered in allen Automationen statt sensor.esssoc.
Monitoring
Füge eine Notification hinzu wenn ungültige Werte erkannt werden:
alias: "Debug: SOC Spike Detector"
description: "Warnt bei ungültigen SOC-Werten"
trigger:
- platform: numeric_state
entity_id: sensor.esssoc
above: 105
action:
- service: notify.persistent_notification
data:
title: "SOC Spike erkannt!"
message: "SOC zeigt {{ states('sensor.esssoc') }}% - wahrscheinlich ungültiger Wert"
- service: system_log.write
data:
message: "SOC spike detected: {{ states('sensor.esssoc') }}% at {{ now() }}"
level: warning
mode: queued
Nächste Schritte
- JETZT: Implementiere Lösung 4 (kombinierter Ansatz)
- TESTE: Aktiviere heute Abend manuelles Laden und beobachte
- MONITOR: Installiere die Spike Detector Automation
- LANGFRISTIG: Erwäge einen gefilterten Sensor für mehr Robustheit
Zusätzliche Absicherungen
Füge auch in der execute_charging_schedule Funktion einen Check ein:
# In battery_charging_optimizer.py, Zeile 67
current_soc = float(state.get('sensor.esssoc') or 50)
# Plausibilitäts-Check hinzufügen:
if current_soc > 105 or current_soc < 0:
log.warning(f"⚠ Ungültiger SOC-Wert erkannt: {current_soc}%. Verwende letzten gültigen Wert.")
# Verwende einen Fallback-Wert oder den letzten gültigen Wert
current_soc = 50 # Oder aus einem gespeicherten State laden