DASP: drop the P-ION resend overrides, use standard 512-byte packets
The save and file-open requests used their own fixed resend intervals (5 s / 15 s) and the hello asked for 256-byte packets. Ontrol's Sedona Java stack does neither and works with the P-ION: the standard backoff (1, 2, 4, 8 s) sends a busy device a few copies with the same seqNum, which its receive window drops. Both are removed. Also fixes a race in SendWindow.send(): the packet entered the window before its payload and sent_time were set, so housekeeping could resend it with an empty payload, and the device would then drop the real one as a duplicate. Tested on a P-ION at 192.168.1.252, App > Get with File: save 3.2 s (2 resends), app.sab + kits.scode in 11.3 s with 500-byte chunks (was 14.6 s at 256), device stayed up, files identical to a 256-byte backup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -35,18 +35,6 @@ BUF_ID = 7
|
||||
STR_ID = 8
|
||||
|
||||
|
||||
# DASP resend intervals (seconds) for requests a device can be slow to take, as Ontrol's
|
||||
# Niagara driver sets them: a P-ION saving a large app takes 2-3+ s, and a file open can
|
||||
# take 10+ s on some devices. Resent every second instead, the device is sent copies
|
||||
# while it is still busy with the first.
|
||||
SAVE_SEND_RETRY = 5.0
|
||||
FILE_OPEN_SEND_RETRY = 15.0
|
||||
|
||||
# The DASP packet sizes Ontrol's Niagara driver asks for in its hello.
|
||||
IDEAL_MAX = 256
|
||||
ABS_MAX = 256
|
||||
|
||||
|
||||
class SoxException(Exception):
|
||||
pass
|
||||
|
||||
@@ -678,13 +666,13 @@ class SoxClient:
|
||||
|
||||
# ── Invoke Action ───────────────────────────────────────────
|
||||
|
||||
def invoke(self, comp_id, slot_id, type_id=None, arg=None, send_retry=None):
|
||||
def invoke(self, comp_id, slot_id, type_id=None, arg=None):
|
||||
req = _prepare_request(ord('i'))
|
||||
req.write_u2(comp_id)
|
||||
req.write_u1(slot_id)
|
||||
if arg is not None and type_id is not None:
|
||||
encode_value(req, type_id, arg)
|
||||
res = self.request(req, send_retry)
|
||||
res = self.request(req)
|
||||
res.check_response('I')
|
||||
|
||||
# ── Add Component ───────────────────────────────────────────
|
||||
@@ -950,7 +938,7 @@ class SoxClient:
|
||||
opened = closed = False
|
||||
try:
|
||||
try:
|
||||
res = self.request(req, FILE_OPEN_SEND_RETRY)
|
||||
res = self.request(req)
|
||||
except SoxException as e:
|
||||
# A P-ION on firmware 1.32 never answers a file get -- it drops off
|
||||
# the network for ~20 s, as a restart would -- even for a file it
|
||||
@@ -1002,21 +990,17 @@ class SoxClient:
|
||||
|
||||
# ── Networking ──────────────────────────────────────────────
|
||||
|
||||
def request(self, req, send_retry=None):
|
||||
results = self.requests([req], send_retry)
|
||||
def request(self, req):
|
||||
results = self.requests([req])
|
||||
return results[0]
|
||||
|
||||
def requests(self, reqs, send_retry=None):
|
||||
"""Sends the batch and waits for every reply.
|
||||
|
||||
send_retry (seconds) sets the DASP resend interval of these datagrams, for a
|
||||
request the device is known to be slow to take.
|
||||
"""
|
||||
def requests(self, reqs):
|
||||
"""Sends the batch and waits for every reply."""
|
||||
if self.is_closed:
|
||||
raise SoxException("SoxClient closed")
|
||||
|
||||
if len(reqs) > 255:
|
||||
return self._chunk_requests(reqs, send_retry)
|
||||
return self._chunk_requests(reqs)
|
||||
|
||||
with self._lock:
|
||||
for i, req in enumerate(reqs):
|
||||
@@ -1027,7 +1011,7 @@ class SoxClient:
|
||||
self._req_event.clear()
|
||||
|
||||
for req in reqs:
|
||||
self._session.send(req.to_bytes(), send_retry)
|
||||
self._session.send(req.to_bytes())
|
||||
|
||||
deadline = time.monotonic() + 30.0
|
||||
while True:
|
||||
@@ -1051,11 +1035,11 @@ class SoxClient:
|
||||
self._responses = None
|
||||
raise SoxException("Request timeout")
|
||||
|
||||
def _chunk_requests(self, reqs, send_retry=None):
|
||||
def _chunk_requests(self, reqs):
|
||||
results = []
|
||||
for i in range(0, len(reqs), 255):
|
||||
chunk = reqs[i:i + 255]
|
||||
results.extend(self.requests(chunk, send_retry))
|
||||
results.extend(self.requests(chunk))
|
||||
return results
|
||||
|
||||
# called by receiver thread
|
||||
|
||||
Reference in New Issue
Block a user