From 929985c64af0a69db30c89e3c03d22294fc0935c Mon Sep 17 00:00:00 2001
From: Tobias Reisinger <tobias@msrg.cc>
Date: Tue, 28 May 2024 21:17:21 +0200
Subject: [PATCH] Improve handling of override_schedule

---
 src/models/controller.rs | 15 ++++-----------
 src/models/relay.rs      | 31 ++++++++++++++++---------------
 src/types/mod.rs         | 10 ++--------
 src/types/relay_state.rs | 22 ++++++++++++++++++++++
 4 files changed, 44 insertions(+), 34 deletions(-)
 create mode 100644 src/types/relay_state.rs

diff --git a/src/models/controller.rs b/src/models/controller.rs
index ebc556a..e1a272b 100644
--- a/src/models/controller.rs
+++ b/src/models/controller.rs
@@ -57,20 +57,11 @@ impl Controller {
 		self.relays
 			.iter_mut()
 			.zip(relay_states.iter())
-			.for_each(|(relay, state)| {
-				relay.active_schedule = state.active_schedule.clone();
-				relay.is_on = state.is_on;
-			});
+			.for_each(|(relay, state)| relay.apply_state(state));
 	}
 
 	pub fn get_relay_states(&self) -> RelayStates {
-		self.relays
-			.iter()
-			.map(|r| RelayState {
-				active_schedule: r.active_schedule.clone(),
-				is_on: r.is_on,
-			})
-			.collect()
+		self.relays.iter().map(RelayState::from).collect()
 	}
 
 	pub fn check_next_time(&mut self, now: &EmgauwaNow) -> Option<NaiveTime> {
@@ -90,6 +81,8 @@ impl Controller {
 			.find(|r| r.r.number == relay_num)
 			.ok_or(EmgauwaError::Other(String::from("Relay not found")))?;
 
+		log::debug!("Pulsing relay {} until {:?}", relay_num, until);
+
 		relay.pulsing = Some(until);
 		Ok(())
 	}
diff --git a/src/models/relay.rs b/src/models/relay.rs
index f44b290..51289ca 100644
--- a/src/models/relay.rs
+++ b/src/models/relay.rs
@@ -9,7 +9,7 @@ use sqlx::Sqlite;
 use crate::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule};
 use crate::errors::DatabaseError;
 use crate::models::FromDbModel;
-use crate::types::{EmgauwaUid, Weekday};
+use crate::types::{EmgauwaUid, RelayState, Weekday};
 use crate::utils;
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -20,12 +20,7 @@ pub struct Relay {
 	pub controller_id: EmgauwaUid,
 	pub schedules: Vec<DbSchedule>,
 	pub active_schedule: DbSchedule,
-	#[serde(
-		default,                                    // <- important for deserialization
-		skip_serializing_if = "Option::is_none",    // <- important for serialization
-		with = "::serde_with::rust::double_option",
-	)]
-	pub override_schedule: Option<Option<DbSchedule>>,
+	pub override_schedule: Option<DbSchedule>,
 	pub is_on: Option<bool>,
 	pub tags: Vec<String>,
 
@@ -112,12 +107,12 @@ impl Relay {
 	}
 
 	pub fn reload_active_schedule(&mut self, weekday: Weekday) {
-		if let Some((Some(schedule), schedule_weekday)) = self.unwrap_override_schedule() {
-			if schedule_weekday == weekday {
+		if let Some(schedule) = &self.override_schedule {
+			if self.override_schedule_weekday == weekday {
 				self.active_schedule = schedule.clone();
 				return;
 			}
-			if schedule_weekday != weekday {
+			if self.override_schedule_weekday != weekday {
 				self.override_schedule = None;
 			}
 		}
@@ -125,10 +120,16 @@ impl Relay {
 		self.active_schedule = self.schedules.get(weekday as usize).unwrap().clone()
 	}
 
-	pub fn unwrap_override_schedule(&self) -> Option<(&Option<DbSchedule>, Weekday)> {
-		if let Some(schedule) = &self.override_schedule {
-			return Some((schedule, self.override_schedule_weekday));
-		}
-		None
+	pub fn apply_state(&mut self, state: &RelayState) {
+		self.active_schedule = state.active_schedule.clone();
+		self.override_schedule.clone_from(&state.override_schedule);
+		self.is_on = state.is_on;
 	}
+
+	pub fn find_and_apply_state(&mut self, stated_relays: &[Relay]) {
+		if let Some(stated_relay) = stated_relays.iter().find(|r| r.r.id == self.r.id) {
+			self.apply_state(&stated_relay.into());
+		}
+	}
+
 }
diff --git a/src/types/mod.rs b/src/types/mod.rs
index 24f3c78..44d116c 100644
--- a/src/types/mod.rs
+++ b/src/types/mod.rs
@@ -2,10 +2,12 @@ mod emgauwa_now;
 mod emgauwa_uid;
 mod request;
 mod schedule_uid;
+mod relay_state;
 
 use actix::Message;
 pub use emgauwa_now::EmgauwaNow;
 pub use emgauwa_uid::EmgauwaUid;
+pub use relay_state::{RelayState, RelayStates};
 pub use request::*;
 pub use schedule_uid::ScheduleUid;
 use serde_derive::{Deserialize, Serialize};
@@ -16,14 +18,6 @@ use crate::models::{Controller, Relay};
 
 pub type Weekday = i64;
 
-#[derive(Debug, Clone, Serialize, Deserialize)]
-pub struct RelayState {
-	pub active_schedule: DbSchedule,
-	pub is_on: Option<bool>
-}
-
-pub type RelayStates = Vec<RelayState>;
-
 #[derive(Debug, Serialize, Deserialize, Message)]
 #[rtype(result = "Result<(), EmgauwaError>")]
 pub enum ControllerWsAction {
diff --git a/src/types/relay_state.rs b/src/types/relay_state.rs
new file mode 100644
index 0000000..f4a2e3a
--- /dev/null
+++ b/src/types/relay_state.rs
@@ -0,0 +1,22 @@
+use serde_derive::{Deserialize, Serialize};
+use crate::db::DbSchedule;
+use crate::models::Relay;
+
+#[derive(Debug, Clone, Serialize, Deserialize)]
+pub struct RelayState {
+    pub active_schedule: DbSchedule,
+    pub override_schedule: Option<DbSchedule>,
+    pub is_on: Option<bool>
+}
+
+pub type RelayStates = Vec<RelayState>;
+
+impl From<&Relay> for RelayState {
+    fn from(relay: &Relay) -> Self {
+        RelayState {
+            active_schedule: relay.active_schedule.clone(),
+            override_schedule: relay.override_schedule.clone(),
+            is_on: relay.is_on
+        }
+    }
+}
\ No newline at end of file