Aktionen

Es gibt zwei Möglichkeiten, Aktionen zu definieren. Die Aktionen - einzeln Variante wird am Ende der Dokumentation der Vollständigkeit halber beschrieben. Für einfache Aktionen ohne Angabe zusätzlicher Attribute wie delay, order, repeat, etc. kann diese andere Möglichkeit der Aktionsangabe durchaus Sinn machen.

Bei der hier beschriebenen kombinierten Variante zur Definition von Aktionen werden alle Parameter einer Aktion in einem Attribut definiert. Der Aktionsname se_action_<Bedingungsname/Aktionsname> bezieht sich dabei auf das Item, das über se_item_<Bedingungsname/Aktionsname> unter dem Regelwerk-Item definiert und benannt wurde. Die Herangehensweise ähnelt also stark der Deklaration von Bedingungen.

Zusätzlich zu se_item_<Bedingungsname/Aktionsname> lässt sich über den Eintrag se_mindelta_<Bedingungsname/Aktionsname> definieren, um welchen Wert sich ein Item mindestens geändert haben muss, um neu gesetzt zu werden. Diese Konfiguration kann für einzelne Aktionen individuell über die Angabe mindelta überschrieben werden. Im unten stehenden Beispiel wird der Lamellenwert abhängig vom Sonnenstand berechnet. Ohne mindelta würden sich die Lamellen ständig um wenige Grad(bruchteile) ändern. Wird jedoch mindelta beispielsweise auf den Wert 10 gesetzt, findet eine Änderung erst statt, wenn sich der errechnete Wert um mindestens 10 Grad vom aktuellen Lamellenwert unterscheidet. Im Beispiel wird auch mittels se_status_<Bedingungsname> ein gesondertes Item definiert, das den Wert vom KNX-Aktor empfängt.

Außerdem ist es möglich, über se_repeat_actions generell zu definieren, ob Aktionen für die Stateengine wiederholt ausgeführt werden sollen oder nicht. Diese Konfiguration kann für einzelne Aktionen individuell über die Angabe repeat überschrieben werden.

Beispiel zu Aktionen

Das folgende Beispiel führt je nach Zustand folgende Aktionen aus:

  • Daemmerung: Höhe des Raffstores: 100(%), Lamellendrehung: 25(%)

  • Nachfuehren: Höhe des Raffstores: 100(%), Lamellendrehung: je nach Sonnenausrichtung, aber erst, wenn eine Mindeständerung von 10 Grad vorhanden ist.

  • Sonder: Ausführen der Logic myLogic mit dem Wert 42 und einer Verzögerung von 10 Sekunden.

#items/item.yaml
raffstore1:
    automatik:
        struct: stateengine.general
        rules:
            se_item_height: raffstore1.hoehe # Definition des zu ändernden Höhe-Items
            se_item_lamella: raffstore1.lamelle # Definition des zu ändernden Lamellen-Items
            se_status_lamella: raffstore1.lamelle.status # Definition des Lamellen Statusitems
            se_mindelta_lamella: 10 # Mindeständerung von 10 Grad, sonst werden die Lamellen nicht aktualisiert.
            Daemmerung:
                <...>
                se_action_height:
                    - 'function: set'
                    - 'to: value:100'
                se_action_lamella:
                    - 'function: set'
                    - 'to: value:25'
                <...>
            Nachfuehren:
                <...>
                se_action_height:
                    - 'function: set'
                    - 'to: value:100'
                se_action_lamella:
                    - 'function: set'
                    - 'to: eval:se_eval.sun_tracking()'
                <...>
            Sonder:
                <...>
                se_action_logic1:
                    - 'function: trigger'
                    - 'logic: myLogic'
                    - 'value: 42'
                    - 'delay: 10'
                <...>

Aufbau von Aktionen

Bei yaml Files werden die Parameter mittels Aufzählungszeichen „-“ untereinander definiert, die Listeneinträge müssen in Anführungszeichen oder Hochkommas gesetzt werden:

se_action_<Aktionsname>:
   - 'function: <func>'
   - Detailparameter der Funktion, z.B. "to: .."
   - 'delay: <delay>'
   - 'order: <order>'
   - 'repeat: <repeat>'
   - 'conditionset: <conditionset regex>'

Auszuführende Aktionsart

Mit dem Parameter <func> wird die auszuführende Funktion festgelegt. In Abhängigkeit zur gewählten Funktion werden zusätzliche Detailparameter erforderlich. Folgende Werte sind möglich:

Funktion set: Item auf einen Wert setzen

se_action_<Aktionsname>:
    - 'function: set'
    - 'to: <val>/<eval>/<var>/<item>'
    - 'force: [True/False]'

Das Item, das verändert werden soll, muss auf Ebene des Regelwerk-Items über das Attribut se_item_<Aktionsname> oder se_eval_<Aktionsname> angegeben werden.

Der Parameter to: <val> legt fest, auf welchen Wert das Item gesetzt werden soll. Der Wert, auf den das Item gesezt wird, kann als statischer Wert, als Wert eines Items oder als Ergebnis der Ausführung einer Funktion festgelegt werden. Wichtig ist, dass bei z.B. to: item:<item> nach dem item: kein Leerzeichen eingesetzt werden darf!

Wie bei den Bedingungen sind die entsprechenden Prefixe value, item, eval zu nutzen: - statischer Wert, beispielsweise value:500, wobei das value: auch weggelassen werden kann. - Item, z.B. item:settings.helligkeitsschwellwert - Eval-Funktion wie eval:1*2*se_eval.get_relative_itemvalue('..bla') - Template: eine Vorlage, z.B. template:<Name des Templates>

Über den optionalen Parameter force: True kann eine Item-Aktualisierung erzwungen werden, auch wenn sich der Wert nicht ändert. Damit erfolgt auf jeden Fall eine Wertänderung (ggf. sogar zwei) mit allen damit in Zusammenhang stehenden Änderungen (evals, Aktualisierung der Änderungszeiten, etc).

Funktion add: Wert zu einem Listenitem hinzufügen

se_action_<Aktionsname>:
    - 'function: add'
    - 'value: <val>/<eval>/<var>/<item>'
    - 'force: [True/False]'

Das Item, das verändert werden soll, muss auf Ebene des Regelwerk-Items über das Attribut se_item_<Aktionsname> oder se_eval_<Aktionsname> angegeben werden.

Der Parameter value: <val> legt fest, welcher Wert zum Item mit dem Typ list hinzugefügt werden soll. Wird hier direkt ein Wert angegeben, ist darauf zu achten, dass ein String unter Anführungszeichen stehen muss, während eine Zahl das nicht sollte.

Funktion remove: Wert von einem Listenitem entfernen

se_action_<Aktionsname>:
    - 'function: remove'
    - 'value: <val>/<eval>/<var>/<item>'
    - 'mode: [first/last/all]'

Das Item, das verändert werden soll, muss auf Ebene des Regelwerk-Items über das Attribut se_item_<Aktionsname> oder se_eval_<Aktionsname> angegeben werden.

Der Parameter value: <val> legt fest, welcher Wert vom Item mit dem Typ list entfernt werden soll. Dabei ist zu beachten, dass zwischen String (Anführungszeichen) und Zahlen unterschieden wird. Ist der angegegeben Wert nicht in der Liste, wird der originale Itemwert erneut geschrieben, ohne etwas zu entfernen. Über den Parameter mode lässt sich einstellen, ob jeweils alle mit dem Wert übereinstimmenden Einträge in der Liste (mode: all) oder nur der erste (first) bzw. der letzte (last) Eintrag gelöscht werden sollen. Wird der Parameter nicht angegeben, werden immer alle passenden Einträge gelöscht.

Funktion run: Ausführen einer Funktion

se_action_<Aktionsname>:
    - 'function: run'
    - 'eval: (Funktion)'

Die Angabe ist vergleichbar mit dem Ausführen einer Funktion zur Ermittlung des Werts für ein Item, hier wird jedoch kein Item benötigt. Außerdem wird der Rückgabewert der Funktion ignoriert.

Funktion trigger: Auslösen einer Logikausführung

se_action_<Aktionsname>:
    - 'function: trigger'
    - 'logic: <Logikname>'
    - 'value: <val>/<eval>/<var>/<item>'

Löst die Ausführung der Logik <Logikname> aus. Um beim Auslösen einen Wert an die Logik zu übergeben, kann dieser Wert über die Angabe von value: <Wert> hinter dem Logiknamen angegeben werden. Die Angabe kann aber auch entfallen.

Funktion byattr: Alle Items mit bestimmtem Attribut auf einen Wert setzen

se_action_<Aktionsname>:
    - 'function: byattr'
    - 'attribute: <Attributname>'

Mit dieser Funktion wird der Name eines anderen (beliebigen) Attributs angegeben. Beim Ausführen werden alle Items herausgesucht, die das angegebene Attribut enthalten. Diese Items werden auf den Wert gesetzt, der dem genannten Attribut in den Items jeweils zugewiesen ist.

dummy1:
        type: num
        <Attributname>: 42

dummy1 wird auf 42 gesetzt. Ein anderes Item, dummy2,

dummy2:
        type: str
        <Attributname>: Rums

wird gleichzeitig auf Rums gesetzt.

Funktion special: Sondervorgänge

se_action_<Aktionsname>:
    - function: special
    - value: <Sondervorgang>

Für bestimmte Sondervorgänge sind besondere Aktionen im Plugin definiert. Aktuell gibt es zwei besondere Vorgänge:

  • suspend:<suspend_item>,<manuell_item> (z.B. suspend:..suspend,..manuell)

  • retrigger:<trigger_item> (z.B. retrigger:..retrigger)

In den Beispielen wurden also die relativen Items suspend, manuell und retrigger referenziert.

Zusätzliche Parameter

delay: <int>

Über den optionalen Parameter <delay> wird die Verzögerung angegeben, nach der die Aktion ausgeführt werden soll.

Die Angabe erfolgt in Sekunden oder mit dem Suffix „m“ in Minuten. Die Verzögerungszeit kann auch durch ein eval oder Item zur Laufzeit berechnet werden.

'delay: <eval>/<item>' --> Ergebnis eines Eval-Ausdrucks oder eines Items
'delay: 30'            --> 30 Sekunden
'delay: 30m'           --> 30 Minuten
'delay: -1'            --> Entfernen des Schedulers

Der Timer zur Ausführung der Aktion nach der angegebenen Verzögerung wird entfernt, wenn eine gleichartige Aktion mit Delay-Angabe ausgeführt werden soll. Außerdem ist es möglich, den Timer bewusst abzubrechen, ohne eine Aktion auszuführen, indem der Delay auf -1 gesetzt wird. Dies macht insbesondere beim Verlassen von Zuständen Sinn, um ungewünschte verzögerte Aktionen vom „alten“ Zustand zu verhindern.

instanteval: <bool>

Über den optionalen Parameter <instanteval> wird für verzögerte Aktionen angegeben, ob etwaige eval Ausdrücke sofort evaluiert und gespeichert werden sollen oder die Evaluierung erst zum Ausführungszeitpunkt stattfinden soll.

'instanteval: [True|False]'

Beispiel: Ein Item soll auf einen Wert aus einem Item gesetzt werden. Das Item wird anhand des gerade aktuellen Zustands durch ein eval eruiert:

eval:sh.return_item(se_eval.get_relative_itemid('..settings.{}'.format(se_eval.get_relative_itemvalue('..state_name'))))()

Angenommen, der aktuelle Zustand heißt regen, so wird durch den obigen Code das Item auf den Wert aus settings.regen gesetzt. Ändert sich aber während der Verzögerungszeit (delay) der Zustand auf sonne, würde zum Ausführungszeitpunkt der Aktion der Wert aus dem Item settings.sonne herangezogen werden. Wenn dies nicht erwünscht ist und das Item also auf den Vorgabewert des ursprünglichen Zustands (regen) gesetzt werden soll, kann der Parameter instanteval: True gesetzt werden.

repeat: <bool>

'repeat: <eval>/<item>' --> Ergebnis eines Eval-Ausdrucks oder eines Items
'repeat: [True|False]'

Über das Attribut wird unabhängig vom globalen Setting für das stateengine Item festgelegt, ob eine Aktion auch beim erneuten Eintritt in den Status ausgeführt wird oder nicht. Das globale Setting kann im Regelwerk Item unter rules durch se_repeat_actions: false dezidiert auf False gesetzt werden. Standardmäßig, wenn das Attribut also nicht angegeben wird, werden Aktionen wiederholt ausgeführt.

order: <int>

Die Reihenfolge, in der die Aktionen ausgeführt werden, ist nicht zwingend die Reihenfolge in der die Attribute definiert sind. In den meisten Fällen ist dies kein Problem, da oftmals die Aktionen voneinander unabhängig sind und daher in beliebiger Reihenfolge ausgeführt werden können. In Einzelfällen kann es jedoch erforderlich sein, mehrere Aktionen in einer bestimmten Reihenfolge auszuführen. Dies kann über den Parameter order: <order> erfolgen. Mit diesem Attribut wird der Aktion eine Zahl zugewiesen, die als value, item oder eval vorliegen kann. Aktionen werden in aufsteigender Reihenfolge der zugewiesenen Zahlen ausgeführt.

'order: [1|2|...]'

conditionset: <conditionset regex>

'conditionset: ["regex:enter_(.*)_test", "eval:sh.itemX.property.value"]'

Über das Attribut wird festgelegt, dass die Aktion nur dann ausgeführt werden soll, wenn der Zustand durch die angegebene Bedingungsgruppe eingenommen wurde. Zum Vergleich wird immer der volle Pfad (die ID) der Bedingungsgruppe herangezogen. Conditionset erlaubt sowohl einzelne Werte mittels value, regex oder eval, als auch eine Liste. Die Liste kann zum einen wie oben angeführt mit eckigen Klammern, als auch wie gewohnt mit „-“ in einzelnen Zeilen (siehe unten) angegeben werden. Wichtig ist, im ersten Fall reguläre Ausdrücke unter Anführungszeichen zu setzen (und dann Hochkomma um den gesamten Eintrag). Im zweiten Fall sind keine Anführungszeichen notwendig.

Die einzelnen Angaben einer Liste werden als OR evaluiert.

screens:
    conditionset_to_check:
        type: str
        initial_value: "screens.osten_s1.automatik.rules.abend.enter_abend"

      conditionset:
        - regex:enter_(.*)_test
        - eval:sh.screens.conditionset_to_check.property.value

Der gesamte Pfad könnte wie folgt evaluiert werden:

"eval:se_eval.get_relative_itemid('{}.<bedingungsset>'.format(se_eval.get_relative_itemvalue('..state_id')))"

Eine sinnvolle Anwendung hierfür wäre, anstelle von verschiedenen Zuständen mit leicht anderen Bedingungen, alles in einen Zustand zu packen und anhand des Conditionsets unterschiedliche Aktionen ausführen zu lassen. Ein ähnliches Setup könnte im gegebenen Beispiel zwar auch mittels se_use umgesetzt werden, allerdings gibt es auch andere Situationen, wo das komplizierter oder weniger zielführend wäre. Im Beispiel wird abends die Höhe des Raffstores auf 100 gesetzt, falls es regnet. Falls es nicht regnet hingegen auf den Wert, der in den Settings hinterlegt ist.

abend:
    on_enter_or_stay:
        se_action_hoehe:
          - 'function: set'
          - 'to: item:..settings.abend.hoehe'
          - 'order: 1'
          - 'conditionset: regex:(.*)enter(?!_regen)(.*)'
        se_action_hoehe_regen:
          - 'function: set'
          - 'to: 100'
          - 'order: 1'
          - 'conditionset: regex:(.*)enter_regen'

    enter_normal:
        diverse Bedingungen

    enter_regen:
        diverse andere Bedingungen

previousconditionset: <conditionset regex>

"previousconditionset: regex:enter_(.*)_test"

Über das Attribut wird festgelegt, dass die Aktion nur dann ausgeführt werden soll, wenn die vorherige Bedingungsgruppe des aktuellen Zustands mit dem angegebenen Ausdruck übereinstimmt. Die Abfrage erfolgt dabei nach den gleichen Regeln wie bei conditionset oben angegeben.

previousstate_conditionset: <conditionset regex>

"previousstate_conditionset: regex:enter_(.*)_test"

Über das Attribut wird festgelegt, dass die Aktion nur dann ausgeführt werden soll, wenn die Bedingungsgruppe, mit der der vorherige Zustand eingenommen wurde, mit dem angegebenen Ausdruck übereinstimmt. Die Abfrage erfolgt dabei ebenfalls nach den gleichen Regeln wie bei conditionset oben angegeben.

next_conditionset: <conditionset regex>

"next_conditionset: regex:enter_(.*)_test"

Über das Attribut wird festgelegt, dass die Aktion nur dann ausgeführt werden soll, wenn die Bedingungsgruppe, mit der der zukünftige Zustand eingenommen wird, mit dem angegebenen Ausdruck übereinstimmt. Die Abfrage erfolgt dabei ebenfalls nach den gleichen Regeln wie bei conditionset oben angegeben. Diese Angabe ist primär bei leave_actions sinnvoll.

mindelta: <num>

Im folgenden Beispiel wird mindelta für eine einzelne Aktion gesetzt. Anstatt also eine minimale Änderung für alle Aktionen mit bestimmtem Namen festzulegen, wird eine einzelne Aktion nur dann ausgeführt, wenn sich der Wert um mindestens den angegeben Wert geändert hat. Wird mindelta beispielsweise auf den Wert 10 gesetzt, findet eine Änderung erst statt, wenn sich der errechnete Wert um mindestens 10 Grad vom aktuellen Lamellenwert unterscheidet.

#items/item.yaml
raffstore1:
    automatik:
        struct: stateengine.general
        rules:
            se_item_height: raffstore1.hoehe # Definition des zu ändernden Höhe-Items
            se_item_lamella: raffstore1.lamelle # Definition des zu ändernden Lamellen-Items
            se_status_lamella: raffstore1.lamelle.status # Definition des Lamellen Statusitems
            Daemmerung:
                <...>
                se_action_height:
                    - 'function: set'
                    - 'to: value:100'
                se_action_lamella:
                    - 'function: set'
                    - 'to: value:25'
                    - 'mindelta: 10'
                <...>

minagedelta: <num>

minagedelta: 300

Über das Attribut wird festgelegt, dass eine Aktion nur in einem vorgegebenen Intervall ausgeführt wird. Im angegebenen Beispiel wird die Aktion also nur ausgeführt, wenn der letzte Ausführungszeitpunkt mindestens 5 Minuten zurück liegt. So kann verhindert werden, dass die Aktion bei jeder Neuevaluierung des Status ausgeführt wird. Ein Neustart des Plugins setzt den Counter wieder zurück, der letzte Ausführungszeitpunkt wird also nur bei laufendem Betrieb gespeichert und überdauert einen Neustart nicht.

Templates für Aktionen

Setzt man für mehrere Aktionen (z.B. Setzen auf einen Wert abhängig vom aktuellen Zustand) immer die gleichen Ausdrücke ein, so kann Letzteres als Template definiert und referenziert werden. Dadurch wird die Handhabung komplexerer Wertdeklarationen deutlich vereinfacht. Diese Templates müssen wie se_item/se_eval auf höchster Ebene des StateEngine Items (also z.B. rules) deklariert werden.

rules:
  se_template_test: se_eval.get_relative_itemid('wetterstation.helligkeit_{}'.format(se_eval.get_relative_itemvalue('..state_name')))
  se_item_specialitem: meinitem.specialitem # declare an existing item here

  state_one:
      on_enter:
          se_action_specialitem:
              - 'function: set'
              - 'to: template:test'