3.3 KiB
3.3 KiB
VersaGUI – Architektur-Übersicht
Technologie-Stack
| Merkmal | Wert |
|---|---|
| Sprache | C# / .NET 7 |
| UI-Framework | WinForms ([STAThread]) |
| Einstiegspunkt | Program.cs → Application.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ürusb_serial_send(). Der Default-Wert false würde alle Board→PC-Antworten still verwerfen. - IOException ≠ Disconnect: .NET 7 wirft
IOExceptionstattTimeoutExceptionbeiReadByte()-Timeout. Nur als echten Fehler behandeln wenn_port.IsOpen == false. - Packed-kompatible Serialisierung:
DeviceConfig.ToBytes()muss exakt 223 B in derselben Reihenfolge wieSDeviceConfig(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 gibtfalsezurück, Config bleibt unverändert. - Debug-Log:
versapad_rx.txtin%TEMP%– vor Release-Nutzung entfernen (TODO).