///|
/// Common UDS service identifiers used by a diagnostic client.
pub enum UdsService {
DiagnosticSessionControl
EcuReset
ReadDataByIdentifier
WriteDataByIdentifier
ReadMemoryByAddress
WriteMemoryByAddress
RoutineControl
SecurityAccess
CommunicationControl
ClearDiagnosticInformation
ReadDtcInformation
RequestDownload
TransferData
RequestTransferExit
TesterPresent
}
///|
/// A diagnostic request represented as a CAN payload.
pub struct DiagnosticRequest {
service : UdsService
payload : Array[Byte]
}
///|
/// Build a session-control request.
pub fn session_control(session : Byte) -> DiagnosticRequest {
{ service: DiagnosticSessionControl, payload: [(16).to_byte(), session] }
}
///|
/// Build an ECU reset request.
pub fn ecu_reset(reset_type : Byte) -> DiagnosticRequest {
{ service: EcuReset, payload: [(17).to_byte(), reset_type] }
}
///|
/// Build a tester-present request.
pub fn tester_present(suppress_response? : Bool = false) -> DiagnosticRequest {
{
service: TesterPresent,
payload: [
(62).to_byte(),
if suppress_response {
(128).to_byte()
} else {
0
},
],
}
}
///|
/// Build a read-data-by-identifier request.
pub fn read_data(identifier : UInt) -> DiagnosticRequest {
{
service: ReadDataByIdentifier,
payload: [(34).to_byte(), (identifier >> 8).to_byte(), identifier.to_byte()],
}
}
///|
/// Return the service kind.
pub fn DiagnosticRequest::service(self : DiagnosticRequest) -> UdsService {
self.service
}
///|
/// Return a defensive copy of the UDS payload.
pub fn DiagnosticRequest::payload(self : DiagnosticRequest) -> Array[Byte] {
self.payload.copy()
}
///|
/// A response classification for a diagnostic exchange.
pub enum DiagnosticResponse {
Positive(Array[Byte])
Negative(code~ : Byte)
Malformed
}
///|
/// Decode a UDS response payload.
pub fn decode_response(
request : DiagnosticRequest,
payload : Array[Byte],
) -> DiagnosticResponse {
if payload.is_empty() {
return Malformed
}
let expected = match request.service {
DiagnosticSessionControl => 0x50
EcuReset => 0x51
ReadDataByIdentifier => 0x62
WriteDataByIdentifier => 0x6E
ReadMemoryByAddress => 0x63
WriteMemoryByAddress => 0x7D
RoutineControl => 0x71
SecurityAccess => 0x67
CommunicationControl => 0x68
ClearDiagnosticInformation => 0x54
ReadDtcInformation => 0x59
RequestDownload => 0x74
TransferData => 0x76
RequestTransferExit => 0x77
TesterPresent => 0x7E
}
if payload[0].to_int() == expected {
Positive(payload.copy())
} else if payload[0].to_int() == 127 && payload.length() >= 3 {
Negative(code=payload[2])
} else {
Malformed
}
}