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}