Bedingungen

Beispiel

Im folgenden Beispiel wird der Zustand „Daemmerung“ eingenommen, sobald die Helligkeit (über se_item_brightness oder se_status_brightness definiert) über 500 Lux liegt.

#items/item.yaml
raffstore1:
    automatik:
        struct: stateengine.general
            rules:
                se_status_brightness: beispiel.wetterstation.helligkeit
                Daemmerung:
                    name: Dämmerung
                    remark: <Aktionen>
                    enter:
                       se_min_brightness: 500

Name der Bedingung

Der Name einer Bedingung setzt sich aus folgenden drei Teilen zusammen, die jeweils mit einem Unterstrich „_“ getrennt werden:

  • se_: eindeutiger Prefix, um dem Plugin zugeordnet zu werden

  • <Vergleichsfunktion>: siehe unten. Beispiel: min = der Wert des <Bedingungsitems> muss mindestens dem beim Attribut angegebenen Wert entsprechen.

  • <Vergleichsitem/Bedingungsname>: Hier wird entweder das im Regelwerk-Item mittels se_item_<Name> oder se_status_<Name> deklarierte Item oder eine besondere Bedingung (siehe unten) referenziert.

Referenzieren von Items

Für jede „standardmäßige“ Bedingung muss ein Item hinterlegt werden, das geprüft werden soll. Dies geschieht in der Regel durch se_status_<Name>, kann aber auch durch se_item_<Name> erfolgen, falls z.B. das gleiche Item für Bedingungen und Aktionen gebraucht wird.

Im Beispiel wird durch se_status_brightness das Item für den Check von Bedingungen bekannt gemacht. Aufgrund der angegebenen eval-Funktion wird das Item abhängig vom aktuellen Zustandsnamen eruiert. Da Zustand_Eins den Namen „sueden“ hat, wird somit der Wert von wetterstation.helligkeit_sueden abgefragt. Ist dieser mehr als 499, ist die Bedingung erfüllt. Würde der Zustand „osten“ heißen (Name von Zustand_Zwei), würde der Helligkeitswert vom Osten getestet werden. Bedingung wäre dann erfüllt, wenn die Helligkeit 1500 oder mehr beträge.

#items/item.yaml
raffstore1:
    automatik:
        struct: stateengine.general
        rules:
            se_status_brightness: eval:se_eval.get_relative_itemvalue('wetterstation.helligkeit_{}'.format(se_eval.get_variable('current.state_name')))

            Zustand_Eins:
                name: sueden
                enter:
                    se_min_brightness: 500

            Zustand_Zwei:
                name: osten
                enter:
                    se_min_brightness: 1500

Bedingungsgruppen

Unabhängig davon, ob ein Zustand von nur einer Bedingung oder mehreren Bedingungen abhängt, werden Bedingungen immer als Attribute unter ein Item gestellt, das enter heißt. Bei mehreren Bedingungsgruppen kann noch ein beliebiger Name, getrennt durch einen Unterstrich „_“ hinzugefügt werden. Das Bedinungsgruppen-Item könnte dann enter_zuhell heißen. Der Name ist dabei völlig beliebig und nimmt keinen Bezug auf irgendwelche anderen Elemente.

Die folgenden Regeln kommen zur Anwendung:

  • Zustände und Bedingungsgruppen werden in der Reihenfolge geprüft, in der sie in der Konfigurationsdatei definiert sind.

  • Eine einzelne Bedingungsgruppe ist erfüllt, wenn alle Bedingungen, die in der Bedingungsgruppe definiert sind, erfüllt sind (UND-Verknüpfung).

  • Ein Zustand kann aktueller Zustand werden, wenn eine beliebige der definierten Bedingungsgruppen des Zustands erfüllt ist. Die Prüfung ist mit der ersten erfüllten Bedingungsgruppe beendet (ODER-Verknüpfung).

  • Ein Zustand, der keine Bedingungsgruppen hat, kann immer aktueller Zustand werden. Solch ein Zustand kann als Default-Zustand am Ende der Zustände definiert werden.

Wertevergleich

Der zu vergleichende Wert einer Bedingung kann auf folgende Arten definiert werden:

  • statischer Wert (also z.B. 500 Lux). Wird angegegeben mit value:500, wobei das value: auch weggelassen werden kann.

  • Item (beispielsweise ein Item namens settings.helligkeitsschwellwert). Wird angegeben mit item:settings.helligkeitsschwellwert. Das Item kann auch eine Liste von Werten beinhalten.

  • Eval-Funktion (siehe auch eval Ausdrücke). Wird angegeben mit eval:1*2*se_eval.get_relative_itemvalue('..bla')

  • Regular Expression (siehe auch ` RegEx Howto <https://docs.python.org/3/howto/regex.html>`_) - Vergleich mittels re.fullmatch, wobei Groß/Kleinschreibung ignoriert wird. Wird angegeben mit regex:StateEngine Plugin:(.*)

  • Template: eine Vorlage, z.B. eine eval Funktion, die immer wieder innerhalb des StateEngine Items eingesetzt werden kann. Angegeben durch template:<Name des Templates>

Templates für Bedingungsabfragen

Setzt man für mehrere Bedingungsabfragen (z.B. Helligkeit, Temperatur, etc.) immer die gleichen Ausdrücke ein (z.B. eine eval-Funktion), so kann Letzteres als Template definiert und referenziert werden. Dadurch wird die Handhabung komplexerer Abfragen 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: eval:sh...settings.max_bright' - 20
  se_item_specialitem: meinitem.specialitem # declare an existing item here

  state_one:
      enter_testlast: #has to start with enter, can be called whatever
          se_value_laststate: 'template:test' #laststate is a special conditionname
      enter_testother:
          se_value_specialitem: 'template:test' #specialitem must be declared with se_item/se_eval

Bei sämtlichen Bedingungen ist es möglich, Werte als Liste anzugeben. Es ist allerdings nicht möglich, Templates als Listen zu definieren.

Bedingungen mittels eval-Ausdrücken

se_eval_<Name> kann neben der dynamischen Definition von Items auch für einen herkömmlichen eval-Ausdruck herhalten, der dann in einem Bedingungsset geprüft wird.

#items/item.yaml
raffstore1:
    automatik:
        struct: stateengine.general
        rules:
            se_eval_berechnung: sh.test.property.value + 1

            Zustand_Eins:
                name: sueden
                enter:
                    se_value_berechnung: 3

Bedingungslisten

Sämtliche nun gelisteten Bedingungen können entweder eine einzelne Angabe haben oder aus einer Liste mit mehreren Bedingungen bestehen. In letzterem Fall fungiert die Liste als ODER Abfrage. Sobald eine der gelisteten Werte eingetroffen ist, wird die Bedingung als wahr angenommen und der Zustand aktiviert.

se_value_laststate:
    - 'kochen'
    - 'eval:1+2'
    - 'regex:Nachfuehren(.*)'
    - 'item:..laststate_id'

Im oben gezeigten Beispiel kann der letzte Status einen von drei Werten beinhalten, damit die Bedingung wahr ist. In welcher Form diese Werte angegeben werden, ist offen - es müssen also nicht nur reine Strings in die Liste eingefügt werden.

Werden sowohl min(age) als auch max(age) als Liste definiert, spielt die Reihenfolge der Liste eine Rolle, da die beiden Werte als Paar herangezogen werden.

se_minage_<Bedingungsname>:
    - '5'
    - 'eval:1+2'
    - 'novalue'

se_maxage_<Bedingungsname>:
   - '10'
   - 'eval:5*sh.meinwert()'
   - 'item:EinzweitesItem'

Obige Bedingung wird beispielsweise wahr bei: - einem Wert zwischen 5 und 10 - einem Wert zwischen 3 und 5 * der Wert des Items meinwert - einem Wert maximal so hoch wie der in EinzweitesIem hinterlegte

Vergleichsfunktion

Minimum

se_min_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn der aktuelle Wert größer als das angegebene Minimum ist.

Maximum

se_max_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn der aktuelle Wert kleiner als das angegebene Maximum ist.

Bestimmter Wert

se_value_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn der aktuelle Wert gleich dem angegebenen Wert oder gleich einem der in einer Liste angegebenen Wert ist.

se_value_<Bedingungsname>:
   - [Wert1]
   - [Wert2]
   - [WertN]

Negieren

se_negate_<Bedingungsname>: True|False

Die gesamte Bedingung (Minimum, Maximum und Wert) wird negiert (umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind „true“, „yes“, „on“ bzw. „false“, „no“, „off“

Aktualisierung des Items durch

se_updatedby_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn das Item durch den angegebenen Wert bzw. einen der angegebenen Werte geändert wurde. Hier bietet es sich an, den Wert als Regular Expression mittels se_updatedby_<Bedingungsname>: regex:StateEngine Plugin zu definieren. Die Werte(liste) kann auch durch se_updatedbynegate_<Bedingungsname> negiert werden.

se_updatedby_<Bedingungsname>:
   - [Wert1]
   - [Wert2]
   - regex:[WertN]

se_updatedbynegate_<Bedingungsname>: True|False

Änderung des Items durch

se_changedby_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn das Item durch den angegebenen Wert bzw. einen der angegebenen Werte geändert wurde. Hier bietet es sich an, den Wert als Regular Expression mittels se_changedby_<Bedingungsname>: regex:StateEngine Plugin zu definieren. Die Werte(liste) kann auch durch se_changedbynegate_<Bedingungsname> negiert werden.

se_changedby_<Bedingungsname>:
   - [Wert1]
   - [Wert2]
   - regex:[WertN]

se_changedbynegate_<Bedingungsname>: True|False

Triggerung des Items durch

se_triggeredby_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn das Item durch den angegebenen Wert bzw. einen der angegebenen Werte getriggert wurde. Dies kann relevant werden, um herauszufinden, wodurch ein Item mit einem eval-Attribut getriggert wurde, unabhängig davon, ob sich daraus eine Wertänderung ergibt oder nicht. Hier bietet es sich an, den Wert als Regular Expression mittels se_triggeredby_<Bedingungsname>: regex:StateEngine Plugin zu definieren. Die Werte(liste) kann auch durch se_triggeredbynegate_<Bedingungsname> negiert werden.

se_triggeredby_<Bedingungsname>:
   - [Wert1]
   - [Wert2]
   - regex:[WertN]

se_triggeredbynegate_<Bedingungsname>: True|False

Mindestalter

se_agemin_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn das Alter des Items, das zur Ermittlung des Werts angegeben ist, größer als das angegebene Mindestalter ist. Die age Bedingungen sollten immer mit einer value Bedingung verknüpft werden (z.B. se_value_<Bedingungsname>: True)

Höchstalter

se_agemax_<Bedingungsname>: [Wert]

Die Bedingung ist erfüllt, wenn das Alter des Items, das zur Ermittlung des Werts angegeben ist, kleiner als das angegebene Höchstalter ist. Die age Bedingungen sollten immer mit einer value Bedingung verknüpft werden (z.B. se_value_<Bedingungsname>: True)

Altersbedingung negieren

se_agenegate_<Bedingungsname>: True|False

Die Altersbedingung (Mindestalter, Höchstalter) wird negiert (umgekehrt). Für das Attribut wird der Datentyp Boolean verwendet, zulässige Werte sind „true“, „1“, „yes“, „on“ bzw. „false“, „0“, „no“, „off“

„Besondere“ Bedingungen

Das Plugin stellt die Werte für einige „besondere“ Bedingungen automatisch bereit. Für diese Bedingungen muss daher kein Item und keine Eval-Funktion zur Ermittlung des aktuellen Werts angegeben werden. Die „besonderen“ Bedingungen werden über reservierte Bedingungsnamen gekennzeichnet. Diese Bedingungsnamen dürfen daher nicht für andere Bedingungen verwendet werden.

Die folgenden „besonderen“ Bedingungsnamen können verwendet werden

time Aktuelle Uhreit

Die Werte für se_value_time, se_min_time und se_max_time müssen im Format „hh:mm“ („:“) angegeben werden. Es wird ein 24 Stunden-Zeitformat verwendet. Beispiele: „08:00“ oder „13:37“. Um das Ende des Tages anzugeben kann der Wert „24:00“ verwendet werden, der für die Prüfungen automatisch zu „23:59:59“ konvertiert wird. Wichtig sind die Anführungszeichen oder Hochkommas!

weekday Wochentag

0 = Montag, 1 = Dienstag, 2 = Mittwoch, 3 = Donnerstag, 4 = Freitag, 5 = Samstag, 6 = Sonntag

month Monat

1 = Januar, …, 12 = Dezember

sun_azimut Sonnenstand (Horizontalwinkel)

Der Azimut (Horizontalwinkel) ist die Kompassrichtung, in der die Sonne steht. Der Azimut wird von smarthomeNg auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe auch Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Beispielwerte: 0 → Sonne exakt im Norden, 90 → Sonne exakt im Osten, 180 → Sonne exakt im Süden, 270 → Sonne exakt im Westen

sun_altitude Sonnenstand (Vertikalwinkel)

Die Altitude (Vertikalwikel) ist der Winkel, in dem die Sonne über dem Horizont steht. Die Altitude wird von smarthomeNG auf Basis der aktuellen Zeit sowie der konfigurierten geographischen Position berechnet. Siehe ebenfalls SmarthomeNG Dokumentation für Voraussetzungen zur Berechnung der Sonnenposition. Werte: negativ → Sonne unterhalb des Horizonts, 0 → Sonnenaufgang/Sonnenuntergang, 90 → Sonne exakt im Zenith (passiert nur in äquatorialen Bereichen)

age Zeit seit der letzten Änderung des Zustands (Sekunden)

Das Alter wird über die letzte Änderung des Items, das als se_laststate_item_id angegeben ist, ermittelt.

condition_age Zeit seit der letzten Änderung des Bedingungssets (Sekunden)

Das Alter wird über die letzte Änderung des Items, das als se_lastconditionset_item_id angegeben ist, ermittelt.

random Zufallszahl zwischen 0 und 100

Wenn etwas zufällig mit einer Wahrscheinlichkeit von 60% passieren soll, kan beispielsweise die Bedingung se_max_random: 60 verwendet werden.

laststate Id des Zustandsitems des aktuellen Status

Die Abfrage se_value_laststate ist besonders wichtig für Bedingungsabfragen, die über das Verbleiben im aktuellen Zustand bestimmen (z.b. enter_stay). So können aber auch Zustände übersprungen werden, wenn sie nicht nach einem bestimmten anderen Zustand aktiviert werden sollen. Wichtig: Hier muss die vollständige Item-Id angegeben werden

lastconditionset_id/name Id des Bedingungssets des aktuellen Status

Wie bei laststate sind auch die lastconditionset Bedingungsabfragen primär relevant für Abfragen zum Verbleiben in einem Zustand. Gerade bei komplexeren Bedingungssets macht es oftmals Sinn, nach dem Set zu fragen, das denn nun wirklich für die letzte Zustandsbestimmung relevant war.

previousconditionset_id/name Id des vorherigen Bedingungssets

Hier kann das vorhergehende Bedinungsset mit einem Ausdruck/Wert verglichen werden. Dabei spielt es keine Rolle, ob der Zustand gerade gewechselt wurde oder z.B. auf Grund einer anderen Bedingungsgruppe beibehalten wird. Beispiel: Ein Item ist aktuell im Zustand „Suspend“ auf Grund einer manuellen Triggerung, also der Bedingungsgruppe „enter_manuell“. se_value_previousconditionset_name beinhaltet nun den Namen der Bedingungsgruppe vom vorherigen Zustand. Bei einer erneuten Zustandsevaluierung bleibt (höchstwahrscheinlich) das Item im Zustand suspend auf Grund der Bedingungsgruppe „enter_stay“. Die Abfrage beinhaltet nun den Wert der vorigen Gruppe „enter_manuell“.

previousstate Id des Zustandsitems des vorherigen Status

Die Abfrage se_value_previousstate kann genutzt werden, um beispielsweise zu verhindern, dass ein Zustand nach dem Aktivieren eines anderen Zustands erneut eingenommen wird. Beispiel: Im Normalfall wäre folgende Zustandsabfolge möglich, sofern die entsprechenden Bedingungen erfüllt sind: Abend - Nacht - Abend. Durch die folgende Angabe würde der Zustand Abend kein zweites Mal (nach Nacht) eingenommen werden.

abend:
  enter_abend:
     se_value_previousstate: var:current.state_id
     se_negate_previousstate: True

previousstate_conditionset_id/name Id des zuletzt aktiven Bedingungssets des vorherigen Status

Durch diese Bedingung kann festgelegt werden, welche ID oder welchen Namen die zuletzt aktive Bedingungsgruppe des vorherigen Zustands haben darf. Beispiel: Der Zustand Suspend wird durch enter_manuell eingenommen. Bei der nächsten Evaluierung bleibt der Zustand auf Grund von enter_stay aktiv. Der Zustand wird schließlich verlassen, stattdessen ist nun z.B. der Sperrzustand (lock) aktiv. se_value_previousstate_conditionset_name gibt nun enter_stay zurück.

trigger_item, trigger_caller, trigger_source, trigger_dest item, caller, source und dest-Werte, durch die die Zustandsermittlung direkt ausgelöst wurde

Über diese vier Bedingungen kann der direkte Auslöser der Zustandsermittlung abgeprüft werden, also die Änderung, die smarthomeNG veranlasst, die Zustandsermittlung des stateengine-Plugins aufzurufen.

original_item, original_caller, original_source item, caller, source und dest-Werte, durch die die Zustandsermittlung ursprünglich ausgelöst wurde

Über diese vier Bedingungen kann der ursprüngliche Auslöser der Zustandsermittlung abgeprüft werden. Beim Aufruf der Zustandsermittung über einen eval_trigger Eintrag wird über trigger_caller beispielsweise nur Eval weitergegeben. In den drei original_* Bedingungen wird in diesem Fall der Auslöser der Änderung zurückverfolgt und der Einstieg in die Eval-Kette ermittelt.