diff --git a/doc/relay-mistakes-2026-07-04.md b/doc/relay-mistakes-2026-07-04.md new file mode 100644 index 0000000..7beb978 --- /dev/null +++ b/doc/relay-mistakes-2026-07-04.md @@ -0,0 +1,90 @@ +# ELM327 Relay — хронология ошибок и текущее состояние + +## Дата: 2026-07-04 + +--- + +## Текущая версия +**v0.3.7-dev** (commit `3e4eba7`, ветка `opus-fixes`) + +--- + +## Что работает (v0.3.5-dev, тест 13/15) +- AndrOBD-совместимый init: `ATSP0 → ATI → ATS0 → ATL0 → ATE0` +- Клон v1.5: ATAT1 и ATST пропускаются +- `handle()` **без AT-команд** — только state tracking (как AndrOBD) +- `recover()` — только сброс state в READY +- 87% успешных PID-команд после прогрева + +## Что НЕ работает +- **Буферный сдвиг после init**: первые 1-2 команды возвращают мусор/пустоту +- **STOPPED от ELM**: протокол останавливается, нужен перезапуск +- **Двигатель заглушен**: PID не работают, только ATRV + +--- + +## ВСЕ ошибки (хронология) + +### Ошибка 1: Freeze detection через ATRV (v0.3.0-dev) +**Что сделано**: каждые 10 команд слали ATRV для проверки залипания клона. +**Почему ошибка**: ATRV ломает синхронизацию команд. Ответ "12.6V" попадает в буфер и читается как ответ на следующий PID. +**Исправлено**: удалено в v0.3.2-dev. + +### Ошибка 2: AT-команды в handle() (v0.1.x–v0.3.3-dev) +**Что сделано**: handle() при STOPPED/UNABLE/BUS_ERROR слал ATPC→ATWS→ATSP0. +**Почему ошибка**: AT-команды отправляются внутри обработки ответа текущей команды. Их ответы загрязняют буфер для следующей команды. +**Исправлено**: удалено в v0.3.5-dev. handle() теперь только меняет state. + +### Ошибка 3: AT-команды в recover() (v0.1.x–v0.3.3-dev) +**Что сделано**: recover() слал ATPC→ATWS→ATSP0→ATE0 при state=ERROR/DISCONNECTED. +**Почему ошибка**: recover() вызывается из sendCommand() перед отправкой команды. AT-ответы могут не успеть полностью прийти до отправки PID. +**Исправлено**: упрощён в v0.3.3-dev. Только сброс state и timeout. + +### Ошибка 4: Дренаж 0100 после init (v0.3.6-dev) +**Что сделано**: попытка поглотить буферный сдвиг отправкой 0100 сразу после init. +**Почему ошибка**: дренаж сам вызывает сдвиг буфера и дезориентирует клон. +**Исправлено**: удалено в v0.3.7-dev. + +### Ошибка 5: Recovery ATSP0 в relayLoop (v0.3.5-dev–v0.3.7-dev) +**Что сделано**: после STOPPED или пустого ответа — ATSP0 для перезапуска протокола. +**Почему ошибка**: ATSP0 через sendBlocking блокирует single-thread executor. Последующие команды ждут в очереди, тест видит таймауты. +**Текущий статус**: всё ещё в коде v0.3.7-dev. + +### Ошибка 6: Тест без device_id в /response +**Что сделано**: тестовый скрипт вызывал `/response?wait=3` без device_id. +**Почему ошибка**: сервер возвращал ответы от чужих устройств/сессий. +**Исправлено**: сервер (raw_elm.py) обновлён — `/response` принимает `device_id` параметр. Тест обновлён. + +### Ошибка 7: Тест без обновления seq +**Что сделано**: тест всегда слал `seq=0` в `/response`. +**Почему ошибка**: сервер возвращал один и тот же ответ многократно. +**Исправлено**: тест обновляет seq после каждого ответа. + +### Ошибка 8: Версия на сайте не обновлялась +**Что сделано**: деплой менял HTML только в `/opt/elmer/web/templates/`. +**Почему ошибка**: Flask использует `/opt/elmer/templates/index.html`. +**Исправлено**: деплой теперь обновляет оба файла. + +--- + +## Отличия от AndrOBD + +| | AndrOBD | Наш код | +|---|---|---| +| Архитектура | Асинхронный (поток читает → handleTelegram) | Синхронный (sendCommand → ждать ответ) | +| write() | Не дренирует перед отправкой | drainInput() перед каждым write() | +| Init | ATSP0→ATAT1→ATS0→ATL0→ATE0 | ATSP0→ATI→ATS0→ATL0→ATE0 | +| ATI | Не используется | Для детекта клона v1.5 | +| handle() | Только state tracking | Только state tracking ✅ | +| Ошибки | Не шлёт AT-команд из handle() | Не шлёт AT-команд ✅ | + +--- + +## Ключевые файлы + +| Файл | Состояние | +|------|-----------| +| `ElmProtocol.kt` | handle() без AT-команд, recover() пустой | +| `RawRelayService.kt` | relayLoop с recovery ATSP0 | +| `ElmActor.kt` | Single-thread executor | +| `api/raw_elm.py` | /response с device_id фильтром |