📊 Companion server: IDMate — the dashboard & trip log that consumes the telemetry and lets you analyse trips, charges and battery health.
Open telemetry for the VW ID family — an ESP32-based stick that turns the OBD2 port into a live data feed for SoC, battery temperature, power flow, charging behavior and location.
Born out of frustration: the VW ID.7 shows you almost nothing about what's happening under the hood. No real SoC, no battery temperature, no power draw, no charge curve — not even a simple energy consumption history. Even a base-model VW Hybrid puts more data on the dashboard than an ID.7 does. This project is a DIY box that plugs into OBD2 and turns a black-box EV into something you can actually understand — your data, your broker, your dashboard.
- Reads battery, drivetrain and climate data from the CAN bus (UDS/ISO-TP)
- Pushes telemetry to InfluxDB over LTE-M for Grafana dashboards
- Tracks location via Traccar (OsmAnd protocol)
- Emulates a BLE ELM327 so ABRP sees the car natively
- Runs a WiFi AP with a full Web-UI for live data, config and debugging
- Sleeps in the low-µA range when parked, wakes on motion
The stick reads CAN data via UDS, pushes encrypted telemetry over LTE-M MQTT, exposes a BLE ELM327 emulation for ABRP, and serves a local Web-UI on its WiFi AP. Sources are in docs/ (*.puml, render with plantuml).
When MQTT or GPRS misbehave, the firmware escalates through four levels before giving up — built to survive long radio dead zones without endless reboot loops.
| Component | Details |
|---|---|
| MCU | LILYGO T-SIM7080G-S3 (ESP32-S3, 16 MB Flash, 8 MB PSRAM) |
| CAN Transceiver | SN65HVD230 (3.3 V, active mode) |
| Modem | SIM7080G (LTE-M / NB-IoT), onboard |
| GPS + Compass | BLITZ Mini M10 (u-blox M10 multi-GNSS + QMC5883L compass) — external via UART |
| GPS (fallback) | SIM7080G integrated GNSS (used when external GPS is disabled) |
| PMU | AXP2101 (onboard, manages DC rails for modem, GPS, peripherals) |
| RTC | DS1307 + CR2032 (keeps time across power cycles) |
| IMU | MPU-6050 (accelerometer + gyroscope, motion wake-up) |
The firmware supports two GPS configurations controlled by GPS_EXT_ENABLED in config.h:
External GPS (default, recommended): The BLITZ Mini M10 runs continuously on UART2 (GPIO1/GPIO2) and maintains a fix independently of the modem. LTE stays connected via MQTT at all times — no GPS/LTE cycling needed. The M10 draws ~5–8 mA in idle and keeps tracking even during sleep transitions. Power is supplied via the PMU DC5 rail (3.3 V).
Internal GPS (fallback):
When GPS_EXT_ENABLED is set to false, the SIM7080G's built-in GNSS is used instead. Because the SIM7080G shares a single radio frontend, GPS and LTE data cannot run simultaneously. The device cycles between modes every 60 seconds:
GPS active (55 s) → GPS off → LTE on → send data → LTE off → GPS on
The external GPS eliminates this limitation entirely.
The device opens a WiFi Access Point:
- SSID:
IDTelemetry - Password:
IDTelemetry1 - URL:
http://192.168.4.1
Three pages: Data (live telemetry table), Debug (gyro graph, compass, CAN tools, logs) and Config (WiFi, SIM/APN, MQTT, OTA firmware update).
| Part | Description | approx. Price |
|---|---|---|
| LILYGO T-SIM7080G-S3 | ESP32-S3 board with LTE-M/NB-IoT modem | ~35 € |
| SN65HVD230 CAN Transceiver | 3.3 V CAN bus module | ~3 € |
| OBD2 plug with cable | 16-pin OBD2 connector (pin 6 + 14 for CAN) | ~5 € |
| BLITZ Mini M10 | u-blox M10 GNSS + QMC5883L compass (UART) | ~40 € |
| DS1307 RTC module | Real-time clock (I2C) with coin cell | ~2 € |
| MPU-6050 breakout | Accelerometer / gyroscope (I2C) | ~3 € |
| LTE-M SIM card | e.g. ThingsMobile (prepaid, no contract) | ~15 € |
| USB-C cable | For flashing and power | — |
- Install VSCode
- Install the PlatformIO IDE extension in VSCode
- Clone this repo or download it as a ZIP
cp src/secrets.h.example src/secrets.hOpen src/secrets.h and fill in:
- APN of your mobile carrier (e.g.
TMfor ThingsMobile) - Traccar host + device ID (if you want GPS tracking)
- InfluxDB host, org, bucket, token (if you want telemetry dashboards)
- Guard SSID of the car's hotspot (e.g.
"My VW 1747")
⚠️ Generating tokens, keys and secretsUse a cryptographically secure random number generator. Never ask an LLM (ChatGPT, Claude, Copilot, …) to "give me a random 32-byte key" — LLM output is probability-distributed, not random. The same prompt produces a small, predictable distribution of values that an attacker can enumerate offline. The convenience is not worth the silent loss of entropy.
openssl rand -hex 32 # AES-256 key openssl rand -base64 32 # API/webhook tokens python3 -c "import secrets; print(secrets.token_hex(32))"The MQTT AES key in
secrets.hmust match theMQTT_AES_KEYconfigured on the IDMate server side.
LILYGO T-SIM7080G-S3 External Modules
┌──────────────────┐
│ │ ┌─── CAN Bus (OBD2) ───┐
│ GPIO17 (CAN TX) ─┼──→ SN65HVD230 CTX ──→ OBD2 Pin 6 (CAN-H)
│ GPIO18 (CAN RX) ─┼──→ SN65HVD230 CRX ──→ OBD2 Pin 14 (CAN-L)
│ │
│ │ ┌─── I2C Bus (shared) ──┐
│ GPIO45 (SDA) ────┼──→ DS1307 + MPU-6050 + QMC5883L (SDA)
│ GPIO21 (SCL) ────┼──→ DS1307 + MPU-6050 + QMC5883L (SCL)
│ │
│ GPIO3 (INT) ────┼──← MPU-6050 INT (deep sleep wake-up)
│ │
│ │ ┌─── External GPS ──────┐
│ GPIO1 (RX) ─────┼──← BLITZ M10 TX (UART2, 115200 baud)
│ GPIO2 (TX) ─────┼──→ BLITZ M10 RX
│ │
│ 3V3 ─────────────┼──→ VCC for CAN transceiver + RTC
│ GND ─────────────┼──→ GND for all modules
└──────────────────┘
Onboard (no wiring needed):
GPIO5/4 → SIM7080G UART (modem, UART1)
GPIO41 → SIM7080G PWRKEY
GPIO42 → SIM7080G DTR
GPIO40 → SIM7080G STATUS
GPIO44 → SIM7080G FLIGHT (RF kill)
GPIO15/7 → AXP2101 I2C (PMU, Wire1)
GPIO6 → AXP2101 INT (VBUS wake-up)
Insert a nano-SIM card into the slot on the bottom of the LILYGO board.
Note: The MPU-6050 AD0 pin must be pulled to 3.3 V so it uses I2C address 0x69 (avoiding collision with the DS1307 at 0x68). The BLITZ M10 is powered by the PMU DC5 rail (3.3 V).
Connect the board via USB-C, then in VSCode/PlatformIO:
- Upload Filesystem Image — uploads the Web UI to SPIFFS (only needed once, or after HTML changes)
- Upload — flashes the firmware
Or via terminal:
pio run --target uploadfs # upload Web UI
pio run --target upload # flash firmware- Connect to the IDTelemetry WiFi (password:
IDTelemetry1) - Open
http://192.168.4.1in your browser - Configure WiFi Guard, thresholds and backend credentials on the Config page
| GPIO | Function | Direction | Bus |
|---|---|---|---|
| 1 | External GPS RX (← M10 TX) | IN | UART2 |
| 2 | External GPS TX (→ M10 RX) | OUT | UART2 |
| 3 | MPU-6050 INT (deep sleep wake) | IN | EXT1 |
| 4 | Modem RX (← SIM7080G TX) | IN | UART1 |
| 5 | Modem TX (→ SIM7080G RX) | OUT | UART1 |
| 6 | PMU interrupt (VBUS wake) | IN | — |
| 7 | PMU SCL | BIDIR | I2C Wire1 |
| 15 | PMU SDA | BIDIR | I2C Wire1 |
| 17 | CAN TX | OUT | TWAI |
| 18 | CAN RX | IN | TWAI |
| 21 | Sensor SCL | BIDIR | I2C Wire0 |
| 40 | Modem STATUS | IN | — |
| 41 | Modem PWRKEY | OUT | — |
| 42 | Modem DTR | OUT | — |
| 44 | Modem FLIGHT / RF kill | OUT | — |
| 45 | Sensor SDA | BIDIR | I2C Wire0 |
I2C Wire0 devices: DS1307 (0x68), MPU-6050 (0x69), QMC5883L (0x0D — onboard BLITZ M10)
CAN bus TX is only enabled while the configured car WiFi SSID is visible. If the car's hotspot goes out of range, TX is locked immediately. This prevents accidental bus writes when the stick is powered outside the vehicle. An alternative guard mode uses VBUS detection (external 12 V power present = car is on).
When the gyro detects no movement (car parked):
- Final telemetry batch is sent
- GPS enters idle mode (M10 keeps tracking at ~5 mA, resumes instantly)
- ESP32-S3 enters deep sleep (µA range)
- Wakes on MPU-6050 motion interrupt (GPIO3) or VBUS insertion (GPIO6)
| Library | License | Author |
|---|---|---|
| arduino-esp32 | Apache 2.0 | Espressif |
| AsyncTCP | LGPL v3 | mathieucarbou |
| ESPAsyncWebServer | LGPL v3 | mathieucarbou |
| TinyGSM | LGPL v3 | vshymanskyy |
| ArduinoJson | MIT | Benoit Blanchon |
| NimBLE-Arduino | Apache 2.0 | h2zero |
| ArduinoHttpClient | Apache 2.0 | Arduino |
| XPowersLib | MIT | lewis he |
| Space Mono & Syne | OFL | Google Fonts |
Notes:
- ELM327 AT command set: proprietary protocol by ELM Electronics. This project implements an emulation layer for ABRP compatibility.
- OBD-II PIDs: SAE J1979 / ISO 15031 standard, freely usable.
- VW-specific UDS DIDs (service 0x22): community reverse-engineering, no official documentation.
This project follows the HITL principle (Human in the Loop): concept, decisions and direction come from the human — code is AI-assisted.
GNU Affero General Public License v3.0 © 2026 Ingo F — see LICENSE
Donations are voluntary and solely support the project. They have no influence on bug prioritization, feature requests or support.


