Files
shturman/docs/domains/e-vehicle-data.md
kk0t9 7a30ed7a7d docs(domain B): v2 после adversarial-ревью (22 находки) + кросс-док
Существенная переработка power-lifecycle:
- детект running по НАПРЯЖЕНИЮ бортсети (~14В генератор vs ~12.4В покой), не RPM (v2);
  Power.IgnitionState — единственный канон lifecycle-состояния
- триггер shutdown ≠ rate-of-change: ACC-off / under-voltage-held / thermal-trip;
  cold-crank до ~6В — НОРМА (ride-through), не индикатор обрыва
- SoC↔MCU shutdown-протокол специфицирован СЕЙЧАС: hold-up-таймер + heartbeat +
  safe-to-cut + fail-safe при потере линка (обе стороны); MCU — fail-safe-авторитет
- abort при re-power до PONR (ShutdownAborted); shutting-down разбит abortable/committed
- НОВОЕ: thermal shutdown (триггер/гистерезис/UX); ordered teardown (E закрывает ISO-TP);
  таблица MCU-vs-supercap; battery deep-discharge cutoff; монотонные часы для таймеров;
  первый boot без времени; периодическое сохранение времени
- watchdog по фазам (runtime + shutdown RebootWatchdogSec/MCU-дедлайн + boot-окно);
  v0=SoC+MCU+reboot, bootcount=v4
- фазы: MCU HW fail-safe-таймер = v0 (не v1); save-time = v0
- кросс-док: security-privacy (mic power-gated), ipc Power (enum/reason/ShutdownAborted),
  e/data-model (engine_running не дублирует IgnitionState), a-base §7 (периодич. save)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-21 01:53:57 +03:00

135 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Домен E — Vehicle-Data (OBD/CAN, read-only)
> Привилегированный core-сервис: **единственный владелец доступа к CAN/OBD**. Читает
> данные машины, публикует сигналы на шину, читает DTC. Сердце killer-фичи.
Статус: **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
---
## 1. Назначение и границы
- **Что делает:** читает OBD-II (PID/DTC) и/или broadcast-кадры (native CAN + DBC),
перемалывает в digested-сигналы ([data-model](../contracts/data-model.md)),
публикует через `ru.shturman.VehicleData` ([ipc](../contracts/ipc.md) §3).
- **Единственный, кто трогает CAN** → архитектурно держит red-line (принцип #2).
- **Границы (точный red-line):** только диагностические **read-запросы** + пассивное
чтение; **никаких** управляющих/actuator/write/Mode-04. Человеческую расшифровку
НЕ делает (это LLM/ассистент) — отдаёт код + стандартное описание.
## 2. Функции
| функция | MVP/later | зависит от | фаза |
|---------|-----------|------------|------|
| Live-сигналы (стандартные PID) | **MVP** | data-model, hardware(CAN) | v2 |
| **MIL-статус + DTC count** (PID 01) | **MVP** | — | v2 |
| Чтение DTC (Mode 03) + расшифровка по базе | **MVP** | dtc-база | v2 |
| Пробинг поддерживаемых PID | **MVP** | — | v2 |
| `engine_running` (running/stopped/unknown, из RPM) — НЕ дублирует `Power.IgnitionState` | **MVP** | — | v2 |
| Подписка с rate-cap (~1020 Гц) | **MVP** | ipc | v2 |
| Pending/permanent DTC (Mode 07/0A) | later | — | v2+ |
| Мгновенный расход (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 |
| Vendor DTC (`P1xxx`) через vendor-базу | later | vendor DB | later |
| Лог поездок | later | storage | later |
## 3. Данные и интерфейсы
- **Публикует:** `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). При насыщении (Σ подписок × Гц >
пропускной способности) — **бюджет req/s на транспорт** (ELM327 half-duplex, один запрос за
раз, несколько PID/с; нативный CAN выше) + приоритеты/веса PID, round-robin. Эффективная
частота PID = `min(desired_max_hz, потолок шины, доля бюджета)`; приоритетный набор
(`mil_on`+DTC) держит приоритет при насыщении. Управляет *получением*; доставку клиент прореживает сам.
- **DTC-база** (статическая, `vehicle/dtc/`) — живёт в этом домене.
## 4. Приоритизация под простые авто *(резолв routed-вопроса)*
- **MVP killer-фичи опирается на универсальное:** `mil_on` (PID 01) + DTC (Mode 03) —
поддержано почти везде, даже на простых Lada.
- Богатые PID — **best-effort** по результату пробинга.
- **ELM327 медленный** (несколько PID/сек) → на старте опрашиваем малый приоритетный
набор + DTC; native CAN быстрее.
## 5. DTC-расшифровка
- **Структура кода информативна сама по себе** (буква = подсистема, см. [data-model](../contracts/data-model.md) §6)
— даёт базовую категоризацию даже для незнакомого кода.
- **Статическая база:** не обязательно ВСЕ тысячи generic-кодов сразу — стартуем с
частых + алгоритмический разбор структуры, пополняем. RU-описания, `vehicle/dtc/`.
- **LLM (ассистент)** даёт человеческое объяснение (модели знают стандартные коды);
**офлайн-режиму нужна статическая база** — для надёжности и против галлюцинаций кода.
- 🟡 *Выбор:* своя **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.
- **На `ShutdownImminent` (от Power, домен B §4):** немедленно **гасим активный OBD-TX и закрываем
ISO-TP-сессии** (не оставить ECU в открытой диагностической сессии) — до снятия питания.
## 6. Зависимости
- **Вниз:** hardware (CAN-транспорт, listen-only/polling), data-model (каталог),
ipc (контракт сервиса), principles #2 (red-line), security-privacy (привилегированное
ядро, единственный владелец CAN).
- **Потребители:** Assistant (D) — контекст в промпт; Shell (C) — датчики/виджеты;
плагины — `vehicle_read`.
## 7. Открытые вопросы
- 🟡 **DTC-база:** своя RU из открытых списков (рек.) vs готовая.
- ◻️ **Точность производного расхода** (зависит от типа топлива) — см. [data-model](../contracts/data-model.md) §5.
- ◻️ **«Вырос расход»:** набор диагностических сигналов (fuel trim, O2) — later.
- ◻️ **Vendor DBC/коды** — порт под конкретное авто (HAL/BSP, [data-model](../contracts/data-model.md) §7).
- ◻️ **OBD-порт ≠ все шины.** Powertrain-шина на порту; кузов/комфорт/кнопки руля —
на других CAN-шинах, нужен тап конкретной шины. → [hardware.md](../contracts/hardware.md) + data-model §7.
- ◻️ **ELM327-клоны** капризны (баги прошивки, тайминги) — симулятор должен эмулировать их причуды. → [dev-environment.md](../dev-environment.md).
- ◻️ **Runtime-staleness:** таймаут ответа / двигатель заглушен → помечать сигнал `stale`/`unavailable`, не висеть.
---
## Журнал решений (домен E)
| Решение | Выбор | Дата |
|---------|-------|------|
| Транспорт | ELM327 (старт) → нативный SocketCAN; транспорт-агностичные сигналы | 2026-06-16 |
| 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 |