# Запрос к Claude Sonnet — поиск багов в ELM-коде ## Контекст Android-приложение для OBD2-диагностики через ELM327 Bluetooth. Стек: Kotlin, minSdk 24. **Проблема:** динамический тест (опрос 3 PID в цикле) — ELM327 v1.5 перестаёт отвечать. ### Данные тестов (реальные сессии из БД) **v1.3.0-dev (#54):** статика работает, ATWS + 300ms перед динамикой ``` 0106 (STFT): 1 ok / 18 попыток 010C (RPM): 1 ok / 18 попыток 0110 (MAF): 0 ok / 18 попыток Первые 2 ответа — данные, затем 16 пустых. ``` **v1.9.0-dev (#56):** без ATWS, без drain, без sleep(350) ``` 0106 (STFT): 0 ok / 15 попыток ← СТАЛО ХУЖЕ 010C (RPM): 0 ok / 15 попыток 0110 (MAF): 0 ok / 15 попыток ВСЕ 15 ответов пустые. ELM вообще не отвечает. ``` ### Что изменилось в v1.9.0 1. Убрали `ATWS` перед динамикой (заменили на `ATE0`/`ATL0`/`ATS0`) 2. Убрали `Thread.sleep(350)` между командами внутри батча 3. Добавили `setDrainBeforeWrite(false)` — drainInput() не вызывается в write() 4. Вызвали `drainInput()` один раз перед стартом DynamicCollector ### Статика работает идеально (сессия #55, v1.9.0-dev) Все 9 PID (0104-0111) — ok. Проблема ТОЛЬКО в DynamicCollector. ## Код Файлы лежат в `android/app/src/main/java/ru/elmer/client/`: ### ElmProtocol.kt (elm/ElmProtocol.kt) — ПОЛНОСТЬЮ ВАЖЕН Стейт-машина AndrOBD. Методы: `sendCommand()` → `exec()` → `write()` → `read()`. Ключевое: `write()` вызывает `drainInput()` перед каждой командой. `exec()` делает до 10 retry при таймауте (каждый retry = новый write()). ### DynamicCollector.kt (script/DynamicCollector.kt) — ПОЛНОСТЬЮ ВАЖЕН Цикл опроса: `while(running) { for(step in steps) { elm.sendCommand(step.cmd) } sleep(interval) }` Сейчас без sleep между командами внутри батча. ### MainActivity.kt (ui/MainActivity.kt) — строки 344-470 Метод `startDynamicRecording()`. Поток выполнения: 1. `checker.ensureConnected()` — переподключение если нужно 2. Статический проброс 9 PID (каждый через sendCommand) 3. ATE0/ATL0/ATS0 — переинициализация 4. `elmProto.drainInput()` — однократная очистка 5. `elmProto.setDrainBeforeWrite(false)` — отключаем drain 6. `DynamicCollector.start()` — цикл опроса 7. После stop: `elmProto.setDrainBeforeWrite(true)` ## Вопросы 1. **Почему v1.9.0 стал ХУЖЕ чем v1.3.0?** В v1.3.0 было ATWS+300ms и ELM отвечал хотя бы на первые 2 команды. В v1.9.0 — ни одного ответа. 2. **Нужен ли ATWS перед динамикой?** Если да — сколько ждать после него? 3. **Нужен ли drainInput() в write()?** Или достаточно одного drain'а перед стартом? Не съедает ли drainInput() ответы от медленного ELM? 4. **Почему статика работает а динамика нет?** Разница: статика = одиночные sendCommand с паузами между шагами. Динамика = 3 sendCommand подряд в цикле. 5. **Правильно ли `exec()` делает retry с повторной отправкой команды?** Не забивает ли это ELM327? Выдай СВОЙ анализ и КОНКРЕТНЫЕ исправления в файл `doc/claude-analysis-elm-v2.md`. Не пиши общие рекомендации — дай точные правки кода.