Dieses Dokument beschreibt die integrale Architektur-Erweiterung des ionpy-Frameworks. Es dient als verbindliche Grundlage für die Implementierung neuer Entitätstypen, haptischer Steuerungen und geräteübergreifender Automatisierung.
Um zu verhindern, dass Hintergrund-Polling Benutzereingaben im Frontend überschreibt, wird ein duales Sperrsystem implementiert.
[cite_start]In der Klasse AbstractDevice (hardware/base.py) wird eine zeitbasierte Sperre pro Entität eingeführt[cite: 117, 120].
self._last_command_time: Dict[str, float] speichert den Zeitpunkt des letzten Schreibbefehls[cite: 11, 54].execute_command() aufgerufen wird, erhält die entity_id einen Zeitstempel[cite: 13, 138].update_entity() prüft diesen Zeitstempel: Liegt er weniger als 3,0 Sekunden in der Vergangenheit, wird das Sample verworfen und nicht auf den Bus publiziert[cite: 87, 136].In der Web-UI (settings.html) wird eine automatische Erkennung aktiver Eingabefelder implementiert.
Set() namens activeInputs.focusin: Fügt die Element-ID zum Set hinzu.focusout: Entfernt die ID nach einer kurzen Verzögerung (ca. 300-500ms).channel.onmessage prüft vor dem Update eines HTML-Elements, ob dessen ID im Set vorhanden ist. [cite_start]Falls ja, wird das Update verworfen[cite: 53, 54].
Die TableEntity ist das Herzstück für komplexe Geräteeigenschaften wie Speicherplätze (M1-M10), Profil-Listen (Sequenzer) oder Zell-Übersichten.
Eine TableEntity kapselt nicht nur Daten, sondern auch deren Bedeutung.
key, name, type (number/text/toggle/action), unit, sowie Constraints (min, max, step).fixed_size (z.B. genau 10 Speicherplätze) und dynamic_size (Zeilen hinzufügbar/löschbar).{ “row”: r, “col”: “key”, “val”: value }.button. Dies ermöglicht “Apply”-Buttons pro Zeile, um einen kompletten Parametersatz (z.B. Volt und Ampere eines Presets) gleichzeitig an die Hardware zu senden, um instabile Zustände zu vermeiden.active_row_index markiert die Zeile, die das Gerät aktuell tatsächlich verwendet (z.B. welcher Speicherplatz gerade geladen ist).
Haptische Steuerung via USB-Controller, realisiert durch das pygame-Subsystem.
Ein neuer Treiber-Typ, der autonom nach Controllern sucht.
pygame.joystick.get_count() und get_id(), um Controller dynamisch zu finden, ohne Hardcoding in der Config[cite: 63, 64].value-Feld hält[cite: 135].UIMode.LEVEL)[cite: 422].
[cite_start]Zentraler asynchroner Dienst in der SystemEngine[cite: 81], der als Vermittler zwischen dem Bus und den Geräte-Kommandos fungiert.
[cite_start]Der Dienst abonniert den EventBus [cite: 85, 427] und prozessiert Regeln aus einer rules.json.
engine.execute_command(target_dev, key, transformed_val)[cite: 84, 433].[cite_start]Zusätzliche spezialisierte Typen für professionelle Laboranforderungen[cite: 421, 422, 423]:
| Typ | UI-Repräsentation | Funktionalität |
|---|---|---|
| LogEntity | Scrollende Konsole | Lokaler Ereignis-Speicher für gerätespezifische Fehler (z.B. SCPI-Fehlermeldungen). |
| StatusIndicator | Virtuelle LED | Farb-Mapping für Zustände (z.B. 0=Off, 1=OK/Grün, 2=Warnung/Gelb, 3=Alarm/Rot-Blinkend). |
| XYGraphEntity | Kennlinien-Plot | Darstellung von X-Y-Beziehungen (z.B. Batterie-Entladekurve: Spannung über Kapazität). |
| FileEntity | Upload/Download | Schnittstelle für Firmware-Dateien (z.B. ESPHome .bin) oder Konfigurations-Exports. |
| RangeEntity | Multi-Slider/Input | Gruppiert logisch zusammengehörige Werte für Sweeps (Start, Stop, Step, Intervall). |
| ScheduleEntity | Zeitplan-Editor | Verwaltung von Zeitereignissen (z.B. “Schalte Ausgang an Wochentagen um 08:00 Uhr an”). |
async/await) ausgeführt werden, um den Hardware-Poll-Loop nicht zu blockieren[cite: 1, 9].SystemEngine nutzt ihren state_cache als “Single Source of Truth” für die Logic-Regeln[cite: 81, 84].structures/entities.py definiert und in der settings.html mit einem entsprechenden UI-Generator verknüpft werden.Um die wachsende Komplexität der Daten (Gamepad, BMS, IMU-Sensoren) beherrschbar zu machen, werden spezialisierte Views implementiert.
Diese View nutzt Bibliotheken wie Three.js oder Plotly.js, um Daten im dreidimensionalen Raum darzustellen.
VectorEntity [cite: 419]). [cite_start]Ein 3D-Modell (z.B. ein PCB oder eine Batteriebox) neigt sich in Echtzeit entsprechend der Daten aus dem VirtualLaboratory[cite: 252, 263].
[cite_start]Die aktuelle UI ist stark auf einzelne Tabs pro Gerät fokussiert[cite: 16]. Die Global View bricht diese Struktur auf.
UDP3305 [cite: 303][cite_start], den Zellstatus vom JbdBms [cite: 145] [cite_start]und die Lastdaten der AtorchDL24 [cite: 211] auf einer einzigen Seite zusammenfasst.
Da der geplante LogicService komplex werden kann, ist eine textuelle Regel-Liste oft unübersichtlich.
EventBus fließt[cite: 85].
[cite_start]Basierend auf dem SessionManager.
session_id ) ausgewählt werden. Die UI zeigt dann die historischen Daten so an, als würden sie gerade live passieren.Was ich mir sonst noch vorstellen könnte:
Diese View kombiniert visuelles Feedback der Hardware mit den Live-Daten des EventBus.
/api/video/stream.config.yaml des Geräts gespeichert.Zusätzlich zum Videostream kann das System Bildbereiche (ROI) analysieren, um “virtuelle Sensoren” zu generieren.
1. ROI Definition via Koordinaten.
2. HSV-Farbraumfilterung zur Detektion von Statusfarben. 3. State-Machine zur Vermeidung von Bus-Spam (nur Änderungen werden publiziert). * **Anwendung**: "BMS Alarm LED" -> EventBus -> "PSU OFF".
Verwandelt visuelle Anzeigen in digitale Datenströme.
Tesseract oder SSOCR in den Webcam-Treiber.1. Extraktion der Anzeige via ROI.
2. Bildvorbehandlung (Grayscale, Thresholding, Morphologie). 3. Konvertierung String -> Float/Int. 4. Publikation als ''NumericSample'' oder ''TextSample'' auf dem EventBus. * **Anwendung**: Digitalisierung von Legacy-Hardware ohne Schnittstellen (DMMs, Waagen, analoge Anzeigen).
Der Datenfluss im erweiterten System folgt nun diesem Muster: