aquarium_control/launch/
execution_config.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*/
9
10//! Defines a lightweight snapshot of which application threads are configured to run.
11//!
12//! This module provides the `ExecutionConfig` struct, which is created once at application
13//! startup. Its sole purpose is to hold a simple boolean flag for each major,
14//! concurrently running module (like `feed`, `refill`, `heating`, etc.), indicating
15//! whether it was intended to be executed.
16//!
17//! ## Design and Purpose
18//!
19//! The primary role of `ExecutionConfig` is to act as a decoupled, easily passable
20//! source of truth about the runtime configuration.
21//!
22//! - **Decoupling**: Instead of passing the entire, heavy `ConfigData` object throughout
23//!   the application, threads can be given this much simpler struct. This is
24//!   particularly useful for cross-cutting concerns like the IPC `messaging` dispatcher,
25//!   which needs to know if a target thread exists without needing to know its specific
26//!   configuration details.
27//!
28//! - **Simplicity**: It provides a direct and unambiguous way to check if a thread was
29//!   launched. The `new()` constructor handles the one-time translation from the
30//!   more complex `ConfigData` struct.
31//!
32//! - **Testability**: The `Default` implementation provides a convenient way to create
33//!   an `ExecutionConfig` where all modules are considered active, which is useful
34//!   for setting up test environments.
35
36use crate::utilities::config::ConfigData;
37
38/// A snapshot of which application threads are configured to be active at runtime.
39///
40/// This struct is created at application startup from the main `ConfigData`. It serves
41/// as a lightweight, easily passable representation of the execution state, allowing
42/// different parts of the application (like the messaging dispatcher) to quickly
43/// check if a specific thread or module was launched without needing access to the
44/// full configuration object.
45#[derive(Clone, Debug)]
46pub struct ExecutionConfig {
47    pub relay_manager: bool,
48    pub data_logger: bool,
49    pub refill: bool,
50    pub heating: bool,
51    pub tank_level_switch: bool,
52    pub atlas_scientific: bool,
53    pub sensor_manager: bool,
54    pub feed: bool,
55    pub balling: bool,
56    pub monitors: bool,
57    #[cfg(feature = "target_hw")]
58    pub dht: bool,
59    #[cfg(feature = "target_hw")]
60    pub i2c_interface: bool,
61    pub ventilation: bool,
62    pub schedule_check: bool,
63    pub ds18b20: bool,
64    pub watchdog: bool,
65    pub memory: bool,
66    pub tcp_communication: bool,
67}
68
69impl ExecutionConfig {
70    /// Creates a new `ExecutionConfig` based on the application's configuration file.
71    ///
72    /// This constructor reads the `execute` flag from each module's configuration
73    /// section within the provided `ConfigData` to build the execution state.
74    ///
75    /// # Arguments
76    /// * `config` - A reference to the fully parsed application configuration data.
77    pub fn new(config: &ConfigData) -> Self {
78        Self {
79            relay_manager: config.relay_manager.execute,
80            data_logger: config.data_logger.execute,
81            refill: config.refill.execute,
82            heating: config.heating.execute,
83            tank_level_switch: config.tank_level_switch.execute,
84            atlas_scientific: config.atlas_scientific.execute,
85            sensor_manager: config.sensor_manager.execute,
86            feed: config.feed.execute,
87            balling: config.balling.execute,
88            monitors: config.monitors.execute,
89            #[cfg(feature = "target_hw")]
90            dht: config.dht.execute,
91            #[cfg(feature = "target_hw")]
92            i2c_interface: config.i2c_interface.execute,
93            ventilation: config.ventilation.execute,
94            schedule_check: config.schedule_check.execute,
95            ds18b20: config.ds18b20.execute,
96            watchdog: config.watchdog.execute,
97            memory: config.memory.execute,
98            tcp_communication: config.tcp_communication.execute,
99        }
100    }
101}
102
103/// Implements the `Default` trait for `ExecutionConfig`.
104///
105/// This provides a standard way to create a default instance where all modules are
106/// considered active. This is particularly useful for testing environments or as a
107/// fallback. Using the `Default` trait is more idiomatic than a custom `default()`
108/// function and allows for convenient instantiation with `ExecutionConfig::default()`.
109impl Default for ExecutionConfig {
110    fn default() -> Self {
111        Self {
112            relay_manager: true,
113            data_logger: true,
114            refill: true,
115            heating: true,
116            tank_level_switch: true,
117            atlas_scientific: true,
118            sensor_manager: true,
119            feed: true,
120            balling: true,
121            monitors: true,
122            #[cfg(feature = "target_hw")]
123            dht: true,
124            #[cfg(feature = "target_hw")]
125            i2c_interface: true,
126            ventilation: true,
127            schedule_check: true,
128            ds18b20: true,
129            watchdog: true,
130            memory: true,
131            tcp_communication: true,
132        }
133    }
134}