## 🎯 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>
300 lines
13 KiB
YAML
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
|