R4DCB08

Struct R4DCB08 

Source
pub struct R4DCB08;
Available on crate features tokio-rtu or tokio-tcp only.
Expand description

Asynchronous client for interacting with the R4DCB08 temperature module over Modbus.

This struct provides methods to read sensor data and configure the module’s operational parameters by wrapping tokio-modbus asynchronous operations.

All methods that interact with the Modbus device are async and return Futures.

Implementations§

Source§

impl R4DCB08

Source

pub async fn read_temperatures(ctx: &mut Context) -> Result<Temperatures, Error>

Reads the current temperatures from all 8 available channels in degrees Celsius (°C).

If a channel’s sensor is not connected or reports an error, the corresponding proto::Temperature value will be proto::Temperature::NAN.

§Returns

A Result<proto::Temperatures> containing the temperatures for all channels, or a Modbus error.

§Errors
  • tokio_modbus::Error if a Modbus communication error occurs (e.g., IO error, timeout handled by wrapper, Modbus exception).
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidData if the device returns an unexpected number of registers.
§Examples
let temperatures = tokio::time::timeout(Duration::from_secs(2), R4DCB08::read_temperatures(&mut modbus_ctx)).await??;
println!("Temperatures read successfully:");
for (i, temp) in temperatures.iter().enumerate() {
    println!("  Channel {}: {}", i, temp); // `temp` uses Display impl from protocol
}
Source

pub async fn read_temperature_correction( ctx: &mut Context, ) -> Result<TemperatureCorrection, Error>

Reads the configured temperature correction values (°C) for all 8 channels.

A proto::Temperature value of 0.0 typically means no correction is applied, while proto::Temperature::NAN might indicate an uninitialized or error state for a correction value if read.

§Returns

A Result<proto::TemperatureCorrection> containing correction values for each channel, or a Modbus error.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidData if the device returns an unexpected number of registers.
§Examples
let corrections = tokio::time::timeout(Duration::from_secs(2), R4DCB08::read_temperature_correction(&mut modbus_ctx)).await??;
println!("Temperature correction values: {}", corrections);
Source

pub async fn set_temperature_correction( ctx: &mut Context, channel: Channel, correction: Temperature, ) -> Result<(), Error>

Sets a temperature correction value for a specific channel.

The correction value will be added to the raw temperature reading by the module. Setting a correction value of 0.0 effectively disables it for that channel.

§Arguments
  • channel - The proto::Channel to configure.
  • correction - The proto::Temperature correction value to apply (in °C). This type ensures the temperature value is within the representable range.
§Returns

A Result<()> indicating success or failure of the write operation.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidInput if the correction value is NAN.
§Examples
use r4dcb08_lib::protocol::{Channel, Temperature, Error};
use std::time::Duration;

// Set the temperature correction for channel 3 to +1.3°C.
let channel = Channel::try_from(3)?;
let correction_value = Temperature::try_from(1.3)?;

tokio::time::timeout(Duration::from_secs(2), R4DCB08::set_temperature_correction(&mut modbus_ctx, channel, correction_value)).await??;
println!("Correction for channel {} set to {}.", channel, correction_value);
Source

pub async fn read_automatic_report( ctx: &mut Context, ) -> Result<AutomaticReport, Error>

Reads the automatic temperature reporting interval.

An interval of 0 seconds (proto::AutomaticReport::DISABLED) means automatic reporting is off.

§Returns

A Result<proto::AutomaticReport> indicating the configured reporting interval, or a Modbus error.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidData if the device returns malformed data.
§Examples
let report = tokio::time::timeout(Duration::from_secs(2), R4DCB08::read_automatic_report(&mut modbus_ctx)).await??;
if report.is_disabled() {
    println!("Automatic reporting is disabled.");
} else {
    println!("Automatic report interval: {} seconds.", report.as_secs());
}
Source

pub async fn set_automatic_report( ctx: &mut Context, report: AutomaticReport, ) -> Result<(), Error>

Sets the automatic temperature reporting interval.

When enabled (interval > 0), the module may periodically send temperature data unsolicitedly over the RS485 bus (behavior depends on module firmware).

§Arguments
  • report - The proto::AutomaticReport interval (0 = disabled, 1-255 seconds). The proto::AutomaticReport type ensures the value is within the valid hardware range.
§Returns

A Result<()> indicating success or failure of the write operation.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
§Examples
use r4dcb08_lib::protocol::{AutomaticReport, Error};
use std::time::Duration;

let report_interval = AutomaticReport::try_from(Duration::from_secs(10))?;

tokio::time::timeout(Duration::from_secs(2), R4DCB08::set_automatic_report(&mut modbus_ctx, report_interval)).await??;
println!("Automatic report interval set to 10 seconds.");
Source

pub async fn read_baud_rate(ctx: &mut Context) -> Result<BaudRate, Error>

Reads the current Modbus communication baud rate setting from the device.

§Returns

A Result<proto::BaudRate> containing the configured baud rate, or a Modbus error.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidData if the device returns an invalid baud rate code.
§Examples
let baud_rate = tokio::time::timeout(Duration::from_secs(2), R4DCB08::read_baud_rate(&mut modbus_ctx)).await??;
println!("Current baud rate: {}", baud_rate);
Source

pub async fn set_baud_rate( ctx: &mut Context, baud_rate: BaudRate, ) -> Result<(), Error>

Sets the Modbus communication baud rate for the device.

Important: The new baud rate setting will only take effect after the R4DCB08 module is power cycled (turned off and then on again).

§Arguments
  • baud_rate - The desired proto::BaudRate to set.
§Returns

A Result<()> indicating success or failure of the write operation.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
§Examples
use r4dcb08_lib::protocol::{BaudRate, Error};
use std::time::Duration;

// Set the baud rate to 19200.
let new_baud_rate = BaudRate::B19200; // Direct enum variant
// Or from u16:
// let new_baud_rate = BaudRate::try_from(19200)?;

tokio::time::timeout(Duration::from_secs(2), R4DCB08::set_baud_rate(&mut modbus_ctx, new_baud_rate)).await??;
println!("Baud rate set to {}. Power cycle the device for changes to take effect.", new_baud_rate);
Source

pub async fn factory_reset(ctx: &mut Context) -> Result<(), Error>

Resets the R4DCB08 module to its factory default settings.

This resets all configurable parameters like Modbus Address, Baud Rate, Temperature Corrections, etc., to their original defaults.

Important:

  • After this command is successfully sent, the module may become unresponsive on the Modbus bus until it is power cycled.
  • A power cycle (turning the device off and then on again) is required to complete the factory reset process and for the default settings to be applied.
§Returns

A Result<()> indicating if the reset command was sent successfully. It does not confirm the reset is complete, only that the Modbus write was acknowledged.

§Errors
  • tokio_modbus::Error for Modbus communication errors. A timeout error after this command might be expected as the device resets and may not send a response.
§Examples
println!("Attempting to send factory reset command...");
match tokio::time::timeout(Duration::from_secs(2), R4DCB08::factory_reset(&mut modbus_ctx)).await {
    Ok(Ok(())) => println!("Factory reset command sent. Power cycle the device to complete."),
    Ok(Err(e)) => eprintln!("Modbus error during factory reset: {}", e),
    Err(e) => {
        // After the a successful factory reset we get no response :-(
        println!("Factory reset command sent. Device timed out as expected. Power cycle to complete.");
    }
}
Source

pub async fn read_address(ctx: &mut Context) -> Result<Address, Error>

Reads the current Modbus device address (Slave ID) from the module.

Important Usage Notes:

  • This command is typically used when the device’s current address is unknown. To do this, the Modbus request must be sent to the broadcast address (proto::Address::BROADCAST).
  • Single Device Only: Only one R4DCB08 module should be connected to the Modbus bus when executing this command with the broadcast address. If multiple devices are present, they might all respond, leading to data collisions and errors.
§Returns

A Result<proto::Address> containing the device’s configured Modbus address, or a Modbus error.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
  • tokio_modbus::Error::Transport with std::io::ErrorKind::InvalidData if the device returns a malformed or out-of-range address.
§Examples
use r4dcb08_lib::tokio_async::R4DCB08;
use r4dcb08_lib::protocol;
use std::time::Duration;

// Requires serial port features enabled in tokio-modbus
let builder = tokio_serial::new("/dev/ttyUSB0", 9600) // Baud rate 9600
   .parity(tokio_serial::Parity::None)
   .stop_bits(tokio_serial::StopBits::One)
   .data_bits(tokio_serial::DataBits::Eight)
   .flow_control(tokio_serial::FlowControl::None);

let port = tokio_serial::SerialStream::open(&builder)?;
// Assume only one device connected, use broadcast address for reading
let mut modbus_ctx = tokio_modbus::client::rtu::attach_slave(port, tokio_modbus::Slave(*protocol::Address::BROADCAST));

println!("Attempting to read device address using broadcast...");
let device_address = tokio::time::timeout(Duration::from_secs(2), R4DCB08::read_address(&mut modbus_ctx)).await??;
println!("Successfully read device address: {}", device_address);
Source

pub async fn set_address( ctx: &mut Context, new_address: Address, ) -> Result<(), Error>

Sets a new Modbus device address.

Warning:

  • This permanently changes the device’s Modbus address.
  • This command must be sent while addressing the device using its current Modbus address.
  • After successfully changing the address, subsequent communication with the device must use the new address.
§Arguments
  • new_address - The new proto::Address to assign to the device.
§Returns

A Result<()> indicating success or failure of the write operation.

§Errors
  • tokio_modbus::Error for Modbus communication errors.
§Examples
use r4dcb08_lib::tokio_async::R4DCB08;
use r4dcb08_lib::protocol::{Address, Error};
use std::time::Duration;

// Requires serial port features enabled in tokio-modbus
let builder = tokio_serial::new("/dev/ttyUSB0", 9600) // Baud rate 9600
   .parity(tokio_serial::Parity::None)
   .stop_bits(tokio_serial::StopBits::One)
   .data_bits(tokio_serial::DataBits::Eight)
   .flow_control(tokio_serial::FlowControl::None);

// --- Assume device is currently at address 1 ---
let current_device_address = Address::try_from(1)?;

let port = tokio_serial::SerialStream::open(&builder)?;
let mut modbus_ctx = tokio_modbus::client::rtu::attach_slave(port, tokio_modbus::Slave(*current_device_address));

// --- New address we want to set ---
let new_device_address = Address::try_from(10)?;

println!("Attempting to change device address from {} to {}...", current_device_address, new_device_address);
tokio::time::timeout(Duration::from_secs(2), R4DCB08::set_address(&mut modbus_ctx, new_device_address)).await??;
println!("Device address successfully changed to {}.", new_device_address);
println!("You will need to reconnect using the new address for further communication.");

Trait Implementations§

Source§

impl Debug for R4DCB08

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.