rsiot/components_config/modbus_frame/
rtu_response.rs1use bytes::{Buf, Bytes, BytesMut};
2
3use super::{CRC_ALG, Error};
4
5pub struct RTUResponse {
7 pub address: u8,
9
10 pub data: Bytes,
12}
13
14impl RTUResponse {
15 pub fn parse(self) -> Result<BytesMut, Error> {
17 let mut frame: BytesMut = self.data.into();
18
19 let mut crc_packet = frame.split_off(frame.len() - 2);
20 let crc_packet: u16 = crc_packet.get_u16_le();
21 let crc_calculated = CRC_ALG.checksum(&frame);
22 if crc_packet != crc_calculated {
23 return Err(Error::CRCMismatch);
24 }
25
26 let address = frame.try_get_u8()?;
27 if address != self.address {
28 return Err(Error::AddressMismatch {
29 address_in_packet: address,
30 expected_address: self.address,
31 });
32 }
33
34 let _func_code = frame.try_get_u8()?;
35
36 let length = frame.try_get_u8()? as usize;
37 if length != frame.len() {
38 return Err(Error::LengthMismatch {
39 length_in_packet: length,
40 expected_length: frame.len(),
41 });
42 }
43
44 Ok(frame)
45 }
46}
47
48#[cfg(test)]
49mod tests {
50 use super::*;
51
52 use pretty_assertions::assert_eq;
53
54 #[test]
55 fn test() -> anyhow::Result<()> {
56 let data = vec![
57 0x01, 0x03, 0x16, 0x03, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x01, 0x39, 0x42, 0x38,
59 ];
60
61 let correct = Bytes::from(data[3..25].to_vec());
62
63 let test = RTUResponse {
64 address: 1,
65 data: Bytes::from_owner(data),
66 }
67 .parse()?;
68
69 assert_eq!(test, correct);
70
71 Ok(())
72 }
73}