- Revised the Kiosk-Mode section in SUMMARY.md to include recent changes related to SSL support and improved user experience. - Clarified instructions for setting up kiosk mode with the new SSL configuration. - Ensured consistency in formatting and alignment for better readability.
40 KiB
title, subtitle, author, date, subject, company
title | subtitle | author | date | subject | company |
---|---|---|---|---|---|
MYP – Manage Your Printer | Abschlussprojekt der IHK-Prüfung | Till Tomczak | 2023 | Fachinformatiker für digitale Vernetzung | Mercedes-Benz |
MYP – Manage Your Printer: Projektzusammenfassung
1. Projektüberblick
MYP (Manage Your Printer) ist ein System zur zentralen Verwaltung und Steuerung von 3D-Druckern mittels Smart-Plug-Technologie. Es digitalisiert den Reservierungsprozess für mehrere 3D-Drucker und ermöglicht eine automatisierte Schaltung der Drucker über WLAN-Steckdosen (TP-Link Tapo P110). Zu den Kernfunktionen gehören unter anderem:
- Benutzer- und Rechteverwaltung: Registrierung, Login und Rollenkonzept (Admin/Benutzer). Administrierende können Drucker und Nutzer verwalten, während Standard-Benutzer Reservierungen anlegen und ihre Druckjobs verwalten dürfen.
- Drucker- und Auftragsmanagement: Zentrales Reservierungssystem ermöglicht es Nutzern, Zeitfenster für Druckaufträge zu buchen. Die Drucker werden automatisch zum Start einer Reservierung eingeschaltet und nach Ende wieder ausgeschaltet. Es findet keine direkte Kommunikation mit den 3D-Druckern statt – anstatt die Drucker selbst anzusprechen, wird ausschließlich deren Stromzufuhr über die Smart-Plug-Steckdosen gesteuert. Dadurch bleibt das System herstellerunabhängig und einfach, da keine Eingriffe in die Druckerhardware erfolgen müssen.
- Statistikerfassung: Das System protokolliert Nutzungszeiten und abgeschlossene Druckaufträge, um Auswertungen (z.B. Gesamtdruckzeit pro Zeitraum) zu ermöglichen.
- Offline-Fähigkeit & Kiosk-Modus: MYP ist so konzipiert, dass es nach der Installation ohne Internetzugang betrieben werden kann. Ein dedizierter Kiosk-Modus (auf einem Raspberry Pi) erlaubt die Anzeige eines Dashboards im Vollbild (z.B. auf einem Monitor in der Nähe der Drucker), um aktuelle Druckerbelegungen und den Systemstatus anzuzeigen.
Technologisch besteht MYP aus einem Flask-basierten Backend in Python mit einer leichten SQLite-Datenbank zur Datenspeicherung. Über eine RESTful API kommuniziert das Backend mit dem Frontend sowie optional mit externen Diensten. Die Kommunikation kann verschlüsselt über HTTPS erfolgen (selbstsigniertes Zertifikat) und unterstützt einen Progressive Web App (PWA) Ansatz, sodass die Web-Oberfläche auch offline im Browser funktionieren kann. Insgesamt stellt MYP eine cyber-physische Lösung dar, die IT-System (Reservierungsplattform) und Hardware (Smart-Plugs und Drucker) eng vernetzt.
2. Ausgangssituation und Zielsetzung
Ausgangssituation: In der Ausgangslage wurden die verfügbaren 3D-Drucker des Unternehmens dezentral und manuell verwaltet. Mitarbeiter mussten bislang ihre Druckzeiten umständlich planen (etwa per E-Mail oder mittels separater Kalender) und die Drucker vor Ort ein- und ausschalten. Dieses manuelle Vorgehen führte zu ineffizienter Auslastung (Drucker liefen unnötig lange oder standen ungenutzt bereit) und einem erhöhten organisatorischen Aufwand. Außerdem bestand keine automatische Rückmeldung über den Druckerzustand – es war unklar, ob ein Drucker gerade druckt, verfügbar ist oder vielleicht vergessen wurde auszuschalten. Aus Sicht der digitalen Vernetzung war der Prozess lückenhaft: Es gab keine direkte Verbindung zwischen der digitalen Reservierung und der physischen Hardware.
Ziel des Projekts: Die Projektarbeit zielte darauf ab, den 3D-Drucker-Reservierungsprozess zu digitalisieren und effizienter zu gestalten. Konkret sollte eine Plattform geschaffen werden, die Benutzerreservierungen mit der physischen Verfügbarkeit der Drucker verknüpft. Durch die Etablierung einer cyber-physischen Kommunikation sollten relevante Hardwarekomponenten (insb. smarte Steckdosen für die Drucker) automatisiert angesteuert werden, um menschliche Eingriffe zu minimieren. Wichtige Zielsetzungen waren:
- Automatisierung: Drucker sollen sich zum reservierten Zeitpunkt automatisch einschalten und nach Ende des Zeitfensters abschalten. Damit wird Energie gespart und Sicherheit erhöht (kein unbeaufsichtigtes Laufenlassen).
- Zentrale Verwaltung: Alle Drucker und Reservierungen sollten in einem zentralen System verwaltbar sein, mit Überblick über aktuelle Belegungen und Historie.
- Benutzerfreundlichkeit: Endnutzer sollten einfach über eine Web-Oberfläche einen Drucker buchen können, ohne sich um technische Details kümmern zu müssen. Das System übernimmt im Hintergrund die zeitgesteuerte Schaltung.
- Offline-Betrieb: Da das Projekt in einem abgeschotteten Umfeld (z.B. Prüfungsumgebung, internes Firmennetz ohne Internet) laufen muss, sollte die Lösung ohne Internetanbindung funktionsfähig sein. Ein eigenständiges lokales WLAN bzw. Netzwerksegment war hierfür einzuplanen.
- Sicherheit und Kontrolle: Durch Rollen und Authentifizierung sollte nur berechtigten Personen der Zugriff erlaubt werden. Zusätzlich sollen Protokollierung und Statistiken Transparenz über die Nutzung schaffen.
Mit MYP wird ein Schritt hin zur Industrie-4.0-Umgebung gemacht, in der betriebliche Ressourcen (hier: 3D-Drucker) digital vernetzt und automatisiert verwaltet werden. Das Projekt bildet die Grundlage, auf der künftig weitere Verbesserungen wie Echtzeit-Status der Drucker oder eine tiefere Integration in bestehende Systeme aufbauen können.
3. Planung und technische Architektur
Planungsphase: Zu Beginn wurden die bestehende Infrastruktur und Anforderungen analysiert. Es stellte sich heraus, dass mehrere 3D-Drucker vorhanden sind, die jedoch bisher stand-alone betrieben wurden (teils mit eigener Netzwerkfähigkeit, die aber ungenutzt blieb). Als erstes wurden zusammen mit der IT-Abteilung die Rahmenbedingungen geklärt: Es musste ein geeigneter Netzwerkbereich für das neue System bereitgestellt werden (inkl. IP-Adressen und ggf. DNS-Namen für den Server) und eine Lösung für den offline Betrieb gefunden werden. Ein Netzwerkplan wurde erstellt, um die Integration von MYP in das Firmennetz sowie ein paralleles isoliertes WLAN zu skizzieren (siehe Abschnitt 4). Parallel dazu wurden die Systemanforderungen konkretisiert (siehe unten).
Technologie- und Komponentenauswahl: Auf Basis der Anforderungen entschied man sich für folgende technische Architektur:
- Hardware: Es wurde ein Raspberry Pi 4 als Zentrale (
Controller Pi
) eingesetzt. Dieser Einplatinencomputer ist leistungsfähig genug für den Flask-Server und den Browser im Kiosk-Modus, bietet WLAN und LAN Schnittstellen und ist aufgrund seiner Größe und Kosten ideal für diese Anwendung. Die Entscheidung fiel bewusst auf den Raspberry Pi mit dem Betriebssystem Raspberry Pi OS (Raspbian), da hier eine schnelle Einrichtung und viele Community-Ressourcen verfügbar sind (alternativ erwogene Systeme wie OpenSUSE oder NixOS wurden verworfen zugunsten der spezifisch angepassten Raspberry-Distribution). - Smart Plugs: Zur Schaltung der Drucker wurden TP-Link Tapo P110 WLAN-Steckdosen ausgewählt. Diese Modelle bieten neben Schaltfunktionen auch Energiedaten und lassen sich über eine lokale API ansteuern. Wichtig war, dass die Steckdosen lokal im LAN angesprochen werden können, ohne auf Cloud-Services angewiesen zu sein. Die P110 erfüllen dies mittels eines herstellerspezifischen Protokolls, das mit Authentifizierung und Verschlüsselung arbeitet.
- Software Backend: Die Server-Anwendung wurde in Python mit dem Flask-Framework realisiert. Flask eignet sich durch seine Leichtgewichtigkeit für Embedded-Umgebungen und ermöglicht dennoch eine saubere REST-API-Implementierung. Für die Datenpersistenz wird eine SQLite-Datenbank genutzt, die direkt im Dateisystem des Pi liegt – ideal für eine lokale Einzelplatz-Lösung ohne separaten DB-Server. Das Backend ist modular aufgebaut (siehe Abschnitt 5) und läuft als Daemon (Systemd-Service) auf dem Raspberry Pi.
- Software Frontend: Als Benutzeroberfläche dient eine Web-Anwendung (HTML5/JavaScript/CSS), die entweder in eine bestehende Reservierungsplattform integriert werden kann oder eigenständig als PWA läuft. Während der Entwicklung wurde besonders darauf geachtet, dass das Frontend im Offline-Modus funktioniert, um z.B. im Prüfungsraum ohne Internet dennoch eine Bedienoberfläche zu haben. Technisch kamen moderne Web-Technologien (u.a. Tailwind CSS für responsives Design und ein Service Worker für Caching) zum Einsatz.
Architekturüberblick: MYP folgt dem klassischen Client-Server-Modell. Der Raspberry Pi fungiert als Server und Kontrollinstanz, an den die Smart-Plugs und optional die 3D-Drucker angebunden sind. Clients (Browser der Benutzer oder das integrierte Firmenportal) greifen über die REST-API auf den Server zu. Die API-Schicht abstrahiert alle Funktionen wie User-Management, Druckerstatus, Reservierungsplanung usw. in eindeutige Endpunkte (siehe Abschnitt 6). Eine besondere Komponente ist der Scheduler im Backend, der als Hintergrunddienst zeitkritische Aufgaben ausführt (z.B. Steckdose einschalten zum richtigen Zeitpunkt, siehe Abschnitt 7).
Die Planung sah einen klaren Projektstrukturplan mit Meilensteinen vor: Einrichtung der Hardware, Implementierung der Kernfunktionen (API, Datenbank, Plug-Steuerung), Aufbau der Netzwerkinfrastruktur, Entwicklung der Oberfläche, Tests und Dokumentation. Risiken wie z.B. unbekannte Steckdosen-Protokolle wurden durch frühzeitige Recherche (Wireshark-Mitschnitte, Libraries) mitigiert. Insgesamt wurde die Architektur so gewählt, dass sie erweiterbar ist – weitere Drucker oder Funktionen (z.B. Sensorintegration) können in Zukunft ergänzt werden, ohne das Grundsystem zu verändern.
4. Digitale Vernetzung und Netzwerkkonzept
Die Vernetzung aller Komponenten erfolgt in einem abgeschotteten lokalen Netzwerk (LAN) ohne Internetzugang. Dies gewährleistet, dass die Lösung autark funktioniert und sicher vor externen Einflüssen ist. Der Raspberry Pi übernimmt dabei eine Doppelrolle als Netzwerkknoten im Firmennetz und als Access Point für ein eigenes WLAN. Die folgende Abbildung veranschaulicht das Netzwerkkonzept:
Abb. 1: Netzwerkdiagramm der MYP-Architektur. Das Firmennetzwerk (192.168.x.x/24) bildet den übergeordneten Rahmen, in dem der Raspberry Pi als Controller integriert ist. Der Pi besitzt im Firmennetz eine feste IP-Adresse (z.B. 192.168.0.105) und kann optional unter einem durch die IT vergebenen DNS-Alias angesprochen werden. Über dieses kabelgebundene LAN (LAN-Port) kommuniziert der Pi mit den Benutzer-Arbeitsplätzen (Clients) – beispielsweise dem bestehenden Reservierungsportal oder Administrations-PCs. Gleichzeitig spannt der Pi ein Ad-hoc-WLAN (10.0.0.0/24) auf, das völlig isoliert vom restlichen Firmennetz läuft. In dieses WLAN werden die Smart-Plugs eingebunden, sodass sie vom Pi direkt angesprochen werden können, ohne dass die Daten das Firmennetz verlassen. Auch der im Kiosk-Modus betriebene Info-Bildschirm ist Teil dieses Pi-Netzwerks – entweder physisch via HDMI verbunden oder als separates Gerät, das sich ins WLAN 10.0.0.x einwählt.
Im Firmennetz sind die 3D-Drucker selbst zwar ebenfalls mit IP-Adressen registriert (teils über feste Zuteilung), jedoch werden sie vom MYP-System nicht aktiv adressiert. Die feste IP der Drucker dient lediglich Dokumentationszwecken bzw. könnte für zukünftige Erweiterungen (z.B. direkte Statusabfrage der Drucker) genutzt werden. Aktuell erfolgt die Steuerung ausschließlich indirekt über die zugeordneten Smart-Plugs. Jeder Drucker ist einer spezifischen WLAN-Steckdose zugeordnet, die physisch dessen Stromzufuhr schaltet. Der Pi sendet Schaltbefehle per IP-Netzwerk direkt an die Smart-Plug (über deren lokale API).
Netzwerk-Topologie und Sicherheit: Das isolierte WLAN (Pi-Netz) hat keinen Router ins Internet. Der Pi fungiert hier als DHCP-Server und ggf. DNS-Server nur für das interne 10.0.0.x-Netz. Somit bleiben alle MQTT/HTTP-Kommunikationen lokal. Für den Zugriff der Benutzer auf das System gibt es zwei Wege:
- Über das Firmennetz: Hierbei greifen die Nutzer von ihren Arbeitsplätzen (192.168.x.x) über den zugewiesenen Hostname/IP auf die Flask-API bzw. die Weboberfläche zu. Dieser Zugriff kann optional über HTTPS abgesichert sein (siehe Sicherheit). Da die Nutzergeräte im selben internen Netz sind, bleiben die Latenzen gering und kein externer Traffic fällt an. Die IT-seitige Freigabe eines DNS-Namens (z.B.
myp.intern
) erleichtert die Erreichbarkeit. - Direkt über das Pi-WLAN (Notfallbetrieb): Für Demonstrationszwecke oder falls das Firmennetz ausfällt, kann ein Gerät direkt mit dem vom Pi bereitgestellten WLAN verbunden werden. In diesem Ad-hoc-Netz kann man via IP (z.B.
10.0.0.1
) auf die Weboberfläche zugreifen. Dieser Modus gewährleistet, dass das System offline einsatzfähig ist und vollständig ohne bestehende Infrastruktur betrieben werden kann (wichtig z.B. während der IHK-Prüfungssituation).
Zwischen den beiden Netzteilen (Firmennetz und Pi-WLAN) besteht nur der Raspberry Pi als Knoten. Eine Weiterleitung von Verkehrsströmen wird unterbunden, um Sicherheit zu gewährleisten. Diese Segmentierung stellt sicher, dass ein potentielles Problem im Pi-Netz (z.B. ein kompromittiertes IoT-Gerät) nicht ins Firmennetz gelangt. Gleichzeitig sind die Smart-Plugs im isolierten WLAN vor externen Zugriffen geschützt.
Kommunikationsprotokolle: Die Kommunikation zwischen Frontend (Browser) und Backend (Flask) erfolgt über HTTP/REST mit JSON-Datenformat. Im normalen Betrieb wird HTTP über das Firmennetz genutzt; optional kann der Datenverkehr mit TLS 1.2+ verschlüsselt werden (selbstsigniertes Zertifikat). Die Kommunikation zwischen Backend und Smart-Plug erfolgt über das proprietäre Tapo-Protokoll. Hierzu nutzt MYP eine Python-Bibliothek, die die notwendigen Schritte (Handshake, Authentifizierung, Verschlüsselung) kapselt. Da dieses Protokoll auf TCP/IP aufsetzt, bleibt die Kommunikation ebenfalls lokal innerhalb des 10.0.0.x-Netzes. Die Datenbank (SQLite) liegt auf dem Pi und wird vom Flask-Backend mittels SQL-Zugriff (über eine ORM oder direkt) angesprochen – externe Netzwerkkommunikation ist hierfür nicht nötig.
Zusammenfassend implementiert das Netzwerkkonzept von MYP eine digitale Vernetzung im Kleinen: Alle relevanten Komponenten (Benutzer-Clients, Server, Steckdosen, Anzeigen) sind über ein Intranet miteinander verbunden. Durch die Trennung vom Internet und den Einsatz von lokalen APIs wird eine robuste, datenschutzfreundliche Umgebung geschaffen, die dennoch die Vorteile der Automatisierung und zentralen Steuerung voll ausschöpft.
5. Umsetzung des Backends
Die Backend-Implementierung erfolgte mit Python 3.11 und dem Mikroframework Flask. Der Quellcode ist modular in mehrere Komponenten unterteilt, um Wartbarkeit und Übersicht zu gewährleisten:
app.py
– Hauptanwendung: Diese Datei startet den Flask-Server und registriert alle Blueprints (Modul-Komponenten) und Routen. Hier werden auch grundlegende Einstellungen vorgenommen (z.B. CORS-Konfiguration, Datenbank-Initialisierung, Start des Schedulers). Außerdem wird beim Start geprüft, ob die Datenbank bereits existiert; falls nicht, wird eine Initialisierung vorgenommen und ein erster Admin-Benutzer kann über einen speziellen Endpunkt erstellt werden (siehe README-Erststart).- Blueprints/Routes – Das Backend ist in logische Module aufgeteilt, z.B. einen Authentifizierungs-Blueprint für Login/Logout, einen User-Blueprint für Benutzerverwaltung, einen Printer-Blueprint und einen Job-Blueprint. Jeder Blueprint kapselt zugehörige URL-Endpunkte und die Geschäftslogik dahinter. Flask ermöglicht so eine saubere Trennung der Verantwortlichkeiten. Beispielsweise verarbeitet der Auth-Blueprint Anfragen an
/auth/register
oder/auth/login
, während der Printer-Blueprint Endpunkte wie/api/printers
bereitstellt. models.py
– Datenbankmodelle: Die zentralen Datenstrukturen (Benutzer, Drucker, Druckauftrag, Statistiken) sind als Klassen definiert, die mit der SQLite-Datenbank verbunden sind. Hier wird z.B. festgelegt, welche Felder ein Printer oder Job hat und wie die Beziehungen zwischen den Modellen sind (siehe Abschnitt 6).job_scheduler.py
– Hintergrundprozesse: Dieses Modul enthält die Implementierung des Schedulers, der periodisch Aufgaben ausführt. Dazu gehören insbesondere das automatische Ein- und Ausschalten der Smart-Plugs zu den geplanten Zeiten der Druckaufträge sowie das Überwachen laufender Jobs (Restzeit, Abbruch bei Timeout etc.). Der Scheduler läuft in einem separaten Thread oder Prozess und kommuniziert ggf. über Thread-sichere Queues oder Datenbankflags mit dem Hauptprozess.- Hilfskomponenten: Zusätzlich gibt es Hilfsfunktionen und -klassen, z.B. für das Logging (Schreiben in
myp.log
), für Auth-Decorators (z.B.@login_required
oder Rollenprüfungen), sowie Konfigurations-Skripte (z.B. Erzeugen von SSL-Zertifikaten, Systemstart-Scripts). Die Struktur lehnt sich an gängige Flask-Projektvorlagen an.
Das Backend wurde als Dienst unter Linux eingerichtet. Ein systemd Service-File (/etc/systemd/system/myp.service
) garantiert, dass die Flask-Anwendung automatisch beim Boot des Raspberry Pi startet. Dieser Service definiert den Startbefehl (ExecStart=/opt/myp/.venv/bin/python /opt/myp/app.py
) und stellt sicher, dass der Dienst bei Netzwerkverfügbarkeit startet und bei Absturz automatisch neu gestartet wird. Dadurch ist ein unbeaufsichtigter Dauerbetrieb möglich (wichtig für den 24/7 Einsatz in einer Firmenumgebung).
Die API läuft standardmäßig auf Port 5000 und lauscht auf allen Interfaces des Pi. Somit ist sie sowohl vom Firmennetz (Ethernet) als auch vom Pi-WLAN erreichbar. In der Entwicklungsphase wurde zunächst HTTP verwendet; für den Produktivbetrieb kann mittels Werkzeug und Selbstsignierung HTTPS aktiviert werden (das Setup-Skript create_ssl_cert.sh
generiert z.B. ein Zertifikat und Flask kann entsprechend konfiguriert werden).
Datenpersistenz: Alle persistenten Daten werden in einer SQLite-Datenbankdatei (myp.db
) im Verzeichnis database/
des Projekts gespeichert. SQLite wurde gewählt, da sie keinen separaten Server erfordert und Transaktionen in einer Einzelbenutzer-Umgebung zuverlässig handhabt. Für Backup-Zwecke lässt sich die DB-Datei einfach kopieren; perspektivisch könnte eine regelmäßige Exportsicherung implementiert werden (z.B. beim Shutdown auf USB-Stick). Das Datenmodell ist überschaubar, wodurch auch manuelle Eingriffe (mit SQLite-Tools) im Notfall möglich sind.
Zusammenfassung Backend-Funktion: Beim Eintreffen einer Anfrage vom Frontend prüft Flask zunächst die Route und ruft den entsprechenden Handler auf (z.B. die Funktion create_job()
für POST /api/jobs
). Dieser Handler führt Geschäftslogik aus – etwa Eingabedaten validieren, in die Datenbank schreiben und ggf. den Scheduler informieren – und gibt dann eine JSON-Antwort zurück. Die Geschäftslogik deckt alle im Abschnitt 1 genannten Funktionen ab, von Benutzerregistrierung bis zum Schalten der Drucker. Durch klare Trennung der Schichten (HTTP -> Logik -> Datenbank -> Hardware) ist das System gut wartbar und erweiterbar.
6. API-Design und Datenmodell
Das MYP-Backend bietet eine REST-API mit klar definierten Endpunkten, über die alle Funktionen gesteuert werden können. Die API ist ressourcenorientiert aufgebaut, d.h. es gibt separate Pfade für Drucker, Druckaufträge (Jobs), Benutzer usw. und es werden die HTTP-Methoden gemäß ihrer Semantik verwendet (GET für Abfragen, POST für Erstellen, DELETE für Löschen usw.). Ein Auszug der wichtigsten API-Endpunkte lautet:
- Authentifizierung:
POST /auth/register
(Registrierung eines neuen Benutzers),POST /auth/login
(Anmeldung, erzeugt eine Session). Nach erfolgreichem Login erhält der Client einen Session-Cookie, über den nachfolgende Anfragen authentifiziert werden. Optional kann auch ein Logout-Endpunkt genutzt werden. - Drucker-Endpunkte:
GET /api/printers
liefert die Liste aller bekannten Drucker;POST /api/printers
fügt einen neuen Drucker hinzu (Admin-Recht erforderlich);GET /api/printers/<id>
holt Details zu einem Drucker;DELETE /api/printers/<id>
löscht einen Drucker. Außerdem gibt esGET /api/printers/status
um den Status aller Drucker (ein/aus, verfügbar/belegt) in aggregierter Form abzurufen. - Jobs/Reservierungen:
GET /api/jobs
listet alle geplanten Druckaufträge;POST /api/jobs
legt einen neuen Auftrag an. Jeder Auftrag ist einem Drucker und einem Benutzer zugeordnet und enthält Startzeit und erwartete Dauer. Für laufende Aufträge existieren spezielle Aktionen:POST /api/jobs/<id>/finish
markiert einen Druckjob als fertig und schaltet den Drucker (die Steckdose) ab. Ähnlich gibt es/abort
zum Abbrechen (ebenfalls mit Abschalten) und/extend
um die Endzeit zu verlängern. ÜberGET /api/jobs/<id>/status
kann der aktuelle Status (z.B. „läuft" oder „wartet") sowie der Plug-Zustand abgefragt werden, undGET /api/jobs/<id>/remaining-time
liefert die Restzeit in Sekunden. - Benutzer-Verwaltung:
GET /api/users
gibt eine Liste aller Benutzer zurück (nur für Admins sichtbar);GET /api/users/<id>
ruft Profildetails ab;DELETE /api/users/<id>
löscht einen Benutzer (nur Admin). Registrierung erfolgt wie erwähnt über/auth/register
oder initial über einen speziellen Setup-Endpunkt (/api/create-initial-admin
beim allerersten Start). - Sonstiges:
GET /api/stats
liefert globale Nutzungsstatistiken (z.B. Gesamtstunden aller Drucker);GET /api/test
dient als einfacher Health-Check des Systems. Im Kiosk-Betrieb wurden außerdem Endpunkte wie/api/kiosk/activate
vorgesehen, um Anzeigebildschirme zentral zu steuern (z.B. ein-/ausschalten des Anzeige-Modus). Zudem gibt es Endpunkte zum Scheduler-Management (Start/Stop des Hintergrunddienstes, Status abfragen) für Administrationszwecke.
Alle API-Aufrufe (bis auf Registrierung/Login und Health-Check) erfordern eine gültige Authentifizierung. Dies wird mittels Session-Cookies und dem Flask-Login-Mechanismus erreicht (siehe Abschnitt 10, Sicherheit). Bei fehlender Berechtigung oder ungültiger Session antwortet der Server mit HTTP 401/403 Fehlern.
Datenmodell: Im Hintergrund sind die Daten in mehreren verbundenen Tabellen organisiert. Das relationale Schema wurde so gestaltet, dass es die wichtigsten Entitäten und Beziehungen des Druckerreservierungssystems abbildet. Folgende Kern-Modelle existieren:
Abb. 2: Datenmodell (vereinfachtes ER-Diagramm) von MYP. Das Diagramm zeigt die Haupttabellen User, Printer, PrintJob sowie zusätzliche Tabellen für Session und Account. Jeder User besitzt ein eindeutiges Login (E-Mail) und einen Rollentyp (z.B. "admin"
oder "user"
). Ein Printer repräsentiert einen physischen 3D-Drucker und speichert u.a. einen Namen, eine optionale Beschreibung und einen Status (z.B. verfügbar, belegt, offline). Die PrintJob-Tabelle (auch Reservierung genannt) verknüpft einen Benutzer und einen Drucker mit einem geplanten Zeitfenster: Sie enthält Felder für Startzeit (start_at
) und Dauer bzw. Endzeit, eventuell einen Kommentar, sowie Flags für den Zustand des Auftrags (etwa ob er abgebrochen wurde). Über Fremdschlüssel-Beziehungen sind PrintJob -> Printer (viele-zu-eins) und PrintJob -> User (viele-zu-eins) realisiert – ein Drucker kann also mehrere Jobs über die Zeit haben, ein Nutzer kann mehrere Jobs buchen, aber jeder Job gehört genau zu einem Drucker und einem Nutzer.
Zusätzlich implementiert das System ein Session-Management: Die Tabelle Session (oder alternativ in der Konfiguration von Flask-Login) hält aktive Sessions mit Gültigkeitsdauer. So kann z.B. ein Login-Token (Session-ID) einem User zugeordnet und dessen Ablauf (expires
) verwaltet werden. In unserer Implementierung wurde Flask-Login genutzt, das standardmäßig clientseitige Session-Cookies verwendet; die Session-Tabelle könnte für eigene Auth-Flows oder Token-Storage benutzt werden.
Die Account-Tabelle im Diagramm deutet an, dass perspektivisch auch externe Authentifizierungsprovider (wie Firmen-SSO oder OAuth) angebunden werden könnten. Sie enthält Felder für Provider-Namen, Token, Refresh-Token etc., wurde aber im Rahmen des Projekts nicht aktiv genutzt, da die Authentifizierung lokal über Benutzeraccounts erfolgt. Dieses Design bietet aber Erweiterungspotenzial, falls man z.B. eine Anbindung an ein zentrales Benutzerverzeichnis vornehmen möchte.
Datenbankzugriffe: Alle CRUD-Operationen der API werden mittels SQL auf dieser SQLite-Datenbank ausgeführt. Für häufige Abfragen (z.B. Liste der aktuellen aktiven Jobs) wurden effiziente Queries erstellt. Constraints (wie eindeutige E-Mails für User, referentielle Integrität zwischen Job und Drucker/User) sorgen für Konsistenz. Durch das einfache Schema konnte auf komplexe Joins weitgehend verzichtet werden; die meisten Abfragen nutzen direkte Schlüssel-Beziehungen.
Validierung und Fehlerbehandlung: Das API-Design sieht vor, ungültige Eingaben abzufangen. Beispielsweise prüft der POST /api/jobs
Handler, ob für den gewählten Drucker bereits ein überschneidender Auftrag existiert, bevor ein neuer angelegt wird. Auch werden Zeiten auf sinnvolle Werte geprüft (Start in der Zukunft, Dauer positiv usw.). Im Fehlerfall liefert das API klare Fehlermeldungen im JSON-Format, die dem Frontend angezeigt werden können. Diese Maßnahmen stellen sicher, dass die Datenkonsistenz in der Datenbank gewahrt bleibt und Benutzerfehler abgefangen werden.
7. Plug-Steuerung und Zeitlogik (Scheduler)
Ein zentrales technisches Merkmal von MYP ist die automatisierte Steuerung der Smart-Plug Steckdosen entsprechend der Zeitplanung der Druckaufträge. Hierfür wurde ein Scheduler entwickelt, der kontinuierlich im Hintergrund läuft. Die Herausforderungen dabei waren sowohl die zuverlässige Kommunikation mit den TP-Link Tapo P110 Steckdosen als auch die präzise Zeitsteuerung (damit Drucker weder zu früh noch zu spät geschaltet werden).
Ansteuerung der TP-Link Tapo P110: Die Tapo-Smartplugs verwenden ein proprietäres, verschlüsseltes Protokoll zur lokalen Steuerung. Zu Projektbeginn war unklar, wie die Steckdosen ohne Cloud-Dienst angesprochen werden können. Durch Recherche und Protokollanalyse (u.a. mittels Wireshark-Mitschnitten) wurde ermittelt, dass eine bestimmte Sequenz von Handshake- und Login-Aufrufen notwendig ist, bevor Schaltbefehle akzeptiert werden. Glücklicherweise existierte eine Python-Bibliothek namens PyP100/PyP110, die diese Low-Level-Details kapselt. MYP nutzt diese Bibliothek, um eine Steckdose zu schalten. Intern läuft dies wie folgt ab: Zu Beginn wird ein Handshake mit der Steckdose (über deren IP im 10.0.0.x Netz) durchgeführt, dann erfolgt ein Login mit den in der Steckdose hinterlegten Zugangsdaten (E-Mail/Passwort des Tapo-Kontos) und anschließend können Befehle wie ein/aus als verschlüsselte Pakete gesendet werden. Dieser Ablauf dauert nur wenige Hundert Millisekunden. Die Bibliothek abstrahiert diese Schritte in Methoden wie p110.turnOn()
oder p110.turnOff()
.
Im System sind die Zugangsdaten für die Steckdosen einmalig hinterlegt (im Konfigurationsbereich oder Code), da die Steckdosen fest an das Offline-System gebunden sind. Wichtig: Die Kommunikation mit den Plugs bleibt im lokalen Netzwerk, es wird kein externer Server kontaktiert. Damit die Plugs trotz Offline-Betrieb funktionieren, wurden sie initial über die Tapo-App ins lokale WLAN eingebunden. Nach dieser Einrichtung sind sie auch ohne Internet durch die lokale API steuerbar.
Scheduler-Funktion: Der Scheduler ist dafür zuständig, alle zeitabhängigen Aktionen im System auszuführen. Im Kern prüft er in regelmäßigen kurzen Intervallen (z.B. jede Minute oder kontinuierlich mit Sleep-Timern), ob bestimmte Ereignisse anstehen. Wichtige Aufgaben sind:
- Job-Start schalten: Wenn die Startzeit eines Druckjobs erreicht ist (oder unmittelbar bevorsteht), sendet der Scheduler den Befehl zum Einschalten der zugehörigen Steckdose. Dadurch wird der 3D-Drucker mit Strom versorgt und der Druck kann – falls jemand vor Ort den Druckauftrag gestartet hat – beginnen. Gleichzeitig markiert das System den Job als „gestartet".
- Job-Ende schalten: Sobald das geplante Endzeit eines Auftrags erreicht ist, sorgt der Scheduler dafür, dass die Steckdose (und damit der Drucker) ausgeschaltet wird. Dies passiert sowohl im regulären Abschlussfall als auch bei vorzeitigen Abbrüchen. Damit wird sichergestellt, dass kein Drucker über das reservierte Zeitfenster hinaus Strom zieht. Wird ein Job manuell durch den Nutzer via
/finish
oder/abort
beendet, schaltet das Backend sofort den Plug aus und Scheduler erkennt, dass für diesen Job keine weitere Aktion mehr nötig ist. - Status-Monitoring: In kurzen Abständen fragt das System den aktuellen Status der Steckdosen bzw. Jobs ab, um z.B. die verbleibende Restlaufzeit zu berechnen oder zu erkennen, ob ein Benutzer eventuell vergessen hat, einen Druckauftrag zu beenden. Sollte eine Steckdose unerwarteterweise nicht den Befehl ausführen (z.B. Verbindung verloren), kann der Scheduler nach einer Wartezeit einen Wiederholungsversuch starten. Solche Ereignisse werden auch im Log vermerkt.
- Warteschlangenverwaltung: Falls mehrere Aufträge in direkter Folge auf einem Drucker geplant sind, koordiniert der Scheduler die Übergänge. Beispielsweise wird vermieden, dass ein Drucker ausgeschaltet wird, um kurz danach für den nächsten Job wieder eingeschaltet zu werden – stattdessen könnte ein fließender Übergang signalisiert werden (sofern im Anwendungsfall relevant). Im aktuellen System wird allerdings aus Sicherheitsgründen zwischen zwei Jobs immer ausgeschaltet, es sei denn ein Folgejob beginnt innerhalb weniger Minuten. Diese Logik ließe sich anpassen, wenn Dauerbetriebsphasen gewünscht sind.
Die Zeitlogik wurde mithilfe von Python-Zeitbibliotheken umgesetzt, wobei Zeitzone und Sommerzeit korrekt berücksichtigt werden (das System nutzt die Serverzeit des Raspberry Pi, der per NTP synchronisiert ist). Der Scheduler-Thread wird beim Start des Flask-Servers initialisiert und trägt sich auch selbst in die Datenbank bzw. Status-API ein, damit administratives Monitoring möglich ist (z.B. via /api/scheduler/status
kann geprüft werden, ob der Scheduler aktiv ist).
Besonderheiten und Feinabstimmung: Während der Umsetzung der Zeitsteuerung traten einige Herausforderungen auf. So musste z.B. entschieden werden, was passiert, wenn ein geplanter Auftrag vom Benutzer verlängert wird, während er bereits läuft. MYP löst dies so: Beim Extend (/extend
) wird die neue Endzeit in der DB aktualisiert und der Scheduler erhält ein Signal (oder liest periodisch die Endzeit neu aus). Entsprechend passt er den Abschalt-Timer an. Analog dazu werden Abbruchwünsche sofort umgesetzt. Ein weiterer Aspekt war die Genauigkeit: Das Ein- und Ausschalten erfolgt nahezu in Echtzeit zur Sollzeit, es können aber geringe Latenzen (Sekundenbereich) durch Verarbeitungszeit entstehen. Für den Anwendungsfall (3D-Druck) ist dies unkritisch. Sollten strengere Echtzeit-Bedingungen gefordert sein, könnte man hier noch optimieren (z.B. per präzisem Sleep bis zur Zielzeit anstatt Intervallprüfung).
Insgesamt ermöglicht die Kombination aus Smart-Plug-API und Scheduler eine vollautomatische Steuerung der Drucker-Stromversorgung basierend auf der Reservierungsplanung. Dies entlastet die Nutzer und garantiert, dass Drucker nur dann eingeschaltet sind, wenn sie tatsächlich gebraucht werden – ein praktischer Mehrwert des Projekts.
8. Backup-Frontend: technische Notlösung, Aufbau, Probleme
Die primäre Integration von MYP erfolgt in das bestehende Reservierungsportal des Unternehmens (die Haupt-Frontend-Lösung). Im Projektverlauf wurde allerdings deutlich, dass für Vorführungszwecke und als Ausfallsicherung ein eigenständiges Backup-Frontend nötig ist. Diese Notlösung stellt sicher, dass das System auch dann bedienbar und sichtbar bleibt, wenn die Hauptplattform nicht verfügbar ist – z.B. in der isolierten Prüfungsumgebung oder bei Netzwerkproblemen.
Haupt-Frontend (Integration): Geplant war, MYP so in die vorhandene Drucker-Reservierungsplattform zu integrieren, dass Endnutzer idealerweise gar nicht merken, dass ein separates System dahintersteht. Denkbar war etwa, dass im Firmen-Intranet eine Weboberfläche eingebettet wird oder das Portal über die MYP-API im Hintergrund kommuniziert. In der Praxis hätte dies bedeutet, dass z.B. ein Benutzer über die gewohnte Web-Oberfläche einen Druckjob bucht, und im Hintergrund ruft das Portal die MYP-API auf, um die Smart-Plug-Schaltung vorzunehmen. Diese Variante hätte den Vorteil, keine neue UI einführen zu müssen und bestehende Workflows beizubehalten. Allerdings erfordert eine solche Integration Abstimmungen mit dem bestehenden System (Datenformate, Authentifizierung) und ausreichende Berechtigungen (CORS und Firewall mussten angepasst werden, damit die Plattform im Firmennetz mit dem Pi kommunizieren darf). Während des Projekts wurde der Grundstein dafür gelegt (API bereitgestellt, CORS-Freigaben konfiguriert), jedoch konnte die vollständige Portal-Integration nicht in der vorgegebenen Zeit umgesetzt werden.
Backup-Frontend (PWA): Als technische Alternative wurde daher ein eigenständiges Web-Frontend entwickelt, das direkt auf die MYP-API zugreift. Dieses Frontend ist als Progressive Web App (PWA) gestaltet und wird vom Flask-Server gehostet. Es läuft unter derselben Adresse (Host/Port) wie das Backend, wodurch keine Cross-Origin-Probleme auftreten, wenn man es lokal aufruft. Das Backup-Frontend stellt alle nötigen Funktionen zur Verfügung: Benutzer-Login, Ansicht der Drucker und deren Status, Anzeige der vorhandenen Reservierungen sowie die Möglichkeit, neue Druckaufträge zu erstellen oder laufende Jobs zu steuern. Im Wesentlichen spiegelt es also die Funktionalität der API in einer grafischen Oberfläche wider.
Technisch wurde das Backup-Frontend mit HTML5, JavaScript und Tailwind CSS umgesetzt, um schnell ein responsive Design zu erreichen. Es verwendet Fetch-Aufrufe, um mit der Flask-API zu kommunizieren. Über einen Service Worker werden statische Assets und sogar API-Antworten zwischengespeichert, sodass die Oberfläche nach einmaligem Laden auch offline nutzbar ist – ein wichtiger Aspekt für den Demo-Modus ohne Internet. Die Authentifizierung ist nahtlos: nach Login erhält der Browser ein Session-Cookie vom Backend, welches für weitere API-Requests genutzt wird.
Einsatz im Kiosk-Modus: Das Backup-Frontend wird im Prüfungs- und Demonstrationsszenario im Kiosk-Modus gezeigt. Hierzu startet der Raspberry Pi automatisch einen Chromium-Browser im Vollbild, der die PWA lädt. Über die Autologin-Funktion von Raspbian und ein Startscript (kiosk.sh
) wird dieser Prozess beim Boot angestoßen. Der Kiosk-Browser zeigt eine spezielle Übersichtsseite, die primär für Anzeigezwecke gedacht ist (z.B. eine Statusübersicht aller Drucker und aktuellen Reservierungen, quasi „Dashboard"). Über einen administrativen Shortcut kann jedoch auch die normale Bedienoberfläche aufgerufen werden, um Interaktionen zu ermöglichen.
Struktur und Grenzen: Da das Backup-Frontend in begrenzter Zeit entstand, wurde es pragmatisch gehalten. Es verzichtet auf aufwändige grafische Elemente und konzentriert sich auf Funktionalität. Eine Herausforderung war, die Bedienung möglichst selbsterklärend zu gestalten, obwohl es sich um einen technischen Prototypen handelt. Kleinere Probleme, wie die Darstellung auf dem kleinen Touch-Bildschirm oder das automatische Neuladen der Seite, wurden iterativ behoben. Zudem musste das Frontend mit der selbstsignierten HTTPS-Konfiguration umgehen können. Im Kiosk-Browser wurde deshalb eingestellt, dass Zertifikatswarnungen ignoriert werden (im internen Netz vertretbar).
Ein weiteres Problemfeld war die Daten-Synchronisation zwischen Haupt- und Backup-Frontend: Wenn parallel das Firmenportal und die PWA genutzt würden, könnten theoretisch Inkonsistenzen auftreten (z.B. ein Benutzer bucht im Portal, sieht es nicht sofort im PWA). Da in der Praxis jedoch entweder das eine oder das andere Interface genutzt wird (nicht beide gleichzeitig aktiv im Einsatz), ist dies verkraftbar. Bei einer zukünftigen echten Parallel-Nutzung wäre ggf. eine WebSocket- oder Push-Mechanismus sinnvoll, um alle Clients synchron zu halten.
Zusammengefasst diente das Backup-Frontend als Fallback-Lösung, um die Funktionsfähigkeit von MYP jederzeit demonstrieren und gewährleisten zu können. Es hat sich im Test als äußerst nützlich erwiesen, insbesondere im Offline-Betrieb, und stellt sicher, dass der Zugriff auf die Druckersteuerung nicht von externen Systemen abhängig ist.
9. Herausforderungen und Problemlösungen während der Umsetzung
Während der Projektumsetzung traten diverse Herausforderungen auf, die mit geeigneten Lösungen adressiert wurden. Im Folgenden einige wichtige Punkte und wie sie gelöst wurden:
-
Lokale Plug-Steuerung (Reverse Engineering): Eine der größten technischen Hürden war das Ansteuern der Tapo P110 Steckdosen ohne Cloud. Anfangs schlugen einfache HTTP-Requests fehl, da die Kommunikation verschlüsselt abläuft. Lösung: intensive Recherche führte zur Verwendung der PyP110-Bibliothek, welche die nötigen Handshake- und Login-Vorgänge intern erledigt. Zusätzlich wurde mit Wireshark die Kommunikation der Tapo-App analysiert, um das Verständnis zu vertiefen. Dadurch konnte das Team sicherstellen, dass die Smart-Plugs stabil und schnell auf Befehle reagieren.
-
Abgeschottetes Netzwerk einrichten: Den Raspberry Pi gleichzeitig ins Firmennetz zu integrieren und ein isoliertes WLAN bereitzustellen, erwies sich als anspruchsvoll. Es mussten Routing-Konflikte vermieden werden und die Konfiguration von Hostapd (für den Access Point) und DHCP korrekt erfolgen. Eine Stolperfalle war z.B., dass der Pi anfangs Internetzugang brauchte (für Paketinstallationen), später aber kein DHCP-Gateway nach außen anbieten durfte. Durch sorgfältiges Anpassen der
/etc/dhcpcd.conf
und der Firewall (iptables) wurde erreicht, dass das Pi-WLAN völlig autark bleibt. Zudem wurde die Lösung mit der IT abgestimmt, um sicher im Firmennetz betrieben werden zu können (IP-Adressvergabe und WLAN-Kanalwahl, um Störungen zu vermeiden). -
Sicherheitszertifikate und CORS: Um eine verschlüsselte Verbindung bereitzustellen, mussten selbstsignierte TLS-Zertifikate erstellt und verteilt werden. Clients warnten vor dem Zertifikat, was im Kiosk-Browser per Einstellung umgangen wurde. Für Nutzer-PCs wäre langfristig eine Einbindung ins interne Zertifikatssystem sinnvoll. Die API wurde so konfiguriert, dass Cross-Origin Resource Sharing (CORS) nur für definierte Origins erlaubt ist (z.B. die Domain des Intranet-Portals). Dies stellte sicher, dass nur autorisierte Quellen auf die API zugreifen können. Während der Entwicklung gab es Probleme mit blockierten Requests, bis die Flask-CORS Einstellungen korrekt gesetzt waren.
-
Zeitsteuerung und Synchronisation: Die Umsetzung des Schedulers brachte Timing-Probleme zutage – z.B. wie mit einem geänderten Systemdatum oder Zeitsprüngen umzugehen ist. Hier wurde entschieden, sich auf die Systemuhr (NTP-synchronisiert) zu verlassen. Ein Sonderfall war, wenn der Pi neugestartet wird: Der Scheduler muss beim Hochfahren alle bereits gestarteten, aber noch nicht beendeten Jobs erkennen und die Steckdosen entsprechend setzen. Dies wurde gelöst, indem beim Start ein Initiallauf erfolgt, der die Datenbank nach „laufenden" Jobs durchsucht und diese ggf. (wieder) aktiviert oder abschaltet, falls Endzeit überschritten. Damit wird Konsistenz auch nach ungeplantem Neustart gewährleistet.
-
Datenbank-Locks und Gleichzeitigkeit: Da Flask standardmäßig mehrere Threads/Prozesse handhaben kann (insbesondere bei Verwendung von Werkzeug in Debug oder Gunicorn als Server), traten potenziell race conditions beim Datenbankzugriff auf. SQLite erlaubt zwar gleichzeitiges Lesen, aber beim Schreiben gab es anfangs Locking-Issues, als der Scheduler und ein Web-Request parallel auf die DB zugreifen wollten. Dies wurde durch ein Thread-Locking im Code gelöst und indem Schreibzugriffe kurz gehalten bzw. seriell angeordnet wurden. In einem späteren Ausbau könnte hier ein Wechsel auf einen robusteren DB-Server (PostgreSQL) ratsam sein, aber im Testbetrieb reichte die angepasste SQLite-Nutzung aus.