chore: remove trash from root — analysis.md, idea.md, legacy-*, .instructions.md, logo.jpg, morda.md
This commit is contained in:
@@ -1,57 +0,0 @@
|
||||
# Инструкция для Copilot — проект elmAI
|
||||
|
||||
> Последнее обновление: 31 мая 2026 · v0.36.0-dev
|
||||
|
||||
## Репозитории
|
||||
|
||||
| Репо | Назначение | Хостинг |
|
||||
|------|-----------|---------|
|
||||
| `elmer/` (этот) | Сервер Python/Flask | gitea.services.ngcloud.ru/Nail/elmer |
|
||||
| `elmer/android/` | Android-приложение Kotlin | github.com/Repinoid/elmer-android |
|
||||
|
||||
## Деплой
|
||||
|
||||
### Сервер (obdai.ru, 5.172.178.213)
|
||||
- Код: `/opt/elmer` (git clone gitea)
|
||||
- Ветка: `master` (по умолчанию)
|
||||
- Деплой: `ssh obdai.ru "cd /opt/elmer && git pull && sudo systemctl restart elmer"`
|
||||
- Сервис: `gunicorn -w 4 -b 127.0.0.1:8000 web.app:app`
|
||||
- Прокси: nginx :443 → :8000
|
||||
- **APK отдавать напрямую через nginx, НЕ через Flask/gunicorn:** `location = /elmer.apk { alias /opt/elmer/web/static/app-debug.apk; }`
|
||||
|
||||
### APK
|
||||
- Сборка: **автоматически GitHub Actions** при пуше в master
|
||||
- Деплой: CI сам заливает APK на сервер (`appleboy/scp-action`)
|
||||
- Ссылка: `https://obdai.ru/elmer.apk` → nginx отдаёт напрямую `web/static/app-debug.apk`
|
||||
|
||||
### Версионирование
|
||||
- APK: `android/app/build.gradle.kts` → `versionName`
|
||||
- Сайт: `web/templates/index.html` (синхронизировать вручную)
|
||||
- Документация: в заголовках `.md` файлов
|
||||
|
||||
## Правила работы
|
||||
|
||||
1. **ЕСЛИ в диалоге содержится ВОПРОС в любой форме — только ответить. НИЧЕГО НЕ ПРЕДПРИНИМАТЬ.** Не писать код, не редактировать файлы, не коммитить, не деплоить. Только прямые императивы («сделай», «исправь», «напиши», «внеси», «задеплой») — команда к действию.
|
||||
2. **Не выдумывать инфраструктуру.** Никаких Docker, Kubernetes. Всё на голом железе.
|
||||
3. **Читать документацию перед действиями.** `doc/architecture.md` — канонический источник.
|
||||
3. **Не редактировать отчёты Опуса.** `doc/opus-review*.md` — только для чтения.
|
||||
4. **Ключи и токены:** LLM-ключ только на сервере (`config.yaml`), НЕ в APK. `X-Api-Key` приложения — через `BuildConfig.API_KEY` из `local.properties`.
|
||||
5. **Git:** `elmer/` и `elmer/android/` — отдельные репо, отдельные коммиты.
|
||||
6. **Ветки:** `master` — продакшен, `opus-fixes` и др. — для правок. Вливать в master когда готово.
|
||||
7. **После правок:** коммит + пуш + (если сервер) деплой через SSH.
|
||||
8. **Версия:** менять в трёх местах — `build.gradle.kts`, `index.html`, доки.
|
||||
9. **Документировать изменения** в `doc/history/YYYY-MM-DD.md` после каждого сеанса работы. Формат: 🔴/🟡/🟢 для приоритета, по файлам.
|
||||
|
||||
## Структура сервера
|
||||
|
||||
```
|
||||
elmer/
|
||||
├── api/ # REST, БД, скрипты, парсер
|
||||
├── brain/ # LLM-клиент, промпты
|
||||
├── obd/ # ELM327 стейт-машина
|
||||
├── web/ # Flask, шаблоны, статика (APK)
|
||||
├── android/ # Android-приложение (отдельный репо)
|
||||
├── doc/ # Документация
|
||||
├── config.yaml # LLM API key, порты
|
||||
└── run.py # Локальный запуск
|
||||
```
|
||||
-249
@@ -1,249 +0,0 @@
|
||||
# Elmer — анализ и план (2026-05-25)
|
||||
|
||||
## Суть проекта
|
||||
|
||||
Сервис анализа ошибок электроники автомобиля через ELM327 OBD2 + LLM.
|
||||
|
||||
## Железо
|
||||
|
||||
- **Сканер:** ELM327 Bluetooth v1.5, чип PIC18F25K80 (китайский клон)
|
||||
- **Ноутбук разработчика:** с Bluetooth, будет соединяться с ELM327 напрямую для отладки
|
||||
|
||||
## Целевая аудитория
|
||||
|
||||
- Технически любопытный автовладелец (не профессионал, но и не «глубинарий»)
|
||||
- Уже имеет ELM327 — значит базовое понимание есть
|
||||
- Хочет понять проблему, а не просто получить код ошибки
|
||||
|
||||
## Ключевые требования к ответам
|
||||
|
||||
- **Честная уверенность:** «С вероятностью ~80% проблема в X, потому что...»
|
||||
- **Пояснение логики:** почему именно этот вывод
|
||||
- **Предупреждения:** «Если НЕ помогло — тогда проверь Y»
|
||||
- **Никаких категоричных «меняй X»** без 100% уверенности
|
||||
- **Liability Protection:** нельзя чтобы пользователь сломал машину из-за неверного диагноза
|
||||
|
||||
## LLM
|
||||
|
||||
- Рассматривается DeepSeek (дёшево через API)
|
||||
- Или другая простая/дешёвая модель
|
||||
- Нужен RAG/grounding на реальных repair manuals и TSB, чтобы минимизировать галлюцинации
|
||||
|
||||
## Компоненты системы
|
||||
|
||||
1. **Android-приложение** (в последнюю очередь)
|
||||
- Стабильная версия Android (не гоняться за новейшей)
|
||||
- Максимально простое: минимум кнопок
|
||||
- Русский язык
|
||||
- Bluetooth SPP → ELM327
|
||||
|
||||
2. **Сервер** (после отладки логики на ноутбуке)
|
||||
- Принимает данные от приложения
|
||||
- Формирует запросы к LLM
|
||||
- Итеративный цикл: запрос → ответ → может запросить ещё параметры или действия от пользователя
|
||||
- Отдаёт диагноз с пояснениями
|
||||
|
||||
3. **LLM-слой**
|
||||
- Промпт с контекстом автомобиля (VIN → марка/модель/двигатель)
|
||||
- RAG на базу знаний (ошибки, мануалы, TSB)
|
||||
- Итеративная диагностика: сервер может переспрашивать LLM
|
||||
|
||||
## Протокол диагностики (конечный автомат)
|
||||
|
||||
Цикл:
|
||||
1. Приложение считывает VIN → сервер
|
||||
2. Приложение считывает коды ошибок → сервер
|
||||
3. Сервер → LLM: первичный анализ
|
||||
4. LLM может запросить:
|
||||
- Дополнительные PID'ы с ЭБУ (live data)
|
||||
- Действия от пользователя (прогазовать, проехать, считать на холодную и т.д.)
|
||||
5. Повторять пока не будет достаточно данных для диагноза
|
||||
6. Финальный ответ: диагноз + степень уверенности + пояснения + что делать
|
||||
|
||||
## План разработки (три фазы)
|
||||
|
||||
### Фаза 1: Ноутбук + ELM327 (СЕЙЧАС)
|
||||
- Python-скрипт: Bluetooth → ELM327 → читаем VIN, ошибки, PID'ы
|
||||
- Отправляем в LLM вручную — отлаживаем логику, промпты, цикл вопросов-ответов
|
||||
- Никакого сервера, никакого Android
|
||||
|
||||
### Фаза 2: Сервер
|
||||
- Flask/FastAPI — принимать данные, проксировать в LLM
|
||||
- База знаний / RAG
|
||||
- State machine диагностики
|
||||
|
||||
### Фаза 3: Android-приложение
|
||||
- Bluetooth SPP (Serial Port Profile) — есть нюансы на Android 12+
|
||||
- Минималистичный UI
|
||||
- Отправка данных на сервер, отображение ответов
|
||||
|
||||
## Риски
|
||||
|
||||
1. **ELM327 v1.5 клон** — неполный протокол, глюки на高速 CAN
|
||||
2. **PID'ы разные у разных марок** — нужна БД по производителям
|
||||
3. **LLM галлюцинации** — только grounding/RAG спасёт
|
||||
4. **Bluetooth SPP на Android 12+** — permissions, pairing
|
||||
|
||||
## Ресурсы
|
||||
|
||||
- `python-OBD` — библиотека для работы с ELM327 (или свой serial-протокол)
|
||||
- `pyserial` уже установлен в системе
|
||||
- DeepSeek API (или OpenRouter как альтернатива)
|
||||
|
||||
---
|
||||
|
||||
## Структура проекта (создана 2026-05-25)
|
||||
|
||||
```
|
||||
elmer/
|
||||
├── elmer/ # Python-пакет
|
||||
│ ├── __init__.py # версия 0.1.0
|
||||
│ ├── config.py # загрузка config.yaml + подстановка ${ENV}
|
||||
│ ├── elm.py # ELM327: pyserial, VIN, DTC, PID
|
||||
│ ├── db.py # SQLite: cars, tokens, llm_messages, ecu_parameters, dtc_codes
|
||||
│ ├── prompts.py # SYSTEM_PROMPT + build_user_prompt()
|
||||
│ └── diagnose.py # DeepSeek API (OpenAI-совместимый)
|
||||
├── config.yaml # настройки (BT-порт, API-ключ, PID'ы)
|
||||
├── requirements.txt # pyserial, pyyaml, requests
|
||||
├── run.py # главный вход: ELM → данные → LLM → печать + сохранение
|
||||
├── idea.md # исходная задумка
|
||||
└── analysis.md # этот файл
|
||||
```
|
||||
|
||||
## Запуск (в салоне авто)
|
||||
|
||||
```bash
|
||||
# 1. Установить зависимости
|
||||
pip install -r requirements.txt
|
||||
|
||||
# 2. Сопрячь ELM327 по Bluetooth
|
||||
bluetoothctl pair 11:22:33:44:55:66
|
||||
# (в config.yaml прописан порт /dev/rfcomm0)
|
||||
|
||||
# 3. Запустить
|
||||
DEEPSEEK_API_KEY=sk-... python run.py
|
||||
```
|
||||
|
||||
Что произойдёт:
|
||||
1. Подключится к ELM327
|
||||
2. Прочитает VIN
|
||||
3. Считает ошибки (stored mode 03 + pending mode 07)
|
||||
4. Считает параметры (обороты, температура, скорость, дроссель, MAP, IAT, топливные тримы)
|
||||
5. Отправит в DeepSeek → напечатает диагноз
|
||||
6. Сохранит всё в `elmer.db` (SQLite)
|
||||
|
||||
---
|
||||
|
||||
## Десктопный UI (Web)
|
||||
|
||||
Для тестирования на ноутбуке (не тыкать грязным пальцем в телефон):
|
||||
- `web/app.py` — Flask (порт 5005), один endpoint `/api/diagnose` (POST)
|
||||
- `web/templates/index.html` — одна кнопка, тёмная тема, результат
|
||||
- В будущем этот же код — прототип серверного API
|
||||
|
||||
Запуск:
|
||||
```bash
|
||||
DEEPSEEK_API_KEY=sk-... python web/app.py
|
||||
# Открыть http://localhost:5005
|
||||
```
|
||||
|
||||
## Версии для пользователей (будущее)
|
||||
|
||||
- **Android** — Kotlin/Java, Bluetooth SPP
|
||||
- **Windows** — тот же веб-интерфейс в WebView (или Electron, или просто браузер)
|
||||
- Общий серверный API между ними
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## Архитектура клиент-сервер (решено 2026-05-25)
|
||||
|
||||
### Принцип: тонкий клиент
|
||||
|
||||
Клиент ничего не знает о диагнозе. Только транспорт:
|
||||
|
||||
```
|
||||
ELM327 ←Bluetooth SPP→ Android Client ←HTTP JSON→ Сервер ←API→ DeepSeek
|
||||
```
|
||||
|
||||
### Клиент как универсальный SDK
|
||||
|
||||
- Пользователь вводит URL своего сервера (или используется наш по умолчанию)
|
||||
- Протокол HTTP/JSON документирован — любой backend
|
||||
- Два режима работы клиента:
|
||||
1. **«Опрос» (основной):** клиент сам читает VIN + DTC + PID'ы, шлёт JSON серверу
|
||||
2. **«Ретранслятор» (расширенный):** сервер шлёт сырые AT-команды, клиент пересылает ответ
|
||||
|
||||
### Десктоп
|
||||
|
||||
- Браузер (Chrome) → локальный Flask → pyserial → ELM327
|
||||
- Отдельного «приложения» для Windows не нужно
|
||||
- Тот же `web/app.py` — и тестовый UI, и прототип сервера
|
||||
|
||||
### Открытость и доверие
|
||||
|
||||
| Что | Где | Зачем |
|
||||
|---|---|---|
|
||||
| **Клиент (Android)** | GitHub (открытый) | Доверие — любой может проверить код, собрать сам |
|
||||
| **Сервер (Python)** | Gitea (закрытый) | API-ключи, логика, коммерческая часть |
|
||||
| **Публикация** | RuStore | Бесплатно, модерация = дополнительное доверие |
|
||||
|
||||
### Git-стратегия
|
||||
|
||||
- `gitea.services.ngcloud.ru/Nail/elmer` — разработка сервера (текущий репо)
|
||||
- `github.com/Nail/elmer-android` — клиент (будет создан), лицензия MIT
|
||||
- Серверный репо на GitHub НЕ публикуем
|
||||
|
||||
---
|
||||
|
||||
## TODO / Дорожная карта
|
||||
|
||||
### 🔴 Фаза 1 — отладка на ноутбуке (ближайшая)
|
||||
|
||||
- [ ] Проверить Bluetooth на ноутбуке: `hciconfig`, `bluetoothctl`
|
||||
- [ ] Сопрячь ELM327: `bluetoothctl pair <MAC>`
|
||||
- [ ] Привязать к `/dev/rfcomm0`: `rfcomm bind 0 <MAC>`
|
||||
- [ ] `pip install -r requirements.txt`
|
||||
- [ ] `DEEPSEEK_API_KEY=sk-... python run.py` — консольный тест
|
||||
- [ ] `DEEPSEEK_API_KEY=sk-... python web/app.py` — веб-тест
|
||||
- [ ] Подключить реальную машину, считать VIN + ошибки + параметры
|
||||
- [ ] Оценить качество ответа DeepSeek
|
||||
|
||||
### 🟡 Фаза 2 — сервер
|
||||
|
||||
- [ ] Выделенный сервер/ВМ (или Kubernetes pod)
|
||||
- [ ] Flask → production (gunicorn)
|
||||
- [ ] API: `/api/diagnose` (как сейчас), + `/api/sessions`, + `/api/history/<vin>`
|
||||
- [ ] База: миграция SQLite → PostgreSQL
|
||||
- [ ] RAG: база знаний (repair manuals, TSB) для grounding
|
||||
- [ ] State machine: итеративные запросы к LLM
|
||||
- [ ] HTTPS (Let's Encrypt)
|
||||
|
||||
### 🟢 Фаза 3 — Android-клиент
|
||||
|
||||
- [ ] Создать репо `github.com/Nail/elmer-android`
|
||||
- [ ] Kotlin, minSdk ~24 (Android 7), targetSdk 34
|
||||
- [ ] Bluetooth SPP: поиск, pairing, connect, read/write
|
||||
- [ ] OBD2 парсер: VIN (0902), DTC (03/07), PID (01XX)
|
||||
- [ ] UI: одна кнопка «Диагностика» + поле ввода URL сервера
|
||||
- [ ] HTTP-клиент: POST JSON на сервер, показ ответа (Markdown → текст)
|
||||
- [ ] Permissions: только BLUETOOTH + INTERNET
|
||||
- [ ] Подпись APK, публикация в RuStore
|
||||
- [ ] README: как собрать самому, как использовать с чужим сервером
|
||||
|
||||
---
|
||||
|
||||
## Заметки по итогам обсуждения
|
||||
|
||||
- **Гипотеза подтверждена:** DeepSeek уже дал полный анализ по логам VCDS. Лучше гугла.
|
||||
- **Модерация RuStore:** проверяет вредоносный код и permissions. BLUETOOTH + INTERNET — вопросов не вызовет.
|
||||
- **Sideload (APK напрямую):** проверок нет, но permissions видны до установки.
|
||||
- **Chrome на Android НЕ может:** Web Bluetooth API только BLE, Web Serial API не поддерживается.
|
||||
- **Termux с Python:** теоретически, но Bluetooth-доступ сложен.
|
||||
- **ELM327 v1.5 (PIC18F25K80):** китайский клон. Неполный протокол, возможны глюки. Держать в уме.
|
||||
- **Нет готового аналога:** ниша новая (LLM + OBD2), старые приложения без AI-анализа.
|
||||
|
||||
---
|
||||
|
||||
*Продолжить: тестировать в салоне авто с реальным ELM327.*
|
||||
@@ -1,60 +0,0 @@
|
||||
# obdai.ru — AI-диагностика автомобиля через ELM327
|
||||
|
||||
Сервис анализа ошибок электроники автомобиля с помощью ИИ (DeepSeek).
|
||||
|
||||
## Как работает
|
||||
|
||||
```
|
||||
ELM327 ←Bluetooth→ Телефон (тонкий клиент) ←HTTP→ Сервер ←API→ DeepSeek
|
||||
↑
|
||||
вся логика здесь
|
||||
```
|
||||
|
||||
## Железо пользователя
|
||||
|
||||
- ELM327 Bluetooth (клон PIC18F25K80 — дешёвый, массовый)
|
||||
- Android-телефон (7+)
|
||||
|
||||
## Тонкий клиент (Android)
|
||||
|
||||
Только транспорт, никакой логики:
|
||||
- Bluetooth SPP → ELM327
|
||||
- Читает сырые OBD-ответы
|
||||
- Отправляет HTTP POST на сервер
|
||||
- Показывает ответ от сервера
|
||||
|
||||
Открытый исходный код на GitHub → доверие пользователей.
|
||||
Публикация в RuStore.
|
||||
|
||||
## Сервер (вся логика)
|
||||
|
||||
1. Принимает сырые данные от клиента (`/api/v1/raw-obd`)
|
||||
2. Парсит: VIN, коды ошибок, параметры ЭБУ
|
||||
3. Формирует промпт → DeepSeek API
|
||||
4. LLM отвечает → сервер анализирует → может запросить ещё данные
|
||||
5. Итеративный цикл:
|
||||
- диагноз
|
||||
- или команда «считай ещё параметр X»
|
||||
- или задание водителю («прогазуй до 3000 об/мин», «проедь 5 км», «дожми до кикдауна»)
|
||||
6. Финальный ответ: диагноз + степень уверенности + пояснения + что делать
|
||||
|
||||
## Десктоп (для тестирования)
|
||||
|
||||
Ноутбук → Bluetooth → ELM327 → локальный Flask → DeepSeek.
|
||||
Браузерный UI. Без Android.
|
||||
|
||||
## Домен
|
||||
|
||||
**obdai.ru** (обыгрывается: «обдай грязью» + OBD + AI)
|
||||
|
||||
## LLM
|
||||
|
||||
DeepSeek (через OpenAI-совместимый API). Дёшево, справляется с анализом логов.
|
||||
|
||||
## Компоненты
|
||||
|
||||
| Компонент | Где | Технологии |
|
||||
|---|---|---|
|
||||
| Сервер | obdai.ru | Python, Flask → gunicorn, PostgreSQL |
|
||||
| Клиент Android | GitHub + RuStore | Kotlin, AndrOBD library (GPLv2), OkHttp |
|
||||
| Десктоп | Локально | Python, Flask, pyserial, браузер |
|
||||
@@ -1,86 +0,0 @@
|
||||
#!/bin/bash
|
||||
# Деплой Elmer на obdai.ru
|
||||
set -e
|
||||
|
||||
echo "=== Установка пакетов ==="
|
||||
apt update && apt install -y python3-pip python3-venv nginx certbot python3-certbot-nginx
|
||||
|
||||
echo "=== Клонирование репо ==="
|
||||
cd /opt
|
||||
git clone https://gitea.services.ngcloud.ru/Nail/elmer.git || (cd elmer && git pull)
|
||||
cd elmer
|
||||
git checkout fat-client
|
||||
|
||||
echo "=== Виртуальное окружение ==="
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
pip install gunicorn
|
||||
|
||||
echo "=== Конфигурация ==="
|
||||
cp config.yaml config.yaml.bak
|
||||
cat > config.yaml << 'YAML'
|
||||
elm327:
|
||||
port: /dev/rfcomm0
|
||||
baudrate: 38400
|
||||
|
||||
llm:
|
||||
api_key: "sk-ucI5YvOticoOQ9Kuj5K9mQ"
|
||||
model: "gpt-oss-120b"
|
||||
base_url: "https://api.aillm.ru/v1"
|
||||
|
||||
pids:
|
||||
"0105": ["coolant_temp", "°C"]
|
||||
"010C": ["rpm", "об/мин"]
|
||||
"010D": ["speed", "км/ч"]
|
||||
YAML
|
||||
|
||||
echo "=== Systemd сервис ==="
|
||||
cat > /etc/systemd/system/elmer.service << 'UNIT'
|
||||
[Unit]
|
||||
Description=Elmer Flask API
|
||||
After=network.target
|
||||
|
||||
[Service]
|
||||
User=naeel
|
||||
WorkingDirectory=/opt/elmer
|
||||
ExecStart=/opt/elmer/venv/bin/gunicorn -w 4 -b 127.0.0.1:8000 web.app:app
|
||||
Restart=always
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
UNIT
|
||||
|
||||
echo "=== Nginx ==="
|
||||
cat > /etc/nginx/sites-available/elmer << 'NGX'
|
||||
server {
|
||||
listen 80;
|
||||
server_name obdai.ru www.obdai.ru ai.obdai.ru test.obdai.ru;
|
||||
|
||||
location /static/ {
|
||||
alias /opt/elmer/web/static/;
|
||||
}
|
||||
|
||||
location / {
|
||||
proxy_pass http://127.0.0.1:8000;
|
||||
proxy_set_header Host $host;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
}
|
||||
}
|
||||
NGX
|
||||
|
||||
ln -sf /etc/nginx/sites-available/elmer /etc/nginx/sites-enabled/
|
||||
rm -f /etc/nginx/sites-enabled/default
|
||||
nginx -t && systemctl reload nginx
|
||||
|
||||
echo "=== SSL ==="
|
||||
certbot --nginx -d obdai.ru -d www.obdai.ru --non-interactive --agree-tos -m tazet@narod.ru || true
|
||||
|
||||
echo "=== Запуск ==="
|
||||
systemctl daemon-reload
|
||||
systemctl enable elmer
|
||||
systemctl restart elmer
|
||||
systemctl restart nginx
|
||||
|
||||
echo "=== ГОТОВО ==="
|
||||
curl -s http://obdai.ru/api/v1/script | head -c 50
|
||||
@@ -1,78 +0,0 @@
|
||||
## 4. Контекст проекта (РЕЗЮМЕ для нового чата)
|
||||
|
||||
### Что это
|
||||
elmAI — Android-приложение + Python-сервер для диагностики авто через ELM327.
|
||||
|
||||
### Текущая версия
|
||||
**v0.48.0** (APK: https://obdai.ru/elmer.apk)
|
||||
|
||||
### Репозитории
|
||||
- Сервер: https://gitea.services.ngcloud.ru/Nail/elmer (ветка master)
|
||||
- Android: https://github.com/Repinoid/elmer-android (ветка relay-only)
|
||||
- Сервер живёт на 5.172.178.213 (SSH: naeel@5.172.178.213, ключ ~/.ssh/naeel_vm_id_ed25519)
|
||||
|
||||
### Деплой
|
||||
```bash
|
||||
# ВСЕГДА сначала bump версии в android/app/build.gradle.kts!
|
||||
cd /home/naeel/elmer/android && git add -A && git commit -m "..." && git push origin master
|
||||
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 \
|
||||
"cd /opt/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 — НИЧЕГО не делать без прямого указания
|
||||
@@ -1,173 +0,0 @@
|
||||
# Морда elmAI v2
|
||||
|
||||
> Новая архитектура UI. Обсуждено 7 июня 2026.
|
||||
|
||||
## Макет
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 🔧 elmAI v?.?.? │
|
||||
│ 📡 Сервер ● 🔌 ELM ● 🚗 ЭБУ ● 🧠 LLM ● │ иконки + светофоры
|
||||
├──────────────────────────────────────────┤
|
||||
│ [ ОШИБКИ / ДИАГНОСТИКА / СТАРТ / СТОП ] │ одна кнопка
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ поле вывода результатов │
|
||||
│ │
|
||||
├──────────────────────────────────────────┤
|
||||
│ [📋 История] │
|
||||
├──────────────────────────────────────────┤
|
||||
│ [____________________________] [➤] │ поле ввода + кнопка
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Иконки и светофоры
|
||||
|
||||
Четыре иконки в строке под версией. Справа от каждой — цветной индикатор.
|
||||
|
||||
| Иконка | Текст | 🟢 Зелёный | 🟡 Жёлтый | 🔴 Красный |
|
||||
|--------|-------|-----------|----------|-----------|
|
||||
| 📡 | Сервер | ping < 3с | проверка... | нет связи |
|
||||
| 🔌 | ELM | BT + ATI ok | подключение... | нет ELM |
|
||||
| 🚗 | ЭБУ | 0100 ответил | — | нет связи с ЭБУ |
|
||||
| 🧠 | LLM | ping-llm ok | проверка... | нет доступа |
|
||||
|
||||
- Жёлтый — только на время проверки
|
||||
- LLM проверяется только если Сервер зелёный
|
||||
- ЭБУ проверяется только если ELM зелёный
|
||||
- **Тап по иконке** — перепроверка. Сбрасывает цвет на жёлтый, запускает проверку заново.
|
||||
|
||||
### Таймауты
|
||||
|
||||
- **ELM**: 2 попытки BT-подключения по ~4с = макс 8с → 🔴
|
||||
- **Сервер**: HTTP GET `/api/v1/ping`, таймаут 3с → 🔴
|
||||
- **LLM**: HTTP GET `/api/v1/ping-llm`, таймаут 5с → 🔴 (только если Сервер 🟢)
|
||||
- При тапе на иконку проверка запускается немедленно, без задержек.
|
||||
|
||||
### Стартовый сценарий
|
||||
|
||||
1. Открыли приложение → все индикаторы 🟡 или 🔴
|
||||
2. ELM 🟡 — пробуем подключиться (8с макс) → 🟢 или 🔴
|
||||
3. Сервер 🟡 — ping (3с) → 🟢 или 🔴
|
||||
4. Если Сервер 🟢 → LLM 🟡 — ping-llm (5с) → 🟢 или 🔴
|
||||
5. Если ELM 🟢 → ЭБУ — пробуем `0100` → 🟢 или 🔴
|
||||
|
||||
После первого цикла индикаторы не обновляются автоматически — только по тапу.
|
||||
|
||||
## Кнопка-трансформер
|
||||
|
||||
Одна широкая кнопка. Меняет текст, цвет и действие в зависимости от этапа.
|
||||
|
||||
```
|
||||
🔴 [⚠️ ОШИБКИ] — начальное состояние
|
||||
↓ тап
|
||||
сканирование DTC (03 + 07)
|
||||
↓
|
||||
🔵 [🔍 ДИАГНОСТИКА] — ошибки считаны
|
||||
↓ тап
|
||||
ЕСЛИ сервер 🟢 → запрос параметров ЭБУ → отправка на сервер → LLM-анализ → вывод
|
||||
ЕСЛИ сервер 🔴 → пояснение в выводе: «Сервер недоступен. Сделайте тест.»
|
||||
↓
|
||||
🟢 [▶ СТАРТ] — готов к динамическому тесту
|
||||
↓ тап
|
||||
подсказка в выводе: «Газ до 3000, 3-4с, сброс. → СТОП»
|
||||
запись 12 PID каждые 250мс
|
||||
↓
|
||||
🔴 [⏹ СТОП] — запись идёт
|
||||
↓ тап
|
||||
запись остановлена, данные в памяти
|
||||
вывод: «Записано N отсчётов. ➤ для отправки.»
|
||||
↓
|
||||
🟢 [▶ СТАРТ] — можно повторить тест
|
||||
```
|
||||
|
||||
- После СТОП можно снова нажать СТАРТ — новый тест, старые данные сохраняются.
|
||||
- **Отправка данных** — не кнопкой, а через ➤ в поле ввода.
|
||||
|
||||
## Поле вывода
|
||||
|
||||
- ScrollView, моноширинный шрифт
|
||||
- После done — кнопка «✕ Закрыть» (сворачивает вывод, возвращает все кнопки)
|
||||
- После Share в истории — возврат в приложение (стандартное поведение Android)
|
||||
|
||||
## Поле ввода + кнопка ➤
|
||||
|
||||
2 строки, всегда активно. Плейсхолдер: «Что беспокоит? Чем подробнее — тем лучше».
|
||||
|
||||
Кнопка ➤ справа:
|
||||
- **Обычный режим**: текст из поля → отправка на сервер (`/api/v1/chat`) → сервер спрашивает LLM → ответ в вывод
|
||||
- **После СТОП**: накопленные данные теста → отправка на сервер (`/api/v1/session/upload`) + текст (если есть) → сервер анализирует через LLM → ответ в вывод
|
||||
- Ответ → в поле вывода
|
||||
|
||||
## История
|
||||
|
||||
- Кнопка «📋 История»
|
||||
- Список последних 20 сессий (дата, заголовок, статус загрузки)
|
||||
- Выбор → диагноз во всплывающем окне
|
||||
- Кнопка «📤 Поделиться» → системный Share Sheet (Telegram, WhatsApp, Gmail...)
|
||||
- После Share — возврат в наше приложение
|
||||
|
||||
## Что удаляется
|
||||
|
||||
- Кнопки «📡 Сервер», «🔌 ELM», «🚗 ЭБУ» как отдельные — заменены на иконки со светофорами
|
||||
- Кнопки «⏱ На месте», «🚗 В движении» — всё через одну кнопку-трансформер
|
||||
- `tvDtcStatus` («Сначала считай ошибки») — не нужен
|
||||
- `cbFullMode` (чекбокс полной диагностики) — всегда полная
|
||||
- `tvPrompt` (оверлей) — не нужен
|
||||
- `btnDynStart` — не нужен
|
||||
|
||||
## Серверные изменения
|
||||
|
||||
Ничего нового — всё уже есть:
|
||||
- `/api/v1/ping` ✅
|
||||
- `/api/v1/ping-llm` ✅
|
||||
- `/api/v1/chat` ✅
|
||||
- `/api/v1/session/upload` с `dynamic_samples` ✅
|
||||
|
||||
## Текущий макет (реализовано)
|
||||
|
||||
```
|
||||
elmAI v0.68 📡🟢 ELM🟢 ECU🟢 LLM🟢 ← одна строка
|
||||
[ ОШИБКИ / ДИАГНОСТИКА / СТАРТ / СТОП ]
|
||||
вывод
|
||||
[ 📋 История ] ⏱ 12с ← таймер справа
|
||||
[____________________________] [➤] ← 3 строки ввода
|
||||
```
|
||||
|
||||
## Логика кнопки (стейт-машина)
|
||||
|
||||
| State | Текст | Цвет | Действие |
|
||||
|-------|-------|------|----------|
|
||||
| INIT | ⚠️ ОШИБКИ | 🟠 | scanDtc() |
|
||||
| DTC | 🔍 ДИАГНОСТИКА | 🔵 | runDiagnostics() |
|
||||
| DIAG | ▶ СТАРТ | 🟢 | startDynamicRecording() |
|
||||
| START | ⏹ СТОП | 🔴 | stopDynamicRecording() |
|
||||
| STOP | ▶ СТАРТ | 🟢 | не используется |
|
||||
|
||||
- Кнопка неактивна (alpha=0.4) если ELM 🔴 или ECU 🔴
|
||||
- Поле ввода неактивно если LLM 🔴
|
||||
- После DTC-сканирования ECU → 🟢
|
||||
- После СТОП → DIAG (можно снова СТАРТ)
|
||||
|
||||
## Исправлено (v0.57 → v0.68)
|
||||
|
||||
| v | Что |
|
||||
|---|-----|
|
||||
| 0.57 | Layout v2, иконки, трансформер |
|
||||
| 0.58 | Всё в одной строке |
|
||||
| 0.59 | setIndicator в runOnUiThread |
|
||||
| 0.60 | LLM → 🤓 |
|
||||
| 0.61 | Таймер в строке Истории, нет ELM → кнопка неактивна |
|
||||
| 0.62 | Поле ввода неактивно без LLM |
|
||||
| 0.63 | 🤓 → 🎓 |
|
||||
| 0.64 | 🎓 → LLM текст |
|
||||
| 0.65 | СТОП работает, ECU 🟢 после сканирования |
|
||||
| 0.66 | ensureConnected всегда перед dynamic test |
|
||||
| 0.67 | Кнопка неактивна без ECU |
|
||||
| 0.68 | Двойной вызов checkLlm/checkEcu убран, таймер в catch |
|
||||
|
||||
## Известные проблемы (TODO)
|
||||
|
||||
- `findElmDevice()` возвращает null при >1 устройствах (диалог асинхронный)
|
||||
- Android 12+ — startChecks до получения BT-разрешений
|
||||
- `State.STOP` не используется
|
||||
Reference in New Issue
Block a user