Extract reusable device protocols, ports and logic analyzers from SETGUI

This commit is contained in:
2026-09-23 20:11:37 +03:00
parent 80ba17d77d
commit 795a1279b1
63 changed files with 10181 additions and 6 deletions

View File

@@ -0,0 +1,71 @@
"""Выбор wire-протокола для одного последовательного канала SETGUI.
Во время подключения оба потоковых parser-а получают одинаковые байты. Первый
полностью проверенный кадр фиксирует режим канала до следующего ``reset``.
Версия находится сразу после общего SOF A5 5A, поэтому протоколы не могут
ошибочно принять кадр друг друга.
"""
from __future__ import annotations
from enum import Enum
from set_devices import protocol as gui_v1
from setprotocol import core as setp_v2
class ProtocolMode(Enum):
"""Wire-протокол, выбранный для текущего физического соединения."""
AUTO = "auto"
SETPROTOCOL_V2 = "setprotocol_v2"
GUI_V1 = "gui_v1"
@property
def display_name(self) -> str:
return {
ProtocolMode.AUTO: "Определение протокола…",
ProtocolMode.SETPROTOCOL_V2: "SETProtocol v2",
ProtocolMode.GUI_V1: "GUI protocol v1 (совместимость)",
}[self]
class ProtocolRouter:
"""Потоковый маршрутизатор SETProtocol v2 и устаревшего GUI v1."""
def __init__(self) -> None:
self._v2 = setp_v2.FrameParser()
self._v1 = gui_v1.FrameParser()
self.mode = ProtocolMode.AUTO
def reset(self, mode: ProtocolMode = ProtocolMode.AUTO) -> None:
self._v2.reset()
self._v1.reset()
self.mode = mode
def select(self, mode: ProtocolMode) -> None:
"""Фиксирует режим и отбрасывает остатки предыдущего разбора."""
if mode is ProtocolMode.AUTO:
self.reset()
return
self.reset(mode)
def feed(self, data: bytes) -> list[gui_v1.Frame | setp_v2.Frame]:
if self.mode is ProtocolMode.SETPROTOCOL_V2:
return list(self._v2.feed(data))
if self.mode is ProtocolMode.GUI_V1:
return list(self._v1.feed(data))
# В AUTO parser-ы независимы. Неверная версия учитывается только их
# внутренней диагностикой и не влияет на второй parser.
v2_frames = self._v2.feed(data)
v1_frames = self._v1.feed(data)
if v2_frames:
self.mode = ProtocolMode.SETPROTOCOL_V2
self._v1.reset()
return list(v2_frames)
if v1_frames:
self.mode = ProtocolMode.GUI_V1
self._v2.reset()
return list(v1_frames)
return []