436 lines
12 KiB
Markdown
436 lines
12 KiB
Markdown
# OBD2 Client
|
||
|
||
Python приложение для мониторинга OBD2 данных Skoda Kodiaq 2021 на Raspberry Pi 5.
|
||
|
||
## Возможности
|
||
|
||
- **OBD2 Protocol** — чтение стандартных PID (Mode 01)
|
||
- **Offline-first Storage** — SQLite с автосинхронизацией в PostgreSQL
|
||
- **Handler Pipeline** — модульная обработка данных
|
||
- **Flipper Zero UI** — отображение на портативном дисплее
|
||
- **UPS Monitoring** — мониторинг X120x UPS HAT
|
||
- **Systemd Services** — автозапуск при загрузке
|
||
|
||
## Установка
|
||
|
||
```bash
|
||
# Основные зависимости
|
||
pip install -r requirements.txt
|
||
|
||
# Для PostgreSQL (опционально)
|
||
pip install psycopg2-binary
|
||
|
||
# Для UPS мониторинга (опционально, только RPi)
|
||
pip install smbus2 gpiozero
|
||
```
|
||
|
||
## Конфигурация RPi5
|
||
|
||
### /boot/firmware/config.txt
|
||
|
||
```ini
|
||
# CAN HAT (MCP2515)
|
||
dtparam=spi=on
|
||
dtoverlay=mcp2515-can0,oscillator=16000000,interrupt=25
|
||
|
||
# UART для Flipper Zero
|
||
enable_uart=1
|
||
dtoverlay=disable-bt
|
||
```
|
||
|
||
### Инициализация CAN
|
||
|
||
```bash
|
||
sudo ip link set can0 type can bitrate 500000
|
||
sudo ip link set can0 up
|
||
```
|
||
|
||
## Использование
|
||
|
||
### Базовый запуск
|
||
|
||
```bash
|
||
python -m src.main --interface can0
|
||
```
|
||
|
||
### С Flipper Zero
|
||
|
||
```bash
|
||
python -m src.main --interface can0 --flipper /dev/serial0
|
||
```
|
||
|
||
### Только сканирование PID
|
||
|
||
```bash
|
||
python -m src.main --interface can0 --scan-only
|
||
```
|
||
|
||
### Тестовый режим (виртуальный CAN)
|
||
|
||
```bash
|
||
sudo modprobe vcan
|
||
sudo ip link add dev vcan0 type vcan
|
||
sudo ip link set up vcan0
|
||
|
||
python -m src.main --interface vcan0 --virtual
|
||
```
|
||
|
||
### Параметры CLI
|
||
|
||
| Параметр | Описание |
|
||
|----------|----------|
|
||
| `-i, --interface` | CAN интерфейс (can0, vcan0) |
|
||
| `-c, --config` | Путь к config.json |
|
||
| `-v, --virtual` | Виртуальный CAN режим |
|
||
| `--scan-only` | Только сканирование PID |
|
||
| `--flipper PORT` | Включить Flipper Zero сервер |
|
||
| `--no-monitor` | Отключить консольный вывод |
|
||
| `--debug` | Отладочный режим |
|
||
|
||
## Конфигурация
|
||
|
||
### config.json
|
||
|
||
```json
|
||
{
|
||
"can": {
|
||
"interface": "can0",
|
||
"bitrate": 500000,
|
||
"virtual": false
|
||
},
|
||
"obd2": {
|
||
"request_id": "0x7DF",
|
||
"response_id": "0x7E8",
|
||
"timeout": 0.2
|
||
},
|
||
"polling": {
|
||
"interval_fast": 0.1,
|
||
"interval_slow": 1.0,
|
||
"fast_pids": ["0x0C", "0x0D", "0x11", "0x04"],
|
||
"slow_pids": ["0x05", "0x5C", "0x0F", "0x2F"]
|
||
},
|
||
"storage": {
|
||
"enabled": true,
|
||
"db_path": null,
|
||
"wal_mode": true,
|
||
"retention_days": 30,
|
||
"batch_size": 50,
|
||
"flush_interval": 1.0
|
||
},
|
||
"postgresql": {
|
||
"enabled": false,
|
||
"host": "localhost",
|
||
"port": 5432,
|
||
"database": "carpibord",
|
||
"user": "carpibord",
|
||
"password": "",
|
||
"sync_interval": 30.0,
|
||
"batch_size": 500
|
||
},
|
||
"flipper": {
|
||
"enabled": true,
|
||
"port": "/dev/serial0",
|
||
"baudrate": 115200,
|
||
"show_ups": true
|
||
}
|
||
}
|
||
```
|
||
|
||
### Переменные окружения
|
||
|
||
```bash
|
||
# CAN
|
||
export OBD2_CAN_INTERFACE=can0
|
||
export OBD2_CAN_BITRATE=500000
|
||
|
||
# Storage
|
||
export OBD2_STORAGE_ENABLED=true
|
||
export OBD2_STORAGE_PATH=/data/obd2.db
|
||
|
||
# PostgreSQL
|
||
export OBD2_PG_ENABLED=true
|
||
export OBD2_PG_HOST=postgres.example.com
|
||
export OBD2_PG_DATABASE=carpibord
|
||
export OBD2_PG_USER=carpibord
|
||
export OBD2_PG_PASSWORD=secret
|
||
|
||
# Flipper
|
||
export OBD2_FLIPPER_ENABLED=true
|
||
export OBD2_FLIPPER_PORT=/dev/serial0
|
||
```
|
||
|
||
## Архитектура
|
||
|
||
### Handler Pipeline (Offline-First)
|
||
|
||
```
|
||
VehiclePoller ──► HandlerPipeline
|
||
│
|
||
├── StorageHandler ──► SQLite (obd2_data.db)
|
||
│ │ │
|
||
│ │ [unsynced data]
|
||
│ │ │
|
||
│ └─────── background sync ───────┐
|
||
│ │
|
||
└── PostgreSQLHandler ◄──────────────────┘
|
||
│
|
||
▼
|
||
PostgreSQL (remote)
|
||
```
|
||
|
||
**Принцип работы:**
|
||
1. `VehiclePoller` опрашивает PID и вызывает callbacks
|
||
2. `StorageHandler` батчит данные и пишет в SQLite
|
||
3. `PostgreSQLHandler` в фоне синхронизирует unsynced записи в PostgreSQL
|
||
4. При потере связи данные накапливаются локально
|
||
5. При восстановлении — автоматическая досинхронизация
|
||
|
||
### Структура проекта
|
||
|
||
```
|
||
obd2_client/
|
||
├── src/
|
||
│ ├── main.py # Точка входа, CLI
|
||
│ ├── config.py # Конфигурация
|
||
│ ├── logger.py # Логирование
|
||
│ │
|
||
│ ├── can/ # CAN абстракция
|
||
│ │ ├── frame.py # CANFrame dataclass
|
||
│ │ └── interface.py # CANInterface
|
||
│ │
|
||
│ ├── obd2/ # OBD2 протокол
|
||
│ │ ├── pids.py # Определения PID, декодеры
|
||
│ │ ├── protocol.py # Request/Response
|
||
│ │ └── scanner.py # Автодетект PID
|
||
│ │
|
||
│ ├── vehicle/ # Состояние автомобиля
|
||
│ │ ├── state.py # VehicleState (thread-safe)
|
||
│ │ └── poller.py # VehiclePoller (fast/slow)
|
||
│ │
|
||
│ ├── handlers/ # Data Pipeline
|
||
│ │ ├── base.py # BaseHandler, OBD2Reading
|
||
│ │ ├── pipeline.py # HandlerPipeline
|
||
│ │ ├── storage_handler.py # SQLite handler
|
||
│ │ └── postgresql_handler.py # PostgreSQL sync
|
||
│ │
|
||
│ ├── storage/ # Persistence
|
||
│ │ └── storage.py # SQLite + sessions
|
||
│ │
|
||
│ └── flipper/ # Flipper Zero интеграция
|
||
│ ├── protocol.py # UART протокол
|
||
│ ├── server.py # FlipperServer
|
||
│ ├── pages.py # PageManager, страницы
|
||
│ └── providers/ # Data providers
|
||
│ ├── base.py # BaseProvider
|
||
│ └── ups_provider.py # X120x UPS
|
||
│
|
||
├── config.json
|
||
├── config.json.example
|
||
├── requirements.txt
|
||
└── README.md
|
||
```
|
||
|
||
## Поддерживаемые PID
|
||
|
||
### OBD2 Standard (Mode 0x01)
|
||
|
||
| PID | Параметр | Единицы | Интервал |
|
||
|-----|----------|---------|----------|
|
||
| 0x04 | Engine Load | % | Fast |
|
||
| 0x05 | Coolant Temp | °C | Slow |
|
||
| 0x0C | Engine RPM | RPM | Fast |
|
||
| 0x0D | Vehicle Speed | km/h | Fast |
|
||
| 0x0F | Intake Air Temp | °C | Slow |
|
||
| 0x10 | MAF Rate | g/s | Slow |
|
||
| 0x11 | Throttle Position | % | Fast |
|
||
| 0x2F | Fuel Level | % | Slow |
|
||
| 0x5C | Oil Temperature | °C | Slow |
|
||
|
||
### UDS Extended (Mode 0x22) — MQB Platform
|
||
|
||
UDS (ISO 14229) позволяет читать расширенные данные напрямую из ECU.
|
||
**Это read-only протокол, не влияющий на работу автомобиля.**
|
||
|
||
#### Engine ECU (0x7E0 → 0x7E8)
|
||
|
||
| PID | Параметр | Единицы | Min | Max |
|
||
|-----|----------|---------|-----|-----|
|
||
| 0x202A | Boost Pressure Actual | kPa | 0 | 400 |
|
||
| 0x2029 | Boost Pressure Target | kPa | 0 | 400 |
|
||
| 0xF423 | Fuel Rail Pressure | kPa | 0 | 25000 |
|
||
| 0x10C0 | Lambda Actual | λ | 0.5 | 2.0 |
|
||
| 0x1456 | Lambda Target | λ | 0.5 | 2.0 |
|
||
| 0x437C | Torque Actual | Nm | 0 | 500 |
|
||
| 0x39A2 | Wastegate Position | % | 0 | 100 |
|
||
| 0x39A3 | Wastegate Target | % | 0 | 100 |
|
||
| 0x2004 | Ignition Timing | ° | -10 | 50 |
|
||
| 0x200A | Timing Correction Cyl 1 | ° | -15 | 5 |
|
||
| 0x200B | Timing Correction Cyl 2 | ° | -15 | 5 |
|
||
| 0x200C | Timing Correction Cyl 3 | ° | -15 | 5 |
|
||
| 0x200D | Timing Correction Cyl 4 | ° | -15 | 5 |
|
||
|
||
#### Instrument Cluster (0x714 → 0x77E)
|
||
|
||
| PID | Параметр | Единицы | Min | Max |
|
||
|-----|----------|---------|-----|-----|
|
||
| 0x22D1 | RPM (from cluster) | RPM | 0 | 8000 |
|
||
| 0x224D | Ambient Light Sensor | - | 0 | 255 |
|
||
|
||
#### DSG Transmission (0x7E1 → 0x7E9)
|
||
|
||
| PID | Параметр | Единицы | Min | Max |
|
||
|-----|----------|---------|-----|-----|
|
||
| 0x3816 | Current Gear | gear | -1 | 7 |
|
||
| 0x3815 | Gear Selector (PRNDM) | mode | 0 | 5 |
|
||
| 0x1940 | Transmission Temp | °C | -40 | 150 |
|
||
|
||
## UDS конфигурация
|
||
|
||
```json
|
||
"uds": {
|
||
"enabled": true,
|
||
"interval_fast": 0.2,
|
||
"interval_slow": 1.0,
|
||
"fast_pids": ["0x202A", "0x437C", "0x10C0", "0x2004"],
|
||
"slow_pids": ["0x39A2", "0x200A", "0x3816", "0x3815"]
|
||
}
|
||
```
|
||
|
||
### Flipper Zero — страница UDS Data
|
||
|
||
```
|
||
┌──────────────────────┐
|
||
│ UDS Data │
|
||
├──────────────────────┤
|
||
│ Boost: 185 kPa │
|
||
│ Torque: 280 Nm │
|
||
│ Lambda: 1.000 │
|
||
│ Timing: 12.5 deg │
|
||
│ Wastegate: 45% │
|
||
│ Gear: 4 │
|
||
└──────────────────────┘
|
||
```
|
||
|
||
## Flipper Zero интеграция
|
||
|
||
### Подключение
|
||
|
||
```
|
||
RPi5 GPIO Flipper Zero
|
||
───────── ────────────
|
||
GPIO14 (TX) ────── Pin 14 (RX)
|
||
GPIO15 (RX) ────── Pin 13 (TX)
|
||
GND ────── Pin 18 (GND)
|
||
```
|
||
|
||
### Страницы
|
||
|
||
| # | Страница | Тип | Описание |
|
||
|---|----------|-----|----------|
|
||
| 0 | Live Data | Info | RPM, Speed, Temps, Throttle, Fuel |
|
||
| 1 | Statistics | Info | Queries, Success rate, Uptime |
|
||
| 2 | System Info | Info | IP, CPU, Memory, CAN interface |
|
||
| 3 | App Status | Info | Pipeline, Storage, PostgreSQL sync |
|
||
| 4 | UPS Status | Info | Battery %, Voltage, Power status |
|
||
| 5 | Actions | Menu | Reconnect, Clear cache, Reboot, Shutdown |
|
||
|
||
### Управление
|
||
|
||
| Кнопка | Действие |
|
||
|--------|----------|
|
||
| ← / → | Переключение страниц |
|
||
| ↑ / ↓ | Прокрутка / выбор пункта меню |
|
||
| OK | Подтверждение |
|
||
| Back | Отмена |
|
||
|
||
## Systemd сервисы
|
||
|
||
### Установка
|
||
|
||
```bash
|
||
cd ../systemd
|
||
sudo ./install.sh
|
||
```
|
||
|
||
### Управление
|
||
|
||
```bash
|
||
# Запуск
|
||
sudo systemctl start carpibord
|
||
|
||
# Статус
|
||
sudo systemctl status carpibord
|
||
|
||
# Логи
|
||
journalctl -u carpibord -f
|
||
|
||
# Остановка
|
||
sudo systemctl stop carpibord
|
||
```
|
||
|
||
### Сервисы
|
||
|
||
| Сервис | Описание |
|
||
|--------|----------|
|
||
| `can0-link.service` | Поднимает CAN интерфейс на 500 kbps |
|
||
| `carpibord.service` | Запускает OBD2 Client после CAN и сети |
|
||
|
||
## PostgreSQL Setup
|
||
|
||
### Создание базы
|
||
|
||
```sql
|
||
CREATE DATABASE carpibord;
|
||
CREATE USER carpibord WITH PASSWORD 'your-password';
|
||
GRANT ALL PRIVILEGES ON DATABASE carpibord TO carpibord;
|
||
```
|
||
|
||
### Таблицы (создаются автоматически)
|
||
|
||
```sql
|
||
-- Readings
|
||
CREATE TABLE obd2_readings (
|
||
id SERIAL PRIMARY KEY,
|
||
device_id TEXT DEFAULT 'rpi5',
|
||
session_id TEXT,
|
||
pid INTEGER NOT NULL,
|
||
name TEXT NOT NULL,
|
||
value REAL NOT NULL,
|
||
unit TEXT NOT NULL,
|
||
timestamp TIMESTAMPTZ NOT NULL
|
||
);
|
||
|
||
-- Sessions
|
||
CREATE TABLE obd2_sessions (
|
||
id TEXT PRIMARY KEY,
|
||
device_id TEXT DEFAULT 'rpi5',
|
||
start_time TIMESTAMPTZ NOT NULL,
|
||
end_time TIMESTAMPTZ,
|
||
duration_seconds REAL,
|
||
reading_count INTEGER,
|
||
avg_speed REAL,
|
||
max_speed REAL,
|
||
avg_rpm REAL,
|
||
max_rpm REAL
|
||
);
|
||
```
|
||
|
||
## UPS мониторинг (X120x)
|
||
|
||
Поддерживаются UPS HAT на базе MAX17048 fuel gauge:
|
||
- X1201, X1202 и совместимые
|
||
- Подключение по I2C (адрес 0x36)
|
||
- GPIO 6 для детекции потери питания
|
||
|
||
### Отображаемые данные
|
||
|
||
- Battery % с визуализацией `[==== ]`
|
||
- Напряжение батареи (V)
|
||
- Статус: Charging / Full / Battery Mode
|
||
- Input voltage (V)
|
||
- Предупреждения при низком заряде
|
||
|
||
## Лицензия
|
||
|
||
MIT
|