Restructure AGENTS.md to the projekt-doku standard, audit README status
AGENTS.md now follows the mandated section structure (Project Goal, Aktuell unterstützte Architektur, Kritische Domänenregeln, Existing-Codebase-Regel, Implementierungsdisziplin, Naming, Deferred Work, Dokumentation und Verifikation) instead of an organically grown set of headings. Folds in all prior technical notes (protocol validation, network-drive build/runtime gotchas, threading rules) under the appropriate section, and fixes a stale "no tray icon yet" line that no longer matched the code. README gets an explicit honest status paragraph (what's tested, what's not: no automated tests, no prebuilt exe download, hardcoded paths). No docs/ tree: project has no database or persistent multi-user service, so the full doc structure isn't warranted per the standard.
This commit is contained in:
parent
d25044be25
commit
553ecc54d8
2 changed files with 176 additions and 176 deletions
340
AGENTS.md
340
AGENTS.md
|
|
@ -1,201 +1,191 @@
|
|||
# versapad-viewer
|
||||
# AGENTS.md
|
||||
|
||||
Eigenes kleines Tool (Grovy311-Kontext, nicht Teil der fremden jappel-Repos
|
||||
VersaGUI/VersaMCU). Zeigt die Steuermatrix (4x5 Button-Grid + 4 Encoder) als
|
||||
Browser-Live-Seite oder natives Tkinter-Fenster. Inzwischen mehr als ein
|
||||
reiner Viewer: der Tkinter-Desktop-Viewer hat einen vollen Programmiermodus
|
||||
(Action-Editor, Serial-Schreibzugriff aufs Board, Makro-Editor) bekommen —
|
||||
faktisch ein schlankes Python-Pendant zu VersaGUI. Der Browser-Server
|
||||
(`server.py`) blieb bewusst read-only/einfach.
|
||||
## Project Goal
|
||||
|
||||
## Architektur
|
||||
Eigenständiges Begleit-Tool für das VersaPad-Makropad (Grovy311-Kontext,
|
||||
nicht Teil der fremden jappel-Repos VersaGUI/VersaMCU). Zeigt die
|
||||
Steuermatrix (4×5-Button-Grid + 4 Encoder) an, synchronisiert sie live mit
|
||||
dem Board und kann sie komplett neu programmieren — inzwischen ein
|
||||
schlankes Python-Pendant zur offiziellen VersaGUI (C#/.NET), plus ein
|
||||
MCP-Server, der dieselbe Programmierung per KI-Tool-Aufruf ermöglicht.
|
||||
Nutzerorientierte Einführung: [`README.md`](README.md).
|
||||
|
||||
## Aktuell unterstützte Architektur
|
||||
|
||||
**Read-only-Schicht (JSON, beide Frontends):**
|
||||
- `versapad_data.py` — Decoding fuer Anzeige: JSON laden, HID-Keycode/
|
||||
Consumer-Usage/Modifier → lesbarer Text, Grid-Geometrie (index =
|
||||
spalte*5+reihe), `hid_key_choices()`/`consumer_choices()` fuer Dropdowns.
|
||||
- `server.py` — stdlib `http.server`, generiert HTML bei jedem Request neu,
|
||||
- `versapad_data.py` — Decoding für Anzeige: JSON laden, HID-Keycode/
|
||||
Consumer-Usage/Modifier → lesbarer Text, Grid-Geometrie
|
||||
(`index = spalte*5+reihe`), `hid_key_choices()`/`consumer_choices()`.
|
||||
- `server.py` — stdlib `http.server`, generiert HTML pro Request neu,
|
||||
Profil-Wechsel über `?profile=0|1|2`, Auto-Reload alle 4s. Rein lesend,
|
||||
kein Programmiermodus (bewusst einfach gehalten).
|
||||
|
||||
**MCP-Server (Config per KI-Tool-Aufruf statt Hand-JSON):**
|
||||
- `versapad_mcp_server.py` — registriert als User-Scope-MCP-Server "versapad"
|
||||
(`claude mcp add -s user versapad -- <Python313> versapad_mcp_server.py`,
|
||||
landet in `~/.claude.json`). Tools: `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` (mutieren nur In-Memory-State), `save_local`/
|
||||
`load_local` (↔ `versapad_config_all.json`), `load_from_board`/
|
||||
`write_to_board` (↔ echtes Board per Serial). Nutzt das MCP-SDK v2 (Paket
|
||||
`mcp`, Klasse `mcp.server.mcpserver.MCPServer` — **nicht** `FastMCP` aus
|
||||
`mcp.server.fastmcp`, das gibt's in dieser SDK-Version nicht mehr, wurde
|
||||
umbenannt). `@mcp.tool()`-dekorierte Funktionen bleiben direkt aufrufbar
|
||||
(kein `.fn`-Unterschied wie bei alten FastMCP-Versionen).
|
||||
|
||||
**Binaer-/Serial-Schicht (fuer den Programmiermodus):**
|
||||
- `versapad_protocol.py` — pack/unpack fuer `SDeviceConfig`(740B, alle 3
|
||||
**Binär-/Serial-Schicht (Programmiermodus + MCP):**
|
||||
- `versapad_protocol.py` — pack/unpack für `SDeviceConfig` (740B, alle 3
|
||||
Profile) und `SMacroTable` (512B, 32 Slots) + CRC16 (Poly 0x1021, Init
|
||||
0xFFFF), 1:1 aus den Firmware-Structs (`nvm_config.h`, `action.h`,
|
||||
`macro_config.h`, `CButton.h`-LEDAnim-Enum, `nvm_config.cpp`-CRC).
|
||||
**Gegen echtes Board validiert:** read → unpack → pack → byte-identisch
|
||||
zum Original, inkl. CRC — siehe Git-Historie dieser Datei / Sessionlog.
|
||||
0xFFFF), 1:1 aus den Firmware-Structs. **Gegen echtes Board validiert:**
|
||||
read → unpack → pack ist byte-identisch zum Original, inkl. CRC.
|
||||
- `versapad_serial.py` — `VersaPadLink`: liest/schreibt komplette Config +
|
||||
Makros per 8-Byte-Paket-Protokoll (`CmdConfigRead/Begin/Data/Commit`,
|
||||
`CmdMacroRead/Begin/Data/Commit`), Board-Identifikation per VID/PID
|
||||
Makros per 8-Byte-Paket-Protokoll, Board-Identifikation per VID/PID
|
||||
`239A:0042`. Schreiben ist sicher im Sinne von "kann NVM nicht zerlegen"
|
||||
— Firmware prueft Magic/CRC/Keycode-Bereich vor jedem Save und antwortet
|
||||
sonst nur mit NACK (kein Datenmuell moeglich).
|
||||
- `versapad_combined.py` — kombiniertes Ein-Datei-Format (alle 3 Profile +
|
||||
Makros + **nur lokal gespeicherte** Profilnamen) statt der 3 Einzel-JSONs.
|
||||
Passt besser zum Wire-Protokoll: `CONFIG_BEGIN/COMMIT` ueberträgt ohnehin
|
||||
immer den kompletten 740B-Block auf einmal, nie nur ein Profil.
|
||||
Default-Pfad: `~\OneDrive\Desktop\versapad_config_all.json`.
|
||||
— Firmware prüft Magic/CRC/Keycode-Bereich vor jedem Save, antwortet
|
||||
sonst nur mit NACK.
|
||||
- `versapad_combined.py` — Ein-Datei-Format (alle 3 Profile + Makros +
|
||||
**nur lokal gespeicherte** Profilnamen), Default-Pfad
|
||||
`~\OneDrive\Desktop\versapad_config_all.json`. Passt zum Wire-Protokoll:
|
||||
`CONFIG_BEGIN/COMMIT` überträgt ohnehin immer den kompletten 740B-Block.
|
||||
|
||||
**UI:**
|
||||
- `desktop_viewer.py` — Tkinter, flaches Design (Label-Flächen, keine
|
||||
Canvas-Formen/Anti-Aliasing). Zellen nutzen `.place()` mit festen
|
||||
Pixel-Positionen statt `.pack()` (mit pack sah das Grid je nach leerer/
|
||||
belegter Zelle ungleichmäßig aus). Drei unabhängige Modi:
|
||||
- **Nur lesen** (Default): pollt die 3 JSONs alle 1.5s.
|
||||
- **Live-Sync**: pollt per Serial das aktive Profil vom Board, schaltet
|
||||
Tabs automatisch mit. Laeuft in einem Hintergrundthread, der NUR ueber
|
||||
eine `queue.Queue` mit dem Main-Thread kommuniziert (`self.after()`
|
||||
direkt aus einem Fremdthread aufrufen ist in Tkinter nicht threadsicher
|
||||
und hat den Prozess in einer frueheren Version lautlos abstuerzen
|
||||
lassen — `pyw` hat kein Konsolenfenster, der Crash war unsichtbar).
|
||||
- **Programmiermodus**: Zellen anklicken → `action_dialog.py`
|
||||
(`ActionEditDialog`/`MacroStepsDialog`) bearbeitet Action-Typ, HID-Taste
|
||||
(Dropdown statt Tastendruck-Capture — kein WinAPI-Hook, um nicht wieder
|
||||
einen AV-Fehlalarm wie bei den Fensterverstecktricks zu riskieren),
|
||||
Consumer, Makro-Slot+Schritte, ProfileSwitch, LED-Farbe/Animation.
|
||||
"Vom Board laden"/"Zum Board übertragen" nutzen die Binaer-Schicht.
|
||||
Schaltet Live-Sync automatisch aus (ein `VersaPadLink` kann nicht von
|
||||
zwei Konsumenten gleichzeitig genutzt werden).
|
||||
- `action_dialog.py` — die beiden Bearbeiten-Dialoge, importiert nur
|
||||
`versapad_data` (fuer Dropdown-Inhalte).
|
||||
- `desktop_viewer.py` — Tkinter, flaches Design, drei unabhängige Modi
|
||||
(Nur lesen / Live-Sync / Programmiermodus, siehe Kritische Domänenregeln),
|
||||
Tray-Icon statt Taskleisten-Minimierung, Info-Button mit MCP-Doku.
|
||||
- `action_dialog.py` — Bearbeiten-Dialoge (`ActionEditDialog`,
|
||||
`MacroStepsDialog`) für den Programmiermodus.
|
||||
|
||||
## Quelle der Wahrheit — nicht raten
|
||||
**MCP-Server:**
|
||||
- `versapad_mcp_server.py` — registriert als User-Scope-MCP-Server
|
||||
"versapad" (`claude mcp add -s user versapad -- <python> versapad_mcp_server.py`).
|
||||
Nutzt MCP-SDK v2 (Paket `mcp`, Klasse `mcp.server.mcpserver.MCPServer` —
|
||||
**nicht** `FastMCP` aus `mcp.server.fastmcp`, das existiert in dieser
|
||||
SDK-Version nicht mehr, wurde umbenannt). `@mcp.tool()`-dekorierte
|
||||
Funktionen bleiben direkt aufrufbar (kein `.fn`-Unterschied wie bei
|
||||
älteren FastMCP-Versionen). Tool-Liste: siehe README oder
|
||||
`MCP_INFO_TEXT` in `desktop_viewer.py`.
|
||||
|
||||
Bei Aenderungen am Schema/Decoding/Binaerformat immer gegen die Firmware-
|
||||
und GUI-Quellen abgleichen, nie aus dem Gedaechtnis rekonstruieren:
|
||||
Vollständige Modulübersicht mit Zeilenreferenzen bei Bedarf direkt im Code
|
||||
nachschlagen — die Dateien sind klein genug, dass eine separate
|
||||
`docs/current-architecture.md` hier keinen Mehrwert hätte (siehe
|
||||
Dokumentation und Verifikation unten für die Größeneinschätzung).
|
||||
|
||||
## Kritische Domänenregeln
|
||||
|
||||
- Geometrie: `index = spalte*5 + reihe`, Reihe 0 = oben, Reihe 4 = unten
|
||||
(Firmware-Reihenfolge). Nicht raten, nicht neu herleiten.
|
||||
- Encoder 0 `sw` ist auf allen 3 Profilen der Profilwechsel — nicht ohne
|
||||
Rücksprache mit dem User ändern.
|
||||
- Makros sind eine EINE globale 32-Slot-Tabelle, nicht pro Profil. Slot 0-19
|
||||
= MX-Button-Index, Slot 20-31 = `20 + enc*3 + act_idx`. Zwei Profile, die
|
||||
denselben Slot referenzieren, spielen dieselben Schritte ab.
|
||||
- Ein Makro-Schritt mit `keycode=0` beendet die Sequenz (Firmware-Konvention)
|
||||
— keine Lücken vor dem letzten belegten Schritt lassen.
|
||||
- Makro-Schritte erlauben nur Strg/Shift/Alt als Modifier, kein Win (passend
|
||||
zum Original-`ActionDialog.cs`-Verhalten).
|
||||
- Profilnamen leben NUR lokal in `versapad_config_all.json`
|
||||
(`profile_names`) — die Firmware-Structs haben keinen Platz für einen
|
||||
String (Header exakt 32B, jedes Profil exakt 236B, alles verplant). Sie
|
||||
landen nie aufs Board, egal welcher Schreibpfad benutzt wird.
|
||||
- Der COM-Port ist exklusiv. Live-Sync und Programmiermodus schalten sich
|
||||
gegenseitig aus (ein `VersaPadLink` kann nicht von zwei Konsumenten
|
||||
gleichzeitig genutzt werden); VersaGUI läuft als Tray-App dauerhaft im
|
||||
Hintergrund weiter, auch wenn nur ihr Konfigurationsfenster geschlossen
|
||||
wird — für Parallelbetrieb mit diesem Tool muss sie über ihr eigenes
|
||||
Tray-Menü ("Beenden") wirklich beendet werden.
|
||||
- Programmiermodus-Änderungen werden bei jeder Bearbeitung automatisch in
|
||||
`versapad_config_all.json` gespeichert (nicht erst bei explizitem
|
||||
"Datei speichern"). Der Nur-Lese-Modus bevorzugt dieselbe Datei, falls
|
||||
vorhanden, und fällt sonst auf die klassischen `versapad_config{1,2,3}.json`
|
||||
zurück — beide Ansichten müssen dieselbe Quelle zeigen, sonst wirkt eine
|
||||
Bearbeitung "verschwunden".
|
||||
- HID-Tasten-Auswahl im Programmiermodus ist ein Dropdown, kein
|
||||
Tastendruck-Capture (bewusst — kein WinAPI-Hook, um keinen AV-Fehlalarm
|
||||
wie bei den Fensterverstecktricks in anderen Projekten zu riskieren).
|
||||
- Zeichentasten-Labels zeigen eine US-Layout-Näherung, nicht das tatsächlich
|
||||
aktive Windows-Tastaturlayout (die echte VersaGUI löst das über
|
||||
`GetKeyNameText()`, das bilden wir ohne WinAPI-Call nicht nach).
|
||||
- Tk-Aufrufe (`self.after()`, Widget-Konfiguration) NIE direkt aus einem
|
||||
Fremdthread (Serial-Thread, pystray-Thread) — hat in einer früheren
|
||||
Version einen stillen Absturz verursacht. Threads legen Ergebnisse nur in
|
||||
eine `queue.Queue`, der Main-Thread holt sie per `after()`-Polling ab.
|
||||
- `.exe` (PyInstaller) läuft NICHT vom Netzlaufwerk aus (`Z:\Git\...`,
|
||||
SMB-Share) — Windows blockiert das Nachladen der `_internal`-DLLs von
|
||||
einem Netzwerkpfad ohne jede Fehlermeldung. Bauen scheitert dort zusätzlich
|
||||
an Tcl/Tk-`tzdata`-Pfadlängen. `build_and_deploy.ps1` kopiert den
|
||||
Quellcode deshalb zuerst nach `%TEMP%`, baut nur dort, deployt nach
|
||||
`%LOCALAPPDATA%`.
|
||||
- `--onedir`, nicht `--onefile` beim PyInstaller-Build — Single-File-Bundles
|
||||
lösen öfter AV-Fehlalarme aus (sehen strukturell wie ein Packer aus).
|
||||
|
||||
## Existing-Codebase-Regel
|
||||
|
||||
Es gibt bereits eine Codebasis mit validierter, gegen die echte Firmware
|
||||
getesteter Logik (Binärformat, CRC, Protokoll). Nicht blind neu raten oder
|
||||
umschreiben. Vor größeren Änderungen am Binärformat/Protokoll immer gegen
|
||||
die Firmware- und GUI-Quellen abgleichen, nicht aus dem Gedächtnis
|
||||
rekonstruieren:
|
||||
- `VersaGUI/src/ActionDialog.cs` (HidKeyName, s_consumer, Modifier-Bits)
|
||||
- `VersaGUI/src/Protocol.cs` (Paket-IDs, Chunk-Groessen)
|
||||
- `VersaGUI/src/Protocol.cs` (Paket-IDs, Chunk-Größen)
|
||||
- `VersaMCU/src/config/nvm_config.h` + `.cpp` (SDeviceConfig-Layout, CRC)
|
||||
- `VersaMCU/src/config/action.h` (SAction, ActionType-Enum-Werte)
|
||||
- `VersaMCU/src/config/macro_config.h` + `.cpp` (SMacroTable-Layout)
|
||||
- `VersaMCU/src/CButton.h` (LEDAnim-Enum-Werte)
|
||||
- `VersaMCU/src/CMainController.cpp` (welche Commands die Firmware
|
||||
tatsaechlich behandelt — Protocol.cs definiert mehr Konstanten als die
|
||||
Firmware zwingend implementiert, immer hier gegenchecken)
|
||||
*tatsächlich* behandelt — `Protocol.cs` definiert mehr Konstanten als
|
||||
zwingend implementiert sind, immer hier gegenchecken)
|
||||
|
||||
Zeichentasten (A-Z, Ziffern, Satzzeichen) zeigen US-Layout-Näherung, da die
|
||||
echte GUI das über `GetKeyNameText()` layoutabhängig auflöst — das bilden
|
||||
wir ohne WinAPI-Call nicht nach.
|
||||
Frühere falsche Annahme, die hier stand: Makros seien nur per SWD/JTAG
|
||||
schreibbar. Falsch — `USB_CMD_MACRO_BEGIN/DATA/COMMIT` in
|
||||
`CMainController.cpp` sind normal über USB implementiert. Korrigiert, auch
|
||||
im `versapad`-Skill (`~/.claude/skills/versapad/SKILL.md`).
|
||||
|
||||
**Korrektur einer frueheren Annahme:** Anders als zuerst notiert, kann die
|
||||
Firmware Makros sehr wohl per normaler USB-Verbindung schreiben
|
||||
(`USB_CMD_MACRO_BEGIN/DATA/COMMIT` in `CMainController.cpp` sind
|
||||
implementiert) — kein SWD/JTAG noetig. Der VersaPad-Skill
|
||||
(`~/.claude/skills/versapad/SKILL.md`) behauptet noch das Gegenteil und
|
||||
sollte bei Gelegenheit korrigiert werden.
|
||||
## Implementierungsdisziplin
|
||||
|
||||
## Start
|
||||
In Phasen arbeiten, nicht mehrere unabhängige Features in einem Rutsch ohne
|
||||
Zwischenverifikation bauen. Vor jeder Änderung am Binärformat/Protokoll:
|
||||
gegen ein echtes Board testen (read → unpack → pack → Vergleich auf
|
||||
Byte-Identität), nicht nur gegen Beispieldaten. Vor jedem Schreibvorgang
|
||||
aufs Board: erst mit unveränderten Daten testen (Identity-Write), bevor
|
||||
echte Änderungen geschrieben werden.
|
||||
|
||||
## Naming
|
||||
|
||||
Code-Identifier englisch (Python-Konvention: `pack_config`, `read_macros`,
|
||||
`ActionEditDialog`). UI-Text, Kommentare und Docstrings deutsch (Projekt-
|
||||
und User-Konvention). Domänenbegriffe aus der Firmware direkt übernehmen,
|
||||
nicht neu erfinden: `profile`, `action`, `led`, `slot`, `macro`, `encoder`,
|
||||
`chunk`. Keine generischen Namen wie `data`/`item`/`entry`, wo eine
|
||||
Bedeutung existiert — Ausnahme: `data` als Feldname ist durch die Firmware
|
||||
selbst vorgegeben (`SAction.data`), dort beibehalten statt umzubenennen.
|
||||
|
||||
## Deferred Work
|
||||
|
||||
- Volle `docs/`-Baumstruktur (siehe Dokumentation und Verifikation unten —
|
||||
Projektgröße rechtfertigt das aktuell nicht, kein DB-/API-Dienst)
|
||||
- Board-seitiges Umschalten des aktiven Profils per Button in der GUI —
|
||||
explizit vom User abgelehnt ("lass uns weg"), Live-Sync bleibt read-only
|
||||
- Profilnamen aufs Board schreiben — technisch unmöglich (kein Platz im
|
||||
Firmware-Struct), bleibt lokal
|
||||
- Tastendruck-Capture statt Dropdown im Programmiermodus — bewusst
|
||||
vermieden (WinAPI-Hook-Risiko)
|
||||
- Hintergrund-Thread für "Vom Board laden"/"Zum Board übertragen" — laufen
|
||||
aktuell synchron im UI-Thread (kurzzeitiges Einfrieren möglich)
|
||||
- Vorgefertigte `.exe` im Repo/als Release-Asset — bewusst nicht committet
|
||||
(Build-Artefakt), Anleitung zum Selbstbauen steht in `README.md`
|
||||
|
||||
Nicht an diesen Punkten arbeiten, ohne dass der User es explizit anfragt.
|
||||
|
||||
## Dokumentation und Verifikation
|
||||
|
||||
- `README.md` ist der Einstiegspunkt (Installation, Nutzung, Architektur-
|
||||
Überblick).
|
||||
- `AGENTS.md` (diese Datei) ist die agentenseitige Quelle der Wahrheit für
|
||||
Domänenregeln und Architekturgrenzen — jede Session aktualisieren, die
|
||||
daran etwas ändert oder etwas Wichtiges lernt.
|
||||
- Größeneinschätzung nach Projekt-Dokumentationsstandard: kleines/mittleres
|
||||
Tool ohne eigene Datenbank und ohne persistenten API-Dienst (der
|
||||
Browser-Server ist ein einfacher lokaler Lese-Viewer, kein
|
||||
Mehrbenutzer-Backend) → `README.md` + `AGENTS.md` sind Pflicht und
|
||||
vorhanden, ein voller `docs/`-Baum ist nicht angemessen.
|
||||
|
||||
Prüfungen vor einem Commit an Binärformat/Protokoll:
|
||||
```bash
|
||||
python -m py_compile *.py
|
||||
```
|
||||
py server.py # Browser, http://127.0.0.1:8765
|
||||
pyw desktop_viewer.py # natives Fenster, kein Konsolenfenster
|
||||
```
|
||||
Oder `run_browser.bat` / `run_desktop.bat` per Doppelklick, oder die
|
||||
Desktop-Verknuepfungen "VersaPad Viewer (Browser)" / "VersaPad Viewer
|
||||
(Fenster)".
|
||||
Danach ein Live-Testskript gegen ein angeschlossenes Board laufen lassen
|
||||
(read → unpack → pack → Bytevergleich, siehe Existing-Codebase-Regel) —
|
||||
es gibt keine automatisierten Unit-Tests dafür, die Verifikation läuft
|
||||
manuell/interaktiv pro Session.
|
||||
|
||||
**Wichtig:** `pyw`/`py` benutzen, nicht bare `pythonw`/`python` — auf hal9001
|
||||
liegt in PATH zuerst eine Hermes-Agent-venv (`...\hermes\hermes-agent\venv\
|
||||
Scripts\pythonw.exe`) ohne pyserial. `pyw`/`py` (Python Launcher) lösen
|
||||
zuverlässig zur echten Python313-Installation auf.
|
||||
|
||||
## Gepackte .exe (PyInstaller) — kein Terminal-Flash, kein Python-Setup nötig
|
||||
|
||||
`build_and_deploy.ps1` kopiert den Quellcode zuerst nach `%TEMP%`, baut dort
|
||||
mit PyInstaller (`--windowed --onedir --icon icon.ico`), und kopiert das
|
||||
Ergebnis nach `%LOCALAPPDATA%\VersaPadViewer\VersaPadViewer.exe`.
|
||||
Desktop-Verknüpfung "VersaPad Viewer (Fenster)" zeigt dorthin (inkl. eigenem
|
||||
Icon, `IconLocation` zeigt auf die `.exe` selbst statt auf `pythonw.exe`).
|
||||
|
||||
**`--onedir`, nicht `--onefile`** — Single-File-PyInstaller-Bundles lösen
|
||||
öfter AV-Fehlalarme aus (sehen strukturell wie ein Packer aus); `--onedir`
|
||||
(Ordner mit `.exe` + `_internal`) ist unauffälliger. Trotzdem unsigniert,
|
||||
also grundsätzlich nie über Smart App Control/AV in Stein gemeißelt sicher.
|
||||
|
||||
**Zwei Netzlaufwerk-Stolpersteine, deshalb baut UND deployt alles lokal:**
|
||||
1. Laufzeit: die gebaute `.exe` läuft NICHT vom Netzlaufwerk aus (`Z:\Git\...`,
|
||||
SMB-Share auf cj-ki) — Windows blockiert das Nachladen der
|
||||
`_internal`-DLLs von einem Netzwerkpfad, der Prozess startet dann einfach
|
||||
nie, ganz ohne Fehlermeldung/Crash-Log/AV-Benachrichtigung (sah zuerst wie
|
||||
ein AV-Block aus, war aber keiner — verifiziert indem dieselbe `.exe` 1:1
|
||||
lokal kopiert sofort lief).
|
||||
2. Buildzeit: PyInstaller scheitert beim Kopieren der Tcl/Tk-`tzdata`
|
||||
(viele tief verschachtelte, lang benannte Zeitzonen-Ordner) auf dem
|
||||
SMB-Share mit `FileNotFoundError: [WinError 3]` — Pfadlängen-Problem,
|
||||
kombiniert mit dem eh schon langen Projektpfad (`Z:\Git\Versa Board\
|
||||
versapad-viewer\dist\...`).
|
||||
|
||||
Deshalb kopiert `build_and_deploy.ps1` den Quellcode zuerst nach `%TEMP%`
|
||||
und baut NUR dort — Z: wird nur zum Lesen der `.py`-Dateien angefasst.
|
||||
|
||||
Bei erneutem Bauen: `.\build_and_deploy.ps1` in PowerShell ausführen
|
||||
(lokal, nicht über die sandboxed Bash-Tool-Umgebung — die hat eine eigene
|
||||
Dateisystem-Sicht, die nicht zuverlässig mit dem echten Windows-Dateisystem
|
||||
übereinstimmt; siehe Sessionlog: ein `cp -r` über Bash landete an einem Ort,
|
||||
den PowerShell/der reale Explorer nicht sah. Kopieroperationen für Dinge,
|
||||
die der User/andere Prozesse sehen sollen, gehören in PowerShell, nicht in
|
||||
Bash).
|
||||
|
||||
## Icon + Tray (kein Taskleisten-Eintrag beim Minimieren, wie VersaGUI)
|
||||
|
||||
- `icon.png`/`icon.ico` — generiert via Pillow (dunkles abgerundetes Quadrat,
|
||||
blauer Block, 2x2-Punktraster; flaches Design, keine Farbverläufe/
|
||||
Anti-Aliasing-Details, siehe Speicher-Notiz zu Tkinter-Flat-Design).
|
||||
`.ico` fürs Fenster-/Taskleisten-/Exe-Icon, `.png` fürs Tray-Icon (pystray
|
||||
braucht ein PIL-Image, kein Multi-Res-`.ico`).
|
||||
- `resource_path()` in `desktop_viewer.py` findet Assets sowohl im
|
||||
Quellordner als auch im PyInstaller-Bundle (`sys._MEIPASS`).
|
||||
- Minimieren (`<Unmap>` mit `state()=='iconic'`) ruft `withdraw()` statt
|
||||
normal zu minimieren → kein Taskleisten-Eintrag, nur noch Tray-Icon.
|
||||
Schließen (X) macht dasselbe (`_hide_to_tray`, nicht `_quit`) — echtes
|
||||
Beenden nur über "Beenden" im Tray-Rechtsklickmenü (mirrort VersaGUIs
|
||||
`TrayApp`-Menü: Öffnen/Beenden). Tray-Icon läuft über `pystray.Icon.
|
||||
run_detached()` in eigenem Thread — Klicks im Tray-Menü legen nur ein
|
||||
Ereignis in `self._tray_queue`, das der Main-Thread per `after()`-Polling
|
||||
abholt (dieselbe Queue-statt-Direktzugriff-Regel wie beim Serial-Thread,
|
||||
siehe oben — Tk-Aufrufe aus einem Fremdthread haben schon mal einen
|
||||
stillen Absturz verursacht).
|
||||
- Neue Abhängigkeiten: `pystray`, `pillow` (zusätzlich zu `pyserial`).
|
||||
- Info-Button (ⓘ oben rechts im Header) öffnet einen Dialog mit der
|
||||
MCP-Server-Doku (`MCP_INFO_TEXT`-Konstante) — rein informativ, keine Logik.
|
||||
|
||||
## Dateien/Pfade (hardcoded, hal9001-spezifisch)
|
||||
|
||||
- Einzel-JSONs (Read-only-Modus): `~\OneDrive\Desktop\versapad_config{1,2,3}.json`
|
||||
— Profil 0 Windows / 1 Fusion 360 / 2 BricsCAD, siehe `versapad_data.CONFIG_PATHS`.
|
||||
- Kombinierte Datei (Programmiermodus-Export): `~\OneDrive\Desktop\
|
||||
versapad_config_all.json` (Default, siehe `versapad_combined.DEFAULT_PATH`).
|
||||
|
||||
## Offene Punkte
|
||||
|
||||
- Kein automatischer Windows-Start/Tray-Icon — bewusst einfach gehalten,
|
||||
bei Bedarf nachrüstbar.
|
||||
- Live-Sync und VersaGUI (bzw. Programmiermodus) können den COM-Port nicht
|
||||
gleichzeitig halten (exklusiver Zugriff) — zeigt dann "Port belegt", kein
|
||||
Crash. VersaGUI läuft als Tray-App dauerhaft im Hintergrund weiter, auch
|
||||
wenn nur das Konfigurationsfenster geschlossen wird — für Programmiermodus/
|
||||
Live-Sync muss es über das Tray-Icon → "Beenden" wirklich beendet werden.
|
||||
Live-Sync wird beim Aktivieren des Programmiermodus automatisch ausgeschaltet.
|
||||
Innerhalb des Programmiermodus selbst laufen "Vom Board laden"/"Zum Board
|
||||
übertragen" synchron im UI-Thread (kurzzeitiges Einfrieren möglich, v.a.
|
||||
bei Timeout) — bislang nicht als Hintergrund-Thread ausgelagert.
|
||||
Der Browser-Server (`server.py`) hat keinen Programmiermodus.
|
||||
- HID-Tasten-Auswahl im Programmiermodus ist ein Dropdown, kein
|
||||
Tastendruck-Capture (bewusst, um WinAPI-Hooks/AV-Fehlalarme zu vermeiden).
|
||||
- Macro-Editor erlaubt nur Strg/Shift/Alt pro Schritt (kein Win), passend
|
||||
zum Original-`ActionDialog.cs`-Verhalten fuer Makro-Steps.
|
||||
Committen: prägnante Commit-Message je abgeschlossenem, verifiziertem
|
||||
Arbeitspaket. Nach jedem Push: alle bekannten Remotes prüfen (`origin` auf
|
||||
GitHub, `jappel` auf git.jappel.io) — beide müssen synchron bleiben, siehe
|
||||
Speicher-Notiz "Multi-Remote-Repos synchron halten".
|
||||
|
|
|
|||
10
README.md
10
README.md
|
|
@ -6,6 +6,16 @@ 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
|
||||
Standard-Dateipfade für die Config-JSONs sind aktuell für eine bestimmte
|
||||
Windows-Maschine hartkodiert (`versapad_data.CONFIG_PATHS`,
|
||||
`versapad_combined.DEFAULT_PATH`) — für einen anderen Rechner dort anpassen.
|
||||
|
||||
## Features
|
||||
|
||||
- **Steuermatrix-Anzeige** — 4×5-Button-Grid + 4 Encoder, farbige LED-Vorschau,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue