ESP32-based vehicle telemetry system built on Freematics hardware that collects OBD-II and GPS data, persists it safely to SD, and uploads it over LTE with retry and recovery logic.
This project is designed for real-world fleet use where connectivity is unreliable and data loss is unacceptable.
- 🚗 OBD-II Telemetry
- RPM, speed, throttle, engine load, coolant temp, fuel level, distance
- 📍 GPS Tracking
- Latitude, longitude, altitude, satellite count
- 📡 LTE Connectivity
- SIMCom modem via Freematics
- Signal quality awareness
- 💾 Store-and-Forward (SD Card)
- NDJSON rows written to SD
- File rotation by size / time
- Safe across reboots and outages
- 🗜 Compressed Uploads
- Gzip compression
- Base64 transport (ASCII-safe for AT commands)
- 🔁 Retry & Backoff
- Exponential backoff with jitter
- Idempotent uploads using file IDs
- 🆔 Device Identification
vin(from OBD with fallback)hardware_id= modem IMEI
- 🧠 Modular Architecture
- Clear separation of concerns
- Easy to extend (raw TCP, TLS, ICCID, etc.)
OBD-II + GPS
│
▼
telemetry_row
│
▼
SD Spool (NDJSON)
│
├─ gzip + base64
▼
LTE Upload (HTTP)
│
▼
Server Ingestion
Design principle: never lose data.
Uploads are best-effort; persistence is guaranteed.
obd-networking-v2/
├── obd-networking-v2.ino # Main sketch
├── config.h / config.cpp # Global configuration
├── debug.h / debug.cpp # Debug toggles + logging
├── telemetry_row.* # Build one telemetry row (stateless)
├── cell_at.h # Modem wrapper (AT helpers)
├── vin.* # VIN discovery logic
├── http_client.* # HTTP stack init / recovery
├── src/
│ ├── util/
│ │ ├── fs_utils.* # SD helpers
│ │ └── time_utils.* # Timestamp helpers
│ ├── storage/
│ │ ├── sd_store.* # SD initialization
│ │ └── spooler.* # Store-and-forward logic
│ ├── compress/
│ │ └── gzipper.* # Gzip (pluggable)
│ └── net/
│ ├── http_stream.* # Upload gzipped data
│ └── retry_policy.* # Retry & backoff
└── README.md
{
"vin": "1GC5KNEY3TF185576",
"hardware_id": "356938035643809",
"ts_ms": 12345678,
"rpm": 1820,
"spd": 47,
"fuel": 62,
"thr": 18,
"load": 42,
"temp": 190,
"dist": 12345,
"dtc": "NONE",
"lat": 41.3083,
"lng": -72.9279,
"alt": 14.2,
"sat": 8,
"acc_x": 0.0,
"os_version": "0.0.1",
"device": "Freematics ONE+",
"engine_efficiency": 15.3,
"lte_connected": true
}- Freematics ESP32 (ONE / ONE+)
- SIMCom LTE modem
- SD card
- Vehicle with OBD-II port
Tested with GM / Ford / Dodge trucks in intermittent LTE conditions.
Key values live in config.h / config.cpp:
API_URL– ingestion endpointDEVICE_TOKEN– device auth tokenAPN– cellular APN- Sampling and rotation intervals
Secrets are currently hard-coded. For production use:
- move secrets to a git-ignored
secrets.h, or - inject via build flags / CI
This repo now includes a working PlatformIO project and the required
Freematics libraries under lib/.
For field updates over USB, use the repo-level build script:
./build.shThat flow will:
- bootstrap PlatformIO if it is not already installed
- keep PlatformIO state local to the repo under
.platformio-core/ - install project dependencies
- build the firmware
- copy flash artifacts into
dist/freematics_one_plus/ - auto-detect a USB serial port and flash the board
Useful variants:
./build.sh --build-only
./build.sh --port /dev/cu.usbserial-1110
./build.sh --flash-only --port /dev/ttyUSB0
./build.sh --monitor --port /dev/cu.usbserial-1110- Python 3 if
PlatformIO/piois not already installed - ESP32 USB serial driver / device access on your machine
- Freematics ONE / ONE+ hardware connected over USB
platformio runThis builds the firmware for the freematics_one_plus environment defined in
platformio.ini.
platformio run --target uploadIf PlatformIO does not detect the serial port automatically:
platformio run --target upload --upload-port /dev/tty.usbserial-*platformio device monitor -b 115200Or with an explicit port:
platformio device monitor -b 115200 -p /dev/tty.usbserial-*- The build target uses
esp-wrover-kit, matching the Freematics ESP32 examples. - Build artifacts are written to
.pio/and are git-ignored. - The repo vendors only the required Freematics libraries:
lib/FreematicsPluslib/FreematicsONE
The server endpoint should:
- Accept JSON payloads
- Decode:
transfer_encoding = base64content_encoding = gzip
- Gunzip → parse NDJSON line-by-line
- Deduplicate uploads using
X-File-Id
Raw TCP streaming (no base64) can be added later for higher throughput.
🚧 Active development
Planned improvements:
- Raw TCP streaming uploads
- SIM ICCID capture
- TLS support
- PlatformIO compatibility
- Server-side schema validation
MIT (or replace with your preferred license)
Built by Robert Davis
Designed for real-world fleet telemetry and operations tooling.