Add handler for relays (and schedules) in controller

This commit is contained in:
Tobias Reisinger 2024-04-23 01:43:32 +02:00
parent 55a352f85a
commit 45e128361a
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
2 changed files with 88 additions and 6 deletions

View file

@ -1,9 +1,9 @@
use actix::Addr; use actix::Addr;
use emgauwa_lib::constants::WEBSOCKET_RETRY_TIMEOUT; 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::errors::{DatabaseError, EmgauwaError};
use emgauwa_lib::models::Controller; use emgauwa_lib::models::{Controller, Relay};
use emgauwa_lib::types::ControllerWsAction; use emgauwa_lib::types::{ControllerWsAction, ScheduleUid};
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::{Pool, Sqlite}; use sqlx::{Pool, Sqlite};
@ -105,20 +105,26 @@ pub async fn handle_action(
app_state: &Addr<AppState>, app_state: &Addr<AppState>,
action: ControllerWsAction, action: ControllerWsAction,
) -> Result<(), EmgauwaError> { ) -> Result<(), EmgauwaError> {
let this = app_state_get_this(app_state).await?;
match action { match action {
ControllerWsAction::Controller(controller) => { 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(()), _ => Ok(()),
} }
} }
pub async fn handle_controller( async fn handle_controller(
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
app_state: &Addr<AppState>, app_state: &Addr<AppState>,
this: &Controller,
controller: Controller, controller: Controller,
) -> Result<(), EmgauwaError> { ) -> Result<(), EmgauwaError> {
let this = app_state_get_this(app_state).await?;
if controller.c.uid != this.c.uid { if controller.c.uid != this.c.uid {
return Err(EmgauwaError::Other(String::from( return Err(EmgauwaError::Other(String::from(
"Controller UID mismatch during update", "Controller UID mismatch during update",
@ -134,3 +140,68 @@ pub async fn handle_controller(
Ok(()) Ok(())
} }
async fn handle_schedules(
conn: &mut PoolConnection<Sqlite>,
app_state: &Addr<AppState>,
schedules: Vec<DbSchedule>,
) -> 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<Sqlite>,
app_state: &Addr<AppState>,
this: &Controller,
relays: Vec<Relay>,
) -> 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(())
}

View file

@ -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<Sqlite> for ScheduleUid { impl Type<Sqlite> for ScheduleUid {
fn type_info() -> SqliteTypeInfo { fn type_info() -> SqliteTypeInfo {
<&[u8] as Type<Sqlite>>::type_info() <&[u8] as Type<Sqlite>>::type_info()