Live Editor: add DASP/Sox device connection with full CRUD and COV

Port the DASP transport and Sox protocol stack from sedonaOntrol Java
to Python, enabling live device editing alongside the existing offline
SAX editor. Lazy-loads components on navigation, caches them, and
subscribes to COV events for the active wiresheet.

New files: dasp.py, sox.py, device_session.py, connect_dialog.py,
live_hooks.py. Modified: app_state.py (live-mode state), main.py
(Device menu, COV polling, lazy tree expand), properties.py (Sox
write-through), sax_file.py (structural mutations route through
live_hooks), schema.py (find_manifest helper).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-09-11 23:31:36 +03:00
co-authored by Claude Opus 4.6
parent 48dfd82832
commit dafebcebda
10 changed files with 3052 additions and 26 deletions
+20 -5
View File
@@ -32,6 +32,7 @@ import tkinter as tk
from tkinter import font as tkfont, messagebox, ttk
import app_state
import live_hooks
import schema
import undo
from sax_dom import (get_component_path, read_meta_property, set_prop_value,
@@ -1132,11 +1133,16 @@ class PropertiesPanel:
self.status_var.set("No changes to save.")
return
live_failures = []
for element, prop_name, _before, after in changes:
if prop_name != "meta":
set_prop_value(element, prop_name, after)
if live_hooks.is_live():
if not live_hooks.live_set_prop_value(element, prop_name, after):
live_failures.append(prop_name)
undo.push(undo.SlotValueCommand(list(changes)))
if not app_state.live_mode:
undo.push(undo.SlotValueCommand(list(changes)))
app_state.mark_dirty()
self.refresh()
@@ -1144,10 +1150,19 @@ class PropertiesPanel:
self.on_change()
count = len(changes)
self.status_var.set(
f"{count} slot{'' if count == 1 else 's'} changed. "
"Ctrl+S writes the file."
)
if live_failures:
self.status_var.set(
f"Written locally but failed on device: {', '.join(live_failures)}"
)
elif app_state.live_mode:
self.status_var.set(
f"{count} slot{'' if count == 1 else 's'} written to device."
)
else:
self.status_var.set(
f"{count} slot{'' if count == 1 else 's'} changed. "
"Ctrl+S writes the file."
)
app_state.set_status(
f"{self.comp.get('name', '?')}: {count} slot{'' if count == 1 else 's'} changed."
)