Get with File on P-ION: connect and transfer the way Ontrol's Niagara driver does
A real P-ION (fw 1.32) restarted on every Sox file get. Ontrol's Niagara 4 driver gets app.sab from the same device, so its settings are copied: - DASP hello asks for 256-byte packets (idealMax/absMax), so file chunks are 238 bytes - the message-length header (0x81) goes to Orion only, decided once the platform id is read - the app is saved on the device before app.sab is read, the save resent every 5 s rather than 1 s (a P-ION save takes 2-3+ s) - the file open is resent every 15 s; DASP gains a per-packet resend interval for this Tested on a P-ION at 192.168.1.252: save 3.2 s, app.sab + kits.scode + app.sax in 15.8 s, no resends, device stayed up. The unsaved-changes question became a notice, since the app is now always saved first. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+22
-2
@@ -23,6 +23,7 @@ import zipfile
|
||||
|
||||
import app_state
|
||||
import sab_app
|
||||
import sox
|
||||
from ox_widget_properties import IMAGE_EXTENSIONS, ORION_KIT, RION_KIT
|
||||
|
||||
APP_SAB = "app.sab"
|
||||
@@ -159,6 +160,19 @@ def _source_entry(media, source_path):
|
||||
return f"{media.bank_folder}/{file_name}"
|
||||
|
||||
|
||||
def save_app(client):
|
||||
"""Invokes App.save on the device and waits for it to finish.
|
||||
|
||||
Ontrol's Niagara driver does this before every app.sab get, resending the request
|
||||
only every 5 s: a P-ION saving a large app takes seconds, and 1 s resends of the
|
||||
request while it is busy are what knocked it over.
|
||||
"""
|
||||
comp = client.cache_get(0) or client.load(0)
|
||||
slots = client.slot_registry.get((comp.kit_id, comp.type_id)) or []
|
||||
slot = next((s for s in slots if s["name"] == "save" and s.get("is_action")), None)
|
||||
client.invoke(0, slot["id"] if slot else 0, send_retry=sox.SAVE_SEND_RETRY)
|
||||
|
||||
|
||||
class BackupResult:
|
||||
def __init__(self):
|
||||
self.path = None
|
||||
@@ -171,8 +185,9 @@ class BackupResult:
|
||||
def get_with_file(client, path, status=None):
|
||||
"""Reads the app and its media off the device and writes the backup zip to `path`.
|
||||
|
||||
Runs off the main thread; status(text, fraction) reports progress. Returns a
|
||||
BackupResult; a failure to read app.sab or kits.scode raises.
|
||||
The app is saved on the device first, so app.sab holds what is running. Runs off
|
||||
the main thread; status(text, fraction) reports progress. Returns a BackupResult;
|
||||
a failure to save, or to read app.sab or kits.scode, raises.
|
||||
"""
|
||||
def report(text, fraction=None):
|
||||
if status:
|
||||
@@ -190,6 +205,11 @@ def get_with_file(client, path, status=None):
|
||||
result = BackupResult()
|
||||
entries = [] # (zip name, bytes or local path)
|
||||
|
||||
report("Saving the app on the device ...", 0.0)
|
||||
try:
|
||||
save_app(client)
|
||||
except Exception as e:
|
||||
raise RuntimeError(f"Saving the app on the device: {e}") from e
|
||||
sab = fetch(APP_SAB, 0.0, 0.15)
|
||||
entries.append(("device/" + APP_SAB, sab))
|
||||
entries.append(("device/" + KITS_SCODE, fetch(KITS_SCODE, 0.15, 0.35)))
|
||||
|
||||
Reference in New Issue
Block a user