Eine Velobox Applikation (kurz Vlbapp) ist eine auf der Velobox als Applikationsserver laufende, in den Stationsdaemon integrierte Anwendung.
(Der Stationsdaemon (vlbstationd.sh) ist die zentrale, als Daemon laufende Softwarekomponente der Velobox.)
Jede Vlbapp definiert ihr eigenes API, mit dem die Client-Anwendung (gewöhnlich eine GUI) über eine Websocket-Verbindung kommuniziert.
Hier wird beschrieben, wie eine solche Applikation auszusehen hat und in den Stationsdaemon eingebunden wird.
| 10.03.2023 | Siegmar Müller | Begonnen |
| 11.03.2023 | Siegmar Müller | Grobe Übersicht fertig |
Der Stationsdaemon ist in der Programmiersprache TCL geschrieben, in der auch die Apps erstellt werden müssen und deren Kenntnis im Weiteren vorausgesetzt wird. Eine Reihe von TCL- (und anderen) Dateien befinden sich innerhalb einer einzigen, vorgegebenen Verzeichnisstruktur. Funktionsblöcke sind darüber hinaus in namespaces organisiert.
Ein von einer App entgegengenommener API-Befehl hat die Form einer Kommandozeile mit definierter Syntax. Die App sendet ihrerseits JSON-Objektstrings an die verbundenen Clients, die als Ereignismeldungen zu interpretieren sind. Ein Ereignis (event) kann die Antwort auf einen API-Befehl sein, aber auch anderweitig durch eine von der App überwachte Komponente asynkron ausgelöst worden sein, z.B. das Eintreffen von Sensordaten.
Jede Vlbapp hat ihren eindeutigen Kodenamen <vlbapp>. Sie ist aufgeteilt in ein Kommunikationsmodul custom/wsserver/wsdomains/apps/<vlbapp>.tcl und das eigentliche Applikationsmodul custom/apps/<vlbapp>.tcl.
Anmerkung: Das Konzept der Velobox3 bringt Vereinfachungen, die aus der Nutzung des Apple-Bonjour Protokolls resultieren (Linux avahi). Damit kann jede Velobox im LAN ohne irgendeine Registrierung mit ihrem Hostnamen als <velobox-hostname>.local erreicht werden.
Der Stationsdaemon besitzt einen eigenen HTTP/Websocketserver (lib/wssserver.tcl). Beim Hochfahren lädt dieser alle TCL-Dateien aus dem Verzeichnis custom/wsserver/wsdomains, einschließlich aller Unterverzeichnisse. Es handelt sich um die Module zum Bearbeiten von Websocketrequests, die die erforderliche Handlerprozedur für Websocketrequests bereitstellen müssen. Es gelten die folgenden Konventionen:
Das Kommunikationsmodul einer Vlbapp namens <vlbapp> ist eine Websocketdomäne apps/<vlbapp> deren Handler die Schnittstelle zur eigentlichen Vlbapp darstellt. Es behandelt insbesondere folgende Ereignisse:
Der Stationsdaemon besitzt einige Module, die der Kommunikation mit angeschlossener Hardware, aber auch mit externen Diensten im Netzwerk dienen. Eine Vlbapp kann dort spezielle Prozeduren aufrufen und eigene Callback Prozeduren hinterlegen, mit denen sie über spezielle Ereignisse informiert werden kann. Details dazu werden weiter unten beschrieben.
Applikationsmodule werden beim Hochfahren des Stationsdaemon am Schluß, nach dem Laden aller Bibliotheks- und Kernelmodule aus dem Verzeichnis custom/apps geladen. Jedes Applikationsmodul enthält die Kommandos namespace eval <vlbapp> ... und set app_loaded <vlbapp>. Sofern die Vlbapp die Prozedur init besitzt, wird diese nach dem Laden aufgerufen. Weiterhin sollten die folgenden Prozeduren verfügbar sein:
Zum Verteilen von JSON-Ereignismeldungen an ihre angemeldeten Clients
steht dem Applikationsmodul im Websocket Server die Prozedur
::WSServer::disposeServerMessage {apps/<vlbapp> text <json-objektstring>}
zur Verfügung.
(Sinn und Zweck derselben)
(Datenbank vlbclients)
(Datenbank vlbsettings)
| Browser | ||
| ↕ | ||
| (LAN) | Externe Applikation | |
| ↕ | ||
| Htdocs | ↕ | |
| ↕ | ||
| (APIs über Websocket) | ||
| ↕ | ↕ | |
| Vlbapps | ||
| ↕ | ||
| (Prozeduraufrufe) | ||
| (Callbacks) | ||
| ↕ | ||
| Kernelmodule | ||
| (2 Schichten: Basis- und App-Kernelmodule) | ↘↓ | |
| ↕ | Bibliotheksmodule | |
| (Hardware) | ||
| (LAN) | ||
Allgemeine Bibliotheksmodule (lib/)
Binäre Module
Reines TCL: dbld2img piepser wsserver
TODO Hier Übersicht, Details s. "Generierung von JPEG-Druckbildern".
Allgemeine Bibliotheksmodule (lib/) werden vor den Kernelmodulen geladen.
Basis-Kernelmodule (lib/kernel) werden vor den App-Kernelmodulen (custom/kernel/) geladen.
Sofern das geladenen Kernelmodul eine Prozedur init {} besitzt,
wird diese nach dem Laden aller Module derselben Ebene (Basis- bzw. App-) aufgerufen.
App-Kernelmodule haben so die Möglichkeit, sich mit Callback-Prozeduren bei
Basis-Kernelmodulen anzumelden.
db.tcl
watchttyacm.tcl
TTY*** Module hinterlegen bei watchTTYACM Callback Prozeduren, die aufgerufen werden, sobald eine über USB angeschlossene Druckmatte des entsprechenden Typs erkannt wurde. Diese Callback Prozeduren starten die Datenübernahme mit den ermittelten Parametern. Die Callback Prozeduren werden auch aufgerufen, wenn eine Matte entfernt wurde.
Um alle CPU-Kerne in diesen rechenintensiven Prozeß einzubeziehen, werden die interpolierten JPEG-Druckbilder in Hintergrundthreads generiert. Im Bibliotheksmodul ::DBLD2IMG stehen dafür 5 Threads in Wartestellung. Eine größere Zahl wäre angesichts von max. 4 vorhandenen CPU-Kernen eher kontraproduktiv. Die Prozedur ::DBLD2IMG::startJPEG {...}(Details s. unten) sucht dazu den nächsten freien Thread, der das fertige Bild im shared Memory hinterlegt und den Aufrufer mittels der von ihm übergebenen Callback-Prozedur über die Fertigstellung des Bildes informiert. Der muß nun das fertige Bild abholen, bevor das nächste Bild generiert ist. Wenn Bilder zu unterschiedlichen Zwecken kurz hintereinander erzeugt werden, ist i.a. nicht klar, welches der Bilder gerade fertig geworden ist. (Die parallel laufenden Threads können sich ggf. überholen.) Zur Lösung dieses Problems wird zwischen Bildtypen (imagetype) unterschieden, deren Übergabe in verschiedenen Speicherbereichen erfolgt.
Wenn gerade alle Threads belegt sind, wird kein Bild erzeugt und die als Callbacks hinterlegten "overload handler" werden aufgerufen. Wenn von einer Bildfolge kein Bild verloren gehen darf, darf die Generierung eines Folgebildes erst dann angestoßen werden, nachdem die Fertigstellung des Vorgängers gemeldet wurde.
JPEGSattel JPEGHocker
... am Beispiel des Hockerbildes in der Vlbapp "sitzknochenabstand".