"""Выбор 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 []