obd2 0.10.1
obd2: ^0.10.1 copied to clipboard
A production-ready SAE J1979 OBD-II SDK for Flutter with BLE support for ELM327-compatible adapters. Provides real-time telemetry, DTC parsing, and type-safe PID handling.
๐ Flutter OBD2 #
A modern SAE J1979 OBD-II SDK for Flutter.
Flutter OBD2 provides a clean, type-safe, and transport-separated architecture for communicating with ELM327-compatible Bluetooth Low Energy (BLE) adapters using the SAE J1979 (Generic OBD-II) standard.
โ๏ธ This SDK intentionally supports SAE J1979 only. It does not implement UDS or manufacturer-specific diagnostic protocols.
๐ฑ Platform Support #
| Platform | Status |
|---|---|
| Android | โ Supported |
| iOS | โ ๏ธ Untested |
| macOS | โ Not Supported |
| Windows | โ ๏ธ Untested |
| Web | โ Not Supported |
๐ฆ Current Release Status #
Version: 0.10.x (Stabilization Phase)
- โ Mode 01 (Live Telemetry) โ Production ready
- ๐ง Modes 02โ04 โ Implemented, limited real-world validation
- ๐ง OdometerEngine โ Experimental
- ๐งช Full unit test coverage with CI integration
- ๐ Architecture finalized for 1.0 milestone
๐ Example Dashboard #

โจ Why Flutter OBD2? #
Most OBD libraries:
- Mix transport and protocol logic
- Expose raw hex responses
- Require manual PID parsing
- Overload the ECU with unsafe polling
Flutter OBD2 provides:
- โ Clean layered architecture
- โ
Strongly typed
DetailedPID<T>system - โ Adaptive, collision-safe telemetry scheduler
- โ Concurrency-safe command lifecycle
- โ Service-level diagnostic execution
- โ Formula evaluation engine
- โ Greedy BLE compatibility layer
- โ Strict SAE J1979 implementation
This is a diagnostic SDK, not just a Bluetooth wrapper.
๐ Architecture Overview #
BluetoothAdapterOBD2 (BLE Transport)
โ
AdapterOBD2 (Core Engine)
โ
SaeJ1979 Protocol
โโโ telemetry
โโโ freezeFrame
โโโ readCodes
โโโ clearCodes
๐ Transport Layer โ BluetoothAdapterOBD2 #
Handles:
- BLE connection
- GATT discovery
- Characteristic subscription
- Raw byte streaming
- ELM327 initialization
๐ง Core Engine โ AdapterOBD2 #
Handles:
- ASCII encoding / decoding
- Concurrency-safe raw command execution
- Strict request lifecycle control
- Service-level abstraction (
sendService,sendServiceWithPID) - Response buffering & header validation
- Formula evaluation
- Composite PID parsing
This separation ensures transport and diagnostic layers remain fully independent.
๐ SAE J1979 Protocol #
Provides:
- Static PID definitions
- Mode grouping (01โ04)
- Byte extraction logic
- Standards-compliant DTC decoding
- Freeze frame conversion logic
๐ Getting Started #
๐งฐ Requirements #
- Flutter 3.x
- Dart 3.x
- ELM327-compatible BLE adapter (NexLink BLE adapters recommended)
1๏ธโฃ Installation #
dependencies:
obd2: ^0.10.0
flutter_blue_plus: ^2.1.0
2๏ธโฃ Connect to Adapter #
import 'package:obd2/obd2.dart';
import 'package:flutter_blue_plus/flutter_blue_plus.dart';
final adapter = BluetoothAdapterOBD2();
await adapter.connect(myBluetoothDevice);
The adapter automatically:
- Connects
- Discovers services
- Subscribes to notify/indicate characteristics
- Selects writable pipe
- Sends AT initialization commands
- Negotiates protocol
No protocol injection required.
๐ก Mode 01 โ Live Telemetry (Production Ready) #
final telemetry = adapter.protocol.telemetry;
final session = telemetry.stream(
detailedPIDs: [
Telemetry.rpm,
Telemetry.speed,
Telemetry.coolantTemperature,
],
onData: (TelemetryData data) {
final rpm = data.get(Telemetry.rpm);
if (rpm != null) {
print("RPM: $rpm");
}
},
);
session.stop();
๐ง Telemetry Engine Features #
- EDF (Earliest Deadline First) scheduler
- Min-heap task prioritization
- Token bucket QPS rate limiting
- EMA-based adaptive latency control
- Respects per-PID
pollingIntervalMs - Prevents ECU flooding and BLE congestion
- Concurrency-safe execution
- Type-safe PID retrieval
Designed for stable high-frequency telemetry streaming.
๐ Supported PID Discovery #
final supported = await adapter.protocol.telemetry
.detectSupportedTelemetry();
print("Supported: $supported");
Bitmask-based detection aligned with SAE J1979 capability discovery.
๐ง Mode 02 โ Freeze Frame (Experimental) #
final freeze = adapter.protocol.freezeFrame;
final snapshot = await freeze.getFrameData();
final rpm = snapshot[Telemetry.rpm];
Features:
- Automatic Mode 01 โ Mode 02 PID conversion
- Proper DTC byte decoding
- Unified PID โ value mapping aligned with live telemetry
- Graceful handling of unsupported freeze PIDs
๐จ Mode 03 โ Read Diagnostic Trouble Codes (Experimental) #
final codes = await adapter.protocol.readCodes.getDTCs();
print("Fault Codes: $codes");
Features:
- Pure service-level execution
- Strict connection validation
- Standards-compliant DTC bit decoding
- Header validation & payload extraction
๐งน Mode 04 โ Clear Diagnostic Trouble Codes (Experimental) #
final success = await adapter.protocol.clearCodes.eraseDTCs();
print("Cleared: $success");
Features:
- Service-level Mode 04 execution
- Proper positive response validation (0x44)
- No dummy PID abstraction
๐งฌ Type-Safe PID System #
Each PID is defined as:
DetailedPID<T>
Includes:
parameterIDformulaunitpollingIntervalMsobd2QueryReturnType
Compile-time enforced return types:
| Type | Example |
|---|---|
double |
RPM |
String |
Fuel Type |
List<double> |
Lambda |
List<int> |
Status Bitmask |
No manual casting required.
๐ฆ Telemetry Models #
TelemetryData #
Strongly-typed telemetry snapshot container.
final rpm = data.get(Telemetry.rpm);
Ensures compile-time safety when retrieving values.
OdometerUpdateResult #
Immutable model representing odometer calculation results with timestamp integrity.
๐งฎ OdometerEngine (Experimental) #
A standalone Riemann integration engine for distance tracking.
final engine = OdometerEngine(12500.0);
engine.start(DateTime.now());
engine.update(65.0, DateTime.now());
print(engine.value);
Features:
- Riemann-based distance integration
- GPS drift filtering (< 0.5 km/h ignored)
- Backwards clock protection
- Large delta spike guard
- Safe reset and restart logic
Designed for GPS-based distance estimation independent of ECU odometer.
๐ BLE Compatibility Strategy #
BluetoothAdapterOBD2 uses a Greedy Discovery Model:
- Connect
- Discover all services
- Subscribe to every notify/indicate characteristic
- Prefer standard ELM327 UUIDs (FFF2 / FFE1)
- Initialize adapter
Optimized for low-cost ELM327 clones.
๐ง Public API Overview #
Core #
await adapter.connect(device);
await adapter.disconnect();
SAE J1979 Access #
adapter.protocol.telemetry
adapter.protocol.freezeFrame
adapter.protocol.readCodes
adapter.protocol.clearCodes
๐งช Testing & CI #
- Full unit tests
dart analyzeenforced- GitHub Actions CI
- Mock adapter testing (no hardware required)
โ What This Package Is Not #
Flutter OBD2 does not:
- Flash ECUs
- Remap fuel maps
- Modify odometers
- Access manufacturer-specific modules
- Implement UDS or ISO 14229
This package strictly implements the SAE J1979 emissions diagnostic standard.
โ ๏ธ Testing Status #
| Mode | Validation Level |
|---|---|
| Mode 01 | โ Fully Tested |
| Mode 02 | ๐ง Partial |
| Mode 03 | ๐ง Partial |
| Mode 04 | ๐ง Partial |
| OdometerEngine | ๐ง Experimental |
Full real-world validation targeted for v1.0.0.
๐ฏ Road to 1.0 #
Version 1.0.0 will signify:
- Complete real-world validation
- Stable API commitment
- Production-grade diagnostic reliability
๐งญ Design Philosophy #
Flutter OBD2:
- Implements SAE J1979 correctly
- Avoids unnecessary abstraction
- Separates transport from diagnostics
- Prioritizes clarity over feature bloat
- Is engineered for long-term stability
๐ License #
Licensed under the Mozilla Public License 2.0.
