"""Provide utility plugins for all kinds of systems.
TODO: documentation, doctests, check configurations during _process_conf
-TODO: State, AndState, OrState?
+TODO: AndState, OrState?
"""
import asyncio
async def _receive(self, message: Message) -> None:
if 'command' in message:
if message['command'] == 'get state':
- await self._bus.send({'sender': self._name,
- 'state': self._state,
- 'changed': False})
+ answer = {'sender': self._name, 'state': self._state}
+ await self._bus.send(answer)
elif message['command'] == 'set state':
if 'state' in message and self._state != message['state']:
self._state: bool = message['state']
- await self._bus.send({'sender': self._name,
- 'state': self._state,
- 'changed': True})
+ event = {'sender': self._name, 'event': 'changed',
+ 'state': self._state}
+ await self._bus.send(event)
def _process_conf(self, conf: PluginConfiguration) -> None:
self._state = False
- sends: list[Message] = [{'sender': self._name, 'state': bool}]
+ sends: list[Message] = [{'event': 'changed', 'state': bool},
+ {'state': bool}]
receives: list[Message] = [{'target': self._name,
'command': 'get state'},
{'target': self._name,
Sie haben in der Regel einen Schlüssel `'event'` mit einem Wert, der die
Art des Ereignisses passend benennt und eventuell weitere Schlüssel, die
dieses näher beschreiben.
+ Auch das Registrieren und Deregistrieren von Klienten am Bus selbst wird
+ als Ereignis mit einem `'event'`-Schlüssel signalisiert.
- Einige Nachrichten sind als Kommandos an einen bestimmten Klienten
gedacht.
Sie haben in der Regel einen Schlüssel `'target'` mit dem Namen dieses
Debug-Oberflächen, diese Nachrichten empfangen und verarbeiten, da
`'target'`-Schlüssel von der Infrastruktur bzw. dem Bus nicht speziell
behandelt werden.)
+- Das `State`-Plugin ist ein Beispiel, welche Nachrichten (Boolesche)
+ Zustände senden und empfangen sollten:
+ Bei Änderung des Zustandes wird ein Ereignis mit `'event'`-Wert
+ `'changed'` und dem neuen Zustand als `'state'`-Wert geschickt.
+ Das Plugin reagiert auf ein `'get state'`-Kommando, indem es eine
+ Nachricht mit dem Schlüssel `'state'` und dem aktuellen Zustand als Wert
+ (aber ohne `'event'`-Schlüssel schickt, da kein wirkliches Ereignis
+ eingetreten ist) schickt.
+ Da in diesem Plugin der Zustand auch von außen setzbar ist, reagiert es
+ auf ein `'set state'`-Kommando, das einen `'state'`-Schlüssel mit einem
+ neuen, zu setzenden Wert enthält, indem es diesen Zustand setzt (und eine
+ Ereignis-Nachricht sendet, wenn dies eine Änderung war).
+- Sowohl der Bus selbst als auch das `State`-Plugin senden als Reaktion auf
+ `'get …'`-Nachrichten Antworten, die genau so aufgebaut sind wie die
+ Ereignis-Nachrichten, die sie auch aktiv senden, wenn eine Änderung
+ eingetreten ist.
+ Hierdurch können Klienten diese Nachrichten gleich behandeln, wenn das
+ Änderungs-Ereignis für sie nicht relevant ist, sondern nur die weiteren
+ Informationen in der Nachricht (der jetzt aktuelle Zustand der
+ `State`-Instanz bzw. das Vorhandensein und das Interface eines Klienten
+ am Bus).
Hinsichtlich der Reihenfolge in der verschiedene Klienten, die alle für die
gleiche Nachricht registriert sind, diese erhalten, werden von der
"State Change Logger": {
"plugin": "Log",
"filter": [
- { "sender": "Example State", "changed": true }
+ { "sender": "Example State", "event": "changed" }
]
}
}
```
Debug Logger: {'sender': '', 'event': 'registered', 'client': 'Example State',
- 'sends': [{'sender': 'Example State', 'state': "<class 'bool'>"}],
+ 'sends': [{'event': 'changed', 'state': "<class 'bool'>"},
+ {'state': "<class 'bool'>"}],
'receives': [{'target': 'Example State', 'command': 'get state'},
{'target': 'Example State', 'command': 'set state',
'state': "<class 'bool'>"}]}
Debug Logger: {'sender': '', 'event': 'registered', 'client': 'Debug Logger',
'sends': [], 'receives': [{}]}
Debug Logger: {'sender': '', 'event': 'registered', 'client': 'State Change Logger',
- 'sends': [], 'receives': [{'sender': 'Example State', 'changed': True}]}
+ 'sends': [], 'receives': [{'sender': 'Example State', 'event': 'changed'}]}
```
Die Instanz `Debug Logger` zeigt uns alle im System verschickten
Nachrichten an. Zunächst meldet der Nachrichten-Bus selbst alle
Debug Logger: {'sender': 'WaitCheck', 'event': 'finished'}
Debug Logger: {'sender': 'TriggerStateCheck', 'target': 'Example State', 'command': 'get state'}
Debug Logger: {'sender': 'TriggerWaitCheck', 'target': 'WaitCheck', 'command': 'wait'}
-Debug Logger: {'sender': 'Example State', 'state': False, 'changed': False}
+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
```
Debug Logger: {'sender': 'WaitOff', 'event': 'finished'}
-Debug Logger: {'sender': 'TriggerStateOffOn', 'target': 'Example State', 'command': 'set state', 'state': True}
+Debug Logger: {'sender': 'TriggerStateOffOn', 'target': 'Example State',
+ 'command': 'set state', 'state': True}
Debug Logger: {'sender': 'TriggerWaitOffOn', 'target': 'WaitOn', 'command': 'wait'}
-Debug Logger: {'sender': 'Example State', 'state': True, 'changed': True}
-State Change Logger: {'sender': 'Example State', 'state': True, 'changed': True}
+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
Debug Logger: {'sender': 'WaitCheck', 'event': 'finished'}
Debug Logger: {'sender': 'TriggerStateCheck', 'target': 'Example State', 'command': 'get state'}
Debug Logger: {'sender': 'TriggerWaitCheck', 'target': 'WaitCheck', 'command': 'wait'}
-Debug Logger: {'sender': 'Example State', 'state': True, 'changed': False}
+Debug Logger: {'sender': 'Example State', 'state': True}
```
Wiederum eine halbe Sekunde später wird durch Ablauf von `WaitCheck` wieder
eine Abfrage des Zustands ausgelöst.
```
Debug Logger: {'sender': 'WaitOn', 'event': 'finished'}
-Debug Logger: {'sender': 'TriggerStateOnOff', 'target': 'Example State', 'command': 'set state', 'state': False}
+Debug Logger: {'sender': 'TriggerStateOnOff', 'target': 'Example State',
+ 'command': 'set state', 'state': False}
Debug Logger: {'sender': 'TriggerWaitOnOff', 'target': 'WaitOff', 'command': 'wait'}
-Debug Logger: {'sender': 'Example State', 'state': False, 'changed': True}
-State Change Logger: {'sender': 'Example State', 'state': False, 'changed': True}
+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
auf `False` gesetzt.