Start to check device relay information

This commit is contained in:
Pierre HUBERT 2024-07-31 23:33:58 +02:00
parent 5497c36c75
commit 48a2f728de
2 changed files with 118 additions and 2 deletions

View File

@ -36,6 +36,10 @@ impl SizeConstraint {
let len = val.trim().len(); let len = val.trim().len();
len >= self.min && len <= self.max len >= self.min && len <= self.max
} }
pub fn validate_usize(&self, val: usize) -> bool {
val >= self.min && val <= self.max
}
} }
/// Backend static constraints /// Backend static constraints

View File

@ -1,6 +1,7 @@
//! # Devices entities definition //! # Devices entities definition
use crate::constants::StaticConstraints; use crate::constants::StaticConstraints;
use std::collections::HashMap;
/// Device information provided directly by the device during syncrhonisation. /// Device information provided directly by the device during syncrhonisation.
/// ///
@ -75,13 +76,20 @@ pub struct DailyMinRuntime {
pub catch_up_hours: Vec<usize>, pub catch_up_hours: Vec<usize>,
} }
#[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq)] #[derive(Clone, Copy, Debug, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
pub struct DeviceRelayID(uuid::Uuid); pub struct DeviceRelayID(uuid::Uuid);
impl Default for DeviceRelayID {
fn default() -> Self {
Self(uuid::Uuid::new_v4())
}
}
/// Single device relay information /// Single device relay information
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] #[derive(Clone, Debug, serde::Serialize, serde::Deserialize, Default)]
pub struct DeviceRelay { pub struct DeviceRelay {
/// Device relay id. Should be unique across the whole application /// Device relay id. Should be unique across the whole application
#[serde(default)]
id: DeviceRelayID, id: DeviceRelayID,
/// Human-readable name for the relay /// Human-readable name for the relay
name: String, name: String,
@ -103,6 +111,80 @@ pub struct DeviceRelay {
conflicts_with: Vec<DeviceRelayID>, conflicts_with: Vec<DeviceRelayID>,
} }
impl DeviceRelay {
/// Check device relay for errors
pub fn error(&self, list: &[DeviceRelay]) -> Option<&'static str> {
let constraints = StaticConstraints::default();
if !constraints.relay_name_len.validate(&self.name) {
return Some("Invalid relay name length!");
}
if !constraints.relay_priority.validate_usize(self.priority) {
return Some("Invalid relay priority!");
}
if !constraints
.relay_consumption
.validate_usize(self.consumption)
{
return Some("Invalid consumption!");
}
if !constraints
.relay_minimal_uptime
.validate_usize(self.minimal_uptime)
{
return Some("Invalid minimal uptime!");
}
if !constraints
.relay_minimal_downtime
.validate_usize(self.minimal_downtime)
{
return Some("Invalid minimal uptime!");
}
if let Some(daily) = &self.daily_runtime {
if !constraints
.relay_daily_minimal_runtime
.validate_usize(daily.min_runtime)
{
return Some("Invalid minimal daily runtime!");
}
if daily.reset_time > 3600 * 24 {
return Some("Invalid daily reset time!");
}
if daily.catch_up_hours.is_empty() {
return Some("No catchup hours defined!");
}
if daily.catch_up_hours.iter().any(|h| h > &23) {
return Some("At least one catch up hour is invalid!");
}
}
let relays_map = list.iter().map(|r| (r.id, r)).collect::<HashMap<_, _>>();
if self.depends_on.iter().any(|d| !relays_map.contains_key(d)) {
return Some("A specified dependent relay does not exists!");
}
if self
.conflicts_with
.iter()
.any(|d| !relays_map.contains_key(d))
{
return Some("A specified conflicting relay does not exists!");
}
// TODO : check for loops
None
}
}
/// Device general information /// Device general information
/// ///
/// This structure is used to update device information /// This structure is used to update device information
@ -128,3 +210,33 @@ impl DeviceGeneralInfo {
None None
} }
} }
#[cfg(test)]
mod tests {
use crate::devices::device::DeviceRelay;
#[test]
fn check_device_relay_error() {
let unitary = DeviceRelay {
name: "unitary".to_string(),
..Default::default()
};
let bad_name = DeviceRelay {
name: "".to_string(),
..Default::default()
};
let dep_on_unitary = DeviceRelay {
name: "dep_on_unitary".to_string(),
depends_on: vec![unitary.id],
..Default::default()
};
assert_eq!(unitary.error(&[]), None);
assert_eq!(unitary.error(&[unitary.clone(), bad_name.clone()]), None);
assert!(bad_name.error(&[]).is_some());
assert_eq!(dep_on_unitary.error(&[unitary.clone()]), None);
assert!(dep_on_unitary.error(&[]).is_some());
}
}