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.
193 lines
9.6 KiB
Markdown
193 lines
9.6 KiB
Markdown
# 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.
|