1use std::io::{Error, ErrorKind::InvalidData, Result};
2
3use bytes::{Buf, BufMut, Bytes, BytesMut};
4use tokio_util::codec::Decoder;
5
6use crate::codec::{RtuClientCodec, RtuServerCodec};
7use crate::frame::{
8 Exception,
9 Function,
10 Head, request::{ReadCoilsRequest, Request}, response::{ReadCoilsResponse, Response}, Version,
11};
12use crate::frame::request::*;
13use crate::frame::response::*;
14use crate::util::crc;
15
16use super::{TcpClientCodec, TcpServerCodec};
17
18impl Decoder for RtuClientCodec {
19 type Item = Response;
20 type Error = Error;
21
22 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Response>> {
23 if src.len() < 2 {
24 return Ok(None);
25 }
26
27 let mut data_bytes = BytesMut::new();
28
29 let head_bytes = src.copy_to_bytes(2);
30 data_bytes.put_slice(&(head_bytes.to_vec()));
31 let mut head = Head::rtu_try_from(head_bytes)?;
32
33 let len: usize = {
34 if head.is_exception {
35 1
36 } else {
37 match head.function {
38 Function::ReadCoils
39 | Function::ReadDiscreteInputs
40 | Function::ReadMultipleHoldingRegisters
41 | Function::ReadInputRegisters => {
42 src.get(0).map_or(0, |&bytes_num| bytes_num as usize + 1)
43 }
44 Function::WriteSingleCoil
45 | Function::WriteSingleHoldingRegister
46 | Function::WriteMultipleCoils
47 | Function::WriteMultipleHoldingRegisters => 4,
48 }
49 }
50 };
51
52 if src.len() < len + 2 {
53 return Ok(None);
54 }
55
56 head.body_length(len as u16);
57
58 let body_bytes = src.copy_to_bytes(len);
59 data_bytes.put_slice(&(body_bytes.to_vec()));
60 let response = get_response(body_bytes, head);
61
62 let crc = src.get_u16();
63 if crc::check(&(data_bytes.to_vec()), crc) {
64 return Ok(Some(response));
65 }
66 return Err(Error::new(
67 InvalidData,
68 format!("Invalid crc code: 0x{:0>2X}", crc),
69 ));
70 }
71}
72
73impl Decoder for RtuServerCodec {
74 type Item = Request;
75 type Error = Error;
76
77 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Request>> {
78 if src.len() < 2 {
79 return Ok(None);
80 }
81
82 let mut data_bytes = BytesMut::new();
83 let head_bytes = src.copy_to_bytes(2);
84 data_bytes.put_slice(&(head_bytes.to_vec()));
85 let mut head = Head::rtu_try_from(head_bytes)?;
86
87 let len: usize = {
88 match head.function {
89 Function::ReadCoils
90 | Function::ReadDiscreteInputs
91 | Function::ReadMultipleHoldingRegisters
92 | Function::ReadInputRegisters
93 | Function::WriteSingleCoil
94 | Function::WriteSingleHoldingRegister => 4,
95 Function::WriteMultipleCoils | Function::WriteMultipleHoldingRegisters => {
96 src.get(4).map_or(0, |&bytes_num| bytes_num as usize + 5)
97 }
98 }
99 };
100 if src.len() < len + 2 {
101 return Ok(None);
102 }
103
104 head.body_length(len as u16);
105 let body_bytes = src.copy_to_bytes(len);
106 data_bytes.put_slice(&(body_bytes.to_vec()));
107 let request = get_request(body_bytes, head);
108 let crc = src.get_u16();
109 if crc::check(&(data_bytes.to_vec()), crc) {
110 return Ok(Some(request));
111 }
112 return Err(Error::new(
113 InvalidData,
114 format!("Invalid crc code: 0x{:0>2X}", crc),
115 ));
116 }
117}
118
119impl Decoder for TcpClientCodec {
120 type Item = Response;
121 type Error = Error;
122
123 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Response>> {
124 if src.len() < 4 {
125 return Ok(None);
126 }
127 let head = Head::tcp_try_from(src.copy_to_bytes(8))?;
128 let len = head.length as usize - 2;
129 let response = get_response(src.copy_to_bytes(len), head);
130 Ok(Some(response))
131 }
132}
133
134impl Decoder for TcpServerCodec {
135 type Item = Request;
136 type Error = Error;
137
138 fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Request>> {
139 if src.len() < 8 {
140 return Ok(None);
141 }
142 let head = Head::tcp_try_from(src.copy_to_bytes(8))?;
143 let len = head.length as usize - 2;
144 let request = get_request(src.copy_to_bytes(len), head);
145 Ok(Some(request))
146 }
147}
148
149fn get_request(src: Bytes, head: Head) -> Request {
150 match head.function {
151 Function::ReadCoils => Request::ReadCoils(head, ReadCoilsRequest::from(src)),
152 Function::ReadDiscreteInputs => {
153 Request::ReadDiscreteInputs(head, ReadDiscreteInputsRequest::from(src))
154 }
155 Function::ReadMultipleHoldingRegisters => Request::ReadMultipleHoldingRegisters(
156 head,
157 ReadMultipleHoldingRegistersRequest::from(src),
158 ),
159 Function::ReadInputRegisters => {
160 Request::ReadInputRegisters(head, ReadInputRegistersRequest::from(src))
161 }
162 Function::WriteSingleCoil => {
163 Request::WriteSingleCoil(head, WriteSingleCoilRequest::from(src))
164 }
165 Function::WriteSingleHoldingRegister => {
166 Request::WriteSingleHoldingRegister(head, WriteSingleHoldingRegisterRequest::from(src))
167 }
168 Function::WriteMultipleCoils => {
169 Request::WriteMultipleCoils(head, WriteMultipleCoilsRequest::from(src))
170 }
171 Function::WriteMultipleHoldingRegisters => Request::WriteMultipleHoldingRegisters(
172 head,
173 WriteMultipleHoldingRegistersRequest::from(src),
174 ),
175 }
176}
177
178fn get_response(src: Bytes, head: Head) -> Response {
179 if head.is_exception {
180 return Response::Exception(head, ExceptionResponse::from(src));
181 }
182
183 match head.function {
184 Function::ReadCoils => Response::ReadCoils(head, ReadCoilsResponse::from(src)),
185 Function::ReadDiscreteInputs => {
186 Response::ReadDiscreteInputs(head, ReadDiscreteInputsResponse::from(src))
187 }
188 Function::ReadMultipleHoldingRegisters => Response::ReadMultipleHoldingRegisters(
189 head,
190 ReadMultipleHoldingRegistersResponse::from(src),
191 ),
192 Function::ReadInputRegisters => {
193 Response::ReadInputRegisters(head, ReadInputRegistersResponse::from(src))
194 }
195 Function::WriteSingleCoil => {
196 Response::WriteSingleCoil(head, WriteSingleCoilResponse::from(src))
197 }
198 Function::WriteSingleHoldingRegister => Response::WriteSingleHoldingRegister(
199 head,
200 WriteSingleHoldingRegisterResponse::from(src),
201 ),
202 Function::WriteMultipleCoils => {
203 Response::WriteMultipleCoils(head, WriteMultipleCoilsResponse::from(src))
204 }
205 Function::WriteMultipleHoldingRegisters => Response::WriteMultipleHoldingRegisters(
206 head,
207 WriteMultipleHoldingRegistersResponse::from(src),
208 ),
209 }
210}
211
212impl From<Bytes> for ReadCoilsRequest {
213 fn from(mut buf: Bytes) -> Self {
214 ReadCoilsRequest {
215 first_address: buf.get_u16(),
216 coils_number: buf.get_u16(),
217 }
218 }
219}
220
221impl From<Bytes> for ReadDiscreteInputsRequest {
222 fn from(mut buf: Bytes) -> Self {
223 ReadDiscreteInputsRequest {
224 first_address: buf.get_u16(),
225 discrete_inputs_number: buf.get_u16(),
226 }
227 }
228}
229
230impl From<Bytes> for ReadMultipleHoldingRegistersRequest {
231 fn from(mut buf: Bytes) -> Self {
232 ReadMultipleHoldingRegistersRequest {
233 first_address: buf.get_u16(),
234 registers_number: buf.get_u16(),
235 }
236 }
237}
238
239impl From<Bytes> for ReadInputRegistersRequest {
240 fn from(mut buf: Bytes) -> Self {
241 ReadInputRegistersRequest {
242 first_address: buf.get_u16(),
243 registers_number: buf.get_u16(),
244 }
245 }
246}
247
248impl From<Bytes> for WriteSingleCoilRequest {
249 fn from(mut buf: Bytes) -> Self {
250 WriteSingleCoilRequest {
251 coil_address: buf.get_u16(),
252 value: buf.get_u16(),
253 }
254 }
255}
256
257impl From<Bytes> for WriteSingleHoldingRegisterRequest {
258 fn from(mut buf: Bytes) -> Self {
259 WriteSingleHoldingRegisterRequest {
260 register_address: buf.get_u16(),
261 value: buf.get_u16(),
262 }
263 }
264}
265
266impl From<Bytes> for WriteMultipleCoilsRequest {
267 fn from(mut buf: Bytes) -> Self {
268 WriteMultipleCoilsRequest {
269 first_address: buf.get_u16(),
270 coils_number: buf.get_u16(),
271 bytes_number: buf.get_u8(),
272 values: buf.to_vec(),
273 }
274 }
275}
276
277impl From<Bytes> for WriteMultipleHoldingRegistersRequest {
278 fn from(mut buf: Bytes) -> Self {
279 WriteMultipleHoldingRegistersRequest {
280 first_address: buf.get_u16(),
281 registers_number: buf.get_u16(),
282 bytes_number: buf.get_u8(),
283 values: buf.to_vec(),
284 }
285 }
286}
287
288impl From<Bytes> for ReadCoilsResponse {
289 fn from(mut buf: Bytes) -> Self {
290 ReadCoilsResponse {
291 bytes_number: buf.get_u8(),
292 values: buf.to_vec(),
293 }
294 }
295}
296
297impl From<Bytes> for ReadDiscreteInputsResponse {
298 fn from(mut buf: Bytes) -> Self {
299 ReadDiscreteInputsResponse {
300 bytes_number: buf.get_u8(),
301 values: buf.to_vec(),
302 }
303 }
304}
305
306impl From<Bytes> for ReadMultipleHoldingRegistersResponse {
307 fn from(mut buf: Bytes) -> Self {
308 ReadMultipleHoldingRegistersResponse {
309 bytes_number: buf.get_u8(),
310 values: buf.to_vec(),
311 }
312 }
313}
314
315impl From<Bytes> for ReadInputRegistersResponse {
316 fn from(mut buf: Bytes) -> Self {
317 ReadInputRegistersResponse {
318 bytes_number: buf.get_u8(),
319 values: buf.to_vec(),
320 }
321 }
322}
323
324impl From<Bytes> for WriteSingleCoilResponse {
325 fn from(mut buf: Bytes) -> Self {
326 WriteSingleCoilResponse {
327 coil_address: buf.get_u16(),
328 value: buf.get_u16(),
329 }
330 }
331}
332
333impl From<Bytes> for WriteSingleHoldingRegisterResponse {
334 fn from(mut buf: Bytes) -> Self {
335 WriteSingleHoldingRegisterResponse {
336 register_address: buf.get_u16(),
337 value: buf.get_u16(),
338 }
339 }
340}
341
342impl From<Bytes> for WriteMultipleCoilsResponse {
343 fn from(mut buf: Bytes) -> Self {
344 WriteMultipleCoilsResponse {
345 first_address: buf.get_u16(),
346 coils_number: buf.get_u16(),
347 }
348 }
349}
350
351impl From<Bytes> for WriteMultipleHoldingRegistersResponse {
352 fn from(mut buf: Bytes) -> Self {
353 WriteMultipleHoldingRegistersResponse {
354 first_address: buf.get_u16(),
355 registers_number: buf.get_u16(),
356 }
357 }
358}
359
360impl From<Bytes> for ExceptionResponse {
361 fn from(mut buf: Bytes) -> Self {
362 ExceptionResponse {
363 exception: Exception::try_from(buf.get_u8()).unwrap(),
364 }
365 }
366}
367
368impl Head {
369 fn tcp_try_from(mut buf: Bytes) -> Result<Self> {
370 let tid = buf.get_u16();
371 let pid = buf.get_u16();
372 let length = buf.get_u16();
373 let uid = buf.get_u8();
374 let (function, is_exception) = get_function(buf.get_u8())?;
375 Ok(Head {
376 tid,
377 pid,
378 length,
379 uid,
380 function,
381 version: Version::Tcp,
382 is_exception,
383 })
384 }
385
386 fn rtu_try_from(mut buf: Bytes) -> Result<Self> {
387 let uid = buf.get_u8();
388 let (function, is_exception) = get_function(buf.get_u8())?;
389 Ok(Head {
390 tid: 0,
391 pid: 0,
392 length: 0,
393 uid,
394 function,
395 version: Version::Rtu,
396 is_exception,
397 })
398 }
399}
400
401impl TryFrom<u8> for Exception {
402 type Error = Error;
403
404 fn try_from(value: u8) -> Result<Self> {
405 match Exception::from_code(value) {
406 None => {
407 return Err(Error::new(
408 InvalidData,
409 format!("Invalid Exception code: 0x{:0>2X}", value),
410 ));
411 }
412 Some(exception) => Ok(exception),
413 }
414 }
415}
416
417impl TryFrom<u8> for Function {
418 type Error = Error;
419 fn try_from(value: u8) -> Result<Self> {
420 let func = match value {
421 0x01 => Function::ReadCoils,
422 0x02 => Function::ReadDiscreteInputs,
423 0x03 => Function::ReadMultipleHoldingRegisters,
424 0x04 => Function::ReadInputRegisters,
425 0x05 => Function::WriteSingleCoil,
426 0x06 => Function::WriteSingleHoldingRegister,
427 0x0F => Function::WriteMultipleCoils,
428 0x10 => Function::WriteMultipleHoldingRegisters,
429 _ => {
430 return Err(Error::new(
431 Exception::IllegalFunction.as_error_kind(),
432 format!("Invalid function code: 0x{:0>2X}", value),
433 ));
434 }
435 };
436 Ok(func)
437 }
438}
439
440fn get_function(function_code: u8) -> Result<(Function, bool)> {
441 let function: Function;
442 let mut is_exception = false;
443 if function_code <= 0x80 {
444 function = Function::try_from(function_code)?;
445 } else {
446 function = Function::try_from(function_code - 0x80)?;
447 is_exception = true;
448 }
449 Ok((function, is_exception))
450}
451
452#[cfg(test)]
453mod rtu_client_decoder_test {
454 use bytes::BytesMut;
455 use tokio_util::codec::Decoder;
456
457 use crate::codec::RtuClientCodec;
458 use crate::frame::{Exception, Function};
459 use crate::Frame;
460
461 #[test]
462 fn read_coils_response_test() {
463 let mut codec = RtuClientCodec::default();
464 let v: Vec<u8> = vec![0x0B, 0x01, 0x04, 0xCD, 0x6B, 0xB2, 0x7F, 0x2B, 0xE1];
465 let mut buf = BytesMut::from(&v[..]);
466 let response_l = codec.decode(&mut buf).unwrap().unwrap();
467 let frame = Frame::rtu();
468 let response_r = frame.read_coils_response(0x0B, vec![0xCD, 0x6B, 0xB2, 0x7F]);
469 assert_eq!(response_l, response_r);
470 }
471
472 #[test]
473 fn read_discrete_inputs_response_test() {
474 let mut codec = RtuClientCodec::default();
475 let v: Vec<u8> = vec![0x0B, 0x02, 0x04, 0xAC, 0xDB, 0xFB, 0x0D, 0x82, 0x7C];
476 let mut buf = BytesMut::from(&v[..]);
477 let response_l = codec.decode(&mut buf).unwrap().unwrap();
478 let frame = Frame::rtu();
479 let response_r = frame.read_discrete_response(0x0B, vec![0xAC, 0xDB, 0xFB, 0x0D]);
480 assert_eq!(response_l, response_r);
481 }
482
483 #[test]
484 fn read_multiple_holding_registers_response_test() {
485 let mut codec = RtuClientCodec::default();
486 let v: Vec<u8> = vec![
487 0x0B, 0x03, 0x06, 0xAE, 0x41, 0x56, 0x52, 0x43, 0x40, 0xFA, 0xCD,
488 ];
489 let mut buf = BytesMut::from(&v[..]);
490 let response_l = codec.decode(&mut buf).unwrap().unwrap();
491 let frame = Frame::rtu();
492 let response_r =
493 frame.read_holding_register_response(0x0B, vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40]);
494 assert_eq!(response_l, response_r);
495 }
496
497 #[test]
498 fn read_input_registers_response_test() {
499 let mut codec = RtuClientCodec::default();
500 let v: Vec<u8> = vec![0x0B, 0x04, 0x02, 0x10, 0x2F, 0x6D, 0x2D];
501 let mut buf = BytesMut::from(&v[..]);
502 let response_l = codec.decode(&mut buf).unwrap().unwrap();
503 let frame = Frame::rtu();
504 let response_r = frame.read_input_register_response(0x0B, vec![0x10, 0x2F]);
505 assert_eq!(response_l, response_r);
506 }
507
508 #[test]
509 fn write_single_coil_response_test() {
510 let mut codec = RtuClientCodec::default();
511 let v: Vec<u8> = vec![0x0B, 0x05, 0x00, 0xBF, 0x00, 0x00, 0xFC, 0x84];
512 let mut buf = BytesMut::from(&v[..]);
513 let response_l = codec.decode(&mut buf).unwrap().unwrap();
514 let frame = Frame::rtu();
515 let response_r = frame.write_single_coil_response(0x0B, 0x00BF, 0x0000);
516 assert_eq!(response_l, response_r);
517 }
518
519 #[test]
520 fn write_single_holding_register_response_test() {
521 let mut codec = RtuClientCodec::default();
522 let v: Vec<u8> = vec![0x0B, 0x006, 0x000, 0x004, 0x0AB, 0x0CD, 0x076, 0x004];
523 let mut buf = BytesMut::from(&v[..]);
524 let response_l = codec.decode(&mut buf).unwrap().unwrap();
525 let frame = Frame::rtu();
526 let response_r = frame.write_single_holding_register_response(0x0B, 0x0004, 0xABCD);
527 assert_eq!(response_l, response_r);
528 }
529
530 #[test]
531 fn write_multiple_coils_response_test() {
532 let mut codec = RtuClientCodec::default();
533 let v: Vec<u8> = vec![0x0B, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0xE5, 0x60];
534 let mut buf = BytesMut::from(&v[..]);
535 let response_l = codec.decode(&mut buf).unwrap().unwrap();
536 let frame = Frame::rtu();
537 let response_r = frame.write_multiple_coils_response(0x0B, 0x001B, 0x0009);
538 assert_eq!(response_l, response_r);
539 }
540
541 #[test]
542 fn write_multiple_holding_registers_response_test() {
543 let mut codec = RtuClientCodec::default();
544 let v: Vec<u8> = vec![0x0B, 0x10, 0x00, 0x12, 0x00, 0x02, 0xE1, 0x67];
545 let mut buf = BytesMut::from(&v[..]);
546 let response_l = codec.decode(&mut buf).unwrap().unwrap();
547 let frame = Frame::rtu();
548 let response_r = frame.write_multiple_holding_registers_response(0x0B, 0x0012, 0x0002);
549 assert_eq!(response_l, response_r);
550 }
551
552 #[test]
553 fn exception_response_test() {
554 let mut codec = RtuClientCodec::default();
555 let v: Vec<u8> = vec![0x0A, 0x81, 0x02, 0xB0, 0x53];
556 let mut buf = BytesMut::from(&v[..]);
557 let response_l = codec.decode(&mut buf).unwrap().unwrap();
558 let frame = Frame::rtu();
559 let response_r =
560 frame.exception_response(0x0A, Function::ReadCoils, Exception::IllegalDataAddress);
561 assert_eq!(response_l, response_r);
562 }
563}
564
565#[cfg(test)]
566mod tcp_client_decoder_test {
567 use bytes::BytesMut;
568 use tokio_util::codec::Decoder;
569
570 use crate::{codec::TcpClientCodec, Frame};
571 use crate::frame::{Exception, Function};
572
573 #[test]
574 fn read_coils_response_test() {
575 let mut codec = TcpClientCodec::default();
576 let v: Vec<u8> = vec![
577 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x01, 0x02, 0x00, 0x01,
578 ];
579 let mut buf = BytesMut::from(&v[..]);
580 let response_l = codec.decode(&mut buf).unwrap().unwrap();
581 let frame = Frame::tcp();
582 let response_r = frame.read_coils_response(0x01, vec![0x00, 0x01]);
583 assert_eq!(response_l, response_r);
584 }
585
586 #[test]
587 fn read_discrete_inputs_response_test() {
588 let mut codec = TcpClientCodec::default();
589 let v: Vec<u8> = vec![
590 0x00, 0x01, 0x00, 0x00, 0x00, 0x07, 0x01, 0x02, 0x04, 0xAC, 0xDB, 0xFB, 0x0D,
591 ];
592 let mut buf = BytesMut::from(&v[..]);
593 let response_l = codec.decode(&mut buf).unwrap().unwrap();
594 let frame = Frame::tcp();
595 let response_r = frame.read_discrete_response(0x01, vec![0xAC, 0xDB, 0xFB, 0x0D]);
596 assert_eq!(response_l, response_r);
597 }
598
599 #[test]
600 fn read_multiple_holding_registers_response_test() {
601 let mut codec = TcpClientCodec::default();
602 let v: Vec<u8> = vec![
603 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x01, 0x03, 0x06, 0xAE, 0x41, 0x56, 0x52, 0x43,
604 0x40,
605 ];
606 let mut buf = BytesMut::from(&v[..]);
607 let response_l = codec.decode(&mut buf).unwrap().unwrap();
608 let frame = Frame::tcp();
609 let response_r =
610 frame.read_holding_register_response(0x01, vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40]);
611 assert_eq!(response_l, response_r);
612 }
613
614 #[test]
615 fn read_input_registers_response_test() {
616 let mut codec = TcpClientCodec::default();
617 let v: Vec<u8> = vec![
618 0x00, 0x01, 0x00, 0x00, 0x00, 0x05, 0x01, 0x04, 0x02, 0x10, 0x2F,
619 ];
620 let mut buf = BytesMut::from(&v[..]);
621 let response_l = codec.decode(&mut buf).unwrap().unwrap();
622 let frame = Frame::tcp();
623 let response_r = frame.read_input_register_response(0x01, vec![0x10, 0x2F]);
624 assert_eq!(response_l, response_r);
625 }
626
627 #[test]
628 fn write_single_coil_response_test() {
629 let mut codec = TcpClientCodec::default();
630 let v: Vec<u8> = vec![
631 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0xBF, 0x00, 0x00,
632 ];
633 let mut buf = BytesMut::from(&v[..]);
634 let response_l = codec.decode(&mut buf).unwrap().unwrap();
635 let frame = Frame::tcp();
636 let response_r = frame.write_single_coil_response(0x01, 0x00BF, 0x0000);
637 assert_eq!(response_l, response_r);
638 }
639
640 #[test]
641 fn write_single_holding_register_response_test() {
642 let mut codec = TcpClientCodec::default();
643 let v: Vec<u8> = vec![
644 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x04, 0xAB, 0xCD,
645 ];
646 let mut buf = BytesMut::from(&v[..]);
647 let response_l = codec.decode(&mut buf).unwrap().unwrap();
648 let frame = Frame::tcp();
649 let response_r = frame.write_single_holding_register_response(0x01, 0x0004, 0xABCD);
650 assert_eq!(response_l, response_r);
651 }
652
653 #[test]
654 fn write_multiple_coils_response_test() {
655 let mut codec = TcpClientCodec::default();
656 let v: Vec<u8> = vec![
657 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x0F, 0x00, 0x1B, 0x00, 0x09,
658 ];
659 let mut buf = BytesMut::from(&v[..]);
660 let response_l = codec.decode(&mut buf).unwrap().unwrap();
661 let frame = Frame::tcp();
662 let response_r = frame.write_multiple_coils_response(0x01, 0x001B, 0x0009);
663 assert_eq!(response_l, response_r);
664 }
665
666 #[test]
667 fn write_multiple_holding_registers_response_test() {
668 let mut codec = TcpClientCodec::default();
669 let v: Vec<u8> = vec![
670 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x10, 0x00, 0x12, 0x00, 0x02,
671 ];
672 let mut buf = BytesMut::from(&v[..]);
673 let response_l = codec.decode(&mut buf).unwrap().unwrap();
674 let frame = Frame::tcp();
675 let response_r = frame.write_multiple_holding_registers_response(0x01, 0x0012, 0x0002);
676 assert_eq!(response_l, response_r);
677 }
678
679 #[test]
680 fn exception_response_test() {
681 let mut codec = TcpClientCodec::default();
682 let v: Vec<u8> = vec![0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x0A, 0x81, 0x02];
683 let mut buf = BytesMut::from(&v[..]);
684 let response_l = codec.decode(&mut buf).unwrap().unwrap();
685 let frame = Frame::tcp();
686 let response_r =
687 frame.exception_response(0x0A, Function::ReadCoils, Exception::IllegalDataAddress);
688 assert_eq!(response_l, response_r);
689 }
690}
691
692#[cfg(test)]
693mod rtu_server_decoder_test {
694 use bytes::BytesMut;
695 use tokio_util::codec::Decoder;
696
697 use crate::codec::RtuServerCodec;
698 use crate::frame::Frame;
699
700 #[test]
701 fn read_coils_request_test() {
702 let mut codec = RtuServerCodec::default();
703 let v: Vec<u8> = vec![0x0B, 0x01, 0x00, 0x1D, 0x00, 0x1F, 0xED, 0x6E];
704 let mut buf = BytesMut::from(&v[..]);
705 let request_l = codec.decode(&mut buf).unwrap().unwrap();
706
707 let frame = Frame::rtu();
708 let request_r = frame.read_coils_request(0x0B, 0x001D, 0x001F);
709 assert_eq!(request_l, request_r);
710 }
711
712 #[test]
713 fn read_discrete_inputs_test() {
714 let mut codec = RtuServerCodec::default();
715 let v: Vec<u8> = vec![0x0B, 0x02, 0x00, 0x7A, 0x00, 0x1C, 0x58, 0xB0];
716 let mut buf = BytesMut::from(&v[..]);
717 let request_l = codec.decode(&mut buf).unwrap().unwrap();
718 let frame = Frame::rtu();
719 let request_r = frame.read_discrete_request(0x0B, 0x007A, 0x001C);
720 assert_eq!(request_l, request_r);
721 }
722
723 #[test]
724 fn read_multiple_holding_registers_test() {
725 let mut codec = RtuServerCodec::default();
726 let v: Vec<u8> = vec![0x0B, 0x03, 0x00, 0x6F, 0x00, 0x03, 0x35, 0x7C];
727 let mut buf = BytesMut::from(&v[..]);
728 let request_l = codec.decode(&mut buf).unwrap().unwrap();
729 let frame = Frame::rtu();
730 let request_r = frame.read_multiple_holding_registers_request(0x0B, 0x006F, 0x0003);
731 assert_eq!(request_l, request_r);
732 }
733
734 #[test]
735 fn read_input_registers_test() {
736 let mut codec = RtuServerCodec::default();
737 let v: Vec<u8> = vec![0x0B, 0x04, 0x00, 0x0A, 0x00, 0x01, 0x11, 0x62];
738 let mut buf = BytesMut::from(&v[..]);
739 let request_l = codec.decode(&mut buf).unwrap().unwrap();
740 let frame = Frame::rtu();
741 let request_r = frame.read_input_registers_request(0x0B, 0x000A, 0x0001);
742 assert_eq!(request_l, request_r);
743 }
744
745 #[test]
746 fn write_single_coil_test() {
747 let mut codec = RtuServerCodec::default();
748 let v: Vec<u8> = vec![0x0B, 0x05, 0x00, 0xBF, 0x00, 0x00, 0xFC, 0x84];
749 let mut buf = BytesMut::from(&v[..]);
750 let request_l = codec.decode(&mut buf).unwrap().unwrap();
751 let frame = Frame::rtu();
752 let request_r = frame.write_single_coil_request(0x0B, 0x00BF, 0x0000);
753 assert_eq!(request_l, request_r);
754 }
755
756 #[test]
757 fn write_single_holding_register_test() {
758 let mut codec = RtuServerCodec::default();
759 let v: Vec<u8> = vec![0x0B, 0x06, 0x00, 0x04, 0xAB, 0xCD, 0x76, 0x04];
760 let mut buf = BytesMut::from(&v[..]);
761 let request_l = codec.decode(&mut buf).unwrap().unwrap();
762 let frame = Frame::rtu();
763 let request_r = frame.write_single_holding_register_request(0x0B, 0x0004, 0xABCD);
764 assert_eq!(request_l, request_r);
765 }
766
767 #[test]
768 fn write_multiple_coils_test() {
769 let mut codec = RtuServerCodec::default();
770 let v: Vec<u8> = vec![
771 0x0B, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0x02, 0x4D, 0x01, 0x6C, 0xA7,
772 ];
773 let mut buf = BytesMut::from(&v[..]);
774 let request_l = codec.decode(&mut buf).unwrap().unwrap();
775 let frame = Frame::rtu();
776 let request_r = frame.write_multiple_coils_request(0x0B, 0x001B, 0x0009, vec![0x4D, 0x01]);
777 assert_eq!(request_l, request_r);
778 }
779
780 #[test]
781 fn write_multiple_holding_registers_test() {
782 let mut codec = RtuServerCodec::default();
783 let v: Vec<u8> = vec![
784 0x0B, 0x10, 0x00, 0x12, 0x00, 0x02, 0x04, 0x0B, 0x0A, 0xC1, 0x02, 0xA0, 0xD5,
785 ];
786 let mut buf = BytesMut::from(&v[..]);
787 let request_l = codec.decode(&mut buf).unwrap().unwrap();
788 let frame = Frame::rtu();
789 let request_r = frame.write_multiple_holding_registers_request(
790 0x0B,
791 0x0012,
792 vec![0x0B, 0x0A, 0xC1, 0x02],
793 );
794 assert_eq!(request_l, request_r);
795 }
796}
797
798#[cfg(test)]
799mod tcp_server_decoder_test {
800 use bytes::BytesMut;
801 use tokio_util::codec::Decoder;
802
803 use crate::codec::TcpServerCodec;
804 use crate::frame::Frame;
805
806 #[test]
807 fn read_coils_request_test() {
808 let mut codec = TcpServerCodec::default();
809 let v: Vec<u8> = vec![
810 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x01, 0x00, 0x02, 0x00, 0x08,
811 ];
812 let mut buf = BytesMut::from(&v[..]);
813 let request_l = codec.decode(&mut buf).unwrap().unwrap();
814
815 let frame = Frame::tcp();
816 let request_r = frame.read_coils_request(0x01, 0x02, 0x08);
817 assert_eq!(request_l, request_r);
818 }
819
820 #[test]
821 fn read_discrete_inputs_test() {
822 let mut codec = TcpServerCodec::default();
823 let v: Vec<u8> = vec![
824 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x02, 0x00, 0x7A, 0x00, 0x1C,
825 ];
826 let mut buf = BytesMut::from(&v[..]);
827 let request_l = codec.decode(&mut buf).unwrap().unwrap();
828 let frame = Frame::tcp();
829 let request_r = frame.read_discrete_request(0x01, 0x007A, 0x001C);
830 assert_eq!(request_l, request_r);
831 }
832
833 #[test]
834 fn read_multiple_holding_registers_test() {
835 let mut codec = TcpServerCodec::default();
836 let v: Vec<u8> = vec![
837 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x6F, 0x00, 0x03,
838 ];
839 let mut buf = BytesMut::from(&v[..]);
840 let request_l = codec.decode(&mut buf).unwrap().unwrap();
841 let frame = Frame::tcp();
842 let request_r = frame.read_multiple_holding_registers_request(0x01, 0x006F, 0x0003);
843 assert_eq!(request_l, request_r);
844 }
845
846 #[test]
847 fn read_input_registers_test() {
848 let mut codec = TcpServerCodec::default();
849 let v: Vec<u8> = vec![
850 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x04, 0x00, 0x0A, 0x00, 0x01,
851 ];
852 let mut buf = BytesMut::from(&v[..]);
853 let request_l = codec.decode(&mut buf).unwrap().unwrap();
854 let frame = Frame::tcp();
855 let request_r = frame.read_input_registers_request(0x01, 0x000A, 0x0001);
856 assert_eq!(request_l, request_r);
857 }
858
859 #[test]
860 fn write_single_coil_test() {
861 let mut codec = TcpServerCodec::default();
862 let v: Vec<u8> = vec![
863 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x05, 0x00, 0xBF, 0x00, 0x00,
864 ];
865 let mut buf = BytesMut::from(&v[..]);
866 let request_l = codec.decode(&mut buf).unwrap().unwrap();
867 let frame = Frame::tcp();
868 let request_r = frame.write_single_coil_request(0x01, 0x00BF, 0x0000);
869 assert_eq!(request_l, request_r);
870 }
871
872 #[test]
873 fn write_single_holding_register_test() {
874 let mut codec = TcpServerCodec::default();
875 let v: Vec<u8> = vec![
876 0x00, 0x01, 0x00, 0x00, 0x00, 0x06, 0x01, 0x06, 0x00, 0x04, 0xAB, 0xCD,
877 ];
878 let mut buf = BytesMut::from(&v[..]);
879 let request_l = codec.decode(&mut buf).unwrap().unwrap();
880 let frame = Frame::tcp();
881 let request_r = frame.write_single_holding_register_request(0x01, 0x0004, 0xABCD);
882 assert_eq!(request_l, request_r);
883 }
884
885 #[test]
886 fn write_multiple_coils_test() {
887 let mut codec = TcpServerCodec::default();
888 let v: Vec<u8> = vec![
889 0x00, 0x01, 0x00, 0x00, 0x00, 0x09, 0x01, 0x0F, 0x00, 0x1B, 0x00, 0x09, 0x02, 0x4D,
890 0x01,
891 ];
892 let mut buf = BytesMut::from(&v[..]);
893 let request_l = codec.decode(&mut buf).unwrap().unwrap();
894 let frame = Frame::tcp();
895 let request_r = frame.write_multiple_coils_request(0x01, 0x001B, 0x0009, vec![0x4D, 0x01]);
896 assert_eq!(request_l, request_r);
897 }
898
899 #[test]
900 fn write_multiple_holding_registers_test() {
901 let mut codec = TcpServerCodec::default();
902 let v: Vec<u8> = vec![
903 0x00, 0x01, 0x00, 0x00, 0x00, 0x0B, 0x01, 0x10, 0x00, 0x12, 0x00, 0x02, 0x04, 0x0B,
904 0x0A, 0xC1, 0x02,
905 ];
906 let mut buf = BytesMut::from(&v[..]);
907 let request_l = codec.decode(&mut buf).unwrap().unwrap();
908 let frame = Frame::tcp();
909 let request_r = frame.write_multiple_holding_registers_request(
910 0x01,
911 0x0012,
912 vec![0x0B, 0x0A, 0xC1, 0x02],
913 );
914 assert_eq!(request_l, request_r);
915 }
916}