11452 Zeichen
Score aktualisiert
100%
Code: 109661cf0ec24d39af063ced434fd046
Token in Entwicklung nicht aktualisiert
img-Tag in Entwicklung deaktiviert
Die Logik von WebUI-Programmen führt immer wieder zu Verwirrung – nicht zuletzt, weil
die Weboberfläche der CCU eine andere Logik suggeriert, als tatsächlich angewendet wird.
Ich möchte an dieser Stelle versuchen zu erläutern, was wann wie ausgeführt wird.
Man erkennt schon an der Länge dieser Seite, dass das ein etwas umfangreicheres Thema
ist.
Benennung von Systemvariablen
Prinzipiell kann man Systemvariablen – so wie allen Objekten in der CCU – beliebige
Namen geben, also z. B. auch Umlaute und Sonderzeichen verwenden. Ich empfehle jedoch,
sich auf reguläre Buchstaben (a-z, A-Z) zu beschränken: Bei Umlauten und Sonderzeichen
besteht die Gefahr, dass Systemvariablen in Scripten nicht überall gefunden werden.
„Aktualisierung“, „Änderung“ und „prüfen“
Schauen wir uns dieses einfache Beispiel-Programm an.
Der Raumthermostat, der hier in der Bedingung angegeben ist, sendet regelmäßig alle
2-3 Minuten die Temperatur an die CCU. Immer, wenn diese die Temperatur empfängt, prüft
sie, ob mindestens eine der Bedingungen für die Programmauslösung erfüllt ist.
Im Beispiel ist „bei Änderung“ ausgewählt. Die CCU meint damit aber nicht
etwa die Änderung der Temperatur, sondern nur die Änderung der Bedingung: Bei 20,0°C
ist die Bedingung nicht erfüllt, bei 20,1°C ist sie erfüllt. Das Programm wird nur
ausgeführt, wenn die Temperatur auf 20,1°C steigt.
Steigt sie weiter, ist die Bedingung weiter erfüllt – das Programm wird nicht
ausgeführt.
Sinkt sie wieder auf 20°C oder weniger, ist das zwar eine Änderung – aber die
Bedingung ist nicht mehr erfüllt, also wird das Programm auch nicht ausgeführt.
Erst wenn die Temperatur danach wieder steigt, kommt es zur Programmausführung.
bei Aktualisierung auslösen
Die Programmausführung erfolgt hier immer, wenn die Bedingung erfüllt ist – nicht nur
dann, wenn sie vorher nicht erfüllt war.
Sendet der Raumthermostat 20,1°C, wird das Programm ausgeführt.
Aktualisiert er auf einen beliebigen Wert von 20,1°C oder mehr, wird das Programm
ebenfalls ausgeführt – also beim Raumthermostat alle 2-3 Minuten.
Sinkt die Temperatur auf 20,0°C oder weniger, wird das Programm nicht mehr
ausgeführt, weil die Bedingung nicht erfüllt ist.
Diese Option dient dazu, eine Bedingung zu prüfen, ohne dass der entsprechende Kanal
das Programm selbst auslöst. Für dieses einfache Programm macht das erst mal keinen Sinn
– es würde niemals aufgrund einer Bedingung ausgeführt.
Mehrere Bedingungen
Fügt man mehrere Bedingungen ein, so werden diese natürlich alle beachtet:
Die Logik ist hier wie erwartet:
- Ist es nicht wärmer als 20.0°C, wird der „Dann“-Teil nicht ausgeführt
- Ist das Licht nicht eingeschaltet, wird der „Dann“-Teil ebenfalls nicht
ausgeführt
- Ist es wärmer als 20.0°C und das Licht ist eingeschaltet, wird der
„Dann“-Teil alle 2-3 Minuten ausgeführt, wenn der Raumthermostat einen neuen
Wert sendet.
- Wird das Licht eingeschaltet und der Raumthermostat hat zuletzt eine Temperatur von mehr
als 20.0°C gemeldet, wird der „Dann“-Teil ebenfalls ausgeführt.
Programmauslösung und Programmausführung
Was man unbedingt im Hinterkopf behalten sollte: Programmauslösung und
Programmausführung sind zwei unterschiedliche Dinge. Ich habe das Programm mal etwas
geändert:
Auf den ersten Blick würde man erwarten, dass bei Überschreiten von 20.0°C der erste
„Dann“-Teil ausgeführt wird. Wenn irgendwann die 25.0°C überschritten wurden,
dann wird bei jeder Aktualisierung der zweite „Dann“-Teil ausgeführt.
Tatsächlich wird aber bei jeder Programmauslösung – egal, von welcher Bedingung sie
angestoßen wurde – das komplette Programm ausgeführt, d.h. alle Bedingungen werden
geprüft, bis das Programm den ersten zutreffenden „Dann“-Teil ausführen kann.
- Bei Überschreiten von 20.0°C wird der erste „Dann“-Teil ausgeführt.
- Weitere Aktualisierungen bis 25.0°C führen nicht zur Programmauslösung, da es keine
passende „bei Aktualisierung“-Bedingung gibt.
- Bei Überschreiten von 25.0°C wird wieder das Programm ausgelöst. Die erste Bedingung
ist aber weiterhin zutreffend: 25,1°C sind größer als 20.0°C. Das bedeutet: Auch hier
wird der erste „Dann“-Teil ausgeführt.
- Mit jeder Aktualisierung oberhalb von 25.0°C ist die zweite Bedingung erfüllt und das
Programm wird ausgelöst. Bei jeder Ausführung ist weiterhin die erste Bedingung erfüllt
und der erste „Dann“-Teil wird ausgeführt.
Eine Bedingung reicht
Um ein WebUI-Programm auszulösen, reicht es, wenn nur eine der Bedingungen erfüllt
ist.
Das Programm wird nur durch den Raumthermostat ausgelöst. Die zweite Bedingung – ist
das Licht ausgeschaltet? – steht auf „nur prüfen“ und kann somit das Programm
nicht triggern.
Die Bedingungen für den Raumthermostat sind freilich widersprüchlich: Es kann nicht
gleichzeitig wärmer und kälter als 20.0°C sein.
Logische Folgerung: Das Programm wird nie ausgeführt, richtig? Falsch. Tatsächlich
wird das Programm alle 2-3 Minuten ausgeführt: Entweder von der ersten Bedingung, dass es
wärmer als 20.0°C ist, oder von der zweiten, dass es kälter ist. Nur bei exakt 20.0°C
passiert nichts, denn dann ist keine der beiden auslösenden Bedingungen erfüllt.
Sobald irgendeine Bedingung zutrifft, wird das gesamte Programm ausgeführt – und wenn
das Licht ausgeschaltet ist, dann ist die „nur prüfen“-Bedingung erfüllt und
der „Dann“-Teil wird ausgeführt.
Manuelle und automatische Programmausführung
Wenn ein Programm unter „Status und Bedienung“ / „Programme“
aufgerufen wird, dann wird immer der erste „Dann“-Teil ausgeführt. Das ist
wenigstens endlich mal einfach.
Wenn ein Programm automatisch ausgeführt wird, also weil eine der Bedingungen für die
Programmauslösung erfüllt ist, dann werden sämtliche Bedingungen geprüft wie im
vorherigen Abschnitt beschrieben.
Neben der Programmausführung aufgrund einer erfüllten Bedingung gibt es noch drei
weitere Gründe, warum ein Programm angestoßen wird:
- beim erst maligen Speichern eines Programms – auch, wenn ein vorhandenes Programm
überarbeitet wurde und als neues Programm gespeichert wird
- wenn das Programm in der Liste aktiviert wird (Haken bei „aktiv“ gesetzt)
- beim Neustart der CCU
Auch bei diesen automatischen Starts wird das komplette Programm ausgeführt und die
Bedingungen werden geprüft – genauso, als wäre das Programm über eine Bedingung
ausgelöst worden.
Nehmen wir ein Beispiel:
Das Programm ist eigentlich simpel:
- Wenn Sabotage erkannt wird, dann wird eine E-Mail geschickt mit dem Hinweis
„Sabotage erkannt“.
- Wenn die Sabotagemeldung aufgehoben wird, dann wird eine E-Mail mit dem Hinweis
geschickt „Sabotage wurde behoben“.
Schon beim Abspeichern stellt man fest, dass da was nicht stimmt, denn es kommt eine
E-Mail mit dem Hinweis, dass Sabotage behoben wurde – obwohl doch zuvor gar keine erkannt
war.
Das Gleiche passiert beim Neustart: Das Programm wird automatisch ausgeführt. Die
Bedingung „Sabotage“ trifft nicht zu, also wird der „Sonst“-Teil
ausgeführt.
Bei einer Infomail ist das kein Problem, aber wenn man z. B. eine Rolladensteuerung
programmiert oder Fenster und Türen mit WinMatic und KeyMatic öffnen und schließen
lässt, dann sollte man unbedingt darauf achten, dass alle Programme sich bei Neustarts in
einem definierten Zustand befinden.
Im schlimmsten Fall – wenn man z. B. einen automatischen
Neustart der CCU programmiert – kann die CCU in einer Endlos-Schleife enden, aus der
man sie nicht herausbekommt. Im Zweifelsfall sollte man daher neue Programme immer
zunächst mit ungefährlichen Aktionen erstellen und die eigentlichen Aktivitäten erst
hinterher ergänzen.
Das Zeitmodul
Um das Zeitmodul mache ich einen großen Bogen.
Das Programm im obigen Beispiel wird zu Beginn und Ende des Zeitraums ausgelöst und
dann jeweils komplett abgearbeitet. Bei der Ausführung dient der Zeitraum als Bedingung:
Innerhalb des angegebenen Bereichs (also nach dem Startzeitpunkt) ist sie erfüllt,
außerhalb (also nach dem Endzeitpunkt) nicht.
Wird das Programm durch andere Bedingungen ausgelöst, so wird der angegebene Zeitraum
genauso ausgewertet – oder auch nicht. In der Praxis kommt es gelegentlich vor, dass
Bedingungen des Zeitmoduls in unerwarteter Weise interpretiert werden, wenn das Programm
nicht durch das Modul selbst ausgelöst wurde …
Insgesamt bin ich dazu übergegangen, nicht allzu intensiv mit dem Zeitmodul zu
arbeiten. Im Gegensatz zur sonstigen WebUI-Logik bin ich mir da nie so ganz sicher, ob es
denn dann wirklich auch genau das tut, was es soll … Spätestens bei der Frage, wie ein
Programm bei einem Neustart der CCU reagiert, wird es schnell haarig.
Einfache Aufgaben – also z. B. ein Programm einmal pro Stunde starten oder auch in
anderen Programmen prüfen, ob sie z. B. tagsüber ausgelöst wurden – kann man damit
durchaus realisieren.
Was man keinesfalls tun sollte, ist mehrere Zeitmodule im selben Programm anzuwenden.
Hier würde ich den Umweg über mehrere WebUI-Programme gehen, die dann über
Systemvariablen das eigentliche Programm steuern.
Aktualisierung durch Scripte
In meinem Mini-Framework für das
E-Mail-Add-on wird der E-Mail-Versand angestoßen, sobald durch ein Programm die
Systemvariable E-Mail.Versand gesetzt wird.
Wer E-Mail.Versand über ein WebUI-Programm setzt, erlebt keine
Überraschungen: Die Systemvariable wird aktualisiert, das Programm wird ausgelöst und
die E-Mail verschickt.
Wer allerdings ein Script streng nach Scriptdokumentation von eQ-3 schreibt, steht auf
dem Schlauch: Nichts passiert. Die Systemvariable bekommt ihren Wert, aber das Programm
wird nicht ausgeführt.
Zeit, sich die Befehle zum Setzen und Auslesen von Datenpunkten näher anzuschauen.
Laut Dokumentation sollen Systemvariable über diese Funktion in Scripten geändert
werden.
Der Haken: Die Systemvariable bekommt zwar den richtigen Wert zugewiesen, gilt aber
nicht als „aktualisiert“. Programme, die durch diese Systemvariable ausgelöst
werden sollten, werden nicht ausgelöst.
gesamtes Script markieren / kopieren
dom.GetObject ("E-Mail.Subject").Variable ("Betreff");
dom.GetObject ("E-Mail.Body").Variable ("Mailkörper");
dom.GetObject ("E-Mail.Versand").Variable (1);
Nichts passiert.
In der Anfangszeit der CCU konnte man mit dieser Funktion nicht nur den aktuellen Wert
eines Datenpunktes auslesen, sondern auch Systemvariablen einen neuen zuweisen. Dabei trat
das gleiche Problem auf wie bei .Variable().
Inzwischen ist das Problem gelöst: .Value() funktioniert nicht mehr, um Werte
zu setzen.
Das ist der Weg, über den Werte gesetzt werden: Die Systemvariable wird aktualisiert
und davon abhängende Programme ausgeführt.
gesamtes Script markieren / kopieren
dom.GetObject ("E-Mail.Subject").State ("Betreff");
dom.GetObject ("E-Mail.Body").State ("Mailkörper");
dom.GetObject ("E-Mail.Versand").State (1);
.State() kann aber noch mehr: Wenn Datenpunkte von Geräten, die dauerhaft auf
Empfang sind, mit dieser Funktion abgefragt werden, dann fragt die CCU aktiv das
entsprechende Gerät nach einem aktuellen Status. Das funktioniert zum Beispiel bei
Schaltaktoren, Dimmern oder auch der WinMatic.
Ich nutze diese Eigenschaft bei meinem zweiten Script zur Behandlung von
Kommunikationsstörungen, um Geräte anzusprechen, ohne Schaltfunktionen auszulösen.
Abgesehen davon, dass diese Kommunikation ein Script natürlich ausbremst, handelt es
sich hierbei freilich um eine ganz normale Aktualisierung. Das heißt: Wenn .State()
verwendet wird, um den Status eines Kanals abzufragen, werden die von diesem Kanal
abhängigen Programme ggf. getriggert. In der Regel wird man also .Value() verwenden
wollen, um den Status eines Gerätes abzufragen.