aquarium_control/simulator/
tcp_communication_channels.rs

1/* Copyright 2025 Uwe Martin
2
3Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
5The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
7THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
8*/
9use crate::launch::channels::{AquaChannelError, AquaReceiver, AquaSender};
10use crate::simulator::tcp_communication::TcpCommunicationError;
11use crate::utilities::channel_content::InternalCommand;
12use std::fmt;
13
14/// Struct collects the channels for communication with other threads.
15pub struct TcpCommunicationChannels {
16    /// Receiver part of the channel for communication from the relay manager wrapped in Option type
17    pub rx_tcp_communication_from_relay_manager_opt: Option<AquaReceiver<InternalCommand>>,
18
19    /// Receiver part of the channel for communication from the sensor manager wrapped in Option type
20    pub rx_tcp_communication_from_sensor_manager_opt: Option<AquaReceiver<InternalCommand>>,
21
22    /// Sender part of the channel for communication to sensor manager wrapped in Option type
23    pub tx_tcp_communication_to_sensor_manager_opt:
24        Option<AquaSender<Result<f32, TcpCommunicationError>>>,
25
26    /// Receiver part of the channel for communication from tank level switch wrapped in Option type
27    pub rx_tcp_communication_from_tank_level_switch_opt: Option<AquaReceiver<InternalCommand>>,
28
29    /// Sender part of the channel for communication to tank level switch wrapped in Option type
30    pub tx_tcp_communication_to_tank_level_switch_opt:
31        Option<AquaSender<Result<f32, TcpCommunicationError>>>,
32
33    /// Sender part of the channel for communication to the signal handler
34    pub tx_tcp_communication_to_signal_handler: AquaSender<bool>,
35
36    /// Receiver part of the channel for communication from the signal handler
37    pub rx_tcp_communication_from_signal_handler: AquaReceiver<InternalCommand>,
38}
39
40impl TcpCommunicationChannels {
41    /// Receives a command from the relay manager if the channel exists.
42    #[allow(unused)]
43    pub fn receive_from_relay_manager(
44        &mut self,
45    ) -> Option<Result<InternalCommand, AquaChannelError>> {
46        self.rx_tcp_communication_from_relay_manager_opt
47            .as_mut()
48            .map(|rx| rx.recv())
49    }
50
51    /// Receives a command from the sensor manager if the channel exists.
52    #[allow(unused)]
53    pub fn receive_from_sensor_manager(
54        &mut self,
55    ) -> Option<Result<InternalCommand, AquaChannelError>> {
56        self.rx_tcp_communication_from_sensor_manager_opt
57            .as_mut()
58            .map(|rx| rx.recv())
59    }
60
61    /// Sends a result to the sensor manager if the channel exists.
62    #[allow(unused)]
63    pub fn send_to_sensor_manager(
64        &mut self,
65        data: Result<f32, TcpCommunicationError>,
66    ) -> Option<Result<(), AquaChannelError>> {
67        self.tx_tcp_communication_to_sensor_manager_opt
68            .as_mut()
69            .map(|tx| tx.send(data))
70    }
71
72    /// Receives a command from the tank level switch if the channel exists.
73    #[allow(unused)]
74    pub fn receive_from_tank_level_switch(
75        &mut self,
76    ) -> Option<Result<InternalCommand, AquaChannelError>> {
77        self.rx_tcp_communication_from_tank_level_switch_opt
78            .as_mut()
79            .map(|rx| rx.recv())
80    }
81
82    /// Sends a result to the tank level switch if the channel exists.
83    #[allow(unused)]
84    pub fn send_to_tank_level_switch(
85        &mut self,
86        data: Result<f32, TcpCommunicationError>,
87    ) -> Option<Result<(), AquaChannelError>> {
88        self.tx_tcp_communication_to_tank_level_switch_opt
89            .as_mut()
90            .map(|tx| tx.send(data))
91    }
92
93    /// Sends an acknowledgment to the signal handler.
94    pub fn send_to_signal_handler(&mut self, ack: bool) -> Result<(), AquaChannelError> {
95        self.tx_tcp_communication_to_signal_handler.send(ack)
96    }
97
98    /// Receives a command from the signal handler.
99    #[allow(unused)]
100    pub fn receive_from_signal_handler(&mut self) -> Result<InternalCommand, AquaChannelError> {
101        self.rx_tcp_communication_from_signal_handler.try_recv()
102    }
103}
104
105#[cfg(feature = "debug_channels")]
106impl fmt::Display for TcpCommunicationChannels {
107    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
108        writeln!(f, "=== TcpCommunicationChannels ===")?;
109        writeln!(
110            f,
111            "rx_tcp_communication_from_relay_manager_opt: {}",
112            self.rx_tcp_communication_from_relay_manager_opt
113                .as_ref()
114                .unwrap()
115                .count
116        )?;
117        writeln!(
118            f,
119            "rx_tcp_communication_from_sensor_manager_opt: {}",
120            self.rx_tcp_communication_from_sensor_manager_opt
121                .as_ref()
122                .unwrap()
123                .count
124        )?;
125        writeln!(
126            f,
127            "tx_tcp_communication_to_sensor_manager_opt: {}",
128            self.tx_tcp_communication_to_sensor_manager_opt
129                .as_ref()
130                .unwrap()
131                .count
132        )?;
133        writeln!(
134            f,
135            "rx_tcp_communication_from_tank_level_switch_opt: {}",
136            self.rx_tcp_communication_from_tank_level_switch_opt
137                .as_ref()
138                .unwrap()
139                .count
140        )?;
141        writeln!(
142            f,
143            "tx_tcp_communication_to_tank_level_switch_opt: {}",
144            self.tx_tcp_communication_to_tank_level_switch_opt
145                .as_ref()
146                .unwrap()
147                .count
148        )?;
149        writeln!(
150            f,
151            "tx_tcp_communication_to_signal_handler: {}",
152            self.tx_tcp_communication_to_signal_handler.count
153        )?;
154        write!(
155            f,
156            "rx_tcp_communication_from_signal_handler: {}",
157            self.rx_tcp_communication_from_signal_handler.count
158        )
159    }
160}
161
162#[cfg(not(feature = "debug_channels"))]
163impl fmt::Display for TcpCommunicationChannels {
164    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
165        write!(
166            f,
167            "Channel counters are not active. Use --features \"debug_channels\" to enable them."
168        )
169    }
170}
171
172impl TcpCommunicationChannels {
173    #[cfg(all(not(test), feature = "debug_channels"))]
174    pub fn report_status(&self) {
175        println!("TcpCommunicationChannels Status:");
176
177        println!(
178            "- rx_tcp_communication_from_relay_manager_opt: {}",
179            self.rx_tcp_communication_from_relay_manager_opt
180                .as_ref()
181                .map_or("None", |_| "Some")
182        );
183
184        println!(
185            "- rx_tcp_communication_from_sensor_manager_opt: {}",
186            self.rx_tcp_communication_from_sensor_manager_opt
187                .as_ref()
188                .map_or("None", |_| "Some")
189        );
190
191        println!(
192            "- tx_tcp_communication_to_sensor_manager_opt: {}",
193            self.tx_tcp_communication_to_sensor_manager_opt
194                .as_ref()
195                .map_or("None", |_| "Some")
196        );
197
198        println!(
199            "- rx_tcp_communication_from_tank_level_switch_opt: {}",
200            self.rx_tcp_communication_from_tank_level_switch_opt
201                .as_ref()
202                .map_or("None", |_| "Some")
203        );
204
205        println!(
206            "- tx_tcp_communication_to_tank_level_switch_opt: {}",
207            self.tx_tcp_communication_to_tank_level_switch_opt
208                .as_ref()
209                .map_or("None", |_| "Some")
210        );
211
212        println!("- tx_tcp_communication_to_signal_handler: Present");
213
214        println!("- rx_tcp_communication_from_signal_handler: Present");
215    }
216}