diff --git a/emgauwa-controller/src/ws/mod.rs b/emgauwa-controller/src/ws/mod.rs index edead72..50f105e 100644 --- a/emgauwa-controller/src/ws/mod.rs +++ b/emgauwa-controller/src/ws/mod.rs @@ -1,9 +1,9 @@ use actix::Addr; use emgauwa_lib::constants::WEBSOCKET_RETRY_TIMEOUT; -use emgauwa_lib::db::DbController; +use emgauwa_lib::db::{DbController, DbRelay, DbSchedule}; use emgauwa_lib::errors::{DatabaseError, EmgauwaError}; -use emgauwa_lib::models::Controller; -use emgauwa_lib::types::ControllerWsAction; +use emgauwa_lib::models::{Controller, Relay}; +use emgauwa_lib::types::{ControllerWsAction, ScheduleUid}; use futures::{SinkExt, StreamExt}; use sqlx::pool::PoolConnection; use sqlx::{Pool, Sqlite}; @@ -105,20 +105,26 @@ pub async fn handle_action( app_state: &Addr, action: ControllerWsAction, ) -> Result<(), EmgauwaError> { + let this = app_state_get_this(app_state).await?; + match action { ControllerWsAction::Controller(controller) => { - handle_controller(conn, app_state, controller).await + handle_controller(conn, app_state, &this, controller).await + } + ControllerWsAction::Relays(relays) => handle_relays(conn, app_state, &this, relays).await, + ControllerWsAction::Schedules(schedules) => { + handle_schedules(conn, app_state, schedules).await } _ => Ok(()), } } -pub async fn handle_controller( +async fn handle_controller( conn: &mut PoolConnection, app_state: &Addr, + this: &Controller, controller: Controller, ) -> Result<(), EmgauwaError> { - let this = app_state_get_this(app_state).await?; if controller.c.uid != this.c.uid { return Err(EmgauwaError::Other(String::from( "Controller UID mismatch during update", @@ -134,3 +140,68 @@ pub async fn handle_controller( Ok(()) } + +async fn handle_schedules( + conn: &mut PoolConnection, + app_state: &Addr, + schedules: Vec, +) -> Result<(), EmgauwaError> { + let mut handled_uids = vec![ + // on and off schedules are always present and should not be updated + ScheduleUid::On, + ScheduleUid::Off, + ]; + for schedule in schedules { + if handled_uids.contains(&schedule.uid) { + continue; + } + handled_uids.push(schedule.uid.clone()); + + log::debug!("Handling schedule: {:?}", schedule); + let schedule_db = DbSchedule::get_by_uid(conn, &schedule.uid).await?; + + if let Some(schedule_db) = schedule_db { + schedule_db + .update(conn, schedule.name.as_str(), &schedule.periods) + .await?; + } else { + DbSchedule::create( + conn, + schedule.uid.clone(), + schedule.name.as_str(), + &schedule.periods, + ) + .await?; + } + } + + app_state.send(app_state::Reload {}).await??; + + Ok(()) +} + +async fn handle_relays( + conn: &mut PoolConnection, + app_state: &Addr, + this: &Controller, + relays: Vec, +) -> Result<(), EmgauwaError> { + for relay in relays { + if relay.controller.uid != this.c.uid { + return Err(EmgauwaError::Other(String::from( + "Controller UID mismatch during relay update", + ))); + } + DbRelay::get_by_controller_and_num(conn, &this.c, relay.r.number) + .await? + .ok_or(DatabaseError::NotFound)? + .update(conn, relay.r.name.as_str()) + .await?; + + handle_schedules(conn, app_state, relay.schedules).await?; + } + + app_state.send(app_state::Reload {}).await??; + + Ok(()) +} diff --git a/emgauwa-lib/src/types/schedule_uid.rs b/emgauwa-lib/src/types/schedule_uid.rs index 2e903a9..b538df9 100644 --- a/emgauwa-lib/src/types/schedule_uid.rs +++ b/emgauwa-lib/src/types/schedule_uid.rs @@ -42,6 +42,17 @@ impl Debug for ScheduleUid { } } +impl PartialEq for ScheduleUid { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Off, Self::Off) => true, + (Self::On, Self::On) => true, + (Self::Any(my_uuid), Self::Any(other_uuid)) => my_uuid == other_uuid, + _ => false, + } + } +} + impl Type for ScheduleUid { fn type_info() -> SqliteTypeInfo { <&[u8] as Type>::type_info()