From: Benjamin Braatz Date: Mon, 22 Mar 2021 08:51:23 +0000 (+0100) Subject: Improve example in conf.json and index.md. X-Git-Tag: v0.3.0~40 X-Git-Url: http://git.graph-it.com/?a=commitdiff_plain;h=79dd31ae8ba1c0f3834bc656986208d3e2a87a8d;p=graphit%2Fcontrolpi.git Improve example in conf.json and index.md. --- diff --git a/conf.json b/conf.json index 0e27b04..7ab4622 100644 --- a/conf.json +++ b/conf.json @@ -2,100 +2,85 @@ "Example State": { "plugin": "State" }, - "WaitCheck": { - "plugin": "Wait", - "seconds": 1.0 + "Example GenericWait": { + "plugin": "GenericWait" }, - "TriggerStateCheck": { + "Trigger Wait Check": { "plugin": "Alias", "from": { - "sender": { "const": "WaitCheck" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Check" }, "event": { "const": "finished" } }, "to": { - "target": "Example State", - "command": "get state" + "target": "Example GenericWait", "seconds": 1.0, + "id": "Check", "command": "wait" } }, - "TriggerWaitCheck": { + "Trigger State Check": { "plugin": "Alias", "from": { - "sender": { "const": "WaitCheck" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Check" }, "event": { "const": "finished" } }, "to": { - "target": "WaitCheck", - "command": "wait" + "target": "Example State", "command": "get state" } }, - "WaitOn": { - "plugin": "Wait", - "seconds": 1.5 - }, - "TriggerStateOnOff": { + "Trigger Wait On Off": { "plugin": "Alias", "from": { - "sender": { "const": "WaitOn" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "On" }, "event": { "const": "finished" } }, "to": { - "target": "Example State", - "command": "set state", - "new state": false + "target": "Example GenericWait", "seconds": 1.5, + "id": "Off", "command": "wait" } }, - "TriggerWaitOnOff": { + "Trigger Wait Off On": { "plugin": "Alias", "from": { - "sender": { "const": "WaitOn" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Off" }, "event": { "const": "finished" } }, "to": { - "target": "WaitOff", - "command": "wait" + "target": "Example GenericWait", "seconds": 1.5, + "id": "On", "command": "wait" } }, - "WaitOff": { - "plugin": "Wait", - "seconds": 1.5 - }, - "TriggerStateOffOn": { + "Trigger State On Off": { "plugin": "Alias", "from": { - "sender": { "const": "WaitOff" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "On" }, "event": { "const": "finished" } }, "to": { - "target": "Example State", - "command": "set state", - "new state": true + "target": "Example State", "command": "set state", + "new state": false } }, - "TriggerWaitOffOn": { + "Trigger State Off On": { "plugin": "Alias", "from": { - "sender": { "const": "WaitOff" }, - "event": { "const": "finished" } + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Off" }, "event": { "const": "finished" } }, "to": { - "target": "WaitOn", - "command": "wait" + "target": "Example State", "command": "set state", + "new state": true } }, "Test Procedure": { "plugin": "Init", "messages": [ - { "event": "started" }, - { "target": "WaitOff", "command": "wait" }, - { "target": "WaitCheck", "command": "wait" }, - { "event": "stopped" } + { "target": "Example GenericWait", "seconds": 1.5, + "id": "Off", "command": "wait" }, + { "target": "Example GenericWait", "seconds": 1.0, + "id": "Check", "command": "wait" } ] }, "Debug Logger": { - "plugin": "Log", - "filter": [ - {} - ] + "plugin": "Log", "filter": [{}] }, "State Change Logger": { "plugin": "Log", diff --git a/doc/index.md b/doc/index.md index e99e8ba..eb1e6d1 100644 --- a/doc/index.md +++ b/doc/index.md @@ -122,264 +122,273 @@ Die Beispiel-Konfiguration sieht folgendermaßen aus: }, ``` Ein `State`-Plugin speichert intern einen Booleschen Wert (`True` oder -`False`) und stellt Kommandos `get state` und `set state` zur Verfügung, um -diesen Wert abzufragen oder zu ändern und reagiert darauf durch das Senden -von `state`-Ereignissen. +`False`) und stellt Kommandos `"get state"` und `"set state"` zur +Verfügung, um diesen Wert abzufragen oder zu ändern und reagiert darauf +durch das Senden von `"state"`-Ereignissen. ```json - "WaitCheck": { - "plugin": "Wait", - "seconds": 1.0 + "Example GenericWait": { + "plugin": "GenericWait" }, - "TriggerStateCheck": { +``` +Ein `GenericWait`-Plugin reagiert auf `"wait"`-Kommandos, die Schlüssel +`"seconds"` und `"id"` enthalten, indem es die angegebene Anzahl Sekunden +wartet und dann ein `"finished"`-Ereignis mit dem angegebenen `"id"`-String +sendet. + +```json + "Trigger Wait Check": { "plugin": "Alias", - "from": { "sender": "WaitCheck", "event": "finished" }, - "to": { "target": "Example State", "command": "get state" } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Check" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example GenericWait", "seconds": 1.0, + "id": "Check", "command": "wait" + } }, - "TriggerWaitCheck": { +``` +In der Beispiel-Konfiguration verwenden wir `Alias`-Instanzen, um bei +Ablauf verschiedener Wartezeiten Aktionen auszulösen. +Hier wird bei Ablauf einer Wartezeit mit `"id": "Check"` sofort eine neue +Wartezeit von einer Sekunde mit der gleichen `"id"` gestartet. + +```json + "Trigger State Check": { "plugin": "Alias", - "from": { "sender": "WaitCheck", "event": "finished" }, - "to": { "target": "WaitCheck", "command": "wait" } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Check" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example State", "command": "get state" + } }, ``` -Ein `Wait`-Plugin stellt ein Kommando `wait` zur Verfügung und wartet nach -Erhalt dieses Kommandos die in der Konfiguration angegebene Zahl an -Sekunden, bevor es ein `finished`-Ereignis sendet. Die beiden -`Alias`-Plugin-Instanzen übersetzen dieses Ereignis zum Einen in eine -Abfrage an das `State`-Plugin nach seinem momentanen Zustand, zum Anderen -in einen neuen Start des `Wait`-Plugins selbst. Es wird also im Endeffekt -jede Sekunde einmal der Zustand des `State`-Plugins abgefragt. +Außerdem wird bei Ablauf von `"id": "Check"` einmal der momentane Zustand +von `"Example State"` mit `"get state"` abgefragt. +Es wird also im Endeffekt jede Sekunde einmal der Zustand des +`State`-Plugins abgefragt. Statt `Alias`-Instanzen zu verwenden, um Ereignisse direkt in Kommandos anderer (oder desselben) Plugins zu übersetzen, werden im Paket -[controlpi-statemachine](https://docs.graph-it.com/graphit/controlpi-statemachine) +[controlpi-statemachine](https://docs.graph-it.com/graphit/controlpi-statemachine/) Zustands-Maschinen zur Verfügung gestellt, mit denen sich komplexere Verschaltungen eleganter konfigurieren lassen. ```json - "WaitOn": { - "plugin": "Wait", - "seconds": 1.5 - }, - "TriggerStateOnOff": { + "Trigger Wait On Off": { "plugin": "Alias", - "from": { "sender": "WaitOn", "event": "finished" }, - "to": { "target": "Example State", "command": "set state", "new state": false } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "On" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example GenericWait", "seconds": 1.5, + "id": "Off", "command": "wait" + } }, - "TriggerWaitOnOff": { + "Trigger Wait Off On": { "plugin": "Alias", - "from": { "sender": "WaitOn", "event": "finished" }, - "to": { "target": "WaitOff", "command": "wait" } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Off" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example GenericWait", "seconds": 1.5, + "id": "On", "command": "wait" + } }, - "WaitOff": { - "plugin": "Wait", - "seconds": 1.5 - }, - "TriggerStateOffOn": { +``` +Mit diesen beiden `Alias`-Instanzen wird dafür gesorgt, dass bei Ablauf +einer `"On"`-Wartezeit eine `"Off"`-Wartezeit von anderthalb Sekunden +gestartet wird und umgekehrt. + +```json + "Trigger State On Off": { "plugin": "Alias", - "from": { "sender": "WaitOff", "event": "finished" }, - "to": { "target": "Example State", "command": "set state", "new state": true } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "On" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example State", "command": "set state", + "new state": false + } }, - "TriggerWaitOffOn": { + "Trigger State Off On": { "plugin": "Alias", - "from": { "sender": "WaitOff", "event": "finished" }, - "to": { "target": "WaitOn", "command": "wait" } + "from": { + "sender": { "const": "Example GenericWait" }, + "id": { "const": "Off" }, "event": { "const": "finished" } + }, + "to": { + "target": "Example State", "command": "set state", + "new state": true + } }, ``` -Mit `WaitOn` und `WaitOff` werden zwei `Wait`-Instanzen so konfiguriert, -dass sie sich gegenseitig aufrufen, wobei die eine den Zustand der -`State`-Instanz auf `False`, die andere dann wieder auf `True` setzt. +Bei Ablauf einer `"On"`-Wartezeit wird `"Example State"` mit `"set state"` +ausgeschaltet, bei Ablauf von `"Off"` eingeschaltet. +Zusammen sorgt dies dafür, dass `"Example State"` alle anderthalb Sekunden +den Zustand wechelt. ```json "Test Procedure": { "plugin": "Init", "messages": [ - { "event": "started" }, - { "target": "WaitOff", "command": "wait" }, - { "target": "WaitCheck", "command": "wait" }, - { "event": "stopped" } + { "target": "Example GenericWait", "seconds": 1.5, + "id": "Off", "command": "wait" }, + { "target": "Example GenericWait", "seconds": 1.0, + "id": "Check", "command": "wait" } ] }, ``` `Init`-Instanzen senden einfach am Beginn der Ausführung des -ControlPi-Systems eine konfigurierte Liste von Nachrichten. Hier werden die -beiden `Wait`-Instanzen für das Setzen und das Auslesen des -`State`-Zustandes (die sich danach endlos selbst auslösen) das erste Mal -angestoßen. +ControlPi-Systems eine konfigurierte Liste von Nachrichten. +Hier werden eine erste `"Off"`- und eine erste `"Check"`-Wartezeit +gestartet, die sich durch die oben beschriebenen `Alias`-Instanzen dann +endlos selbst auslösen. ```json "Debug Logger": { - "plugin": "Log", - "filter": [ - {} - ] + "plugin": "Log", "filter": [{}] }, "State Change Logger": { "plugin": "Log", "filter": [ - { "sender": "Example State", "event": "changed" } + { + "sender": { "const": "Example State" }, + "event": { "const": "changed" } + } ] } } ``` `Log`-Instanzen geben einfach durch einen konfigurierten Filter bestimmte Nachrichten auf der Konsole (oder, falls das System als systemd-Unit läuft, -im System-Journal) aus. Hier wird eine Instanz `Debug Logger`, die alle -Nachrichten ausgibt, und eine Instanz `State Change Logger`, die nur -Nachrichten der `State`-Instanz und diese auch nur, wenn eine Änderung -stattgefunden hat, ausgibt, konfiguriert. +im System-Journal) aus. +Hier wird eine Instanz `"Debug Logger"`, die alle Nachrichten ausgibt, und +eine Instanz `"State Change Logger"`, die nur `"changed"`-Ereignisse der +`State`-Instanz ausgibt, konfiguriert. Die Ausgabe eines Laufs dieses Beispiel-Systems sieht folgendermaßen aus: ``` $ python -m controlpi conf.json -State 'Example State' configured. -Wait 'WaitCheck' configured. -Alias 'TriggerStateCheck' configured. -Alias 'TriggerWaitCheck' configured. -Wait 'WaitOn' configured. -Alias 'TriggerStateOnOff' configured. -Alias 'TriggerWaitOnOff' configured. -Wait 'WaitOff' configured. -Alias 'TriggerStateOffOn' configured. -Alias 'TriggerWaitOffOn' configured. -Init 'Test Procedure' configured. -Log 'Debug Logger' configured. -Log 'State Change Logger' configured. -``` -Zunächst melden alle konfigurierten Plugin-Instanzen, dass sie ihre -jeweilige Konfiguration eingelesen und verarbeitet haben. - -``` -State 'Example State' running. -Wait 'WaitCheck' running. -Alias 'TriggerStateCheck' running. -Alias 'TriggerWaitCheck' running. -Wait 'WaitOn' running. -Alias 'TriggerStateOnOff' running. -Alias 'TriggerWaitOnOff' running. -Wait 'WaitOff' running. -Alias 'TriggerStateOffOn' running. -Alias 'TriggerWaitOffOn' running. -Init 'Test Procedure' running. -Log 'Debug Logger' running. -Log 'State Change Logger' running. -``` -Dann melden wiederum alle, dass ihre Haupt-Routinen jetzt laufen. Bis auf -die `Init`-Instanz, die die konfigurierten Nachrichten in dieser -Hauptroutine abschickt, haben alle bisher gezeigten Plugins leere -Haupt-Routinen, da ihr Verhalten nur als Reaktion auf empfangene -Nachrichten stattfindet. - -``` -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'Example State', - 'sends': [{'event': 'changed', 'state': ""}, - {'state': ""}], - 'receives': [{'target': 'Example State', 'command': 'get state'}, - {'target': 'Example State', 'command': 'set state', - 'new state': ""}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'WaitCheck', - 'sends': [{'event': 'finished'}], - 'receives': [{'target': 'WaitCheck', 'command': 'wait'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerStateCheck', - 'sends': [{'target': 'Example State', 'command': 'get state'}], - 'receives': [{'sender': 'WaitCheck', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerWaitCheck', - 'sends': [{'target': 'WaitCheck', 'command': 'wait'}], - 'receives': [{'sender': 'WaitCheck', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'WaitOn', - 'sends': [{'event': 'finished'}], - 'receives': [{'target': 'WaitOn', 'command': 'wait'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerStateOnOff', - 'sends': [{'target': 'Example State', 'command': 'set state', 'new state': False}], - 'receives': [{'sender': 'WaitOn', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerWaitOnOff', - 'sends': [{'target': 'WaitOff', 'command': 'wait'}], - 'receives': [{'sender': 'WaitOn', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'WaitOff', - 'sends': [{'event': 'finished'}], - 'receives': [{'target': 'WaitOff', 'command': 'wait'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerStateOffOn', - 'sends': [{'target': 'Example State', 'command': 'set state', 'new state': True}], - 'receives': [{'sender': 'WaitOff', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'TriggerWaitOffOn', - 'sends': [{'target': 'WaitOn', 'command': 'wait'}], - 'receives': [{'sender': 'WaitOff', 'event': 'finished'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'Test Procedure', - 'sends': [{'event': 'started'}, {'event': 'stopped'}, - {'target': 'WaitCheck', 'command': 'wait'}, - {'target': 'WaitOff', 'command': 'wait'}, - {'target': 'Test Procedure', 'command': 'execute'}], - 'receives': [{'target': 'Test Procedure', 'command': 'execute'}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'Debug Logger', - 'sends': [], 'receives': [{}]} -Debug Logger: {'sender': '', 'event': 'registered', 'client': 'State Change Logger', - 'sends': [], 'receives': [{'sender': 'Example State', 'event': 'changed'}]} +Debug Logger: {'sender': '', 'event': 'registered', + 'client': 'Example State', 'plugin': 'State', + 'sends': [{'event': {'const': 'changed'}, + 'state': {'type': 'boolean'}}, + {'state': {'type': 'boolean'}}], + 'receives': [{'target': {'const': 'Example State'}, + 'command': {'const': 'get state'}}, + {'target': {'const': 'Example State'}, + 'command': {'const': 'set state'}, + 'new state': {'type': 'boolean'}}]} +... +Debug Logger: {'sender': '', 'event': 'registered', + 'client': 'State Change Logger', 'plugin': 'Log', + 'sends': [], + 'receives': [{'sender': {'const': 'Example State'}, + 'event': {'const': 'changed'}}]} ``` Die Instanz `Debug Logger` zeigt uns alle im System verschickten -Nachrichten an. Zunächst meldet der Nachrichten-Bus selbst alle -Registrierungen der konfigurierten Plugins als Klienten des Busses. In -unserem Fall gibt es für jedes Plugin genau einen Klienten. Für komplexere -Plugins kann es aber durchaus mehrere (oder keine) Klienten für ein Plugin -geben, beispielsweise für jede gerade offfene Verbindung zu einer -Netzwerkschnittstelle. - -``` -Debug Logger: {'sender': 'Test Procedure', 'target': 'Test Procedure', 'command': 'execute'} -Debug Logger: {'sender': 'Test Procedure', 'event': 'started'} -Debug Logger: {'sender': 'Test Procedure', 'target': 'WaitOff', 'command': 'wait'} -Debug Logger: {'sender': 'Test Procedure', 'target': 'WaitCheck', 'command': 'wait'} -Debug Logger: {'sender': 'Test Procedure', 'event': 'stopped'} -``` -Die `Init`-Instanz `Test Procedure` hat alle ihre Nachrichten gesendet und -sie wurden von `Debug Logger` empfangen. - -``` -Debug Logger: {'sender': 'WaitCheck', 'event': 'finished'} -Debug Logger: {'sender': 'TriggerStateCheck', 'target': 'Example State', 'command': 'get state'} -Debug Logger: {'sender': 'TriggerWaitCheck', 'target': 'WaitCheck', 'command': 'wait'} +Nachrichten an. +Zunächst meldet der Nachrichten-Bus selbst alle Registrierungen der +konfigurierten Plugins als Klienten des Busses mit den jeweils für sie +registrierten gesendeten und empfangenen Nachrichten-Vorlagen. +In unserem Fall gibt es für jedes Plugin genau einen Klienten. +Für komplexere Plugins kann es aber durchaus mehrere (oder keine) Klienten +für ein Plugin geben, beispielsweise für jede gerade offfene Verbindung zu +einer Netzwerkschnittstelle. + +``` +Debug Logger: {'sender': 'Test Procedure', 'target': 'Example GenericWait', + 'seconds': 1.5, 'id': 'Off', 'command': 'wait'} +Debug Logger: {'sender': 'Test Procedure', 'target': 'Example GenericWait', + 'seconds': 1.0, 'id': 'Check', 'command': 'wait'} +``` +Die `Init`-Instanz `"Test Procedure"` sendet ihre beiden konfigurierten +Nachrichten und startet damit sowohl die erste `"Off"`- als auch die erste +`"Check"`-Wartezeit. + +``` +Debug Logger: {'sender': 'Example GenericWait', + 'event': 'finished', 'id': 'Check'} +Debug Logger: {'sender': 'Trigger Wait Check', + 'target': 'Example GenericWait', 'seconds': 1.0, + 'id': 'Check', 'command': 'wait'} +Debug Logger: {'sender': 'Trigger State Check', + 'target': 'Example State', 'command': 'get state'} Debug Logger: {'sender': 'Example State', 'state': False} ``` -Nach einer Sekunde ist die Wartezeit der `Wait`-Instanz `WaitCheck` das -erste Mal abgelaufen und daraufhin werden auch die beiden -`Alias`-Nachrichten geschickt, woraufhin `Example State' mit seinem -momentanen Zustand (aber auch mit der Information, dass dieser sich nicht -geändert hat) antwortet. - -``` -Debug Logger: {'sender': 'WaitOff', 'event': 'finished'} -Debug Logger: {'sender': 'TriggerStateOffOn', 'target': 'Example State', - 'command': 'set state', 'new state': True} -Debug Logger: {'sender': 'TriggerWaitOffOn', 'target': 'WaitOn', 'command': 'wait'} -Debug Logger: {'sender': 'Example State', 'event': 'changed', 'state': True} -State Change Logger: {'sender': 'Example State', 'event': 'changed', 'state': True} -``` -Eine weitere halbe Sekunde später sorgt der Ablauf der Instanz `WaitOff` -dafür, dass `Example State` auf `True` gesetzt wird. Hier reagiert jetzt -auch der `State Change Logger`. - -``` -Debug Logger: {'sender': 'WaitCheck', 'event': 'finished'} -Debug Logger: {'sender': 'TriggerStateCheck', 'target': 'Example State', 'command': 'get state'} -Debug Logger: {'sender': 'TriggerWaitCheck', 'target': 'WaitCheck', 'command': 'wait'} +Nach einer Sekunde ist die `"Check"`-Wartezeit das erste Mal abgelaufen. +Sie wird durch die erste ihrer `Alias`-Instanzen sofort neu gestartet. +Durch die zweite `Alias`-Instanz wird der momentane Zustand von +`"Example State"` abgefragt, der dann antwortet. + +``` +Debug Logger: {'sender': 'Example GenericWait', + 'event': 'finished', 'id': 'Off'} +Debug Logger: {'sender': 'Trigger Wait Off On', + 'target': 'Example GenericWait', 'seconds': 1.5, + 'id': 'On', 'command': 'wait'} +Debug Logger: {'sender': 'Trigger State Off On', + 'target': 'Example State', 'command': 'set state', + 'new state': True} +Debug Logger: {'sender': 'Example State', + 'event': 'changed', 'state': True} +State Change Logger: {'sender': 'Example State', + 'event': 'changed', 'state': True} +``` +Eine halbe Sekunde später sorgt der Ablauf der `"Off"`-Wartezeit dafür, +dass `"Example State"` auf `True` gesetzt wird. +Hier reagiert jetzt auch der `"State Change Logger"`. + +``` +Debug Logger: {'sender': 'Example GenericWait', + 'event': 'finished', 'id': 'Check'} +Debug Logger: {'sender': 'Trigger Wait Check', + 'target': 'Example GenericWait', 'seconds': 1.0, + 'id': 'Check', 'command': 'wait'} +Debug Logger: {'sender': 'Trigger State Check', + 'target': 'Example State', 'command': 'get state'} Debug Logger: {'sender': 'Example State', 'state': True} + ``` -Wiederum eine halbe Sekunde später wird durch Ablauf von `WaitCheck` wieder +Wiederum eine halbe Sekunde später wird durch Ablauf von `"Check"` wieder eine Abfrage des Zustands ausgelöst. ``` -Debug Logger: {'sender': 'WaitOn', 'event': 'finished'} -Debug Logger: {'sender': 'TriggerStateOnOff', 'target': 'Example State', - 'command': 'set state', 'new state': False} -Debug Logger: {'sender': 'TriggerWaitOnOff', 'target': 'WaitOff', 'command': 'wait'} -Debug Logger: {'sender': 'Example State', 'event': 'changed', 'state': False} -State Change Logger: {'sender': 'Example State', 'event': 'changed', 'state': False} -``` -Nachdem `WaitOn` das erste Mal abgelaufen ist, wird `Example State` wieder +Debug Logger: {'sender': 'Example GenericWait', + 'event': 'finished', 'id': 'On'} +Debug Logger: {'sender': 'Trigger Wait On Off', + 'target': 'Example GenericWait', 'seconds': 1.5, + 'id': 'Off', 'command': 'wait'} +Debug Logger: {'sender': 'Trigger State On Off', + 'target': 'Example State', 'command': 'set state', + 'new state': False} +Debug Logger: {'sender': 'Example State', + 'event': 'changed', 'state': False} +State Change Logger: {'sender': 'Example State', + 'event': 'changed', 'state': False} +``` +Nachdem `"On"` das erste Mal abgelaufen ist, wird `"Example State"` wieder auf `False` gesetzt. Dies wiederholt sich jetzt solange weiter, bis das Programm abgebrochen wird. +Ein reales System wird weniger von sich immer wieder selbst triggernden +Abläufen geprägt sein, sondern eher auf Einflüsse von außen reagieren. +Beispielsweise kann ein System durch +[controlpi-wsserver](https://docs.graph-it.com/graphit/controlpi-wsserver/) +Nachrichten über Websockets austauschen und damit auf Web-Oberflächen und +andere externe Systeme reagieren oder durch +[controlpi-pinio](https://docs.graph-it.com/graphit/controlpi-pinio/) mit +an die GPIO-Pins eines Raspberry Pi angeschlossener Hardware interagieren. + ## Installation auf Raspberry Pi Auf dem Raspberry Pi wollen wir den Code in ein virtuelles Environment installieren, wobei die weitere Vorgehensweise davon ausgeht, dass dieses