From e3a5c6f07da76f7cad92fc4d17e5f64cc5bd6eda Mon Sep 17 00:00:00 2001 From: Brian Harrison Date: Mon, 6 Apr 2026 17:41:29 -0400 Subject: [PATCH] 5A: treat partial end-of-stream byte as graceful stream termination MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When the device finishes streaming waveform data, it sends a single partial byte (raw_bytes=1) rather than a complete A5 frame, then goes silent for the full 120s timeout. Observed: 35 chunks succeed, chunk 36 times out with raw_bytes=1 — identical for both events in the test run. Fix: on TimeoutError, if bytes_fed > 0 and we already have collected frames, treat it as natural end-of-stream and break to the termination step rather than propagating the exception. True transport failures (raw_bytes=0, no prior frames) still raise. Co-Authored-By: Claude Sonnet 4.6 --- minimateplus/protocol.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/minimateplus/protocol.py b/minimateplus/protocol.py index f6c5f13..9a2041f 100644 --- a/minimateplus/protocol.py +++ b/minimateplus/protocol.py @@ -522,10 +522,21 @@ class MiniMateProtocol: try: rsp = self._recv_one(expected_sub=rsp_sub, reset_parser=False) except TimeoutError: + raw = self._parser.bytes_fed log.warning( "5A TIMEOUT chunk=%d counter=0x%04X raw_bytes=%d", - chunk_num, counter, self._parser.bytes_fed, + chunk_num, counter, raw, ) + if raw > 0 and frames_data: + # Device sent a partial byte (likely a bare DLE/ETX end-of-stream + # signal) but never completed a full frame. Treat as graceful + # stream end and fall through to the termination step. + log.warning( + "5A end-of-stream detected at chunk=%d (raw_bytes=%d, " + "frames_collected=%d) — proceeding to termination", + chunk_num, raw, len(frames_data), + ) + break raise log.warning(