#![allow(dead_code)]
use super::*;
use crate::uds::uds_definitions::SEND_RECEIVE_SID_OFFSET;
const READ_DATA_BY_IDENTIFIER_SID: u8 = 0x22;
#[derive(Debug, PartialEq)]
pub struct ReadDataByIdentifierResponse {
pub data_records: Vec<DataRecord>,
}
#[derive(Debug, PartialEq)]
pub struct DataRecord {
pub data_identifier: u16,
pub data: Vec<u8>,
}
impl UdsClient {
pub async fn read_data_by_identifier(&self, data_identifiers: &[u16]) -> EcuResponseResult {
if data_identifiers.len() == 1 {
return self
.read_single_data_by_identifier(data_identifiers[0])
.await;
}
let request = compose_read_data_by_identifier_request(data_identifiers);
let raw_response = self.send_and_receive(&request).await?;
parse_read_data_by_identifier_response(&raw_response)
}
async fn read_data_by_identifier_tuple(
&self,
data_identifiers_and_lengths: &[(u16, u32)],
) -> EcuResponseResult {
let mut data_identifiers = vec![];
for (i, _) in data_identifiers_and_lengths {
data_identifiers.push(*i);
}
let request: Vec<u8> = compose_read_data_by_identifier_request(&data_identifiers);
let response = self.send_and_receive(&request).await?;
parse_read_data_by_identifier_tuple_response(data_identifiers_and_lengths, &response)
}
async fn read_single_data_by_identifier(&self, data_identifier: u16) -> EcuResponseResult {
self.read_data_by_identifier_tuple(&[(data_identifier, u32::MAX)])
.await
}
}
fn compose_read_data_by_identifier_request(data_identifiers: &[u16]) -> Vec<u8> {
let mut request: Vec<u8> = vec![READ_DATA_BY_IDENTIFIER_SID];
for &i in data_identifiers {
let msb = (i >> 8) as u8;
request.push(msb);
let lsb = i as u8;
request.push(lsb);
}
request
}
fn parse_read_data_by_identifier_response(raw_response: &[u8]) -> EcuResponseResult {
let mut response_iter = raw_response.iter();
let sid = *response_iter.next().ok_or(UdsError::ResponseEmpty)?;
if sid != READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET {
return Err(UdsError::SidMismatch {
expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
received: sid,
raw_message: raw_response.to_vec(),
});
}
let ret = UdsResponse::ReadDataByIdentifier(DataFormat::Raw(raw_response[1..].to_vec()));
Ok(ret)
}
fn parse_read_data_by_identifier_tuple_response(
data_identifiers_and_lengths: &[(u16, u32)],
raw_response: &[u8],
) -> EcuResponseResult {
let mut response_iterator = raw_response.iter();
let sid = *response_iterator.next().ok_or(UdsError::InvalidLength {
raw_message: raw_response.to_vec(),
})?;
if sid != READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET {
return Err(UdsError::SidMismatch {
expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
received: sid,
raw_message: raw_response.to_vec(),
});
}
let mut data_records = Vec::new();
for &(did, len) in data_identifiers_and_lengths {
let msb = *response_iterator.next().ok_or(UdsError::InvalidLength {
raw_message: raw_response.to_vec(),
})?;
let lsb = *response_iterator.next().ok_or(UdsError::InvalidLength {
raw_message: raw_response.to_vec(),
})?;
let response_did = ((msb as u16) << 8) + (lsb as u16);
if did != response_did {
return Err(UdsError::DidMismatch {
expected: did,
received: response_did,
raw_message: raw_response.to_vec(),
});
}
let mut data_record: Vec<u8> = Vec::new();
if len != u32::MAX {
for _ in 0..len {
data_record.push(*response_iterator.next().ok_or(UdsError::InvalidLength {
raw_message: raw_response.to_vec(),
})?);
}
} else {
loop {
let next_element = response_iterator.next();
match next_element {
Some(&x) => data_record.push(x),
None => break,
}
}
}
let data_record = DataRecord {
data_identifier: response_did,
data: data_record,
};
data_records.push(data_record);
}
let read_data_by_identifier_response = ReadDataByIdentifierResponse { data_records };
let ret =
UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(read_data_by_identifier_response));
Ok(ret)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_ok_message() {
let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
let dummy_message = vec![
READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
0,
10,
0,
0,
20,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
];
let reference =
UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(ReadDataByIdentifierResponse {
data_records: vec![
DataRecord {
data_identifier: 10,
data: vec![0],
},
DataRecord {
data_identifier: 20,
data: vec![0, 0, 0, 0, 0, 1, 2, 3, 4, 5],
},
],
}));
let result = parse_read_data_by_identifier_tuple_response(
&data_identifiers_and_lengths,
&dummy_message,
);
assert_eq!(result, Ok(reference));
}
#[test]
fn test_did_mismatch() {
let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
let dummy_message = vec![
READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
0,
10,
0,
0,
21,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
];
let result = parse_read_data_by_identifier_tuple_response(
&data_identifiers_and_lengths,
&dummy_message,
);
assert_eq!(
result,
Err(UdsError::DidMismatch {
expected: 20,
received: 21,
raw_message: dummy_message
})
);
}
#[test]
fn test_sid_mismatch() {
let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
let dummy_message = vec![
READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET + 10,
0,
10,
0,
0,
20,
0,
0,
0,
0,
0,
1,
2,
3,
4,
5,
];
let result = parse_read_data_by_identifier_tuple_response(
&data_identifiers_and_lengths,
&dummy_message,
);
assert_eq!(
result,
Err(UdsError::SidMismatch {
expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
received: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET + 10,
raw_message: dummy_message,
})
);
}
#[test]
fn test_invalid_length_short() {
let data_identifiers_and_lengths = vec![(10, 1), (20, 10), (21, 0)];
let dummy_message = vec![
READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
0,
10,
0,
0,
20,
0,
0,
0,
0,
0,
1,
2,
3,
4,
0,
21,
];
let result = parse_read_data_by_identifier_tuple_response(
&data_identifiers_and_lengths,
&dummy_message,
);
assert_eq!(
result,
Err(UdsError::InvalidLength {
raw_message: dummy_message
})
);
}
#[test]
fn test_parse_with_zero_len() {
let data_identifiers_and_lengths = vec![(10, u32::MAX)];
let dummy_message = vec![
READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
0,
10,
32,
32,
21,
65,
9,
8,
7,
4,
];
let reference =
UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(ReadDataByIdentifierResponse {
data_records: vec![DataRecord {
data_identifier: 10,
data: vec![32, 32, 21, 65, 9, 8, 7, 4],
}],
}));
let result = parse_read_data_by_identifier_tuple_response(
&data_identifiers_and_lengths,
&dummy_message,
);
assert_eq!(result, Ok(reference));
}
#[test]
fn test_formulate_request() {
let data_identifiers = vec![0x10, 0x20, 0x30, 0x4320, 0x4200];
let result = compose_read_data_by_identifier_request(&data_identifiers);
let reference = vec![
READ_DATA_BY_IDENTIFIER_SID,
0x0,
0x10,
0x0,
0x20,
0x0,
0x30,
0x43,
0x20,
0x42,
0x00,
];
assert_eq!(result, reference);
}
}