Skip to main content

Requests

Request parameters

All requests take a RequestParam structure with the following fields:

  • UnitId: A single Modbus channel can communicate with many devices. The 8-bit unit ID specifies the device for which the request is intended. On a serial line, this is used to implement a multi-drop scheme. On TCP/IP, it is used when communicating with a gateway that relays the requests to multiple devices, or a single device that supports multiple virtual sub-devices.
  • Timeout: This is the maximum time to wait for a response before reporting an error.

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 parameter to specify what values are requested. It has a 16-bit start index and a 16-bit count value.

danger

The sum of the start and count fields cannot exceed 65,536. The library will automatically fail such invalid requests returning an error.

The asynchronous response will contain an iterator with the received values. If an error occurs, the iterator will be empty.

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

let params = RequestParam::new(UnitId::new(1), Duration::from_secs(1));

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

Write requests

The library supports four write requests:

  • write_single_coil
  • write_single_register
  • write_multiple_coils
  • write_multiple_registers
note

The registers that are written using the write_single_register and write_multiple_registers are holding registers.

The "single" requests, as their name suggests, writes a single point at a time. The "multiple" requests write multiple contiguous points of the same type in a single message.

In order to write a set of discontinuous points, you must perform multiple requests. Modbus does not have a transaction mechanism. Therefore, you must keep in mind that the device state might change in between requests.

The following example demonstrates how to write a coil:

let params = RequestParam::new(UnitId::new(1), Duration::from_secs(1));

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

The following example demonstrates writing the multiple registers:

let params = RequestParam::new(UnitId::new(1), Duration::from_secs(1));

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