Compare commits

..

No commits in common. "929985c64af0a69db30c89e3c03d22294fc0935c" and "f26e66d68796bcd3e391a36100c12c3bb9fa210a" have entirely different histories.

12 changed files with 35 additions and 124 deletions

BIN
Cargo.lock generated

Binary file not shown.

View file

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

View file

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

View file

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

View file

@ -10,7 +10,7 @@ use sqlx::Sqlite;
use crate::db::DbController;
use crate::errors::{DatabaseError, EmgauwaError};
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)]
pub struct Controller {
@ -57,20 +57,19 @@ impl Controller {
self.relays
.iter_mut()
.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 {
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
.iter_mut()
.filter_map(|r| {
r.reload_active_schedule(now.weekday);
r.active_schedule.get_next_time(&now.time)
})
.iter()
.filter_map(|r| r.active_schedule.get_next_time(now))
.min()
}
@ -81,8 +80,6 @@ impl Controller {
.find(|r| r.r.number == relay_num)
.ok_or(EmgauwaError::Other(String::from("Relay not found")))?;
log::debug!("Pulsing relay {} until {:?}", relay_num, until);
relay.pulsing = Some(until);
Ok(())
}

View file

@ -3,13 +3,13 @@ use serde_derive::{Deserialize, Serialize};
use sqlx::pool::PoolConnection;
use sqlx::Sqlite;
use crate::db::{DbJunctionRelaySchedule, DbMacroAction, DbSchedule};
use crate::db::{DbJunctionRelaySchedule, DbMacroAction};
use crate::errors::{DatabaseError, EmgauwaError};
use crate::models::{FromDbModel, Relay};
use crate::models::{FromDbModel, Relay, Schedule};
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct MacroAction {
pub schedule: DbSchedule,
pub schedule: Schedule,
pub relay: Relay,
pub weekday: i64,
}
@ -30,7 +30,8 @@ impl FromDbModel for MacroAction {
db_model: Self::DbModel,
_cache: Self::DbModelCache,
) -> 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 = Relay::from_db_model(conn, relay_db)?;
@ -47,7 +48,7 @@ impl FromDbModel for MacroAction {
impl MacroAction {
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?;
Ok(())
}

View file

@ -9,8 +9,7 @@ use sqlx::Sqlite;
use crate::db::{DbController, DbJunctionRelaySchedule, DbRelay, DbSchedule};
use crate::errors::DatabaseError;
use crate::models::FromDbModel;
use crate::types::{EmgauwaUid, RelayState, Weekday};
use crate::utils;
use crate::types::EmgauwaUid;
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Relay {
@ -20,18 +19,12 @@ pub struct Relay {
pub controller_id: EmgauwaUid,
pub schedules: Vec<DbSchedule>,
pub active_schedule: DbSchedule,
pub override_schedule: Option<DbSchedule>,
pub is_on: Option<bool>,
pub tags: Vec<String>,
// for internal use only.
#[serde(skip)]
pub pulsing: Option<Instant>,
#[serde(
skip,
default = "utils::get_weekday",
)]
pub override_schedule_weekday: Weekday,
}
impl FromDbModel for Relay {
@ -65,11 +58,9 @@ impl FromDbModel for Relay {
controller_id,
schedules,
active_schedule,
override_schedule: None,
is_on,
tags,
pulsing: None,
override_schedule_weekday: Weekday::default(),
})
}
}
@ -78,9 +69,16 @@ 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)?;
self.reload_active_schedule(utils::get_weekday());
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(())
}
@ -105,31 +103,4 @@ impl Relay {
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 = schedule.clone();
return;
}
if self.override_schedule_weekday != weekday {
self.override_schedule = None;
}
}
self.active_schedule = self.schedules.get(weekday as usize).unwrap().clone()
}
pub fn apply_state(&mut self, state: &RelayState) {
self.active_schedule = state.active_schedule.clone();
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

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

View file

@ -1,13 +1,9 @@
mod emgauwa_now;
mod emgauwa_uid;
mod request;
mod schedule_uid;
mod relay_state;
use actix::Message;
pub use emgauwa_now::EmgauwaNow;
pub use emgauwa_uid::EmgauwaUid;
pub use relay_state::{RelayState, RelayStates};
pub use request::*;
pub use schedule_uid::ScheduleUid;
use serde_derive::{Deserialize, Serialize};
@ -18,6 +14,8 @@ use crate::models::{Controller, Relay};
pub type Weekday = i64;
pub type RelayStates = Vec<Option<bool>>;
#[derive(Debug, Serialize, Deserialize, Message)]
#[rtype(result = "Result<(), EmgauwaError>")]
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: 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)]
pub struct RequestRelayUpdate {
pub name: Option<String>,
#[serde(
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 active_schedule: Option<RequestScheduleId>,
pub schedules: Option<Vec<RequestScheduleId>>,
pub tags: Option<Vec<String>>,
}

View file

@ -103,7 +103,7 @@ pub fn get_weekday() -> Weekday {
pub fn printable_relay_states(relay_states: &RelayStates) -> String {
let mut relay_debug = String::new();
relay_states.iter().for_each(|state| {
relay_debug.push_str(match state.is_on {
relay_debug.push_str(match state {
Some(true) => "+",
Some(false) => "-",
None => "?",