1mod data_model; pub use data_model::{DataModel, DataStructure};
2
3use crate::common::{crc, exception::Exception, PacketError, RequestForm};
4
5
6#[derive(Debug)]
8pub struct ModbusSlave<const L1: usize, const L2: usize> {
9 modbus_id: u8,
15
16 holding_registers: DataModel<L1, u16>,
21
22 input_registers: DataModel<L2, u16>,
27}
28
29
30impl<'a, const L1: usize, const L2: usize> ModbusSlave<L1, L2> {
31 pub fn new(modbus_id: u8, holding_registers: DataModel<L1, u16>, input_registers: DataModel<L2, u16>) -> ModbusSlave<L1, L2> {
32 ModbusSlave { modbus_id, holding_registers, input_registers }
33 }
34
35 pub fn get_modbus_id(&self) -> u8 {
36 self.modbus_id
37 }
38
39 pub fn set_modbus_id(&mut self, modbus_id: u8) {
40 self.modbus_id = modbus_id;
41 }
42
43 pub fn get_holding_registers(&self) -> &DataModel<L1, u16> {
44 &self.holding_registers
45 }
46
47 pub fn get_holding_registers_mut(&mut self) -> &mut DataModel<L1, u16> {
48 &mut self.holding_registers
49 }
50
51 pub fn get_input_registers(&self) -> &DataModel<L2, u16> {
52 &self.input_registers
53 }
54
55 pub fn get_input_registers_mut(&mut self) -> &mut DataModel<L2, u16> {
56 &mut self.input_registers
57 }
58
59 pub fn analyze_packet(&self, packet: &[u8], word_buffer: &'a mut [u16]) -> Result<RequestForm<'a>, PacketError> {
60 let len = packet.len();
61
62 if len < 4 {
64 return Err(PacketError::TooShort(len));
65 }
66
67 crc::validate(packet)?;
69
70 if (self.modbus_id != 0x00) && (self.modbus_id != packet[0]) {
72 return Err(PacketError::NotMyId(packet[0]));
73 }
74
75 let fc = packet[1];
76 match fc {
77 0x03 => {
79 if self.holding_registers.is_empty() {
81 return Err(PacketError::Exeption(fc, Exception::IllegalFunction));
82 }
83
84 if len < 8 {
86 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
87 }
88
89 let start_register: u16 = ((packet[2] as u16) << 8) | (packet[3] as u16);
90 let registers_count: u16 = ((packet[4] as u16) << 8) | (packet[5] as u16);
91
92 let end_register: u16 = match start_register.checked_add(registers_count) {
94 Some(v) => v,
95 None => return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress)),
96 };
97
98 for adr in start_register..=end_register {
100 if let None = self.holding_registers.find_index(adr) {
101 return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress));
102 }
103 }
104
105 Ok(RequestForm::ReadHoldingRegisters { start_register, registers_count })
106 },
107
108 0x04 => {
110 if self.input_registers.is_empty() {
112 return Err(PacketError::Exeption(fc, Exception::IllegalFunction));
113 }
114
115 if len < 8 {
117 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
118 }
119
120 let start_register: u16 = ((packet[2] as u16) << 8) | (packet[3] as u16);
121 let registers_count: u16 = ((packet[4] as u16) << 8) | (packet[5] as u16);
122
123 let end_register: u16 = match start_register.checked_add(registers_count) {
125 Some(v) => v,
126 None => return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress)),
127 };
128
129 for adr in start_register..=end_register {
131 if let None = self.input_registers.find_index(adr) {
132 return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress));
133 }
134 }
135
136 Ok(RequestForm::ReadInputRegisters { start_register, registers_count })
137 },
138
139 0x06 => {
141 if self.holding_registers.is_empty() {
143 return Err(PacketError::Exeption(fc, Exception::IllegalFunction));
144 }
145
146 if len < 8 {
148 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
149 }
150
151 let register_address: u16 = ((packet[2] as u16) << 8) | (packet[3] as u16);
152 let data_to_write: u16 = ((packet[4] as u16) << 8) | (packet[5] as u16);
153
154 if let None = self.holding_registers.find_index(register_address) {
156 return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress));
157 }
158
159 Ok(RequestForm::WriteSingleRegister { register_address, data_to_write })
160 },
161
162 0x10 => {
164 if self.holding_registers.is_empty() {
166 return Err(PacketError::Exeption(fc, Exception::IllegalFunction));
167 }
168
169 if len < 9 {
171 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
172 }
173
174 let start_register: u16 = ((packet[2] as u16) << 8) | (packet[3] as u16);
175 let registers_count: u16 = ((packet[4] as u16) << 8) | (packet[5] as u16);
176 let bytes_count: u8 = packet[6];
177
178 if len < 9 + bytes_count as usize {
180 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
181 }
182
183 if bytes_count as u16 != registers_count.saturating_mul(2) {
185 return Err(PacketError::Exeption(fc, Exception::IllegalDataValue));
186 }
187
188 let end_register: u16 = match start_register.checked_add(registers_count) {
190 Some(v) => v,
191 None => return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress)),
192 };
193
194 for adr in start_register..=end_register {
196 if let None = self.holding_registers.find_index(adr) {
197 return Err(PacketError::Exeption(fc, Exception::IllegalDataAddress));
198 }
199 }
200
201 for i in 0..registers_count as usize {
203 word_buffer[i] = ((packet[7 + (i * 2) + 0] as u16) << 8) | (packet[7 + (i * 2) + 1] as u16);
204 }
205
206 Ok(RequestForm::WriteMultipleRegisters { start_register, data_to_write: &word_buffer[..registers_count as usize] })
207 },
208
209 #[cfg(feature="bypass")]
211 0x45 => {
212 todo!()
213 },
214 _ => return Err(PacketError::Exeption(fc, Exception::IllegalFunction)),
215 }
216 }
217
218 pub fn build_exception_response_packet(&self, fc: u8, exception: Exception) -> [u8; 5] {
219 let mut result: [u8; 5] = [
220 self.modbus_id,
221 fc | 0x80,
222 exception.into(),
223 0x00,
224 0x00,
225 ];
226
227 let crc_bytes = crc::gen_bytes(&result[..3]);
228 result[3..5].copy_from_slice(&crc_bytes);
229
230 result
231 }
232}