Skip to content

Commit 425ff18

Browse files
committed
feat: launch multiple daemon, and add modbus and acquisition configurations
1 parent 2bd9c29 commit 425ff18

File tree

18 files changed

+516
-77
lines changed

18 files changed

+516
-77
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ url = "2.5.4"
5151
rcgen = "0.13.2" # Certificate generation
5252
time = "0.3.41" # Time handling for certificates
5353
rsa = "0.9.8"
54+
tokio = "1.45.0"
5455

5556
[dev-dependencies]
5657
criterion = "0.6" # Benchmarking

config.yaml.example

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,7 @@ visualization:
1919
rs256_private_key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUdyQWdFQUFpRUFyd0FZcXAvdGVvaUE4N2FWQStJTjQ1U1RvMTdMUVZPbGRUT3FJeHhQeElNQ0F3RUFBUUlnCldRVlpodUpYOGE4aXVkYzFNb1o1dldYcmxwdFlEUTQ3RXUwa2pNVVA2T0VDRVFEUjEyN0RsZWNKNU80V3B2VEcKdnQ1YkFoRUExWDZ4ZVVzUXpISkZTYlV4eXZEYStRSVJBS2Z1b05ZbHdTQko5Y0JySExseFJzRUNFUURCcTBOZApqNTMyaUxhWURablV5amNwQWhCSG9CU1JSTS9ESVA5dWE1MDhYMEtOCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
2020
rs256_public_key: LS0tLS1CRUdJTiBSU0EgUFVCTElDIEtFWS0tLS0tCk1DZ0NJUUN2QUJpcW4rMTZpSUR6dHBVRDRnM2psSk9qWHN0QlU2VjFNNm9qSEUvRWd3SURBUUFCCi0tLS0tRU5EIFJTQSBQVUJMSUMgS0VZLS0tLS0K
2121

22+
modbus:
23+
port: 1502
24+
address: '127.0.0.1'
25+
enabled: false

examples/use_config.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ fn main() -> Result<()> {
1515
// Add a custom HMAC secret for JWT tokens
1616
let hmac_secret = Some("custom-jwt-secret-from-cmdline".to_string());
1717

18-
config.apply_args(web_port, web_address.to_string(), hmac_secret);
18+
config.apply_args(web_port, web_address.to_string(), hmac_secret, true);
1919
println!(
2020
"Configuration after applying command line arguments: {:?}",
2121
config

resources/config.schema.json

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,56 @@
6666
"rs256_private_key",
6767
"rs256_public_key"
6868
]
69+
},
70+
"modbus": {
71+
"type": "object",
72+
"properties": {
73+
"port": {
74+
"type": "integer",
75+
"minimum": 1,
76+
"maximum": 65534
77+
},
78+
"address": {
79+
"type": "string",
80+
"anyOf": [
81+
{
82+
"format": "ipv4"
83+
},
84+
{
85+
"format": "ipv6"
86+
}
87+
],
88+
"description": "IPv4 or IPv6 address to bind the Modbus service to."
89+
},
90+
"enabled": {
91+
"type": "boolean",
92+
"default": false,
93+
"description": "Enable Modbus TCP server"
94+
}
95+
},
96+
"required": [
97+
"port",
98+
"address"
99+
]
100+
},
101+
"acquisition": {
102+
"type": "object",
103+
"properties": {
104+
"enabled": {
105+
"type": "boolean",
106+
"default": true,
107+
"description": "Enable data acquisition"
108+
},
109+
"interval_ms": {
110+
"type": "integer",
111+
"minimum": 10,
112+
"default": 1000,
113+
"description": "Data acquisition interval in milliseconds"
114+
}
115+
},
116+
"required": [
117+
"enabled"
118+
]
69119
}
70120
},
71121
"required": [

src/config.rs

Lines changed: 119 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
//! let mut config = Config::from_file(Path::new("config.yaml")).unwrap();
3030
//!
3131
//! // Apply command line overrides if needed
32-
//! config.apply_args(8081, "0.0.0.0".to_string(), None);
32+
//! config.apply_args(8081, "0.0.0.0".to_string(), None, false);
3333
//!
3434
//! // Access configuration values
3535
//! println!("Server port: {}", config.visualization.port);
@@ -46,6 +46,53 @@ use std::{
4646
path::Path,
4747
};
4848

49+
/// Configuration for the data acquisition process.
50+
///
51+
/// This structure contains settings that control how data is acquired
52+
/// from the photoacoustic sensor, including timing parameters and
53+
/// whether the acquisition system is enabled.
54+
#[derive(Debug, Deserialize, Serialize, Clone)]
55+
pub struct AcquisitionConfig {
56+
/// Enable or disable data acquisition.
57+
///
58+
/// When set to `false`, the system will not perform any data acquisition
59+
/// operations. Default is `true`.
60+
pub enabled: bool,
61+
62+
/// Time interval between consecutive data acquisitions in milliseconds.
63+
///
64+
/// This controls how frequently the system samples data from the sensor.
65+
/// Lower values provide more frequent updates but may increase system load.
66+
/// Default value is 1000ms (1 second).
67+
pub interval_ms: u64,
68+
// Other acquisition settings
69+
}
70+
// implement Default for AcquisitionConfig
71+
impl Default for AcquisitionConfig {
72+
fn default() -> Self {
73+
Self {
74+
enabled: true,
75+
interval_ms: 1000,
76+
}
77+
}
78+
}
79+
80+
#[derive(Debug, Clone, Serialize, Deserialize)]
81+
pub struct ModbusConfig {
82+
pub enabled: bool,
83+
pub port: u16,
84+
pub address: String,
85+
}
86+
// implement Default for ModbusConfig
87+
impl Default for ModbusConfig {
88+
fn default() -> Self {
89+
Self {
90+
enabled: false,
91+
port: 502,
92+
address: "127.0.0.1".to_string(),
93+
}
94+
}
95+
}
4996
/// Root configuration structure for the photoacoustic application.
5097
///
5198
/// This structure serves as the main container for all configuration sections
@@ -71,6 +118,22 @@ pub struct Config {
71118
/// If not specified in the configuration file, default values are used.
72119
#[serde(default)]
73120
pub visualization: VisualizationConfig,
121+
122+
/// Acquisition settings for the photoacoustic application.
123+
///
124+
/// This section controls parameters related to the data acquisition process,
125+
/// such as enabling/disabling acquisition, and the interval between acquisitions.
126+
/// If not specified, default values will be used.
127+
#[serde(default)]
128+
pub acquisition: AcquisitionConfig,
129+
130+
/// Modbus settings for the photoacoustic application.
131+
///
132+
/// This section controls parameters related to the Modbus communication,
133+
/// such as enabling/disabling Modbus, the port to use, and the address.
134+
/// If not specified, default values will be used.
135+
#[serde(default)]
136+
pub modbus: ModbusConfig,
74137
}
75138

76139
/// Configuration for the visualization web server.
@@ -149,6 +212,13 @@ pub struct VisualizationConfig {
149212
/// Can be generated with the `rs256keygen` binary.
150213
#[serde(default = "default_rs256_public_key")]
151214
pub rs256_public_key: String,
215+
216+
/// Enable or disable the visualization server.
217+
///
218+
/// This flag can be used to easily enable or disable the server
219+
/// without removing the configuration. Default is `true`.
220+
#[serde(default = "default_enabled")]
221+
pub enabled: bool,
152222
}
153223

154224
/// Provides the default TCP port (8080) for the visualization server.
@@ -197,10 +267,22 @@ fn default_key() -> Option<String> {
197267
}
198268
}
199269

270+
/// Provides the default HMAC secret key for JWT token signing.
271+
///
272+
/// This key is used for HMAC-based JWT authentication. It should be kept secret
273+
/// and not shared publicly. The default value is a placeholder and should be
274+
/// replaced with a strong, randomly generated key in production environments.
275+
/// The key should be at least 256 bits (32 bytes) long for security.
200276
fn default_hmac_secret() -> String {
201277
"my-super-secret-jwt-key-for-photoacoustic-app".to_string()
202278
}
203279

280+
/// Provides the default RS256 private key for JWT token signing.
281+
///
282+
/// This key is used for RS256-based JWT authentication. It should be kept secret
283+
/// and not shared publicly. The default value is a placeholder and should be
284+
/// replaced with a strong, randomly generated key in production environments.
285+
/// The key should be in PEM format and Base64 encoded.
204286
fn default_rs256_private_key() -> String {
205287
let key_str = include_str!("../resources/private.key");
206288
if key_str.is_empty() {
@@ -209,6 +291,14 @@ fn default_rs256_private_key() -> String {
209291
base64::engine::general_purpose::STANDARD.encode(key_str.as_bytes())
210292
}
211293
}
294+
295+
/// Provides the default RS256 public key for JWT token verification.
296+
///
297+
/// This key is used for verifying JWT tokens signed with the RS256 algorithm.
298+
/// It should be shared publicly to allow clients to verify the tokens.
299+
/// The default value is a placeholder and should be replaced with a strong,
300+
/// randomly generated key in production environments.
301+
/// The key should be in PEM format and Base64 encoded.
212302
fn default_rs256_public_key() -> String {
213303
let key_str = include_str!("../resources/pub.key");
214304
if key_str.is_empty() {
@@ -217,6 +307,16 @@ fn default_rs256_public_key() -> String {
217307
base64::engine::general_purpose::STANDARD.encode(key_str.as_bytes())
218308
}
219309
}
310+
311+
/// Provides the default enabled state for the visualization server.
312+
///
313+
/// This flag indicates whether the server should be started by default.
314+
/// The default value is `true`, meaning the server will be enabled unless
315+
/// explicitly disabled in the configuration file.
316+
fn default_enabled() -> bool {
317+
true
318+
}
319+
220320
impl Default for VisualizationConfig {
221321
fn default() -> Self {
222322
Self {
@@ -228,6 +328,7 @@ impl Default for VisualizationConfig {
228328
hmac_secret: default_hmac_secret(),
229329
rs256_private_key: default_rs256_private_key(),
230330
rs256_public_key: default_rs256_public_key(),
331+
enabled: default_enabled(),
231332
}
232333
}
233334
}
@@ -236,6 +337,11 @@ impl Default for Config {
236337
fn default() -> Self {
237338
Self {
238339
visualization: VisualizationConfig::default(),
340+
acquisition: AcquisitionConfig {
341+
enabled: true,
342+
interval_ms: 1000,
343+
},
344+
modbus: ModbusConfig::default(),
239345
}
240346
}
241347
}
@@ -314,7 +420,13 @@ impl Config {
314420
}
315421

316422
/// Apply command line arguments to override configuration values
317-
pub fn apply_args(&mut self, web_port: u16, web_address: String, hmac_secret: Option<String>) {
423+
pub fn apply_args(
424+
&mut self,
425+
web_port: u16,
426+
web_address: String,
427+
hmac_secret: Option<String>,
428+
daemon_mode: bool, // New parameter
429+
) {
318430
// Only override if command-line arguments are provided
319431
if web_port != default_port() {
320432
debug!("Overriding port from command line: {}", web_port);
@@ -330,6 +442,11 @@ impl Config {
330442
debug!("Overriding HMAC secret from command line");
331443
self.visualization.hmac_secret = secret;
332444
}
445+
446+
// Enable visualization in daemon mode
447+
if daemon_mode {
448+
self.visualization.enabled = true;
449+
}
333450
}
334451

335452
/// Validate additional rules that aren't covered by the JSON schema

0 commit comments

Comments
 (0)