fix(server): fallback парсинг raw если decoded не распознан
This commit is contained in:
+62
-3
@@ -43,6 +43,8 @@ def build_default_script() -> dict:
|
|||||||
|
|
||||||
def _parse_batch(responses: list[dict]) -> dict:
|
def _parse_batch(responses: list[dict]) -> dict:
|
||||||
"""Парсит батч ответов в структуру для LLM."""
|
"""Парсит батч ответов в структуру для LLM."""
|
||||||
|
import re
|
||||||
|
|
||||||
result = {
|
result = {
|
||||||
"vin": None,
|
"vin": None,
|
||||||
"dtc_stored": [],
|
"dtc_stored": [],
|
||||||
@@ -58,24 +60,79 @@ def _parse_batch(responses: list[dict]) -> dict:
|
|||||||
|
|
||||||
result["raw_log"].append(f"→ {cmd}\n← {raw}")
|
result["raw_log"].append(f"→ {cmd}\n← {raw}")
|
||||||
|
|
||||||
# VIN
|
# ── VIN ──
|
||||||
if decoded.startswith("VIN:"):
|
if decoded.startswith("VIN:"):
|
||||||
vin = decoded.replace("VIN:", "").strip()
|
vin = decoded.replace("VIN:", "").strip()
|
||||||
if len(vin) == 17:
|
if len(vin) == 17:
|
||||||
result["vin"] = vin
|
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:"):
|
if decoded.startswith("DTC stored:"):
|
||||||
codes = decoded.replace("DTC stored:", "").strip()
|
codes = decoded.replace("DTC stored:", "").strip()
|
||||||
if codes != "none":
|
if codes != "none":
|
||||||
result["dtc_stored"] = [c.strip() for c in codes.split()]
|
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:"):
|
if decoded.startswith("DTC pending:"):
|
||||||
codes = decoded.replace("DTC pending:", "").strip()
|
codes = decoded.replace("DTC pending:", "").strip()
|
||||||
if codes != "none":
|
if codes != "none":
|
||||||
result["dtc_pending"] = [c.strip() for c in codes.split()]
|
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")):
|
if ":" in decoded and not decoded.startswith(("VIN", "DTC", "ELM", "Protocol")):
|
||||||
parts = decoded.split(":", 1)
|
parts = decoded.split(":", 1)
|
||||||
if len(parts) == 2:
|
if len(parts) == 2:
|
||||||
@@ -84,6 +141,8 @@ def _parse_batch(responses: list[dict]) -> dict:
|
|||||||
"value": parts[1].strip(),
|
"value": parts[1].strip(),
|
||||||
})
|
})
|
||||||
|
|
||||||
|
logger.info(f"[{cmd}] decoded={decoded[:60]}")
|
||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user