docs: create AGENTS.md — comprehensive project description for AI agents
This commit is contained in:
@@ -0,0 +1,280 @@
|
||||
# elmAI — полное описание проекта для AI-агентов
|
||||
|
||||
> Последнее обновление: 2026-07-10 | Версия app: 1.18.0-dev | Версия raw: 0.4.1-dev
|
||||
|
||||
---
|
||||
|
||||
## 1. ЧТО ЭТО
|
||||
|
||||
elmAI — OBD2-диагностика автомобиля через ELM327-адаптер + LLM (DeepSeek).
|
||||
|
||||
Телефон подключается к ELM327 по Bluetooth, собирает данные с ЭБУ, отправляет на сервер, сервер анализирует через LLM и возвращает диагноз.
|
||||
|
||||
---
|
||||
|
||||
## 2. РЕПОЗИТОРИИ
|
||||
|
||||
| Репо | URL | Ветка | Что внутри |
|
||||
|------|-----|-------|-----------|
|
||||
| **Сервер** | `gitea.services.ngcloud.ru/Nail/elmer` | `dynamic-tests` | Python Flask + elmAI бэкенд |
|
||||
| **Android** | `github.com/Repinoid/elmer-android` | `opus-fixes` | Kotlin Android-приложение |
|
||||
|
||||
**ВАЖНО**: Android-репо лежит ВНУТРИ серверного: `/home/naeel/elmer/android/`. Это отдельный git-репо со своим remote. Коммитить и пушить надо ИЗНУТРИ `android/`.
|
||||
|
||||
---
|
||||
|
||||
## 3. СЕРВЕР (obdai.ru, 5.172.178.213)
|
||||
|
||||
```
|
||||
elmer/
|
||||
├── api/ # Flask API
|
||||
│ ├── routes.py # Основные эндпоинты (script, upload, chat, probe, sessions)
|
||||
│ ├── raw_elm.py # Командная очередь для raw-реле (SQLite table command_queue)
|
||||
│ ├── db.py # SQLite (sessions, device_profiles, command_queue)
|
||||
│ ├── scripts.py # Сборка диагностических скриптов L0/L1/L2 + dynamic
|
||||
│ ├── parser.py # Парсинг ответов ELM327 (PID, DTC, VIN)
|
||||
│ ├── dtc.py # Эндпоинты DTC
|
||||
│ ├── ping.py # Эндпоинты ping/ping-llm
|
||||
│ └── config.py # Загрузка config.yaml
|
||||
├── brain/ # LLM-клиент
|
||||
│ ├── client.py # Diagnoser — HTTP к DeepSeek
|
||||
│ └── prompts.py # Промпты для диагностики
|
||||
├── obd/ # ELM327 протокол (Python)
|
||||
│ ├── protocol.py # Стейт-машина AndrOBD (ElmProt.java)
|
||||
│ ├── connection.py, commands.py, classifier.py, probe.py, state.py, timing.py
|
||||
├── web/ # Flask web
|
||||
│ ├── app.py # Точка входа, регистрация blueprints
|
||||
│ ├── templates/index.html # Страница загрузки APK
|
||||
│ └── static/ # APK-файлы
|
||||
├── doc/ # ВСЯ документация
|
||||
├── config.yaml # API-ключи, порты
|
||||
└── deploy.sh # Скрипт деплоя
|
||||
```
|
||||
|
||||
**Стек**: Python 3, Flask, gunicorn (4 воркера, порт 8000), nginx (:443 → :8000), SQLite.
|
||||
|
||||
**Сервис**: `sudo systemctl restart elmer`
|
||||
|
||||
---
|
||||
|
||||
## 4. ANDROID
|
||||
|
||||
### 4.1. Основное приложение (`app/`) — прямая диагностика
|
||||
|
||||
**Пакет**: `ru.elmer.client` | **Версия**: 1.18.0-dev (versionCode 38)
|
||||
|
||||
```
|
||||
app/src/main/java/ru/elmer/client/
|
||||
├── Config.kt # Константы: HOST, SCRIPT_URL, defaultScript(), client()
|
||||
├── db/SessionDb.kt # SQLite: sessions, responses
|
||||
├── elm/
|
||||
│ ├── ElmProtocol.kt # Стейт-машина AndrOBD (1:1 с ElmProt.java)
|
||||
│ ├── ElmChecker.kt # Проверка ELM: checkDevice(), checkEcu(), scanDtc(), sendRaw()
|
||||
│ └── ObdDecoder.kt # Декодер PID/DTC/VIN (object-синглтон)
|
||||
├── script/
|
||||
│ └── DynamicCollector.kt # Циклический опрос PID с интервалом
|
||||
├── server/
|
||||
│ └── ServerClient.kt # HTTP к серверу (OkHttp): ping, pingLlm, chat, getSessions, uploadSession, downloadScript
|
||||
└── ui/
|
||||
└── MainActivity.kt # UI: индикаторы, кнопка-трансформер, чат, диагностика, динамический тест
|
||||
```
|
||||
|
||||
**8 классов**. Зависимости: OkHttp 4.12.0, AndroidX, org.json. БЕЗ Room, Coroutines, DI.
|
||||
|
||||
**Поток диагностики**: MainActivity → ElmChecker → ElmProtocol → команды → ObdDecoder → SessionDb → ServerClient.uploadSession() → ответ от LLM.
|
||||
|
||||
### 4.2. Raw-реле (`raw/`) — ретранслятор команд
|
||||
|
||||
**Пакет**: `ru.elmer.raw` | **Версия**: 0.4.1-dev (versionCode 18)
|
||||
|
||||
```
|
||||
raw/src/main/java/ru/elmer/raw/
|
||||
├── ElmProtocol.kt # 1:1 копия app/ElmProtocol.kt
|
||||
├── ElmActor.kt # Single-thread executor вокруг ElmProtocol
|
||||
├── RawRelayService.kt # Foreground-сервис: BT→init→поллинг команд→ответ
|
||||
├── RelayClient.kt # HTTP к /api/v1/elm/raw/* (OkHttp, БЕЗ X-Api-Key)
|
||||
└── MainActivity.kt # Минимальный UI (выбор BT, статус, счётчики)
|
||||
```
|
||||
|
||||
**5 классов**. Отдельный APK (`applicationId: ru.elmer.raw`).
|
||||
|
||||
**Поток**: RawRelayService → connectBt → ElmProtocol.init() → hello → цикл: pollCommand → sendCommand → postResponse.
|
||||
|
||||
**Назначение**: тупой ретранслятор. Сервер диктует команды, телефон передаёт в ELM и возвращает ответы. Используется для интерактивной диагностики через Copilot и тестов 3 мин / 5 мин.
|
||||
|
||||
---
|
||||
|
||||
## 5. ANDROID — ЧТО СДЕЛАНО (рефакторинг 2026-07-10)
|
||||
|
||||
Ветка `opus-fixes`, 8 коммитов:
|
||||
|
||||
1. **Config.kt** — единый источник хоста (`https://obdai.ru`), замена всех хардкодов
|
||||
2. **default_script.json** → `assets/`, DEFAULT_SCRIPT из кода удалён
|
||||
3. **ServerClient** — добавлены `chat()` и `getSessions()`, весь HTTP через OkHttp + X-Api-Key
|
||||
4. **HttpURLConnection** выпилен из MainActivity
|
||||
5. **ElmChecker.sendRaw()** — инкапсуляция ElmProtocol, `getElm()` удалён
|
||||
6. **FQN → import** — все полные имена заменены на нормальные import'ы
|
||||
7. **Удалён мёртвый код**: ScriptRunnerService, ScriptEngine, UploadProgress + FOREGROUND_SERVICE permissions
|
||||
|
||||
**Результат**: 8 классов (было 10), 0 HttpURLConnection, 0 FQN, 0 getElm(), 0 obdai.ru вне Config, весь HTTP аутентифицирован.
|
||||
|
||||
---
|
||||
|
||||
## 6. ANDROID — ЧТО НЕ СДЕЛАНО (TODO)
|
||||
|
||||
### app/
|
||||
- Разбить MainActivity (~750 строк) — вынести логику из UI
|
||||
- Разбить ElmChecker (372 строки) — отделить BT от ELM-команд
|
||||
- v1.5 клоны: деградация после 10-12 команд (ограничение железа)
|
||||
|
||||
### raw/
|
||||
- **deviceId** генерится заново при каждом создании RelayClient — сохранить в SharedPreferences
|
||||
- **Нет аутентификации** — BuildConfig.API_KEY есть, но RelayClient его не шлёт
|
||||
- **Нет retry** при ошибках HTTP
|
||||
- **SERVER_URL** захардкожен в build.gradle.kts и дублируется в Intent extra
|
||||
- **drainInput() в write()** — потенциальный сдвиг буфера (Неудача #5 из failures-journal.md)
|
||||
|
||||
### Сервер
|
||||
- Script Engine для режимов «3 мин на месте» / «5 мин в движении» — НЕ РЕАЛИЗОВАН
|
||||
- Дублирование: routes.py и script_endpoint.py (script_endpoint.py — мёртвый)
|
||||
|
||||
---
|
||||
|
||||
## 7. РЕЖИМЫ ДИАГНОСТИКИ
|
||||
|
||||
### Режим 1: Прямая диагностика (app/)
|
||||
Однократный сбор данных: скрипт → батч ответов → сервер → LLM → диагноз.
|
||||
|
||||
### Режим 2: Динамический тест (app/)
|
||||
Циклический опрос PID. Кнопка СТАРТ/СТОП. Сервер подбирает тайминги через `/api/v1/test/next`.
|
||||
|
||||
### Режим 3: Raw-реле (raw/)
|
||||
Сервер управляет потоком команд. Телефон — тупой ретранслятор.
|
||||
|
||||
### Режим 4: Прогрев на месте (raw/, 3 минуты)
|
||||
3 PID (RPM, темп, дроссель) каждые 2 секунды × 90 циклов = 270 запросов. Оценка прогрева, холостых, реакции на газ.
|
||||
|
||||
### Режим 5: В движении (raw/, 5 минут)
|
||||
Те же 3 PID каждые 2 секунды × 150 циклов = 450 запросов. Нагрузочный тест, динамика разгона.
|
||||
|
||||
*Режимы 4 и 5 требует реализации Script Engine на сервере.*
|
||||
|
||||
---
|
||||
|
||||
## 8. API ЭНДПОИНТЫ
|
||||
|
||||
### Основные (app/)
|
||||
|
||||
| Метод | Путь | Назначение |
|
||||
|-------|------|-----------|
|
||||
| GET | `/api/v1/ping` | Проверка сервера |
|
||||
| GET | `/api/v1/ping-llm` | Проверка LLM |
|
||||
| GET | `/api/v1/script?mode=test` | Скрипт диагностики |
|
||||
| POST | `/api/v1/session/upload` | Загрузка батча + LLM-анализ |
|
||||
| POST | `/api/v1/chat` | Чат с LLM |
|
||||
| GET | `/api/v1/sessions` | Список сессий |
|
||||
| POST | `/api/v1/test/next` | Следующий шаг динамического теста |
|
||||
| GET/PUT | `/api/v1/elm/profile/<mac>` | Профиль скорости ELM |
|
||||
|
||||
### Raw-реле (raw/)
|
||||
|
||||
| Метод | Путь | Назначение |
|
||||
|-------|------|-----------|
|
||||
| POST | `/api/v1/elm/raw/hello` | Android: «я готов» (чистит старые команды) |
|
||||
| POST | `/api/v1/elm/raw/cmd` | Copilot/сервер: поставить команду в очередь |
|
||||
| GET | `/api/v1/elm/raw/cmd?device_id=X` | Android: забрать pending команду |
|
||||
| POST | `/api/v1/elm/raw/response` | Android: вернуть ответ |
|
||||
| GET | `/api/v1/elm/raw/response?device_id=X&seq=N` | Copilot: прочитать ответ |
|
||||
| GET | `/api/v1/elm/raw/status` | Статус устройства |
|
||||
|
||||
---
|
||||
|
||||
## 9. ДЕПЛОЙ
|
||||
|
||||
### 9.1. Сервер
|
||||
|
||||
```bash
|
||||
cd /home/naeel/elmer
|
||||
git add -A && git commit -m "..." && git push origin dynamic-tests
|
||||
|
||||
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
|
||||
"
|
||||
```
|
||||
|
||||
### 9.2. Android APK (app)
|
||||
|
||||
```bash
|
||||
# 1. Bump версии в app/build.gradle.kts (versionCode и versionName)
|
||||
cd /home/naeel/elmer/android
|
||||
sed -i 's/versionCode = XX/versionCode = YY/' app/build.gradle.kts
|
||||
sed -i 's/versionName = "X.Y.Z-dev"/versionName = "X.Y+1.Z-dev"/' app/build.gradle.kts
|
||||
|
||||
# 2. Закоммитить + запушить
|
||||
git add -A && git commit -m "bump vX.Y+1.Z-dev" && git push origin opus-fixes
|
||||
|
||||
# 3. Залить исходники на сервер и собрать APK
|
||||
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/
|
||||
|
||||
ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 "
|
||||
rm -rf /opt/elmer/android && tar xzf /tmp/android-src.tar.gz -C /opt/elmer/
|
||||
cd /opt/elmer/android && gradle wrapper --gradle-version 8.7
|
||||
export ANDROID_SDK_ROOT=\$HOME/android-sdk
|
||||
./gradlew :app:clean :app:assembleDebug
|
||||
cp app/build/outputs/apk/debug/app-debug.apk /opt/elmer/web/static/
|
||||
"
|
||||
# 4. Обновить версию в /opt/elmer/web/templates/index.html и /opt/elmer/templates/index.html
|
||||
```
|
||||
|
||||
### 9.3. Raw APK
|
||||
|
||||
```bash
|
||||
# Аналогично app, но:
|
||||
# - bump версии в raw/build.gradle.kts
|
||||
# - сборка: ./gradlew :raw:assembleDebug
|
||||
# - копия: cp raw/build/outputs/apk/debug/raw-debug.apk /opt/elmer/web/static/elm-raw-v022.apk
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. ПРАВИЛА (НЕ НАРУШАТЬ)
|
||||
|
||||
1. **НИЧЕГО не делать без прямого указания пользователя.** Даже если видишь проблему — только сказать.
|
||||
2. **На вопрос — только ответ.** Не продолжать «а ещё могу...», не предлагать помощь.
|
||||
3. **После выполнения команды — сказать «готово» и ЖДАТЬ.**
|
||||
4. **Коммит + push после КАЖДОЙ правки.** Один коммит = одна правка. Формат: `fix:`, `feat:`, `refactor:`, `bump:`, `docs:`, `style:`, `chore:`.
|
||||
5. **При деплое — всегда bump версии.** Инкрементировать патч (Z в X.Y.Z-dev).
|
||||
6. **ELM327 — только как AndrOBD (ElmProt.java).** Никакой самодеятельности в протоколе. Init: ATSP0→ATAT1→ATS0→ATL0→ATE0. Никакого drainInput() перед write().
|
||||
7. **Не материться.** Пользователь матерится — ты нет.
|
||||
8. **Не гадать.** Если не уверен — проверить факты чтением кода.
|
||||
9. **Код правит ТОЛЬКО пользователь или Copilot по команде.** Не исполнять советы Opus по ELM-командам — Opus специалист по архитектуре кода, а не по ELM327.
|
||||
|
||||
---
|
||||
|
||||
## 11. КЛЮЧЕВЫЕ ДОКУМЕНТЫ
|
||||
|
||||
| Файл | Содержание |
|
||||
|------|-----------|
|
||||
| `AGENTS.md` | Этот файл — полное описание проекта |
|
||||
| `doc/architecture.md` | Архитектура сервера и Android |
|
||||
| `doc/diagnostic-logic.md` | 5 режимов диагностики |
|
||||
| `doc/failures-journal.md` | 12 провалов при разработке raw-реле |
|
||||
| `doc/SETUP.md` | Настройка окружения |
|
||||
| `STRUCTURE.md` | Полное дерево файлов |
|
||||
| `resume.txt` | Краткое резюме для нового чата |
|
||||
| `.github/copilot-instructions.md` | Правила для Copilot |
|
||||
| `android/doc/opus-arch-questions-2026-07-10.md` | Вопросы Opus по архитектуре |
|
||||
| `android/doc/opus-refactor-plan-2026-07-10.md` | План рефакторинга от Opus |
|
||||
|
||||
---
|
||||
|
||||
## 12. КОНТАКТЫ / ДОСТУП
|
||||
|
||||
- **Сервер**: 5.172.178.213, SSH: `naeel@5.172.178.213`, ключ: `~/.ssh/naeel_vm_id_ed25519`
|
||||
- **Домен**: obdai.ru (SSL через certbot)
|
||||
- **Gitea**: gitea.services.ngcloud.ru/Nail/elmer
|
||||
- **GitHub**: github.com/Repinoid/elmer-android
|
||||
Reference in New Issue
Block a user