Files
battery-charging-optimizer/FIX_SOC_SPIKE_PROBLEM.md

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:

  1. Plausibilitäts-Check: SOC muss zwischen 99% und 105% liegen
  2. Debounce: SOC muss für mindestens 30 Sekunden über 99% sein
  3. 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:

  1. 30 Sekunden Debounce: Warte 30s nachdem SOC > 99%
  2. Plausibilitäts-Check: SOC muss < 105% sein
  3. Initial Delay: Manual Control muss mindestens 60s aktiv sein
  4. Availability Check: Sensor muss verfügbar sein

Installation

Option A: Via Home Assistant UI (Empfohlen für schnellen Test)

  1. Gehe zu Einstellungen → Automationen & Szenen
  2. Suche "Batterie Optimierung: Stopp bei Max-SOC"
  3. Bearbeite die Automation
  4. Ersetze den Inhalt mit einer der obigen Lösungen
  5. Speichern

Option B: Via YAML

  1. Öffne deine automations.yaml oder die entsprechende Datei
  2. Finde die Automation (ID oder Alias)
  3. Ersetze sie mit der neuen Version
  4. 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

  1. JETZT: Implementiere Lösung 4 (kombinierter Ansatz)
  2. TESTE: Aktiviere heute Abend manuelles Laden und beobachte
  3. MONITOR: Installiere die Spike Detector Automation
  4. 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