easy_modbus/frame/
response.rs

1use std::fmt;
2use std::fmt::Formatter;
3
4use bytes::{BufMut, BytesMut};
5
6use crate::frame::{Exception, Version};
7use crate::frame::Version::Rtu;
8use crate::util::crc;
9
10use super::{Head, Length};
11
12#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13pub enum Response {
14    ReadCoils(Head, ReadCoilsResponse),
15    ReadDiscreteInputs(Head, ReadDiscreteInputsResponse),
16    ReadMultipleHoldingRegisters(Head, ReadMultipleHoldingRegistersResponse),
17    ReadInputRegisters(Head, ReadInputRegistersResponse),
18    WriteSingleCoil(Head, WriteSingleCoilResponse),
19    WriteSingleHoldingRegister(Head, WriteSingleHoldingRegisterResponse),
20    WriteMultipleCoils(Head, WriteMultipleCoilsResponse),
21    WriteMultipleHoldingRegisters(Head, WriteMultipleHoldingRegistersResponse),
22    Exception(Head, ExceptionResponse),
23}
24
25impl fmt::Display for Response {
26    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
27        let mut buf = BytesMut::with_capacity(64);
28        response_to_bytesmut(self.clone(), &mut buf);
29        let mut first = true;
30        for byte in buf {
31            if !first {
32                write!(f, " ")?;
33            }
34            write!(f, "{:02X}", byte)?;
35            first = false;
36        }
37        Ok(())
38    }
39}
40
41/// Function Code `0x01`
42#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
43pub struct ReadCoilsResponse {
44    /// Number of bytes of coil input values to follow
45    pub(crate) bytes_number: u8,
46
47    /// Coil input values
48    ///
49    /// Values of each coil input is binary (0 for off, 1 for on). First requested coil input is
50    /// as least significant bit of first byte in reply. If number of coils inputs is not a multiple
51    /// of 8, most significant bits of last byte will be stuffed zeros.
52    pub(crate) values: Vec<u8>,
53}
54
55impl Length for ReadCoilsResponse {
56    fn len(&self) -> u16 {
57        1 + self.values.len() as u16
58    }
59}
60
61impl ReadCoilsResponse {
62    pub(crate) fn new(values: Vec<u8>) -> ReadCoilsResponse {
63        let bytes_number = values.len() as u8;
64        ReadCoilsResponse {
65            bytes_number,
66            values,
67        }
68    }
69
70    pub fn get_bytes_number(&self) -> &u8 {
71        &self.bytes_number
72    }
73
74    pub fn get_values(&self) -> &Vec<u8> {
75        &self.values
76    }
77}
78
79/// Function Code `0x02`
80#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
81pub struct ReadDiscreteInputsResponse {
82    /// Number of bytes of discrete input values to follow
83    pub(crate) bytes_number: u8,
84
85    /// Discrete input values
86    ///
87    /// Values of each discrete input is binary (0 for off, 1 for on). First requested discrete
88    /// input is stored as least significant bit of first byte in reply. If number of discrete
89    /// inputs is not a multiple of 8, most significant bits of last byte will be stuffed with
90    /// zeros.
91    pub(crate) values: Vec<u8>,
92}
93
94impl Length for ReadDiscreteInputsResponse {
95    fn len(&self) -> u16 {
96        1 + self.values.len() as u16
97    }
98}
99
100impl ReadDiscreteInputsResponse {
101    pub(crate) fn new(values: Vec<u8>) -> ReadDiscreteInputsResponse {
102        ReadDiscreteInputsResponse {
103            bytes_number: values.len() as u8,
104            values,
105        }
106    }
107
108    pub fn get_bytes_number(&self) -> &u8 {
109        &self.bytes_number
110    }
111
112    pub fn get_values(&self) -> &Vec<u8> {
113        &self.values
114    }
115}
116
117/// Function Code `0x03`
118#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
119pub struct ReadMultipleHoldingRegistersResponse {
120    /// Number of bytes of register values to follow
121    pub(crate) bytes_number: u8,
122
123    /// Register values
124    pub(crate) values: Vec<u8>,
125}
126
127impl Length for ReadMultipleHoldingRegistersResponse {
128    fn len(&self) -> u16 {
129        1 + self.values.len() as u16
130    }
131}
132
133impl ReadMultipleHoldingRegistersResponse {
134    pub(crate) fn new(values: Vec<u8>) -> ReadMultipleHoldingRegistersResponse {
135        let bytes_number = values.len() as u8;
136        ReadMultipleHoldingRegistersResponse {
137            bytes_number,
138            values,
139        }
140    }
141
142    pub fn get_bytes_number(&self) -> &u8 {
143        &self.bytes_number
144    }
145
146    pub fn get_values(&self) -> &Vec<u8> {
147        &self.values
148    }
149}
150
151/// Function Code `0x04`
152#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
153pub struct ReadInputRegistersResponse {
154    /// Number of bytes of register value to follow
155    pub(crate) bytes_number: u8,
156
157    /// Register values
158    pub(crate) values: Vec<u8>,
159}
160
161impl Length for ReadInputRegistersResponse {
162    fn len(&self) -> u16 {
163        1 + self.values.len() as u16
164    }
165}
166
167impl ReadInputRegistersResponse {
168    pub(crate) fn new(values: Vec<u8>) -> ReadInputRegistersResponse {
169        let bytes_number = values.len() as u8;
170        ReadInputRegistersResponse {
171            bytes_number,
172            values,
173        }
174    }
175
176    pub fn get_bytes_number(&self) -> &u8 {
177        &self.bytes_number
178    }
179
180    pub fn get_values(&self) -> &Vec<u8> {
181        &self.values
182    }
183}
184
185/// Function Code `0x05`
186#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
187pub struct WriteSingleCoilResponse {
188    /// Address of coil
189    pub(crate) coil_address: u16,
190
191    /// Value to write
192    ///
193    /// 0 (0x0000) for off, 65,280 (0xFF00) for on
194    pub(crate) value: u16,
195}
196
197impl Length for WriteSingleCoilResponse {
198    fn len(&self) -> u16 {
199        4
200    }
201}
202
203impl WriteSingleCoilResponse {
204    pub(crate) fn new(coil_address: u16, value: u16) -> WriteSingleCoilResponse {
205        WriteSingleCoilResponse {
206            coil_address,
207            value,
208        }
209    }
210
211    pub fn get_coil_address(&self) -> &u16 {
212        &self.coil_address
213    }
214
215    pub fn get_value(&self) -> &u16 {
216        &self.value
217    }
218}
219
220/// Function Code `0x06`
221#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
222pub struct WriteSingleHoldingRegisterResponse {
223    /// Address of holding register to write
224    pub(crate) register_address: u16,
225
226    /// Value to write
227    pub(crate) value: u16,
228}
229
230impl Length for WriteSingleHoldingRegisterResponse {
231    fn len(&self) -> u16 {
232        4
233    }
234}
235
236impl WriteSingleHoldingRegisterResponse {
237    pub(crate) fn new(register_address: u16, value: u16) -> WriteSingleHoldingRegisterResponse {
238        WriteSingleHoldingRegisterResponse {
239            register_address,
240            value,
241        }
242    }
243
244    pub fn get_register_address(&self) -> &u16 {
245        &self.register_address
246    }
247
248    pub fn get_value(&self) -> &u16 {
249        &self.value
250    }
251}
252
253/// Function Code `0x0F`
254#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
255pub struct WriteMultipleCoilsResponse {
256    /// Address of the first coil
257    pub(crate) first_address: u16,
258
259    /// Number of coils
260    pub(crate) coils_number: u16,
261}
262
263impl Length for WriteMultipleCoilsResponse {
264    fn len(&self) -> u16 {
265        4
266    }
267}
268
269impl WriteMultipleCoilsResponse {
270    pub(crate) fn new(first_address: u16, coils_number: u16) -> WriteMultipleCoilsResponse {
271        WriteMultipleCoilsResponse {
272            first_address,
273            coils_number,
274        }
275    }
276
277    pub fn get_first_address(&self) -> &u16 {
278        &self.first_address
279    }
280
281    pub fn get_coils_number(&self) -> &u16 {
282        &self.coils_number
283    }
284}
285
286/// Function Code `0x10`
287#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
288pub struct WriteMultipleHoldingRegistersResponse {
289    /// Address of first written holding register
290    pub(crate) first_address: u16,
291
292    /// Number of written holding registers
293    pub(crate) registers_number: u16,
294}
295
296impl Length for WriteMultipleHoldingRegistersResponse {
297    fn len(&self) -> u16 {
298        4
299    }
300}
301
302impl WriteMultipleHoldingRegistersResponse {
303    pub(crate) fn new(
304        first_address: u16,
305        registers_number: u16,
306    ) -> WriteMultipleHoldingRegistersResponse {
307        WriteMultipleHoldingRegistersResponse {
308            first_address,
309            registers_number,
310        }
311    }
312
313    pub fn get_first_address(&self) -> &u16 {
314        &self.first_address
315    }
316
317    pub fn get_registers_number(&self) -> &u16 {
318        &self.registers_number
319    }
320}
321
322#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
323pub struct ExceptionResponse {
324    pub(crate) exception: Exception,
325}
326
327impl Length for ExceptionResponse {
328    fn len(&self) -> u16 {
329        1
330    }
331}
332
333impl ExceptionResponse {
334    pub(crate) fn new(exception: Exception) -> Self {
335        ExceptionResponse { exception }
336    }
337
338    pub fn get_exception(&self) -> &Exception {
339        &self.exception
340    }
341}
342
343impl From<ReadCoilsResponse> for BytesMut {
344    fn from(response: ReadCoilsResponse) -> Self {
345        let mut buf = BytesMut::new();
346        buf.put_u8(response.bytes_number);
347        buf.put_slice(response.values.as_slice());
348        buf
349    }
350}
351
352impl From<ReadDiscreteInputsResponse> for BytesMut {
353    fn from(response: ReadDiscreteInputsResponse) -> Self {
354        let mut buf = BytesMut::new();
355        buf.put_u8(response.bytes_number);
356        buf.put_slice(response.values.as_slice());
357        buf
358    }
359}
360
361impl From<ReadMultipleHoldingRegistersResponse> for BytesMut {
362    fn from(response: ReadMultipleHoldingRegistersResponse) -> Self {
363        let mut buf = BytesMut::new();
364        buf.put_u8(response.bytes_number);
365        buf.put_slice(response.values.as_slice());
366        buf
367    }
368}
369
370impl From<ReadInputRegistersResponse> for BytesMut {
371    fn from(response: ReadInputRegistersResponse) -> Self {
372        let mut buf = BytesMut::new();
373        buf.put_u8(response.bytes_number);
374        buf.put_slice(response.values.as_slice());
375        buf
376    }
377}
378
379impl From<WriteSingleCoilResponse> for BytesMut {
380    fn from(response: WriteSingleCoilResponse) -> Self {
381        let mut buf = BytesMut::new();
382        buf.put_u16(response.coil_address);
383        buf.put_u16(response.value);
384        buf
385    }
386}
387
388impl From<WriteSingleHoldingRegisterResponse> for BytesMut {
389    fn from(response: WriteSingleHoldingRegisterResponse) -> Self {
390        let mut buf = BytesMut::new();
391        buf.put_u16(response.register_address);
392        buf.put_u16(response.value);
393        buf
394    }
395}
396
397impl From<WriteMultipleCoilsResponse> for BytesMut {
398    fn from(response: WriteMultipleCoilsResponse) -> Self {
399        let mut buf = BytesMut::new();
400        buf.put_u16(response.first_address);
401        buf.put_u16(response.coils_number);
402        buf
403    }
404}
405
406impl From<WriteMultipleHoldingRegistersResponse> for BytesMut {
407    fn from(response: WriteMultipleHoldingRegistersResponse) -> Self {
408        let mut buf = BytesMut::new();
409        buf.put_u16(response.first_address);
410        buf.put_u16(response.registers_number);
411        buf
412    }
413}
414
415impl From<ExceptionResponse> for BytesMut {
416    fn from(response: ExceptionResponse) -> Self {
417        let mut buf = BytesMut::new();
418        buf.put_u8(response.exception.to_code());
419        buf
420    }
421}
422
423impl From<Head> for BytesMut {
424    fn from(head: Head) -> Self {
425        let mut buf = BytesMut::new();
426
427        let function_code = if head.is_exception {
428            head.function.to_code() + 0x80
429        } else {
430            head.function.to_code()
431        };
432
433        if head.version == Version::Tcp {
434            buf.put_u16(head.tid);
435            buf.put_u16(head.pid);
436            buf.put_u16(head.length);
437        }
438        buf.put_u8(head.uid);
439        buf.put_u8(function_code);
440        buf
441    }
442}
443
444pub(crate) fn response_to_bytesmut(item: Response, dst: &mut BytesMut) {
445    let version;
446    match item {
447        Response::ReadCoils(head, body) => {
448            version = head.version.clone();
449            dst.put(BytesMut::from(head));
450            dst.put(BytesMut::from(body));
451        }
452        Response::ReadDiscreteInputs(head, body) => {
453            version = head.version.clone();
454            dst.put(BytesMut::from(head));
455            dst.put(BytesMut::from(body));
456        }
457        Response::ReadMultipleHoldingRegisters(head, body) => {
458            version = head.version.clone();
459            dst.put(BytesMut::from(head));
460            dst.put(BytesMut::from(body));
461        }
462        Response::ReadInputRegisters(head, body) => {
463            version = head.version.clone();
464            dst.put(BytesMut::from(head));
465            dst.put(BytesMut::from(body));
466        }
467        Response::WriteSingleCoil(head, body) => {
468            version = head.version.clone();
469            dst.put(BytesMut::from(head));
470            dst.put(BytesMut::from(body));
471        }
472        Response::WriteSingleHoldingRegister(head, body) => {
473            version = head.version.clone();
474            dst.put(BytesMut::from(head));
475            dst.put(BytesMut::from(body));
476        }
477        Response::WriteMultipleCoils(head, body) => {
478            version = head.version.clone();
479            dst.put(BytesMut::from(head));
480            dst.put(BytesMut::from(body));
481        }
482        Response::WriteMultipleHoldingRegisters(head, body) => {
483            version = head.version.clone();
484            dst.put(BytesMut::from(head));
485            dst.put(BytesMut::from(body));
486        }
487        Response::Exception(head, body) => {
488            version = head.version.clone();
489            dst.put(BytesMut::from(head));
490            dst.put(BytesMut::from(body));
491        }
492    };
493    if Rtu == version {
494        dst.put_u16(crc::compute(&dst.to_vec()));
495    }
496}
497
498#[cfg(test)]
499mod response_test {
500    use crate::frame::{Exception, Length};
501    use crate::frame::response::*;
502
503    #[test]
504    fn test_read_coils_response() {
505        let response_l =
506            ReadCoilsResponse::new(vec![0b1100_1101, 0b0110_1011, 0b1011_0010, 0b0111_1111]);
507        let response_r = ReadCoilsResponse {
508            bytes_number: 0x04,
509            values: vec![0b1100_1101, 0b0110_1011, 0b1011_0010, 0b0111_1111],
510        };
511        assert_eq!(response_l, response_r);
512        assert_eq!(response_l.len(), 5);
513    }
514
515    #[test]
516    fn test_read_discrete_inputs_response() {
517        let response_l =
518            ReadDiscreteInputsResponse::new(vec![0b1010_1100, 0b1101_1011, 0b1111_1011, 0b0000_1101]);
519        let response_r = ReadDiscreteInputsResponse {
520            bytes_number: 0x04,
521            values: vec![0b1010_1100, 0b1101_1011, 0b1111_1011, 0b0000_1101],
522        };
523        assert_eq!(response_l, response_r);
524        assert_eq!(response_l.len(), 5);
525    }
526
527
528    #[test]
529    fn test_read_multiple_holding_registers_response() {
530        let response_l =
531            ReadMultipleHoldingRegistersResponse::new(vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40]);
532        let response_r = ReadMultipleHoldingRegistersResponse {
533            bytes_number: 0x06,
534            values: vec![0xAE, 0x41, 0x56, 0x52, 0x43, 0x40],
535        };
536        assert_eq!(response_l, response_r);
537        assert_eq!(response_l.len(), 7);
538    }
539
540    #[test]
541    fn test_read_input_register_response() {
542        let response_l = ReadInputRegistersResponse::new(vec![0x0C, 0x00, 0x00, 0x00]);
543        let response_r = ReadInputRegistersResponse {
544            bytes_number: 0x04,
545            values: vec![0x0C, 0x00, 0x00, 0x00],
546        };
547        assert_eq!(response_l, response_r);
548        assert_eq!(response_l.len(), 5);
549    }
550
551    #[test]
552    fn test_write_single_coils_response() {
553        let response_l = WriteSingleCoilResponse::new(0x00, 0xFF);
554        let response_r = WriteSingleCoilResponse {
555            coil_address: 0x00,
556            value: 0xFF,
557        };
558        assert_eq!(response_l, response_r);
559        assert_eq!(response_l.len(), 4);
560    }
561
562    #[test]
563    fn test_write_single_holding_register_response() {
564        let response_l = WriteSingleHoldingRegisterResponse::new(0x01, 0xABCD);
565        let response_r = WriteSingleHoldingRegisterResponse {
566            register_address: 0x01,
567            value: 0xABCD,
568        };
569        assert_eq!(response_l, response_r);
570        assert_eq!(response_l.len(), 4);
571    }
572
573    #[test]
574    fn test_write_multiple_coils_response() {
575        let response_l = WriteMultipleCoilsResponse::new(0x00, 0x09);
576        let response_r = WriteMultipleCoilsResponse {
577            first_address: 0x00,
578            coils_number: 0x09,
579        };
580        assert_eq!(response_l, response_r);
581        assert_eq!(response_l.len(), 4);
582    }
583
584    #[test]
585    fn test_multiple_holding_registers_response() {
586        let response_l = WriteMultipleHoldingRegistersResponse::new(0x00, 0x02);
587        let response_r = WriteMultipleHoldingRegistersResponse {
588            first_address: 0x00,
589            registers_number: 0x02,
590        };
591        assert_eq!(response_l, response_r);
592        assert_eq!(response_l.len(), 4);
593    }
594
595    #[test]
596    fn test_exception_response() {
597        let response_l = ExceptionResponse::new(Exception::IllegalDataAddress);
598        let response_r = ExceptionResponse {
599            exception: Exception::IllegalDataAddress,
600        };
601        assert_eq!(response_l, response_r);
602        assert_eq!(response_l.len(), 1);
603    }
604}