1use std::sync::{Arc, RwLock};
14
15use async_trait::async_trait;
16
17use crate::frame::{Exception, Request, Response};
18use crate::server::Service;
19
20const DEFAULT_REG_COUNT: usize = 1024;
22pub struct SlaveStore {
42 coils: RwLock<Vec<u8>>,
43 discrete_inputs: RwLock<Vec<u8>>,
44 holding_registers: RwLock<Vec<u16>>,
45 input_registers: RwLock<Vec<u16>>,
46}
47
48impl Default for SlaveStore {
49 fn default() -> Self {
50 Self {
51 coils: RwLock::new(vec![0u8; DEFAULT_REG_COUNT / 8]),
52 discrete_inputs: RwLock::new(vec![0u8; DEFAULT_REG_COUNT / 8]),
53 holding_registers: RwLock::new(vec![0u16; DEFAULT_REG_COUNT]),
54 input_registers: RwLock::new(vec![0u16; DEFAULT_REG_COUNT]),
55 }
56 }
57}
58
59impl SlaveStore {
60 pub fn new() -> Self {
62 Self::default()
63 }
64
65 pub fn with_holding_registers(regs: &[(u16, u16)]) -> Self {
68 let store = Self::new();
69 let max_addr = regs.iter().map(|&(a, _)| a as usize).max().unwrap_or(0);
70 {
71 let mut hr = store
72 .holding_registers
73 .write()
74 .unwrap_or_else(|e| e.into_inner());
75 if hr.len() <= max_addr {
76 hr.resize(max_addr + 1, 0);
77 }
78 for &(addr, val) in regs {
79 hr[addr as usize] = val;
80 }
81 }
82 store
83 }
84
85 fn read_bit(lock: &RwLock<Vec<u8>>, addr: u16) -> bool {
89 let bytes = lock.read().unwrap_or_else(|e| e.into_inner());
90 let byte_idx = addr as usize / 8;
91 let bit_idx = addr as usize % 8;
92 bytes
93 .get(byte_idx)
94 .map(|b| (b >> bit_idx) & 1 != 0)
95 .unwrap_or(false)
96 }
97
98 fn write_bit(lock: &RwLock<Vec<u8>>, addr: u16, value: bool) {
100 let mut bytes = lock.write().unwrap_or_else(|e| e.into_inner());
101 let byte_idx = addr as usize / 8;
102 if byte_idx >= bytes.len() {
103 bytes.resize(byte_idx + 1, 0);
104 }
105 if value {
106 bytes[byte_idx] |= 1 << (addr as usize % 8);
107 } else {
108 bytes[byte_idx] &= !(1 << (addr as usize % 8));
109 }
110 }
111
112 fn read_bits(lock: &RwLock<Vec<u8>>, addr: u16, count: u16) -> Vec<bool> {
115 let bytes = lock.read().unwrap_or_else(|e| e.into_inner());
116 let mut result = Vec::with_capacity(count as usize);
117 for i in 0..count {
118 let a = addr as usize + i as usize;
119 let byte_idx = a / 8;
120 let bit_idx = a % 8;
121 result.push(
122 bytes
123 .get(byte_idx)
124 .map(|b| (b >> bit_idx) & 1 != 0)
125 .unwrap_or(false),
126 );
127 }
128 result
129 }
130
131 fn read_registers(lock: &RwLock<Vec<u16>>, addr: u16, count: u16) -> Vec<u16> {
133 let regs = lock.read().unwrap_or_else(|e| e.into_inner());
134 let start = addr as usize;
135 if start >= regs.len() {
136 return vec![0u16; count as usize];
137 }
138 let end = (start + count as usize).min(regs.len());
139 let mut result = vec![0u16; count as usize];
140 result[..end - start].copy_from_slice(®s[start..end]);
141 result
142 }
143
144 fn write_register(lock: &RwLock<Vec<u16>>, addr: u16, value: u16) {
146 let mut regs = lock.write().unwrap_or_else(|e| e.into_inner());
147 if addr as usize >= regs.len() {
148 regs.resize(addr as usize + 1, 0);
149 }
150 regs[addr as usize] = value;
151 }
152
153 pub fn read_coil(&self, addr: u16) -> bool {
157 Self::read_bit(&self.coils, addr)
158 }
159
160 pub fn write_coil(&self, addr: u16, value: bool) {
162 Self::write_bit(&self.coils, addr, value);
163 }
164
165 pub fn read_coils_range(&self, addr: u16, count: u16) -> Vec<bool> {
167 Self::read_bits(&self.coils, addr, count)
168 }
169
170 pub fn read_discrete_input(&self, addr: u16) -> bool {
174 Self::read_bit(&self.discrete_inputs, addr)
175 }
176
177 pub fn write_discrete_input(&self, addr: u16, value: bool) {
181 Self::write_bit(&self.discrete_inputs, addr, value);
182 }
183
184 pub fn read_discrete_inputs_range(&self, addr: u16, count: u16) -> Vec<bool> {
186 Self::read_bits(&self.discrete_inputs, addr, count)
187 }
188
189 pub fn read_holding_register(&self, addr: u16) -> u16 {
193 let hr = self
194 .holding_registers
195 .read()
196 .unwrap_or_else(|e| e.into_inner());
197 hr.get(addr as usize).copied().unwrap_or(0)
198 }
199
200 pub fn read_holding_range(&self, addr: u16, count: u16) -> Vec<u16> {
202 Self::read_registers(&self.holding_registers, addr, count)
203 }
204
205 pub fn write_holding_register(&self, addr: u16, value: u16) {
207 Self::write_register(&self.holding_registers, addr, value);
208 }
209
210 pub fn read_input_register(&self, addr: u16) -> u16 {
214 let ir = self
215 .input_registers
216 .read()
217 .unwrap_or_else(|e| e.into_inner());
218 ir.get(addr as usize).copied().unwrap_or(0)
219 }
220
221 pub fn read_input_range(&self, addr: u16, count: u16) -> Vec<u16> {
223 Self::read_registers(&self.input_registers, addr, count)
224 }
225
226 pub fn write_input_register(&self, addr: u16, value: u16) {
230 Self::write_register(&self.input_registers, addr, value);
231 }
232}
233
234#[async_trait]
235impl Service for Arc<SlaveStore> {
236 async fn call(&self, request: Request<'_>) -> Result<Response, Exception> {
237 let store = self.as_ref();
238 Ok(match request {
239 Request::ReadCoils(addr, cnt) => Response::ReadCoils(store.read_coils_range(addr, cnt)),
240 Request::ReadDiscreteInputs(addr, cnt) => {
241 Response::ReadDiscreteInputs(store.read_discrete_inputs_range(addr, cnt))
242 }
243 Request::ReadHoldingRegisters(addr, cnt) => {
244 Response::ReadHoldingRegisters(store.read_holding_range(addr, cnt))
245 }
246 Request::ReadInputRegisters(addr, cnt) => {
247 Response::ReadInputRegisters(store.read_input_range(addr, cnt))
248 }
249 Request::WriteSingleCoil(addr, value) => {
250 store.write_coil(addr, value);
251 Response::WriteSingleCoil(addr, value)
252 }
253 Request::WriteSingleRegister(addr, value) => {
254 store.write_holding_register(addr, value);
255 Response::WriteSingleRegister(addr, value)
256 }
257 Request::WriteMultipleCoils(addr, values) => {
258 let mut coils = store.coils.write().unwrap_or_else(|e| e.into_inner());
260 for (i, &v) in values.iter().enumerate() {
261 let a = addr as usize + i;
262 let byte_idx = a / 8;
263 let bit_idx = a % 8;
264 if byte_idx >= coils.len() {
265 coils.resize(byte_idx + 1, 0);
266 }
267 if v {
268 coils[byte_idx] |= 1 << bit_idx;
269 } else {
270 coils[byte_idx] &= !(1 << bit_idx);
271 }
272 }
273 drop(coils);
274 Response::WriteMultipleCoils(addr, values.len() as u16)
275 }
276 Request::WriteMultipleRegisters(addr, values) => {
277 let mut hr = store
279 .holding_registers
280 .write()
281 .unwrap_or_else(|e| e.into_inner());
282 for (i, &v) in values.iter().enumerate() {
283 let a = addr as usize + i;
284 if a >= hr.len() {
285 hr.resize(a + 1, 0);
286 }
287 hr[a] = v;
288 }
289 drop(hr);
290 Response::WriteMultipleRegisters(addr, values.len() as u16)
291 }
292 Request::MaskWriteRegister(addr, and_mask, or_mask) => {
293 let mut hr = store
295 .holding_registers
296 .write()
297 .unwrap_or_else(|e| e.into_inner());
298 let a = addr as usize;
299 if a >= hr.len() {
300 hr.resize(a + 1, 0);
301 }
302 let current = hr[a];
303 hr[a] = (current & and_mask) | (or_mask & !and_mask);
304 Response::MaskWriteRegister(addr, and_mask, or_mask)
305 }
306 Request::ReadWriteMultipleRegisters(read_addr, read_qty, write_addr, values) => {
307 let regs = store.read_holding_range(read_addr, read_qty);
314 let mut hr = store
316 .holding_registers
317 .write()
318 .unwrap_or_else(|e| e.into_inner());
319 for (i, &v) in values.iter().enumerate() {
320 let a = write_addr as usize + i;
321 if a >= hr.len() {
322 hr.resize(a + 1, 0);
323 }
324 hr[a] = v;
325 }
326 drop(hr);
327 Response::ReadWriteMultipleRegisters(regs)
328 }
329 Request::Diagnostic(sf, data) => {
330 match sf {
331 0x0000 => Response::Diagnostic(sf, data),
333 0x000A => Response::Diagnostic(sf, 0x0000),
335 0x000B..=0x000E => Response::Diagnostic(sf, 0x0000),
337 _ => return Err(Exception::IllegalDataValue),
338 }
339 }
340 _ => return Err(Exception::IllegalFunction),
341 })
342 }
343}