VersaGUI/doc/00_architecture.md
2026-03-30 19:51:38 +02:00

3.3 KiB
Raw Permalink Blame History

VersaGUI Architektur-Übersicht

Technologie-Stack

Merkmal Wert
Sprache C# / .NET 7
UI-Framework WinForms ([STAThread])
Einstiegspunkt Program.csApplication.Run(new TrayApp())
Laufzeitmodell ApplicationContext (kein Form als Hauptfenster)
Threading UI-Thread + 1 Hintergrund-Lese-Thread + Timer-Thread

Komponentenübersicht

Datei Verantwortung
TrayApp ApplicationContext; hält Tray-Icon, öffnet ConfigForm, verarbeitet Board-Events
SerialManager Verbindungsverwaltung, WMI-Erkennung, Lese-Thread, Sende-Methoden
ConfigForm Hauptfenster (Grid + Encoder-Panel + Footer); öffnet ActionDialog
ActionDialog Modaler Dialog zum Bearbeiten einer Aktion + LED-Einstellungen
DeviceConfig C#-Spiegel von SDeviceConfig; Serialisierung/Deserialisierung (223 B)
MacroTable C#-Spiegel von SMacroTable; Serialisierung/Deserialisierung (256 B)
ConfigJson JSON-Import/Export für DeviceConfig
Protocol Konstanten für alle Command/Event-IDs (spiegelt usb_serial.h)

Datenfluss

Board → SerialManager (ReadLoop, BG-Thread)
    → SynchronizationContext.Post (→ UI-Thread)
        → TrayApp.OnPacket()
            ├── Config-Dump: _rxConfigBuf aufbauen → DeviceConfig.FromBytes()
            ├── Makro-Dump:  _rxMacroBuf aufbauen  → MacroTable.FromBytes()
            └── HOST_COMMAND-Events: (TODO: Aktion ausführen)

Benutzer → ConfigForm → ActionDialog
    → DeviceConfig / MacroTable (in-memory ändern)
    → SerialManager.SendConfig() + SendMacros() (BG-Task)
        → Board (chunked, 6 B/Paket)

Threading-Modell

UI-Thread        : TrayApp, ConfigForm, ActionDialog, alle WinForms-Controls
BG-Thread        : SerialManager.ReadLoop()  blockiert auf ReadByte()
Timer-Thread     : SerialManager._reconnectTimer → TryConnect() alle 3 s
Sende-Task       : ConfigForm.OnSave() → Task.Run() (blockiert ~400 ms für Transfer)

Alle Board-Events werden per SynchronizationContext.Post auf den UI-Thread gepostet. Controls dürfen nie vom BG-Thread angefasst werden.

Verbindungslebenszyklus

Start → Timer feuert → TryConnect() → WMI-Suche (VID 0x239A / PID 0x0042)
  → SerialPort öffnen (DtrEnable=true VOR Open()!)
  → 200 ms warten → ReadLoop starten → Connected-Event → RequestConfig() + RequestMacros()

Disconnect → ReadLoop bricht ab → Disconnected-Event → 5 s Backoff → Timer läuft weiter

Invarianten / Constraints

  • DtrEnable=true muss VOR Open() gesetzt werden: SAMD21 prüft DTR für usb_serial_send(). Der Default-Wert false würde alle Board→PC-Antworten still verwerfen.
  • IOException ≠ Disconnect: .NET 7 wirft IOException statt TimeoutException bei ReadByte()-Timeout. Nur als echten Fehler behandeln wenn _port.IsOpen == false.
  • Packed-kompatible Serialisierung: DeviceConfig.ToBytes() muss exakt 223 B in derselben Reihenfolge wie SDeviceConfig (packed C++) erzeugen. Jede Änderung am Firmware-Layout muss hier gespiegelt werden.
  • Config-Version: DeviceConfig.Version == 2. FromBytes() prüft Magic + Version + CRC; schlägt einer fehl → Methode gibt false zurück, Config bleibt unverändert.
  • Debug-Log: versapad_rx.txt in %TEMP% vor Release-Nutzung entfernen (TODO).