1use std::fmt;
2use std::fmt::Formatter;
3
4use bytes::{BufMut, BytesMut};
5
6use crate::frame::Version::Rtu;
7use crate::util::crc;
8
9use super::{Head, Length};
10
11#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum Request {
14 ReadCoils(Head, ReadCoilsRequest),
15 ReadDiscreteInputs(Head, ReadDiscreteInputsRequest),
16 ReadMultipleHoldingRegisters(Head, ReadMultipleHoldingRegistersRequest),
17 ReadInputRegisters(Head, ReadInputRegistersRequest),
18 WriteSingleCoil(Head, WriteSingleCoilRequest),
19 WriteSingleHoldingRegister(Head, WriteSingleHoldingRegisterRequest),
20 WriteMultipleCoils(Head, WriteMultipleCoilsRequest),
21 WriteMultipleHoldingRegisters(Head, WriteMultipleHoldingRegistersRequest),
22}
23
24impl fmt::Display for Request {
25 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26 let mut buf = BytesMut::with_capacity(64);
27 request_to_bytesmut(self.clone(), &mut buf);
28 let mut first = true;
29 for byte in buf {
30 if !first {
31 write!(f, " ")?;
32 }
33 write!(f, "{:02X}", byte)?;
34 first = false;
35 }
36 Ok(())
37 }
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
42pub struct ReadCoilsRequest {
43 pub(crate) first_address: u16,
45
46 pub(crate) coils_number: u16,
51}
52
53impl Length for ReadCoilsRequest {
54 fn len(&self) -> u16 {
55 4
56 }
57}
58
59impl ReadCoilsRequest {
60 pub(crate) fn new(first_address: u16, coils_number: u16) -> ReadCoilsRequest {
61 ReadCoilsRequest {
62 first_address,
63 coils_number,
64 }
65 }
66}
67
68#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
70pub struct ReadDiscreteInputsRequest {
71 pub(crate) first_address: u16,
73
74 pub(crate) discrete_inputs_number: u16,
79}
80
81impl Length for ReadDiscreteInputsRequest {
82 fn len(&self) -> u16 {
83 4
84 }
85}
86
87impl ReadDiscreteInputsRequest {
88 pub(crate) fn new(
89 first_address: u16,
90 discrete_inputs_number: u16,
91 ) -> ReadDiscreteInputsRequest {
92 ReadDiscreteInputsRequest {
93 first_address,
94 discrete_inputs_number,
95 }
96 }
97
98 pub fn get_first_address(&self) -> &u16 {
99 &self.first_address
100 }
101
102 pub fn get_discrete_input_number(&self) -> &u16 {
103 &self.discrete_inputs_number
104 }
105}
106
107#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
109pub struct ReadMultipleHoldingRegistersRequest {
110 pub(crate) first_address: u16,
112
113 pub(crate) registers_number: u16,
118}
119
120impl Length for ReadMultipleHoldingRegistersRequest {
121 fn len(&self) -> u16 {
122 4
123 }
124}
125
126impl ReadMultipleHoldingRegistersRequest {
127 pub(crate) fn new(
128 first_address: u16,
129 registers_number: u16,
130 ) -> ReadMultipleHoldingRegistersRequest {
131 ReadMultipleHoldingRegistersRequest {
132 first_address,
133 registers_number,
134 }
135 }
136
137 pub fn get_first_address(&self) -> &u16 {
138 &self.first_address
139 }
140
141 pub fn get_registers_number(&self) -> &u16 {
142 &self.registers_number
143 }
144}
145
146#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
148pub struct ReadInputRegistersRequest {
149 pub(crate) first_address: u16,
151
152 pub(crate) registers_number: u16,
157}
158
159impl Length for ReadInputRegistersRequest {
160 fn len(&self) -> u16 {
161 4
162 }
163}
164
165impl ReadInputRegistersRequest {
166 pub(crate) fn new(first_address: u16, registers_number: u16) -> ReadInputRegistersRequest {
167 ReadInputRegistersRequest {
168 first_address,
169 registers_number,
170 }
171 }
172
173 pub fn get_first_address(&self) -> &u16 {
174 &self.first_address
175 }
176
177 pub fn get_registers_number(&self) -> &u16 {
178 &self.registers_number
179 }
180}
181
182#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
184pub struct WriteSingleCoilRequest {
185 pub(crate) coil_address: u16,
187
188 pub(crate) value: u16,
192}
193
194impl Length for WriteSingleCoilRequest {
195 fn len(&self) -> u16 {
196 4
197 }
198}
199
200impl WriteSingleCoilRequest {
201 pub(crate) fn new(coil_address: u16, value: u16) -> WriteSingleCoilRequest {
202 WriteSingleCoilRequest {
203 coil_address,
204 value,
205 }
206 }
207
208 pub fn get_coil_address(&self) -> &u16 {
209 &self.coil_address
210 }
211
212 pub fn get_value(&self) -> &u16 {
213 &self.value
214 }
215}
216
217#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
219pub struct WriteSingleHoldingRegisterRequest {
220 pub(crate) register_address: u16,
222
223 pub(crate) value: u16,
225}
226
227impl Length for WriteSingleHoldingRegisterRequest {
228 fn len(&self) -> u16 {
229 4
230 }
231}
232
233impl WriteSingleHoldingRegisterRequest {
234 pub(crate) fn new(register_address: u16, value: u16) -> WriteSingleHoldingRegisterRequest {
235 WriteSingleHoldingRegisterRequest {
236 register_address,
237 value,
238 }
239 }
240
241 pub fn get_register_address(&self) -> &u16 {
242 &self.register_address
243 }
244
245 pub fn get_value(&self) -> &u16 {
246 &self.value
247 }
248}
249
250#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
252pub struct WriteMultipleCoilsRequest {
253 pub(crate) first_address: u16,
257
258 pub(crate) coils_number: u16,
260
261 pub(crate) bytes_number: u8,
266
267 pub(crate) values: Vec<u8>,
271}
272
273impl Length for WriteMultipleCoilsRequest {
274 fn len(&self) -> u16 {
275 5 + self.values.len() as u16
276 }
277}
278
279impl WriteMultipleCoilsRequest {
280 pub(crate) fn new(
281 first_address: u16,
282 coils_number: u16,
283 values: Vec<u8>,
284 ) -> WriteMultipleCoilsRequest {
285 WriteMultipleCoilsRequest {
286 first_address,
287 coils_number,
288 bytes_number: values.len() as u8,
289 values,
290 }
291 }
292
293 pub fn first_address(&self) -> &u16 {
294 &self.first_address
295 }
296
297 pub fn coils_number(&self) -> &u16 {
298 &self.coils_number
299 }
300}
301
302#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
304pub struct WriteMultipleHoldingRegistersRequest {
305 pub(crate) first_address: u16,
307
308 pub(crate) registers_number: u16,
313
314 pub(crate) bytes_number: u8,
316
317 pub(crate) values: Vec<u8>,
319}
320
321impl Length for WriteMultipleHoldingRegistersRequest {
322 fn len(&self) -> u16 {
323 5 + self.values.len() as u16
324 }
325}
326
327impl WriteMultipleHoldingRegistersRequest {
328 pub(crate) fn new(first_address: u16, values: Vec<u8>) -> WriteMultipleHoldingRegistersRequest {
329 WriteMultipleHoldingRegistersRequest {
330 first_address,
331 registers_number: values.len() as u16 / 2,
332 bytes_number: values.len() as u8,
333 values,
334 }
335 }
336
337 pub fn get_first_address(&self) -> &u16 {
338 &self.first_address
339 }
340
341 pub fn get_registers_number(&self) -> &u16 {
342 &self.registers_number
343 }
344
345 pub fn get_bytes_number(&self) -> &u8 {
346 &self.bytes_number
347 }
348
349 pub fn get_values(&self) -> &Vec<u8> {
350 &self.values
351 }
352}
353
354impl From<ReadCoilsRequest> for BytesMut {
355 fn from(request: ReadCoilsRequest) -> Self {
356 let mut buf = BytesMut::new();
357 buf.put_u16(request.first_address);
358 buf.put_u16(request.coils_number);
359 buf
360 }
361}
362
363impl From<ReadDiscreteInputsRequest> for BytesMut {
364 fn from(request: ReadDiscreteInputsRequest) -> Self {
365 let mut buf = BytesMut::new();
366 buf.put_u16(request.first_address);
367 buf.put_u16(request.discrete_inputs_number);
368 buf
369 }
370}
371
372impl From<ReadMultipleHoldingRegistersRequest> for BytesMut {
373 fn from(request: ReadMultipleHoldingRegistersRequest) -> Self {
374 let mut buf = BytesMut::new();
375 buf.put_u16(request.first_address);
376 buf.put_u16(request.registers_number);
377 buf
378 }
379}
380
381impl From<ReadInputRegistersRequest> for BytesMut {
382 fn from(request: ReadInputRegistersRequest) -> Self {
383 let mut buf = BytesMut::new();
384 buf.put_u16(request.first_address);
385 buf.put_u16(request.registers_number);
386 buf
387 }
388}
389
390impl From<WriteSingleCoilRequest> for BytesMut {
391 fn from(request: WriteSingleCoilRequest) -> Self {
392 let mut buf = BytesMut::new();
393 buf.put_u16(request.coil_address);
394 buf.put_u16(request.value);
395 buf
396 }
397}
398
399impl From<WriteSingleHoldingRegisterRequest> for BytesMut {
400 fn from(request: WriteSingleHoldingRegisterRequest) -> Self {
401 let mut buf = BytesMut::new();
402 buf.put_u16(request.register_address);
403 buf.put_u16(request.value);
404 buf
405 }
406}
407
408impl From<WriteMultipleCoilsRequest> for BytesMut {
409 fn from(request: WriteMultipleCoilsRequest) -> Self {
410 let mut buf = BytesMut::new();
411 buf.put_u16(request.first_address);
412 buf.put_u16(request.coils_number);
413 buf.put_u8(request.bytes_number);
414 buf.put_slice(request.values.as_slice());
415 buf
416 }
417}
418
419impl From<WriteMultipleHoldingRegistersRequest> for BytesMut {
420 fn from(request: WriteMultipleHoldingRegistersRequest) -> Self {
421 let mut buf = BytesMut::new();
422 buf.put_u16(request.first_address);
423 buf.put_u16(request.registers_number);
424 buf.put_u8(request.bytes_number);
425 buf.put_slice(request.values.as_slice());
426 buf
427 }
428}
429
430pub(crate) fn request_to_bytesmut(item: Request, dst: &mut BytesMut) {
431 let version;
432 match item {
433 Request::ReadCoils(head, body) => {
434 version = head.version.clone();
435 dst.put(BytesMut::from(head));
436 dst.put(BytesMut::from(body));
437 }
438 Request::ReadDiscreteInputs(head, body) => {
439 version = head.version.clone();
440 dst.put(BytesMut::from(head));
441 dst.put(BytesMut::from(body));
442 }
443 Request::ReadMultipleHoldingRegisters(head, body) => {
444 version = head.version.clone();
445 dst.put(BytesMut::from(head));
446 dst.put(BytesMut::from(body));
447 }
448 Request::ReadInputRegisters(head, body) => {
449 version = head.version.clone();
450 dst.put(BytesMut::from(head));
451 dst.put(BytesMut::from(body));
452 }
453 Request::WriteSingleCoil(head, body) => {
454 version = head.version.clone();
455 dst.put(BytesMut::from(head));
456 dst.put(BytesMut::from(body));
457 }
458 Request::WriteSingleHoldingRegister(head, body) => {
459 version = head.version.clone();
460 dst.put(BytesMut::from(head));
461 dst.put(BytesMut::from(body));
462 }
463 Request::WriteMultipleCoils(head, body) => {
464 version = head.version.clone();
465 dst.put(BytesMut::from(head));
466 dst.put(BytesMut::from(body));
467 }
468 Request::WriteMultipleHoldingRegisters(head, body) => {
469 version = head.version.clone();
470 dst.put(BytesMut::from(head));
471 dst.put(BytesMut::from(body));
472 }
473 };
474 if Rtu == version {
475 dst.put_u16(crc::compute(&dst.to_vec()));
476 }
477}
478
479#[cfg(test)]
480mod request_test {
481 use crate::frame::Length;
482 use crate::frame::request::*;
483
484 #[test]
485 fn test_read_coils_request() {
486 let request_l = ReadCoilsRequest::new(0x01, 0x02);
487 let request_r = ReadCoilsRequest {
488 first_address: 0x01,
489 coils_number: 0x02,
490 };
491 assert_eq!(request_l, request_r);
492 assert_eq!(request_l.len(), 4);
493 }
494
495 #[test]
496 fn test_read_discrete_inputs_request() {
497 let request_l = ReadDiscreteInputsRequest::new(0x01, 0x02);
498 let request_r = ReadDiscreteInputsRequest {
499 first_address: 0x01,
500 discrete_inputs_number: 0x02,
501 };
502 assert_eq!(request_l, request_r);
503 assert_eq!(request_l.len(), 4);
504 }
505
506 #[test]
507 fn test_read_multiple_holding_register_request() {
508 let request_l = ReadMultipleHoldingRegistersRequest::new(0x01, 0x02);
509 let request_r = ReadMultipleHoldingRegistersRequest {
510 first_address: 0x01,
511 registers_number: 0x02,
512 };
513 assert_eq!(request_l, request_r);
514 assert_eq!(request_l.len(), 4);
515 }
516
517 #[test]
518 fn test_read_input_register_request() {
519 let request_l = ReadInputRegistersRequest::new(0x01, 0x02);
520 let request_r = ReadInputRegistersRequest {
521 first_address: 0x01,
522 registers_number: 0x02,
523 };
524 assert_eq!(request_l, request_r);
525 assert_eq!(request_l.len(), 4);
526 }
527
528 #[test]
529 fn test_write_single_coil_request() {
530 let request_l = WriteSingleCoilRequest::new(0x01, 0xABCD);
531 let request_r = WriteSingleCoilRequest {
532 coil_address: 0x01,
533 value: 0xABCD,
534 };
535 assert_eq!(request_l, request_r);
536 assert_eq!(request_l.len(), 4);
537 }
538
539 #[test]
540 fn test_write_single_holding_register_request() {
541 let request_l = WriteSingleHoldingRegisterRequest::new(0x01, 0x02);
542 let request_r = WriteSingleHoldingRegisterRequest {
543 register_address: 0x01,
544 value: 0x02,
545 };
546 assert_eq!(request_l, request_r);
547 assert_eq!(request_l.len(), 4);
548 }
549
550 #[test]
551 fn test_write_multiple_coils_request() {
552 let request_l = WriteMultipleCoilsRequest::new(0x01, 0x09, vec![0b0100_1101, 0b0000_0001]);
553 let request_r = WriteMultipleCoilsRequest {
554 first_address: 0x01,
555 coils_number: 0x09,
556 bytes_number: 0x02,
557 values: vec![0b0100_1101, 0b0000_0001],
558 };
559 assert_eq!(request_l, request_r);
560 assert_eq!(request_l.len(), 7);
561 }
562
563 #[test]
564 fn test_write_multiple_holding_registers_request() {
565 let request_l = WriteMultipleHoldingRegistersRequest::new(0x01, vec![0x00, 0x0F]);
566 let request_r = WriteMultipleHoldingRegistersRequest {
567 first_address: 0x01,
568 registers_number: 0x01,
569 bytes_number: 0x02,
570 values: vec![0x00, 0x0f],
571 };
572 assert_eq!(request_l, request_r);
573 assert_eq!(request_l.len(), 7);
574 }
575}