Files
battery-charging-optimizer/templates.yaml
felix.zoesch 0fa03a566a feat: Major update - Battery Optimizer v3.4.0 with comprehensive fixes
## 🎯 Hauptänderungen

### Version 3.4.0 - SOC-Drift & Charging Capacity
-  Sicherheitspuffer (20-50% konfigurierbar) für untertägige SOC-Schwankungen
-  Monatliche automatische Batterie-Kalibrierung
- 🐛 SOC-Plausibilitäts-Check (filtert 65535% Spikes beim Modus-Wechsel)
- 🐛 Zeitabhängige API-Abfrage (vor/nach 14:00 Uhr)

### Neue Features
- 🔋 **Safety Buffer**: Kompensiert SOC-Drift und Eigenverbrauch
- 🔋 **Auto-Calibration**: Monatlicher Vollzyklus für SOC-Genauigkeit
- 🔋 **Spike Protection**: 4-fach Schutz gegen ungültige SOC-Werte
- 🔋 **Smart API**: Verhindert HTTP 500 Errors bei fehlenden Tomorrow-Preisen

### Dokumentation
- 📚 SOC_CALIBRATION_GUIDE.md - Umfassender Kalibrierungs-Guide
- 📚 FIX_CHARGING_CAPACITY.md - Sicherheitspuffer-Dokumentation
- 📚 FIX_SOC_SPIKE_PROBLEM.md - Spike-Protection-Lösung
- 📚 FIX_API_TIMING.md - Zeitabhängige API-Abfrage
- 📚 DIAGNOSE_LADE_PROBLEM.md - Debug-Guide

### Neue Dateien
- battery_calibration_automation.yaml - 4 Automations für Kalibrierung
- battery_calibration_input_helper.yaml - Input Helper Config
- battery_optimizer_input_helper_safety_buffer.yaml - Puffer Config
- debug_schedule.py - Umfassendes Debug-Script

### Scripts
- battery_charging_optimizer.py v3.4.0
- hastrom_flex_extended.py v1.1.0
- debug_schedule.py v1.0.0

### Fixes
- 🐛 SOC springt auf 65535% beim ESS-Modus-Wechsel → Debounce + Plausibilitäts-Check
- 🐛 API-HTTP-500 vor 14:00 → Zeitabhängige Abfrage
- 🐛 Batterie nicht bis 100% geladen → Sicherheitspuffer
- 🐛 SOC driftet ohne Vollzyklen → Automatische Kalibrierung

## 🚀 Installation

1. Input Helper erstellen (siehe battery_optimizer_input_helper_safety_buffer.yaml)
2. Automations installieren (siehe battery_calibration_automation.yaml)
3. Scripts aktualisieren (battery_charging_optimizer.py v3.4.0)
4. PyScript neu laden

## 📊 Verbesserungen

- Präzisere Ladeplanung durch Sicherheitspuffer
- Robustheit gegen SOC-Drift
- Keine API-Fehler mehr vor 14:00
- Hardware-Stopp bei 100% wird respektiert
- Bessere Batterie-Gesundheit durch regelmäßige Kalibrierung

🤖 Generated with Claude Code (claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-12-12 08:04:07 +01:00

300 lines
13 KiB
YAML

#############
# TEMPLATES
#############
template:
- sensor:
## KNX Strommessung -> Leistung ##
- name: "Spülmaschine Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_spuhlmaschine_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
- name: "Trockner Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_trockner_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float)|round(2, default=0))}}"
- name: "Waschmaschine Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_waschmaschine_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
- name: "Herd Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_herd_l1_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float) + states('sensor.st_herd_l2_strommessung_2')|float * (230 if states('sensor.on_grid_l2_voltage') == 'unavailable' else states('sensor.on_grid_l2_voltage')|float) + states('sensor.st_herd_l3_strommessung_2')|float * (230 if states('sensor.on_grid_l3_voltage') == 'unavailable' else states('sensor.on_grid_l3_voltage')|float))|round(2, default=0)}}"
- name: "Backofen Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_backofen_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
- name: "Gefrierschrank Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_hwr_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
- name: "Kühlschrank Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_kulschrank_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
- name: "Klimaanlage Leistung"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: "{{(states('sensor.st_klimaanlage_strommessung')|float * (230 if states('sensor.on_grid_l1_voltage') == 'unavailable' else states('sensor.on_grid_l1_voltage')|float))|round(2, default=0)}}"
## openems ##
- name: "Batterie Ladeleistung"
unique_id: battery_charge_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.essdischargepower')|float) < -55) %}
{{(states('sensor.essdischargepower')|float) * -1}}
{% else %}
0
{% endif %}
- name: "Batterie Entladeleistung"
unique_id: battery_discharge_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.essdischargepower')|float) > 0 ) %}
{{(states('sensor.essdischargepower'))}}
{% else %}
0
{% endif %}
- name: "Netzbezug"
unique_id: grid_import_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.gridactivepower')|float) > 0) %}
{{(states('sensor.gridactivepower'))}}
{% else %}
0
{% endif %}
- name: "Netzeinspeisung"
unique_id: grid_export_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.gridactivepower')|float) < 0 ) %}
{{(states('sensor.gridactivepower')|float) * -1}}
{% else %}
0
{% endif %}
- name: "grid_to_battery_power"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.gridactivepower')|float) > states('sensor.consumptionactivepower')|float ) %}
{{ (states('sensor.gridactivepower')|float - states('sensor.productionactivepower')|float - states('sensor.consumptionactivepower')|float )| round(2, default=0)}}
{% else %}
0
{% endif %}
- name: "ProductionDcActiveEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.productiondcactiveenergy')|float / 1000 }}"
- name: "ConsumptionActiveEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.consumptionactiveenergy')|float / 1000 }}"
- name: "GridBuyActiveEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.gridbuyactiveenergy')|float / 1000 }}"
- name: "GridSellActiveEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.gridsellactiveenergy')|float / 1000 }}"
- name: "EssDcChargeEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.essdcchargeenergy')|float / 1000 }}"
- name: "EssDcDischargeEnergyKwh"
unit_of_measurement: "kWh"
state_class: total_increasing
device_class: energy
state: "{{ states('sensor.essdcdischargeenergy')|float / 1000 }}"
## goodwe ##
- name: "GW Batterie Ladeleistung"
unique_id: gw_battery_charge_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.battery_power')|float) < 0) %}
{{(states('sensor.battery_power')|float) * -1}}
{% else %}
0
{% endif %}
- name: "GW Batterie Entladeleistung"
unique_id: gw_battery_discharge_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.battery_power')|float) > 0 ) %}
{{(states('sensor.battery_power'))}}
{% else %}
0
{% endif %}
- name: "GW Netzbezug"
unique_id: gw_grid_import_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.active_power')|float) < 0) %}
{{(states('sensor.active_power')|float) * -1}}
{% else %}
0
{% endif %}
- name: "GW Netzeinspeisung"
unique_id: gw_grid_export_power
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.active_power')|float) > 0 ) %}
{{(states('sensor.active_power')|float)}}
{% else %}
0
{% endif %}
- name: "GW grid_to_battery_power"
unit_of_measurement: "W"
state_class: measurement
device_class: power
state: >
{% if ((states('sensor.active_power')|float) > states('sensor.house_consumption')|float ) %}
{{ (states('sensor.active_power')|float - states('sensor.pv_power')|float - states('sensor.house_consumption')|float )| round(2, default=0)}}
{% else %}
0
{% endif %}
# - name: "GW ProductionDcActiveEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.productiondcactiveenergy')|float / 1000 }}"
# - name: "GW ConsumptionActiveEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.consumptionactiveenergy')|float / 1000 }}"
# - name: "GW GridBuyActiveEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.gridbuyactiveenergy')|float / 1000 }}"
# - name: "GW GridSellActiveEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.gridsellactiveenergy')|float / 1000 }}"
# - name: "GW EssDcChargeEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.essdcchargeenergy')|float / 1000 }}"
# - name: "GW EssDcDischargeEnergyKwh"
# unit_of_measurement: "kWh"
# state_class: total_increasing
# device_class: energy
# state: "{{ states('sensor.essdcdischargeenergy')|float / 1000 }}"
### mfm ###
- name: "MFM Frequenz Hz"
unit_of_measurement: "Hz"
device_class: frequency
state_class: measurement
state: "{{ states('sensor.mfm_frequenz')|float / 1000 }}"
### count burning lights ###
- name: "count_lights_on"
unit_of_measurement: "an"
state_class: measurement
state: "{{ states.light | selectattr('state', 'eq', 'on') | list | count }}"
### count open windows ###
- name: "count_windows_open"
unit_of_measurement: "offen"
state_class: measurement
state: "{{ expand('group.window_sensors') | selectattr('state', 'eq', 'on') | list | count }}"
### Garagentor ###
- name: "garagentor_position_invertiert"
unit_of_measurement: "%"
state_class: measurement
state: "{{ 100 - (state_attr('cover.garagentor', 'current_position') | int) }}"
### EPEX/Flex Spotpreise ###
- name: epex_spot_price_ct_per_kWh
unit_of_measurement: "ct/kWh"
availability: '{{ states("sensor.epex_spot_de_price") != "unavailable" }}'
state: '{{ states("sensor.epex_spot_de_price") | float / 10 }}'
- name: hastrom_flex_price_euro_per_MWh
unit_of_measurement: "EUR/MWh"
availability: '{{ states("sensor.hastrom_flex") != "unavailable" }}'
state: '{{ states("sensor.hastrom_flex") | float * 10 }}'
### Roborock ###
- name: "rocky_vacuum_status"
state: '{{ state_attr("vacuum.rocky", "status") }}'
### haStrom Flex Extended ###
- name: "haStrom flex Extended"
unique_id: hastrom_flex_ext
unit_of_measurement: "ct/kWh"
device_class: monetary
icon: mdi:cash
state: "{{ states('sensor.hastrom_flex_ext') | float(0) }}"
attributes:
prices_today: "{{ state_attr('sensor.hastrom_flex_ext', 'prices_today') }}"
datetime_today: "{{ state_attr('sensor.hastrom_flex_ext', 'datetime_today') }}"
prices_tomorrow: "{{ state_attr('sensor.hastrom_flex_ext', 'prices_tomorrow') }}"
datetime_tomorrow: "{{ state_attr('sensor.hastrom_flex_ext', 'datetime_tomorrow') }}"
tomorrow_available: "{{ state_attr('sensor.hastrom_flex_ext', 'tomorrow_available') }}"
- name: "haStrom FLEX PRO Extended"
unique_id: hastrom_flex_pro_ext
unit_of_measurement: "ct/kWh"
device_class: monetary
icon: mdi:cash-multiple
state: "{{ states('sensor.hastrom_flex_pro_ext') | float(0) }}"
attributes:
prices_today: "{{ state_attr('sensor.hastrom_flex_pro_ext', 'prices_today') }}"
datetime_today: "{{ state_attr('sensor.hastrom_flex_pro_ext', 'datetime_today') }}"
prices_tomorrow: "{{ state_attr('sensor.hastrom_flex_pro_ext', 'prices_tomorrow') }}"
datetime_tomorrow: "{{ state_attr('sensor.hastrom_flex_pro_ext', 'datetime_tomorrow') }}"
tomorrow_available: "{{ state_attr('sensor.hastrom_flex_pro_ext', 'tomorrow_available') }}"
### Riemann Sum ###
sensor:
- platform: integration
source: sensor.batterie_ladeleistung
name: Battery Charge Energy
unit_prefix: k
round: 2
method: left
- platform: integration
source: sensor.batterie_entladeleistung
name: Battery Discharge Energy
unit_prefix: k
round: 2
method: left