[[Uebersicht|← Zurück zur Homepage]] # HA-Automation: Akku Lade-/Entladesperre bei Tibber-Preisniveau **Version:** 1.0 **Datum:** 30.06.2026, 13:43 UTC **Status:** Codierungsanweisung erstellt, noch nicht implementiert ## Ziel Automation für die drei Marstek Venus Akkus (MTV01, MTV02, MTV03), die abhängig vom Tibber-Preisniveau (`sensor.daheim_aktuelles_preisniveau`) das Laden erzwingt und das Entladen sperrt (bei günstigem Strom) bzw. dies wieder zurücknimmt (bei normalem/teurem Strom). ## Logik **Trigger:** State-Trigger auf `sensor.daheim_aktuelles_preisniveau` **Fall A — Zustand "günstig" oder "sehr günstig":** - `switch.mtv01/02/03_battery_allow_discharge` → `false` (falls nicht bereits false) - `switch.mtv01/02/03_battery_allow_charge` → `true` (falls nicht bereits true) **Fall B — sonstiger Zustand (normal/teuer):** - `switch.mtv01/02/03_battery_allow_discharge` → `true` (falls nicht bereits true) - `switch.mtv01/02/03_battery_allow_charge` → `false` (falls nicht bereits false) Jeder Switch wird nur geschaltet, wenn sein aktueller Zustand vom Zielzustand abweicht (keine unnötigen Schreibzugriffe). **Benachrichtigung:** Eine gesammelte `persistent_notification` pro Durchlauf, die alle tatsächlich geänderten Switches auflistet. Wurde kein Switch geändert, entfällt die Benachrichtigung. ## Codierungsanweisung für Claude Code ``` Erstelle eine Home Assistant Automation (YAML, automations.yaml-kompatibel) mit folgenden Anforderungen: Trigger: - platform: state entity_id: sensor.daheim_aktuelles_preisniveau Condition: keine (Verzweigung über choose/if-then in der Action) Action (Pseudocode): 1. Definiere Zielzustand je nach trigger.to_state.state: - state in ["günstig", "sehr günstig"]: target_discharge = "off" (false) target_charge = "on" (true) - sonst: target_discharge = "on" (true) target_charge = "off" (false) 2. Für jeden der 6 Switches: - switch.mtv01_battery_allow_discharge - switch.mtv02_battery_allow_discharge - switch.mtv03_battery_allow_discharge - switch.mtv01_battery_allow_charge - switch.mtv02_battery_allow_charge - switch.mtv03_battery_allow_charge Prüfe aktuellen Zustand gegen Zielzustand (discharge-Switches gegen target_discharge, charge-Switches gegen target_charge). Bei Abweichung: switch.turn_on/turn_off aufrufen und den Switch-Friendly-Name + neuen Zustand in einer Variablen/Liste sammeln (z.B. via repeat-Loop über eine input-Liste mit entity_id + target_state, um Code-Duplikation zu vermeiden). 3. Nach Durchlauf aller 6 Switches: Wenn die Sammel-Liste nicht leer ist, eine einzelne persistent_notification erstellen mit: - Titel: "Akku-Sperre Tibber-Preisniveau" - Inhalt: Aufzählung aller geänderten Switches mit altem → neuem Zustand, plus aktuellem Preisniveau-Zustand Ist die Liste leer, keine Notification erzeugen. Empfohlene Umsetzung: nutze eine Template-/Repeat-Struktur (z.B. repeat.for_each über eine Liste von Dicts {entity, target}) statt 6x identischen Code zu wiederholen, um Wartbarkeit zu erhöhen. Variablen (variables:) für target_discharge/target_charge am Anfang der Action setzen. Automation-ID/Alias: "Akku Lade-Sperre bei Tibber-Preisniveau" mode: single ``` ## Offene Punkte - Switch-Verhalten bei nicht erreichbarem Entity (unavailable/unknown): Entscheidung liegt bei Claude Code. - Reihenfolge Charge/Discharge beim Umschalten: Entscheidung liegt bei Claude Code. ## Fertiges YAML (v1.2) ```yaml alias: "Akku Lade-Sperre bei Tibber-Preisniveau" description: > Sperrt/erlaubt Laden und Entladen der Marstek Akkus MTV01-03 abhängig vom Tibber-Preisniveau (günstig/sehr günstig vs. normal/teuer). mode: single trigger: - platform: state entity_id: sensor.daheim_aktuelles_preisniveau condition: [] variables: guenstig: > {{ trigger.to_state.state in ['günstig', 'sehr günstig'] }} target_discharge: "{{ 'off' if guenstig else 'on' }}" target_charge: "{{ 'on' if guenstig else 'off' }}" switch_liste: > {{ [ {'entity': 'switch.mtv01_battery_allow_discharge', 'target': target_discharge}, {'entity': 'switch.mtv02_battery_allow_discharge', 'target': target_discharge}, {'entity': 'switch.mtv03_battery_allow_discharge', 'target': target_discharge}, {'entity': 'switch.mtv01_battery_allow_charge', 'target': target_charge}, {'entity': 'switch.mtv02_battery_allow_charge', 'target': target_charge}, {'entity': 'switch.mtv03_battery_allow_charge', 'target': target_charge} ] }} action: - variables: geaenderte: [] - repeat: for_each: "{{ switch_liste }}" sequence: - variables: entity: "{{ repeat.item.entity }}" target: "{{ repeat.item.target }}" aktuell: "{{ states(repeat.item.entity) }}" - if: - condition: template value_template: "{{ aktuell not in ['unavailable', 'unknown'] and aktuell != target }}" then: - service: "switch.turn_{{ target }}" target: entity_id: "{{ entity }}" - variables: geaenderte: > {{ geaenderte + [{ 'name': state_attr(entity, 'friendly_name') or entity, 'alt': aktuell, 'neu': target }] }} - if: - condition: template value_template: "{{ geaenderte | length > 0 }}" then: - service: persistent_notification.create data: title: "Akku-Sperre Tibber-Preisniveau" message: > Preisniveau: {{ trigger.to_state.state }} {% for s in geaenderte %} - {{ s.name }}: {{ s.alt }} → {{ s.neu }} {% endfor %} ``` **Entscheidung unavailable/unknown:** Switch wird übersprungen, nicht geschaltet. **Entscheidung Reihenfolge:** Discharge-Switches zuerst, dann Charge-Switches (Liste oben). ## Verlauf - v1.0 (30.06.2026, 13:43 UTC): Codierungsanweisung erstellt, Rückfragen zu Trigger, Benachrichtigungsform und Sammel-/Einzelnachricht geklärt. - v1.1 (30.06.2026, 13:48 UTC): Offene Punkte (unavailable-Verhalten, Reihenfolge Charge/Discharge) an Claude Code zur Entscheidung übergeben. - v1.2 (30.06.2026, 14:05 UTC): Fertiges YAML erstellt und in Note dokumentiert, offene Punkte entschieden (unavailable → überspringen, Reihenfolge → Discharge vor Charge). --- [[Hinweise/Impressum|Impressum]] | [[Hinweise/Datenschutzerklärung|Datenschutz]]