Lets you record what a binding actually does (e.g. "Save in Fusion
360") alongside the auto-generated label ("Strg+S"). Notes live in a
new "note" field on every action dict, purely local like profile
names -- the firmware struct has no room for strings, and
pack_config/unpack_config already only touch type/data so the extra
key round-trips harmlessly.
Two things had to be handled carefully: changing a button's key/type
must not wipe its note (all set_button_*/set_encoder_* setters and the
edit dialog now carry the previous note forward), and re-reading from
the board must not erase notes either, since the firmware doesn't know
about them -- versapad_combined.merge_notes() restores them onto the
freshly-fetched state by button/encoder index.
Editable via the Programmiermodus dialog (new text field), visible on
both the desktop card (grown from 84 to 114px to fit it) and the
browser view. MCP server gets set_button_note()/set_encoder_note() so
notes can be set programmatically too.
167 lines
8.2 KiB
Markdown
167 lines
8.2 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 neben der
|
||
Installation (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
|
||
|
||
## 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, siehe `versapad_combined.py`) liegt neben der
|
||
Installation: bei der gebauten `.exe` im selben Ordner, beim Start aus dem
|
||
Quellcode im Projektordner (`versapad_data.app_dir()`). Fehlt sie (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.
|
||
|
||
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). In der MCP-Server-Liste der jeweiligen Anwendung
|
||
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
|
||
|
||
## Weiterentwicklung
|
||
|
||
Tiefere technische Notizen (Protokoll-Details, bekannte Stolpersteine beim
|
||
Bauen, Design-Entscheidungen) stehen in [`AGENTS.md`](AGENTS.md).
|
||
|
||
## Lizenz / Herkunft
|
||
|
||
Eigenständiges Begleit-Tool, kein Teil der offiziellen VersaGUI/VersaMCU-Repos.
|