pub struct TcpCommunication {
write_stream: TcpStream,
buf_reader: BufReader<TcpStream>,
execution_config: ExecutionConfig,
}Expand description
Contains configuration of implementation for opening, reading, and closing TCP channel. Thread communication is as follows:
Fields§
§write_stream: TcpStreamthe raw TCP stream
buf_reader: BufReader<TcpStream>buffered reader for TCP stream
execution_config: ExecutionConfiginformation about which threads are started
Implementations§
Source§impl TcpCommunication
impl TcpCommunication
Sourcepub fn new(
tcp_connection: &TcpCommunicationConfig,
execution_config: ExecutionConfig,
) -> Result<TcpCommunication, TcpCommunicationError>
pub fn new( tcp_connection: &TcpCommunicationConfig, execution_config: ExecutionConfig, ) -> Result<TcpCommunication, TcpCommunicationError>
Creates a new TcpCommunication instance and establishes a TCP connection to a simulator.
This constructor attempts to connect to a TCP server (acting as a simulator)
at the specified IP address and port. Upon a successful connection, it prepares
both a TcpStream for writing and a BufReader for efficient reading from the stream.
§Arguments
tcp_connection- Configuration data for the TCP connection, including the targetip_addressandportof the simulator.execution_config- Information about which threads are started
§Returns
A Result containing a new TcpCommunication struct with an established
TCP connection on success.
§Errors
Returns a TcpCommunicationError if the connection or setup fails:
TcpCommunicationError::ConnectionFailed: If the initial TCP connection to the specified address and port cannot be established. This could be due to the simulator not running, a firewall blocking the connection, or an incorrect address/port.TcpCommunicationError::StreamCloneFailed: If the underlyingTcpStreamcannot be cloned, which is a necessary step for creating separate read and write handles.
Sourcefn get_last_word(sequence: &str) -> Option<&str>
fn get_last_word(sequence: &str) -> Option<&str>
Extracts the last word from a given string slice, using whitespace as the delimiter.
This private helper function is useful for parsing responses where the desired data (e.g., a numeric value) is consistently the final token in a space-separated sequence. This implementation avoids heap allocation by using a reverse iterator.
§Arguments
sequence- The string slice from which to extract the last word.
§Returns
An Option<&str>:
Some(&str)containing a reference to the last word if the string contains words.Noneif the input string is empty or contains only whitespace.
Sourcefn write_stream_check_for_error(
&mut self,
request: String,
) -> Result<(), TcpCommunicationError>
fn write_stream_check_for_error( &mut self, request: String, ) -> Result<(), TcpCommunicationError>
Writes a string request to the TCP stream and handles potential errors.
This private helper function sends a request string as bytes over the TCP stream.
It verifies that the entire request was written successfully and flushes the stream
to ensure the data is sent immediately.
§Arguments
request- TheStringcontaining the data to be written to the TCP stream.
§Returns
An empty Result (Ok(())) on a successful write-operation and flush.
§Errors
Returns a TcpCommunicationError if the write or flush operation fails:
TcpCommunicationError::WritingToStreamFailed: If the underlying OS returns an error while writing to the TCP socket. This usually indicates a connection issue.TcpCommunicationError::FlushFailed: If the OS cannot flush its write buffer to the socket, also indicating a connection problem.
Sourcefn change_relay(
&mut self,
relay_id: u16,
state: bool,
) -> Result<(), TcpCommunicationError>
fn change_relay( &mut self, relay_id: u16, state: bool, ) -> Result<(), TcpCommunicationError>
Communicates with the simulator to change the state of a specific relay.
This private helper function constructs a TCP message to command a relay
to either switch ON or OFF. It then writes this command to the TCP stream
and waits for a response from the simulator to confirm the command was received.
§Arguments
relay_id- The numeric ID of the relay whose state is to be changed.state- A boolean value indicating the desired state:truefor ON,falsefor OFF.
§Returns
An empty Result (Ok(())) if the command was sent and a response was received successfully.
§Errors
Returns a TcpCommunicationError if any part of the process fails:
TcpCommunicationError::ReadingFromStreamFailed: If a response line cannot be read from the simulator, which likely indicates the connection was dropped.- It will also propagate any errors from
write_stream_check_for_error.
Sourcefn get_signal(
&mut self,
aquarium_signal: AquariumSignal,
) -> Result<f32, TcpCommunicationError>
fn get_signal( &mut self, aquarium_signal: AquariumSignal, ) -> Result<f32, TcpCommunicationError>
Communicates with the simulator to request and retrieve a sensor signal value.
This private helper function constructs a TCP message to ask the simulator
for the current reading of a specific AquariumSignal. It then writes this
request to the TCP stream, waits for a response, and parses the received
string into an f32 value.
§Arguments
aquarium_signal- TheAquariumSignalenum variant describing the sensor signal (e.g., water temperature, pH) for which the value is requested.
§Returns
A Result containing the retrieved sensor value as an f32 on success.
§Errors
Returns a TcpCommunicationError if any part of the process fails:
TcpCommunicationError::IllegalSignalRequestToSimulator: If an unsupportedAquariumSignalis requested.TcpCommunicationError::ReadingFromStreamFailed: If a response cannot be read from the TCP stream.TcpCommunicationError::ResponseContainsNoWords: If the simulator’s response is empty or contains no parsable words.TcpCommunicationError::LastWordOfResponseEmpty: If the last word of the response is an empty string.TcpCommunicationError::ResponseConversionError: If the last word of the response cannot be parsed into anf32.- It will also propagate any errors from
write_stream_check_for_error.
Sourcefn receive_and_answer(
&mut self,
rx: &mut AquaReceiver<InternalCommand>,
tx: &mut AquaSender<Result<f32, TcpCommunicationError>>,
) -> Result<(), TcpCommunicationError>
fn receive_and_answer( &mut self, rx: &mut AquaReceiver<InternalCommand>, tx: &mut AquaSender<Result<f32, TcpCommunicationError>>, ) -> Result<(), TcpCommunicationError>
Receives a RequestSignal command without blocking from a channel and sends back the corresponding sensor value via TCP.
This private helper function is used to service requests from various modules
that are configured to run in simulator mode. It checks the provided receiver channel (rx) for an
InternalCommand::RequestSignal. If such a request is found, it uses self.get_signal()
to fetch the simulated sensor value and sends it back through the provided sender channel (tx).
Other command types are ignored.
§Arguments
rx- A reference to the receiver channel from whichInternalCommandrequests are received.tx- A reference to the sender channel through which thef32sensor response is sent back.
§Returns
A Result which is:
Ok(f32): In the case of successErr(TcpCommunicationError:): in case of failure
Sourcefn handle_simulated_sensor(
&mut self,
is_active: bool,
rx_opt: &mut Option<AquaReceiver<InternalCommand>>,
tx_opt: &mut Option<AquaSender<Result<f32, TcpCommunicationError>>>,
module_name: &str,
)
fn handle_simulated_sensor( &mut self, is_active: bool, rx_opt: &mut Option<AquaReceiver<InternalCommand>>, tx_opt: &mut Option<AquaSender<Result<f32, TcpCommunicationError>>>, module_name: &str, )
Handles a request-response cycle for a simulated sensor if it’s active.
Sourcepub fn execute(
&mut self,
tcp_communication_channels: &mut TcpCommunicationChannels,
)
pub fn execute( &mut self, tcp_communication_channels: &mut TcpCommunicationChannels, )
Executes the main control loop for the TCP communication module.
This function runs continuously as a server, processing incoming requests from various client threads (e.g., Ambient, Atlas Scientific, Tank Level Switch, Relay Manager). It dispatches these requests to the connected TCP simulator and sends back the responses.
The loop remains active until a Quit command is received from the signal handler.
Upon receiving Quit, it breaks out of the loop and sends a confirmation back to the signal handler.
§Arguments
tcp_communication_channels- A mutable reference to a struct containing the channels for communication with other threads, including senders/receivers for SensorManager, Tank Level Switch, Relay Manager, and the Signal Handler.
Trait Implementations§
Source§impl ProcessExternalRequestTrait for TcpCommunication
impl ProcessExternalRequestTrait for TcpCommunication
Source§fn process_external_request(
&mut self,
rx_from_signal_handler: &mut AquaReceiver<InternalCommand>,
_: Option<&mut AquaReceiver<InternalCommand>>,
) -> (bool, bool, bool)
fn process_external_request( &mut self, rx_from_signal_handler: &mut AquaReceiver<InternalCommand>, _: Option<&mut AquaReceiver<InternalCommand>>, ) -> (bool, bool, bool)
Checks for and processes new commands relevant to the TCP Communication module from external channels.
This is the specialized implementation of ProcessExternalRequestTrait for TcpCommunication.
It delegates directly to process_external_request_without_messaging, indicating
that the TcpCommunication module primarily processes commands from the signal handler
and does not use a separate messaging channel for external requests.
§Arguments
rx_from_signal_handler- A reference to the receiver end of the channel for commands originating from the signal handler._- This parameter is ignored, as theTcpCommunicationmodule does not process messages from a messaging channel in this context.
§Returns
A tuple (bool, bool, bool) indicating the status of commands received:
- The first
boolistrueif aQuitcommand was received; otherwisefalse. - The second
boolis alwaysfalse(no “Start” commands processed). - The third
boolis alwaysfalse(no “Stop” commands processed).