DOIF/Einsteigerleitfaden, Grundfunktionen und Erläuterungen

Aus FHEMWiki

DOIF, für FHEM-Einsteiger konzipiert, wurde über Benutzeranforderungen zu einem immer vielfältigeren Werkzeug weiter entwickelt. Damit orientiert sich die Weiterentwicklung des DOIF an praktischen Aufgabenstellungen. Im Ergebnis können einfache Probleme, sowie auch spezielle und komplexe Aufgaben in kompakter Weise gelöst werden. Damit nimmt jedoch auch die Zahl der Einstellungsmöglichkeiten über Attribute, Syntaxvarianten und deren Kombinationen zu. Das macht es für Einsteiger und Fortgeschrittene nicht leicht den Überblick zu behalten.

Hier soll der Blick auf die Teile des DOIF beschränkt werden, die für die Einfachheit des DOIF aus seiner Anfangszeit stehen und die ausreichen 80% der Aufgabenstellungen lösen.

Info green.pngHinweis! Die deutschsprachige FHEM-Befehlsreferenz (Commandref) zum DOIF sollte bei Fragen immer das erste Nachschlagewerk sein. Sie ist aktueller, genauer und mit Beispielen versehen. Dieser Artikel ist eine geraffte Darstellung der Grundlagen des DOIF mit einigen Erläuterungen.


Voraussetzung

Die FHEM-Begriffe Gerät (Device), State (Status), Readings, Internals, Attribute, Event (Ereignis), Befehl (Command) und deren Funktion sollen bekannt sein.

DOIF-Light für Einsteiger

Die meisten Verknüpfungsaufgaben können mit einem Verständnis der folgenden Abschnitte der Hilfe zum DOIF (deutschsprachige Befehlsreferenz) gelöst werden.

Struktur und Verhalten des DOIF

Grundbegriffe und Aufbau

Der Aufbau des DOIF entspricht einer Baumstruktur mit Bedingungszweigen.

Emblem-question-yellow.svgAchtung! Der Begriff Ereignis wird in diesem Artikel erweitert verwendet und umfasst ablaufende Timer und Ereignisse(Events).


"DOIF_Aufbau_Ablauf"

Um DOIF zu verstehen, müssen vorab folgende Grundbegriffe präzisiert werden.

Auslöser sind Zeitpunkte, Gerätenamen(bei checkReadingEvent 0, voreingestellt bis Version 16651 2018-04-23 06:28:53Z Damian) oder die Kombination von Gerätename:Reading(bei checkReadingEvent 1, voreingestellt nach Version 16651 2018-04-23 06:28:53Z Damian) und reguläre Ausdrücke, die auf Gerätenamen oder ein Ereignis passen.

Ereignisse sind für DOIF ablaufende Timer oder Ereignisse (Events) die durch Geräte initiiert werden.

Zweig (auch Bedingungszweig) wird im DOIF von einem DOIF-Schlüsselwort (DOIF, DOELSEIF, DOELSE) eingeleitet und endet vor dem nächsten DOIF-Schlüsselwort. Ein Zweig entspricht damit genau einer Zeile in dem obigen Diagramm.

Status des DOIF ist der Inhalt des Readings state.

Statuswechsel können sehr komplex sein. Für das erste Verständnis genügt es zu wissen, dass das device in einen anderen Zweig wechselt (sich also der Status oder der Inhalt des Readings ändert).

(Anmerkung: In den ersten Versionen von DOIF gab nur Stati cmd_1, cmd_2 und es gab nur eine Status- bzw. Reading-Abfrage und Zeittrigger. Dann kamen Zeitintervalle, Sequenzen mit Zwischenzuständen, reine Ereignistrigger, Attribut checkall hinzu, so dass diese einfache Erklärung inzwischen nicht mehr genügt.)

Verhaltensweise ohne steuernde Attribute

Der DOIF-Prozess wird gestartet wenn ein Ereignis eintrifft. Nun wird geprüft, ob das Ereignis zu dem Auslöser einer Bedingung passt. Ist dies der Fall, wird die Bedingung geprüft. Die Prüfung erfolgt im Bedingungsteil.


Angaben im Bedingungsteil

Der Bedingungsteil besteht aus einer Perl-Ebene und einer Präprozessorebene.


Info blue.png
(Perl-Ebene [DOIF-Präprozessor] Perl-Ebene [DOIF-Präprozessor] ...)


Die erste Ebene der ersten runden Klammer nach den Schlüsselwörtern DOIF oder DOELSEIF umschliesst eine Bedingung.

Für Angaben in dieser Klammer (Perl-Ebene) gilt die Perl-Syntax (Operatoren, Operanden, wie Funktionen, Variablen), ausgenommen sind die Angaben in der ersten Ebene der eckigen Klammern, sie umschliessen die Ebene des DOIF-Präprozessors. Dort gilt die Syntax des DOIF-Präprozessors.

In dieser Ebene der eckigen Klammern werden DOIF-Operanden angegeben. Die DOIF-Operanden beinhalten die Auslöser.

Ist die Bedingung wahr, werden die nach der Bedingung stehenden Befehle ausgeführt. Ist die Bedingung unwahr (falsch) wird der nächste Zweig bearbeitet.

Nach der Befehlsausführung wird der Status des DOIF auf die Befehlsnummer gesetzt (cmd_x) und DOIF wartet auf das nächste Ereignis.

Ist DOELSE angegeben, es gab einen passenden Auslöser und alle geprüften Bedingungen waren unwahr, dann werden die nach DOELSE angegebenen Befehle ausgeführt.

Ein Statuswechsel findet statt, nachdem ein anderer Bedingungszweig wahr wurde und die zugehörigen Befehle ausgeführt worden sind. Die Befehle eines Zweiges werden dabei ohne vorherigen Statuswechsel nur einmal ausgeführt.

Ein DOIF mit nur einem Zweig enthält ein internes DOELSE, d.h. bei unwahrer Bedingung und vorhandenem Auslöser findet ein Statuswechsel auf cmd_2 statt.

Auslöser

Auslöser können durch direkte Angabe des Gerätenamen, Readings, Internals usw. angegeben werden.

Readings und Internals

[<Gerätename>] oder [<Gerätename>:&STATE] bezieht sich auf das Internal STATE des Gerätes.

commandref/DOIF_Ereignissteuerung

[<Gerätename>:<Readingname>] bezieht sich auf das Reading des Gerätes.

commandref/DOIF_Ereignissteuerung

[<Gerätename>:<Readingname>:d] bezieht sich auf den ersten numerischen Teil des Reading-Wertes.

commandref/DOIF_Filtern_nach_Zahlen

[<Gerätename>:<Readingname>:d<Anzahl der gerundeten Stellen nach dem Dezimaltrenner>] bezieht sich auf den ersten numerischen Teil des Reading-Wertes, der auf Anzahl Stellen gerundet ist.

commandref/DOIF_Filtern_nach_Zahlen

[<Gerätename>:<Readingname>:sec] bezieht sich auf das Alter des Zeitstempels in Sekunden.

commandref/DOIF_Zeitspanne_eines_Readings_seit_der_letzten_Aenderung

[<Gerätename>:&<Internalname>] bezieht sich auf das Internal des Gerätes.

commandref/DOIF_Ereignissteuerung

[<Auslöserangabe>,<Vorgabewert>] nicht existierende Auslöser können mit einem Vorgabewert angegeben werden.

commandref/DOIF_notexist

Zeitangaben

[<Zeitpunkt>] gibt einen Zeitpunkt an

commandref/DOIF_Zeitsteuerung

[<Zeitpunkt Beginn>-<Zeitpunkt Ende>|<Wochentagangaben>] gibt eine Zeitspanne an, optionale Wochentagangabe

commandref/DOIF_Zeitsteuerung_mit_Zeitintervallen

[[<Auslöserangabe>]] gibt einen Zeitpunkt indirekt an.

commandref/DOIF_Indirekten_Zeitangaben

Mit Zeitangaben kann gerechnet werden, Berechnungen erfolgen in runden Klammern.

Liefert eine Perl-Funktion HH:MM:SS muss sie in geschweifte Klammern eingeschlossen werden.

[{sunrise}] z.B. Angabe eines Zeitpunktes durch die Perl-Funktion sunrise.

commandref/DOIF_Zeitsteuerung_mit_Zeitberechnung

Auslöser (erweitert)

Auslöser können auch allgemein formuliert werden, dazu ist die Fertigkeit erforderlich Reguläre Ausdrücke (Regex) formulieren zu können.

Readings und Internals

[<Auslöserangabe>:<Regex Filter>,<Ausgabeformatierung>] Auslöser können mit einem Filter eränzt werden, die gefilterten Werte können in der Ausgabeformatierung weiterverarbeitet werden.

commandref/DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

Ereignisse

[<Gerätename>:"<Regex Ereignisrest>"]

commandref/DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

["<Regex Gerätename>:<Regex Ereignisrest>"]

commandref/DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

["<Regex Ereignis>",<Vorgabewert>]

commandref/DOIF_Ereignissteuerung_ueber_Auswertung_von_Events

["<Regex Ereignis>":<Regex Filter>,<Ausgabeformatierung>,<Vorgabewert>] optional: Filter und Formatierung, verpflichtend: Vorgabe

commandref/DOIF_Ereignissteuerung_ueber_Auswertung_von_Events und commandref/DOIF_Filtern_nach_Zahlen

Ereignisse mit Aggregation (Sammlung) von Werten

[<Funktion>:<Format>:"<Regex Gerätename>:<Regex Ereignisrest>":<Reading>:<Bedingung>,<Vorgabewert>] optional: Format, Reading, Bedingung und Vorgabewert

commandref/DOIF_aggregation

Ereignisse mit vordefinierten Filtern (Durchschnitt, Median, Differenz, anteiliger Anstieg)

[<Gerätename>:<Reading>:<Filtername><Pufferlänge>]

commandref/DOIF_Reading_Funktionen

Alle Auslöser

[?<Auslöserangabe>] Auslöser, die mit Fragezeichen beginnen lösen nicht aus, sie werden nur abgefragt

commandref/DOIF_Zeitintervalle_Readings_und_Status_ohne_Trigger

Angaben im Befehlsteil

Befehle stehen nach einer Bedingung oder nach DOELSE in runden Klammern (erste Klammerebene), das ist die FHEM-Ebene. Befehle können direkt angegeben werden.


Info blue.png
(<FHEM-Befehle>), ("<Systembefehle>") oder {<Perl-Befehle>}


Befehle können zu Sequenzen gruppiert werden durch mehrere runde Klammerpaare der ersten Ebene)


Info blue.png
(<Befehle der Sequenz 1>) (<Befehle der Sequenz 2>) ... (<Befehle der Sequenz n>)


Trennzeichen für Befehle ist das Komma, daher ist keine Verdoppelung der Trennzeichen erforderlich.


Info blue.png
(<Befehl 1>, <Befehl 2>, ... <Befehl n>)


Enthält ein Befehl ein Komma, dass kein Befehlstrennzeichen ist, dann ist der Befehl in zusätzliche runde Klammern einzuschliessen.


Info blue.png
((<Befehlsteil 1a>,<Befehlsteil 1b>), <Befehl 2>, ... <Befehl n>)


Berechnungen erfolgen in geschweiften Klammern auf der Perl-Ebene und müssen unmittelbar mit einer runden Klammer beginnen.

Der Zugriff auf Readings, Internals usw. erfolgt wie im DOIF üblich, über Angaben in eckigen Klammern inklusive Ausgabeformatierung und Präprozessorersatznamen, wie $SELF, $DEVICE, $EVENT, $EVENTS (extended set magic).

Häufige Attribute

Attribute verändern das Standardverhalten des DOIF.


do always

Ohne do always gilt:Die Befehle eines Bedingungszweiges werden ohne vorherigen Statuswechsel nur einmal ausgeführt.

Das Attribut setzt diese Regel ausser Kraft. Befehle werden wiederholt im bestehenden Status ausgeführt.

Das interne DOELSE entfällt bei DOIF mit einem Zweig.

Wait-Timer werden bei wiederholtem Wahrwerden der Bedingung nicht abgebrochen.

wait

Das Attribut verzögert die Befehlsausführung, nach wahr werden einer Bedingung.

Laufende Wait-Timer werden bei einem eingeleiteten Statuswechsel des DOIF abgebrochen, daher werden die zu verzögernden Befehle nicht mehr ausgeführt.

do resetwait

Das Attribut beinhaltet do always, bricht aber die Wait-Timer bei wiederholtem Wahrwerden der Bedingung ab.

readingList, setList, webCmd, widgetOverride

Diese Attribute statten DOIF mit Dummy-Eigenschaften aus, so dass DOIF als erweitertes Eingabeelement im Frontend dienen kann.

Erste Schritte mit DOIF: Zeit- und Ereignissteuerung

Die nachfolgenden Beispiele sind aus der Einleitung der Hilfe zum DOIF entnommen. Sie werden hier weiter erläutert.

Beispiel A): Ereignissteuerung

Info green.pngHinweis: Verwendung von
  • [<Gerätename>:"<Ereignis>"] zur Abfrage eines Ereignisses von einem Gerät
  • DOELSE das Schlüsselwort leitet einen Befehlszweig ohne explizite Bedingung ein. Dieser Zweig wird ausgeführt, wenn keine geprüfte Bedingung wahr ist.
  • devStateIcon zum direkten Ausführen eines Befehls im DOIF und zur Anzeige von Icons

Aufgabenstellung:

Eine Fernbedienung soll einen Fernseher einschalten, der über eine Funksteckdose angeschlossen ist.

Das Gerät Fernbedienung wird durch den Dummy remotecontrol dargestellt. In der Realität könnte es die Definition eines Empfängers für eine Infrarot-Fernbedienung sein.

Das Gerät Funksteckdose TV wird durch den Dummy tv dargestellt. In der Realität könnte es die Definition einer Intertechno-Funkstekdose aus dem Baumarkt sein.

Die Signale von remotecontrol werden über das DOIF di_rc_tv alias Steuerlogik in einen Befehl für die Funksteckdose tv umgesetzt.

Das Signal ist als Ereignis im Eventmonitor sichtbar 2017-02-28 09:07:03 dummy tv on

Das DOIF reagiert durch die Angabe von [remotecontrol:"on"] in der Schaltbedingung. Weil on als Wert in dem Ereignis enthalten ist, wird die Bedingung wahr. Das bewirkt das Ausführen des Befehls set tv on. Danach nimmt das DOIF den Status cmd_1 an.

Falls off im Ereignis enthalten ist wird die Bedingung nicht wahr, daher wird der Befehl set tv off des DOELSE-Zweiges des DOIF ausgeführt und DOIF nimmt den Status cmd_2 an.

Definition:

define di_rc_tv DOIF ([remotecontol:"on"]) (set tv on) DOELSE (set tv off)

Über das Attribut devStateIcon können die Befehle des DOIF direkt ausgeführt werden.

attr di_rc_tv devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1

Hinweis: In neueren Versionen ggf. initialized durch initialize ersetzen.

Das erste Tripel cmd_1:general_an:cmd_2 hat die Bedeutung aktueller Status:Icon-Name:Status nach Betätigung des Icons. Also, wenn der Status cmd_2 ist, dann zeige das Icon general_an und wenn das Icon betätigt wird, dann führe den Befehl aus, der zu cmd_1 gehört.

Das zweite Tripel hat die gleiche Funktion, jedoch wird in diesem Fall das Icon general_aus angezeigt, wenn der Status des DOIF cmd_1 ist oder initialized .


Die nachstehende, komplette Definition für die Gruppe A) kann über Raw definition in FHEM importiert werden. Hinweis: In neueren Versionen ggf. initialized durch initialize ersetzen.

defmod di_rc_tv DOIF ([remotecontrol:"on"]) (set tv on) DOELSE (set tv off)
attr di_rc_tv alias Steuerlogik
attr di_rc_tv devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1
attr di_rc_tv group A) Fernbedienung (Ereignissteuerung)
attr di_rc_tv icon helper_doif
attr di_rc_tv room Schulungsraum

defmod remotecontrol dummy
attr remotecontrol alias Fernbedienung
attr remotecontrol devStateIcon .*:noIcon
attr remotecontrol group A) Fernbedienung (Ereignissteuerung)
attr remotecontrol icon it_remote
attr remotecontrol room Schulungsraum
attr remotecontrol webCmd on:off

defmod tv dummy
attr tv alias Funksteckdose TV
attr tv devStateIcon on:it_television@red off:it_television@blue
attr tv group A) Fernbedienung (Ereignissteuerung)
attr tv icon it_television
attr tv room Schulungsraum
save

Beispiel B): Zeitsteuerung

Info green.pngHinweis: Verwendung von
  • [<Zeitpunkt>|<Wochentagangabe>] zur Angabe eines Zeitpunktes mit Wochentagbeschränkung. Die Zeiten gelten für die angegebenen Wochentage.
  • DOELSEIF das Schlüsselwort leitet einen Bedingungszweig ein und muss eine Bedingung enthalten. Dieser Zweig wird ausgeführt, wenn eine Bedingung geprüft wird und sie wahr ist.
  • devStateIcon zum direkten Ausführen eines Befehls im DOIF und zur Anzeige von Icons

Aufgabenstellung:

Ein Radio soll werktags und am Wochenende zu unterschiedlichen Zeiten ein- u. ausgeschaltet werden.

Das Gerät Funksteckdose Radio wird durch den Dummy radio dargestellt. In der Realität könnte es die Definition einer Intertechno-Funkstekdose aus dem Baumarkt sein.

Wenn die Uhrzeit mit einem Schaltzeitpunkt übereinstimmt, wird die Zeitpunktangabe wahr. Wird dann auch die gesamte Bedingung wahr, dann wird der zu diesem Bedingungszweig gehörende Befehl ausgeführt. Das DOIF di_clock_radio alias Zeitschaltuhr setzt dann einen Befehl zum Schalten der Funksteckdose radio ab.

Das Zeitereignis ist im Eventmonitor nicht sichtbar.

Die Zeitpunkte eines Bedingungszweiges sind or(oder) verknüpft. Im ersten Bedingungszweig steht die Einschaltbedingung, im Zweiten (DOELSEIF) die Auschaltbedingung.

Definition:

define di_clock_radio DOIF ([06:30|Mo Di Mi] or [08:30|Do Fr Sa So]) (set radio on) DOELSEIF ([08:00|Mo Di Mi] or [09:30|Do Fr Sa So]) (set radio off)

Über das Attribut devStateIcon können die Befehle des DOIF über das WEB-Frontend unabhängig von den Schaltzeitpunkten ausgeführt werden.

attr ddi_clock_radio devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1

Hinweis: In neueren Versionen ggf. initialized durch initialize ersetzen.

Die nachstehende, komplette Definition für die Gruppe B) kann über Raw definition in FHEM importiert werden.

defmod di_clock_radio DOIF ([06:30|8] or [08:30|7]) (set radio on) DOELSEIF ([08:00|8] or [09:30|7]) (set radio off)
attr di_clock_radio alias Zeitschaltuhr
attr di_clock_radio devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1
attr di_clock_radio group B) Zeitschaltuhr (Zeitsteuerung)
attr di_clock_radio icon helper_doif
attr di_clock_radio room Schulungsraum

defmod radio dummy
attr radio alias Funksteckdose Radio
attr radio devStateIcon on:it_radio@red off:it_radio@blue
attr radio group B) Zeitschaltuhr (Zeitsteuerung)
attr radio icon it_radio
attr radio room Schulungsraum
save

Beispiel C): Kombinierte Ereignis- und Zeitsteuerung

Info green.pngHinweis: Verwendung von
  • [<Beginzeitpunkt>-<Endzeitpunkt>] zur Angabe einer Zeitspanne.
  • [<Gerätename>:<Reading-Name>] zur Abfrage eines Reading-Inhaltes.
  • < , eines numerischen Vergleichsoperators und Vergleich mit einer Konstanten (40).
  • DOELSE das Schlüsselwort leitet einen Befehlszweig ohne explizite Bedingung ein. Dieser Zweig wird ausgeführt, wenn keine geprüfte Bedingung wahr ist.
  • devStateIcon zum direkten Ausführen eines Befehls im DOIF und zur Anzeige von Icons
  • readingList, setList und webCmd zur Erzeugung eines Eingabeelementes im Frontend
  • stateFormat um einen benutzerdefinierten Status zu erzeugen.

Aufgabenstellung:

Eine Lampe soll in einer Zeispanne eingeschaltet werden, wenn die Helligkeit einen bestimmten Wert unterschreitet.

Das Gerät Lampe wird durch den Dummy lamp dargestellt. In der Realität könnte es die Definition einer funkgesteuerten Lampenfassung sein.

Das Gerät Helligkeitssensor wird durch den Dummy sensor dargestellt. In der Realität könnte es die Definition eines Homematic Funk-Lichtsensor sein oder ein selbstgebauter Helligkeitssensor mit TSL2561-Chip.

Wenn die aktuelle Uhrzeit in der angegebenen Zeitspanne liegt, ist die Zeitspanne wahr. Wenn dann auch die Helligkeit unter 40 sinkt, wird die gesamte Bedingung wahr, weil Zeitspanne und Hellikeitsvergleich and(und) verknupft sind. Der zu diesem Bedingungszweig gehörende Befehl wird dann ausgeführt. Das DOIF di_lamp alias Lampenlogik setzt dann einen Befehl zum Schalten der Lampe lamp ab. Der DOELSE-Zweig wird ausgeführt, wenn die Bedingung im ersten Zweig unwahr wird.

Definition:

define di_lamp DOIF ([06:00-19:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)

Über das Attribut devStateIcon können die Befehle des DOIF über das WEB-Frontend unabhängig von den Schaltzeitpunkten ausgeführt werden.

attr di_lamp devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1

Hinweis: In neueren Versionen ggf. initialized durch initialize ersetzen.

Das Attribut setList zusammen mit readingList und webCmd realisiert im Gerät sensor für das Reading brightness einen Schieberegler, mit dem eine Helligkeit zwischen 0 und 100 in in Schritten von 1 simuliert werden kann und der im Frontend angezeigt wird.

attr sensor readingList brightness
attr sensor setList brightness:slider,0,1,100
attr sensor webCmd brightness

Mit dem Attribut stateFormat wird im Gerät sensor das Reading brightness in den Status geschrieben. Damit wird der Helligkeitswert auch im Frontend sichtbar.

attr sensor stateFormat brightness

Die nachstehende, komplette Definition für die Gruppe C) kann über Raw definition in FHEM importiert werden. Hinweis: In neueren Versionen ggf. initialized durch initialize ersetzen.

defmod di_lamp DOIF ([06:00-19:00] and [sensor:brightness] < 40) (set lamp on) DOELSE (set lamp off)
attr di_lamp alias Lampenlogik
attr di_lamp devStateIcon cmd_1:general_an:cmd_2 cmd_2|initialized:general_aus:cmd_1
attr di_lamp group C) Kombinierte Ereignis- und Zeitsteuerung
attr di_lamp icon helper_doif
attr di_lamp room Schulungsraum

defmod lamp dummy
attr lamp alias Lampe
attr lamp group C) Kombinierte Ereignis- und Zeitsteuerung
attr lamp icon light_light
attr lamp room Schulungsraum

defmod sensor dummy
attr sensor alias Helligkeitssensor
attr sensor group C) Kombinierte Ereignis- und Zeitsteuerung
attr sensor icon message_light_intensity
attr sensor readingList brightness
attr sensor room Schulungsraum
attr sensor setList brightness:slider,0,1,100
attr sensor stateFormat brightness
attr sensor webCmd brightness
save

Ansicht der Gruppen A) bis C) im Frontend

Erste schritte DOIF.png

Links