Skip to content

Commit 58a7517

Browse files
committed
0.97 - Update how DTC status is read for both UDS and KWP
1 parent 3f54649 commit 58a7517

4 files changed

Lines changed: 49 additions & 77 deletions

File tree

Cargo.toml

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ecu_diagnostics"
3-
version = "0.96.1"
3+
version = "0.97.0"
44
authors = ["Ashcon Mohseninia <ashconm@outlook.com>"]
55
edition = "2021"
66
description = "A rust crate for ECU diagnostic servers and communication APIs"
@@ -29,18 +29,19 @@ slcan = ["dep:serial-rs"]
2929

3030
[dependencies]
3131
#automotive_diag = { version = "0.1", path = "../automotive_diag" }
32-
automotive_diag = "0.1"
32+
automotive_diag = "0.1.11"
3333
j2534_rust = { version = "1.5.0", optional = true }
34-
serde_json = { version = "1.0.79", optional = true }
35-
libloading = { version = "0.8.4", optional = true }
36-
log="0.4.16"
37-
strum = "0.26.3"
38-
strum_macros = "0.26.4"
39-
thiserror="1.0.44"
34+
serde_json = { version = "1.0.140", optional = true }
35+
libloading = { version = "0.8.6", optional = true }
36+
log="0.4.27"
37+
strum = "0.27.1"
38+
strum_macros = "0.27.1"
39+
thiserror="2.0.12"
4040
serial-rs = { version = "0.2.1", optional = true }
41+
bitflags = "2.9.0"
4142

4243
[dev-dependencies]
43-
env_logger = "0.11.3"
44+
env_logger = "0.11.7"
4445

4546
[target.'cfg(windows)'.dependencies]
4647
winreg = { version = "0.10.1", optional = true }

src/dtc.rs

Lines changed: 23 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
//! Module for common Diagnostic trouble code data
2+
use bitflags::bitflags;
23

34
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
45
/// DTC name interpretation format specifier
@@ -27,33 +28,26 @@ pub(crate) fn dtc_format_from_uds(fmt: u8) -> DTCFormatType {
2728
}
2829
}
2930

30-
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
31-
/// Storage state of the DTC
32-
pub enum DTCStatus {
33-
/// No DTC is stored in non volatile memory
34-
None,
35-
/// DTC has not met criteria for it to become active or stored,
36-
/// but a failure condition has been met
37-
Pending,
38-
/// DTC is no longer present, but is stored in non volatile memory
39-
Stored,
40-
/// DTC is present and stored in non volatile memory
41-
Active,
42-
/// Permanent (Can NOT be cleared from the ECU!)
43-
Permanent,
44-
/// Unknown DTC Status
45-
Unknown(u8),
46-
}
47-
48-
impl DTCStatus {
49-
pub(crate) fn from_kwp_status(x: u8) -> DTCStatus {
50-
match (x & 0b01100000) >> 5 {
51-
0b00 => Self::None,
52-
0b01 => Self::Stored,
53-
0b10 => Self::Pending,
54-
0b11 => Self::Active,
55-
_ => Self::Unknown(x & 0b01100000), // Should never happen
56-
}
31+
bitflags! {
32+
/// DTC Status byte according to D.2 of ISO14229
33+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
34+
pub struct DtcStatusByte: u8 {
35+
/// Most recent check has failed
36+
const TEST_FAILED = 0b00000001;
37+
/// Test failed at any time in the most recent operation cycle
38+
const TEST_FAILED_THIS_OPERATION_CYCLE = 0b00000010;
39+
/// DTC is pending
40+
const PENDING_DTC = 0b00000100;
41+
/// DTC is stored
42+
const CONFIRMED_DTC = 0b00001000;
43+
/// DTC check has not been completed since cleared
44+
const TEST_NOT_COMPLETED_SINCE_LAST_CLEAR = 0b00010000;
45+
/// DTC failed since the last clear
46+
const TEST_FAILED_SINCE_LAST_CLEAR = 0b00100000;
47+
/// DTC check has not been completed this operation cycle
48+
const TEST_NOT_COMPLETED_THIS_OP_CYCLE = 0b01000000;
49+
/// Check engine lamp is requested
50+
const WARNING_INDICATOR_REQUESTED = 0b10000000;
5751
}
5852
}
5953

@@ -66,13 +60,7 @@ pub struct DTC {
6660
/// The raw value of the DTC according to the ECU
6761
pub raw: u32,
6862
/// Status of the DTC
69-
pub status: DTCStatus,
70-
/// Indication if the DTC turns on the MIL lamp (Malfunction indicator lamp).
71-
/// This usually means that the Check engine light is illuminated on the
72-
/// vehicles instrument cluster
73-
pub mil_on: bool,
74-
/// Indication if the DTC conditions have been met since the last clear.
75-
pub readiness_flag: bool,
63+
pub status: DtcStatusByte,
7664
}
7765

7866
impl DTC {
@@ -124,9 +112,7 @@ pub mod test {
124112
let iso15031_6_dtc = DTC {
125113
format: super::DTCFormatType::Iso15031_6,
126114
raw: 8276,
127-
status: super::DTCStatus::None,
128-
mil_on: false,
129-
readiness_flag: false,
115+
status: super::DtcStatusByte::empty()
130116
};
131117
println!("{:04X}", iso15031_6_dtc.raw);
132118
println!("{}", iso15031_6_dtc.get_name_as_string());

src/kwp2000/read_dtc_by_status.rs

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Functions for reading DTCs from ECU
22
33
use crate::{
4-
dtc::{DTCFormatType, DTCStatus, DTC},
4+
dtc::{DTCFormatType, DtcStatusByte, DTC},
55
dynamic_diag::DynamicDiagSession,
66
DiagError, DiagServerResult,
77
};
@@ -67,13 +67,11 @@ impl DynamicDiagSession {
6767
let mut ret: Vec<DTC> = Vec::with_capacity(num_dtcs as usize); // Pre-allocate
6868

6969
for x in (0..res.len()).step_by(3) {
70-
let status = res[x + 2];
70+
let status = DtcStatusByte::from_bits_retain( res[x + 2]);
7171
ret.push(DTC {
7272
format: DTCFormatType::Iso15031_6,
7373
raw: (res[x] as u32) << 8 | res[x + 1] as u32,
74-
status: DTCStatus::from_kwp_status(status),
75-
mil_on: status & 0b10000000 != 0,
76-
readiness_flag: status & 0b00010000 != 0,
74+
status: status,
7775
})
7876
}
7977
Ok(ret)
@@ -117,13 +115,11 @@ impl DynamicDiagSession {
117115
let mut ret: Vec<DTC> = Vec::with_capacity(num_dtcs as usize); // Pre-allocate
118116

119117
for x in (0..res.len()).step_by(3) {
120-
let status = res[x + 2];
118+
let status = DtcStatusByte::from_bits_retain( res[x + 2]);
121119
ret.push(DTC {
122120
format: DTCFormatType::TwoByteHexKwp,
123121
raw: (res[x] as u32) << 8 | res[x + 1] as u32,
124-
status: DTCStatus::from_kwp_status(status),
125-
mil_on: status & 0b10000000 != 0,
126-
readiness_flag: status & 0b00010000 != 0,
122+
status: status,
127123
})
128124
}
129125
Ok(ret)
@@ -152,13 +148,11 @@ impl DynamicDiagSession {
152148
}
153149

154150
for x in (0..res_bytes.len()).step_by(3) {
155-
let status = res_bytes[x + 2];
151+
let status = DtcStatusByte::from_bits_retain( res_bytes[x + 2]);
156152
res.push(DTC {
157153
format: DTCFormatType::TwoByteHexKwp,
158154
raw: (res_bytes[x] as u32) << 8 | res_bytes[x + 1] as u32,
159-
status: DTCStatus::from_kwp_status(status),
160-
mil_on: status & 0b10000000 != 0,
161-
readiness_flag: status & 0b00010000 != 0,
155+
status: status,
162156
})
163157
}
164158
match self.kwp_read_extended_supported_dtcs(range) {

src/uds/read_dtc_information.rs

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Provides methods to read and query DTCs on the ECU, as well as grabbing Env data about each DTC
22
33
use crate::{
4-
dtc::{self, DTCFormatType, DTCStatus, DTC},
4+
dtc::{self, DTCFormatType, DtcStatusByte, DTC},
55
dynamic_diag::DynamicDiagSession,
66
DiagError, DiagServerResult,
77
};
@@ -68,14 +68,11 @@ impl DynamicDiagSession {
6868
for x in (0..resp.len()).step_by(4) {
6969
let dtc_code: u32 =
7070
(resp[x] as u32) << 16 | (resp[x + 1] as u32) << 8 | resp[x + 2] as u32;
71-
let status = resp[x + 3];
72-
71+
let status: DtcStatusByte = DtcStatusByte::from_bits_retain(resp[x+3]);
7372
result.push(DTC {
7473
format: fmt,
7574
raw: dtc_code,
76-
status: DTCStatus::Unknown(status), // TODO
77-
mil_on: status & 0b10000000 != 0,
78-
readiness_flag: false,
75+
status: status,
7976
})
8077
}
8178

@@ -115,14 +112,12 @@ impl DynamicDiagSession {
115112
for x in (0..resp.len()).step_by(4) {
116113
let dtc_code: u32 =
117114
(resp[x] as u32) << 16 | (resp[x + 1] as u32) << 8 | resp[x + 2] as u32;
118-
let status = resp[x + 3];
115+
let status = DtcStatusByte::from_bits_retain(resp[x + 3]);
119116

120117
result.push(DTC {
121118
format: fmt,
122119
raw: dtc_code,
123-
status: DTCStatus::Unknown(status), // TODO
124-
mil_on: status & 0b10000000 != 0,
125-
readiness_flag: false,
120+
status: status,
126121
})
127122
}
128123
Ok(result)
@@ -221,14 +216,12 @@ impl DynamicDiagSession {
221216
for x in (0..resp.len()).step_by(4) {
222217
let dtc_code: u32 =
223218
(resp[x] as u32) << 16 | (resp[x + 1] as u32) << 8 | resp[x + 2] as u32;
224-
let status = resp[x + 3];
219+
let status = DtcStatusByte::from_bits_retain(resp[x + 3]);
225220

226221
result.push(DTC {
227222
format: fmt,
228223
raw: dtc_code,
229-
status: DTCStatus::Unknown(status), // TODO
230-
mil_on: status & 0b10000000 != 0,
231-
readiness_flag: false,
224+
status: status,
232225
})
233226
}
234227
Ok(result)
@@ -407,14 +400,12 @@ impl DynamicDiagSession {
407400
for x in (0..resp.len()).step_by(4) {
408401
let dtc_code: u32 =
409402
(resp[x] as u32) << 16 | (resp[x + 1] as u32) << 8 | resp[x + 2] as u32;
410-
let status = resp[x + 3];
403+
let status = DtcStatusByte::from_bits_retain(resp[x + 3]);
411404

412405
result.push(DTC {
413406
format: fmt,
414407
raw: dtc_code,
415-
status: DTCStatus::Unknown(status), // TODO
416-
mil_on: status & 0b10000000 != 0,
417-
readiness_flag: false,
408+
status: status,
418409
})
419410
}
420411
Ok(result)

0 commit comments

Comments
 (0)