Compare commits

..

No commits in common. "41cc9e0622b69868eb13db843b1323337cb7a544" and "f26e66d68796bcd3e391a36100c12c3bb9fa210a" have entirely different histories.

27 changed files with 102 additions and 197 deletions

BIN
Cargo.lock generated

Binary file not shown.

View file

@ -13,7 +13,6 @@ actix-web-actors = "4.2"
serde = "1.0" serde = "1.0"
serde_json = "1.0" serde_json = "1.0"
serde_derive = "1.0" serde_derive = "1.0"
serde_with = "3.8"
simple_logger = "5.0" simple_logger = "5.0"
log = "0.4" log = "0.4"

View file

@ -1 +0,0 @@
DROP VIEW v_relays;

View file

@ -1,8 +0,0 @@
CREATE VIEW v_relays
AS
SELECT
relays.*,
controllers.uid AS controller_uid
FROM
relays
INNER JOIN controllers ON controllers.id = relays.controller_id;

View file

@ -158,7 +158,7 @@ impl DbController {
) -> Result<Vec<DbRelay>, DatabaseError> { ) -> Result<Vec<DbRelay>, DatabaseError> {
sqlx::query_as!( sqlx::query_as!(
DbRelay, DbRelay,
"SELECT * FROM v_relays WHERE v_relays.controller_id = ?", "SELECT * FROM relays WHERE controller_id = ?",
self.id self.id
) )
.fetch_all(conn.deref_mut()) .fetch_all(conn.deref_mut())

View file

@ -5,10 +5,11 @@ use sqlx::Sqlite;
use crate::db::{DbRelay, DbSchedule}; use crate::db::{DbRelay, DbSchedule};
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::types::Weekday;
pub struct DbJunctionRelaySchedule { pub struct DbJunctionRelaySchedule {
pub id: i64, pub id: i64,
pub weekday: i64, pub weekday: Weekday,
pub relay_id: i64, pub relay_id: i64,
pub schedule_id: i64, pub schedule_id: i64,
} }
@ -31,7 +32,7 @@ impl DbJunctionRelaySchedule {
pub async fn get_junction_by_relay_and_weekday( pub async fn get_junction_by_relay_and_weekday(
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
relay: &DbRelay, relay: &DbRelay,
weekday: i64, weekday: Weekday,
) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> { ) -> Result<Option<DbJunctionRelaySchedule>, DatabaseError> {
sqlx::query_as!( sqlx::query_as!(
DbJunctionRelaySchedule, DbJunctionRelaySchedule,
@ -50,8 +51,8 @@ impl DbJunctionRelaySchedule {
) -> Result<Vec<DbRelay>, DatabaseError> { ) -> Result<Vec<DbRelay>, DatabaseError> {
sqlx::query_as!( sqlx::query_as!(
DbRelay, DbRelay,
r#"SELECT v_relays.* FROM v_relays INNER JOIN junction_relay_schedule r#"SELECT relays.* FROM relays INNER JOIN junction_relay_schedule
ON junction_relay_schedule.relay_id = v_relays.id ON junction_relay_schedule.relay_id = relays.id
WHERE junction_relay_schedule.schedule_id = ? WHERE junction_relay_schedule.schedule_id = ?
ORDER BY junction_relay_schedule.weekday"#, ORDER BY junction_relay_schedule.weekday"#,
schedule.id schedule.id
@ -64,7 +65,7 @@ impl DbJunctionRelaySchedule {
pub async fn get_schedule( pub async fn get_schedule(
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
relay: &DbRelay, relay: &DbRelay,
weekday: i64, weekday: Weekday,
) -> Result<Option<DbSchedule>, DatabaseError> { ) -> Result<Option<DbSchedule>, DatabaseError> {
sqlx::query_as!( sqlx::query_as!(
DbSchedule, DbSchedule,
@ -100,7 +101,7 @@ impl DbJunctionRelaySchedule {
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
relay: &DbRelay, relay: &DbRelay,
schedule: &DbSchedule, schedule: &DbSchedule,
weekday: i64, weekday: Weekday,
) -> Result<DbJunctionRelaySchedule, DatabaseError> { ) -> Result<DbJunctionRelaySchedule, DatabaseError> {
match Self::get_junction_by_relay_and_weekday(conn, relay, weekday).await? { match Self::get_junction_by_relay_and_weekday(conn, relay, weekday).await? {
None => sqlx::query_as!( None => sqlx::query_as!(
@ -138,7 +139,7 @@ impl DbJunctionRelaySchedule {
schedules: Vec<&DbSchedule>, schedules: Vec<&DbSchedule>,
) -> Result<(), DatabaseError> { ) -> Result<(), DatabaseError> {
for (weekday, schedule) in schedules.iter().enumerate() { for (weekday, schedule) in schedules.iter().enumerate() {
Self::set_schedule(conn, relay, schedule, weekday as i64).await?; Self::set_schedule(conn, relay, schedule, weekday as Weekday).await?;
} }
Ok(()) Ok(())
} }

View file

@ -1,10 +1,10 @@
use chrono::{NaiveTime, Timelike}; use chrono::{NaiveTime, Timelike};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use sqlx::{Decode, Encode, Sqlite, Type};
use sqlx::database::HasArguments; use sqlx::database::HasArguments;
use sqlx::encode::IsNull; use sqlx::encode::IsNull;
use sqlx::error::BoxDynError; use sqlx::error::BoxDynError;
use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef}; use sqlx::sqlite::{SqliteTypeInfo, SqliteValueRef};
use sqlx::{Decode, Encode, Sqlite, Type};
use crate::db::DbPeriods; use crate::db::DbPeriods;
@ -67,12 +67,12 @@ impl Period {
let start_before_end = self.start.lt(&self.end); let start_before_end = self.start.lt(&self.end);
match (start_after_now, end_after_now, start_before_end) { match (start_after_now, end_after_now, start_before_end) {
(false, false, true) => false, // both before now; start before end means "normal" period before now (false, false, true) => false, // both before now; start before end means "normal" period before now
(false, false, false) => true, // both before now; end before start means "inversed" period around now (false, false, false) => true, // both before now; end before start means "inversed" period around now
(true, false, _) => false, // only start after now (true, false, _) => false, // only start after now
(false, true, _) => true, // only end after now (false, true, _) => true, // only end after now
(true, true, true) => false, // both after now but start first (true, true, true) => false, // both after now but start first
(true, true, false) => true, // both after now but end first (true, true, false) => true, // both after now but end first
} }
} }

View file

@ -4,9 +4,10 @@ use serde_derive::{Deserialize, Serialize};
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::Sqlite; use sqlx::Sqlite;
use crate::db::{DbController, DbJunctionTag, DbTag}; use crate::db::{DbController, DbJunctionRelaySchedule, DbJunctionTag, DbSchedule, DbTag};
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::types::EmgauwaUid; use crate::types::Weekday;
use crate::utils;
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DbRelay { pub struct DbRelay {
@ -14,15 +15,13 @@ pub struct DbRelay {
pub id: i64, pub id: i64,
pub name: String, pub name: String,
pub number: i64, pub number: i64,
#[serde(rename = "controller_id")]
pub controller_uid: EmgauwaUid,
#[serde(skip)] #[serde(skip)]
pub controller_id: i64, pub controller_id: i64,
} }
impl DbRelay { impl DbRelay {
pub async fn get_all(conn: &mut PoolConnection<Sqlite>) -> Result<Vec<DbRelay>, DatabaseError> { pub async fn get_all(conn: &mut PoolConnection<Sqlite>) -> Result<Vec<DbRelay>, DatabaseError> {
sqlx::query_as!(DbRelay, "SELECT * FROM v_relays") sqlx::query_as!(DbRelay, "SELECT * FROM relays")
.fetch_all(conn.deref_mut()) .fetch_all(conn.deref_mut())
.await .await
.map_err(DatabaseError::from) .map_err(DatabaseError::from)
@ -32,7 +31,7 @@ impl DbRelay {
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
id: i64, id: i64,
) -> Result<Option<DbRelay>, DatabaseError> { ) -> Result<Option<DbRelay>, DatabaseError> {
sqlx::query_as!(DbRelay, "SELECT * FROM v_relays WHERE v_relays.id = ?", id) sqlx::query_as!(DbRelay, "SELECT * FROM relays WHERE id = ?", id)
.fetch_optional(conn.deref_mut()) .fetch_optional(conn.deref_mut())
.await .await
.map_err(DatabaseError::from) .map_err(DatabaseError::from)
@ -45,7 +44,7 @@ impl DbRelay {
) -> Result<Option<DbRelay>, DatabaseError> { ) -> Result<Option<DbRelay>, DatabaseError> {
sqlx::query_as!( sqlx::query_as!(
DbRelay, DbRelay,
"SELECT * FROM v_relays WHERE v_relays.controller_id = ? AND v_relays.number = ?", "SELECT * FROM relays WHERE controller_id = ? AND number = ?",
controller.id, controller.id,
number number
) )
@ -73,7 +72,7 @@ impl DbRelay {
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
tag: &DbTag, tag: &DbTag,
) -> Result<Vec<DbRelay>, DatabaseError> { ) -> Result<Vec<DbRelay>, DatabaseError> {
sqlx::query_as!(DbRelay, "SELECT v_relays.* FROM v_relays INNER JOIN junction_tag ON junction_tag.relay_id = v_relays.id WHERE junction_tag.tag_id = ?", tag.id) sqlx::query_as!(DbRelay, "SELECT relay.* FROM relays AS relay INNER JOIN junction_tag ON junction_tag.relay_id = relay.id WHERE junction_tag.tag_id = ?", tag.id)
.fetch_all(conn.deref_mut()) .fetch_all(conn.deref_mut())
.await .await
.map_err(DatabaseError::from) .map_err(DatabaseError::from)
@ -85,25 +84,16 @@ impl DbRelay {
new_number: i64, new_number: i64,
new_controller: &DbController, new_controller: &DbController,
) -> Result<DbRelay, DatabaseError> { ) -> Result<DbRelay, DatabaseError> {
let result = sqlx::query!( sqlx::query_as!(
"INSERT INTO relays (name, number, controller_id) VALUES (?, ?, ?)", DbRelay,
"INSERT INTO relays (name, number, controller_id) VALUES (?, ?, ?) RETURNING *",
new_name, new_name,
new_number, new_number,
new_controller.id, new_controller.id,
) )
.execute(conn.deref_mut()) .fetch_optional(conn.deref_mut())
.await?; .await?
.ok_or(DatabaseError::InsertGetError)
let last_insert_id = result.last_insert_rowid();
sqlx::query_as!(
DbRelay,
"SELECT * FROM v_relays WHERE id = ?",
last_insert_id
)
.fetch_one(conn.deref_mut())
.await
.map_err(DatabaseError::from)
} }
pub async fn delete(&self, conn: &mut PoolConnection<Sqlite>) -> Result<(), DatabaseError> { pub async fn delete(&self, conn: &mut PoolConnection<Sqlite>) -> Result<(), DatabaseError> {
@ -173,4 +163,14 @@ impl DbRelay {
.await? .await?
.ok_or(DatabaseError::NotFound) .ok_or(DatabaseError::NotFound)
} }
pub async fn get_active_schedule(
&self,
conn: &mut PoolConnection<Sqlite>,
) -> Result<DbSchedule, DatabaseError> {
let weekday = utils::get_weekday();
DbJunctionRelaySchedule::get_schedule(conn, self, weekday as Weekday)
.await?
.ok_or(DatabaseError::NotFound)
}
} }

View file

@ -47,9 +47,7 @@ impl From<&EmgauwaError> for String {
EmgauwaError::Database(err) => String::from(err), EmgauwaError::Database(err) => String::from(err),
EmgauwaError::Uid(_) => String::from("the uid is in a bad format"), EmgauwaError::Uid(_) => String::from("the uid is in a bad format"),
EmgauwaError::Internal(_) => String::from("internal error"), EmgauwaError::Internal(_) => String::from("internal error"),
EmgauwaError::Connection(uid) => { EmgauwaError::Connection(uid) => format!("unable to connect to controller with uid: {}", uid),
format!("unable to connect to controller with uid: {}", uid)
}
EmgauwaError::Other(err) => format!("other error: {}", err), EmgauwaError::Other(err) => format!("other error: {}", err),
EmgauwaError::Hardware(err) => format!("hardware error: {}", err), EmgauwaError::Hardware(err) => format!("hardware error: {}", err),
} }

View file

@ -9,8 +9,8 @@ use sqlx::Sqlite;
use crate::db::DbController; use crate::db::DbController;
use crate::errors::{DatabaseError, EmgauwaError}; use crate::errors::{DatabaseError, EmgauwaError};
use crate::models::{convert_db_list, FromDbModel, Relay}; use crate::models::{convert_db_list_cache, FromDbModel, Relay};
use crate::types::{EmgauwaNow, RelayState, RelayStates}; use crate::types::RelayStates;
#[derive(Serialize, Deserialize, Debug, Clone, MessageResponse)] #[derive(Serialize, Deserialize, Debug, Clone, MessageResponse)]
pub struct Controller { pub struct Controller {
@ -28,7 +28,7 @@ impl FromDbModel for Controller {
db_model: Self::DbModel, db_model: Self::DbModel,
) -> Result<Self, DatabaseError> { ) -> Result<Self, DatabaseError> {
let relays_db = block_on(db_model.get_relays(conn))?; let relays_db = block_on(db_model.get_relays(conn))?;
let cache = convert_db_list(conn, relays_db)?; let cache = convert_db_list_cache(conn, relays_db, db_model.clone())?;
Self::from_db_model_cache(conn, db_model, cache) Self::from_db_model_cache(conn, db_model, cache)
} }
@ -57,20 +57,19 @@ impl Controller {
self.relays self.relays
.iter_mut() .iter_mut()
.zip(relay_states.iter()) .zip(relay_states.iter())
.for_each(|(relay, state)| relay.apply_state(state)); .for_each(|(relay, is_on)| {
relay.is_on = *is_on;
});
} }
pub fn get_relay_states(&self) -> RelayStates { pub fn get_relay_states(&self) -> RelayStates {
self.relays.iter().map(RelayState::from).collect() self.relays.iter().map(|r| r.is_on).collect()
} }
pub fn check_next_time(&mut self, now: &EmgauwaNow) -> Option<NaiveTime> { pub fn get_next_time(&self, now: &NaiveTime) -> Option<NaiveTime> {
self.relays self.relays
.iter_mut() .iter()
.filter_map(|r| { .filter_map(|r| r.active_schedule.get_next_time(now))
r.reload_active_schedule(now.weekday);
r.get_next_time(&now.time)
})
.min() .min()
} }
@ -81,8 +80,6 @@ impl Controller {
.find(|r| r.r.number == relay_num) .find(|r| r.r.number == relay_num)
.ok_or(EmgauwaError::Other(String::from("Relay not found")))?; .ok_or(EmgauwaError::Other(String::from("Relay not found")))?;
log::debug!("Pulsing relay {} until {:?}", relay_num, until);
relay.pulsing = Some(until); relay.pulsing = Some(until);
Ok(()) Ok(())
} }

View file

@ -3,13 +3,13 @@ use serde_derive::{Deserialize, Serialize};
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::Sqlite; use sqlx::Sqlite;
use crate::db::{DbJunctionRelaySchedule, DbMacroAction, DbSchedule}; use crate::db::{DbJunctionRelaySchedule, DbMacroAction};
use crate::errors::{DatabaseError, EmgauwaError}; use crate::errors::{DatabaseError, EmgauwaError};
use crate::models::{FromDbModel, Relay}; use crate::models::{FromDbModel, Relay, Schedule};
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MacroAction { pub struct MacroAction {
pub schedule: DbSchedule, pub schedule: Schedule,
pub relay: Relay, pub relay: Relay,
pub weekday: i64, pub weekday: i64,
} }
@ -30,7 +30,8 @@ impl FromDbModel for MacroAction {
db_model: Self::DbModel, db_model: Self::DbModel,
_cache: Self::DbModelCache, _cache: Self::DbModelCache,
) -> Result<Self, DatabaseError> { ) -> Result<Self, DatabaseError> {
let schedule = block_on(db_model.get_schedule(conn))?; let schedule_db = block_on(db_model.get_schedule(conn))?;
let schedule = Schedule::from_db_model(conn, schedule_db)?;
let relay_db = block_on(db_model.get_relay(conn))?; let relay_db = block_on(db_model.get_relay(conn))?;
let relay = Relay::from_db_model(conn, relay_db)?; let relay = Relay::from_db_model(conn, relay_db)?;
@ -47,7 +48,7 @@ impl FromDbModel for MacroAction {
impl MacroAction { impl MacroAction {
pub async fn execute(&self, conn: &mut PoolConnection<Sqlite>) -> Result<(), EmgauwaError> { pub async fn execute(&self, conn: &mut PoolConnection<Sqlite>) -> Result<(), EmgauwaError> {
DbJunctionRelaySchedule::set_schedule(conn, &self.relay.r, &self.schedule, self.weekday) DbJunctionRelaySchedule::set_schedule(conn, &self.relay.r, &self.schedule.s, self.weekday)
.await?; .await?;
Ok(()) Ok(())
} }

View file

@ -1,65 +1,66 @@
use std::time::Instant; use std::time::Instant;
use chrono::{NaiveTime, Weekday}; use chrono::NaiveTime;
use futures::executor::block_on; use futures::executor::block_on;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
use sqlx::pool::PoolConnection; use sqlx::pool::PoolConnection;
use sqlx::Sqlite; use sqlx::Sqlite;
use crate::db::{DbJunctionRelaySchedule, DbRelay, DbSchedule}; use crate::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule};
use crate::errors::DatabaseError; use crate::errors::DatabaseError;
use crate::models::FromDbModel; use crate::models::FromDbModel;
use crate::types::RelayState; use crate::types::EmgauwaUid;
use crate::utils;
#[derive(Serialize, Deserialize, Debug, Clone)] #[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Relay { pub struct Relay {
#[serde(flatten)] #[serde(flatten)]
pub r: DbRelay, pub r: DbRelay,
pub controller: DbController,
pub controller_id: EmgauwaUid,
pub schedules: Vec<DbSchedule>, pub schedules: Vec<DbSchedule>,
pub active_schedule: Option<DbSchedule>, pub active_schedule: DbSchedule,
pub override_schedule: Option<DbSchedule>,
pub is_on: Option<bool>, pub is_on: Option<bool>,
pub tags: Vec<String>, pub tags: Vec<String>,
// for internal use only. // for internal use only.
#[serde(skip)] #[serde(skip)]
pub pulsing: Option<Instant>, pub pulsing: Option<Instant>,
#[serde(skip, default = "utils::default_weekday")]
pub override_schedule_weekday: Weekday,
} }
impl FromDbModel for Relay { impl FromDbModel for Relay {
type DbModel = DbRelay; type DbModel = DbRelay;
type DbModelCache = (); type DbModelCache = DbController;
fn from_db_model( fn from_db_model(
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
db_model: Self::DbModel, db_model: Self::DbModel,
) -> Result<Self, DatabaseError> { ) -> Result<Self, DatabaseError> {
Self::from_db_model_cache(conn, db_model, ()) let cache = block_on(db_model.get_controller(conn))?;
Self::from_db_model_cache(conn, db_model, cache)
} }
fn from_db_model_cache( fn from_db_model_cache(
conn: &mut PoolConnection<Sqlite>, conn: &mut PoolConnection<Sqlite>,
db_model: Self::DbModel, db_model: Self::DbModel,
_cache: Self::DbModelCache, cache: Self::DbModelCache,
) -> Result<Self, DatabaseError> { ) -> Result<Self, DatabaseError> {
let tags = block_on(db_model.get_tags(conn))?; 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 schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &db_model))?;
let active_schedule = block_on(db_model.get_active_schedule(conn))?;
let is_on = None; let is_on = None;
Ok(Relay { Ok(Relay {
r: db_model, r: db_model,
controller: cache,
controller_id,
schedules, schedules,
active_schedule: None, active_schedule,
override_schedule: None,
is_on, is_on,
tags, tags,
pulsing: None, pulsing: None,
override_schedule_weekday: utils::default_weekday(),
}) })
} }
} }
@ -68,24 +69,25 @@ impl Relay {
pub fn reload(&mut self, conn: &mut PoolConnection<Sqlite>) -> Result<(), DatabaseError> { pub fn reload(&mut self, conn: &mut PoolConnection<Sqlite>) -> Result<(), DatabaseError> {
self.r = block_on(self.r.reload(conn))?; self.r = block_on(self.r.reload(conn))?;
self.schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &self.r))?; self.schedules = block_on(DbJunctionRelaySchedule::get_schedules(conn, &self.r))?;
self.reload_active_schedule(conn)?;
Ok(()) 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 { pub fn is_on(&self, now: &NaiveTime) -> bool {
if let Some(active_schedule) = &self.active_schedule { self.active_schedule.is_on(now)
active_schedule.is_on(now)
} else {
false
}
} }
pub fn get_next_time(&self, now: &NaiveTime) -> Option<NaiveTime> { pub fn get_next_time(&self, now: &NaiveTime) -> Option<NaiveTime> {
if let Some(active_schedule) = &self.active_schedule { self.active_schedule.get_next_time(now)
active_schedule.get_next_time(now)
} else {
None
}
} }
pub fn check_pulsing(&mut self, now: &Instant) -> Option<Instant> { pub fn check_pulsing(&mut self, now: &Instant) -> Option<Instant> {
@ -101,30 +103,4 @@ impl Relay {
None => None, None => None,
} }
} }
pub fn reload_active_schedule(&mut self, weekday: Weekday) {
if let Some(schedule) = &self.override_schedule {
if self.override_schedule_weekday == weekday {
self.active_schedule = Some(schedule.clone());
return;
}
if self.override_schedule_weekday != weekday {
self.override_schedule = None;
}
}
self.active_schedule = Some(self.schedules.get(weekday as usize).unwrap().clone())
}
pub fn apply_state(&mut self, state: &RelayState) {
self.active_schedule.clone_from(&state.active_schedule);
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());
}
}
} }

View file

@ -16,6 +16,7 @@ pub struct Server {
#[allow(unused)] #[allow(unused)]
pub struct Logging { pub struct Logging {
pub level: String, pub level: String,
pub file: String,
} }
#[derive(Clone, Debug, Deserialize, Default)] #[derive(Clone, Debug, Deserialize, Default)]
@ -39,6 +40,7 @@ impl Default for Logging {
fn default() -> Self { fn default() -> Self {
Logging { Logging {
level: String::from("info"), level: String::from("info"),
file: String::from("stdout"),
} }
} }
} }

View file

@ -1,27 +0,0 @@
use std::time::Instant;
use chrono::{Local, NaiveTime, Timelike, Weekday};
use crate::utils;
pub struct EmgauwaNow {
pub time: NaiveTime,
pub instant: Instant,
pub weekday: Weekday,
pub midnight: NaiveTime,
}
impl EmgauwaNow {
pub fn now(midnight: &NaiveTime) -> EmgauwaNow {
EmgauwaNow {
time: Local::now().time(),
instant: Instant::now(),
weekday: utils::get_weekday(midnight),
midnight: *midnight,
}
}
pub fn num_seconds_from_midnight(&self) -> u32 {
self.time.num_seconds_from_midnight()
}
}

View file

@ -1,13 +1,9 @@
mod emgauwa_now;
mod emgauwa_uid; mod emgauwa_uid;
mod request; mod request;
mod schedule_uid; mod schedule_uid;
mod relay_state;
use actix::Message; use actix::Message;
pub use emgauwa_now::EmgauwaNow;
pub use emgauwa_uid::EmgauwaUid; pub use emgauwa_uid::EmgauwaUid;
pub use relay_state::{RelayState, RelayStates};
pub use request::*; pub use request::*;
pub use schedule_uid::ScheduleUid; pub use schedule_uid::ScheduleUid;
use serde_derive::{Deserialize, Serialize}; use serde_derive::{Deserialize, Serialize};
@ -16,6 +12,10 @@ use crate::db::DbSchedule;
use crate::errors::EmgauwaError; use crate::errors::EmgauwaError;
use crate::models::{Controller, Relay}; use crate::models::{Controller, Relay};
pub type Weekday = i64;
pub type RelayStates = Vec<Option<bool>>;
#[derive(Debug, Serialize, Deserialize, Message)] #[derive(Debug, Serialize, Deserialize, Message)]
#[rtype(result = "Result<(), EmgauwaError>")] #[rtype(result = "Result<(), EmgauwaError>")]
pub enum ControllerWsAction { pub enum ControllerWsAction {

View file

@ -1,22 +0,0 @@
use serde_derive::{Deserialize, Serialize};
use crate::db::DbSchedule;
use crate::models::Relay;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RelayState {
pub active_schedule: Option<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
}
}
}

View file

@ -23,12 +23,7 @@ pub struct RequestScheduleUpdate {
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
pub struct RequestRelayUpdate { pub struct RequestRelayUpdate {
pub name: Option<String>, pub name: Option<String>,
#[serde( pub active_schedule: Option<RequestScheduleId>,
default, // <- important for deserialization
skip_serializing_if = "Option::is_none", // <- important for serialization
with = "::serde_with::rust::double_option",
)]
pub override_schedule: Option<Option<RequestScheduleId>>,
pub schedules: Option<Vec<RequestScheduleId>>, pub schedules: Option<Vec<RequestScheduleId>>,
pub tags: Option<Vec<String>>, pub tags: Option<Vec<String>>,
} }

View file

@ -2,17 +2,17 @@ use std::ffi::CString;
use std::io::{Error, ErrorKind}; use std::io::{Error, ErrorKind};
use std::str::FromStr; use std::str::FromStr;
use chrono::{Datelike, NaiveTime, Weekday}; use chrono::Datelike;
use log::LevelFilter; use log::LevelFilter;
use simple_logger::SimpleLogger; use simple_logger::SimpleLogger;
use crate::errors::EmgauwaError; use crate::errors::EmgauwaError;
use crate::settings::{Logging, Permissions}; use crate::settings::Permissions;
use crate::types::RelayStates; use crate::types::{RelayStates, Weekday};
pub fn init_logging(logging: &Logging) -> Result<(), EmgauwaError> { pub fn init_logging(level: &str) -> Result<(), EmgauwaError> {
let log_level: LevelFilter = LevelFilter::from_str(&logging.level) let log_level: LevelFilter = LevelFilter::from_str(level)
.map_err(|_| EmgauwaError::Other(format!("Invalid log level: {}", logging.level)))?; .map_err(|_| EmgauwaError::Other(format!("Invalid log level: {}", level)))?;
log::trace!("Log level set to {:?}", log_level); log::trace!("Log level set to {:?}", log_level);
SimpleLogger::new() SimpleLogger::new()
@ -92,24 +92,18 @@ fn drop_privileges_user(user: &str) -> Result<(), Error> {
Ok(()) Ok(())
} }
pub fn get_weekday(midnight: &NaiveTime) -> Weekday { pub fn get_weekday() -> Weekday {
let dt = chrono::offset::Local::now().naive_local(); (chrono::offset::Local::now()
let weekday = dt.weekday(); .date_naive()
if dt.time().lt(midnight) { .weekday()
weekday.pred() .number_from_monday()
} else { - 1) as Weekday
weekday
}
}
pub fn default_weekday() -> Weekday {
Weekday::Mon
} }
pub fn printable_relay_states(relay_states: &RelayStates) -> String { pub fn printable_relay_states(relay_states: &RelayStates) -> String {
let mut relay_debug = String::new(); let mut relay_debug = String::new();
relay_states.iter().for_each(|state| { relay_states.iter().for_each(|state| {
relay_debug.push_str(match state.is_on { relay_debug.push_str(match state {
Some(true) => "+", Some(true) => "+",
Some(false) => "-", Some(false) => "-",
None => "?", None => "?",