# Резюме elmAI — для нового чата > Создано: 2026-07-10 | Предыдущий чат: relay-отладка ## Проект elmAI — OBD2-диагностика через ELM327 + LLM (DeepSeek). Два репо: `elmer/` (gitea, сервер) и `elmer/android/` (github, Android). ## Версии | Компонент | Версия | |-----------|--------| | Основной APK (app) | v0.42.0-dev | | Raw-реле APK (raw) | v0.4.0-dev | ## Два режима 1. **app/** — прямая диагностика: телефон→ELM→скрипт→батч→сервер→LLM 2. **raw/** — ретранслятор: Copilot→сервер→телефон→ELM→ответ. HTTP-поллинг. ## Raw-реле (raw/) ``` Copilot → POST /cmd → очередь SQLite → GET /cmd (телефон) → sendCommand() → ELM ↓ Copilot ← GET /response?device_id=X&seq=N ← POST /response (телефон) ← ответ ``` **Ключевые файлы:** - `ElmProtocol.kt` — 1:1 с `app/.../ElmProtocol.kt` (AndrOBD: ATSP0→ATAT1→ATST→ATS0→ATL0→ATE0) - `ElmActor.kt` — single-thread executor - `RawRelayService.kt` — foreground-сервис: BT→init→поллинг - `RelayClient.kt` — HTTP к `/api/v1/elm/raw/*` **handle()**: BUS_ERROR→ATPC+ATSP0, ERROR→ATWS, STOPPED→только state. MAX_RETRIES=3. ## Результаты тестов (клоны v1.5) - Клон #1: 12/12 (100% первые 12), потом 13/16 (81%) - Клон #2: 13/18 (72%) - Закономерность: деградация после 10-12 команд - Двигатель заглушен: PID не работают (STOPPED) - RPM: 2688–2807, темп: 84–88°C, дроссель: 0–1.5% — данные верны ## Сервер (obdai.ru, 5.172.178.213) - nginx:443 → gunicorn:8000 (4 воркера) - Flask: `web/app.py`, blueprints: routes, dtc, ping, raw_elm - SQLite: `command_queue` (raw), `sessions` (app) - `/api/v1/elm/raw/*`: hello, cmd×2, response×2, status - **device_id обязателен** в `/response` - **Flask использует** `/opt/elmer/templates/index.html` (не web/templates) ## 12 главных провалов (подробно: `doc/failures-journal.md`) 1. Не скопировал рабочий `app/ElmProtocol.kt` — писал с нуля 2. Доверял Opus вместо проверки AndrOBD 3. ATST96 убивает клон 4. ATI в init ломает порядок 5. drainInput() в write() — буферный сдвиг 6. Freeze detection через ATRV 7. AT-команды в handle() 8. Recovery ATSP0 в relayLoop 9. Дренаж 0100 после init 10. Тест без device_id 11. Версия сайта не обновлялась 12. APK не долетел до телефона ## Правила (`.github/copilot-instructions.md`) 1. НИЧЕГО не делать без прямого указания 2. На вопросы — только отвечать 3. Коммит + push после каждой правки 4. При деплое — bump версии в build.gradle.kts 5. Формат: fix/feat/refactor/bump/docs 6. ELM327 — только как AndrOBD, без самодеятельности 7. Рассуждение ≠ команда ## Деплой raw APK ```bash cd android sed -i 's/appVersionCode = XX/appVersionCode = YY/' raw/build.gradle.kts sed -i 's/X.Y.Z-dev/X.Y+1.Z-dev/' raw/build.gradle.kts git add -A && git commit -m "bump vX.Y+1.Z-dev" && git push origin opus-fixes scp raw/build.gradle.kts raw/src/.../*.kt obdai.ru:/opt/elmer/android/raw/ ssh obdai.ru './gradlew :raw:assembleDebug && cp ...apk /opt/elmer/web/static/elm-raw-v022.apk' # Обновить версию в /opt/elmer/templates/index.html и /opt/elmer/web/templates/index.html ``` ## Ключевые документы - `doc/failures-journal.md` — 12 провалов - `doc/architecture.md` — полная архитектура - `doc/diagnostic-logic.md` — режимы диагностики - `STRUCTURE.md` — все файлы и папки ### Репозитории - Сервер: https://gitea.services.ngcloud.ru/Nail/elmer (ветка **dynamic-tests**) - Android: https://github.com/Repinoid/elmer-android (ветка **dynamic-tests**) - Сервер живёт на 5.172.178.213 (SSH: naeel@5.172.178.213, ключ ~/.ssh/naeel_vm_id_ed25519) ### Деплой (localhost → сервер) ```bash # 1. bump версии в android/app/build.gradle.kts на локальной машине! # 2. закоммитить + запушить (dynamic-tests!) cd /home/naeel/elmer && git add -A && git commit -m "..." && git push origin dynamic-tests # 3. залить android-исходники на сервер # 3. залить android-исходники на сервер cd /home/naeel/elmer && tar czf /tmp/android-src.tar.gz --exclude='.git' --exclude='build' --exclude='.gradle' android/ scp -i ~/.ssh/naeel_vm_id_ed25519 /tmp/android-src.tar.gz naeel@5.172.178.213:/tmp/ # 4. на сервере: обновить сервер + собрать APK ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 " cd /opt/elmer && git checkout dynamic-tests && git pull origin dynamic-tests pip install -r requirements.txt sudo systemctl restart elmer rm -rf android && tar xzf /tmp/android-src.tar.gz cd android && gradle wrapper --gradle-version 8.7 export ANDROID_SDK_ROOT=\$HOME/android-sdk ./gradlew clean assembleDebug cp app/build/outputs/apk/debug/app-debug.apk /opt/elmer/web/static/ " ``` ### Структура проекта ``` elmer/ android/ — Android-приложение (Kotlin) .../client/ MainActivity.kt — UI + приёмники ElmForwardService.kt — BT/TCP-реле TestService.kt — автономный тест ELM api/ — Flask API (Python) db.py — БД (sessions + device_profiles) routes.py — эндпоинты scripts.py — скрипты L0/L1/L2 parser.py — парсинг ответов config.py, dtc.py, ping.py brain/ — LLM-клиент, промпты obd/ — ELM-протокол (Python) commands.py — каталог AT-команд classifier.py — классификация ответов connection.py — SerialTransport probe.py — пробинг ELM protocol.py — стейт-машина AndrOBD state.py — состояния/ответы timing.py — адаптивный таймаут doc/ — Документация, сессии web/ — Flask web, статика ``` ### Что сделано (сессия 2026-06-07) #### Сервер - **Пробинг ELM**: трехуровневый каскад (L0/L1/L2), профили в БД по MAC - **Fix init**: больше не шлём ATAT1/ATSTxx (вешало клоны) - **Скрипты под уровень**: L0 (5 PIDs), L1 (8 + VIN), L2 (14 + калибровки) - **Рефакторинг**: код разбит на независимые модули (commands, classifier, connection...) #### Android - **Вывод**: append вместо overwrite (строки не перекрываются) - **Таймер**: отдельный TextView, тикает только во время обмена (Engine Time) - **TestService**: адаптивные таймауты, ATS0, \r терминатор ### Что НЕ сделано (TODO) - Полевой тест на машине ← СЕЙЧАС - Разбить MainActivity.kt - Разбить ElmChecker.kt ### Важные правила - ELM327 v1.5 — фейк, НЕ слать ATAT1/AT@1/AT@2/ATST/ATCAF1/ATCFC1 - Все статусы через append("\n..."), не tvStatus.text = - Таймер операций (opTimerStart/Stop), не сессии - Версию поднимать ВЕЗДЕ: build.gradle.kts, index.html (2 места), CHANGELOG.md, resume.txt, doc/architecture.md - В проекте elmer — НИЧЕГО не делать без прямого указания