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]) -> 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 match packet[1] {
76 0x03 => {
77 if self.holding_registers.is_empty() {
78 return Err(PacketError::Exeption(packet[1], Exception::IllegalFunction));
79 }
80 todo!()
81 },
82 0x04 => {
83 if self.input_registers.is_empty() {
84 return Err(PacketError::Exeption(packet[1], Exception::IllegalFunction));
85 }
86 todo!()
87 },
88 0x06 => {
89 if self.holding_registers.is_empty() {
90 return Err(PacketError::Exeption(packet[1], Exception::IllegalFunction));
91 }
92 todo!()
93 },
94 0x10 => {
95 if self.holding_registers.is_empty() {
96 return Err(PacketError::Exeption(packet[1], Exception::IllegalFunction));
97 }
98 todo!()
99 },
100 #[cfg(feature="bypass")]
101 0x45 => {
102 todo!()
103 },
104 _ => return Err(PacketError::Exeption(packet[1], Exception::IllegalFunction)),
105 }
106 }
107
108 pub fn build_exception_response_packet(&self, fc: u8, exception: Exception) -> [u8; 5] {
109 let mut result: [u8; 5] = [
110 self.modbus_id,
111 fc | 0x80,
112 exception.into(),
113 0x00,
114 0x00,
115 ];
116
117 let crc_bytes = crc::gen_bytes(&result[..3]);
118 result[3..5].copy_from_slice(&crc_bytes);
119
120 result
121 }
122}