eval und eval_trigger

Attribut eval

Wenn ein Item einen neuen Wert zugewiesen bekommen soll (z.B. via KNX oder Logik), wird der neue Wert zunächst in value zwischengespeichert. Wenn ein Attribut eval existiert, so wird der Ausdruck hinter eval = … ausgeführt und das Ergebnis dieses Ausdrucks als neuer Wert ins Item übernommen. Sollten alter und neuer Wert des Items unterschiedlich sein oder ist das Attribut enforce_updates vorhanden und auf True gesetzt, dann werden abhängige Logiken getriggert.

Im folgenden Beispiel liefert ein Sensor die Temperatur in Fahrenheit. Das Item soll aber die Temperatur in °Celsius speichern.

Temperatur:
    # Formel (°F  -  32)  x  5/9 = °C
    type: num
    eval: (value - 32 ) * 5 / 9  # Aus 68°F werden somit 20°C
Die Auswertung des eval Ausdrucks wird gestartet, wenn:
  • dem Item ein neuer Wert zugewiesen wird (siehe Erläuterug im ersten Absatz)

  • sich der Wert des oder der Items aus dem eval_trigger ändert (siehe Erläuterug weiter unten)

  • ein timer verwendet wird und die angegebene Zeit abgelaufen ist

  • ein autotimer verwendet wird und die angegebene Zeit abgelaufen ist

  • ein crontab definiert ist und die zeitlichen Angaben zutreffen

Das Eval Attribut kann auch bis zu einem gewissen Grad Logiken beinhalten. Wichtig ist, dass bei der Angabe eines if auch ein else implementiert sein muss. Außerdem ist dem Item ein sh. voran zu setzen. Die () Klammern hinter dem Item sind nötig, um den Item-Wert abzufragen.

Temperatur:
    Trigger:
        # Wird wahr, wenn die Temperatur über 20 Grad wird und falsch, wenn nicht.
        type: bool
        eval: 1 if sh.Temperatur() > 20 else 0
        eval_trigger: Temperatur

Weiter ist es möglich, direkt die Werte der eval_trigger im eval entsprechend auszuwerten:

Keyword

Beschreibung

sum

Errechnet die Summe aller eval_trigger Items.

avg

Errechnet den Mittelwert aller Items auf die sich eval_trigger bezieht.

min

Errechnet den Minimalwert aller Items auf die sich eval_trigger bezieht.

max

Errechnet den Maximalwert aller Items auf die sich eval_trigger bezieht.

and

Setzt den Wert des Items auf True, wenn alle Items auf die sich eval_triggers bezieht den Wert True haben.

or

Setzt den Wert des Items auf True, wenn eines der Items auf die sich eval_triggers bezieht den Wert True haben.

Beispiel:

Raum:

    Temperatur:
        type: num
        name: average temperature
        eval: avg
        eval_trigger:
          - room_a.temp
          - room_b.temp

    Praesenz:
        type: bool
        name: movement in on the rooms
        eval: or
        eval_trigger:
          - room_a.presence
          - room_b.presence

Seit SmartHomeNG v1.3 wird das Python Modul math bereitgestellt und es können entsprechende Funktionen genutzt werden.

Beispiel:

oneitem:
  type: num
  eval: ceil(sh.otheritem() / 60.0)

Seit SmartHomeNG v1.3 können für eval auch relative Relative Item Referenzen genutzt werden. Dann müssen Bezüge auf andere Items nicht mehr absolut angegeben werden sondern können sich relative auf andere Items beziehen.

Tipp

Im Abschnitt Logiken ist auf der Seite Feiertage, Daten und Zeiten beschrieben, welche Feiertags- und Datums-Funktionen in Logiken benutzt werden können. Diese Funktionen können auch in eval Attributen genutzt werden können.

Tipp

Im Abschnitt Beispiele sind auf der Seite eval und eval_trigger Beispiele weitere ausführliche Beispiele zu finden.

Eval Syntax

Der Syntax eines eval Ausdrucks ist der Syntax einer Python conditional expression

Dieser Syntax wird bei den Item Attributen eval, on_change und on_update verwendet.

Zu beachten ist, dass der Syntax einer if-Bedingung in einer Python conditional Expression folgender ist:

eval: <expression-if-true> if <condition> else <expression-if-false>

Beispiel:

eval: value if value>0 else 0

Die Expression setzt den Item-Wert auf den bisherigen Wert, falls er >0 ist, sonst wird der Wert auf 0 gesetzt. Damit findet eine Zuweisung statt und on_change bzw. on_update Trigger werden ausgelöst.

Wenn das Beispiel folgendermaßen formuliert wird:

eval: 0 if value<0 else None

Hätte es auf den Item-Wert letztlich die selben Auswirkungen: Hier wird der Item-Wert auf 0 gesetzt, falls der Wert <0 ist, sonst (None) wird keine Aktion ausgeführt (damit bleibt der Wert unverändert erhalten). Damit werden on_change bzw. on_update Trigger nur ausgelöst, wenn der Wert vorher <0 war. Bei Erhalt des Wertes (None), werden keine Trigger ausgelöst.

Attribut eval_trigger

Das Attribut eval_trigger legt eine Abhängigkeit von anderen Items fest. Sobald sich diese im Wert ändern, wird eine Neuberechnung gestartet. Das obige Beispiel könnte so erweitert werden:

TemperaturFahrenheit:
    type: num
TemperaturCelsius:
    # Formel (°F  -  32)  x  5/9 = °C
    type: num
    eval: (sh.TemperaturFahrenheit() - 32 ) * 5 / 9  # Aus 68°F werden somit 20°C
    eval_trigger: TemperaturFahrenheit

Hier gibt es nun ein Attribut eval_trigger mit dem Item Namen TemperaturFahrenheit. Sobald sich dieses Item ändert, wird auch der Wert von TemperaturCelsius neu berechnet.

Im Attribut eval_trigger kann eine Liste mehrerer Items angegeben werden. Die Items müssen für das alte .conf Format jeweils durch ein ‘|’ voneinander getrennt werden. In der.yaml kann eine Liste angegeben werden (siehe oben). Der Ausdruck unter eval wird neu berechnet, wenn sich eines dieser Items verändert. Die Items können auch mit einem Stern generalisiert werden. Temperatur.* bedeutet, dass alle Kinderitems des Temperatur-Items zum Evaluieren des Items führen. Oder *.Trigger sorgt dafür, dass das Item durch alle Kind-Items mit dem Namen “Trigger” aktualisiert werden kann, also z.B. durch Temperatur.Trigger, Licht.OG.Trigger, etc.

Seit SmartHomeNG v1.3 können für eval_trigger auch Relative Item Referenzen

Relative Item Referenzen genutzt werden. Dann müssen Bezüge auf andere Items nicht mehr absolut angegeben werden sondern können sich relative auf andere Items beziehen.

Bemerkung

Ein häufiger Fehler bei der Nutzung von eval im Zusammenspiel mit eval_trigger ist, bei eval_trigger auch den vollen Python-Pfad zu einem SmartHomeNG Item zu verwenden, wie im eval Ausdruck.

Richtig ist es, bei eval_trigger nur der Item-Pfad zu nutzen (ohne führendes sh. und ohne folgende ()).

Korrekt:

  • eval: sh. my.value ()

  • eval_trigger: my.value | my.other.value

Falsch:

  • eval: sh.my.value

  • eval_trigger: sh. my.value | sh. my.other.value

Gemeinsame Verwendung von eval und on_… Item Attributen

Bei Verwendung des eval Attributes zusammen mit on_change oder on_update in der selben Item Definition ist zu beachten, dass value unterschiedliche Werte hat/haben kann.

Im Ausdruck des eval Attributes hat value den alten Wert des Items. Nach Abschluss dieser Berechnung, wird dem Item das Ergebnis zugewiesen. Anschließend werden die Ausdrücke für on_change und on_update berechnet. Zu diesem Zeitpunkt hat das Item (und damit value) bereits den neuen Wert.

Wenn in eval Ausdrücken in on_change oder on_update Attributen auf den alten Wert des Items zugegriffen werden soll, muss dazu die Item Funktion prev_value() genutzt werden. Auf den alten Wert des aktuellen Items kann ohne die Angabe der vollständigen Item Pfades durch den Ausdruck sh.self.prev_value() zugegriffen werden.

Achtung

Bei eval Ausdrücken (wie sie in den Item Attributen eval, on_update und on_change verwendet werden) ist zu beachten, dass bei Verwendung von if auch immer ein else Zweig angegeben werden muss!

Wenn man jedoch ein Item nur verändern möchte wenn die if Bedingung erfüllt ist und sonst unverändert lassen möchte, muss als else Zweig der Ausdruck else None angegeben werden. None bewirkt, dass das Item unverändert bleibt, und somit auch keine Trigger ausgelöst werden.