Skip to main content

Requests

Request parameters​

All requests take a RequestParam with two values:

  • UnitId: the device the request is for. On a serial line, it selects one of the servers sharing the line, and 0x00 is a broadcast. On TCP, it matters when talking to a gateway that relays requests to several devices, or to a device that hosts several units.
  • Timeout: the time allowed to send the request and receive its response. A request whose response doesn't arrive in time fails with a response timeout. One that couldn't even be sent in time fails with an I/O error, and the library closes and reopens the connection or serial port.

A common pattern is to create a RequestParam for each device you communicate with and reuse it on every request.

Read requests​

The library supports four read requests:

Request nameResponse type
read_coilsSingle bits
read_discrete_inputsSingle bits
read_holding_registers16-bit registers
read_input_registers16-bit registers

Each read request takes an AddressRange: a 16-bit start address and a count of values to read. One request can read up to 2000 coils or discrete inputs, or 125 registers. The library fails a request whose range is empty, runs past address 65535, or exceeds that limit, without sending it; split larger reads into several requests.

The response contains exactly the values you asked for, in address order, each paired with its address. The library fails the request if the server's response doesn't match it.

The following example demonstrates reading the first 5 coils from a device:

let params = RequestParam::new(UnitId::new(UNIT_ID), REQUEST_TIMEOUT);

let result = channel
.read_coils(params, AddressRange::try_from(0, 5).unwrap())
.await;

Write requests​

The library supports four write requests:

Request nameWrites
write_single_coilOne coil
write_single_registerOne holding register
write_multiple_coilsContiguous coils
write_multiple_registersContiguous holding registers

The "multiple" requests write contiguous points of the same type in one message, up to 1968 coils or 123 registers. As with reads, the library fails an empty or larger write without sending it, and fails the request if the server's reply doesn't match it.

To write discontinuous points, make several requests. Modbus lacks a transaction mechanism, so device state may change between requests.

The following example demonstrates how to write a coil:

let params = RequestParam::new(UnitId::new(UNIT_ID), REQUEST_TIMEOUT);

let result = channel
.write_single_coil(params, Indexed::new(0, true))
.await;

The following example demonstrates writing multiple registers:

let params = RequestParam::new(UnitId::new(UNIT_ID), REQUEST_TIMEOUT);

let result = channel
.write_multiple_registers(params, WriteMultiple::from(0, vec![0xCA, 0xFE]).unwrap())
.await;