obd2/src/commands/mod.rs
Robert Sammelson 13b9041511
Add the remaining service $00 PIDs up to $20
Also restructure the code to implement get_dtcs and get_dtc_info by
implementing GetObd2Values on the data types they return. This brings
them in line with every other getter function besides get_vin.
2023-05-21 01:53:12 -04:00

223 lines
9.3 KiB
Rust

//! High level OBD-II interface
//!
//! Retrieves data from the vehicle, over the OBD-II link. The interface is defined by SAE J1979,
//! and a list of services and PIDs is available [on
//! Wikipedia](https://en.wikipedia.org/wiki/OBD-II_PIDs). This module mostly uses service 1.
mod implementation;
use implementation::{GetObd2Values, GetObd2ValuesMode};
#[macro_use]
mod macros;
mod types;
use types::private;
pub use types::{Dtc, DtcsInfo, OxygenSensorData};
use crate::{Obd2Device, Result};
func! {
/// Trait for devices that can retrieve data over OBD-II
///
/// Automatically implemented for implementors of [odb2::Obd2Device](crate::Obd2Device), and
/// currently cannot be otherwise implemented.
trait Obd2DataRetrieval;
{
/// Retreive the VIN (vehicle identification number)
///
/// This should match the number printed on the vehicle, and is a good
/// command for checking that the OBD-II interface is working correctly.
fn get_vin(self, 0x09, 0x02) -> Result<String> {
implementation::get_vin(self)
}
}
/// Get DTCs for each ECU
fn get_dtcs(0x03) -> Vec<Dtc>;
/// Get service 1 PID support for $01 to $20
fn get_service_1_pid_support_1(0x01, 0x00) -> u32;
/// Get DTC (diagnostic trouble code) metadata for each ECU
fn get_dtc_info(0x01, 0x01) -> DtcsInfo;
/// Get DTC that caused the current freeze frame
fn get_freeze_frame_dtc(0x01, 0x02) -> Dtc;
/// Get fuel system status (system A and B)
///
/// The first value describes the first fuel system. If there is a secondary fuel system, the
/// second value can be nonzero. Each value can represent one bank using the bottom four bits,
/// or two banks using either the bottom five bits or the whole byte, depending on the
/// configuration of the banks.
///
/// Valid values for single bank systems:
/// - `0`: engine off (including temporarily for vehicles that turn of the engine at idle)
/// - `1`: open loop — conditions to go closed loop not yet met
/// - `2`: closed loop
/// - `4`: open loop — due to current conditions
/// - `8`: open loop — due to fault
fn get_fuel_system_status(0x01, 0x03) -> [u8; 2];
/// Get the calculated engine load (out of 255)
fn get_engine_load(0x01, 0x04) -> u8;
/// Get the temperature of the engine's coolant in ºC
fn get_engine_coolant_temperature<u8>(0x01, 0x05, |v: i16| v - 40) -> i16;
/// Get the short term fuel trim for bank 1
///
/// This is for vehicles with closed loop air/fuel ratio control. It ranges from about -1 to 1,
/// where negative percentages mean the mix is being made more lean. If the fuel system is in
/// open-loop control, this will read 0.
fn get_short_term_fuel_trim_1<u8>(0x01, 0x06, |v: f32| (v / 128.) - 1.) -> f32;
/// Get the long term fuel trim for bank 1
///
/// This is for vehicles with closed loop air/fuel ratio control. It ranges from about -1 to 1,
/// where negative percentages mean the mix is being made more lean. This long term trim value
/// represents a value saved between shutdowns of the engine. In open-loop control, if this
/// value is not used it will read 0.
fn get_long_term_fuel_trim_1<u8>(0x01, 0x07, |v: f32| (v / 128.) - 1.) -> f32;
/// Like [get_short_term_fuel_trim_1](Self::get_short_term_fuel_trim_1) but for bank 2
fn get_short_term_fuel_trim_2<u8>(0x01, 0x08, |v: f32| (v / 128.) - 1.) -> f32;
/// Like [get_long_term_fuel_trim_1](Self::get_long_term_fuel_trim_1) but for bank 2
fn get_long_term_fuel_trim_2<u8>(0x01, 0x09, |v: f32| (v / 128.) - 1.) -> f32;
/// Get the fuel pressure in kPa
///
/// This measurement is gauge pressure (measured relative to the atmosphere)
fn get_fuel_pressure<u8>(0x01, 0x0A, |v: i16| v * 3) -> i16;
/// Get the intake manifold pressure in kPa
///
/// This measurement is absolute pressure.
fn get_engine_manifold_pressure<u16>(0x01, 0x0B, |v: f32| v) -> f32;
/// Get the RPM of the engine in increments of 0.25
fn get_rpm<u16>(0x01, 0x0C, |v: f32| v / 4.0) -> f32;
/// Get the speed of the vehicle in km/h
fn get_speed(0x01, 0x0D) -> u8;
/// Get the timing advance in degrees BTDC
///
/// Higher numbers mean the ignition happens earlier; that is, longer before the piston reaches
/// the top of the cylinder.
fn get_timing_advance<u8>(0x01, 0x0E, |v: f32| (v - 128.0) / 2.0) -> f32;
/// Get intake manifold air temperature in ºC
fn get_intake_air_temperature<u8>(0x01, 0x0F, |v: i16| v - 40) -> i16;
/// Get air flow rate in g/s
fn get_air_flow_rate<u16>(0x01, 0x10, |v: f32| v * 0.01) -> f32; // TODO: scaling
/// Get absolute throttle position (out of 255)
///
/// This is the raw sensor value, so idle throttle will probably be more than 0 and open
/// throttle will probably be less than 255.
fn get_throttle_position(0x01, 0x11) -> u8;
/// Get commanded secondary air status (bitfield)
///
/// This describes where the secondary air system has been commanded to inject air. The valid
/// values are:
/// - `1`: Upstream of the first catalytic converter inlet
/// - `2`: Downstream of the first catalytic converter inlet
/// - `4`: Off (or atmosphere)
/// - `8`: On for diagnostics
///
/// This system exists to reduce emissions. By injecting air in front of the catalytic
/// converter, extra fuel in the exhaust combusts, heating the catalytic converter. Once the
/// catalytic converter is up to temperature, air is injected into the catalytic converter to
/// help it catalyze unburned fuel.
///
/// See: <https://en.wikipedia.org/wiki/Secondary_air_injection>
fn get_commanded_secondary_air_status(0x01, 0x12) -> u8;
/// Get location of oxygen sensors
///
/// This version (cf. [get_oxygen_sensors_4_bank](Self::get_oxygen_sensors_4_bank)) is
/// recommended for two bank systems. A vehicle must not support both variants.
///
/// The each nibble represents the sensors of one bank, the less significant nibble is bank 1.
/// The bits of the nibble represent each of the four possible sensors, with sensor 1 in the
/// least significant bit.
fn get_oxygen_sensors_2_bank(0x01, 0x13) -> u8;
/// Get oxygen sensor 1 voltage and associated air/fuel short term trim
///
/// This is bank 1, sensor 1.
fn get_oxygen_sensor_1(0x01, 0x14) -> OxygenSensorData;
/// Get oxygen sensor 2 voltage and associated air/fuel short term trim
///
/// This is for bank 1, sensor 2.
fn get_oxygen_sensor_2(0x01, 0x15) -> OxygenSensorData;
/// Get oxygen sensor 3 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 1, sensor 3. If using four banks, this is for bank 2
/// sensor 1.
fn get_oxygen_sensor_3(0x01, 0x16) -> OxygenSensorData;
/// Get oxygen sensor 4 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 1, sensor 4. If using four banks, this is for bank 2
/// sensor 2.
fn get_oxygen_sensor_4(0x01, 0x17) -> OxygenSensorData;
/// Get oxygen sensor 5 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 2, sensor 1. If using four banks, this is for bank 3
/// sensor 1.
fn get_oxygen_sensor_5(0x01, 0x18) -> OxygenSensorData;
/// Get oxygen sensor 6 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 2, sensor 2. If using four banks, this is for bank 3
/// sensor 2.
fn get_oxygen_sensor_6(0x01, 0x19) -> OxygenSensorData;
/// Get oxygen sensor 7 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 2, sensor 3. If using four banks, this is for bank 4
/// sensor 1.
fn get_oxygen_sensor_7(0x01, 0x1A) -> OxygenSensorData;
/// Get oxygen sensor 8 voltage and associated air/fuel short term trim
///
/// If using two banks, this is for bank 2, sensor 4. If using four banks, this is for bank 4
/// sensor 2.
fn get_oxygen_sensor_8(0x01, 0x1B) -> OxygenSensorData;
/// Get which OBD standard this vehicle is designed to support
fn get_obd_requirements(0x01, 0x1C) -> u8;
/// Get location of oxygen sensors
///
/// This version (cf. [get_oxygen_sensors_2_bank](Self::get_oxygen_sensors_2_bank)) is
/// recommended for four bank systems. A vehicle must not support both variants.
///
/// The each pair of bits represents the sensors of one bank, the least significant pair is
/// bank 1. The bits of the pair represent each of the two possible sensors, with sensor 1 in
/// the less significant bit.
fn get_oxygen_sensors_4_bank(0x01, 0x1D) -> u8;
/// Get auxiliary input status
///
/// The least significant bit indicates whether [power
/// take-off](https://en.wikipedia.org/wiki/Power_Take_Off) is active.
fn get_auxiliary_input_status(0x01, 0x1E) -> u8;
/// Get the amount of time since the engine was started in seconds
///
/// This should saturate—not roll over—after the engine has been running for [u16::MAX] seconds
/// (≈18.2 hours).
fn get_run_time(0x01, 0x1F) -> u16;
/// Get service 1 PID support for $21 to $40
fn get_service_1_pid_support_2(0x01, 0x20) -> u32;
}