ControlPi-System, die Plugins verwaltet und ihnen ermöglicht über einen Bus
Nachrichten auszutauschen.
-## Installation zum Entwickeln
-Es wird mindestens Python 3.7 benötigt. Für Ubuntu-Versionen, die selbst
-noch keine aktuelle Python-Version zur Verfügung stellen, kann eine aus dem
-PPA [deadsnakes](https://launchpad.net/~deadsnakes/+archive/ubuntu/ppa)
-installiert werden:
-```sh
-$ sudo add-apt-repository ppa:deadsnakes/ppa
-$ sudo apt update
-$ sudo apt install python3.9 python3.9-venv
-```
-
-Das Repository mit dem Code dieses Pakets kann vom öffentlichen git-Server
-bezogen werden:
-```sh
-$ git clone git://git.graph-it.com/graphit/controlpi.git
-```
-(Falls Zugang zu diesem Server per SSH besteht und Änderungen gepusht
-werden sollen, sollte stattdessen die SSH-URL benutzt werden.)
-
-Damit Python-Module in diesem Paket gefunden und eventuelle Abhängigkeiten
-installiert werden, dies aber von anderen Teilen des Systems, auf dem
-entwickelt wird, isoliert gehalten wird, sollte ein virtuelles Environment
-verwendet werden. Wo dieses Verzeichnis liegt, ist dabei relativ egal.
-Übliche Orte sind innerhalb des Code-Repository-Verzeichnisses (hierfür
-wird `venv/` von git ignoriert), parallel zum Code-Repository oder an einer
-zentralen Stelle des Home-Verzeichnisses gesammelt.
-
-Sobald das virtuelle Environment eingerichtet und aktiviert ist, beziehen
-sich Befehle wie `python` und `pip` auf die in diesem Environment
-konfigurierten und müssen nicht mehr mit genauer Version aufgerufen werden:
-```sh
-$ python3.9 -m venv <Pfad zum venv>
-$ source <Pfad zum venv>/bin/activate
-(venv)$ pip install --upgrade pip setuptools wheel
-```
-
-Damit Änderungen am Code sofort wirksam werden und getestet werden können,
-sollte das Paket, an dem gerade entwickelt wird, im virtuellen Environment
-editierbar installiert werden:
-```sh
-(venv)$ pip install --editable <Pfad zum Code-Repository>
-```
-
-## Code-Stil, Typ-Checks und Tests
-Die Formatierung des Codes und das Vorhandensein und der Stil der
-Kommentare werden durch `pycodestyle` und `pydocstyle` überprüft. Die an
-Funktionen und Variablen annotierten Typ-Informationen werden durch `mypy`
-gecheckt. Alle drei Tools können rekursiv ein gesamtes Python-Paket
-überprüfen:
-```sh
-(venv)$ pycodestyle <Pfad zum Code-Repository>/controlpi
-(venv)$ pydocstyle <Pfad zum Code-Repository>/controlpi
-(venv)$ mypy <Pfad zum Code-Repository>/controlpi
-```
-
-Sie sind als Extra-Requirements in der Datei `setup.py` definiert, sodass
-sie mit einem einzigen `pip`-Aufruf installiert werden können:
-```sh
-(venv)$ pip install --editable <Pfad zum Code-Repository>[dev]
-```
-
-Der Code wird durch in die Dokumentation eingebettete „doctests“ getestet.
-Diese können für jede Code-Datei einzeln mit dem in der
-Python-Standard-Distribution enthaltenen Modul `doctest` ausgeführt werden:
-```sh
-(venv)$ python -m doctest <Pfad zur Code-Datei>
-```
-(Für die Datei `__main__.py`, die das kleine Hauptprogramm zum Ausführen
-des Systems enthält, funtioniert dies leider nicht.)
-
-Komplette Informationen über alle durchgeführten Tests und die Abdeckung
-des Codes mit Tests erhält man mit der zusätzlichen Option `-v`:
-```sh
-(venv)$ python -m doctest -v <Pfad zur Code-Datei>
-```
-
-Außerdem wird durch die `[dev]`-Extras in `setup.py` auch das Tool `pdoc`
-zur automatischen Generierung von API-Dokumentation in HTML installiert:
-```sh
-(venv)$ pdoc --html --config sort_identifiers=False --force \
- --output-dir doc/ controlpi/ controlpi-plugins/
-```
-
## Überblick
Die ControlPi-Infrastruktur hat zwei Haupt-Bestandteile:
- Ein Plugin-System erlaubt es, ohne Anpassungen am Code der Infrastruktur
weitere Plugin-Klassen in Python zu implementieren und (in anderen
Code-Repositories und anderen Distributions-Paketen) zum System
hinzuzufügen.
- Im Modul `controlpi-plugins.util` bzw. der Datei
- `controlpi-plugins/util.py` befindet sich eine Reihe nützlicher
+ In den Modulen `controlpi_plugins.util`, `controlpi_plugins.state` und
+ `controlpi_plugins.wait` befinden sich eine Reihe nützlicher
Standard-Plugins, an denen die generelle Struktur nachvollzogen werden
kann.
- Ein Nachrichten-Bus erlaubt den Austausch von Nachrichten zwischen allen
Nachrichten bestehen aus einer Menge von Schlüssel-Wert-Paaren. (Sie sind
Dictionaries bzw. Mappings.)
+Die generierte Dokumentation des API der grundlegenden Infrastruktur ist
+unter [controlpi/](graphit/controlpi/controlpi/) zu finden.
+Die Kollektion an grundlegenden Plugins ist unter
+[controlpi_plugins/](graphit/controlpi/controlpi_plugins/) dokumentiert.
+
Um Nachrichten zu senden und/oder zu empfangen muss ein Klient am Bus unter
einem Namen registriert werden.
Eine Plugin-Instanz kann entweder genau einen Klienten registrieren (der
Netzwerk-Schnittstelle.
Die Infrastruktur definiert nur die Anforderung, dass jede gesendete
-Nachricht einen speziellen Schlüssel `'sender'` mit dem Namen des sendenden
+Nachricht einen speziellen Schlüssel `"sender"` mit dem Namen des sendenden
Klienten als Wert enthält.
Der Bus überprüft, ob diese Art von Nachricht für diesen Sender registriert
wurde, und liefert sie nur dann aus.
Sie müssen nicht unbedingt bestimmte Empfänger haben, sie gehören nicht
unbedingt zu einem bestimmten Typen etc.
-Einige Konventionen, die z.B. von den Plugins in `controlpi-plugins.util`
+Einige Konventionen, die z.B. von den Plugins in diesem Repository
eingehalten werden, sind aber:
- Einige Nachrichten signalisieren, dass ein Ereignis eingetreten ist.
- Sie haben in der Regel einen Schlüssel `'event'` mit einem Wert, der die
+ 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.
+ 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
- Ziel-Klienten als Wert und einen Schlüssel `'command'` mit einem
+ Sie haben in der Regel einen Schlüssel `"target"` mit dem Namen dieses
+ Ziel-Klienten als Wert und einen Schlüssel `"command"` mit einem
festgelegten Namen für das auszuführende Kommando und eventuell weiteren
Schlüsseln, die dann so etwas wie Parameter des Kommandos sind.
(Es können aber auch andere Klienten, beispielsweise Logger oder
Debug-Oberflächen, diese Nachrichten empfangen und verarbeiten, da
- `'target'`-Schlüssel von der Infrastruktur bzw. dem Bus nicht speziell
+ `"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
+ 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 `'new state'`-Schlüssel mit
+ auf ein `"set state"`-Kommando, das einen `"new 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
+ `"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
reagieren.
Die ControlPi-Infrastruktur ist auf nebenläufiger Programmierung mit
-`asyncio` aufgebaut.
+[`asyncio`](https://docs.python.org/3/library/asyncio.html) aufgebaut.
Diese garantiert, dass Code solange ohne Unterbrechung läuft, bis er selbst
die Kontrolle abgibt, weil er auf eine Ein- oder Ausgabe-Operation oder
ähnliches wartet.
wird.
## Installation auf Raspberry Pi
-Auch auf dem Raspberry Pi wollen wir den Code in ein virtuelles Environment
+Auf dem Raspberry Pi wollen wir den Code in ein virtuelles Environment
installieren, wobei die weitere Vorgehensweise davon ausgeht, dass dieses
direkt unter `/home/pi` liegt, also insgesamt den Pfad
`/home/pi/controlpi-venv` hat:
```sh
$ journalctl -u controlpi.service
```
+
+## Installation zum Entwickeln
+Es wird mindestens Python 3.7 benötigt.
+```sh
+$ sudo apt install python3 python3-venv
+```
+
+Das Repository mit dem Code dieses Pakets kann vom öffentlichen git-Server
+bezogen werden:
+```sh
+$ git clone git://git.graph-it.com/graphit/controlpi.git
+```
+(Falls Zugang zu diesem Server per SSH besteht und Änderungen gepusht
+werden sollen, sollte stattdessen die SSH-URL benutzt werden.)
+
+Damit Python-Module in diesem Paket gefunden und eventuelle Abhängigkeiten
+installiert werden, dies aber von anderen Teilen des Systems, auf dem
+entwickelt wird, isoliert gehalten wird, sollte ein virtuelles Environment
+verwendet werden. Wo dieses Verzeichnis liegt, ist dabei relativ egal.
+Übliche Orte sind innerhalb des Code-Repository-Verzeichnisses (hierfür
+wird `venv/` von git ignoriert), parallel zum Code-Repository oder an einer
+zentralen Stelle des Home-Verzeichnisses gesammelt.
+
+Sobald das virtuelle Environment eingerichtet und aktiviert ist, beziehen
+sich Befehle wie `python` und `pip` auf die in diesem Environment
+konfigurierten und müssen nicht mehr mit genauer Version aufgerufen werden:
+```sh
+$ python3 -m venv <Pfad zum venv>
+$ source <Pfad zum venv>/bin/activate
+(venv)$ pip install --upgrade pip setuptools wheel
+```
+
+Damit Änderungen am Code sofort wirksam werden und getestet werden können,
+sollte das Paket, an dem gerade entwickelt wird, im virtuellen Environment
+editierbar installiert werden:
+```sh
+(venv)$ pip install --editable <Pfad zum Code-Repository>
+```
+
+## Code-Stil, Typ-Checks und Tests
+Die Formatierung des Codes und das Vorhandensein und der Stil der
+Kommentare werden durch
+[`pycodestyle`](https://pycodestyle.pycqa.org/en/latest/) und
+[`pydocstyle`](http://www.pydocstyle.org/en/stable/) überprüft.
+Die an Funktionen und Variablen annotierten Typ-Informationen werden durch
+[`mypy`](http://mypy-lang.org/) gecheckt.
+Alle drei Tools können rekursiv ein gesamtes Python-Paket überprüfen:
+```sh
+(venv)$ pycodestyle <Pfad zum Code-Repository>/controlpi
+(venv)$ pydocstyle <Pfad zum Code-Repository>/controlpi
+(venv)$ mypy <Pfad zum Code-Repository>/controlpi
+```
+
+Sie sind als Extra-Requirements in der Datei `setup.py` definiert, sodass
+sie mit einem einzigen `pip`-Aufruf installiert werden können:
+```sh
+(venv)$ pip install --editable <Pfad zum Code-Repository>[dev]
+```
+
+Der Code wird durch in die Dokumentation eingebettete „doctests“ getestet.
+Diese können für jede Code-Datei einzeln mit dem in der
+Python-Standard-Distribution enthaltenen Modul
+[`doctest`](https://docs.python.org/3/library/doctest.html) ausgeführt
+werden:
+```sh
+(venv)$ python -m doctest <Pfad zur Code-Datei>
+```
+(Für die Datei `__main__.py`, die das kleine Hauptprogramm zum Ausführen
+des Systems enthält, funtioniert dies leider nicht.)
+
+Komplette Informationen über alle durchgeführten Tests und die Abdeckung
+des Codes mit Tests erhält man mit der zusätzlichen Option `-v`:
+```sh
+(venv)$ python -m doctest -v <Pfad zur Code-Datei>
+```
+
+Außerdem wird durch die `[dev]`-Extras in `setup.py` auch das Tool
+[`pdoc`](https://pdoc3.github.io/pdoc/) zur automatischen Generierung von
+API-Dokumentation in HTML installiert:
+```sh
+(venv)$ pdoc --html --config sort_identifiers=False --force \
+ --output-dir doc/ controlpi/ controlpi_plugins/
+```
+Mit diesem wurden auch die oben verlinkten API-Dokumentationen für
+[`controlpi`](graphit/controlpi/controlpi/) und
+[`controlpi_plugins`](graphit/controlpi/controlpi_plugins/)
+generiert.