From 08d787d977c71511a0a96a0f0e89cc9170a6cc6d Mon Sep 17 00:00:00 2001 From: Alexander Date: Sun, 21 Jun 2026 01:27:25 +0300 Subject: [PATCH] =?UTF-8?q?docs(domain=20E):=20v2=20=E2=80=94=20=D1=80?= =?UTF-8?q?=D0=B5=D1=82=D1=80=D0=BE-=D1=80=D0=B5=D0=B2=D1=8C=D1=8E=20pass-?= =?UTF-8?q?2=20(5=20=D0=BD=D0=B0=D1=85=D0=BE=D0=B4=D0=BE=D0=BA)=20+=20tech?= =?UTF-8?q?-stack=20ISO-TP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ISO-TP (ISO 15765-2): нативный CAN-OBD требует can-isotp/CAN_ISOTP для multiframe (Mode 03 DTC, Mode 09 VIN), не голый socketcan; адресация 0x7DF/0x7E8..0x7EF - планировщик опроса: бюджет req/s на транспорт (ELM327 half-duplex) + приоритеты PID, round-robin при насыщении; эффективная частота = min(desired, потолок, доля бюджета) - §5a безопасность активного опроса: гейт по движению, предпочтение passive listen-only, fail-safe при аномалиях шины, риск ретрофита; «безобидность» read-запросов условна - §5b отказ/восстановление транспорта: bus-off + restart-ms, ELM327 reconnect, Online=false → unavailable, без зависания (#4) - владение computed: core (состояние/мгновенный расход) vs плагин (trip-производные) - tech-stack: CAN/OBD row + ISO-TP Co-Authored-By: Claude Opus 4.8 (1M context) --- docs/domains/e-vehicle-data.md | 43 ++++++++++++++++++++++++++++++---- docs/tech-stack.md | 2 +- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/docs/domains/e-vehicle-data.md b/docs/domains/e-vehicle-data.md index c0f93d5..da99d49 100644 --- a/docs/domains/e-vehicle-data.md +++ b/docs/domains/e-vehicle-data.md @@ -3,8 +3,8 @@ > Привилегированный core-сервис: **единственный владелец доступа к CAN/OBD**. Читает > данные машины, публикует сигналы на шину, читает DTC. Сердце killer-фичи. -Статус: **v1 (на ревью).** -Связано с: [ipc.md](../contracts/ipc.md) (`VehicleData`) · [data-model.md](../contracts/data-model.md) · [hardware.md](../contracts/hardware.md) (CAN) · [security-privacy.md](../contracts/security-privacy.md) · [principles.md](../principles.md) (#2) · домен D (Assistant) +Статус: **v2 (на ревью).** v2 — после ретро-ревью (5 находок). +Связано с: [ipc.md](../contracts/ipc.md) (`VehicleData`) · [data-model.md](../contracts/data-model.md) · [hardware.md](../contracts/hardware.md) (CAN) · [security-privacy.md](../contracts/security-privacy.md) · [principles.md](../principles.md) (#1,#2,#4) · [plugin-sdk.md](../contracts/plugin-sdk.md) (trip — у плагина) · домен D --- @@ -29,7 +29,8 @@ | Состояние машины (`off`/`acc`/`running`) | **MVP** | — | v2 | | Подписка с rate-cap (~10–20 Гц) | **MVP** | ipc | v2 | | Pending/permanent DTC (Mode 07/0A) | later | — | v2+ | -| Производные (расход / trip) | later | trip-стейт, storage | v2/v3 | +| Мгновенный расход (computed, **core**) | later | fuel_rate/MAF | v2/v3 | +| Trip-производные (пробег/средний) | — | **у плагина** (свой trip-стейт, plugin-sdk §8) | — | | Топливные коррекции (fuel trim 06–09) — «вырос расход» | later | — | later | | VIN (Mode 09) | later | — | later | | Пассивный сниффинг broadcast (DBC) | later | native CAN, DBC | later | @@ -41,12 +42,22 @@ - **Публикует:** `ru.shturman.VehicleData` (методы/сигналы/properties — [ipc](../contracts/ipc.md) §3). - **Сигналы** — по каталогу [data-model](../contracts/data-model.md); транспорт-агностичны. - **Источник:** ELM327 (serial/BT) и нативный **SocketCAN** (крейт `socketcan`). +- **ISO-TP для нативного CAN-OBD (важно):** CAN-based OBD (ISO 15765-4) требует транспорт + **ISO-TP (ISO 15765-2)** — сегментация/сборка/flow-control multiframe-ответов (Mode 03 — много + DTC, Mode 09 — VIN): ядровой `can-isotp` (сокеты `CAN_ISOTP`), **не голый `socketcan`**. + Адресация: функц. запрос `0x7DF`, ответы ECU `0x7E8..0x7EF` (несколько ECU — собираем/дедупим + по source-ID). Голый `socketcan` — для пассивного сниффинга (DBC); OBD-поллинг — через ISO-TP. + ELM327 прячет ISO-TP в прошивке (касается только нативного пути). - **Покрытие протоколов (важно для старых авто):** OBD-II ходит поверх разных нижних протоколов. **Native SocketCAN — только CAN-based OBD** (авто ~2008+). Старые не-CAN (K-line ISO 9141/KWP2000, J1850) — через **ELM327** (мульти-протокольный). Поэтому ELM327-путь держим живым, не только «на старте» — это охват простых Lada/ретрофита. -- **Опрос коалесцируется:** один PID опрашивается раз на максимальной запрошенной - частоте, результат раздаётся всем подписчикам (не per-subscriber). +- **Опрос: коалесцирование + планировщик/бюджет.** Один PID опрашивается раз на макс. + запрошенной частоте, раздаётся всем (не per-subscriber). При насыщении (Σ подписок × Гц > + пропускной способности) — **бюджет req/s на транспорт** (ELM327 half-duplex, один запрос за + раз, несколько PID/с; нативный CAN выше) + приоритеты/веса PID, round-robin. Эффективная + частота PID = `min(desired_max_hz, потолок шины, доля бюджета)`; приоритетный набор + (`mil_on`+DTC) держит приоритет при насыщении. Управляет *получением*; доставку клиент прореживает сам. - **DTC-база** (статическая, `vehicle/dtc/`) — живёт в этом домене. ## 4. Приоритизация под простые авто *(резолв routed-вопроса)* @@ -68,6 +79,25 @@ - 🟡 *Выбор:* своя **RU-база из открытых списков** generic-кодов (рек.) vs готовая. Vendor-коды (`P1xxx`) — later, через vendor-базы. +## 5a. Безопасность активного опроса + +Потолок ~10–20 Гц (ipc) — *пропускная*, не safety-граница. На живой powertrain-шине: +- **Гейт по движению:** в движении снижаем интенсивность TX и набор PID (используем speed, + уже заведённый для distraction) — бюджет нагрузки на шину. +- **Предпочитаем пассивный listen-only** (broadcast/DBC), где сигнал доступен так, а не активный опрос. +- **Fail-safe:** при аномалиях шины / конфликтах диагностической сессии — backoff/стоп активного опроса. +- **Риск ретрофита на незнакомом авто** (капризные шлюзы/ECU, коллизии сессий) — Lada/энтузиаст целевые. +- Уточняет принцип #2: «безобидность» read-запросов **условна** — на ограниченный, motion-aware, fail-safe TX. + +## 5b. Отказ и восстановление транспорта + +- **Нативный SocketCAN:** детект error-passive / **bus-off**; авто-восстановление (re-init, + `restart-ms`), чтобы один сбой не глушил сервис навсегда; rate-limit попыток + лог error-storm (как домен A). +- **ELM327 (USB/BT):** детект потери линка; reconnect с backoff; re-probe при реконнекте (причуды клонов — §7). +- **ISO-TP/multiframe таймауты** — отдельно от single-frame `GetSignal`-таймаута. +- **При падении транспорта:** `Online=false` (ipc), затронутые сигналы → `unavailable` (не `stale`), + без зависания/краха (#4); при восстановлении — re-probe. + ## 6. Зависимости - **Вниз:** hardware (CAN-транспорт, listen-only/polling), data-model (каталог), @@ -97,3 +127,6 @@ | MVP-ядро | `mil_on` (PID 01) + DTC (Mode 03) — универсально; богатые PID best-effort | 2026-06-16 | | DTC-база | своя RU из открытых generic-списков (🟡); vendor-коды later | 2026-06-16 | | Расшифровка | статическая база (код→описание) + LLM (человеческое объяснение) | 2026-06-16 | +| Транспорт нативного OBD | ISO-TP (`can-isotp`), не голый socketcan; адресация 0x7DF/0x7E8+ | 2026-06-16 | +| Опрос | бюджет req/s на транспорт + приоритеты; гейт по движению; fail-safe/recovery (bus-off) | 2026-06-16 | +| Computed | core: состояние/мгновенный расход; trip-производные — у плагина | 2026-06-16 | diff --git a/docs/tech-stack.md b/docs/tech-stack.md index b3dda6f..5637a8c 100644 --- a/docs/tech-stack.md +++ b/docs/tech-stack.md @@ -42,7 +42,7 @@ | **Песочница** | **bubblewrap** + systemd-hardening | апы/плагины; WASM-тир — позже | | **OS base** | Armbian/Debian (RK3588), ядро ближе к mainline | read-only rootfs + overlay | | **Init / lifecycle** | **systemd** | ядро; апы/плагины — App-Host | -| **CAN/OBD (read-only)** | **SocketCAN** (крейт `socketcan`) | ELM327 на старте; `python-OBD` — только в симуляторе | +| **CAN/OBD (read-only)** | **SocketCAN** (`socketcan`) + **ISO-TP** (`can-isotp`/`CAN_ISOTP`) для нативного OBD | ELM327 (мульти-протокол, прячет ISO-TP) на старте; `python-OBD` — в симуляторе | | **Wake-word** | **openWakeWord** | RU-фраза «Штурман»; Porcupine отвергнут (проприетарный, #12) | | **VAD** | Silero VAD | через ONNX Runtime | | **STT** | Vosk · Silero | офлайн, RU; через биндинги / `ort` |