sphings-dev.de

Bad: Duschen erkennen, Luftentfeuchter steuern, ans Lüften erinnern

Im Bad im Erdgeschoss steht ein Luftentfeuchter, und das Fenster lässt sich zum Lüften öffnen. Beides soll sich nicht in die Quere kommen: Ist draußen die Luft trockener, ist Lüften sinnvoller als der Kompressor. Und nach dem Duschen soll niemand genervt werden, solange das Fenster ohnehin offen ist. Daraus sind vier Automationen geworden, die über ein paar Hilfsentitäten zusammenarbeiten.

Was du brauchst

  • Einen Feuchtesensor im Bad (bei mir sensor.bad_eg_luftfeuchte) und einen Fensterkontakt oder eine Gruppe davon
  • Einen Luftentfeuchter mit Integration in Home Assistant als humidifier- und fan-Entität, dazu einen Tank-Sensor als binary_sensor
  • Einen Außenfeuchtesensor und die Integration thermal_comfort für absolute Feuchte, aus der die Sensoren für Lüftungsgewinn, -dauer und -ziel abgeleitet sind (hier nicht gezeigt)
  • Einen Sensor sensor.bad_eg_feuchte_minimum_30_min (Statistik-Minimum über 30 Minuten), daraus sensor.bad_eg_feuchtesprung_30_min als Differenz zur aktuellen Feuchte
  • Einen Threshold-Helfer binary_sensor.bad_eg_duschen_erkannt auf dem Feuchteanstieg (bei mir oberer Schwellwert 0,8 mit Hysterese 0,2)
  • Helfer: mehrere input_number für Schwellen und Zeiten, input_boolean für Automatik aus, Nachtruhe aktiv und Lüften-Vorrang, ein input_select für das Nachtruhe-Verhalten, ein schedule für die Nachtruhe, ein timer mit restore und input_datetime für die Lüftungsfrist

So funktioniert es

Der Duscherkenner über das Fenster ist ein zweiter, unabhängiger Weg neben dem Threshold-Helfer. Er setzt nur den Merker bad_eg_duschen_erkannt_fenster und steuert nichts. Beide Reihenfolgen werden erkannt: erst geduscht und dann gelüftet, oder Fenster schon offen und dann geduscht. Die Bedingung ist immer dieselbe: Fenster offen, Feuchte über der Mindestfeuchte (bei mir 55 %) und ein Feuchtesprung der letzten 30 Minuten von mehr als 5 Prozentpunkten. Der Merker bleibt 30 Minuten stehen, in dieser Zeit sperrt mode: single jede Neuauslösung. Die Haltezeit ist so lang, weil derselbe Duschgang sonst doppelt zählte: Fenster zu und nach sechs Minuten wieder auf, oder der Sprungsensor schwankte beim Abklingen um die Schwelle. Folge: Eine zweite echte Dusche innerhalb von etwa 30 Minuten zählt diese Variante nicht mehr.

Der Luftentfeuchter läuft im Dauermodus und wird über die Raumfeuchte geschaltet: an ab 67 %, aus unter 58 %, jeweils nach einer Verzögerung von 5 Minuten. Tank voll und ein ausgefallener Feuchtesensor schalten immer ab, auch bei ausgeschalteter Automatik. Öffnet jemand das Fenster, geht das Gerät nach einer einstellbaren Verzögerung (Vorgabe 30 Sekunden) aus. In der Nachtruhe gibt es drei Verhaltensvarianten, davon schaltet „Notbetrieb ab Schwelle“ das Gerät zu Beginn ab und lässt es nur ab einer höheren Notfall-Schwelle wieder laufen.

Dazu kommt „Lüften geht vor dem Kompressor“: Würde Lüften mindestens fünf Prozentpunkte relative Feuchte bringen, geht zuerst eine Meldung aufs Handy, die Fensterdauer und erwartete Feuchte nennt. Erst nach der Lüften-Frist von 45 Minuten läuft der Kompressor an, und nur, wenn bis dahin niemand das Fenster geöffnet hat. Nachts entfällt die Frage, dort wird direkt entfeuchtet. Der Vorrang lässt sich über einen Schalter abschalten. Fällt der Außensensor aus, ist der Gewinn unbekannt, die Bedingung wird falsch, und das Gerät läuft sofort.

Weil der Luftentfeuchter in einer restart-Automation steckt, hat die maximale Laufzeit eine eigene Automation mit Timer. Ein Auslöser „Gerät geht an“ würde in der Steuerung den Einschalt-Zweig abbrechen, bevor Modus und Lüfter gesetzt sind. Der Timer hat restore und übersteht deshalb einen Neustart. Er startet nur bei off auf on, damit ein Wechsel aus unavailable die Zählung nicht neu beginnt. timer.finished feuert nicht, wenn der Timer während eines Stillstands von Home Assistant abläuft. Deshalb schaltet ein Zweig „Laufzeit unbekannt“ ab, wenn das Gerät nach dem Start oder nach unavailable läuft, aber kein Timer aktiv ist.

Die vierte Automation erinnert nach dem Duschen ans Lüften. Endet der Duschgang, startet eine Frist von 30 Minuten, falls das Fenster noch zu ist. Steht es schon offen, wird stattdessen eine Sperre gesetzt, die Feuchtemeldungen unterdrückt. Ein Fenster zählt erst nach fünf Minuten Offenzeit als gelüftet; kurz aufreißen quittiert die Erinnerung nicht. Läuft die Frist bei offenem Fenster ab, wird sie um diese fünf Minuten verschoben. Fällt sie in die Nachtruhe, wandert sie auf eine Minute nach Nachtruhe-Ende, verworfen wird sie nicht.

Die Automation

Im Beispiel gehen die Meldungen an zwei Handys. Der Zweig „Einschalten nach erneuter Feuchte-Verzögerung“ wiederholt im Original die Bedingungen und den Lüften-Vorrang des Zweigs „Zu feucht“ und ist hier als Kommentar abgekürzt.

alias: "Bad EG Duschen erkennen über Fenster"
description: >-
  Zweiter, unabhängiger Duscherkenner. Bedingung: Fenster offen, Feuchte über
  der Mindestfeuchte, Sprung der letzten 30 Minuten groß genug.
  Setzt nur einen Merker, steuert nichts.
triggers:
  - trigger: state
    entity_id: binary_sensor.gruppe_fenster_bad_eg
    to: "on"
    id: fenster_auf        # erst geduscht, dann Fenster auf
  - trigger: numeric_state
    entity_id: sensor.bad_eg_feuchtesprung_30_min
    above: input_number.bad_eg_duschen_fenster_anstieg
    id: sprung             # Fenster war schon auf
conditions:
  - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "on"}
  - condition: numeric_state
    entity_id: sensor.bad_eg_feuchte
    above: input_number.bad_eg_duschen_fenster_mindestfeuchte
  - condition: numeric_state
    entity_id: sensor.bad_eg_feuchtesprung_30_min
    above: input_number.bad_eg_duschen_fenster_anstieg
actions:
  - action: input_boolean.turn_on
    target: {entity_id: input_boolean.bad_eg_duschen_erkannt_fenster}
  - delay: {minutes: 30}   # mode single sperrt in dieser Zeit jede Neuauslösung
  - action: input_boolean.turn_off
    target: {entity_id: input_boolean.bad_eg_duschen_erkannt_fenster}
mode: single
max_exceeded: silent
alias: "Bad EG Luftentfeuchter Steuerung"
mode: restart
triggers:
  - trigger: numeric_state
    entity_id: sensor.bad_eg_luftfeuchte
    above: input_number.luftentfeuchter_einschaltschwelle
    for: {minutes: "{{ states('input_number.luftentfeuchter_verzoegerung_feuchte') | int(5) }}"}
    id: zu_feucht
  - trigger: numeric_state
    entity_id: sensor.bad_eg_luftfeuchte
    below: input_number.luftentfeuchter_ausschaltschwelle
    for: {minutes: "{{ states('input_number.luftentfeuchter_verzoegerung_feuchte') | int(5) }}"}
    id: trocken_genug
  - trigger: numeric_state
    entity_id: sensor.bad_eg_luftfeuchte
    above: input_number.luftentfeuchter_notfall_ein
    for: {minutes: "{{ states('input_number.luftentfeuchter_verzoegerung_feuchte') | int(5) }}"}
    id: notfall_ein
  - trigger: numeric_state
    entity_id: sensor.bad_eg_luftfeuchte
    below: input_number.luftentfeuchter_notfall_aus
    for: {minutes: "{{ states('input_number.luftentfeuchter_verzoegerung_feuchte') | int(5) }}"}
    id: notfall_aus
  - trigger: state
    entity_id: binary_sensor.gruppe_fenster_bad_eg
    to: "on"
    for: {seconds: "{{ states('input_number.luftentfeuchter_verzoegerung_fenster') | int(30) }}"}
    id: fenster_auf
  - {trigger: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, to: "off", id: neu_bewerten}
  - {trigger: state, entity_id: schedule.luftentfeuchter_nachtruhe, to: "off", id: neu_bewerten}
  - {trigger: state, entity_id: schedule.luftentfeuchter_nachtruhe, to: "on",  id: nachtruhe_start}
  - {trigger: state, entity_id: binary_sensor.luftentfeuchter_tank, to: "on", id: tank_voll}
  - {trigger: state, entity_id: binary_sensor.luftentfeuchter_tank, from: "on", to: "off", id: neu_bewerten}
  - trigger: state
    entity_id: sensor.bad_eg_luftfeuchte
    to: [unavailable, unknown]
    for: {minutes: "{{ states('input_number.luftentfeuchter_sensorausfall_timeout') | int(30) }}"}
    id: sensor_weg
  - {trigger: homeassistant, event: start, id: neu_bewerten}
  - trigger: state
    entity_id: sensor.bad_eg_luftfeuchte
    from: [unavailable, unknown]
    not_to: [unavailable, unknown]
    id: neu_bewerten
actions:
  - choose:
      - alias: Tank voll
        conditions: [{condition: trigger, id: tank_voll}]
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
          - action: notify.mobile_app_handy
            data: {title: Luftentfeuchter Bad EG, message: "Wassertank ist voll. Das Gerät wurde abgeschaltet."}
      - alias: Feuchtesensor ausgefallen
        conditions: [{condition: trigger, id: sensor_weg}]
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
          - action: notify.mobile_app_handy
            data: {title: Luftentfeuchter Bad EG, message: "Der Feuchtesensor meldet sich nicht mehr. Das Gerät wurde vorsorglich abgeschaltet."}
      - alias: Fenster offen
        conditions:
          - {condition: trigger, id: fenster_auf}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
      - alias: Nachtruhe beginnt
        conditions:
          - {condition: trigger, id: nachtruhe_start}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_nachtruhe_aktiv, state: "on"}
          - {condition: state, entity_id: input_select.luftentfeuchter_nachtruhe_verhalten, state: ["Auch ausschalten", "Notbetrieb ab Schwelle"]}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
      - alias: Notbetrieb ein
        conditions:
          - {condition: trigger, id: notfall_ein}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_nachtruhe_aktiv, state: "on"}
          - {condition: state, entity_id: schedule.luftentfeuchter_nachtruhe, state: "on"}
          - {condition: state, entity_id: input_select.luftentfeuchter_nachtruhe_verhalten, state: "Notbetrieb ab Schwelle"}
          - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "off"}
          - {condition: state, entity_id: binary_sensor.luftentfeuchter_tank, state: "off"}
        sequence:
          - {action: humidifier.turn_on, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
          - {action: humidifier.set_mode, target: {entity_id: humidifier.bad_eg_luftentfeuchter}, data: {mode: continuous}}
          - {action: fan.set_percentage, target: {entity_id: fan.bad_eg_luftentfeuchter}, data: {percentage: 100}}
      - alias: Notbetrieb aus
        conditions:
          - {condition: trigger, id: notfall_aus}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_nachtruhe_aktiv, state: "on"}
          - {condition: state, entity_id: schedule.luftentfeuchter_nachtruhe, state: "on"}
          - {condition: state, entity_id: input_select.luftentfeuchter_nachtruhe_verhalten, state: "Notbetrieb ab Schwelle"}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
      - alias: Zielfeuchte erreicht
        conditions:
          - {condition: trigger, id: trocken_genug}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
      - alias: Zu feucht
        conditions:
          - {condition: trigger, id: zu_feucht}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "off"}
          - {condition: state, entity_id: binary_sensor.luftentfeuchter_tank, state: "off"}
          - condition: or
            conditions:
              - {condition: state, entity_id: input_boolean.luftentfeuchter_nachtruhe_aktiv, state: "off"}
              - {condition: state, entity_id: schedule.luftentfeuchter_nachtruhe, state: "off"}
        sequence:
          - alias: Lüften geht vor dem Kompressor
            if:
              - {condition: state, entity_id: input_boolean.luftentfeuchter_lueften_vorrang, state: "on"}
              - condition: numeric_state
                entity_id: sensor.bad_eg_lueften_gewinn
                above: input_number.luftentfeuchter_lueften_mindestgewinn
              - {condition: state, entity_id: binary_sensor.raumklima_nachtruhe, state: "off"}
              - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "off"}
              - condition: template
                value_template: "{{ (state_attr('input_datetime.raumklima_bad_eg_dusch_frist', 'timestamp') | float(0)) <= now().timestamp() }}"
            then:
              - repeat:
                  for_each: [notify.mobile_app_handy_1, notify.mobile_app_handy_2]
                  sequence:
                    - action: "{{ repeat.item }}"
                      continue_on_error: true
                      data:
                        title: Bad EG lüften
                        message: >-
                          Bad EG ist bei {{ states('sensor.bad_eg_luftfeuchte') }} %.
                          Fenster etwa {{ states('sensor.bad_eg_lueftungsdauer_empfohlen') }} Minuten weit auf,
                          das bringt dich auf rund {{ states('sensor.bad_eg_lueftungsziel') }} %.
              - delay: {minutes: "{{ states('input_number.luftentfeuchter_lueften_frist') | int(45) }}"}
              - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "off"}
              - condition: numeric_state
                entity_id: sensor.bad_eg_luftfeuchte
                above: input_number.luftentfeuchter_einschaltschwelle
          - {action: humidifier.turn_on, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
          - {action: humidifier.set_mode, target: {entity_id: humidifier.bad_eg_luftentfeuchter}, data: {mode: continuous}}
          - {action: fan.set_percentage, target: {entity_id: fan.bad_eg_luftentfeuchter}, data: {percentage: 100}}
      - alias: Neu bewerten (Fenster zu, Nachtruhe vorbei, HA-Start, Sensor zurück, Tank leer)
        conditions: [{condition: trigger, id: neu_bewerten}]
        sequence:
          - choose:
              - alias: Tank voll – schaltet immer ab
                conditions:
                  - {condition: state, entity_id: binary_sensor.luftentfeuchter_tank, state: "on"}
                sequence:
                  - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
              - alias: Ausschalten, wenn die Automatik zuständig ist
                conditions:
                  - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
                  - condition: or
                    conditions:
                      - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "on"}
                      - condition: numeric_state
                        entity_id: sensor.bad_eg_luftfeuchte
                        below: input_number.luftentfeuchter_ausschaltschwelle
                      - condition: and
                        conditions:
                          - {condition: state, entity_id: input_boolean.luftentfeuchter_nachtruhe_aktiv, state: "on"}
                          - {condition: state, entity_id: schedule.luftentfeuchter_nachtruhe, state: "on"}
                          - {condition: state, entity_id: input_select.luftentfeuchter_nachtruhe_verhalten, state: ["Auch ausschalten", "Notbetrieb ab Schwelle"]}
                sequence:
                  - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
              - alias: Einschalten nach erneuter Feuchte-Verzögerung
                conditions:
                  - condition: numeric_state
                    entity_id: sensor.bad_eg_luftfeuchte
                    above: input_number.luftentfeuchter_einschaltschwelle
                  - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
                sequence:
                  - delay: {minutes: "{{ states('input_number.luftentfeuchter_verzoegerung_feuchte') | int(5) }}"}
                  # danach dieselben Bedingungen wie im Zweig "Zu feucht" erneut prüfen
                  # und dieselbe Lüften-Vorrang-Abfrage plus Einschalten wie dort ausführen
alias: "Bad EG Luftentfeuchter Laufzeit"
description: >-
  Maximale Laufzeit am Stück über einen Timer mit restore. Die Dauer kommt aus
  input_number.luftentfeuchter_max_laufzeit (Minuten) und wird beim Einschalten übernommen.
triggers:
  - {trigger: state, entity_id: humidifier.bad_eg_luftentfeuchter, from: "off", to: "on", id: eingeschaltet}
  - {trigger: state, entity_id: humidifier.bad_eg_luftentfeuchter, from: "on", to: "off", id: ausgeschaltet}
  - trigger: event
    event_type: timer.finished
    event_data: {entity_id: timer.luftentfeuchter_max_laufzeit}
    id: abgelaufen
  - {trigger: homeassistant, event: start, id: pruefen}
  - trigger: state
    entity_id: humidifier.bad_eg_luftentfeuchter
    from: [unavailable, unknown]
    to: "on"
    id: pruefen
actions:
  - choose:
      - alias: Eingeschaltet – Zählung beginnt
        conditions: [{condition: trigger, id: eingeschaltet}]
        sequence:
          - action: timer.start
            target: {entity_id: timer.luftentfeuchter_max_laufzeit}
            data:
              duration: "{{ ((states('input_number.luftentfeuchter_max_laufzeit') | float(180)) * 60) | int | timestamp_custom('%H:%M:%S', false) }}"
      - alias: Ausgeschaltet – Zählung verwerfen
        conditions: [{condition: trigger, id: ausgeschaltet}]
        sequence:
          - {action: timer.cancel, target: {entity_id: timer.luftentfeuchter_max_laufzeit}}
      - alias: Maximale Laufzeit erreicht
        conditions:
          - {condition: trigger, id: abgelaufen}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: humidifier.bad_eg_luftentfeuchter, state: "on"}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
      - alias: Laufzeit unbekannt – Gerät läuft ohne Timer
        conditions:
          - {condition: trigger, id: pruefen}
          - {condition: state, entity_id: input_boolean.luftentfeuchter_automatik_aus, state: "off"}
          - {condition: state, entity_id: humidifier.bad_eg_luftentfeuchter, state: "on"}
          - {condition: state, entity_id: timer.luftentfeuchter_max_laufzeit, state: idle}
        sequence:
          - {action: humidifier.turn_off, target: {entity_id: humidifier.bad_eg_luftentfeuchter}}
mode: queued
alias: "Raumklima: Bad EG nach dem Duschen lüften"
triggers:
  - {trigger: state, id: dusch_ende, entity_id: binary_sensor.bad_eg_duschen_erkannt, from: "on", to: "off"}
  - {trigger: state, id: fenster_auf, entity_id: binary_sensor.gruppe_fenster_bad_eg, to: "on"}
  - {trigger: state, id: fenster_zu, entity_id: binary_sensor.gruppe_fenster_bad_eg, to: "off"}
  - {trigger: time, id: frist, at: input_datetime.raumklima_bad_eg_dusch_frist}
variables:
  aus_wert: "1970-01-01 00:00:00"
  frist_offen: "{{ (state_attr('input_datetime.raumklima_bad_eg_dusch_frist', 'timestamp') | float(0)) > now().timestamp() }}"
actions:
  - choose:
      - alias: Duschgang zu Ende
        conditions: [{condition: trigger, id: dusch_ende}]
        sequence:
          - if:
              - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "on"}
            then:
              - {action: input_boolean.turn_on, target: {entity_id: input_boolean.raumklima_bad_eg_dusch_sperre}}
              - action: input_datetime.set_datetime
                target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                data: {datetime: "{{ aus_wert }}"}
            else:
              - alias: Lüftungsfrist starten
                action: input_datetime.set_datetime
                target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                data:
                  datetime: "{{ (now() + timedelta(minutes = states('input_number.raumklima_dusch_lueftungsfrist') | float(30) | int)).strftime('%Y-%m-%d %H:%M:%S') }}"
      - alias: Fenster geht auf
        conditions:
          - {condition: trigger, id: fenster_auf}
          - {condition: template, value_template: "{{ frist_offen }}"}
        sequence:
          - {action: input_boolean.turn_on, target: {entity_id: input_boolean.raumklima_bad_eg_dusch_sperre}}
      - alias: Fenster geht zu
        conditions: [{condition: trigger, id: fenster_zu}]
        sequence:
          - {action: input_boolean.turn_off, target: {entity_id: input_boolean.raumklima_bad_eg_dusch_sperre}}
          - if:
              - alias: War das Fenster lange genug offen?
                condition: template
                value_template: "{{ trigger.from_state is not none and (now() - trigger.from_state.last_changed).total_seconds() >= (states('input_number.raumklima_dusch_mindestlueftung') | float(5)) * 60 }}"
            then:
              - alias: Gelüftet – Erinnerung entfällt
                action: input_datetime.set_datetime
                target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                data: {datetime: "{{ aus_wert }}"}
      - alias: Lüftungsfrist abgelaufen
        conditions: [{condition: trigger, id: frist}]
        sequence:
          - choose:
              - alias: Fenster steht gerade offen
                conditions:
                  - {condition: state, entity_id: binary_sensor.gruppe_fenster_bad_eg, state: "on"}
                sequence:
                  - action: input_datetime.set_datetime
                    target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                    data:
                      datetime: "{{ (now() + timedelta(minutes = states('input_number.raumklima_dusch_mindestlueftung') | float(5) | int)).strftime('%Y-%m-%d %H:%M:%S') }}"
              - alias: Nachtruhe – Erinnerung auf den Morgen verschieben
                conditions:
                  - {condition: state, entity_id: binary_sensor.raumklima_nachtruhe, state: "on"}
                sequence:
                  - action: input_datetime.set_datetime
                    target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                    data:
                      datetime: >-
                        {% set sek = (state_attr('input_datetime.raumklima_nachtruhe_ende_frei', 'timestamp') if is_state('binary_sensor.arbeitstag', 'off') else state_attr('input_datetime.raumklima_nachtruhe_ende_werktag', 'timestamp')) | int(21600) + 60 %}
                        {% set ziel = today_at('00:00') + timedelta(seconds = sek) %}
                        {{ (ziel if ziel > now() else ziel + timedelta(days=1)).strftime('%Y-%m-%d %H:%M:%S') }}
            default:
              - action: input_datetime.set_datetime
                target: {entity_id: input_datetime.raumklima_bad_eg_dusch_frist}
                data: {datetime: "{{ aus_wert }}"}
              - action: notify.mobile_app_handy
                continue_on_error: true
                data:
                  title: Bad EG lüften
                  message: "Nach dem Duschen wurde nicht gelüftet. Bad EG ist bei {{ states('sensor.bad_eg_luftfeuchte') }} %."
mode: queued
max: 10
max_exceeded: silent

Anpassen

  • Schwellen, Verzögerungen und Maximallaufzeit (bei mir 180 Minuten) sind Helfer und lassen sich ohne Eingriff in die Automation ändern.
  • Ohne Außensensor und thermal_comfort lässt du den Zweig „Lüften geht vor dem Kompressor“ weg. Dann sinkt die Menge der nötigen Helfer erheblich.
  • Das Duschen musst du nicht über zwei Wege erkennen. Eine der beiden Varianten reicht, wenn sie bei dir zuverlässig arbeitet.

Stolpersteine

Es gibt bewusst keinen time_pattern-Recheck in der Steuerung: Im Modus restart würde er regelmäßig die 5-Minuten-Verzögerung im Einschalt-Zweig abbrechen. Stattdessen starten Neubewertungen bei Fensterschluss, Ende der Nachtruhe, leerem Tank, Home-Assistant-Start und Rückkehr des Sensors. Der Zweig „Neu bewerten“ kann dabei auch ausschalten. Vorher lief das Gerät nach einem Neustart unbegrenzt weiter, wenn die Feuchte währenddessen unter die Aus-Schwelle gefallen war und die Flanke verloren ging. Sensorausfall steht bewusst nicht im Ausschalt-Zweig, sonst würde beim Neustart abgeschaltet, solange der Sensor noch nicht bereit ist.

Tags

Unterstützen

Diese Tools entstehen in meiner Freizeit und bleiben kostenlos, offen und cloud-frei. Wenn dir eins davon einen Nachmittag gespart hat, freue ich mich über einen Kaffee oder ein Stück Pizza.

Kaffee oder Pizza

Weitere Beiträge