OBD-II Driver¶
jumpstarter-driver-obd wraps python-obd
to query On-Board Diagnostics (OBD-II) PIDs from a vehicle ECU via an ELM327 adapter.
Installation¶
$ pip3 install --extra-index-url https://pkg.jumpstarter.dev/simple jumpstarter-driver-obd
Hardware Requirements¶
An ELM327 USB adapter (e.g. PremiumCord ELM327 USB)
A vehicle with an OBD-II port (petrol cars from 2001+, diesel from 2004+, all US cars from 1996+)
macOS only: ELM327 USB cables use a CH340 or CP2102 USB-serial chip that may need a kernel extension — install the appropriate driver if the port does not appear after plugging in
Configuration¶
Auto-detect (recommended for a single adapter)¶
Leave port unset or null to let python-obd scan available serial ports and connect to the first
ELM327 it finds:
export:
obd:
type: jumpstarter_driver_obd.driver.OBD
config:
port: null
Note
Auto-detect is reliable on Linux (e.g. /dev/ttyUSB0). On macOS it is not: python-obd
enumerates the /dev/tty.* call-in device nodes, but ELM327 adapters only open on the matching
/dev/cu.* call-out node, so auto-detect fails to connect. On macOS, pass an explicit
/dev/cu.usbserial-* port instead.
Explicit port¶
Specify the serial port directly when you have multiple adapters or want a deterministic setup:
export:
obd:
type: jumpstarter_driver_obd.driver.OBD
config:
port: /dev/ttyUSB0 # Linux
# port: /dev/cu.usbserial-XXXX # macOS
baudrate: 38400
Config parameters¶
Parameter |
Description |
Type |
Required |
Default |
|---|---|---|---|---|
port |
Serial port path; |
str | null |
no |
null |
baudrate |
ELM327 baud rate |
int |
no |
38400 |
fast |
Enable ELM327 fast mode (~100–400 ms faster per query); unreliable on cheap clone adapters, so it is opt-in |
bool |
no |
false |
Usage¶
from jumpstarter_driver_obd import OBDConnectionStatus
# Check connection state
status = obd.status() # returns OBDConnectionStatus
print(status == OBDConnectionStatus.CAR_CONNECTED) # True
print(obd.is_connected()) # True
# Discover what the ECU supports
cmds = obd.supported_commands() # ["RPM", "SPEED", "COOLANT_TEMP", ...]
# Query individual PIDs by name
rpm = obd.query("RPM") # "3000.0 revolutions_per_minute"
speed = obd.query("SPEED") # "60.0 kph"
temp = obd.query("COOLANT_TEMP") # "90.0 degC"
# Clearing trouble codes is a separate, explicit call (see note below)
obd.clear_dtc()
query() returns None when the ECU does not answer the command (unsupported PID
or no vehicle on the bus). It is read-only: it refuses destructive commands such as
CLEAR_DTC (OBD-II mode 04, which erases stored trouble codes and resets emissions
readiness monitors). To clear codes deliberately, call clear_dtc() instead.
Troubleshooting¶
Port not found on macOS
Run ls /dev/cu.* before and after plugging in the cable to spot the new device.
Install a CH340 or CP2102 USB-serial kernel extension if no new port appears.
Permission denied on Linux
Add your user to the dialout group and log out/in:
sudo usermod -aG dialout $USER
Alternatively, create a udev rule for the adapter’s USB vendor/product ID.
“No OBD-II adapters found” Make sure the cable is seated in the OBD-II port (typically under the dashboard on the driver’s side) and that the vehicle ignition is in the ON or ACC position.
API Reference¶
- class jumpstarter_driver_obd.driver.OBD¶
OBD-II vehicle diagnostics via an ELM327 adapter, wrapping python-obd.
port=None(the default) auto-detects the adapter; otherwise pass the serial path, e.g./dev/ttyUSB0.- clear_dtc() None¶
Clear stored DTCs and freeze-frame data (mode 04).
Destructive: also resets readiness monitors, which then need drive cycles to re-complete. Use only as a deliberate reset.
- classmethod client() str¶
Return full import path of the corresponding driver client class
- is_connected() bool¶
True when a vehicle ECU is on the bus, not just the adapter.
- query(command_name: str) str | None¶
Query a PID by name (e.g. ‘RPM’, ‘SPEED’, ‘COOLANT_TEMP’).
Returns None if the ECU doesn’t answer. Destructive commands such as CLEAR_DTC are rejected here; use clear_dtc() instead.
- status() OBDConnectionStatus¶
Connection state.
- supported_commands() list[str]¶
Sorted PID names the connected ECU advertises.
- class jumpstarter_driver_obd.client.OBDClient¶
Client for the OBD-II driver.
- clear_dtc() None¶
Clear stored DTCs and freeze-frame data (mode 04).
Destructive: also resets readiness monitors.
- is_connected() bool¶
True when a vehicle ECU is on the bus, not just the adapter.
- query(command_name: str) str | None¶
Query a PID by name (e.g. ‘RPM’); returns None if the ECU doesn’t answer.
- status() OBDConnectionStatus¶
Connection state.
- supported_commands() list[str]¶
Sorted PID names the connected ECU advertises.
- class jumpstarter_driver_obd.driver.OBDConnectionStatus¶