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:
@@ -1,15 +1,11 @@
|
||||
"""SQLite — сохранение сессий диагностики.
|
||||
"""SQLite — сохранение сессий диагностики + профили ELM-устройств.
|
||||
|
||||
Таблица sessions (35+ колонок):
|
||||
client_ip, real_ip, user_agent, content_length, created_at
|
||||
phone_model, phone_maker, android_version, android_sdk, app_version
|
||||
android_id, device_uuid, phone_lang, phone_tz, phone_display
|
||||
elm_mac, elm_bt_name, obd_protocol
|
||||
vin, dtc_count, pid_count
|
||||
duration_ms, response_count, error_count, retry_count, timeout_count
|
||||
script_mode, transport, mock_mode, car_info
|
||||
diagnosis_text, diagnosis_len, llm_model, llm_duration_ms, llm_success
|
||||
raw_responses, request_id, response_json
|
||||
... (см. ниже)
|
||||
|
||||
Таблица device_profiles:
|
||||
mac (TEXT PK), level (INT), elm_version, elm_desc, protocol,
|
||||
supported (JSON), unsupported (JSON), first_seen, last_seen
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -108,6 +104,22 @@ class Database:
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_aid ON sessions(android_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_request_id ON sessions(request_id);
|
||||
CREATE INDEX IF NOT EXISTS idx_sessions_uuid ON sessions(device_uuid);
|
||||
|
||||
-- Профили ELM-устройств (по BT MAC)
|
||||
CREATE TABLE IF NOT EXISTS device_profiles (
|
||||
mac TEXT PRIMARY KEY, -- BT MAC-адрес
|
||||
level INTEGER NOT NULL, -- 0/1/2 (-1 = нерабочее)
|
||||
elm_version TEXT, -- ATI ответ
|
||||
elm_desc TEXT, -- AT@1 (если есть)
|
||||
protocol TEXT, -- ATDPN
|
||||
voltage TEXT, -- ATRV
|
||||
supported TEXT, -- JSON: ["ATE0","ATL0",...]
|
||||
unsupported TEXT, -- JSON: ["ATAT1",...]
|
||||
errors TEXT, -- JSON: ["ATCFC1: no response",...]
|
||||
first_seen TEXT NOT NULL DEFAULT (datetime('now')),
|
||||
last_seen TEXT NOT NULL DEFAULT (datetime('now'))
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_profiles_level ON device_profiles(level);
|
||||
""")
|
||||
self.conn.commit()
|
||||
|
||||
@@ -221,3 +233,52 @@ class Database:
|
||||
))
|
||||
self.conn.commit()
|
||||
|
||||
# ── device_profiles ──────────────────────────────────
|
||||
|
||||
def get_device_profile(self, mac: str) -> dict | None:
|
||||
"""Возвращает сохранённый профиль устройства по MAC, или None."""
|
||||
row = self.conn.execute(
|
||||
"SELECT * FROM device_profiles WHERE mac = ?", (mac,)
|
||||
).fetchone()
|
||||
if not row:
|
||||
return None
|
||||
p = dict(row)
|
||||
for f in ("supported", "unsupported", "errors"):
|
||||
p[f] = json.loads(p[f]) if p.get(f) else []
|
||||
return p
|
||||
|
||||
def save_device_profile(self, mac: str, profile: dict):
|
||||
"""Сохраняет или обновляет профиль устройства.
|
||||
|
||||
profile — результат obd.probe.probe().
|
||||
"""
|
||||
now = datetime.now(timezone.utc).isoformat()
|
||||
self.conn.execute("""
|
||||
INSERT INTO device_profiles
|
||||
(mac, level, elm_version, elm_desc, protocol, voltage,
|
||||
supported, unsupported, errors, first_seen, last_seen)
|
||||
VALUES (?,?,?,?,?,?, ?,?,?, ?,?)
|
||||
ON CONFLICT(mac) DO UPDATE SET
|
||||
level = excluded.level,
|
||||
elm_version = excluded.elm_version,
|
||||
elm_desc = excluded.elm_desc,
|
||||
protocol = excluded.protocol,
|
||||
voltage = excluded.voltage,
|
||||
supported = excluded.supported,
|
||||
unsupported = excluded.unsupported,
|
||||
errors = excluded.errors,
|
||||
last_seen = excluded.last_seen
|
||||
""", (
|
||||
mac,
|
||||
profile.get("level", -1),
|
||||
profile.get("elm_version"),
|
||||
profile.get("elm_desc"),
|
||||
profile.get("protocol"),
|
||||
profile.get("voltage"),
|
||||
json.dumps(profile.get("supported", []), ensure_ascii=False),
|
||||
json.dumps(profile.get("unsupported", []), ensure_ascii=False),
|
||||
json.dumps(profile.get("errors", []), ensure_ascii=False),
|
||||
now, now,
|
||||
))
|
||||
self.conn.commit()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user