1use bitflags::bitflags;
3
4#[cfg(feature="serde")]
5use serde::{Serialize, Deserialize};
6
7#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
8#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
9pub enum DTCFormatType {
11 Iso15031_6,
13 Iso14229_1,
15 SaeJ1939_73,
17 Iso11992_4,
19 Unknown(u8),
21 TwoByteHexKwp,
23}
24
25pub(crate) fn dtc_format_from_uds(fmt: u8) -> DTCFormatType {
26 match fmt {
27 0x00 => DTCFormatType::Iso15031_6,
28 0x01 => DTCFormatType::Iso14229_1,
29 0x02 => DTCFormatType::SaeJ1939_73,
30 0x03 => DTCFormatType::Iso11992_4,
31 x => DTCFormatType::Unknown(x),
32 }
33}
34
35bitflags! {
36 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
38 #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
39 pub struct DtcStatusByte: u8 {
40 const TEST_FAILED = 0b00000001;
42 const TEST_FAILED_THIS_OPERATION_CYCLE = 0b00000010;
44 const PENDING_DTC = 0b00000100;
46 const CONFIRMED_DTC = 0b00001000;
48 const TEST_NOT_COMPLETED_SINCE_LAST_CLEAR = 0b00010000;
50 const TEST_FAILED_SINCE_LAST_CLEAR = 0b00100000;
52 const TEST_NOT_COMPLETED_THIS_OP_CYCLE = 0b01000000;
54 const WARNING_INDICATOR_REQUESTED = 0b10000000;
56 }
57}
58
59#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
61#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
62pub struct DTC {
63 pub format: DTCFormatType,
66 pub raw: u32,
68 pub status: DtcStatusByte,
70}
71
72impl DTC {
73 pub fn get_name_as_string(&self) -> String {
75 match self.format {
76 DTCFormatType::Iso15031_6 => {
77 let b0 = (self.raw >> 8) as u8;
79 let b1 = self.raw as u8;
80 let component_prefix = match b0 >> 6 {
81 0 => "P",
82 1 => "C",
83 2 => "B",
84 3 => "U",
85 _ => "N", };
87 format!(
88 "{}{:01X}{:01X}{:01X}{:01X}",
89 component_prefix,
90 ((b0 & 0x30) >> 4),
91 b0 & 0x0F,
92 b1 >> 4,
93 b1 & 0x0F
94 )
95 }
96 DTCFormatType::TwoByteHexKwp => {
97 let component_prefix = match (self.raw as u16 & 0b110000000000000) >> 14 {
98 0b00 => "P",
99 0b01 => "C",
100 0b10 => "B",
101 0b11 => "U",
102 _ => "", };
104 format!("{}{:04X}", component_prefix, self.raw & 0b11111111111111)
105 }
107 _ => format!("{}", self.raw),
108 }
109 }
110}
111
112#[cfg(test)]
113pub mod test {
114 use super::DTC;
115
116 #[test]
117 pub fn test_dtc_parse_raw() {
118 let iso15031_6_dtc = DTC {
119 format: super::DTCFormatType::Iso15031_6,
120 raw: 8276,
121 status: super::DtcStatusByte::empty()
122 };
123 println!("{:04X}", iso15031_6_dtc.raw);
124 println!("{}", iso15031_6_dtc.get_name_as_string());
125 }
126}