use std::fmt::{Debug, Display, Formatter};
use std::mem::transmute;
#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq)]
pub enum ObdEnumValue {
FuelSystemStatus(FuelSystemStatus),
CommandedAirStatus(CommandedSecondaryAirStatus),
ObdStandard(OBDStandard),
FuelType(FuelTypeCoding),
}
impl From<ObdEnumValue> for u32 {
fn from(x: ObdEnumValue) -> u32 {
let u: u16 = match x {
ObdEnumValue::FuelSystemStatus(x) => unsafe { transmute(x) },
ObdEnumValue::CommandedAirStatus(x) => unsafe { transmute(x) },
ObdEnumValue::ObdStandard(x) => unsafe { transmute(x) },
ObdEnumValue::FuelType(x) => unsafe { transmute(x) },
};
u as u32
}
}
impl Display for ObdEnumValue {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
ObdEnumValue::FuelSystemStatus(x) => std::fmt::Display::fmt(&x, f),
ObdEnumValue::CommandedAirStatus(x) => std::fmt::Display::fmt(&x, f),
ObdEnumValue::ObdStandard(x) => std::fmt::Display::fmt(&x, f),
ObdEnumValue::FuelType(x) => std::fmt::Display::fmt(&x, f),
}
}
}
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
pub enum FuelSystemStatus {
Off,
OpenLoopLowTemp,
ClosedLoopO2Feedback,
OpenLoopEngineLoad,
OpenLoopSystemFailure,
ClosedLoopWithFault,
Invalid(u8),
}
impl Display for FuelSystemStatus {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self {
FuelSystemStatus::Off => write!(f, "The motor is off"),
FuelSystemStatus::OpenLoopLowTemp => write!(f, "Open loop due to insufficient engine temperature"),
FuelSystemStatus::ClosedLoopO2Feedback => write!(f, "Closed loop, using oxygen sensor feedback to determine fuel mix"),
FuelSystemStatus::OpenLoopEngineLoad => write!(f, "Open loop due to engine load / fuel cut due to deceleration"),
FuelSystemStatus::OpenLoopSystemFailure => write!(f, "Open loop due to system failure"),
FuelSystemStatus::ClosedLoopWithFault => write!(f, "Closed loop, using at least one oxygen sensor but there is a fault in the feedback system"),
FuelSystemStatus::Invalid(x) => write!(f, "Invalid fuel system status 0x{:02X}", x)
}
}
}
impl From<u8> for FuelSystemStatus {
fn from(x: u8) -> Self {
match x {
0x00 => Self::Off,
0x01 => Self::OpenLoopEngineLoad,
0x02 => Self::ClosedLoopO2Feedback,
0x04 => Self::OpenLoopEngineLoad,
0x08 => Self::OpenLoopSystemFailure,
0x10 => Self::ClosedLoopWithFault,
x => Self::Invalid(x),
}
}
}
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
pub enum CommandedSecondaryAirStatus {
Upstream,
DownstreamOfCat,
FromOutsideOrOff,
PumpCommandedForDiagnostics,
Invalid(u8),
}
impl Display for CommandedSecondaryAirStatus {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self {
CommandedSecondaryAirStatus::Upstream => write!(f, "Upstream"),
CommandedSecondaryAirStatus::DownstreamOfCat => {
write!(f, "Downstream of catalytic converter")
}
CommandedSecondaryAirStatus::FromOutsideOrOff => {
write!(f, "From the outside atmosphere or off")
}
CommandedSecondaryAirStatus::PumpCommandedForDiagnostics => {
write!(f, "Pump commanded on for diagnostics")
}
CommandedSecondaryAirStatus::Invalid(x) => {
write!(f, "Invalid commanded secondary air status 0x{:02X}", x)
}
}
}
}
impl From<u8> for CommandedSecondaryAirStatus {
fn from(x: u8) -> Self {
match x {
0x01 => Self::Upstream,
0x02 => Self::DownstreamOfCat,
0x04 => Self::FromOutsideOrOff,
0x08 => Self::PumpCommandedForDiagnostics,
x => Self::Invalid(x),
}
}
}
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub enum OBDStandard {
OBD_II_CARB,
OBD_EPA,
OBD_OBD_II,
OBD_I,
NON_COMPLIANT,
EOBD,
EOBD_OBD_II,
EOBD_OBD,
EOBD_OBD_OBD_II,
JOBD,
JOBD_OBD_II,
JOBD_EOBD,
JOBD_EOBD_OBD_II,
EMD,
EMD_PLUS,
HD_OBD_C,
HD_OBD,
WWH_OBD,
HD_EOBD_I,
HD_EOBD_I_N,
HD_EOBD_II,
HD_EOBD_II_N,
OBDBR_1,
OBDBR_2,
KOBD,
IOBD_I,
IOBD_II,
HD_EOBD_IV,
Reserved(u8),
NotAvailable(u8),
}
impl Display for OBDStandard {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match &self {
OBDStandard::OBD_II_CARB => write!(f, "OBD-II as defined by the CARB"),
OBDStandard::OBD_EPA => write!(f, "OBD as defined by the EPA"),
OBDStandard::OBD_OBD_II => write!(f, "OBD and OBD-II"),
OBDStandard::OBD_I => write!(f, "OBD-I"),
OBDStandard::NON_COMPLIANT => write!(f, "Not OBD Compliant"),
OBDStandard::EOBD => write!(f, "Europe OBD"),
OBDStandard::EOBD_OBD_II => write!(f, "Europe OBD and OBD-II"),
OBDStandard::EOBD_OBD => write!(f, "Europe OBD and OBD"),
OBDStandard::EOBD_OBD_OBD_II => write!(f, "Europe OBD, OBD and OBD-II"),
OBDStandard::JOBD => write!(f, "Japan OBD"),
OBDStandard::JOBD_OBD_II => write!(f, "Japan OBD and OBD-II"),
OBDStandard::JOBD_EOBD => write!(f, "Japan OBD and Europe OBD"),
OBDStandard::JOBD_EOBD_OBD_II => write!(f, "Japan OBD, Europe OBD and OBD-II"),
OBDStandard::EMD => write!(f, "Engine Manufacturer Diagnostics"),
OBDStandard::EMD_PLUS => write!(f, "Engine Manufacturer Diagnostics Enhanced"),
OBDStandard::HD_OBD_C => write!(f, "Heavy Duty OBD (Child/Partial)"),
OBDStandard::HD_OBD => write!(f, "Heavy Duty OBD"),
OBDStandard::WWH_OBD => write!(f, "World wide harmonized OBD"),
OBDStandard::HD_EOBD_I => write!(f, "Heavy duty OBD Stage I without NOx control"),
OBDStandard::HD_EOBD_I_N => write!(f, "Heavy duty OBD Stage I with NOx control"),
OBDStandard::HD_EOBD_II => write!(f, "Heavy duty OBD Stage II without NOx control"),
OBDStandard::HD_EOBD_II_N => write!(f, "Heavy duty OBD Stage II with NOx control"),
OBDStandard::OBDBR_1 => write!(f, "Brazil OBD Phase 1"),
OBDStandard::OBDBR_2 => write!(f, "Brazil OBD Phase 2"),
OBDStandard::KOBD => write!(f, "Korean OBD"),
OBDStandard::IOBD_I => write!(f, "Indian OBD-I"),
OBDStandard::IOBD_II => write!(f, "Indian OBD-II"),
OBDStandard::HD_EOBD_IV => write!(f, "Heavy duty Euro OBD Stage VI"),
OBDStandard::Reserved(x) => write!(f, "Reserved 0x{:02X}", x),
OBDStandard::NotAvailable(x) => write!(f, "Not available for assignment 0x{:02X}", x),
}
}
}
impl From<u8> for OBDStandard {
fn from(x: u8) -> Self {
match x {
1 => Self::OBD_II_CARB,
2 => Self::OBD_EPA,
3 => Self::OBD_OBD_II,
4 => Self::OBD_I,
5 => Self::NON_COMPLIANT,
6 => Self::EOBD,
7 => Self::EOBD_OBD_II,
8 => Self::EOBD_OBD,
9 => Self::EOBD_OBD_OBD_II,
10 => Self::JOBD,
11 => Self::JOBD_OBD_II,
12 => Self::JOBD_EOBD,
13 => Self::JOBD_EOBD_OBD_II,
17 => Self::EMD,
18 => Self::EMD_PLUS,
19 => Self::HD_OBD_C,
20 => Self::HD_OBD,
21 => Self::WWH_OBD,
23 => Self::HD_EOBD_I,
24 => Self::HD_EOBD_I_N,
25 => Self::HD_EOBD_II,
26 => Self::HD_EOBD_II_N,
28 => Self::OBDBR_1,
29 => Self::OBDBR_2,
30 => Self::KOBD,
31 => Self::IOBD_I,
32 => Self::IOBD_II,
33 => Self::HD_EOBD_IV,
14 | 15 | 16 | 22 | 27 | 34..=250 => Self::Reserved(x),
x => Self::NotAvailable(x),
}
}
}
#[derive(Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq)]
#[allow(non_camel_case_types)]
pub enum FuelTypeCoding {
NotAvailable,
Gasoline,
Methanol,
Ethanol,
Diesel,
LPG,
CNG,
Propane,
Electric,
BifuelGasoline,
BifuelMethanol,
BifuelEthanol,
BifuelLPG,
BifuelCNG,
BifuelPropane,
BifuelElectricity,
BifuelElectricAndCombustion,
HybridGasoline,
HybridEthanol,
HybridDiesel,
HybridElectric,
HybridElectricAndCombustion,
HybridRegen,
BifuelDiesel,
Reserved(u8),
}
impl Display for FuelTypeCoding {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
FuelTypeCoding::NotAvailable => write!(f, "Not available"),
FuelTypeCoding::Gasoline => write!(f, "Gasoline"),
FuelTypeCoding::Methanol => write!(f, "Methanol"),
FuelTypeCoding::Ethanol => write!(f, "Ethanol"),
FuelTypeCoding::Diesel => write!(f, "Diesel"),
FuelTypeCoding::LPG => write!(f, "LPG"),
FuelTypeCoding::CNG => write!(f, "CNG"),
FuelTypeCoding::Propane => write!(f, "Propane"),
FuelTypeCoding::Electric => write!(f, "Electric"),
FuelTypeCoding::BifuelGasoline => write!(f, "Bifuel running Gasoline"),
FuelTypeCoding::BifuelMethanol => write!(f, "Bifuel running Methanol"),
FuelTypeCoding::BifuelEthanol => write!(f, "Bifuel running Ethanol"),
FuelTypeCoding::BifuelLPG => write!(f, "Bifuel running LPG"),
FuelTypeCoding::BifuelCNG => write!(f, "Bifuel running CNG"),
FuelTypeCoding::BifuelPropane => write!(f, "Bifuel running Propane"),
FuelTypeCoding::BifuelElectricity => write!(f, "Bifuel running Electricity"),
FuelTypeCoding::BifuelElectricAndCombustion => {
write!(f, "Bifuel running electric and combustion engine")
}
FuelTypeCoding::HybridGasoline => write!(f, "Hybrid Gasoline"),
FuelTypeCoding::HybridEthanol => write!(f, "Hybrid Ethanol"),
FuelTypeCoding::HybridDiesel => write!(f, "hybrid Diesel"),
FuelTypeCoding::HybridElectric => write!(f, "Hybrid Electric"),
FuelTypeCoding::HybridElectricAndCombustion => {
write!(f, "Hybrid running electric and combustion engine")
}
FuelTypeCoding::HybridRegen => write!(f, "Hybrid Regenerative"),
FuelTypeCoding::BifuelDiesel => write!(f, "Bifuel running diesel"),
FuelTypeCoding::Reserved(x) => write!(f, "Reserved by ISO/SAE 0x{:02X?}", x),
}
}
}
impl From<u8> for FuelTypeCoding {
fn from(x: u8) -> Self {
match x {
0 => Self::NotAvailable,
1 => Self::Gasoline,
2 => Self::Methanol,
3 => Self::Ethanol,
4 => Self::Diesel,
5 => Self::LPG,
6 => Self::CNG,
7 => Self::Propane,
8 => Self::Electric,
9 => Self::BifuelGasoline,
10 => Self::BifuelMethanol,
11 => Self::BifuelEthanol,
12 => Self::BifuelLPG,
13 => Self::BifuelCNG,
14 => Self::BifuelPropane,
15 => Self::BifuelElectricity,
16 => Self::BifuelElectricAndCombustion,
17 => Self::HybridGasoline,
18 => Self::HybridEthanol,
19 => Self::HybridDiesel,
20 => Self::HybridElectric,
21 => Self::HybridElectricAndCombustion,
22 => Self::HybridRegen,
23 => Self::BifuelDiesel,
_ => Self::Reserved(x),
}
}
}