Fix crash when desktop config JSON is deleted: self-heal from board
server.py and desktop_viewer.py read-only mode required the desktop config JSONs to exist and crashed/showed "Config-Datei fehlt" if one was deleted, even though the board already holds the config durably in NVM. Add versapad_combined.fetch_from_board()/load_or_fetch(): a missing combined JSON is now transparently rebuilt from the board via serial and cached back to disk, falling back to the legacy per-profile JSONs (or a clear error) only when the board is unreachable.
This commit is contained in:
parent
8a2a73c68d
commit
540ce5b1eb
4 changed files with 104 additions and 10 deletions
|
|
@ -17,6 +17,7 @@ import os
|
|||
|
||||
import versapad_data as vp
|
||||
import versapad_protocol as proto
|
||||
import versapad_serial as vs
|
||||
|
||||
DEFAULT_PATH = os.path.expanduser(r"~\OneDrive\Desktop\versapad_config_all.json")
|
||||
|
||||
|
|
@ -92,3 +93,51 @@ def save_file(combined, path=DEFAULT_PATH):
|
|||
def load_file(path=DEFAULT_PATH):
|
||||
with open(path, "r", encoding="utf-8") as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def fetch_from_board(link=None, profile_names=None):
|
||||
"""Liest Config+Makros direkt vom Board per Serial (~1-2s), das Board
|
||||
ist die eigentliche Quelle der Wahrheit (write_to_board() speichert
|
||||
dauerhaft im NVM -- die JSON-Dateien hier sind nur ein Lesecache).
|
||||
link: bestehender VersaPadLink wiederverwenden (z.B. desktop_viewer's
|
||||
self._link, damit nicht zwei Verbindungen um denselben COM-Port
|
||||
konkurrieren) -- sonst wird eine eigene geoeffnet und wieder
|
||||
geschlossen. Wirft RuntimeError mit Klartext-Ursache (last_error),
|
||||
z.B. wenn der Port gerade von VersaGUI/einem anderen Viewer belegt ist."""
|
||||
owns_link = link is None
|
||||
if owns_link:
|
||||
link = vs.VersaPadLink()
|
||||
try:
|
||||
raw_cfg = link.read_full_config()
|
||||
if raw_cfg is None:
|
||||
raise RuntimeError(f"Config vom Board laden fehlgeschlagen: {link.last_error}")
|
||||
raw_macros = link.read_macros()
|
||||
if raw_macros is None:
|
||||
raise RuntimeError(f"Makros vom Board laden fehlgeschlagen: {link.last_error}")
|
||||
cfg_dict = proto.unpack_config(raw_cfg)
|
||||
if not (cfg_dict["magic_ok"] and cfg_dict["crc_ok"]):
|
||||
raise RuntimeError("Board-Antwort ungueltig (Magic/CRC)")
|
||||
macro_slots = proto.unpack_macros(raw_macros)
|
||||
return from_binary(cfg_dict, macro_slots, profile_names=profile_names)
|
||||
finally:
|
||||
if owns_link:
|
||||
link.close()
|
||||
|
||||
|
||||
def load_or_fetch(path=DEFAULT_PATH, link=None, profile_names=None):
|
||||
"""Bevorzugt die lokale Kombi-Datei. Fehlt sie (z.B. versehentlich
|
||||
geloescht), wird sie automatisch per Serial vom Board neu aufgebaut und
|
||||
als neuer Cache gespeichert, statt einen Fehler zu werfen -- das Board
|
||||
behaelt die Config dauerhaft im NVM, die Desktop-JSON ist nur ein
|
||||
Lesecache dafuer und muss nicht von Hand gepflegt werden. Ist das Board
|
||||
nicht erreichbar (nicht verbunden, COM-Port belegt), wirft es
|
||||
RuntimeError mit Klartext-Ursache -- Aufrufer entscheidet, ob es einen
|
||||
weiteren Fallback gibt (z.B. alte Einzel-JSONs)."""
|
||||
if os.path.exists(path):
|
||||
return load_file(path)
|
||||
combined = fetch_from_board(link=link, profile_names=profile_names)
|
||||
try:
|
||||
save_file(combined, path)
|
||||
except OSError:
|
||||
pass # Board-Daten trotzdem verwertbar, nur der Cache konnte nicht geschrieben werden
|
||||
return combined
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue