VersaGUI-py/README.md
Julian Appel 189ec01e68 Merge branch 'main' into dev/jappel
Reconciles two independent lines of work: main cherry-picked and then
extended dev/jappel's build-script/config-portability/rename-tab/
COM-port fixes, additionally fixing a config-loss bug (rebuild wiped
the config when it lived in the install dir -- moved to roaming
%APPDATA% instead) and adding free-text notes per action plus a
frameless resizable window. dev/jappel keeps its .mcp.json registration
and docs/ reference tree, which main deliberately left out.

Conflict resolutions favored main's versions where the two sides solved
the same problem (config location, build deploy target, COM-port
release, tab rename) since main's fixes were validated against a real
rebuild-wipes-config incident. docs/architecture.md and
docs/data-model.md updated to describe the resulting %APPDATA% config
path and the note field.
2026-08-15 18:16:00 +02:00

193 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# VersaPad Viewer
Ein eigenständiges Tool für das [VersaPad](https://git.jappel.io/jappel/VersaMCU)-Makropad
(4×5-Button-Grid + 4 Encoder, SAMD21-Firmware von jappel). Zeigt die aktuelle
Belegung an, kann sie live mit dem Board synchronisieren und komplett neu
programmieren — als Ergänzung zur offiziellen [VersaGUI](https://git.jappel.io/jappel/VersaGUI)
(C#/.NET), nicht als Ersatz.
Aktive Weiterentwicklung. Lesemodus, Live-Sync, Programmiermodus (inkl.
Board-Schreibzugriff) und der MCP-Server sind funktionsfähig und gegen ein
echtes Board getestet (Read-Modify-Write ist byte-identisch zum Original,
inklusive CRC). Nicht vorhanden: automatisierte Tests (Verifikation läuft
manuell gegen ein angeschlossenes Board), eine vorgefertigte `.exe` zum
Download (siehe unten, warum), und Mehrbenutzer-/Netzwerkbetrieb. Die eigene
Config-Datei (`versapad_config_all.json`) liegt automatisch unter
`%APPDATA%\VersaPadViewer\` (siehe „Aufbau" unten) und wird bei Bedarf
automatisch neu angelegt — kein manuelles Pfad-Anpassen mehr nötig. Nur die *optionale*
Lese-Interop mit den JSON-Exports der offiziellen VersaGUI
(`versapad_data.CONFIG_PATHS`) ist noch für eine bestimmte Windows-Maschine
hartkodiert (OneDrive-Desktop) — für einen anderen Rechner dort anpassen,
falls gewünscht.
## Features
- **Steuermatrix-Anzeige** — 4×5-Button-Grid + 4 Encoder, farbige LED-Vorschau,
lesbare Beschriftung (z.B. "Strg+S" statt Rohwerten)
- **Zwei Anzeige-Wege:** Browser (`server.py`, `localhost:8765`) oder natives
Desktop-Fenster (`desktop_viewer.py`, Tkinter)
- **Live-Sync** — pollt per Serial, welches Profil gerade am Board aktiv ist,
und schaltet die Ansicht automatisch mit
- **Programmiermodus** — Zellen anklicken und bearbeiten (Taste, Medientaste,
Makro, Profilwechsel, LED-Farbe/Animation), direkt aufs Board schreiben
oder als Datei speichern
- **Makro-Editor** — bis zu 8 Schritte pro Slot, liest/schreibt die echte
Makro-Tabelle vom Board
- **Notizen** — freier Text pro Button/Encoder-Aktion, was sie tatsächlich
tut (z.B. "Speichern in Fusion 360"), zusätzlich zur automatischen
Beschriftung ("Strg+S"). Rein lokal wie Profilnamen, geht nie aufs Board,
bleibt beim Tastenwechsel und beim "Vom Board laden" erhalten
- **MCP-Server** — lässt eine KI (Claude o.ä.) die Belegung direkt per
Tool-Aufruf ändern, ohne Klicks in der GUI (siehe unten)
- **Tray-Icon** — minimiert/schließt ins Tray statt in die Taskleiste, wie
die offizielle VersaGUI
- **Randloses Fenster** — ohne Windows-Titelleiste, dafür kompakter Kopf
(Modus-Checkboxen direkt neben dem Titel). Verschieben durch Ziehen an
der Kopfzeile, Größe ändern am Anfasser unten rechts, `✕`/`—` legen ins
Tray. Einen Taskleisten-Eintrag gibt es dadurch nicht — das Fenster kommt
über das Tray-Icon zurück.
## Voraussetzungen
- Python 3.11 oder neuer
- Alle Pakete stehen in `requirements.txt` (`pyserial` fürs Board,
`pystray` + `pillow` fürs Tray-Icon/Desktop-Fenster, `mcp` für den
MCP-Server, `pyinstaller` fürs `.exe`-Bauen):
```bash
pip install -r requirements.txt
```
Für den Browser-Modus (`server.py`) reicht die Python-Standardbibliothek —
keine zusätzlichen Pakete nötig. `build_and_deploy.ps1` installiert
`requirements.txt` beim Bauen automatisch selbst — ein manuelles
`pip install` vorher ist dafür nicht nötig.
## Starten
**Aus dem Quellcode:**
```bash
py server.py # Browser-Ansicht: http://127.0.0.1:8765
py desktop_viewer.py # natives Fenster (Konsole sichtbar, zum Debuggen)
pyw desktop_viewer.py # natives Fenster ohne Konsolenfenster
```
**Als eigenständige `.exe` (Windows):** Es liegt keine fertige `.exe` im
Repo (Build-Artefakte sind bewusst nicht eingecheckt — sie sind groß und pro
Maschine/Python-Version unterschiedlich). Selbst bauen:
```powershell
.\build_and_deploy.ps1
```
Das Skript installiert/aktualisiert selbst alle nötigen Pakete aus
`requirements.txt` (kein manuelles `pip install` vorher nötig), baut dann
mit PyInstaller (`--onedir --windowed`, eigenes Icon) und kopiert das
Ergebnis nach `%LOCALAPPDATA%\VersaPadViewer\VersaPadViewer.exe`.
Bricht ein Schritt ab (fehlendes Python, PyInstaller-Fehler, ...), zeigt das
Skript eine klare Fehlermeldung und wartet auf einen Tastendruck, statt sich
bei Doppelklick im Explorer kommentarlos zu schließen (`-NoPause`
unterdrückt das für automatisierte Aufrufe/CI).
**Wichtig:** Sowohl Bauen als auch Ausführen müssen auf einem lokalen
Laufwerk passieren — von einem Netzlaufwerk (SMB-Share) aus scheitert
PyInstaller beim Bauen (Pfadlängen-Problem mit Tcl/Tk-Zeitzonendaten) und
die fertige `.exe` startet zur Laufzeit gar nicht erst (Windows blockiert
das Nachladen der Bundle-DLLs von einem Netzwerkpfad, ohne jede
Fehlermeldung). `build_and_deploy.ps1` kopiert den Quellcode deshalb
automatisch zuerst nach `%TEMP%` und baut nur dort.
## Aufbau
| Datei | Zweck |
|---|---|
| `versapad_data.py` | Decoding für die Anzeige: JSON laden, HID-Keycodes/Consumer-IDs/Modifier → lesbarer Text |
| `versapad_protocol.py` | Binäres NVM-Layout des Boards (740B Config + 512B Makros), CRC16 — pack/unpack |
| `versapad_serial.py` | Serial-Client: liest/schreibt Config + Makros per 8-Byte-Paket-Protokoll |
| `versapad_combined.py` | Ein-Datei-Format für alle 3 Profile + Makros + lokale Profilnamen |
| `server.py` | Browser-Frontend (nur lesend) |
| `desktop_viewer.py` | Tkinter-Frontend (lesend, Live-Sync, Programmiermodus, Tray) |
| `action_dialog.py` | Bearbeiten-Dialoge für den Programmiermodus |
| `versapad_mcp_server.py` | MCP-Server für KI-Tool-Aufrufe |
Das Binärformat (`versapad_protocol.py`) ist 1:1 aus den
VersaMCU-Firmware-Quellen übernommen und gegen ein echtes Board validiert
(Read → unpack → pack ist bytegenau identisch zum Original, inklusive CRC).
Die eigene Config-Datei (`versapad_config_all.json` — alle 3 Profile +
Makros + lokale Profilnamen + Notizen, siehe `versapad_combined.py`) liegt
unter `%APPDATA%\VersaPadViewer\` (`versapad_data.app_dir()`), also
**getrennt vom Installationsordner** und unabhängig davon, ob die `.exe`
oder der Quellcode gestartet wurde. Beides ist Absicht: das Build-Skript
räumt sein Zielverzeichnis vor jedem Deploy komplett ab (läge die Config
dort, würde jeder Rebuild sie löschen), und ein vom Startweg abhängiger
Pfad hatte zu zwei auseinanderlaufenden Configs geführt. Fehlt die Datei
(z.B. frische Installation), wird sie automatisch angelegt — per Serial vom
Board, falls eins angeschlossen ist, sonst als leere Default-Config.
Profilnamen (`profile_names`) stehen direkt in dieser Datei und lassen sich
per Doppelklick auf einen Tab (in jedem Modus — Nur-Lesen, Live-Sync oder
Programmiermodus) oder `rename_profile()` (MCP) ändern. Notizen ebenso —
im Bearbeiten-Dialog des Programmiermodus oder per
`set_button_note()`/`set_encoder_note()` (MCP).
Die klassischen `versapad_config1/2/3.json` sind kein von diesem Tool
geschriebenes Format, sondern optionale Lese-Interop mit einem JSON-Export
der offiziellen VersaGUI (C#/.NET) — Pfad aktuell hartkodiert auf den
OneDrive-Desktop einer bestimmten Windows-Maschine, siehe `CONFIG_PATHS` in
`versapad_data.py`.
## MCP-Server
`versapad_mcp_server.py` macht die Config per Tool-Aufruf statt Hand-JSON
programmierbar — nutzbar von jeder MCP-fähigen KI-Anwendung (Claude Code,
Claude Desktop, andere). Für Claude Code liegt bereits eine projektgebundene
[`.mcp.json`](.mcp.json) im Repo (Server "versapad", Kommando `py
versapad_mcp_server.py`) — beim Öffnen des Projekts wird sie automatisch
zum Verbinden angeboten. Für andere Anwendungen oder user-scope-Registrierung
in der jeweiligen MCP-Server-Liste eintragen: Kommando `python`/`py`,
Argument der Pfad zu `versapad_mcp_server.py`.
Werkzeuge (Auszug): `list_profiles`, `get_profile`, `get_macro`,
`get_board_status` (lesen) · `set_button_key`/`_consumer`/`_macro`/
`_profile_switch`/`_none`/`_led`, dieselben `set_encoder_*`, `set_macro`,
`rename_profile` (bearbeiten) · `save_local`/`load_local` (Datei),
`load_from_board`/`write_to_board` (Board). `set_*`-Aufrufe ändern nur
einen In-Memory-Zustand — erst `save_local()` oder `write_to_board()` macht
die Änderung dauerhaft. Volle Liste mit Details: Info-Button (ⓘ) oben
rechts im Fenster, oder direkt in `versapad_mcp_server.py`.
## Bekannte Einschränkungen
- Der COM-Port ist exklusiv — Live-Sync/Programmiermodus können nicht
gleichzeitig mit der offiziellen VersaGUI laufen (die läuft dauerhaft als
Tray-App weiter, auch wenn nur ihr Konfigurationsfenster geschlossen wird
— für Parallelbetrieb muss sie über ihr Tray-Menü beendet werden)
- HID-Tasten-Auswahl im Programmiermodus ist ein Dropdown, kein
Tastendruck-Capture (bewusst, um keinen WinAPI-Hook zu brauchen)
- Zeichentasten-Labels zeigen eine US-Layout-Näherung, nicht das tatsächlich
aktive Tastatur-Layout
- Unsignierte `.exe` — kann von Antivirus/Smart App Control blockiert
werden; `--onedir` (statt `--onefile`) verringert das Risiko, verhindert
es aber nicht
## Dokumentation
Ausführlichere technische Doku im [`docs/`](docs/)-Ordner:
- [`docs/architecture.md`](docs/architecture.md) — Schichtenmodell,
Prozessmodell, Modi, Config-Speicherort, Nebenläufigkeit
- [`docs/data-model.md`](docs/data-model.md) — JSON-Formate (kombiniert +
Legacy), binäres NVM-Layout, Geometrie, Enums
- [`docs/protocol.md`](docs/protocol.md) — Serial-Wire-Protokoll (Befehle,
Events, Paketformat, CRC16)
## Weiterentwicklung
Agentenseitige Notizen (Domänenregeln, bekannte Bugs und ihre Fixes,
Implementierungsdisziplin, Design-Entscheidungen) stehen in
[`AGENTS.md`](AGENTS.md).
## Lizenz / Herkunft
Eigenständiges Begleit-Tool, kein Teil der offiziellen VersaGUI/VersaMCU-Repos.