Files
elmer/doc/session-2026-05-28.md
T

6.3 KiB
Raw Blame History

Сессия 2026-05-28 — AndrOBD стейт-машина, ELM-протокол, отладка

Хронология

08:00 — Тест v0.12.0-dev на моке

Скрипт отработал (ELM — зелёный), но upload «Сервер недоступен». Flask работал локально, проброс портов был настроен.

Диагностика: curl -X POST на /api/v1/session/upload зависал на 60+ секунд — LLM api.aillm.ru долго отвечал, Flask ждал, OkHttp на телефоне таймаутил через 30с.

Исправление: OkHttp readTimeout увеличен с 30с до 120с → v0.13.0-dev.

09:00 — Стейт-машина AndrOBD

Пользователь потребовал НЕ изобретать своё, а скопировать 1:1 отлаженный код AndrOBD.

Создана ветка androbd-proto.

Проблема 1: команды слались подряд, ответы перемешивались

Было (init() старая):

sendRaw("ATSP0"); sleep(200)  # шлём, НЕ читаем ответ
sendRaw("ATAT1"); sleep(200)  # шлём, НЕ читаем ответ
# → ответы на ATSP0 и ATAT1 в буфере → OBD-команды читают чужие ответы

Стало (init() новая):

_exec("ATSP0", timeout=10000)  # шлём, ЖДЁМ ответ, читаем
_exec("ATAT1", timeout=5000)
# → каждая команда ждёт свой ответ → буфер чист

Проблема 2: ATST отправлялся напрямую, ответ не читался

_process() вызывал _send_atst() которая писала ATST в порт и НЕ читала ответ. Следующая команда читала OK от ATST вместо своего ответа.

Исправление: _send_atst() теперь читает и отбрасывает ответ на ATST.

Проблема 3: _read() возвращал частичный ответ при таймауте

При таймауте _read() возвращал что успел прочитать — например, первую строку DTC. Вторая строка попадала в следующую команду.

Исправление: _read() теперь требует > перед возвратом. Без > — TimeoutError.

Проблема 4: таймаут 200мс мал для мока

Мок ждёт 300-500мс перед ответом на OBD-команды. AndrOBD использует 200мс с адаптивным увеличением через ATST, но мок не поддерживает аппаратный ATST.

Исправление: увеличен базовый таймаут до 500мс, 10 ретраев вместо 5.

Проблема 5: BUS ERROR recovery блокирует всё

При BUS ERROR стейт-машина отправляет ATPC + ATSP0 для восстановления. Мок отвечает на ATSP0 через 1.8с. _try_read() ждал только 1с. Ответ на ATSP0 оставался в буфере и попадал в следующую команду.

Исправление: _try_read использует таймаут 5с для recovery-команд.


Итоговая архитектура AndrOBD

Стейт-машина (AndrOBD ElmProt.java)

UNDEFINED → INITIALIZING → READY → BUSY → READY
                ↓ ERROR              ↓ BUS ERROR
             RECOVERING          DISCONNECTED

Классификация ответов (Rsp.identify)

Ответ Тип Реакция
> PROMPT Конец ответа (разделитель)
OK OK Успех, уменьшить таймаут
SEARCHING... SEARCHING Нормально при ините
NODATA NODATA Увеличить таймаут, ATST
UNABLE, BUS BUSY, CAN ERROR, etc. BUS ERROR DISCONNECTED, ATPC, ATSP0
ERROR ERROR WARM START (ATWS)
DATA ERROR, BUFFER FULL, RX ERROR DATA ERROR WARM START
Всё остальное DATA Успех, уменьшить таймаут

Чтение (StreamHandler.java)

  • Побайтовое, пауза 1мс
  • CR (13) = разделитель строк
  • > (62) = конец ответа
  • LF (10) и пробел (32) = игнорируются
  • Без > ответ не возвращается (TimeoutError)

Адаптивный таймаут (AdaptiveTiming.java)

  • Старт: 500мс (для мока; реальный ELM → 200мс)
  • Шаг: 20мс
  • Диапазон: 50-2000мс
  • ATST отправляется через _queue_atst() → ответ читается корректно

Результаты тестирования

Python-тест (tools/test_androbd.py) против Mock ELM327 v2:

Тест Результат
VIN (0902) → 490201...
DTC (03) → 430113... + 430133...
RPM (010C) → 410C1AF8
ОЖ (0105) → 41055A
Ответы не перемешаны 2/3 прогонов

1/3 прогонов упал из-за случайного BUS BUSY в моке (3%) — стейт-машина корректно восстановилась, но DTC-ответ был пустой (ожидаемое поведение).


Версии APK

Версия Что
v0.11.0-prod Старая, ответы перемешаны
v0.12.0-dev Стейт-машина, но OkHttp 30с → «сервер недоступен»
v0.13.0-dev Стейт-машина + OkHttp 120с

Что дальше (P0 → P3)

| P0 | ELM-протокол со стейт-машиной | сделано (Python + Kotlin) | | P0 | Тест на моке | 2/3 зелёные | | P0 | OkHttp timeout | 30→120с | | P1 | GPS-модуль | запланировано | | P1 | Трёхфазный флоу с жалобами | запланировано | | P2 | DTC-база на сервере | потом | | P2 | LLM cross-validation | потом | | P3 | Web-панель | потом |