fix st
This commit is contained in:
@ -17,13 +17,16 @@ from rfg_adc_plotter.io.sweep_parser_core import (
|
||||
ParserTestStreamParser,
|
||||
SweepAssembler,
|
||||
)
|
||||
from rfg_adc_plotter.types import ParserEvent, PointEvent, SweepPacket
|
||||
from rfg_adc_plotter.types import ParserEvent, PointEvent, StartEvent, SweepPacket
|
||||
|
||||
_PARSER_16_BIT_X2_PROBE_BYTES = 64 * 1024
|
||||
_LEGACY_STREAM_MIN_RECORDS = 32
|
||||
_LEGACY_STREAM_MIN_MATCH_RATIO = 0.95
|
||||
_TTY_STREAM_MIN_MATCH_RATIO = 0.60
|
||||
_DEBUG_FRAME_LOG_EVERY = 10
|
||||
_NO_INPUT_WARN_INTERVAL_S = 5.0
|
||||
_NO_PACKET_WARN_INTERVAL_S = 5.0
|
||||
_NO_PACKET_HINT_AFTER_S = 10.0
|
||||
|
||||
|
||||
def _u16le_at(data: bytes, offset: int) -> int:
|
||||
@ -119,6 +122,19 @@ class SweepReader(threading.Thread):
|
||||
self._frames_dropped = 0
|
||||
self._started_at = time.perf_counter()
|
||||
|
||||
def _resolve_parser_mode_label(self) -> str:
|
||||
if self._parser_complex_ascii:
|
||||
return "complex_ascii"
|
||||
if self._parser_test:
|
||||
return "parser_test_16x2"
|
||||
if self._parser_16_bit_x2:
|
||||
return "parser_16_bit_x2"
|
||||
if self._logscale:
|
||||
return "logscale_32"
|
||||
if self._bin_mode:
|
||||
return "legacy_8byte"
|
||||
return "ascii"
|
||||
|
||||
def _build_parser(self):
|
||||
if self._parser_complex_ascii:
|
||||
return ComplexAsciiSweepParser(), SweepAssembler(fancy=self._fancy, apply_inversion=False)
|
||||
@ -145,6 +161,7 @@ class SweepReader(threading.Thread):
|
||||
parser = LogScale16BitX2BinaryParser()
|
||||
probe_buf = bytearray()
|
||||
probe_events: list[ParserEvent] = []
|
||||
probe_started_at = time.perf_counter()
|
||||
|
||||
while not self._stop_event.is_set() and len(probe_buf) < _PARSER_16_BIT_X2_PROBE_BYTES:
|
||||
data = chunk_reader.read_available()
|
||||
@ -156,15 +173,55 @@ class SweepReader(threading.Thread):
|
||||
if _is_valid_parser_16_bit_x2_probe(probe_events):
|
||||
assembler = SweepAssembler(fancy=self._fancy, apply_inversion=False)
|
||||
probe_packets = self._consume_events(assembler, probe_events)
|
||||
n_points = int(sum(1 for event in probe_events if isinstance(event, PointEvent)))
|
||||
n_starts = int(sum(1 for event in probe_events if isinstance(event, StartEvent)))
|
||||
probe_ms = (time.perf_counter() - probe_started_at) * 1000.0
|
||||
sys.stderr.write(
|
||||
"[info] parser_16_bit_x2 probe: bytes:%d events:%d points:%d starts:%d parser:16x2 elapsed_ms:%.1f\n"
|
||||
% (
|
||||
len(probe_buf),
|
||||
len(probe_events),
|
||||
n_points,
|
||||
n_starts,
|
||||
probe_ms,
|
||||
)
|
||||
)
|
||||
return parser, assembler, probe_packets
|
||||
|
||||
if probe_buf and _looks_like_legacy_8byte_stream(bytes(probe_buf)):
|
||||
probe_looks_legacy = bool(probe_buf) and _looks_like_legacy_8byte_stream(bytes(probe_buf))
|
||||
n_points = int(sum(1 for event in probe_events if isinstance(event, PointEvent)))
|
||||
n_starts = int(sum(1 for event in probe_events if isinstance(event, StartEvent)))
|
||||
probe_ms = (time.perf_counter() - probe_started_at) * 1000.0
|
||||
if probe_looks_legacy:
|
||||
sys.stderr.write(
|
||||
"[info] parser_16_bit_x2 probe: bytes:%d events:%d points:%d starts:%d parser:legacy(fallback) elapsed_ms:%.1f\n"
|
||||
% (
|
||||
len(probe_buf),
|
||||
len(probe_events),
|
||||
n_points,
|
||||
n_starts,
|
||||
probe_ms,
|
||||
)
|
||||
)
|
||||
sys.stderr.write("[info] parser_16_bit_x2: fallback -> legacy\n")
|
||||
parser = LegacyBinaryParser()
|
||||
assembler = SweepAssembler(fancy=self._fancy, apply_inversion=True)
|
||||
probe_packets = self._consume_events(assembler, parser.feed(bytes(probe_buf)))
|
||||
return parser, assembler, probe_packets
|
||||
|
||||
sys.stderr.write(
|
||||
"[warn] parser_16_bit_x2 probe inconclusive: bytes:%d events:%d points:%d starts:%d parser:16x2 elapsed_ms:%.1f\n"
|
||||
% (
|
||||
len(probe_buf),
|
||||
len(probe_events),
|
||||
n_points,
|
||||
n_starts,
|
||||
probe_ms,
|
||||
)
|
||||
)
|
||||
sys.stderr.write(
|
||||
"[hint] parser_16_bit_x2: if source is 8-byte tty CH1/CH2 stream (0x000A,step,ch1,ch2), try --bin\n"
|
||||
)
|
||||
assembler = SweepAssembler(fancy=self._fancy, apply_inversion=False)
|
||||
return parser, assembler, []
|
||||
|
||||
@ -212,7 +269,17 @@ class SweepReader(threading.Thread):
|
||||
def run(self) -> None:
|
||||
try:
|
||||
self._src = SerialLineSource(self._port_path, self._baud, timeout=1.0)
|
||||
queue_cap = int(getattr(self._queue, "maxsize", -1))
|
||||
sys.stderr.write(f"[info] Открыл порт {self._port_path} ({self._src._using})\n")
|
||||
sys.stderr.write(
|
||||
"[info] reader start: parser:%s fancy:%d queue_max:%d source:%s\n"
|
||||
% (
|
||||
self._resolve_parser_mode_label(),
|
||||
int(self._fancy),
|
||||
queue_cap,
|
||||
getattr(self._src, "_using", "unknown"),
|
||||
)
|
||||
)
|
||||
except Exception as exc:
|
||||
sys.stderr.write(f"[error] {exc}\n")
|
||||
return
|
||||
@ -228,12 +295,68 @@ class SweepReader(threading.Thread):
|
||||
for packet in pending_packets:
|
||||
self._enqueue(packet)
|
||||
|
||||
loop_started_at = time.perf_counter()
|
||||
last_input_at = loop_started_at
|
||||
last_packet_at = loop_started_at if self._frames_read > 0 else loop_started_at
|
||||
last_no_input_warn_at = loop_started_at
|
||||
last_no_packet_warn_at = loop_started_at
|
||||
parser_hint_emitted = False
|
||||
|
||||
while not self._stop_event.is_set():
|
||||
data = chunk_reader.read_available()
|
||||
now_s = time.perf_counter()
|
||||
if not data:
|
||||
input_idle_s = now_s - last_input_at
|
||||
if (
|
||||
input_idle_s >= _NO_INPUT_WARN_INTERVAL_S
|
||||
and (now_s - last_no_input_warn_at) >= _NO_INPUT_WARN_INTERVAL_S
|
||||
):
|
||||
sys.stderr.write(
|
||||
"[warn] reader no input bytes for %.1fs on %s (parser:%s)\n"
|
||||
% (
|
||||
input_idle_s,
|
||||
self._port_path,
|
||||
self._resolve_parser_mode_label(),
|
||||
)
|
||||
)
|
||||
last_no_input_warn_at = now_s
|
||||
|
||||
packets_idle_s = now_s - last_packet_at
|
||||
if (
|
||||
packets_idle_s >= _NO_PACKET_WARN_INTERVAL_S
|
||||
and (now_s - last_no_packet_warn_at) >= _NO_PACKET_WARN_INTERVAL_S
|
||||
):
|
||||
try:
|
||||
queue_size = self._queue.qsize()
|
||||
except Exception:
|
||||
queue_size = -1
|
||||
sys.stderr.write(
|
||||
"[warn] reader no sweep packets for %.1fs (input_idle:%.1fs queue:%d parser:%s)\n"
|
||||
% (
|
||||
packets_idle_s,
|
||||
input_idle_s,
|
||||
int(queue_size),
|
||||
self._resolve_parser_mode_label(),
|
||||
)
|
||||
)
|
||||
last_no_packet_warn_at = now_s
|
||||
if (
|
||||
self._parser_16_bit_x2
|
||||
and (not parser_hint_emitted)
|
||||
and (now_s - self._started_at) >= _NO_PACKET_HINT_AFTER_S
|
||||
):
|
||||
sys.stderr.write(
|
||||
"[hint] parser_16_bit_x2 still has no sweeps; if source is tty CH1/CH2, rerun with --bin\n"
|
||||
)
|
||||
parser_hint_emitted = True
|
||||
time.sleep(0.0005)
|
||||
continue
|
||||
for packet in self._consume_events(assembler, parser.feed(data)):
|
||||
|
||||
last_input_at = now_s
|
||||
packets = self._consume_events(assembler, parser.feed(data))
|
||||
if packets:
|
||||
last_packet_at = now_s
|
||||
for packet in packets:
|
||||
self._enqueue(packet)
|
||||
packet = assembler.finalize_current()
|
||||
if packet is not None:
|
||||
|
||||
Reference in New Issue
Block a user