72 lines
2.7 KiB
Python
72 lines
2.7 KiB
Python
"""Выбор 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 []
|