rsiot/components_config/modbus_frame/
rtu_request.rs1use bytes::{BufMut, Bytes, BytesMut};
2
3use super::CRC_ALG;
4
5pub enum FunctionCode {
7 ReadCoils,
9
10 ReadDiscreteInputs,
12
13 ReadHoldingRegisters {
15 quantity: u16,
17 },
18
19 ReadInputRegisters,
21
22 WriteSingleCoil,
24
25 WriteSingleRegister {
27 value: u16,
29 },
30
31 WriteMultipleCoils,
33
34 WriteMultipleRegisters,
36}
37
38pub struct RTURequest {
40 pub address: u8,
42
43 pub start_address: u16,
45
46 pub function_code: FunctionCode,
48}
49
50impl RTURequest {
51 pub fn create(self) -> Bytes {
53 let mut buf = BytesMut::new();
54
55 buf.put_u8(self.address);
56
57 match self.function_code {
58 FunctionCode::ReadCoils => todo!(),
59 FunctionCode::ReadDiscreteInputs => todo!(),
60 FunctionCode::ReadHoldingRegisters { quantity } => {
61 buf.put_u8(0x03);
62 buf.put_u16(self.start_address);
63 buf.put_u16(quantity);
64 }
65 FunctionCode::ReadInputRegisters => todo!(),
66 FunctionCode::WriteSingleCoil => todo!(),
67 FunctionCode::WriteSingleRegister { value } => {
68 buf.put_u8(0x06);
69 buf.put_u16(self.start_address);
70 buf.put_u16(value);
71 }
72 FunctionCode::WriteMultipleCoils => todo!(),
73 FunctionCode::WriteMultipleRegisters => todo!(),
74 };
75
76 let checksum = CRC_ALG.checksum(&buf);
77 buf.put_u16_le(checksum);
78
79 buf.into()
80 }
81}
82
83#[cfg(test)]
84mod tests {
85
86 use super::*;
87
88 use pretty_assertions::assert_eq;
89
90 #[test]
91 fn test_read_holding_registers() {
92 let test = RTURequest {
93 address: 0x01,
94 start_address: 2000,
95 function_code: FunctionCode::ReadHoldingRegisters { quantity: 13 },
96 }
97 .create();
98
99 let correct = Bytes::from_static(&[0x01, 0x03, 0x07, 0xD0, 0x00, 0x0D, 0x84, 0x82]);
100
101 assert_eq!(test, correct);
102 }
103}