feat: DTC-коды: справочник, эндпоинты /dtc/decode, /dtc/upload
This commit is contained in:
@@ -231,6 +231,30 @@ class Database:
|
|||||||
).fetchall()
|
).fetchall()
|
||||||
return [dict(r) for r in rows]
|
return [dict(r) for r in rows]
|
||||||
|
|
||||||
|
def save_dtc_scan(self, client_info: dict, dtc_codes: list[str]):
|
||||||
|
"""Сохраняет быстрый скан кодов ошибок."""
|
||||||
|
self.conn.execute("""
|
||||||
|
INSERT INTO sessions (
|
||||||
|
client_ip, real_ip, user_agent,
|
||||||
|
phone_model, phone_maker, android_version, android_sdk,
|
||||||
|
app_version, android_id, device_uuid,
|
||||||
|
elm_mac, elm_bt_name,
|
||||||
|
dtc_count, response_count,
|
||||||
|
script_mode, transport,
|
||||||
|
raw_responses
|
||||||
|
) VALUES (?,?,?, ?,?,?,?, ?,?,?, ?,?, ?,?, ?,?,?)
|
||||||
|
""", (
|
||||||
|
client_info.get("client_ip"), client_info.get("real_ip"), client_info.get("user_agent"),
|
||||||
|
client_info.get("phone_model"), client_info.get("phone_maker"), client_info.get("android_version"),
|
||||||
|
client_info.get("android_sdk"), client_info.get("app_version"), client_info.get("android_id"),
|
||||||
|
client_info.get("device_uuid"),
|
||||||
|
client_info.get("elm_mac"), client_info.get("elm_bt_name"),
|
||||||
|
len(dtc_codes), 0,
|
||||||
|
"dtc_scan", client_info.get("transport", "bt"),
|
||||||
|
json.dumps([{"decoded": f"DTC stored: {c}"} for c in dtc_codes], ensure_ascii=False)
|
||||||
|
))
|
||||||
|
self.conn.commit()
|
||||||
|
|
||||||
# ── cars ──────────────────────────────────────────────
|
# ── cars ──────────────────────────────────────────────
|
||||||
|
|
||||||
def get_or_create_car(self, vin: str) -> int:
|
def get_or_create_car(self, vin: str) -> int:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ POST /api/v1/session/upload — приём батча, LLM-анализ, воз
|
|||||||
|
|
||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
from flask import jsonify, request
|
from flask import jsonify, request
|
||||||
|
|
||||||
@@ -63,6 +64,23 @@ def _build_diagnosis_prompt(data: dict, car_info: str = "") -> str:
|
|||||||
return "\n".join(parts)
|
return "\n".join(parts)
|
||||||
|
|
||||||
|
|
||||||
|
# Загрузка справочника DTC
|
||||||
|
_DTC_CODES: dict[str, str] = {}
|
||||||
|
|
||||||
|
def _load_dtc_dict():
|
||||||
|
global _DTC_CODES
|
||||||
|
if _DTC_CODES:
|
||||||
|
return _DTC_CODES
|
||||||
|
path = Path(__file__).parent.parent / "doc" / "dtc_codes.txt"
|
||||||
|
if path.exists():
|
||||||
|
for line in path.read_text(encoding="utf-8").splitlines():
|
||||||
|
line = line.strip()
|
||||||
|
if "=" in line and not line.startswith("#"):
|
||||||
|
code, desc = line.split("=", 1)
|
||||||
|
_DTC_CODES[code.strip()] = desc.strip()
|
||||||
|
return _DTC_CODES
|
||||||
|
|
||||||
|
|
||||||
def register(app):
|
def register(app):
|
||||||
"""Регистрирует эндпоинты скриптов на Flask-приложении."""
|
"""Регистрирует эндпоинты скриптов на Flask-приложении."""
|
||||||
|
|
||||||
@@ -234,6 +252,40 @@ def register(app):
|
|||||||
_ping_llm_cache = {"ts": now, "data": result, "ttl": ttl}
|
_ping_llm_cache = {"ts": now, "data": result, "ttl": ttl}
|
||||||
return jsonify(result)
|
return jsonify(result)
|
||||||
|
|
||||||
|
@app.route("/api/v1/dtc/decode", methods=["POST"])
|
||||||
|
def dtc_decode():
|
||||||
|
"""Расшифровка кодов DTC."""
|
||||||
|
data = request.get_json(silent=True) or {}
|
||||||
|
codes = data.get("codes", [])
|
||||||
|
if not codes:
|
||||||
|
return jsonify({"codes": []})
|
||||||
|
dtc = _load_dtc_dict()
|
||||||
|
decoded = []
|
||||||
|
for c in codes:
|
||||||
|
c = c.strip().upper()
|
||||||
|
decoded.append({"code": c, "desc": dtc.get(c, c)})
|
||||||
|
return jsonify({"codes": decoded})
|
||||||
|
|
||||||
|
@app.route("/api/v1/dtc/upload", methods=["POST"])
|
||||||
|
def dtc_upload():
|
||||||
|
"""Приём кодов ошибок без полной диагностики."""
|
||||||
|
data = request.get_json(silent=True)
|
||||||
|
if not data:
|
||||||
|
return jsonify({"error": "empty"}), 400
|
||||||
|
codes = data.get("dtc_codes", [])
|
||||||
|
client_info = data.get("client_info", {})
|
||||||
|
client_info["client_ip"] = request.remote_addr
|
||||||
|
|
||||||
|
try:
|
||||||
|
with Database() as db:
|
||||||
|
db.save_dtc_scan(client_info, codes)
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"DTC upload failed: {e}")
|
||||||
|
|
||||||
|
dtc = _load_dtc_dict()
|
||||||
|
decoded = [{"code": c, "desc": dtc.get(c.strip().upper(), c)} for c in codes]
|
||||||
|
return jsonify({"codes": decoded, "count": len(decoded)})
|
||||||
|
|
||||||
|
|
||||||
def _summary(p: dict) -> dict:
|
def _summary(p: dict) -> dict:
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
# Справочник OBD2 DTC кодов (русские описания)
|
||||||
|
# Источник: AndrOBD codes_ru.properties + общие открытые данные
|
||||||
|
# Формат: код=расшифровка
|
||||||
|
|
||||||
|
P0030=HO2S: нагреватель (bank 1 sensor 1) — цепь управления
|
||||||
|
P0031=HO2S: нагреватель (bank 1 sensor 1) — низкий уровень
|
||||||
|
P0032=HO2S: нагреватель (bank 1 sensor 1) — высокий уровень
|
||||||
|
P0100=ДМРВ: цепь — неисправность
|
||||||
|
P0101=ДМРВ: выход за диапазон / низкая производительность
|
||||||
|
P0102=ДМРВ: низкий сигнал
|
||||||
|
P0103=ДМРВ: высокий сигнал
|
||||||
|
P0105=MAP: цепь — неисправность
|
||||||
|
P0106=MAP: выход за диапазон
|
||||||
|
P0107=MAP: низкий сигнал
|
||||||
|
P0108=MAP: высокий сигнал
|
||||||
|
P0110=IAT: цепь датчика — неисправность
|
||||||
|
P0112=IAT: низкий сигнал
|
||||||
|
P0113=IAT: высокий сигнал
|
||||||
|
P0115=ECT: цепь датчика — неисправность
|
||||||
|
P0117=ECT: низкий сигнал
|
||||||
|
P0118=ECT: высокий сигнал
|
||||||
|
P0120=TPS / педаль газа A: цепь — неисправность
|
||||||
|
P0121=TPS: выход за диапазон
|
||||||
|
P0122=TPS: низкий сигнал
|
||||||
|
P0123=TPS: высокий сигнал
|
||||||
|
P0125=ECT: недостаточная температура для closed loop
|
||||||
|
P0128=Термостат: температура ниже нормы
|
||||||
|
P0130=ДК1 (bank 1 sensor 1): цепь — неисправность
|
||||||
|
P0131=ДК1 (bank 1 sensor 1): низкий сигнал
|
||||||
|
P0132=ДК1 (bank 1 sensor 1): высокий сигнал
|
||||||
|
P0133=ДК1 (bank 1 sensor 1): медленный отклик
|
||||||
|
P0134=ДК1 (bank 1 sensor 1): нет активности
|
||||||
|
P0135=ДК1 (bank 1 sensor 1): нагреватель — неисправность
|
||||||
|
P0136=ДК2 (bank 1 sensor 2): цепь — неисправность
|
||||||
|
P0137=ДК2 (bank 1 sensor 2): низкий сигнал
|
||||||
|
P0138=ДК2 (bank 1 sensor 2): высокий сигнал
|
||||||
|
P0141=ДК2 (bank 1 sensor 2): нагреватель — неисправность
|
||||||
|
P0170=Топливная коррекция (bank 1): неисправность
|
||||||
|
P0171=Топливная коррекция (bank 1): бедная смесь
|
||||||
|
P0172=Топливная коррекция (bank 1): богатая смесь
|
||||||
|
P0200=Форсунка: цепь — неисправность
|
||||||
|
P0201=Форсунка цилиндра 1 — неисправность
|
||||||
|
P0202=Форсунка цилиндра 2 — неисправность
|
||||||
|
P0203=Форсунка цилиндра 3 — неисправность
|
||||||
|
P0204=Форсунка цилиндра 4 — неисправность
|
||||||
|
P0220=TPS / педаль газа B: цепь — неисправность
|
||||||
|
P0300=Пропуски зажигания: случайные / множественные
|
||||||
|
P0301=Пропуски зажигания: цилиндр 1
|
||||||
|
P0302=Пропуски зажигания: цилиндр 2
|
||||||
|
P0303=Пропуски зажигания: цилиндр 3
|
||||||
|
P0304=Пропуски зажигания: цилиндр 4
|
||||||
|
P0325=Датчик детонации 1 (bank 1): цепь — неисправность
|
||||||
|
P0327=Датчик детонации 1: низкий сигнал
|
||||||
|
P0335=ДПКВ: цепь — неисправность
|
||||||
|
P0336=ДПКВ: выход за диапазон
|
||||||
|
P0340=ДПРВ: цепь — неисправность
|
||||||
|
P0341=ДПРВ: выход за диапазон
|
||||||
|
P0351=Катушка зажигания A (цилиндр 1): первичная цепь
|
||||||
|
P0352=Катушка зажигания B (цилиндр 2): первичная цепь
|
||||||
|
P0400=EGR: поток — неисправность
|
||||||
|
P0401=EGR: недостаточный поток
|
||||||
|
P0402=EGR: избыточный поток
|
||||||
|
P0403=EGR: цепь управления
|
||||||
|
P0420=Катализатор (bank 1): эффективность ниже порога
|
||||||
|
P0421=Прогревочный катализатор (bank 1): эффективность ниже порога
|
||||||
|
P0430=Катализатор (bank 2): эффективность ниже порога
|
||||||
|
P0440=EVAP: система улавливания паров — неисправность
|
||||||
|
P0442=EVAP: малая утечка
|
||||||
|
P0446=EVAP: клапан продувки — неисправность
|
||||||
|
P0455=EVAP: большая утечка
|
||||||
|
P0456=EVAP: очень малая утечка
|
||||||
|
P0500=Датчик скорости (VSS): неисправность
|
||||||
|
P0505=РХХ: неисправность
|
||||||
|
P0506=РХХ: обороты ниже нормы
|
||||||
|
P0507=РХХ: обороты выше нормы
|
||||||
|
P0560=Напряжение системы: неисправность
|
||||||
|
P0562=Напряжение системы: низкое
|
||||||
|
P0563=Напряжение системы: высокое
|
||||||
|
P0600=Последовательная линия: неисправность
|
||||||
|
P0601=ЭБУ: ошибка контрольной суммы
|
||||||
|
P0606=ЭБУ / PCM: внутренняя ошибка процессора
|
||||||
|
P0700=АКПП: запрос MIL (общая ошибка трансмиссии)
|
||||||
|
P0705=Датчик положения селектора АКПП: неисправность
|
||||||
|
P0715=Датчик скорости турбины АКПП: неисправность
|
||||||
|
P0720=Датчик выходной скорости АКПП: неисправность
|
||||||
|
P0740=Блокировка гидротрансформатора: неисправность
|
||||||
|
P0741=Блокировка гидротрансформатора: залипает
|
||||||
|
P0743=Блокировка гидротрансформатора: электрическая цепь
|
||||||
|
P0750=Соленоид А переключения АКПП: неисправность
|
||||||
|
P1100=ДМРВ: перемежающаяся ошибка
|
||||||
|
P1110=Система заслонок впуска: неисправность
|
||||||
|
P1120=TPS: выход за нижний предел
|
||||||
|
P1130=ДК1: медленный отклик (bank 1)
|
||||||
|
P1133=ДК1: недостаточная активность (bank 1 sensor 1)
|
||||||
|
P1135=ДК1: нагреватель — слабый ток (bank 1 sensor 1)
|
||||||
|
P1171=Топливная коррекция: бедная смесь при нагрузке
|
||||||
|
P1250=Автопрогрев термостата: неисправность
|
||||||
|
P1300=Зажигание: пропуски — повреждение катализатора
|
||||||
|
P1320=Зажигание: первичный сигнал
|
||||||
|
P1336=Датчик положения коленвала: не усвоен
|
||||||
|
P1340=Рассинхронизация распредвала/коленвала
|
||||||
|
P1400=EGR: залипание клапана
|
||||||
|
P1500=РХХ: обрыв цепи
|
||||||
|
P1540=Кондиционер: давление — неисправность
|
||||||
|
P1600=ЭБУ: потеря связи с иммобилайзером
|
||||||
|
P1610=Иммобилайзер: неверный код
|
||||||
|
P1700=АКПП: внутренняя ошибка контроллера
|
||||||
|
P2000=NOx ловушка (bank 1): эффективность ниже порога
|
||||||
|
P2100=Дроссель (ETC): цепь привода
|
||||||
|
P2101=Дроссель (ETC): выход за диапазон
|
||||||
|
P2120=Датчик педали газа A: цепь
|
||||||
|
P2122=Датчик педали газа A: низкий сигнал
|
||||||
|
P2123=Датчик педали газа A: высокий сигнал
|
||||||
|
P2135=TPS / педаль: корреляция A/B
|
||||||
|
P2138=Датчик педали газа: корреляция
|
||||||
|
P2187=Топливная коррекция: бедная смесь на холостом
|
||||||
|
P2188=Топливная коррекция: богатая смесь на холостом
|
||||||
|
P2195=ДК1: бедная смесь (bank 1 sensor 1)
|
||||||
|
P2196=ДК1: богатая смесь (bank 1 sensor 1)
|
||||||
|
P2237=ДК1: ток накачки (bank 1 sensor 1)
|
||||||
|
P2270=ДК2: бедная смесь (bank 1 sensor 2)
|
||||||
|
P2500=Генератор: лампа — низкий сигнал
|
||||||
|
P2503=Генератор: низкое напряжение
|
||||||
|
C0000=ABS: неисправность
|
||||||
|
B0000=Кузов: неисправность
|
||||||
|
U0000=Шина данных: неисправность
|
||||||
|
U0100=Шина CAN: потеря связи с ECM/PCM
|
||||||
|
U0121=Шина CAN: потеря связи с ABS
|
||||||
Reference in New Issue
Block a user