r4dcb08_lib/
tokio_sync_safe_client.rs

1//! Synchronous `tokio-modbus` client for the R4DCB08 temperature module.
2//!
3//! This module provides a high-level API (`SafeClient` struct) to interact with
4//! the R4DCB08 8-channel temperature module using Modbus RTU or TCP. It handles
5//! the conversion between Rust types defined in the `crate::protocol` module and
6//! the raw Modbus register values.
7//!
8//! ## Example
9//!
10//! ```no_run
11//! use r4dcb08_lib::{
12//!     protocol::Address,
13//!     tokio_sync_safe_client::SafeClient,
14//! };
15//! use tokio_modbus::client::sync::tcp;
16//! use tokio_modbus::Slave;
17//!
18//! fn main() -> Result<(), Box<dyn std::error::Error>> {
19//!     // Connect to the device and create a stateful, safe client
20//!     let socket_addr = "192.168.1.100:502".parse()?;
21//!     let ctx = tcp::connect_slave(socket_addr, Slave(*Address::default()))?;
22//!     let mut client = SafeClient::new(ctx);
23//!
24//!     // Use the client to interact with the device
25//!     let temperatures = client.read_temperatures()?;
26//!
27//!     println!("Successfully read temperatures. Current values: {}", temperatures);
28//!
29//!     Ok(())
30//! }
31//! ```
32
33use crate::{protocol as proto, tokio_common::Result, tokio_sync};
34use std::sync::{Arc, Mutex};
35use tokio_modbus::{client::sync::Context, slave::SlaveContext, Slave};
36
37/// Synchronous client for interacting with the R4DCB08 temperature module over Modbus.
38///
39/// This struct provides methods to read sensor data and configure the module's
40/// operational parameters by wrapping `tokio-modbus` synchronous operations.
41#[derive(Clone)]
42pub struct SafeClient {
43    ctx: Arc<Mutex<Context>>,
44}
45
46impl SafeClient {
47    /// Creates a new `SafeClient` with a given `tokio-modbus` synchronous context.
48    pub fn new(ctx: Context) -> Self {
49        Self {
50            ctx: Arc::new(Mutex::new(ctx)),
51        }
52    }
53
54    /// Creates a new `SafeClient` from a shared `tokio-modbus` synchronous context.
55    pub fn from_shared(ctx: Arc<Mutex<Context>>) -> Self {
56        Self { ctx }
57    }
58
59    /// Clones the shared `tokio-modbus` synchronous context.
60    pub fn clone_shared(&self) -> Arc<Mutex<Context>> {
61        self.ctx.clone()
62    }
63
64    /// Reads the current temperatures from all 8 available channels in degrees Celsius (°C).
65    pub fn read_temperatures(&mut self) -> Result<proto::Temperatures> {
66        let mut ctx = self.ctx.lock().unwrap();
67        tokio_sync::R4DCB08::read_temperatures(&mut ctx)
68    }
69
70    /// Reads the configured temperature correction values (°C) for all 8 channels.
71    pub fn read_temperature_correction(&mut self) -> Result<proto::TemperatureCorrection> {
72        let mut ctx = self.ctx.lock().unwrap();
73        tokio_sync::R4DCB08::read_temperature_correction(&mut ctx)
74    }
75
76    /// Sets a temperature correction value for a specific channel.
77    pub fn set_temperature_correction(
78        &mut self,
79        channel: proto::Channel,
80        correction: proto::Temperature,
81    ) -> Result<()> {
82        let mut ctx = self.ctx.lock().unwrap();
83        tokio_sync::R4DCB08::set_temperature_correction(&mut ctx, channel, correction)
84    }
85
86    /// Reads the automatic temperature reporting interval.
87    pub fn read_automatic_report(&mut self) -> Result<proto::AutomaticReport> {
88        let mut ctx = self.ctx.lock().unwrap();
89        tokio_sync::R4DCB08::read_automatic_report(&mut ctx)
90    }
91
92    /// Sets the automatic temperature reporting interval.
93    pub fn set_automatic_report(&mut self, report: proto::AutomaticReport) -> Result<()> {
94        let mut ctx = self.ctx.lock().unwrap();
95        tokio_sync::R4DCB08::set_automatic_report(&mut ctx, report)
96    }
97
98    /// Reads the current Modbus communication baud rate setting from the device.
99    pub fn read_baud_rate(&mut self) -> Result<proto::BaudRate> {
100        let mut ctx = self.ctx.lock().unwrap();
101        tokio_sync::R4DCB08::read_baud_rate(&mut ctx)
102    }
103
104    /// Sets the Modbus communication baud rate for the device.
105    pub fn set_baud_rate(&mut self, baud_rate: proto::BaudRate) -> Result<()> {
106        let mut ctx = self.ctx.lock().unwrap();
107        tokio_sync::R4DCB08::set_baud_rate(&mut ctx, baud_rate)
108    }
109
110    /// Resets the R4DCB08 module to its factory default settings.
111    pub fn factory_reset(&mut self) -> Result<()> {
112        let mut ctx = self.ctx.lock().unwrap();
113        tokio_sync::R4DCB08::factory_reset(&mut ctx)
114    }
115
116    /// Reads the current Modbus device address (Slave ID) from the module.
117    pub fn read_address(&mut self) -> Result<proto::Address> {
118        let mut ctx = self.ctx.lock().unwrap();
119        tokio_sync::R4DCB08::read_address(&mut ctx)
120    }
121
122    /// Sets a new Modbus device address.
123    ///
124    /// A successful call makes the existing `Context` invalid (as it
125    /// still points to the old address). This function automatically
126    /// updates the slave ID within its managed `Context`.
127    pub fn set_address(&mut self, new_address: proto::Address) -> Result<()> {
128        let mut ctx = self.ctx.lock().unwrap();
129        tokio_sync::R4DCB08::set_address(&mut ctx, new_address)?;
130        ctx.set_slave(Slave(*new_address));
131        Ok(())
132    }
133}