Das Thema wurde schon oft diskutiert. Zuletzt wieder hier. An Beschreibungen herrscht kein Mangel (z.B. hier). Die Frage ist: Wie kann man das möglichst einfach (aber doch korrekt) erklären?
Update 21.2.2019: Testfall 6 und 7 im Skript ergänzt,
Update 27.2.2019: Auslösebedingung exakter beschrieben
Update 5.3. 2019: Auslösebedingung im Beispiel rot markiert
Also mal ein neuer Ansatz. Nicht beschreiben, sondern am "lebenden Objekt" zeigen.
Dazu habe ich
- Systemvariablen angelegt _test_var1 - _test_var3 (jeweils integer) sowie Trace (string)
- Ein Skript mit Testfällen erstellt, das den _test_var unterschiedliche Werte zuweist
Code: Alles auswählen
! Testscript: manuell starten! ! . ! Testfall 1 ! . WriteLine("Testfall 1: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen dom.GetObject("_test_var2").State(1); WriteLine("_test_pgm: Auslöser _test_var1, var2=1, var3=0"); dom.GetObject("_test_var1").State(1); ! Ergebnis ausgeben - die wiederholten GetObject Anweisungen dienen nur dazu, dass nach dem Auslösen ! des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im ! WriteLine weiter unten ausgegeben wird. dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 2a ! . WriteLine("Testfall 2a: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen dom.GetObject("_test_var2").State(2); WriteLine("Auslöser _test_var1, var2=2, var3=0"); dom.GetObject("_test_var1").State(1); ! Ergebnis ausgeben dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 2b ! . WriteLine("Testfall 2b: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen dom.GetObject("_test_var2").State(2); WriteLine("Auslöser _test_var3"); dom.GetObject("_test_var3").State(1); ! Ergebnis ausgeben dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 3 ! . WriteLine("Testfall 3: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen dom.GetObject("_test_var2").State(3); WriteLine("Auslöser _test_var3, var1=0, var2=3"); dom.GetObject("_test_var3").State(1); ! Ergebnis ausgeben dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 5 ! . WriteLine("Testfall 5: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen WriteLine("Auslöser _test_var1, var2=0, var3=0"); dom.GetObject("_test_var1").State(1); ! Ergebnis ausgeben dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 5b ! . WriteLine("Testfall 5b: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("_test_var2").State(0); dom.GetObject("_test_var3").State(0); dom.GetObject("Trace").State("none"); ! Programm _test_pgm auslösen WriteLine("Auslöser _test_var3, var2=1, var3=0"); dom.GetObject("_test_var2").State(1); dom.GetObject("_test_var3").State(1); ! Ergebnis ausgeben dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 5c ! . WriteLine("Testfall 5c: "); ! reset dom.GetObject("Trace").State("none"); ! Auslöservariable auf irgendeinen wert ändern WriteLine("test_var1=57, var2=1, var3=0"); dom.GetObject("_test_var1").State(57); ! Ergebnis ausgeben - die wiederholten GetObject Anweisungen dienen nur dazu, dass nach dem Auslösen ! des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im ! WriteLine weiter unten ausgegeben wird. dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! Testscript: manuell starten! ! . ! Testfall 6 ! . WriteLine("Testfall 6: "); ! Reset dom.GetObject("_test_var1").State(0); dom.GetObject("Trace").State(""); ! Programm _test_pgm_sonst auslösen dom.GetObject("_test_var1").State(150); WriteLine("Auslöser _test_var1=150"); ! Ergebnis ausgeben - die wiederholten GetObejt Anweisungen dienen nur dazu, dass nach dem Auslösen ! des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im ! WriteLine weiter unten ausgegeben wird. dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! . ! Testfall 7 ! . WriteLine("Testfall 7: "); ! Programm _test_pgm_sonst auslösen dom.GetObject("_test_var1").State(300); WriteLine("Auslöser _test_var1=300"); ! Ergebnis ausgeben - die wiederholten GetObejt Anweisungen dienen nur dazz, dass nach dem Auslösen ! des Programms ein wenig Zeit vergeht, damit das Programm die Trace Variable setzen kann, bevor sie im ! WriteLine weiter unten ausgegeben wird. dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); dom.GetObject("Trace").Value(); WriteLine("Testergebnis: "#dom.GetObject("Trace").Value()); ! .
- zwei Programme erstellt, die durch Werteänderungen von _test_var1 und _test_var3 ausgelöst werden.
- Dann mit "Skript Testen" das Skript laufen lassen.
Code: Alles auswählen
Testfall 1:
_test_pgm: Auslöser _test_var1, var2=1, var3=0
Testergebnis: _test: 1. Dann... (_test_var2=1)
Testfall 2a:
Auslöser _test_var1, var2=2, var3=0
Testergebnis: _test: 2. Sonst, wenn... _test_var2 =2
Testfall 2b:
Auslöser _test_var3
Testergebnis: _test: 2. Sonst, wenn... _test_var2 =2
Testfall 3:
Auslöser _test_var3, var1=0, var2=3
Testergebnis: _test: 3. Sonst, wenn... (_test_var2 = egal) =1
Testfall 5:
Auslöser _test_var1, var2=0, var3=0
Testergebnis: _test: 5. Sonst... (Zweig ohne Bedingungen)
Testfall 5b:
Auslöser _test_var3, var2=1, var3=0
Testergebnis: _test: 5. Sonst... (Zweig ohne Bedingungen)
Testfall 5c:
test_var1=57, var2=1, var3=0
Testergebnis: none
Testfall 6:
Auslöser _test_var1=150
Testergebnis: _test_pgm_sonst: Aktivität:Dann durchlaufen
Testfall 7:
Auslöser _test_var1=300
Testergebnis: _test_pgm_sonst: Aktivität:Sonst durchlaufen
Als Erklärung, warum das alles so ist, am Ende doch noch der Versuch einer möglichst kurzen Beschreibung. Unterscheide zwischen
- dem Ereignis (Auslöser)
- der Bedingung, ob ein Programm ausgelöst(gestartet) wird (Auslösebedingung) und
- den Bedingungen, die steuern welcher "Aktivität:"-Block im Programm ausgeführt wird (Auswahlbedingung)
- Programme werden ausgelöst, wenn sie entweder
- manuell (übers WebUI) gestartet werden,
- wenn die CCU neu gestartet wird **) oder
- wenn irgendeine im Programm angegebene Auslösebedingung *) zutrifft. Das kann die Änderung einer Systemvariaben, die kein String ist (wie im Beispiel oben) sein, die Änderung eines Geräte-Datenpunkts oder eine Zeit-Steuerung . Das _test_pgm wird also ausgelöst wenn sich entweder _test_var1 oder _test_var3 ändert
- Es ist egal wo, also in welchem "Bedingung:"-Abschnitt eine Auslösebedingung steht. Sie kann also auch unterhalb des "Aktivität: Dann..."-Blocks stehn, der zur Ausführung kommt bzw. in irgend einem "Bedingung: "-Block stehen. Siehe Testfall 2b
- Nach dem Starten/Auslösen des Programms wird der erste (und kein weiterer!) "Aktivität: Dann..."- Block ausgeführt für den die Auswahlbedingungen (im obigen Beispiel grün eingerahmt) in dem unmittelbar davor stehenden "Bedingung:"-Block zutreffen **).
- Das sind neben "nur prüfen"-Bedingungen auch Bedingungen die in der selben Zeile wie ein Auslöser stehen (oben z.B. "im Wertebereich von bis").
- AUSNAHME: Wird das Programm manuell gestartet/ausgelöst dann wird immer der erste "Aktivität: Dann..."- Block ausgeführt, egal welche Auslöse- oder Auswahlbedingungen davor stehen.
- Alle anderen "Aktivität: Dann..."-Blöcke werden nicht durchlaufen. Es gibt also keine geschachtelten IF's wie in anderen Programmiersprachen.
- Wird das Programm zwar ausgelöst, aber es trifft keine Auswahlbedingung für einen "Aktivität: Dann..."-Block zu, dann wird der "Aktivität: Sonst..."-Block durchlaufen
**) Beim Neustarten der CCU werden vor dem Auslösen von Programmen alle Systemvariablen und Datenpunkte (Status von Geräten) auf den zuletzt bekannten Zustand gesetzt. Ausnahme ist die Systemvariable "Anwesenheit": diese wird immer auf "wahr" gesetzt. Das kann man dazu verwenden, um zu verhindern, dass ein "Aktivität:"-Block bei Neustart ausgeführt wird (siehe z.B. hier).
gzi