From e6e575b9e6147d6e0b80b4affcc75c244c46e137 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Sun, 7 Jun 2026 11:48:49 +0400 Subject: [PATCH] =?UTF-8?q?docs:=20=D0=B0=D1=80=D1=85=D0=B8=D1=82=D0=B5?= =?UTF-8?q?=D0=BA=D1=82=D1=83=D1=80=D0=B0=20dynamic-tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/dynamic-tests.md | 107 +++++++++++++++++++++++++++++++++++++++++++ resume.txt | 12 +++-- 2 files changed, 114 insertions(+), 5 deletions(-) create mode 100644 doc/dynamic-tests.md diff --git a/doc/dynamic-tests.md b/doc/dynamic-tests.md new file mode 100644 index 0000000..a83e2d0 --- /dev/null +++ b/doc/dynamic-tests.md @@ -0,0 +1,107 @@ +# Динамические тесты — архитектура + +> v0.49.0-dev, 7 июня 2026 +> Ветка: `dynamic-tests` + +## Концепция + +Два теста: **на месте** и **в движении**. Разница — только в подсказке юзеру. +Физически оба делают одно: опрашивают 12 PID каждые 250мс, копят в памяти, отправляют на сервер одной пачкой. + +## Flow + +``` +Юзер → кнопка «⏱ На месте» / «🚗 В движении» + → подсказка в окне вывода + → кнопка «▶ Старт» + → опрос 12 PID каждые 250мс, вывод: «запись... N отсчётов» + → кнопка «⏹ Стоп» + → отправка на сервер POST /api/v1/session/upload + → LLM-анализ → вывод в чат +``` + +## Скрипт (сервер) + +Новый режим `?mode=dynamic` в `api/scripts.py`: + +```json +{ + "version": 1, + "title": "Динамический тест", + "mode": "dynamic", + "interval_ms": 250, + "steps": [ + {"id": "pid_04", "cmd": "0104", "desc": "Нагрузка"}, + {"id": "pid_05", "cmd": "0105", "desc": "ОЖ"}, + {"id": "pid_06", "cmd": "0106", "desc": "STFT"}, + {"id": "pid_07", "cmd": "0107", "desc": "LTFT"}, + {"id": "pid_0B", "cmd": "010B", "desc": "MAP"}, + {"id": "pid_0C", "cmd": "010C", "desc": "RPM"}, + {"id": "pid_0D", "cmd": "010D", "desc": "Скорость"}, + {"id": "pid_0E", "cmd": "010E", "desc": "Зажигание"}, + {"id": "pid_0F", "cmd": "010F", "desc": "IAT"}, + {"id": "pid_10", "cmd": "0110", "desc": "MAF"}, + {"id": "pid_11", "cmd": "0111", "desc": "Дроссель"}, + {"id": "pid_1F", "cmd": "011F", "desc": "Время работы"} + ] +} +``` + +## Хранение данных (Android) + +### До отправки — в памяти +```kotlin +data class DynamicSample( + val ts: Long, // System.currentTimeMillis() + val responses: List // 12 ответов ELM +) + +val samples = mutableListOf() // в памяти, быстро +``` + +### После СТОП — попытка отправки +```kotlin +1. Собираем все samples в JSON +2. POST /api/v1/session/upload +3. Если 200 → ОК, забыли +4. Если ошибка → пишем ВСЁ в SessionDb +``` + +### Локальное хранение — через SessionDb (уже есть) +```sql +-- Таблица sessions (уже существует) +session_type = "dynamic" -- отличаем от обычных + +-- Таблица responses (уже существует) +-- Каждый сэмпл = одна запись в responses: +-- session_id, step_id = "sample_N", cmd = "batch", +-- raw = JSON всего опроса, decoded = "запись №N" +``` + +**Плюсы**: не надо новой таблицы, `SessionDb` уже умеет `createSession`/`addResponse`/`getResponses`. + +**Объём**: 30 секунд × 4 опроса/с × 12 PID = 1440 записей ≈ ~100KB — норм. + +### Ретрай непосланных сессий +При старте приложения: `db.getUnuploadedSessions()` → отправить → пометить `uploaded=1`. + +## Промпт для LLM (сервер) + +Отдельный `DYNAMIC_PROMPT` в `brain/prompts.py`: + +``` +Ты — эксперт по диагностике. Получены временные ряды 12 параметров с интервалом 250мс. +Проанализируй: +1. Отклик дросселя — есть ли задержка/провалы +2. STFT/LTFT — богатая или бедная смесь под нагрузкой и при сбросе +3. RPM — плавность роста/падения, пропуски +4. MAP — соответствует ли оборотам +5. Зажигание — есть ли коррекция, детонация +6. Аномалии — резкие скачки, выбросы +Отвечай кратко: 2-3 предложения вывода, затем по пунктам что не так. +``` + +## Что НЕ делаем +- GPS / акселерометр — не сейчас +- Автодетект фаз (разгон/сброс) — ручной СТАРТ/СТОП +- Отправка пачками в реальном времени — копим всё до СТОП diff --git a/resume.txt b/resume.txt index 0a955a2..442cb41 100644 --- a/resume.txt +++ b/resume.txt @@ -9,15 +9,17 @@ elmAI — Android-приложение + Python-сервер для диагно **v0.49.0-dev** (APK: https://obdai.ru/elmer.apk) ### Репозитории -- Сервер: https://gitea.services.ngcloud.ru/Nail/elmer (ветка master) -- Android: https://github.com/Repinoid/elmer-android (ветка relay-only) +- Сервер: 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. закоммитить + запушить -cd /home/naeel/elmer && git add -A && git commit -m "bump vX.Y.Z-dev" && git push origin master +# 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/ @@ -25,7 +27,7 @@ scp -i ~/.ssh/naeel_vm_id_ed25519 /tmp/android-src.tar.gz naeel@5.172.178.213:/t # 4. на сервере: обновить сервер + собрать APK ssh -i ~/.ssh/naeel_vm_id_ed25519 naeel@5.172.178.213 " - cd /opt/elmer && git checkout master && git pull origin master + cd /opt/elmer && git checkout dynamic-tests && git pull origin dynamic-tests pip install -r requirements.txt sudo systemctl restart elmer