v0.48.0 — пробинг ELM327, трехуровневый профиль, рефакторинг obd/

- obd/probe.py: трехуровневый каскад (L0/L1/L2)
- obd/commands.py: каталог всех AT-команд с метаданными
- obd/classifier.py: классификация ответов + определение уровня
- obd/connection.py: транспортный слой (SerialTransport)
- obd/protocol.py: init() только база, без ATAT1/ATST
- api/db.py: таблица device_profiles по BT MAC
- api/scripts.py: три уровня скриптов (l0/l1/l2)
- api/routes.py: /elm/probe, /elm/profile/<mac>, /script?level=
- web/templates/index.html: v0.48.0
- CHANGELOG.md, doc/architecture.md, resume.txt: версии
This commit is contained in:
“Naeel”
2026-06-07 05:55:02 +04:00
parent 7ae0fc5702
commit aa37a1a70c
13 changed files with 918 additions and 158 deletions
+99 -19
View File
@@ -1,29 +1,109 @@
"""Сборка диагностических скриптов."""
"""Сборка диагностических скриптов.
Три уровня в зависимости от возможностей ELM327:
L0 (все клоны) — 5 PIDs + stored DTC
L1 (+ATAT1) — 8 PIDs + VIN + stored/pending DTC
L2 (+CAF1/CFC1) — 14 PIDs + VIN + калибровки + все ошибки
Принцип:
- Чем выше уровень — тем больше PIDs и глубже диагностика
- Скрипты захардкожены (PIDs по SAE J1979), LLM не составляет
- Нет в профиле — не слать (несуществующие команды вешают клонов)
"""
def build_default_script() -> dict:
"""Минимальный скрипт для отладки: 1 PID → LLM."""
def build_script_l0() -> dict:
"""Скрипт для уровня 0 — клоны v1.5 и подобные.
Только однокадровые ответы. Без VIN (много-фреймовый, без CFC1 рвётся).
"""
return {
"version": 1,
"title": "Экспресс-диагностика",
"title": "Диагностика (базовая)",
"steps": [
{"id": "pid_05", "cmd": "0105", "desc": "Температура ОЖ"},
{"id": "elm_atrv", "cmd": "ATRV", "desc": "Напряжение"},
{"id": "pid_05", "cmd": "0105", "desc": "Температура ОЖ"},
{"id": "pid_0C", "cmd": "010C", "desc": "Обороты"},
{"id": "pid_0D", "cmd": "010D", "desc": "Скорость"},
{"id": "pid_11", "cmd": "0111", "desc": "Дроссель"},
{"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"},
{"id": "dtc_03", "cmd": "03", "desc": "Коды ошибок"},
],
}
def build_script_l1() -> dict:
"""Скрипт для уровня 1 — хорошие клоны с ATAT1.
Быстрее L0 за счёт адаптивного тайминга. VIN — медленно но возможно.
"""
return {
"version": 1,
"title": "Диагностика (стандартная)",
"steps": [
{"id": "elm_atrv", "cmd": "ATRV", "desc": "Напряжение"},
{"id": "pid_05", "cmd": "0105", "desc": "Температура ОЖ"},
{"id": "pid_0C", "cmd": "010C", "desc": "Обороты"},
{"id": "pid_0D", "cmd": "010D", "desc": "Скорость"},
{"id": "pid_11", "cmd": "0111", "desc": "Дроссель"},
{"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"},
{"id": "pid_06", "cmd": "0106", "desc": "STFT"},
{"id": "pid_07", "cmd": "0107", "desc": "LTFT"},
{"id": "vin_09", "cmd": "0902", "desc": "VIN"},
{"id": "dtc_03", "cmd": "03", "desc": "Сохр. ошибки"},
{"id": "dtc_07", "cmd": "07", "desc": "Pending ошибки"},
],
}
def build_script_l2() -> dict:
"""Скрипт для уровня 2 — настоящий ELM327 с CAF1+CFC1.
Полный фарш: много PIDs, VIN быстро, калибровки, все типы ошибок.
"""
return {
"version": 1,
"title": "Диагностика (полная)",
"steps": [
{"id": "elm_atrv", "cmd": "ATRV", "desc": "Напряжение"},
{"id": "pid_05", "cmd": "0105", "desc": "Температура ОЖ"},
{"id": "pid_0C", "cmd": "010C", "desc": "Обороты"},
{"id": "pid_0D", "cmd": "010D", "desc": "Скорость"},
{"id": "pid_11", "cmd": "0111", "desc": "Дроссель"},
{"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"},
{"id": "pid_06", "cmd": "0106", "desc": "STFT"},
{"id": "pid_07", "cmd": "0107", "desc": "LTFT"},
{"id": "pid_0B", "cmd": "010B", "desc": "MAP"},
{"id": "pid_0F", "cmd": "010F", "desc": "Темп. воздуха"},
{"id": "pid_10", "cmd": "0110", "desc": "MAF"},
{"id": "pid_1C", "cmd": "011C", "desc": "Стандарт OBD"},
{"id": "vin_09", "cmd": "0902", "desc": "VIN"},
{"id": "cal_09", "cmd": "0904", "desc": "Калибровка"},
{"id": "ecu_09", "cmd": "090A", "desc": "Имя ЭБУ"},
{"id": "dtc_03", "cmd": "03", "desc": "Сохр. ошибки"},
{"id": "dtc_07", "cmd": "07", "desc": "Pending ошибки"},
{"id": "dtc_0A", "cmd": "0A", "desc": "Перманентные"},
],
}
# ── Совместимость со старым API ─────────────────────────
def build_default_script() -> dict:
"""Минимальный скрипт (уровень 0)."""
return build_script_l0()
def build_full_script() -> dict:
"""Полный скрипт диагностики."""
return {
"version": 1,
"title": "Полная диагностика",
"steps": [
{"id": "pid_05", "cmd": "0105", "desc": "Температура ОЖ"},
{"id": "pid_0C", "cmd": "010C", "desc": "Обороты"},
{"id": "pid_0D", "cmd": "010D", "desc": "Скорость"},
{"id": "pid_11", "cmd": "0111", "desc": "Дроссель"},
{"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"},
{"id": "pid_06", "cmd": "0106", "desc": "STFT"},
{"id": "pid_07", "cmd": "0107", "desc": "LTFT"},
],
}
"""Полный скрипт (уровень 2)."""
return build_script_l2()
def build_script_for_level(level: int) -> dict:
"""Возвращает скрипт под уровень устройства."""
if level >= 2:
return build_script_l2()
elif level == 1:
return build_script_l1()
else:
return build_script_l0()