From a46f16d24b0f1c3f37b8c5832b6e820b34fc51d4 Mon Sep 17 00:00:00 2001 From: Repinoid Date: Tue, 26 May 2026 10:33:52 +0300 Subject: [PATCH] =?UTF-8?q?doc:=20=D0=BF=D0=BE=D0=BB=D0=BD=D1=8B=D0=B9=20?= =?UTF-8?q?=D0=BB=D0=BE=D0=B3=20=D1=81=D0=B5=D1=81=D1=81=D0=B8=D0=B8=20?= =?UTF-8?q?=E2=80=94=20=D0=B0=D1=80=D1=85=D0=B8=D1=82=D0=B5=D0=BA=D1=82?= =?UTF-8?q?=D1=83=D1=80=D0=B0,=20=D0=BE=D1=88=D0=B8=D0=B1=D0=BA=D0=B8,=20?= =?UTF-8?q?=D1=80=D0=B5=D1=88=D0=B5=D0=BD=D0=B8=D0=B5=20=D1=81=20offline-?= =?UTF-8?q?=D1=81=D0=BA=D1=80=D0=B8=D0=BF=D1=82=D0=B0=D0=BC=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- doc/session-2026-05-26.md | 83 +++++++++++++++++++++++++++++++++++++++ web/raw_endpoint.py | 2 +- 2 files changed, 84 insertions(+), 1 deletion(-) diff --git a/doc/session-2026-05-26.md b/doc/session-2026-05-26.md index 08dcf83..e320a94 100644 --- a/doc/session-2026-05-26.md +++ b/doc/session-2026-05-26.md @@ -48,6 +48,89 @@ CI упал с `org.gradle.api.artifacts.SelfResolvingDependency`. Причин И создан `gradle/wrapper/gradle-wrapper.properties` с `gradle-8.5-bin.zip`. +--- + +## ЧАСТЬ 2: Тест с реальным ELM327 (Фаэтон) + +### Зелёная кнопка (TestService) — 100% работает +- BT-подключение к ELM327 ✅ +- ATZ → ATEx → ATH1 ✅ +- VIN: получен (16-ричные данные) ✅ +- DTC stored/pending: получены ✅ +- PID'ы: RPM, ОЖ, скорость, дроссель и др. ✅ +- **Тайминги:** `Thread.sleep(250)` между командами — критически важно + +### Оранжевая кнопка (ElmForwardService + сервер) — НЕ работает +Проблема: стейт-машина сервера шлёт команды мгновенно, без пауз. ELM327 не успевает. +- ATZ → OK +- ATEx → OK +- 0902 → SEARCHING...UNABLE TO CONNECT (ELM не может выполнить режим 09) +- Сервер переходит к DTC → шлёт 03 → ELM отвечает `?` → бесконечный цикл `?` + +**Корень проблемы:** тонкий клиент требует server-driven архитектуру (сервер даёт команду → клиент пишет в ELM → ELM отвечает → клиент шлёт ответ серверу → сервер даёт следующую). Но сервер не делает пауз, а ELM327 требует ~200мс между командами. + +### Почему Deadlock при первом запуске оранжевой кнопки +1. Клиент: BT-коннект ✅, входит в loop() +2. ELM327: ждёт команду (не шлёт приветствие без запроса) +3. Клиент: `read()` блокируется — нет данных +4. Сервер: не получает "READY" — не шлёт ATZ +5. **DEADLOCK** + +**Исправлено:** `fwd("READY")` сразу после коннекта — кикстарт сервера. + +--- + +## Вывод: архитектура телефон↔сервер в реальных условиях + +### Проблема +В движении связи с сервером нет. Архитектура «сервер рулит каждой командой» нежизнеспособна. + +### Решение (обсуждено) +**Две фазы работы:** + +**Фаза 1 — ОФЛАЙН (в машине):** +- Клиент получает со старта **скрипт** от сервера +- Скрипт: последовательность команд + промпты водителю +- Клиент сам гоняет протокол (как зелёная кнопка) +- Данные пишутся локально (SQLite) с таймстемпами +- Водитель видит промпты: «Разгон 0-100», «Кикдаун», «Холостой ход 30с» +- Кнопка Старт / Стоп + +**Фаза 2 — ОНЛАЙН (дома):** +- Клиент заливает всю сессию одним POST на сервер +- Сервер парсит, анализирует, LLM → диагноз +- Возможно — выдаёт следующий скрипт для нового теста + +### Формат скрипта (пример): +```json +{ + "name": "Тест турбины", + "steps": [ + {"type": "obd", "cmd": "ATZ"}, + {"type": "obd", "cmd": "010C", "label": "RPM"}, + {"type": "prompt", "text": "Разгон 0-100, кикдаун"}, + {"type": "loop", "pid": "010C", "duration": 30, "rate_ms": 200}, + {"type": "obd", "cmd": "03"}, + {"type": "upload"} + ] +} +``` + +### Кто что делает +| Компонент | Файл | Статус | Что добавить | +|-----------|------|--------|-------------| +| Тестовый клиент | `TestService.kt` | ✅ гоняет протокол | Сохранение в БД, скрипты, промпты | +| Транспортный клиент | `ElmForwardService.kt` | ⚠️ требует стабильной связи | Возможно удалить | +| Стейт-машина | `raw_endpoint.py` | ⚠️ нет пауз | Переделать под батчевую обработку | +| Mock ELM327 | `mock_elm327.py` | ✅ эмулятор | Добавить задержки для реализма | +| Сервер приёма | `web/app.py` | ✅ | POST-эндпоинт для заливки сессии | + +### Договорённости по процессу +- **НИКОГДА не кодить без прямой команды** +- Сначала обсуждать → потом делать +- Коммитить часто, с понятными сообщениями +- Документировать все ошибки и решения + ### 08:40 — Ошибка 3: Коммиты не в ту ветку Изначально все изменения ушли в `master`, но рабочая ветка — `relay-only`. diff --git a/web/raw_endpoint.py b/web/raw_endpoint.py index 24c40ec..da3474a 100644 --- a/web/raw_endpoint.py +++ b/web/raw_endpoint.py @@ -210,7 +210,7 @@ def register(app): logger.info(f"[{session_id}] {parsed}") # SEARCHING/NO DATA — ждём, не продвигаем стейт - is_skip = raw.startswith("SEARCHING") or raw == "NO DATA" or raw == "STOPPED" + is_skip = raw.startswith("SEARCHING") or raw in ("NO DATA", "STOPPED", "?") if is_skip: sess["retries"] = sess.get("retries", 0) + 1 if sess["retries"] > 3: