# 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. Der Dialog öffnet über dem Hauptfenster, Enter bestätigt, Escape bricht ab - **Tastendruck-Erkennung** — statt die Taste im Dropdown zu suchen, „⌨ Taste drücken" klicken und die gewünschte Kombination einfach drücken (Modifier inklusive). Läuft über das Dialogfenster, nicht über einen System-Hook — vom System abgefangene Kombinationen (Win+L, Strg+Alt+Entf) kommen deshalb nicht an, und das Dropdown bleibt zum Nachkorrigieren daneben stehen - **Makro-Editor** — bis zu 8 Schritte pro Slot, liest/schreibt die echte Makro-Tabelle vom Board. Schritte einzeln erfassen oder die ganze Folge am Stück aufnehmen („⏺ Folge aufnehmen"). Die Slot-Auswahl listet alle 32 Slots samt Inhalt, statt sie einzeln durchklicken zu müssen - **Makros im Grid lesbar** — eine Makro-Belegung zeigt die tatsächliche Tastenfolge (`Makro 3: Strg+C → Strg+V`) statt nur der Slot-Nummer; das gilt auch in der Browser-Ansicht und in den MCP-Antworten - **Farb-Schnellwahl** — zwölf Grundfarben direkt in der LED-Zeile des Dialogs, der System-Farbdialog nur noch für den Rest („mehr…") - **Kopieren/Einfügen zwischen Tasten** — Rechtsklick auf eine Karte im Programmiermodus: Belegung und/oder Farbe kopieren und auf andere Tasten anwenden, oder die Belegung leeren. Strg+C/Strg+V wirken auf die Karte unter dem Mauszeiger - **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. - **Tastenkürzel im Hauptfenster** — `Strg+1/2/3` Profil wechseln, `F2` Profil umbenennen, `Strg+E` Programmiermodus an/aus, `Strg+C`/`Strg+V` Taste unter dem Mauszeiger kopieren/einfügen, `Esc` ins Tray. ## 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) - Die Tastendruck-Erkennung läuft bewusst über das Dialogfenster statt über einen globalen WinAPI-Hook — vom System abgefangene Kombinationen (Win+L, Strg+Alt+Entf) erreichen das Fenster nie und lassen sich so nicht erfassen - Zeichentasten-Labels zeigen eine US-Layout-Näherung, nicht das tatsächlich aktive Tastatur-Layout. Das betrifft auch die Tastendruck-Erkennung: HID-Keycodes sind physische US-Tastenpositionen, erkennbar ist ohne WinAPI aber nur das Zeichen des aktiven Layouts — auf deutschem Layout landen Y und Z deshalb vertauscht auf dem Board. Das Ergebnis steht immer sichtbar im Dropdown und lässt sich dort korrigieren - 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.