Zum Hauptinhalt springen

Aktivierung von Home Assistant Szenen verfolgen - Part 2

·1262 Wörter·6 min
Smart Home Guide Automatisierung Home Assistant Licht Sensor Szenen Trigger
Tobias Schulz
Autor
Tobias Schulz
고생 끝에 낙이 온다 · immer, weiter
Inhaltsverzeichnis

Im vorherigen Part habe ich die Lichtszenen und deren Aktivierung beschrieben. Diesmal möchte ich tiefer in das Konzept des Trigger-basierten Template Sensors eintauchen und zeigen, wie dieser verwendet werden kann, um komplexere Szenarien in Home Assistant zu handhaben.

Stand der Dinge
#

Rufen wir uns doch noch einmal eine verkürzte Version meines Sensors in Erinnerung:

- trigger:
  - platform: homeassistant
    event: start
  - platform: event
    event_type: call_service
    event_data:
      domain: scene
      service: turn_on
  action:
    - variables:
        history: >
          {{ ... }}          
  sensor:
    - name: scene_history_wohnzimmer
      unique_id: sensor_scene_history_wohnzimmer
      state: >
        {{ state_attr(history.wohnzimmer[0], "name") }}        
      attributes:
        current: "{{ history.wohnzimmer[0] }}"
        history: "{{ history.wohnzimmer[1:] }}"
    # ... weitere Räume einfügen

Bei jedem Start von Home Assistant sowie jeder Aktivierung einer Szene wird die Aktualisierung des Trigger-basierten Template Sensors ausgelöst. Zuerst werden die Actions abgearbeitet, die in meinem Fall die Variable history mit Daten für alle Räume füllt. Danach werden die Sensor-Konfigurationen nacheinander ausgeführt.

graph LR A[/Trigger/] --> B(Actions ausführen) --> C[Sensoren aktualisieren]

Während also der scene_history_wohnzimmer Sensor aktualisiert wird, steht die history Variable bereits mit allen Werten für das Wohnzimmer zur Verfügung. Diese Tatsache müssen wir im Kopf behalten, wenn wir solche Sensoren bauen. Das gilt natürlich auch für die Sensoren aller weiteren Räume, die wir an unseren Trigger anheften.

Und hier liegt ein kleines Detail versteckt: sobald die history Variable nach Auslösen des Triggers für alle Räume befüllt wird, kann sie nämlich die Sensordaten aller Räume aktualisieren - quasi in einem Durchlauf. Ja, so werden auch die Sensoren der Räume aktualisiert, in denen gerade keine Szene aktiviert wurde. Das werden wir aber später noch brauchen 😁.

Herausforderung
#

Wir haben es im ersten Part erfolgreich geschafft, dass der Name der zuletzt aktivierten Szene im Scene-History-Sensor gespeichert wird. Konkret stand der Sensor auf Essen und verhinderte somit, dass während dem Essen die Wohnzimmer-Beleuchtung gedimmt wird, wenn jemand den Fernseher einschaltet.

Doch was passiert nun, wenn das Licht zwischenzeitlich ausgeschaltet wird? Du ahnst es vermutlich schon: nichts. Die letzte Szene Essen wird solange beibehalten, bis eine andere Szene im Wohnzimmer aktiviert wird. Und hier endet die Geschichte auch schon. Dies wird in anderen Situationen dafür sorgen, dass Automatisierungen eine Szene vermuten und entsprechend reagieren, obwohl sie mittlerweile gar nicht mehr aktiv sein könnte.

Um dieses Problem zu lösen, erweitern wir nun unseren Scene-History-Sensor um weitere Trigger und Attribute.

Erweiterung des Sensors
#

Wir fügen einen weiteren Trigger, ein neues Attribut und ein Makro1 hinzu.

Trigger
#

Ich teile den Triggern nun auch Trigger-IDs zu, um innerhalb des Trigger-basierten Template Sensors prüfen zu können, durch welches Ereignis er eigentlich aktualisiert wird. Entitäten wie light.wohnzimmer_lights gibt es bei mir für jeden Raum, sie gruppieren sämtliche Lampen innerhalb eines Raumes. Das ermöglicht mir die extrem bequeme Abfrage des Beleuchtungsstatus, oder eben alle Lichter gleichzeitig auszuschalten.

- trigger:
  - platform: homeassistant
    event: start
  - platform: event
    event_type: call_service
    event_data:
      domain: scene
      service: turn_on
    id: scene_activated # das ist neu
  # und ein neuer Trigger
  - platform: state
    entity_id:
      - light.wohnzimmer_lights
    from: "on"
    to: "off"
    id: off_again
# ...

Attribut
#

Statten wir den Scene-History-Sensor im Wohnzimmer nun mit dem Attribut aus, welches in Zukunft die Information vorhält, ob das Licht nach dem Aktivieren einer Szene wieder ausgeschaltet wurde.

# ...
- name: scene_history_wohnzimmer
  unique_id: sensor_scene_history_wohnzimmer
  state: >
    {{ state_attr(history.wohnzimmer[0], "name") }}    
  attributes:
    current: "{{ history.wohnzimmer[0] }}"
    history: "{{ history.wohnzimmer[1:] }}"
    # das kommt dazu
    off_again: >
      {% from "scenes.jinja" import get_off_again %}
      {{ get_off_again("wohnzimmer", trigger) }}      

Ich habe mich für den Namen off_again entschieden. Das Template des Attributs importiert ein Makro und führt es dann aus. Damit ich das Template der Funktion get_off_again auch für andere Räume benutzen kann, ohne es immer wieder kopieren zu müssen, habe ich es in eben jenem Makro ausgelagert. Das ist übrigens der übliche Use-Case für Makros, falls du dich schon mal gefragt hast, wozu die eigentlich gut sein sollen 😁.

An das Makro übergebe ich den gewünschten Raum und das gesamte trigger Objekt, welches von Home Assistant zur Verfügung gestellt wird. In diesem Objekt enthalten ist auch die Information, welcher Trigger ausgelöst wurde.

An dieser Stelle machen wir uns die Tatsache zu Nutze, dass beim Auslösen eines Triggers immer State und Attribute des Trigger-basierten Template Sensors aktualisiert werden. Das musst du dir stets im Hinterkopf behalten, denn auch unser Makro ist darauf ausgelegt.

Makro
#

Um eigene Makros zu verwenden, erstelle im config-Ordner deiner Home Assistant Installation den Unterordner custom_templates. Hier legst du deine .jinja-Dateien ab. Ich habe mich für den Dateinamen scenes.jinja entschieden, einfach weil ich es vorteilhaft finde, Informationen thematisch zu strukturieren.

Die Datei hat folgenden Inhalt:

{% macro get_off_again(area, trigger) %}
    {# eine Szene wurde aktiviert #}
    {% if trigger.id == "scene_activated" %}
        {% set areas = trigger.event.data.service_data.entity_id
                | map("area_id")
                | list %}
        {% if area in areas %}
            {% set return = "no" %}
        {% endif %}
    {# Lampen wurden ausgeschaltet #}
    {% elif trigger.id == "off_again" %}
        {% set areas = [area_id(trigger.entity_id)] %}
        {% if area in areas %}
            {% set return = "yes" %}
        {% endif %}
    {% endif %}

    {# Nichts von beidem #}
    {% if return is not defined %}
        {% set return = state_attr("sensor.scene_history_" + area, "off_again") %}
    {% endif %}

    {{ return }}
{% endmacro %}

Erläuterungen
#

Das Makro wird mit zwei Parametern aufgerufen. Dies ist einerseits area, die in meinem Beispiel ja auf wohnzimmer gesetzt ist. Andererseits das trigger Objekt von Home Assistant.

Wird eine Szene aktiviert, soll überprüft werden, ob die ausgelöste Szene im wohnzimmer ist. Falls ja, wird off_again auf no gesetzt. Dieselbe Logik wende ich an, wenn Lampen ausgeschaltet werden. Es wird überprüft, ob es sich um den gewünschten Raum handelt und falls ja, off_again auf yes gesetzt. Du hast richtig gemerkt: wir haben einen Schalter im klassischen Sinne gebaut, der entweder an oder aus ist. Macht bis hierher Sinn, oder?

Für den Fall, dass weder die aktivierte Szene, noch die ausgeschaltete Lampe aus dem wohnzimmer sind, wird einfach der aktuell eingestellte Wert übernommen. Warum das notwendig ist? Ich habe dir weiter oben einen brennenden Tipp dazu gegeben 😎.

Im letzten Schritt wird der Wert der Variable return nun zurückgegeben und in der Folge als off_again Attribut festgelegt.

Abschlussarbeiten
#

Der Scene-History-Sensor kann nun nicht nur erfolgreich die zuletzt aktivierte Szene anzeigen, sondern stellt darüber hinaus auch ein Attribut bereit mit der Information, ob das Licht seit Aktivierung einer Szene wieder abgeschaltet wurde. Damit kann die in Part 1 aufgebaute Automatisierung nicht nur feststellen, ob die Szene Essen im Wohnzimmer zuletzt aktiviert wurde, sondern auch, ob das Licht seither wieder ausgeschaltet worden ist.

Sobald der Fernseher im Wohnzimmer eingeschaltet wird, überprüft die für das Dimmen verantwortliche Automatisierung in Zukunft nicht nur, ob der Scene-History-Sensor auf Essen steht, sondern auch, ob das Licht seither wieder abgeschaltet wurde.

  - condition: not
    conditions:
      - condition: state
        entity_id: sensor.scene_history_wohnzimmer
        state: Essen
      - condition: state
        entity_id: sensor.scene_history_wohnzimmer
        attribute: off_again
        state: "yes"

Jetzt wird die Automatisierung wirklich zuverlässig laufen und das Licht nur im vorgesehenen Moment dimmen 😁. Wenn du bessere Ideen zu einer möglichen Umsetzung hast, schreib mir gern. Mein Ziel war die Vermeidung der Erstellung von unzähligen Helfern.

Der Trigger-basierte Template Sensor ist von mir so designed, dass einfach weitere Räume hinzugefügt werden können, ohne den ganzen Code immer wieder schreiben zu müssen. Das war auch notwendig, da ich die Scene-History in sechs verschiedenen Räumen verwende.

Im nächsten Beitrag zu Home Assistant werde ich darüber berichten, wie ich mit Hilfe der Local calendar, To-do list und Roborock Integrations einen interaktiven Reinigungsplan erstellt habe.


Feature-Foto von Bilal Mansuri auf Unsplash


  1. Seit der Version 2023.4 unterstützt Home Assistant die Erstellung und Wiederverwendung eigener Makros, siehe hier↩︎

Verwandte Artikel

Aktivierung von Home Assistant Szenen verfolgen - Part 1
·1935 Wörter·10 min
Smart Home Guide Home Assistant Licht Sensor Szenen Template
Die Aktivierung von Szenen laufend mit einem Sensor verfolgen.
Paperless Guide: Customization
·815 Wörter·4 min
Paperless Automatisierung Guide Paperless Python Workflow
Das papierlose Büro mit Scripting monitoren und verbessern.
Eigener Strom mit Balkonkraftwerk
·906 Wörter·5 min
Smart Home Balkonkraftwerk Energie Home Assistant Strom
Selbst Strom erzeugen und dabei Geld sparen? Ein kleiner Einblick.