pub struct Client { /* private fields */ }Expand description
A Modbus RTU client on a serial line: the gateway, the master in the specification’s words, that sends each request and waits for its reply.
Each transaction follows the Modbus over Serial Line specification. The client leaves
the line silent for 3.5 characters, or 1.75 ms above 19200 baud, so the request starts a
new frame; drops anything stale waiting in the port; writes the request; and reads the
reply to the length the request implies, against the response timeout. The reply’s CRC,
unit, and function are checked before a value is read out of it, and a refusal comes
back as ClientError::Exception. A write to BROADCAST reaches every device and
draws no reply, so the client waits out the turnaround delay instead. The specification
reserves units 248 to 255, and a client still sends to them, since some devices answer on
one.
On the kernel’s serial device every wait is real. On a simulated, paired, or scripted
port nothing waits: the waits are counted in the port’s
waited_micros, so a test of a meter that never answers
runs at once and still says how long a real one would have taken.
§Examples
use std::sync::{Arc, Mutex};
use pamoja_hal::port::{Parity, SerialPort, Settings};
use pamoja_modbus::{Client, Server};
// A power meter at unit 17, simulated on the far end of a 19200 8E1 line.
let meter = Server::new(17)?.with_holding_registers(107, &[2301, 418, 0]);
let meter = Arc::new(Mutex::new(meter));
let line = Settings::new(19_200).with_parity(Parity::Even);
let mut client = Client::new(SerialPort::simulated(line, Arc::clone(&meter)));
assert_eq!(client.read_holding_registers(17, 107, 3)?, [2301, 418, 0]);
client.write_single_register(17, 109, 1)?;
assert_eq!(meter.lock().unwrap().holding_register(109), Some(1));Implementations§
Source§impl Client
impl Client
Sourcepub fn with_response_timeout(self, timeout: Duration) -> Client
pub fn with_response_timeout(self, timeout: Duration) -> Client
Sourcepub fn with_turnaround(self, delay: Duration) -> Client
pub fn with_turnaround(self, delay: Duration) -> Client
Sourcepub fn set_response_timeout(&mut self, timeout: Duration)
pub fn set_response_timeout(&mut self, timeout: Duration)
Changes how long the client waits for a whole reply, as
with_response_timeout does when the client is made.
§Arguments
timeout- the response timeout.
Sourcepub fn set_turnaround(&mut self, delay: Duration)
pub fn set_turnaround(&mut self, delay: Duration)
Changes how long the client leaves the line quiet after a broadcast, as
with_turnaround does when the client is made.
§Arguments
delay- the turnaround delay.
Sourcepub fn response_timeout(&self) -> Duration
pub fn response_timeout(&self) -> Duration
Returns how long the client waits for a reply.
Sourcepub fn turnaround(&self) -> Duration
pub fn turnaround(&self) -> Duration
Returns how long the client leaves the line quiet after a broadcast.
Sourcepub fn read_coils(
&mut self,
unit: u8,
start: u16,
quantity: u16,
) -> Result<Vec<bool>, ClientError>
pub fn read_coils( &mut self, unit: u8, start: u16, quantity: u16, ) -> Result<Vec<bool>, ClientError>
Reads coils, function 0x01.
§Arguments
unit- the device, 1 to 247.start- the first coil’s address.quantity- how many, 1 to 2000.
§Returns
The coils’ states, in address order.
§Errors
Any ClientError: a quantity out of range, a broadcast, a port failure, a timeout,
a reply that fails its checks, or the device’s exception.
Sourcepub fn read_discrete_inputs(
&mut self,
unit: u8,
start: u16,
quantity: u16,
) -> Result<Vec<bool>, ClientError>
pub fn read_discrete_inputs( &mut self, unit: u8, start: u16, quantity: u16, ) -> Result<Vec<bool>, ClientError>
Reads discrete inputs, function 0x02.
§Arguments
unit- the device, 1 to 247.start- the first input’s address.quantity- how many, 1 to 2000.
§Returns
The inputs’ states, in address order.
§Errors
Any ClientError, as for read_coils.
Sourcepub fn read_holding_registers(
&mut self,
unit: u8,
start: u16,
quantity: u16,
) -> Result<Vec<u16>, ClientError>
pub fn read_holding_registers( &mut self, unit: u8, start: u16, quantity: u16, ) -> Result<Vec<u16>, ClientError>
Reads holding registers, function 0x03.
§Arguments
unit- the device, 1 to 247.start- the first register’s address.quantity- how many, 1 to 125.
§Returns
The registers’ values, in address order.
§Errors
Any ClientError, as for read_coils.
Sourcepub fn read_input_registers(
&mut self,
unit: u8,
start: u16,
quantity: u16,
) -> Result<Vec<u16>, ClientError>
pub fn read_input_registers( &mut self, unit: u8, start: u16, quantity: u16, ) -> Result<Vec<u16>, ClientError>
Reads input registers, function 0x04.
§Arguments
unit- the device, 1 to 247.start- the first register’s address.quantity- how many, 1 to 125.
§Returns
The registers’ values, in address order.
§Errors
Any ClientError, as for read_coils.
Sourcepub fn write_single_coil(
&mut self,
unit: u8,
address: u16,
on: bool,
) -> Result<(), ClientError>
pub fn write_single_coil( &mut self, unit: u8, address: u16, on: bool, ) -> Result<(), ClientError>
Writes one coil, function 0x05.
§Arguments
unit- the device, 1 to 247, orBROADCASTfor every device.address- the coil’s address.on- the state to write.
§Errors
Any ClientError but BroadcastRead.
Sourcepub fn write_single_register(
&mut self,
unit: u8,
address: u16,
value: u16,
) -> Result<(), ClientError>
pub fn write_single_register( &mut self, unit: u8, address: u16, value: u16, ) -> Result<(), ClientError>
Writes one holding register, function 0x06.
§Arguments
unit- the device, 1 to 247, orBROADCASTfor every device.address- the register’s address.value- the value to write.
§Errors
Any ClientError but BroadcastRead.
Sourcepub fn write_multiple_coils(
&mut self,
unit: u8,
start: u16,
values: &[bool],
) -> Result<(), ClientError>
pub fn write_multiple_coils( &mut self, unit: u8, start: u16, values: &[bool], ) -> Result<(), ClientError>
Writes a run of coils, function 0x0F.
§Arguments
unit- the device, 1 to 247, orBROADCASTfor every device.start- the first coil’s address.values- the states to write, 1 to 1968 of them, in address order.
§Errors
Any ClientError but BroadcastRead.
Sourcepub fn write_multiple_registers(
&mut self,
unit: u8,
start: u16,
values: &[u16],
) -> Result<(), ClientError>
pub fn write_multiple_registers( &mut self, unit: u8, start: u16, values: &[u16], ) -> Result<(), ClientError>
Writes a run of holding registers, function 0x10.
§Arguments
unit- the device, 1 to 247, orBROADCASTfor every device.start- the first register’s address.values- the values to write, 1 to 123 of them, in address order.
§Errors
Any ClientError but BroadcastRead.