pub struct AtlasScientific {
config: AtlasScientificConfig,
pub(crate) lock_error_channel_receive_termination: bool,
pub(crate) lock_warn_inapplicable_command_signal_handler: bool,
lock_error_channel_send_i2c_interface: bool,
pub lock_warn_max_mutex_access_duration_temperature: bool,
pub lock_warn_max_mutex_access_duration_ph: bool,
pub lock_warn_max_mutex_access_duration_conductivity: bool,
pub last_measurement_instant: Instant,
pub measurement_interval: Duration,
pub max_mutex_access_duration_millis: Duration,
}Expand description
Contains the communication Atlas Scientific sensors via I2C. Alternatively, TCP communication is used when configured to run with the simulator. The struct holds attributes for the results and for error flags indicating unsuccessful communication. Sensor data is read periodically and stored. Requests from data logger, ventilation, and heating control are answered with last measured data. Creates the channels and sets up threads. Thread communication of this component is as follows:
Fields§
§config: AtlasScientificConfigconfiguration data for AtlasScientific
lock_error_channel_receive_termination: boolinhibition flag to avoid flooding the log file with repeated messages about failure to receive termination signal via the channel
lock_warn_inapplicable_command_signal_handler: boolinhibition flag to avoid flooding the log file with repeated messages about having received inapplicable command via the channel from the signal handler thread
lock_error_channel_send_i2c_interface: boolinhibition flag to avoid flooding the log file with repeated messages about to send request via the channel to I2cInterface thread
lock_warn_max_mutex_access_duration_temperature: boolinhibition flag to avoid flooding the log file with repeated messages about excessive access time to mutex for water temperature
lock_warn_max_mutex_access_duration_ph: boolinhibition flag to avoid flooding the log file with repeated messages about excessive access time to mutex for pH
lock_warn_max_mutex_access_duration_conductivity: boolinhibition flag to avoid flooding the log file with repeated messages about excessive access time to mutex for conductivity
last_measurement_instant: Instantinstant when the last measurement took place
measurement_interval: Durationduration of the measurement interval calculated from the configuration data
max_mutex_access_duration_millis: Durationmaximum allowed duration for access to mutex
Implementations§
Source§impl AtlasScientific
impl AtlasScientific
Sourcepub fn new(config: AtlasScientificConfig) -> AtlasScientific
pub fn new(config: AtlasScientificConfig) -> AtlasScientific
Creates a new AtlasScientific control instance.
This constructor initializes the Atlas Scientific sensor module. It takes the configuration, calculates the measurement interval, and sets up internal state, including lock flags used to prevent log flooding from recurring errors or warnings.
§Arguments
config- Configuration data for the Atlas Scientific module, specifying I2C addresses, sleep times, and the measurement interval.
§Returns
A new AtlasScientific struct, ready to manage sensor data acquisition.
Sourcefn is_numeric(character: u8, negative_allowed: bool) -> bool
fn is_numeric(character: u8, negative_allowed: bool) -> bool
Checks if a given character is a valid part of a numeric string, considering optional negative signs.
This private helper function is used during the parsing of sensor responses to validate
that each character in the data section is either a digit (0-9), a decimal point (.),
or, if negative_allowed is true, a negative sign (-).
§Arguments
character- Theu8byte value of the character to be checked (typically an ASCII representation).negative_allowed- Aboolflag. Iftrue, a negative sign character (-) will be considered valid; otherwise, it will be considered invalid.
§Returns
true if the character is a valid numeric component based on the rules; false otherwise.
Sourcefn check_response(
buffer: [u8; 8],
is_ph: bool,
) -> Result<f32, AtlasScientificError>
fn check_response( buffer: [u8; 8], is_ph: bool, ) -> Result<f32, AtlasScientificError>
Evaluates a raw byte array response from an Atlas Scientific sensor unit, validating its format and converting it to f32.
This private helper function performs several critical steps to parse sensor data:
- Magic Number Check: Verifies the protocol’s start and end “magic” bytes.
- Numeric Content Validation: Ensures all characters within the data section are valid numeric components.
- UTF-8 Conversion & Float Parsing: Converts the validated byte sequence into a string and parses it into an
f32value.
The is_ph flag specifically controls whether a negative sign is allowed, as pH values are non-negative by definition.
§Arguments
buffer- A fixed-size array ofu8bytes representing the complete message received from the sensor.is_ph- Aboolflag indicating if the response is from a pH sensor (true) or another type (false).
§Returns
A Result containing the successfully parsed f32 sensor reading.
§Errors
Returns an AtlasScientificError variant if any validation or parsing step fails:
FirstCharacterNotMagic: If the message’s first byte is incorrect.LastCharacterNotMagic: If the message’s last byte is incorrect.ContainsInvalidCharacter: If the data section contains non-numeric characters.InvalidUtf8Sequence: If the numeric byte sequence is not valid UTF-8.ConversionFailure: If the valid numeric string cannot be parsed into anf32.
Sourcefn send_request_to_i2c_interface(
&mut self,
signal: &AquariumSignal,
atlas_scientific_channels: &mut AtlasScientificChannels,
) -> Result<(), AtlasScientificError>
fn send_request_to_i2c_interface( &mut self, signal: &AquariumSignal, atlas_scientific_channels: &mut AtlasScientificChannels, ) -> Result<(), AtlasScientificError>
Constructs and sends a measurement request to the I2C interface thread.
This function creates an I2cRequest based on the specified signal. It
retrieves the correct I2C address and sleep time from the configuration
for the given sensor. The request is then sent over the provided channel
to the I2C thread for execution.
§Arguments
signal- TheAquariumSignalidentifying which sensor to request a reading from.atlas_scientific_channels- A mutable reference to the struct containing the channels.
§Returns
An empty Result (Ok(())) if the measurement request was successfully created and sent.
§Errors
Returns an AtlasScientificError if any step fails:
InvalidSignal: If an unsupportedAquariumSignalis provided.SignalRequestCreationFailure: If the underlyingI2cRequest::newcall fails (e.g., command too long).SendingRequestToI2cInterfaceFailed: If sending the request over the channel fails, which typically means the receiver (the I2C thread) has been dropped.
Sourcefn write_result_to_mutex(
&self,
signal: &AquariumSignal,
result: AtlasScientificResultData,
mutex_water_temperature: &Arc<Mutex<AtlasScientificResultData>>,
mutex_ph: &Arc<Mutex<AtlasScientificResultData>>,
mutex_conductivity: &Arc<Mutex<AtlasScientificResultData>>,
) -> Result<Instant, AtlasScientificError>
fn write_result_to_mutex( &self, signal: &AquariumSignal, result: AtlasScientificResultData, mutex_water_temperature: &Arc<Mutex<AtlasScientificResultData>>, mutex_ph: &Arc<Mutex<AtlasScientificResultData>>, mutex_conductivity: &Arc<Mutex<AtlasScientificResultData>>, ) -> Result<Instant, AtlasScientificError>
Atomically writes a sensor measurement result to the appropriate shared mutex.
This helper function directs an AtlasScientificResultData to its corresponding
shared Mutex based on the provided signal. It centralizes the
mutex selection and locking logic.
§Arguments
signal- TheAquariumSignalthat determines which mutex to update.result- TheAtlasScientificResultDatato be written.mutex_water_temperature- The shared mutex for the water temperature result.mutex_ph- The shared mutex for the pH sensor result.mutex_conductivity- The shared mutex for the conductivity sensor result.
§Returns
A Result containing the Instant at which the lock was released on success.
§Errors
Returns Err(AtlasScientificError::CouldNotLockMutex) if the target mutex is
poisoned and cannot be locked.
Sourcefn receive_response_from_i2c_interface(
&mut self,
signal: &AquariumSignal,
atlas_scientific_channels: &mut AtlasScientificChannels,
mutex_water_temperature: &Arc<Mutex<AtlasScientificResultData>>,
mutex_ph: &Arc<Mutex<AtlasScientificResultData>>,
mutex_conductivity: &Arc<Mutex<AtlasScientificResultData>>,
) -> Result<AtlasScientificResultData, AtlasScientificError>
fn receive_response_from_i2c_interface( &mut self, signal: &AquariumSignal, atlas_scientific_channels: &mut AtlasScientificChannels, mutex_water_temperature: &Arc<Mutex<AtlasScientificResultData>>, mutex_ph: &Arc<Mutex<AtlasScientificResultData>>, mutex_conductivity: &Arc<Mutex<AtlasScientificResultData>>, ) -> Result<AtlasScientificResultData, AtlasScientificError>
Receives and processes a measurement response from the I2C interface thread.
This function orchestrates the full cycle of handling a sensor reading. It performs a non-blocking receive on the I2C channel. If a message is available, it processes the result, which can be either a successful data payload or an I2C-level error.
For a successful payload, the function:
- Parses the raw byte buffer using
check_response. - Converts the valid data into an
AtlasScientificResultDatastruct. - Atomically writes this result to the correct shared
Mutexusingwrite_result_to_mutex. - Monitors the duration of the mutex lock, issuing a warning if it exceeds the threshold.
§Arguments
signal- TheAquariumSignalindicating which sensor’s data is expected.atlas_scientific_channels- A mutable reference to the struct containing the channels.mutex_water_temperature- The sharedMutexfor the water temperature result.mutex_ph- The sharedMutexfor the pH result.mutex_conductivity- The sharedMutexfor the conductivity result.
§Returns
An AtlasScientificResult containing the AtlasScientificResultData if a valid sensor
reading was successfully received, parsed, and stored.
§Errors
Returns an AtlasScientificError variant if any error occurred:
ChannelIsEmpty: A recoverable error indicating no message was available.ChannelIsDisconnected: A critical error indicating the I2C thread has terminated.I2cCommunicationFailure: The I2C thread reported a hardware-level communication error.ResponseCheckFailed/IncorrectBufferLength: The received data payload was malformed.CouldNotLockMutex: The target mutex was poisoned and could not be updated.
Sourcepub fn execute(
&mut self,
atlas_scientific_channels: &mut AtlasScientificChannels,
mutex_atlas_scientific_water_temperature: Arc<Mutex<AtlasScientificResultData>>,
mutex_atlas_scientific_ph: Arc<Mutex<AtlasScientificResultData>>,
mutex_atlas_scientific_conductivity: Arc<Mutex<AtlasScientificResultData>>,
)
pub fn execute( &mut self, atlas_scientific_channels: &mut AtlasScientificChannels, mutex_atlas_scientific_water_temperature: Arc<Mutex<AtlasScientificResultData>>, mutex_atlas_scientific_ph: Arc<Mutex<AtlasScientificResultData>>, mutex_atlas_scientific_conductivity: Arc<Mutex<AtlasScientificResultData>>, )
Executes the main control loop for the Atlas Scientific sensor module.
This function runs continuously, managing the periodic and sequential measurement of water temperature, pH, and conductivity. It interacts with an I2C interface thread by sending requests for one sensor at a time and then processing the response.
The collected data (or any resulting error) is written to a shared Mutex,
making it available to other application threads. The loop respects the configured
measurement_interval between cycles and remains responsive to Quit and
Terminate commands from the signal handler for a graceful shutdown.
§Arguments
atlas_scientific_channels- A mutable reference to the struct containing allmpscchannels necessary for inter-thread communication with theI2CInterfaceand theSignalHandler.mutex_atlas_scientific_water_temperature- The sharedMutexfor storing the water temperature result.mutex_atlas_scientific_ph- The sharedMutexfor storing the pH result.mutex_atlas_scientific_conductivity- The sharedMutexfor storing the conductivity result.
Trait Implementations§
Source§impl CheckMutexAccessDurationTrait for AtlasScientific
impl CheckMutexAccessDurationTrait for AtlasScientific
Source§fn get_max_mutex_access_duration(&self) -> Duration
fn get_max_mutex_access_duration(&self) -> Duration
Method connects the default trait implementation with the specific implementation for getting maximum permissible access duration
Source§fn get_location(&self) -> &str
fn get_location(&self) -> &str
inform the location of the warning for logging purposes
Source§fn get_warn_lock(&self, key_opt: &Option<&AquariumSignal>) -> bool
fn get_warn_lock(&self, key_opt: &Option<&AquariumSignal>) -> bool
Source§fn set_warn_lock(&mut self, key_opt: &Option<&AquariumSignal>, value: bool)
fn set_warn_lock(&mut self, key_opt: &Option<&AquariumSignal>, value: bool)
fn check_mutex_access_duration( &mut self, key_opt: Option<&AquariumSignal>, instant_after_locking_mutex: Instant, instant_before_locking_mutex: Instant, )
Source§impl GetResponseFromSimulatorTrait for AtlasScientific
impl GetResponseFromSimulatorTrait for AtlasScientific
Source§fn get_response_from_simulator(
requester: String,
tx_to_tcp: &mut AquaSender<InternalCommand>,
rx_from_tcp: &mut AquaReceiver<Result<f32, TcpCommunicationError>>,
internal_command: InternalCommand,
) -> Result<f32, TcpCommunicationError>
fn get_response_from_simulator( requester: String, tx_to_tcp: &mut AquaSender<InternalCommand>, rx_from_tcp: &mut AquaReceiver<Result<f32, TcpCommunicationError>>, internal_command: InternalCommand, ) -> Result<f32, TcpCommunicationError>
Source§impl ProcessExternalRequestTrait for AtlasScientific
impl ProcessExternalRequestTrait for AtlasScientific
Source§fn process_external_request(
&mut self,
rx_from_signal_handler: &mut AquaReceiver<InternalCommand>,
rx_from_messaging_opt: Option<&mut AquaReceiver<InternalCommand>>,
) -> (bool, bool, bool)
fn process_external_request( &mut self, rx_from_signal_handler: &mut AquaReceiver<InternalCommand>, rx_from_messaging_opt: Option<&mut AquaReceiver<InternalCommand>>, ) -> (bool, bool, bool)
Source§impl WaitForTerminationTrait for AtlasScientific
impl WaitForTerminationTrait for AtlasScientific
Source§fn get_warn_lock_mut(&mut self) -> &mut bool
fn get_warn_lock_mut(&mut self) -> &mut bool
Method connects the default trait implementation with the specific implementation accessing the warn-lock.
Source§fn get_error_lock_mut(&mut self) -> &mut bool
fn get_error_lock_mut(&mut self) -> &mut bool
Method connects the default trait implementation with the specific implementation for accessing the error-lock.