docs: сессия 28 мая — AndrOBD стейт-машина, 5 багов, все исправления

This commit is contained in:
Repinoid
2026-05-28 10:09:26 +03:00
parent 41831468f4
commit d1903008c6
+142
View File
@@ -0,0 +1,142 @@
# Сессия 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()` старая):
```python
sendRaw("ATSP0"); sleep(200) # шлём, НЕ читаем ответ
sendRaw("ATAT1"); sleep(200) # шлём, НЕ читаем ответ
# → ответы на ATSP0 и ATAT1 в буфере → OBD-команды читают чужие ответы
```
Стало (`init()` новая):
```python
_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-панель | потом |