Improve example in conf.json and index.md.
authorBenjamin Braatz <bb@bbraatz.eu>
Mon, 22 Mar 2021 08:51:23 +0000 (09:51 +0100)
committerBenjamin Braatz <bb@bbraatz.eu>
Mon, 22 Mar 2021 09:05:27 +0000 (10:05 +0100)
conf.json
doc/index.md

index 0e27b04734f9907d9554f2a8a7ef1eb9156e49cb..7ab462285caefd5bfab66bcbcf8a558c0af1fff0 100644 (file)
--- a/conf.json
+++ b/conf.json
     "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",
index e99e8baf24a7287c19d9988a51a2e260b0922cf7..eb1e6d1867525034faeb2b743ec09062c21292c1 100644 (file)
@@ -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': "<class 'bool'>"},
-              {'state': "<class 'bool'>"}],
-    'receives': [{'target': 'Example State', 'command': 'get state'},
-                 {'target': 'Example State', 'command': 'set state',
-                  'new state': "<class 'bool'>"}]}
-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