libmodbus/modbus_client.rs
1use crate::prelude::*;
2use libc::c_int;
3use libmodbus_sys as ffi;
4
5/// The Modbus protocol defines different data types and functions to read and write them from/to remote devices.
6/// The following functions are used by the clients to send Modbus requests:
7///
8/// * Read data
9/// - [`read_bits()`](struct.Modbus.html#method.read_bits),
10/// [`read_input_bits()`](struct.Modbus.html#method.read_input_bits),
11/// [`read_registers()`](struct.Modbus.html#method.read_registers),
12/// [`read_input_registers()`](struct.Modbus.html#method.read_input_registers),
13/// [`report_slave_id()`](struct.Modbus.html#method.report_slave_id)
14/// * Write data
15/// - [`write_bit()`](struct.Modbus.html#method.write_bit),
16/// [`write_register()`](struct.Modbus.html#method.write_register),
17/// [`write_bits()`](struct.Modbus.html#method.write_bits),
18/// [`write_registers()`](struct.Modbus.html#method.write_registers)
19/// * Write and read data
20/// - [`write_and_read_registers()`](struct.Modbus.html#method.write_and_read_registers)
21/// * Raw requests
22/// - [`send_raw_request()`](struct.Modbus.html#method.send_raw_request),
23/// [`receive_confirmation()`](struct.Modbus.html#method.receive_confirmation)
24/// * Reply an exception
25/// - [`reply_exception()`](struct.Modbus.html#method.reply_exception)
26///
27pub trait ModbusClient {
28 fn read_bits(&self, address: u16, num: u16, dest: &mut [u8]) -> Result<u16, Error>;
29 fn read_input_bits(&self, address: u16, num: u16, dest: &mut [u8]) -> Result<u16, Error>;
30 fn read_registers(&self, address: u16, num: u16, dest: &mut [u16]) -> Result<u16, Error>;
31 fn read_input_registers(&self, address: u16, num: u16, dest: &mut [u16]) -> Result<u16, Error>;
32 fn report_slave_id(&self, max_dest: usize, dest: &mut [u8]) -> Result<u16, Error>;
33 fn write_bit(&self, address: u16, status: bool) -> Result<(), Error>;
34 fn write_bits(&self, address: u16, num: u16, src: &[u8]) -> Result<u16, Error>;
35 fn write_register(&self, address: u16, value: u16) -> Result<(), Error>;
36 fn write_registers(&self, address: u16, num: u16, src: &[u16]) -> Result<u16, Error>;
37 fn write_and_read_registers(
38 &self,
39 write_address: u16,
40 write_num: u16,
41 src: &[u16],
42 read_address: u16,
43 read_num: u16,
44 dest: &mut [u16],
45 ) -> Result<u16, Error>;
46 fn mask_write_register(&self, address: u16, and_mask: u16, or_mask: u16) -> Result<(), Error>;
47 fn send_raw_request(&self, raw_request: &mut [u8], lenght: usize) -> Result<u16, Error>;
48 fn receive_confirmation(&self, response: &mut [u8]) -> Result<u16, Error>;
49}
50
51// TODO: add real, working examples
52impl ModbusClient for Modbus {
53 /// `read_bits` - read many bits
54 ///
55 /// The [`read_bits()`](#method.read_bits) function shall read the status of the `num` bits (coils) to the
56 /// `address` of the remote device. The result of reading is stored in `dest` slice as unsigned bytes (8 bits) set
57 /// to TRUE or FALSE.
58 ///
59 /// The function uses the **Modbus function code 0x01** (read coil status).
60 ///
61 /// # Return value
62 ///
63 /// The function returns a `Result` containing the number of read bits if successful. Otherwise it returns an Error.
64 ///
65 /// # Parameters
66 ///
67 /// * `address` - address of the remote device
68 /// * `num` - number of coils to read
69 /// * `dest` - the result of the reading is stored here
70 ///
71 /// # Examples
72 ///
73 /// ```rust,no_run
74 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
75 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
76 /// let mut dest = vec![0u8; 100];
77 ///
78 /// assert!(modbus.read_bits(0, 1, &mut dest).is_ok());
79 /// ```
80 fn read_bits(&self, address: u16, num: u16, dest: &mut [u8]) -> Result<u16, Error> {
81 unsafe {
82 match ffi::modbus_read_bits(self.ctx, address as c_int, num as c_int, dest.as_mut_ptr())
83 {
84 -1 => Err(Error::Client {
85 msg: "read_bits failure".to_owned(),
86 source: ::std::io::Error::last_os_error(),
87 }),
88 len => Ok(len as u16),
89 }
90 }
91 }
92
93 /// `read_input_bits` - read many input bits
94 ///
95 /// The [`read_input_bits()`](#method.read_input_bits) function shall read the content of the `num` input bits to
96 /// the `address` of the remote device. The result of reading is stored in `dest` slice as unsigned bytes (8 bits)
97 /// set to TRUE or FALSE.
98 ///
99 /// The function uses the **Modbus function code 0x02** (read input status).
100 ///
101 /// # Return value
102 ///
103 /// The function returns a `Result` containing the number of read bits if successful. Otherwise it returns an Error.
104 ///
105 /// # Parameters
106 ///
107 /// * `address` - address of the remote device
108 /// * `num` - number of input bits to read
109 /// * `dest` - the result of the reading is stored here
110 ///
111 /// # Examples
112 ///
113 /// ```rust,no_run
114 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
115 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
116 /// let mut dest = vec![0u8; 100];
117 ///
118 /// assert!(modbus.read_input_bits(0, 1, &mut dest).is_ok());
119 /// ```
120 fn read_input_bits(&self, address: u16, num: u16, dest: &mut [u8]) -> Result<u16, Error> {
121 unsafe {
122 match ffi::modbus_read_input_bits(
123 self.ctx,
124 address as c_int,
125 num as c_int,
126 dest.as_mut_ptr(),
127 ) {
128 -1 => Err(Error::Client {
129 msg: "read_input_bits".to_owned(),
130 source: ::std::io::Error::last_os_error(),
131 }),
132 len => Ok(len as u16),
133 }
134 }
135 }
136
137 /// `read_registers` - read many registers
138 ///
139 /// The [`read_registers()`](#method.read_registers) function shall read the content of the `num` holding registers
140 /// to the `address` of the remote device. The result of reading is stored in `dest` slice as u16 word values.
141 ///
142 /// The function uses the **Modbus function code 0x03** (read holding registers).
143 ///
144 /// # Return value
145 ///
146 /// The function returns a `Result` containing the number of read bits if successful. Otherwise it returns an Error.
147 ///
148 /// # Parameters
149 ///
150 /// * `address` - address of the remote device
151 /// * `num` - number of holding registers to read
152 /// * `dest` - the result of the reading is stored here
153 ///
154 /// # Examples
155 ///
156 /// ```rust,no_run
157 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
158 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
159 /// let mut dest = vec![0u16; 100];
160 ///
161 /// assert!(modbus.read_registers(0, 1, &mut dest).is_ok());
162 /// ```
163 fn read_registers(&self, address: u16, num: u16, dest: &mut [u16]) -> Result<u16, Error> {
164 unsafe {
165 match ffi::modbus_read_registers(
166 self.ctx,
167 address as c_int,
168 num as c_int,
169 dest.as_mut_ptr(),
170 ) {
171 -1 => Err(Error::Client {
172 msg: "read_registers".to_owned(),
173 source: ::std::io::Error::last_os_error(),
174 }),
175 len => Ok(len as u16),
176 }
177 }
178 }
179
180 /// `read_input_registers` - read many input registers
181 ///
182 /// The [`read_input_registers()`](#method.read_input_registers) function shall read the content of the `num`
183 /// holding registers to the `address` of the remote device. The result of reading is stored in `dest` slice as u16
184 /// word values.
185 ///
186 /// The function uses the **Modbus function code 0x04** (read input registers). The holding registers and input
187 /// registers have different historical meaning, but nowadays it’s more common to use holding registers only.
188 ///
189 /// # Return value
190 ///
191 /// The function returns a `Result` containing the number of read bits if successful. Otherwise it returns an Error.
192 ///
193 /// # Parameters
194 ///
195 /// * `address` - address of the remote device
196 /// * `num` - number of input registers to read
197 /// * `dest` - the result of the reading is stored here
198 ///
199 /// # Examples
200 ///
201 /// ```rust,no_run
202 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
203 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
204 /// let mut dest = vec![0u16; 100];
205 ///
206 /// assert!(modbus.read_input_registers(0, 1, &mut dest).is_ok());
207 /// ```
208 fn read_input_registers(&self, address: u16, num: u16, dest: &mut [u16]) -> Result<u16, Error> {
209 unsafe {
210 match ffi::modbus_read_input_registers(
211 self.ctx,
212 address as c_int,
213 num as c_int,
214 dest.as_mut_ptr(),
215 ) {
216 -1 => Err(Error::Client {
217 msg: "read_input_registers".to_owned(),
218 source: ::std::io::Error::last_os_error(),
219 }),
220 len => Ok(len as u16),
221 }
222 }
223 }
224
225 /// `report_slave_id` - returns a description of the controller
226 ///
227 /// The [`report_slave_id()`](#method.report_slave_id) function shall send a request to the controller to obtain a
228 /// description of the controller. The response stored in `dest` contains:
229 /// * the slave ID, this unique ID is in reality not unique at all so it's not possible to depend on it to know
230 /// how the information are packed in the response.
231 /// * the run indicator status (0x00 = OFF, 0xFF = ON)
232 /// * additional data specific to each controller. For example, libmodbus returns the version of the library as
233 /// a string.
234 ///
235 /// # Return value
236 ///
237 /// The function returns a `Result` containing the number of read bits if successful. If the output was truncated
238 /// due the `max_dest` limit then the return value is the number of bytes which would have been written to `dest`.
239 /// Thus, a return value greater than the `max_dest` means that the resonse data was truncated.
240 /// Otherwise the Result contains an Error.
241 ///
242 /// # Parameters
243 ///
244 /// * `max_dest` - limit, write `max_dest` bytes from the response to `dest`
245 /// * `dest` - the result of the reading is stored here
246 ///
247 /// # Examples
248 ///
249 /// ```rust,no_run
250 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
251 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
252 /// let mut bytes = vec![0u8; Modbus::MAX_PDU_LENGTH];
253 ///
254 /// assert!(modbus.report_slave_id(Modbus::MAX_PDU_LENGTH, &mut bytes).is_ok());
255 /// // assert_eq!(bytes, vec![180, 255, 76, 77, 66, 51, 46, 49, 46, 52]));
256 /// ```
257 fn report_slave_id(&self, max_dest: usize, dest: &mut [u8]) -> Result<u16, Error> {
258 unsafe {
259 match ffi::modbus_report_slave_id(self.ctx, max_dest as c_int, dest.as_mut_ptr()) {
260 -1 => Err(Error::Client {
261 msg: "report_slave_id".to_owned(),
262 source: ::std::io::Error::last_os_error(),
263 }),
264 len => Ok(len as u16),
265 }
266 }
267 }
268
269 /// `write_bit` - write a single bit
270 ///
271 /// The [`write_bit()`](#method.write_bit) function shall write the `status` at the `address` of the remote device.
272 /// The value must be set to `true` of `false`.
273 ///
274 /// The function uses the **Modbus function code 0x05** (force single coil).
275 ///
276 /// # Return value
277 ///
278 /// The function return an OK Result, containing a one, if successful. Otherwise it contains an Error.
279 ///
280 /// # Parameters
281 ///
282 /// * `address` - address of the remote device
283 /// * `status` - status that should write at the address `addr`
284 ///
285 /// # Examples
286 ///
287 /// ```rust,no_run
288 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
289 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
290 /// let address = 1;
291 ///
292 /// assert!(modbus.write_bit(address, true).is_ok());
293 /// ```
294 fn write_bit(&self, address: u16, status: bool) -> Result<(), Error> {
295 unsafe {
296 match ffi::modbus_write_bit(self.ctx, address as c_int, status as c_int) {
297 -1 => Err(Error::Client {
298 msg: "write_bit".to_owned(),
299 source: ::std::io::Error::last_os_error(),
300 }),
301 1 => Ok(()),
302 _ => panic!("libmodbus API incompatible response"),
303 }
304 }
305 }
306
307 /// `write_register` - write a single register
308 ///
309 /// The [`write_register()`](#method.write_register) function shall write the value of value holding registers at
310 /// the address addr of the remote device.
311 ///
312 /// The function uses the **Modbus function code 0x06** (preset single register).
313 ///
314 /// # Return value
315 ///
316 /// The function return an OK Result, containing a one, if successful. Otherwise it contains an Error.
317 ///
318 /// # Parameters
319 ///
320 /// * `address` - address of the remote device
321 /// * `value` - vec with the value of the holding register which shall be written
322 ///
323 /// # Examples
324 ///
325 /// ```rust,no_run
326 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
327 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
328 /// let address = 1;
329 /// let value = u16::max_value();
330 ///
331 /// assert!(modbus.write_register(address, value).is_ok());
332 /// ```
333 fn write_register(&self, address: u16, value: u16) -> Result<(), Error> {
334 unsafe {
335 match ffi::modbus_write_register(self.ctx, address as c_int, value) {
336 -1 => Err(Error::Client {
337 msg: "write_register".to_owned(),
338 source: ::std::io::Error::last_os_error(),
339 }),
340 1 => Ok(()),
341 _ => panic!("libmodbus API incompatible response"),
342 }
343 }
344 }
345
346 /// `write_bits` - write many bits
347 ///
348 /// The [`write_bits()`](#method.write_bits) function shall write the status of the bits (coils) from `src` at the
349 /// `address` of the remote device. The `src` array must contains bytes set to TRUE or FALSE.
350 ///
351 /// The function shall return the number of written bits if successful. Otherwise it contains an Error.
352 ///
353 /// # Return value
354 ///
355 /// The function returns a Ok Result containing the number of written bits. Otherwise it contains an Error.
356 ///
357 /// # Parameters
358 ///
359 /// * `address` - address of the remote device
360 /// * `num` - number or bits that should be writen at the address `address`
361 /// * `src` - vec of `0` and `1` (true and false) values
362 ///
363 /// # Examples
364 ///
365 /// ```rust,no_run
366 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
367 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
368 /// let address = 1;
369 /// let tab_bytes = vec![0u8];
370 ///
371 /// assert_eq!(modbus.write_bits(address, 1, &tab_bytes).unwrap(), 1);
372 /// ```
373 fn write_bits(&self, address: u16, num: u16, src: &[u8]) -> Result<u16, Error> {
374 unsafe {
375 match ffi::modbus_write_bits(self.ctx, address as c_int, num as c_int, src.as_ptr()) {
376 -1 => Err(Error::Client {
377 msg: "write_bits".to_owned(),
378 source: ::std::io::Error::last_os_error(),
379 }),
380 num => Ok(num as u16),
381 }
382 }
383 }
384
385 /// `write_registers` - write many registers
386 ///
387 /// The [`write_registers()`](#method.write_registers) function shall write the content of the `num` holding
388 /// registers
389 /// from the array `src` at `address` of the remote device.
390 ///
391 /// The function uses the **Modbus function code 0x10** (preset multiple registers).
392 ///
393 /// # Return value
394 ///
395 /// The function returns a Ok Result containing the number of written bytes. Otherwise it contains an Error.
396 ///
397 /// # Parameters
398 ///
399 /// * `address` - address of the remote device
400 /// * `num` - number of holding registers that should write at the address `address`
401 /// * `src` - holding register
402 ///
403 /// # Examples
404 ///
405 /// ```rust,no_run
406 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
407 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
408 /// let address = 1;
409 /// let tab_bytes = vec![0u16];
410 ///
411 /// assert_eq!(modbus.write_registers(address, 1, &tab_bytes).unwrap(), 1);
412 /// ```
413 fn write_registers(&self, address: u16, num: u16, src: &[u16]) -> Result<u16, Error> {
414 unsafe {
415 match ffi::modbus_write_registers(
416 self.ctx,
417 address as c_int,
418 num as c_int,
419 src.as_ptr(),
420 ) {
421 -1 => Err(Error::Client {
422 msg: "write_registers".to_owned(),
423 source: ::std::io::Error::last_os_error(),
424 }),
425 num => Ok(num as u16),
426 }
427 }
428 }
429
430 /// `write_and_read_registers` - write and read many registers in a single transaction
431 ///
432 /// The [`write_and_read_registers()`](#method.write_and_read_registers) function shall write the content of the
433 /// write_nb holding registers from the array src to the address write_addr of the remote device then shall read
434 /// the content of the read_nb holding registers to the address read_addr of the remote device. The result of
435 /// reading is stored in dest array as word values (16 bits).
436 ///
437 /// The function uses the **Modbus function code 0x17** (write/read registers).
438 ///
439 /// # Return value
440 ///
441 /// The function returns a Ok Result containing the number of read registers. Otherwise it contains an Error.
442 ///
443 /// # Parameters
444 ///
445 /// * `write_address` - address of the remote device
446 /// * `write_num` - number of holding registers
447 /// * `src` - holding register
448 /// * `read_address` - address of the remote device
449 /// * `read_num` - number of holding registers
450 /// * `dest` - holding register
451 ///
452 /// # Examples
453 ///
454 /// ```rust,no_run
455 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
456 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
457 /// let address = 1;
458 /// let request_bytes = vec![1u16];
459 /// let mut response_bytes = vec![0u16];
460 ///
461 /// assert_eq!(modbus.write_and_read_registers(
462 /// address, 1, &request_bytes,
463 /// address, 1, &mut response_bytes).unwrap(), 1);
464 /// ```
465 fn write_and_read_registers(
466 &self,
467 write_address: u16,
468 write_num: u16,
469 src: &[u16],
470 read_address: u16,
471 read_num: u16,
472 dest: &mut [u16],
473 ) -> Result<u16, Error> {
474 unsafe {
475 match ffi::modbus_write_and_read_registers(
476 self.ctx,
477 write_address as c_int,
478 write_num as c_int,
479 src.as_ptr(),
480 read_address as c_int,
481 read_num as c_int,
482 dest.as_mut_ptr(),
483 ) {
484 -1 => Err(Error::Client {
485 msg: "write_and_read_registers".to_owned(),
486 source: ::std::io::Error::last_os_error(),
487 }),
488 num => Ok(num as u16),
489 }
490 }
491 }
492
493 /// `mask_write_register` - mask a single register
494 ///
495 /// The [`mask_write_register()`](#method.mask_write_register) function shall modify the value of the
496 /// holding register at the address `address` of the remote device using the algorithm:
497 ///
498 /// ```bash,no_run
499 /// new value = (current value AND 'and') OR ('or' AND (NOT 'and'))
500 /// ```
501 ///
502 /// The function uses the **Modbus function code 0x16** (mask single register).
503 ///
504 /// # Return value
505 ///
506 /// The function returns a Ok Result if succesful. Otherwise it contains an Error.
507 ///
508 /// # Parameters
509 ///
510 /// * `address` - address of the remote device
511 /// * `and_mask` - AND mask
512 /// * `or_mask` - OR mask
513 ///
514 /// # Examples
515 ///
516 /// ```rust,no_run
517 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
518 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
519 ///
520 /// assert!(modbus.mask_write_register(1, 0xF2, 0x25).is_ok());
521 /// ```
522 fn mask_write_register(&self, address: u16, and_mask: u16, or_mask: u16) -> Result<(), Error> {
523 unsafe {
524 match ffi::modbus_mask_write_register(self.ctx, address as c_int, and_mask, or_mask) {
525 -1 => Err(Error::Client {
526 msg: "mask_write_register".to_owned(),
527 source: ::std::io::Error::last_os_error(),
528 }),
529 1 => Ok(()),
530 _ => panic!("libmodbus API incompatible response"),
531 }
532 }
533 }
534
535 /// `send_raw_request` - send a raw request
536 ///
537 /// The [`send_raw_request()`](#method.send_raw_request) function shall send a request via the socket of the
538 /// current modbus contest.
539 ///
540 /// This function must be used for debugging purposes because you have to take care to make a valid request by hand.
541 /// The function only adds to the message, the header or CRC of the selected backend, so `raw_request` must start
542 /// and contain at least a slave/unit identifier and a function code.
543 /// This function can be used to send request not handled by the library.
544 ///
545 /// The enum [`FunctionCode`](enum.FunctionCode.html) provides a list of supported Modbus functions codes, to help
546 /// build of raw requests.
547 ///
548 /// # Parameters
549 ///
550 /// * `raw_request` - raw request to send
551 /// * `length` - raw request length
552 ///
553 /// # Return value
554 ///
555 /// The function returns a Result, containing the full message lenght, counting the extra data relating to the
556 /// backend, if successful. Otherwise it contains an Error.
557 ///
558 /// # Examples
559 ///
560 /// ```rust,no_run
561 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP, FunctionCode};
562 ///
563 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
564 /// let mut raw_request: Vec<u8> = vec![0xFF, FunctionCode::ReadHoldingRegisters as u8, 0x00, 0x01, 0x0, 0x05];
565 /// let mut response = vec![0u8; Modbus::TCP_MAX_ADU_LENGTH];
566 /// let request_len = raw_request.len();
567 ///
568 /// assert_eq!(modbus.send_raw_request(&mut raw_request, request_len).unwrap(), 6);
569 /// assert!(modbus.receive_confirmation(&mut response).is_ok());
570 /// ```
571 fn send_raw_request(&self, raw_request: &mut [u8], lenght: usize) -> Result<u16, Error> {
572 unsafe {
573 match ffi::modbus_send_raw_request(self.ctx, raw_request.as_mut_ptr(), lenght as c_int)
574 {
575 -1 => Err(Error::Client {
576 msg: "send_raw_request".to_owned(),
577 source: ::std::io::Error::last_os_error(),
578 }),
579 num => Ok(num as u16),
580 }
581 }
582 }
583
584 /// `receive_confirmation` - receive a confirmation request
585 ///
586 /// The [`receive_confirmation()`](#method.receive_confirmation) function shall receive a request via the socket of
587 /// the context `ctx` Member of the [Modbus struct](struct.Modbus.html).
588 /// This function must be used for debugging purposes because the received response isn’t checked against the
589 /// initial request.
590 /// This function can be used to receive request not handled by the library.
591 ///
592 /// The maximum size of the response depends on the used backend, in RTU the `response` array
593 /// must be `Modbus::RTU_MAX_ADU_LENGTH` bytes and in TCP it must be
594 /// `Modbus::TCP_MAX_ADU_LENGTH` bytes. If you want to write code compatible with both,
595 /// you can use the constant `Modbus::MAX_ADU_LENGTH` (maximum value of all libmodbus backends).
596 ///
597 /// # Return value
598 ///
599 /// The function returns a Result containing the response length if successful.
600 /// The returned request length can be zero if the indication request is ignored
601 /// (eg. a query for another slave in RTU mode). Otherwise it contains an Error.
602 ///
603 /// # Parameters
604 ///
605 /// * `response` - store for the received response
606 ///
607 /// # Examples
608 ///
609 /// ```rust,no_run
610 /// use libmodbus::{Modbus, ModbusClient, ModbusTCP};
611 /// let modbus = Modbus::new_tcp("127.0.0.1", 1502).unwrap();
612 /// let mut response = vec![0u8; Modbus::MAX_ADU_LENGTH];
613 ///
614 /// assert!(modbus.receive_confirmation(&mut response).is_ok());
615 /// ```
616 fn receive_confirmation(&self, response: &mut [u8]) -> Result<u16, Error> {
617 unsafe {
618 match ffi::modbus_receive_confirmation(self.ctx, response.as_mut_ptr()) {
619 -1 => Err(Error::Client {
620 msg: "receive_confirmation".to_owned(),
621 source: ::std::io::Error::last_os_error(),
622 }),
623 len => Ok(len as u16),
624 }
625 }
626 }
627}