96 lines
3.5 KiB
Python
96 lines
3.5 KiB
Python
"""Elmer Web UI — Flask-приложение для локального тестирования.
|
|
|
|
Заодно прототип будущего серверного API.
|
|
Запуск: DEEPSEEK_API_KEY=sk-... python web/app.py
|
|
Открыть: http://localhost:5005
|
|
"""
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Добавляем корень проекта в PYTHONPATH
|
|
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
|
|
from flask import Flask, jsonify, render_template, request
|
|
|
|
from elmer.config import load
|
|
from elmer.db import Database
|
|
from elmer.diagnose import Diagnoser
|
|
from elmer.elm import ELM327
|
|
from elmer.prompts import SYSTEM_PROMPT, build_user_prompt
|
|
|
|
app = Flask(__name__)
|
|
config = load()
|
|
|
|
|
|
@app.route("/")
|
|
def index():
|
|
"""Главная страница."""
|
|
return render_template("index.html")
|
|
|
|
|
|
@app.route("/api/diagnose", methods=["POST"])
|
|
def diagnose():
|
|
"""Подключается к ELM327, читает данные, отправляет в LLM, возвращает результат."""
|
|
elm_cfg = config["elm327"]
|
|
|
|
# ── 1. ELM327 ────────────────────────────────
|
|
try:
|
|
elm = ELM327(port=elm_cfg["port"], baudrate=elm_cfg["baudrate"])
|
|
except Exception as e:
|
|
return jsonify({"error": f"Не удалось открыть порт {elm_cfg['port']}: {e}"}), 500
|
|
|
|
if not elm.init():
|
|
elm.close()
|
|
return jsonify({"error": "ELM327 не ответил на ATZ"}), 500
|
|
|
|
# ── 2. VIN ──────────────────────────────────
|
|
vin = elm.read_vin()
|
|
if not vin:
|
|
elm.close()
|
|
return jsonify({"error": "Не удалось прочитать VIN (режим 09 не поддерживается?)"}), 500
|
|
|
|
# ── 3. Ошибки ───────────────────────────────
|
|
dtc_codes = elm.read_dtc_codes("03") + elm.read_dtc_codes("07")
|
|
|
|
# ── 4. Параметры ────────────────────────────
|
|
parameters = elm.read_all_pids(config.get("pids"))
|
|
|
|
elm.close()
|
|
|
|
# ── 5. DeepSeek ─────────────────────────────
|
|
api_key = config["deepseek"]["api_key"]
|
|
if not api_key:
|
|
return jsonify({"error": "DEEPSEEK_API_KEY не задан"}), 500
|
|
|
|
diagnoser = Diagnoser(
|
|
api_key=api_key,
|
|
model=config["deepseek"].get("model", "deepseek-chat"),
|
|
)
|
|
user_prompt = build_user_prompt(vin, dtc_codes, parameters)
|
|
answer = diagnoser.diagnose(SYSTEM_PROMPT, user_prompt)
|
|
|
|
# ── 6. SQLite ───────────────────────────────
|
|
db = Database()
|
|
car_id = db.get_or_create_car(vin)
|
|
token_id = db.create_token(car_id)
|
|
for dtc in dtc_codes:
|
|
db.add_dtc(token_id, dtc["code"], dtc.get("description", ""), dtc["status"])
|
|
for p in parameters:
|
|
db.add_parameter(token_id, p["pid_code"], p["name"], p["value"], p["unit"])
|
|
db.add_llm_message(token_id, "user", user_prompt)
|
|
db.add_llm_message(token_id, "assistant", answer)
|
|
|
|
return jsonify({
|
|
"vin": vin,
|
|
"dtc_codes": dtc_codes,
|
|
"parameters": parameters,
|
|
"diagnosis": answer,
|
|
"token_id": token_id,
|
|
})
|
|
|
|
|
|
if __name__ == "__main__":
|
|
print(f"🌐 Elmer Web: http://localhost:5005")
|
|
app.run(host="0.0.0.0", port=5005, debug=False)
|