docs: журнал неудач (12 провалов) + архив старого
This commit is contained in:
@@ -0,0 +1,192 @@
|
||||
# ELM327 Relay — полный журнал неудач
|
||||
|
||||
## Дата: 2026-07-04–05 | Версия: v0.4.0-dev
|
||||
|
||||
---
|
||||
|
||||
## Итоговое состояние
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Версия на сервере | v0.4.0-dev (commit `ebc41e0`) |
|
||||
| Основа | 1:1 с `app/.../ElmProtocol.kt` (AndrOBD) |
|
||||
| Клон 1 (v1.5) | 12/12 → 13/16 (72-81%) |
|
||||
| Клон 2 (v1.5) | 13/18 (72%) |
|
||||
| Характер отказов | Деградация после 10-12 команд |
|
||||
| Двигатель заглушен | PID не работают (STOPPED), только ATRV |
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 1: Игнорирование рабочего кода
|
||||
|
||||
**Симптом**: `raw/ElmProtocol.kt` написан с нуля вместо копирования `app/ElmProtocol.kt`
|
||||
**Когда**: создание raw-модуля (июнь 2026)
|
||||
**Что сделано не так**: В репозитории УЖЕ был `app/src/.../ElmProtocol.kt` — рабочий протокол на основе AndrOBD. Вместо копирования написан новый с «улучшениями».
|
||||
**Корневая причина**: предположение что raw-реле требует особой логики. Не проверено что `app/ElmProtocol.kt` уже работает.
|
||||
**Исправлено**: v0.4.0-dev — raw/ElmProtocol.kt = 1:1 копия app/ElmProtocol.kt
|
||||
**Урок**: всегда проверять существующий код перед созданием нового.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 2: Доверие Opus без проверки исходников
|
||||
|
||||
**Симптом**: init() с ATE0 первым, ATST96 для клонов, drain перед write
|
||||
**Когда**: июнь–июль 2026
|
||||
**Что сделано не так**: Opus посоветовал — реализовано без сверки с AndrOBD (ElmProt.java). AndrOBD 10 лет в проде, все «улучшения» были ошибками.
|
||||
**Корневая причина**: доверие внешнему анализу вместо проверки первоисточника.
|
||||
**Исправлено**: полная сверка с ElmProt.java (fr3ts0n/AndrOBD). Все отличия задокументированы.
|
||||
**Урок**: первоисточник (код) > любой анализ.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 3: ATST96 убивает клон v1.5
|
||||
|
||||
**Симптом**: клон зависает намертво после init, даже ATRV не отвечает
|
||||
**Когда**: v0.3.0-dev
|
||||
**Что сделано не так**: добавлен `ATST96` (150×4=600ms) для клонов. Команда не поддерживается клоном v1.5 и вешает его.
|
||||
**Корневая причина**: предположение что клону нужен фиксированный таймаут. AndrOBD использует `updateAtst()` с адаптивным таймаутом для всех устройств.
|
||||
**Исправлено**: ATST96 удалён. `updateAtst()` теперь вызывается всегда (как в AndrOBD).
|
||||
**Урок**: не добавлять команды, которых нет в AndrOBD.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 4: ATI в init() ломает порядок
|
||||
|
||||
**Симптом**: буферный сдвиг после каждой команды
|
||||
**Когда**: v0.3.0–v0.3.7-dev
|
||||
**Что сделано не так**: `ATI` вставлен в середину init() для детекта клона. AndrOBD не использует ATI — версия определяется из ответа ELM на MODEL.
|
||||
**Корневая причина**: желание детектить клон внутри init(). AndrOBD определяет клона иначе.
|
||||
**Исправлено**: v0.4.0-dev — ATI удалён из init(). Init: ATSP0→ATAT1→ATST→ATS0→ATL0→ATE0.
|
||||
**Урок**: не вставлять команды в init(), которых нет в AndrOBD.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 5: drainInput() в write()
|
||||
|
||||
**Симптом**: ответ команды N читается как ответ команды N+1
|
||||
**Когда**: все версии raw
|
||||
**Что сделано не так**: `write()` вызывает `drainInput()` перед отправкой. Если ответ предыдущей команды запаздывает, drain съедает его и наступает сдвиг буфера на 1 позицию.
|
||||
**Корневая причина**: AndrOBD не использует drain. Синхронная модель (sendCommand → ждать ответ) требует drain для очистки мусора, но drain сам создаёт мусор если ответ приходит с задержкой.
|
||||
**Статус**: НЕ ИСПРАВЛЕНО. Остаётся в коде v0.4.0-dev. Без drain буфер забивается мусором, с drain — сдвиг на 1 команду. Меньшее из зол.
|
||||
**Урок**: синхронная модель принципиально ограничена. AndrOBD использует асинхронную (поток читает → handleTelegram) и не имеет этой проблемы.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 6: Freeze detection через ATRV
|
||||
|
||||
**Симптом**: ответ "12.6V" читается как ответ на PID, все команды возвращают одно и то же
|
||||
**Когда**: v0.3.0-dev
|
||||
**Что сделано не так**: каждые 10 команд слался ATRV для проверки залипания. Ответ ATRV попадал в буфер и читался как ответ следующего PID.
|
||||
**Корневая причина**: ATRV — AT-команда, не OBD. Её ответ не должен смешиваться с PID-ответами. В синхронной модели это неизбежно.
|
||||
**Исправлено**: удалено в v0.3.2-dev.
|
||||
**Урок**: не смешивать AT-команды с OBD-командами в одном потоке.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 7: AT-команды в handle()
|
||||
|
||||
**Симптом**: после STOPPED/BUS_ERROR следующая команда получает мусор
|
||||
**Когда**: v0.1.x–v0.3.3-dev
|
||||
**Что сделано не так**: handle() при ошибках слал ATPC, ATWS, ATSP0. Эти AT-команды отправлялись внутри обработки ответа текущей команды, их ответы загрязняли буфер.
|
||||
**Корневая причина**: handle() вызывается из exec() который находится в процессе чтения ответа. Отправка AT-команд внутри exec() создаёт вложенные чтения, которые путают буфер.
|
||||
**Исправлено**: в v0.4.0-dev handle() шлёт AT-команды только для BUS_ERROR и ERROR (как в AndrOBD). Для STOPPED — только state tracking.
|
||||
**Урок**: AT-команды в handle() допустимы только если их ответы полностью потребляются (tryRead с таймаутом).
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 8: Recovery ATSP0 в relayLoop
|
||||
|
||||
**Симптом**: тест показывает 0/60 (все таймауты)
|
||||
**Когда**: v0.3.5-dev
|
||||
**Что сделано не так**: после STOPPED или пустого ответа relayLoop слал ATSP0 через sendBlocking. ATSP0 блокирует single-thread executor на 3+ секунд. Все последующие команды ждут в очереди, тест видит таймауты.
|
||||
**Корневая причина**: recovery выполнялся в том же потоке что и обработка команд. Команды накапливались в очереди executor'а.
|
||||
**Исправлено**: удалено в v0.4.0-dev. Recovery теперь только в handle().
|
||||
**Урок**: recovery должен быть частью протокольного уровня (ElmProtocol), а не оркестратора (relayLoop).
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 9: Дренаж 0100 после init
|
||||
|
||||
**Симптом**: relay не отвечает ни на одну команду после init
|
||||
**Когда**: v0.3.6-dev
|
||||
**Что сделано не так**: после init отправлялся 0100 для поглощения буферного сдвига. Дренаж сам создавал сдвиг и дезориентировал клон.
|
||||
**Корневая причина**: попытка «подчистить» буфер создаёт новую команду и новый ответ, который тоже надо чистить — бесконечная рекурсия.
|
||||
**Исправлено**: удалено в v0.3.7-dev.
|
||||
**Урок**: не пытаться чистить буфер дополнительными командами.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 10: Тест читал чужие ответы
|
||||
|
||||
**Симптом**: тест показывал OK (411100) когда relay возвращал пустоту
|
||||
**Когда**: все тесты до исправления сервера
|
||||
**Что сделано не так**: тестовый скрипт вызывал `/response?wait=3` без `device_id`. Сервер возвращал ответы от других устройств или предыдущих сессий.
|
||||
**Корневая причина**: серверный SQL не фильтровал по device_id. Тест не обновлял seq.
|
||||
**Исправлено**: сервер (`api/raw_elm.py`) — `/response` принимает `device_id`. Тест обновляет seq после каждого ответа.
|
||||
**Урок**: всегда проверять что тест читает данные того устройства которое тестируется.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 11: Версия на сайте не обновлялась
|
||||
|
||||
**Симптом**: сайт показывал v0.3.0-dev при v0.4.0-dev на сервере
|
||||
**Когда**: все деплои
|
||||
**Что сделано не так**: `sed` правил только `/opt/elmer/web/templates/index.html`. Flask использует `/opt/elmer/templates/index.html`.
|
||||
**Корневая причина**: два index.html в разных директориях, неизвестно какой использует Flask.
|
||||
**Исправлено**: деплой обновляет оба файла. Выяснено что Flask использует `/opt/elmer/templates/`.
|
||||
**Урок**: проверять какой файл реально сервится перед правкой.
|
||||
|
||||
---
|
||||
|
||||
## НЕУДАЧА 12: v0.4.0-dev не долетел до телефона
|
||||
|
||||
**Симптом**: пользователь тестировал v0.3.7-dev думая что это v0.4.0-dev
|
||||
**Когда**: 2026-07-04 вечер
|
||||
**Что сделано не так**: деплой v0.4.0-dev прошёл, APK на сервере, но пользователь не переустановил приложение.
|
||||
**Корневая причина**: отсутствие проверки версии на телефоне.
|
||||
**Исправлено**: явное указание версии при каждом деплое. Проверка MD5 APK на сервере.
|
||||
**Урок**: всегда проверять что пользователь обновил APK перед тестированием.
|
||||
|
||||
---
|
||||
|
||||
## ОГРАНИЧЕНИЯ КЛОНОВ v1.5 (железо)
|
||||
|
||||
| Параметр | Значение |
|
||||
|----------|----------|
|
||||
| Надёжность (холодный) | 100% первые 10-12 команд |
|
||||
| Надёжность (горячий) | 70-80%, деградация после 10-12 команд |
|
||||
| Буферный сдвиг после init | 1-2 команды (неизбежно в синхронной модели) |
|
||||
| Двигатель заглушен | PID не работают, ATRV — ок |
|
||||
| Двигатель заведён | 70-80% успех |
|
||||
| ATST96 | Убивает клон намертво |
|
||||
| ATAT1 | Клон игнорирует, не мешает |
|
||||
| Время восстановления | 2-3 секунды паузы |
|
||||
|
||||
---
|
||||
|
||||
## ТЕКУЩАЯ АРХИТЕКТУРА (v0.4.0-dev)
|
||||
|
||||
```
|
||||
Android phone Server (obdai.ru)
|
||||
┌──────────────────┐ ┌─────────────────────┐
|
||||
│ RawRelayService │──HTTP────→│ /api/v1/elm/raw/cmd │
|
||||
│ relayLoop() │←──poll───│ /api/v1/elm/raw/ │
|
||||
│ ↓ │ │ response │
|
||||
│ ElmActor │ └─────────────────────┘
|
||||
│ ↓ │
|
||||
│ ElmProtocol │──BT────→ ELM327 → OBD-II → ECU
|
||||
│ (AndrOBD) │←──BT───
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## КЛЮЧЕВЫЕ ФАЙЛЫ
|
||||
|
||||
| Файл | Версия | Описание |
|
||||
|------|--------|----------|
|
||||
| `raw/.../ElmProtocol.kt` | v0.4.0-dev | 1:1 с app/ElmProtocol.kt |
|
||||
| `raw/.../ElmActor.kt` | v0.4.0-dev | Single-thread executor |
|
||||
| `raw/.../RawRelayService.kt` | v0.4.0-dev | Поллинг + обработка ответов |
|
||||
| `api/raw_elm.py` | исправлен | /response с device_id |
|
||||
| `app/.../ElmProtocol.kt` | исходный | Протокол основного приложения |
|
||||
@@ -0,0 +1,24 @@
|
||||
# Тест AndrOBD протокола на клоне v1.5 — 04.07.2026
|
||||
|
||||
## Конфигурация
|
||||
- **ELM:** клон v1.5, протокол A0 (CAN)
|
||||
- **ECU:** зажигание ON, двигатель OFF
|
||||
- **Приложение:** ELM Relay v2 (v0.3.1-dev)
|
||||
- **Инит:** ATSP0→ATI→[без ATAT1/ATST]→ATS0→ATL0→ATE0 (AndrOBD порядок)
|
||||
|
||||
## Результат: 14/15 (93%)
|
||||
|
||||
| Цикл | PID | Ответ |
|
||||
|------|-----|-------|
|
||||
| 0 | 010C | ❌ (хвост инита) |
|
||||
| 0 | 0105 | ✅ 410579 (ОЖ 79°C) |
|
||||
| 0 | 0111 | ✅ 410579 |
|
||||
| 1 | 010C | ✅ 410C0000 (RPM 0) |
|
||||
| 1-4 | все | ✅ (12/12) |
|
||||
|
||||
## Выводы
|
||||
|
||||
1. **ATST96 убивает клон v1.5.** Без него — инит работает.
|
||||
2. **AndrOBD порядок (ATSP0 первый) — правильный.** ATE0 первым не нужен.
|
||||
3. **93% без залипания на 15 командах.** Раньше залипало на 4-й.
|
||||
4. **Первая команда провалена** — хвост от ATI/ATSP0 в буфере. Требует drain перед первым PID.
|
||||
@@ -1,6 +1,8 @@
|
||||
# ELM327 Relay — хронология ошибок и текущее состояние
|
||||
# ELM327 Relay — хронология ошибок (АРХИВ)
|
||||
|
||||
## Дата: 2026-07-04
|
||||
> **Устарело**. Актуальный документ: `doc/failures-journal.md`
|
||||
|
||||
## Дата: 2026-07-04 | Версия на момент написания: v0.3.7-dev
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user