uds_rs/uds/
read_data_by_identifier.rs

1#![allow(dead_code)]
2
3//! # Implementation of ReadDataByIdentifier 0x22 service
4//!
5//! This service provides following methods for UdsClient:
6//!
7//! [UdsClient::read_data_by_identifier]
8//!
9//! Problem with [UdsClient::read_data_by_identifier] is that there can be multiple identifiers and multiple
10//! responses in single message. Response needs apriori information about the size of each data_record.
11//!
12//! Can be solved by only allowing one data identifier per message -> then the data len is
13//! arbitrary, implemented in [UdsClient::read_single_data_by_identifier].
14//!
15//! Other approach is to provide lengths of each data - that is implemented in [UdsClient::read_data_by_identifier_tuple]
16//!
17//! If [UdsClient::read_data_by_identifier] is used with multiple data identifiers, the unparsed response is returned
18//!
19use super::*;
20use crate::uds::uds_definitions::SEND_RECEIVE_SID_OFFSET;
21
22const READ_DATA_BY_IDENTIFIER_SID: u8 = 0x22;
23
24/// Response of all read_data_by_identifier methods
25#[derive(Debug, PartialEq)]
26pub struct ReadDataByIdentifierResponse {
27    data_records: Vec<DataRecord>,
28}
29
30/// Single response entry
31#[derive(Debug, PartialEq)]
32pub struct DataRecord {
33    data_identifier: u16,
34    data: Vec<u8>,
35}
36
37impl UdsClient {
38    pub async fn read_data_by_identifier(&self, data_identifiers: &[u16]) -> EcuResponseResult {
39        if data_identifiers.len() == 1 {
40            return self
41                .read_single_data_by_identifier(data_identifiers[0])
42                .await;
43        }
44        let request = compose_read_data_by_identifier_request(data_identifiers);
45        let raw_response = self.send_and_receive(&request).await?;
46        let response = parse_read_data_by_identifier_response(&raw_response);
47        response
48    }
49    /// Method takes slice of tuples, first element stands for data identifier and second for
50    /// data length. Do not like adding another Struct just for this.
51    // TODO maybe not so strict checking is in order - the absence of requested data should only trigger warning
52    async fn read_data_by_identifier_tuple(
53        &self,
54        data_identifiers_and_lengths: &[(u16, u32)],
55    ) -> EcuResponseResult {
56        let mut data_identifiers = vec![];
57        for (i, _) in data_identifiers_and_lengths {
58            data_identifiers.push(*i);
59        }
60        let request: Vec<u8> = compose_read_data_by_identifier_request(&data_identifiers);
61        let response = self.send_and_receive(&request).await?;
62        let parsed_response =
63            parse_read_data_by_identifier_tuple_response(data_identifiers_and_lengths, &response);
64        return parsed_response;
65    }
66
67    async fn read_single_data_by_identifier(&self, data_identifier: u16) -> EcuResponseResult {
68        self.read_data_by_identifier_tuple(&[(data_identifier, u32::MAX)])
69            .await
70    }
71}
72
73fn compose_read_data_by_identifier_request(data_identifiers: &[u16]) -> Vec<u8> {
74    let mut request: Vec<u8> = vec![READ_DATA_BY_IDENTIFIER_SID];
75    for &i in data_identifiers {
76        let msb = (i >> 8) as u8;
77        request.push(msb);
78        let lsb = i as u8;
79        request.push(lsb);
80    }
81    return request;
82}
83
84fn parse_read_data_by_identifier_response(raw_response: &[u8]) -> EcuResponseResult {
85    let mut response_iter = raw_response.iter();
86    let sid = *response_iter.next().ok_or(UdsError::ResponseEmpty)?;
87    if sid != READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET {
88        return Err(UdsError::SidMismatch {
89            expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
90            received: sid,
91            raw_message: raw_response.to_vec(),
92        });
93    }
94    let ret = UdsResponse::ReadDataByIdentifier(DataFormat::Raw(raw_response[1..].to_vec()));
95    Ok(ret)
96}
97
98/// When u32::MAX is passed as data len, it reads the whole message - should be used only with single
99/// data identifier.
100fn parse_read_data_by_identifier_tuple_response(
101    data_identifiers_and_lengths: &[(u16, u32)],
102    raw_response: &[u8],
103) -> EcuResponseResult {
104    let mut response_iterator = raw_response.iter();
105    let sid = *response_iterator.next().ok_or(UdsError::InvalidLength {
106        raw_message: raw_response.to_vec(),
107    })?;
108
109    if sid != READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET {
110        return Err(UdsError::SidMismatch {
111            expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
112            received: sid,
113            raw_message: raw_response.to_vec(),
114        });
115    }
116
117    let mut data_records = Vec::new();
118
119    for &(did, len) in data_identifiers_and_lengths {
120        let msb = *response_iterator.next().ok_or(UdsError::InvalidLength {
121            raw_message: raw_response.to_vec(),
122        })?;
123        let lsb = *response_iterator.next().ok_or(UdsError::InvalidLength {
124            raw_message: raw_response.to_vec(),
125        })?;
126        let response_did = ((msb as u16) << 8) + (lsb as u16);
127
128        if did != response_did {
129            return Err(UdsError::DidMismatch {
130                expected: did,
131                received: response_did,
132                raw_message: raw_response.to_vec(),
133            });
134        }
135        let mut data_record: Vec<u8> = Vec::new();
136        if len != u32::MAX {
137            for _ in 0..len {
138                data_record.push(*response_iterator.next().ok_or(UdsError::InvalidLength {
139                    raw_message: raw_response.to_vec(),
140                })?);
141            }
142        } else {
143            loop {
144                let next_element = response_iterator.next();
145                match next_element {
146                    Some(&x) => data_record.push(x),
147                    None => break,
148                }
149            }
150        }
151
152        let data_record = DataRecord {
153            data_identifier: response_did,
154            data: data_record,
155        };
156        data_records.push(data_record);
157    }
158    // Do I care if there are some bytes left in the message? I would say yes and should throw
159    // en error (or maybe a warning?)
160
161    let read_data_by_identifier_response = ReadDataByIdentifierResponse { data_records };
162
163    let ret =
164        UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(read_data_by_identifier_response));
165    return Ok(ret);
166}
167#[cfg(test)]
168mod tests {
169    use super::*;
170
171    #[test]
172    fn test_ok_message() {
173        let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
174        let dummy_message = vec![
175            READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
176            0,
177            10,
178            0,
179            0,
180            20,
181            0,
182            0,
183            0,
184            0,
185            0,
186            1,
187            2,
188            3,
189            4,
190            5,
191        ];
192
193        let reference =
194            UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(ReadDataByIdentifierResponse {
195                data_records: vec![
196                    DataRecord {
197                        data_identifier: 10,
198                        data: vec![0],
199                    },
200                    DataRecord {
201                        data_identifier: 20,
202                        data: vec![0, 0, 0, 0, 0, 1, 2, 3, 4, 5],
203                    },
204                ],
205            }));
206
207        let result = parse_read_data_by_identifier_tuple_response(
208            &data_identifiers_and_lengths,
209            &dummy_message,
210        );
211        assert_eq!(result, Ok(reference));
212    }
213    #[test]
214    fn test_did_mismatch() {
215        let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
216        let dummy_message = vec![
217            READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
218            0,
219            10,
220            0,
221            0,
222            21,
223            0,
224            0,
225            0,
226            0,
227            0,
228            1,
229            2,
230            3,
231            4,
232            5,
233        ];
234
235        let result = parse_read_data_by_identifier_tuple_response(
236            &data_identifiers_and_lengths,
237            &dummy_message,
238        );
239        assert_eq!(
240            result,
241            Err(UdsError::DidMismatch {
242                expected: 20,
243                received: 21,
244                raw_message: dummy_message
245            })
246        );
247    }
248    #[test]
249    fn test_sid_mismatch() {
250        let data_identifiers_and_lengths = vec![(10, 1), (20, 10)];
251        let dummy_message = vec![
252            READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET + 10,
253            0,
254            10,
255            0,
256            0,
257            20,
258            0,
259            0,
260            0,
261            0,
262            0,
263            1,
264            2,
265            3,
266            4,
267            5,
268        ];
269
270        let result = parse_read_data_by_identifier_tuple_response(
271            &data_identifiers_and_lengths,
272            &dummy_message,
273        );
274        assert_eq!(
275            result,
276            Err(UdsError::SidMismatch {
277                expected: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
278                received: READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET + 10,
279                raw_message: dummy_message,
280            })
281        );
282    }
283    #[test]
284    fn test_invalid_length_short() {
285        let data_identifiers_and_lengths = vec![(10, 1), (20, 10), (21, 0)];
286        let dummy_message = vec![
287            READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
288            0,
289            10,
290            0,
291            0,
292            20,
293            0,
294            0,
295            0,
296            0,
297            0,
298            1,
299            2,
300            3,
301            4,
302            0,
303            21,
304        ];
305
306        let result = parse_read_data_by_identifier_tuple_response(
307            &data_identifiers_and_lengths,
308            &dummy_message,
309        );
310        assert_eq!(
311            result,
312            Err(UdsError::InvalidLength {
313                raw_message: dummy_message
314            })
315        );
316    }
317    #[test]
318    fn test_parse_with_zero_len() {
319        let data_identifiers_and_lengths = vec![(10, u32::MAX)];
320        let dummy_message = vec![
321            READ_DATA_BY_IDENTIFIER_SID + SEND_RECEIVE_SID_OFFSET,
322            0,
323            10,
324            32,
325            32,
326            21,
327            65,
328            9,
329            8,
330            7,
331            4,
332        ];
333
334        let reference =
335            UdsResponse::ReadDataByIdentifier(DataFormat::Parsed(ReadDataByIdentifierResponse {
336                data_records: vec![DataRecord {
337                    data_identifier: 10,
338                    data: vec![32, 32, 21, 65, 9, 8, 7, 4],
339                }],
340            }));
341
342        let result = parse_read_data_by_identifier_tuple_response(
343            &data_identifiers_and_lengths,
344            &dummy_message,
345        );
346        assert_eq!(result, Ok(reference));
347    }
348    #[test]
349    fn test_formulate_request() {
350        let data_identifiers = vec![0x10, 0x20, 0x30, 0x4320, 0x4200];
351        let result = compose_read_data_by_identifier_request(&data_identifiers);
352        let reference = vec![
353            READ_DATA_BY_IDENTIFIER_SID,
354            0x0,
355            0x10,
356            0x0,
357            0x20,
358            0x0,
359            0x30,
360            0x43,
361            0x20,
362            0x42,
363            0x00,
364        ];
365        assert_eq!(result, reference);
366    }
367}