Im ersten Teil dieser Reihe hatten wir mit Hilfe von YAKINDU Statechart Tools das Verhalten einer Jalousiesteuerung als Zustandsautomat modelliert und dabei grundlegende Elemente der Modellierungssprache kennengelernt, etwa Zustände (states), Zustandsübergänge (transitions) oder Ereignisse (events).
In diesem zweiten Teil schauen wir uns weitere Konzepte an und klären,
- wie sich Aktionen zeitgesteuert auslösen lassen,
- wie ein Zustand innere Zustände haben kann (zusammengesetzter Zustand, composite state) und
- wie verschiedene Zustandsautomaten neben- und miteinander arbeiten können (orthogonale Bereiche, orthogonal regions).
Zustandsübergänge zeitgesteuert auslösen
Der Ablauf von Zeit und das Reagieren darauf ist ein wichtiges Konzept für Zustandsautomaten. Einige Beispiele:
- Eine Ampelsteuerung gibt die jeweilige Zeitdauer von Rot-, Gelb- und Grünphase vor, entweder periodisch – also zeitgesteuert – oder ausgelöst durch Anforderungskontakte.
- In technischen Anlagen – vom Kaffeeautomaten über das Kraftfahrzeug bis zum Kernkraftwerk – sind Wartungsintervalle einzuhalten, um das ordnungsgemäße Funktionieren des Systems zu gewährleisten. Eine Wartung kann durch eine bestimmte Laufleistung der Anlage oder durch Zeitablauf ausgelöst werden, je nachdem, was früher eintritt.
- Ein Verwaltungsakt ist nach Verstreichen der Einspruchsfrist rechtswirksam, sofern der Betroffene nicht vorher Einspruch einlegt.
- In einem Datenkommunikationsverfahren mit positivem Quittierungsverfahren gilt eine Nachricht als verloren, wenn der Sender innerhalb einer vorgegebenen Zeit (Timeout) keine Empfangsquittung von der Gegenstelle erhält.
Dies alles kann man mit Hilfe von Zustandsautomaten modellieren und per Software unmittelbar steuern (Ampel, Datenkommunikation) oder unterstützen (Wartung, Verwaltungsakt).
Wir werden im Folgenden die Jalousiesteuerung aus dem ersten Teil erweitern und dazu zeitgesteuerte Ereignisse verwenden. Es war ja noch die Anforderung offen geblieben, die Jalousie in Abhängigkeit von der Umgebungshelligkeit automatisch herunter- und heraufzufahren. Scheint die Sonne hell, soll die Jalousie den Raum verdunkeln; nimmt die Helligkeit draußen ab, soll die Jalousie herauffahren.
Eine ähnliche Anforderung hatten wir bereits umgesetzt, als es darum ging, die Jalousie bei starkem Wind nach oben zu fahren, um Beschädigungen zu vermeiden. Da die Windgeschwindigkeit immer Vorrang vor Benutzerwünschen hat, war die Modellierung recht einfach und beschränkte sich auf zwei Zustandsübergänge, die bei starkem Wind auslösen, und eine zusätzliche Bedingung, die den Benutzer in diesem Fall daran hindert, die Jalousie nach unten zu fahren.
Die Steuerung der Jalousie durch die Umgebungshelligkeit ist komplexer, denn hier greifen verschiedene Einflussgrößen ineinander. Einerseits soll die Jalousiesteuerung wie beschrieben auf die Umgebungshelligkeit reagieren und die Jalousie automatisch verstellen. Andererseits sollen Benutzerwünsche berücksichtigt werden: Hätte er gern helles Sonnenlicht im Raum und fährt daher die von der Automatik heruntergefahrene Jalousie wieder hoch, dann soll die Jalousiesteuerung dies respektieren und sich mit weiteren Aktionen zurückhalten. Bedient der Benutzer die Jalousie über einen längeren Zeitraum hinweg nicht – hier kommt der Zeitaspekt ins Spiel – oder hat er den Raum womöglich längst verlassen, soll die Automatik wieder übernehmen.
Die Grundidee ist einfach und lässt sich an folgendem Zustandsautomaten erklären:
Das Zustandsdiagramm (Statechart) in Abbildung 1 beschränkt sich auf das Messen der Umgebungshelligkeit und eine entsprechende Reaktion. Initial befindet sich der Zustandsautomat im Status Sensing, in dem er kontinuierlich die Umgebungshelligkeit abfragt. Sobald die Helligkeit – enthalten in der Variable Sun.brightness – den vorgegebenen Schwellenwert Sun.BRIGHT erreicht oder überschreitet, führt der Automat die Transition Sensing → Waiting aus. Die Transition löst dabei das Event Sun.down aus, das für ein Herunterfahren der Jalousie sorgen soll.
Im Zustand Waiting geschieht weiter nichts. Der Benutzer kann die Jalousie einstellen, wie er mag, und die Automatik wird nicht eingreifen, solange Waiting aktiv ist. Das ist jedoch nicht dauerhaft der Fall: Die Transition Waiting → Sensing führt zurück in den Zustand, in dem die Steuerung misst und reagiert. Diese Transition wird "after 4 * 60 * 60 s" ausgelöst, also vier Stunden nach Aktivierung des Zustands Waiting.
Mehrere Zustandsautomaten miteinander kombinieren
Schön wäre es, wenn man diesen einfachen Zustandsautomaten mit dem im ersten Teil entwickelten kombinieren könnte und das erzeugte Event Sun.down irgendwo Auswirkungen hätte. Das sieht so aus:
Die Abbildung zeigt zwei sogenannte orthogonale Bereiche. Beide enthalten jeweils ein eigenes Zustandsdiagramm. Während der Bereich main region auf eine Benutzeraktion oder starken Wind wartet, prüft der Bereich ambient light control gleichzeitig ständig die Umgebungshelligkeit. Der Zustand des Gesamtsystems setzt sich somit aus den Zuständen seiner orthogonalen Bereiche zusammen. Völlig unabhängig sind orthogonale Bereiche aber nicht: Wenn ambient light control vom Zustand Sensing zu Waiting wechselt, erzeugt die Transition per Operator raise ein Sun.down-Ereignis, auf das der Bereich main region reagieren und die Jalousie herunterfahren soll. Damit das klappt, benötigt die Transition Idle → Moving down das Event Sun.down als weiteres auslösendes Ereignis.
Im Simulationsmodus von YAKINDU Statechart Tools kann man die Umgebungshelligkeit eingeben. Ist der Wert von Sun.brightness 80 oder höher, sieht das Ergebnis so aus:
Die Jalousie soll abhängig von der Umgebungshelligkeit aber nicht nur herunterfahren, sondern auch herauf. Wenn wir für beide Funktionen jeweils unabhängige Wartezeiten unterstützen wollen, duplizieren wir den Bereich ambient light control, passen ihn für das Unterschreiten eines Helligkeitswerts an und erweitern den Bereich main region analog um eine Reaktion auf Sun.up:
Orthogonale Bereiche führt YAKINDU Statechart Tools sequentiell innerhalb von immer wieder ablaufenden Verarbeitungszyklen aus. Das ist dann relevant, wenn der raise-Operator in einem Bereich A ein Event erzeugt, das Bereich B verarbeiten soll. Allerdings existiert jedes Event nur innerhalb des aktuellen Verarbeitungszyklus, daher muss die Ausführung von Bereich A zeitlich vor der von Bereich B erfolgen. Mehr dazu finden Sie im Kapitel “Raising and processing an event” der YAKINDU-Statechart-Tools-Dokumentation.
Zusammengesetzte Zustände
Betrachten wir nun folgendes Szenario: An einem durchweg bewölkten Tag bricht immer wieder kurz die Sonne durch, um bald darauf wieder hinter dichten Wolken zu verschwinden. In diesem Fall soll die Jalousie weder ständig herunter- und herauffahren, noch soll sie beim ersten hellen, kurzen Sonnenstrahl herunterfahren und für Stunden unten bleiben. Sie soll erst dann verdunkeln, wenn es draußen dauerhaft hell zu bleiben scheint, sprich: wenn die Umgebungshelligkeit nicht nur kurz, sondern für einige Zeit den Schwellenwert überschritten hat.
Dieses Verhalten modellieren wir gemäß Abbildung 5 wie folgt: Liegt die Umgebungshelligkeit unterhalb des Schwellenwerts, ist der Zustand Not bright aktiv. Überschreitet sie den Schwellenwert, wechselt der Automat in den Zustand Almost bright. Will sagen: Es ist draußen zwar hell, aber wir sind uns nicht sicher, ob das länger so bleibt. Wir warten daher noch ein wenig ab, bevor wir die Jalousie herunterfahren. Solange wir im Zustand Almost bright sind und die Umgebungshelligkeit unter den Schwellenwert sinkt, weil sich eine Wolke vor die Sonne schiebt, geht es sofort nach Not bright zurück, um womöglich kurz darauf wieder zu Almost bright zu springen. Erst dann, wenn Almost bright 10 Minuten lang ohne Unterbrechung aktiv ist, wird die nach Waiting führende Transition ausgelöst und die Jalousie heruntergefahren. Das funktioniert, weil der als Operand von after angegebene Zeitraum jedesmal neu beginnt, wenn der Quellzustand der Transition aktiv wird.
Abbildung 5 zeigt zudem eine äußerst nützliche Möglichkeit, Zustandsdiagramme überschaubar und strukturiert zu halten: den zusammengesetzten Zustand. Je mehr Zustände und Transitionen ein Automat enthält, desto unübersichtlicher wird die grafische Darstellung, die doch gerade für Anschaulichkeit sorgen sollte. Es fällt schwer, das Ganze im Blick zu behalten und Strukturen und logische Zusammenhänge zu erkennen. Spätestens bei Zustandsdiagrammen mit Hunderten oder Tausenden von Zuständen wird das völlig unmöglich.
Zusammengesetzte Zustände (composite states) bringen Struktur und Modularisierung ins Diagramm. Ein zusammengesetzter Zustand enthält innere Zustände und Zustandsübergänge und kann auf diese Weise Funktionalität kapseln. Im Beispiel der Jalousiesteuerung steckt die Funktionalität der verzögerten Verdunklung im zusammengesetzten Zustand Sensing. Eine Transition kann zu einem zusammengesetzten Zustand als solchem führen, aber auch unmittelbar zu einem seiner inneren Zustände. Die Transition Waiting → Sensing zeigt ein Beispiel für Ersteres. Das Verlassen eines zusammengesetzten Zustands kann per Transition von einem inneren Zustand zu einem außerhalb des zusammengesetzten Zustands liegenden Zustand erfolgen, siehe Almost bright → Waiting. Aber auch der zusammengesetzte Zustand als solcher kann als Ausgangspunkt einer Transition dienen. Eine solche Transition wird dann ausgelöst, wenn die Ausführung des zusammengesetzten Zustandes einen finalen Zustand oder einen Exit-Knoten erreicht. Unser Beispiel geht darauf nicht weiter ein; wer mehr wissen will, wird im Artikel "Advanced state machine modeling with entry, exit and final states” fündig.
Der zusammengesetzte Zustand Sensing enthält nur einen einzigen Bereich. Zusammengesetzte Zustände können aber durchaus mehrere orthogonale Bereichen umfassen, wie wir sie bereits auf der obersten Modellebene kennengelernt haben.
Mit YAKINDU Statechart Tools kann der Anwender die Darstellung weiter vereinfachen, indem er die Innereien eines zusammengesetzten Zustands in einem Subdiagramm versteckt. Das sieht dann so aus:
Sensing sieht nun fast so aus wie ein "normaler" Zustand. Nur noch das kleine Symbol rechts unten im Zustand zeigt an, dass es sich um einen zusammengesetzten Zustand handelt. Diese Art der Darstellung spart viel Platz. Mehr dazu im Kapitel “Using subdiagrams” der YAKINDU-Statechart-Tools-Dokumentation.
Die grafische Modellierungssprache von YAKINDU Statechart Tools erlaubt den Eintritt in zusammengesetzte Zustände über beliebig viele benannte Eintrittspunkte (Entries) und das Verlassen über ebenfalls beliebig viele benannte Austrittspunkte (Exits). Im Sinne von Übersicht und Verständlichkeit sollte man die Anzahl dieser Eintritts- und Austrittspunkte sowie die Anzahl der hinein- und herausführenden Transitionen möglichst gering halten.
Weitere Verbesserungsmöglichkeiten des Modells
Das Verhalten der Jalousiesteuerung bei Änderungen der Umgebungshelligkeit lässt sich weiter verbessern. Statt nach jedem automatischen Herauf- oder Herunterfahren eine längere Zeit abzuwarten, ohne Rücksicht darauf zu nehmen, ob jemand anwesend ist, der die Jalousiestellung ändern möchte, wäre es flexibler und komfortabler, die Automatik nur dann für einige Zeit ruhen zu lassen, wenn der Benutzer tatsächlich die[↑]- oder [↓]-Taste drückt.
In diesem Zusammenhang könnte man auch gleich die beiden orthogonalen Bereiche ambient light control 1 und ambient light control 2 zu einem einzigen Bereich zusammenfassen und den Automaten so vereinfachen. Wie das geht, sei dem Leser als Übung überlassen.
Im dritten Teil dieser Reihe werde ich zeigen, wie sich Zustandsautomaten in andere Darstellungsformen übersetzen lassen, zum Beispiel in Quellcode einer Programmiersprache. Wir werden zumindest im Prinzip sehen, wie man den von YAKINDU Statechart Tools generierten Quellcode in eine Umgebung integriert, um echte Lichtsensoren abzufragen und echte Motoren anzusteuern.
Übrigens: Die komplette Blogserie "Modellieren mit Zustandsautomaten" bieten als kostenloses Whitepaper zum Download an.
Kommentare