use chrono::{Local, NaiveTime}; use futures::executor::block_on; use serde_derive::{Deserialize, Serialize}; use sqlx::pool::PoolConnection; use sqlx::Sqlite; use crate::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule}; use crate::errors::DatabaseError; use crate::models::FromDbModel; use crate::types::ControllerUid; #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Relay { #[serde(flatten)] pub r: DbRelay, pub controller: DbController, pub controller_id: ControllerUid, pub schedules: Vec<DbSchedule>, pub active_schedule: DbSchedule, pub is_on: bool, pub tags: Vec<String>, } impl FromDbModel for Relay { type DbModel = DbRelay; type DbModelCache = DbController; fn from_db_model( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, ) -> Result<Self, DatabaseError> { let cache = block_on(db_model.get_controller(conn))?; Self::from_db_model_cache(conn, db_model, cache) } fn from_db_model_cache( conn: &mut PoolConnection<Sqlite>, db_model: Self::DbModel, cache: Self::DbModelCache, ) -> Result<Self, DatabaseError> { let tags = block_on(db_model.get_tags(conn))?; let controller_id = cache.uid.clone(); let schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &db_model))?; let active_schedule = block_on(db_model.get_active_schedule(conn))?; let now = Local::now().time(); let is_on = active_schedule.is_on(&now); Ok(Relay { r: db_model, controller: cache, controller_id, schedules, active_schedule, is_on, tags, }) } } impl Relay { pub fn reload(&mut self, conn: &mut PoolConnection<Sqlite>) -> Result<(), DatabaseError> { self.r = block_on(self.r.reload(conn))?; self.schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &self.r))?; self.reload_active_schedule(conn)?; Ok(()) } pub fn reload_active_schedule( &mut self, conn: &mut PoolConnection<Sqlite>, ) -> Result<(), DatabaseError> { self.active_schedule = block_on(self.r.get_active_schedule(conn))?; let now = Local::now().time(); self.is_on = self.active_schedule.is_on(&now); Ok(()) } pub fn is_on(&self, now: &NaiveTime) -> bool { self.active_schedule.is_on(now) } }