rusty_modbus_codec/request/
device_id.rs1use rusty_modbus_types::{DeviceIdCode, FunctionCode, MeiType};
4
5use crate::error::{DecodeError, EncodeError};
6use crate::request::Encode;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
12pub struct ReadDeviceIdentificationRequest {
13 pub device_id_code: DeviceIdCode,
15 pub object_id: u8,
17}
18
19impl ReadDeviceIdentificationRequest {
20 pub fn decode(data: &[u8]) -> Result<Self, DecodeError> {
31 DecodeError::check_exact_len(data, 3)?;
32 if data[0] != MeiType::ReadDeviceIdentification.code() {
33 return Err(DecodeError::UnknownMeiType(data[0]));
34 }
35 let device_id_code =
36 DeviceIdCode::from_raw(data[1]).ok_or(DecodeError::InvalidDeviceIdCode(data[1]))?;
37 let object_id = data[2];
38 Ok(Self {
39 device_id_code,
40 object_id,
41 })
42 }
43}
44
45impl Encode for ReadDeviceIdentificationRequest {
46 fn encode_into(&self, buf: &mut [u8]) -> Result<usize, EncodeError> {
47 let len = self.encoded_len();
48 if buf.len() < len {
49 return Err(EncodeError::BufferTooSmall {
50 required: len,
51 available: buf.len(),
52 });
53 }
54 EncodeError::check_pdu_len(len)?;
55 buf[0] = FunctionCode::EncapsulatedInterfaceTransport.code();
56 buf[1] = MeiType::ReadDeviceIdentification.code();
57 buf[2] = self.device_id_code.code();
58 buf[3] = self.object_id;
59 Ok(len)
60 }
61
62 fn encoded_len(&self) -> usize {
63 4 }
65}
66
67#[cfg(test)]
68mod tests {
69 use super::*;
70
71 #[test]
72 fn encode_basic_stream_request() {
73 let req = ReadDeviceIdentificationRequest {
74 device_id_code: DeviceIdCode::BasicStream,
75 object_id: 0x00,
76 };
77 let mut buf = [0u8; 5];
78 let len = req.encode_into(&mut buf).unwrap();
79 assert_eq!(&buf[..len], &[0x2B, 0x0E, 0x01, 0x00]);
80 }
81
82 #[test]
83 fn decode_basic_stream_request() {
84 let data = [0x0E, 0x01, 0x00];
85 let req = ReadDeviceIdentificationRequest::decode(&data).unwrap();
86 assert_eq!(req.device_id_code, DeviceIdCode::BasicStream);
87 assert_eq!(req.object_id, 0x00);
88 }
89
90 #[test]
91 fn decode_individual_request() {
92 let data = [0x0E, 0x04, 0x03];
93 let req = ReadDeviceIdentificationRequest::decode(&data).unwrap();
94 assert_eq!(req.device_id_code, DeviceIdCode::Individual);
95 assert_eq!(req.object_id, 0x03);
96 }
97
98 #[test]
99 fn decode_wrong_mei_type() {
100 let data = [0x0D, 0x01, 0x00];
101 assert!(matches!(
102 ReadDeviceIdentificationRequest::decode(&data),
103 Err(DecodeError::UnknownMeiType(0x0D))
104 ));
105 }
106
107 #[test]
108 fn decode_invalid_device_id_code() {
109 let data = [0x0E, 0xFF, 0x00];
110 assert!(matches!(
111 ReadDeviceIdentificationRequest::decode(&data),
112 Err(DecodeError::InvalidDeviceIdCode(0xFF))
113 ));
114 }
115
116 #[test]
117 fn decode_truncated() {
118 let data = [0x0E, 0x01];
119 assert!(matches!(
120 ReadDeviceIdentificationRequest::decode(&data),
121 Err(DecodeError::Truncated { .. })
122 ));
123 }
124}