mqtt_system_monitor/
configuration.rs

1use serde::Deserialize;
2use serde_inline_default::serde_inline_default;
3use std::error::Error;
4
5/// Contains the configuration for communicating with the MQTT broker
6#[serde_inline_default]
7#[derive(Deserialize)]
8pub struct Mqtt {
9    /// Hostname or IP address. Default: localhost
10    #[serde_inline_default(String::from("localhost"))]
11    pub host: String,
12
13    /// Port of the connection to the broker. Default: 1883
14    #[serde_inline_default(1883)]
15    pub port: u16,
16
17    /// Username for the connection to the broker. Default: empty
18    #[serde(default)]
19    pub user: String,
20
21    /// Password for the connection to the broker. Default: empty
22    #[serde(default)]
23    pub password: String,
24
25    /// Prefix for the registration topic sent to Home Assistant. Default: homeassistant
26    ///
27    /// This must match the configuration of the MQTT integration in Home Assistant
28    ///
29    /// See <https://www.home-assistant.io/integrations/mqtt#discovery-options>
30    #[serde_inline_default(String::from("homeassistant"))]
31    #[serde(rename = "registration-prefix")]
32    pub registration_prefix: String,
33
34    /// Delay between each sensor report in seconds. Default: 10 seconds
35    #[serde_inline_default(10)]
36    pub update_period: u64,
37
38    /// Name of the device entity. It should be unique in Home Assistant. Default: machine hostname
39    #[serde(default = "hostname")]
40    pub entity: String,
41}
42
43/// Contains the configuration for the sensors
44#[derive(Deserialize)]
45pub struct Sensors {
46    /// If set, contains a temperature label to search in `sysinfo`'s component reports.
47    pub temperature: Option<String>,
48
49    /// If set, contains a list of network interface to monitor.
50    #[serde(default)]
51    pub network: Vec<String>,
52}
53
54/// Contains all the configuration for `mqtt-system-monitor`
55#[serde_inline_default]
56#[derive(Deserialize)]
57pub struct Configuration {
58    /// Contains the configuration for communicating with the MQTT broker
59    pub mqtt: Mqtt,
60
61    /// Contains the configuration for the sensors
62    pub sensors: Sensors,
63
64    /// Sets the verbosity of the logs.
65    ///   * 1 => Error
66    ///  * 2 => Warning
67    ///  * 3 => Info
68    ///  * 4 => Debug
69    ///  * 5 => Trace
70    #[serde_inline_default(2)]
71    #[serde(rename = "log-verbosity")]
72    pub log_verbosity: usize,
73}
74
75fn hostname() -> String {
76    sysinfo::System::host_name().expect("Cannot read hostname")
77}
78
79impl Configuration {
80    /// Load the configuration from a file
81    ///
82    /// ## Example
83    ///
84    /// ```
85    /// use mqtt_system_monitor::{configuration, Configuration};
86    ///
87    /// let config = Configuration::load("conf/mqtt-system-monitor.conf").expect("Cannot load configuration");
88    ///
89    /// assert_eq!(config.mqtt.host, "localhost");
90    /// ```
91    pub fn load(path: &str) -> Result<Configuration, Box<dyn Error>> {
92        toml::from_str(std::fs::read_to_string(path)?.as_str()).map_err(|err| err.into())
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use super::*;
99
100    /// Test that we can properly load the default configuration
101    #[test]
102    fn test_default_config() -> Result<(), Box<dyn Error>> {
103        let conf = Configuration::load("conf/mqtt-system-monitor.conf")?;
104
105        assert_eq!(conf.mqtt.host, String::from("localhost"));
106        assert_eq!(conf.mqtt.registration_prefix, String::from("homeassistant"));
107
108        // By default, the entity name will be the hostname of the machine
109        assert_eq!(conf.mqtt.entity, hostname());
110
111        // Sensors are off by default
112        assert_eq!(conf.sensors.temperature, None);
113        assert!(conf.sensors.network.is_empty());
114
115        Ok(())
116    }
117}