controller/emgauwa-lib/src/models/relay.rs

107 lines
2.5 KiB
Rust

use std::time::Instant;
use chrono::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: Option<bool>,
pub tags: Vec<String>,
// for internal use only.
#[serde(skip)]
pub pulsing: Option<Instant>,
}
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 is_on = None;
Ok(Relay {
r: db_model,
controller: cache,
controller_id,
schedules,
active_schedule,
is_on,
tags,
pulsing: None,
})
}
}
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))?;
Ok(())
}
pub fn is_on(&self, now: &NaiveTime) -> bool {
self.active_schedule.is_on(now)
}
pub fn get_next_time(&self, now: &NaiveTime) -> Option<NaiveTime> {
self.active_schedule.get_next_time(now)
}
pub fn check_pulsing(&mut self, now: &Instant) -> Option<Instant> {
match self.pulsing {
Some(dur_instant) => {
if dur_instant.lt(now) {
self.pulsing = None;
None
} else {
Some(dur_instant)
}
}
None => None,
}
}
}