refactor: разбил routes/db/protocol на отдельные модули
This commit is contained in:
+3
-103
@@ -34,114 +34,14 @@ obd/protocol.py — ELM327 стейт-машина (AndrOBD).
|
||||
|
||||
import logging
|
||||
import time
|
||||
from enum import Enum, auto
|
||||
from typing import Optional
|
||||
|
||||
from obd.state import State, Rsp
|
||||
from obd.timing import AdaptiveTiming
|
||||
|
||||
logger = logging.getLogger("androbd")
|
||||
|
||||
|
||||
class State(Enum):
|
||||
"""Состояния стейт-машины (AndrOBD STAT).
|
||||
|
||||
UNDEFINED → INITIALIZING → READY — нормальный путь.
|
||||
BUSY — во время выполнения команды.
|
||||
ERROR/DISCONNECTED — ошибка, требуется восстановление.
|
||||
"""
|
||||
UNDEFINED = auto()
|
||||
INITIALIZING = auto()
|
||||
READY = auto()
|
||||
BUSY = auto()
|
||||
ERROR = auto()
|
||||
DISCONNECTED = auto()
|
||||
|
||||
|
||||
class Rsp:
|
||||
"""Классификация ответов ELM327 (AndrOBD RSP_ID).
|
||||
|
||||
Каждый сырой ответ классифицируется:
|
||||
- PROMPT (`>`) — готов к следующей команде
|
||||
- OK — команда выполнена
|
||||
- SEARCHING — идёт поиск протокола
|
||||
- BUS_ERROR/BUS_BUSY/CAN_ERROR/STOPPED — ошибка шины → DISCONNECTED
|
||||
- ERROR/DATA_ERROR/BUFFER_FULL — ошибка → warm start
|
||||
- UNKNOWN — данные (ответ на PID/DTC)
|
||||
"""
|
||||
PROMPT = ">"
|
||||
OK = "OK"
|
||||
SEARCHING = "SEARCHING"
|
||||
NODATA = "NODATA"
|
||||
ERROR = "ERROR"
|
||||
UNABLE = "UNABLE"
|
||||
BUS_BUSY = "BUS BUSY"
|
||||
BUS_ERROR = "BUS ERROR"
|
||||
CAN_ERROR = "CAN ERROR"
|
||||
BUS_INIT = "BUS INIT"
|
||||
STOPPED = "STOPPED"
|
||||
DATA_ERROR = "DATA ERROR"
|
||||
BUFFER_FULL= "BUFFER FULL"
|
||||
RX_ERROR = "RX ERROR"
|
||||
UNKNOWN = ""
|
||||
|
||||
@classmethod
|
||||
def identify(cls, raw: str) -> str:
|
||||
"""Определяет тип ответа по сырой строке."""
|
||||
u = raw.upper().strip()
|
||||
for tag in (cls.SEARCHING, cls.NODATA, cls.ERROR, cls.UNABLE,
|
||||
cls.BUS_BUSY, cls.BUS_ERROR, cls.CAN_ERROR,
|
||||
cls.BUS_INIT, cls.STOPPED, cls.DATA_ERROR,
|
||||
cls.BUFFER_FULL, cls.RX_ERROR, cls.OK):
|
||||
if u.startswith(tag):
|
||||
return tag
|
||||
if raw.strip() == ">":
|
||||
return cls.PROMPT
|
||||
return cls.UNKNOWN
|
||||
|
||||
|
||||
class AdaptiveTiming:
|
||||
"""Адаптивный таймаут ожидания ответа (AndrOBD AdaptiveTiming).
|
||||
|
||||
Динамически подстраивается под скорость ответа ЭБУ:
|
||||
- Успешный ответ → уменьшаем таймаут (быстрее)
|
||||
- Таймаут/NO DATA → увеличиваем таймаут (медленнее)
|
||||
- BUS ERROR → сброс до DEFAULT
|
||||
|
||||
ATST = таймаут / 4 (отправляется в ELM327 как ATSTxx).
|
||||
"""
|
||||
DEFAULT = 500 # мс — начальный таймаут
|
||||
MIN = 50 # мс — минимальный
|
||||
MAX = 2000 # мс — максимальный
|
||||
STEP = 20 # мс — шаг изменения
|
||||
RES = 4 # делитель для ATST
|
||||
|
||||
def __init__(self):
|
||||
self._t = self.DEFAULT
|
||||
self._min = self.MIN
|
||||
|
||||
@property
|
||||
def ms(self) -> int:
|
||||
"""Текущий таймаут в миллисекундах."""
|
||||
return self._t
|
||||
|
||||
@property
|
||||
def atst(self) -> int:
|
||||
"""Значение для ATST (таймаут / 4)."""
|
||||
return max(1, self._t // self.RES)
|
||||
|
||||
def increase(self):
|
||||
"""Увеличить таймаут (ЭБУ медленно отвечает)."""
|
||||
if self._t + self.STEP < self.MAX:
|
||||
self._t += self.STEP
|
||||
|
||||
def decrease(self):
|
||||
"""Уменьшить таймаут (ЭБУ отвечает быстро)."""
|
||||
if self._t - self.STEP >= self._min:
|
||||
self._t -= self.STEP
|
||||
|
||||
def reset(self):
|
||||
"""Сбросить до DEFAULT (после BUS ERROR)."""
|
||||
self._t = self.DEFAULT
|
||||
|
||||
|
||||
class AndrOBD:
|
||||
"""Стейт-машина ELM327 — 1:1 копия AndrOBD (ElmProt.java).
|
||||
|
||||
|
||||
Reference in New Issue
Block a user