oxide_spark_utils/
config.rs

1use std::{collections::HashMap, net::Ipv4Addr};
2
3use config::{ConfigError, File, FileFormat};
4use embedded_svc::wifi::AuthMethod;
5use once_cell::sync::OnceCell;
6use serde::Deserialize;
7
8use crate::{log_level::LogLevel, measure::MeasureKind, sensor_kind::SensorKind};
9
10pub static CONFIG_FILE: OnceCell<&str> = OnceCell::new();
11
12#[derive(Debug, Deserialize)]
13pub struct Config {
14	pub esp: EspConfig,
15	pub mqtt: Option<MqttConfig>,
16	#[serde(default)]
17	pub sensors: Vec<SensorConfig>,
18	pub wifi: Option<WifiConfig>,
19}
20
21impl Config {
22	/// Checks configuration file validity.
23	///
24	/// ```
25	/// use oxide_spark_utils::config::Config;
26	///
27	/// let config = r#"
28	///     [esp]
29	///     id = "esp1"
30	///     log_level = "Error"
31	/// "#;
32	///
33	/// let erroneous_config = r#"
34	///     [esp]
35	///     id = "esp1"
36	///     log_level = "Unknown"
37	/// "#;
38	///
39	/// assert!(matches!(Config::check(config), Ok(())));
40	/// assert!(matches!(Config::check(erroneous_config), Err(_)));
41	/// ```
42	pub fn check(config: &str) -> Result<(), ConfigError> {
43		config::Config::builder()
44			.add_source(File::from_str(config, FileFormat::Toml))
45			.build()
46			.expect("Failed to build configuration")
47			.try_deserialize::<Config>()?;
48
49		Ok(())
50	}
51
52	pub fn set(file: &'static str) {
53		CONFIG_FILE
54			.set(file)
55			.expect("Configuration file has already been set")
56	}
57}
58
59#[derive(Debug, Deserialize)]
60pub struct EspConfig {
61	pub id: String,
62	#[serde(default)]
63	pub log_level: LogLevel,
64}
65
66#[derive(Debug, Deserialize)]
67pub struct WifiConfig {
68	#[serde(default)]
69	pub auth_method: AuthMethod,
70	pub pwd: String,
71	pub ssid: String,
72	#[serde(default = "timeout")]
73	pub timeout: u64,
74}
75
76#[derive(Debug, Deserialize)]
77pub struct MqttConfig {
78	#[serde(default = "channel_size")]
79	pub channel_size: usize,
80	pub ip: Ipv4Addr,
81	#[serde(default = "port")]
82	pub port: u16,
83}
84
85#[derive(Clone, Debug, Deserialize)]
86pub struct SensorConfig {
87	#[serde(default = "freq")]
88	pub freq: u32,
89	pub id: String,
90	pub kind: SensorKind,
91	pub metrics: HashMap<MeasureKind, String>,
92}
93
94fn channel_size() -> usize {
95	50
96}
97
98fn freq() -> u32 {
99	1
100}
101
102fn port() -> u16 {
103	1883
104}
105
106fn timeout() -> u64 {
107	10
108}