From 0fb919fa7c17a24d2c6798ee3298bfc40fd6c9aa Mon Sep 17 00:00:00 2001 From: Repinoid Date: Tue, 26 May 2026 13:22:48 +0300 Subject: [PATCH] =?UTF-8?q?fix(server):=20fallback=20=D0=BF=D0=B0=D1=80?= =?UTF-8?q?=D1=81=D0=B8=D0=BD=D0=B3=20raw=20=D0=B5=D1=81=D0=BB=D0=B8=20dec?= =?UTF-8?q?oded=20=D0=BD=D0=B5=20=D1=80=D0=B0=D1=81=D0=BF=D0=BE=D0=B7?= =?UTF-8?q?=D0=BD=D0=B0=D0=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- web/script_endpoint.py | 65 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/web/script_endpoint.py b/web/script_endpoint.py index 6021b87..516b2fe 100644 --- a/web/script_endpoint.py +++ b/web/script_endpoint.py @@ -43,6 +43,8 @@ def build_default_script() -> dict: def _parse_batch(responses: list[dict]) -> dict: """Парсит батч ответов в структуру для LLM.""" + import re + result = { "vin": None, "dtc_stored": [], @@ -58,24 +60,79 @@ def _parse_batch(responses: list[dict]) -> dict: result["raw_log"].append(f"→ {cmd}\n← {raw}") - # VIN + # ── VIN ── if decoded.startswith("VIN:"): vin = decoded.replace("VIN:", "").strip() if len(vin) == 17: result["vin"] = vin + elif "49" in raw and ("02" in raw or "4902" in raw.replace(" ", "")): + # fallback: парсим VIN из raw + # формат: "014 0:49 02 01 57 56 57..." или "490201575657..." + clean = raw.replace(":", "").replace(" ", "").upper() + if "490201" in clean: + hex_str = clean.split("490201")[-1][:34] + vin = "" + for i in range(0, len(hex_str) - 1, 2): + try: + vin += chr(int(hex_str[i:i+2], 16)) + except (ValueError, OverflowError): + pass + if len(vin) == 17: + result["vin"] = vin + decoded = f"VIN: {vin}" # для лога - # DTC + # ── DTC ── if decoded.startswith("DTC stored:"): codes = decoded.replace("DTC stored:", "").strip() if codes != "none": result["dtc_stored"] = [c.strip() for c in codes.split()] + elif raw.replace(" ", "").startswith("43"): + # fallback: парсим DTC из raw 43XX... + clean = raw.replace(" ", "").upper() + if clean.startswith("43") and len(clean) >= 4: + codes = [] + i = 2 # skip byte count + while i + 3 < len(clean): + try: + a = int(clean[i:i+2], 16) + b = int(clean[i+2:i+4], 16) + p = {0: "P", 1: "C", 2: "B", 3: "U"}.get(a >> 6, "?") + code = f"{p}{(a>>4)&3}{a&15}{b>>4:X}{b&15:X}" + if code != "P0000": + codes.append(code) + except Exception: + pass + i += 4 + if codes: + result["dtc_stored"] = codes + decoded = f"DTC stored: {' '.join(codes)}" if decoded.startswith("DTC pending:"): codes = decoded.replace("DTC pending:", "").strip() if codes != "none": result["dtc_pending"] = [c.strip() for c in codes.split()] + elif raw.replace(" ", "").startswith("47"): + # fallback: pending DTC + clean = raw.replace(" ", "").upper() + if clean.startswith("47") and len(clean) >= 4: + codes = [] + i = 2 + while i + 3 < len(clean): + try: + a = int(clean[i:i+2], 16) + b = int(clean[i+2:i+4], 16) + p = {0: "P", 1: "C", 2: "B", 3: "U"}.get(a >> 6, "?") + code = f"{p}{(a>>4)&3}{a&15}{b>>4:X}{b&15:X}" + if code != "P0000": + codes.append(code) + except Exception: + pass + i += 4 + if codes: + result["dtc_pending"] = codes + decoded = f"DTC pending: {' '.join(codes)}" - # PID (формат: "Имя: значение") + # ── PID ── if ":" in decoded and not decoded.startswith(("VIN", "DTC", "ELM", "Protocol")): parts = decoded.split(":", 1) if len(parts) == 2: @@ -84,6 +141,8 @@ def _parse_batch(responses: list[dict]) -> dict: "value": parts[1].strip(), }) + logger.info(f"[{cmd}] decoded={decoded[:60]}") + return result