Files
elmer/obd/state.py
T

68 lines
2.4 KiB
Python

"""Состояния и классификация ответов ELM327 (AndrOBD STAT/RSP_ID).
State — состояния стейт-машины (UNDEFINED → INITIALIZING → READY → BUSY → ...)
Rsp — классификация сырых ответов ELM327
"""
from enum import Enum, auto
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()
# NO DATA бывает как "NODATA" так и "NO DATA"
if u.replace(" ", "") == "NODATA":
return cls.NODATA
for tag in (cls.SEARCHING, 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