diff --git a/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json b/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json new file mode 100644 index 0000000..ce5073b Binary files /dev/null and b/.sqlx/query-03bfe5bd71d673a621b6ad6af5f71bf18ede519e6b950933f6751ef9cf7521c9.json differ diff --git a/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json b/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json new file mode 100644 index 0000000..f7313fd Binary files /dev/null and b/.sqlx/query-1348af1c13719ffcd72c2a4c6712b2bab2a9923c715295d8b1d937d33844d1a4.json differ diff --git a/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json b/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json new file mode 100644 index 0000000..f6f2724 Binary files /dev/null and b/.sqlx/query-2551c285e3e223311cff8e32022d8b11e95d56b2f166326301a0b6722fc1fd44.json differ diff --git a/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json b/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json new file mode 100644 index 0000000..fe474ae Binary files /dev/null and b/.sqlx/query-2e3528a386066c3fc11be1259298f281279353d0b92625c46ef5cd09a672c031.json differ diff --git a/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json b/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json new file mode 100644 index 0000000..59ce879 Binary files /dev/null and b/.sqlx/query-3adb7ab9cacd5a84d882e4c9860be83d32bb0380b1fb76f90bf4e200636c7f6a.json differ diff --git a/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json b/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json new file mode 100644 index 0000000..a4bfa26 Binary files /dev/null and b/.sqlx/query-486ed307f718754a3d4ea2c6fe944f9571c88fad3316593edf0c72ddef24c73e.json differ diff --git a/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json b/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json new file mode 100644 index 0000000..90e1cca Binary files /dev/null and b/.sqlx/query-49afbeaa1d32f8c2e6fea7a2d57a11ec04dd0aab26139c19583af00e5baaba56.json differ diff --git a/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json b/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json new file mode 100644 index 0000000..39b331c Binary files /dev/null and b/.sqlx/query-8bdd41a11fd2ca0440b2d6c0dc752a342012048741bdcd1ff9461bc46e1cf701.json differ diff --git a/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json b/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json new file mode 100644 index 0000000..c86b729 Binary files /dev/null and b/.sqlx/query-96a0b9960daa8a10e04e22cba592870941545b095193612956c29d37a5a1b774.json differ diff --git a/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json b/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json new file mode 100644 index 0000000..ead136f Binary files /dev/null and b/.sqlx/query-a0c9c1a108c6560b4f073c866415a94af2e823a8d88ab2aa5ace8c2b56023004.json differ diff --git a/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json b/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json new file mode 100644 index 0000000..611b0de Binary files /dev/null and b/.sqlx/query-b6f6fd898dc3f1dbe2c39bf0445bac76c8233c0feee15f4504bf74ea864716ce.json differ diff --git a/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json b/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json new file mode 100644 index 0000000..b312064 Binary files /dev/null and b/.sqlx/query-bcd9d4dd3641e6c84262ed5f6c5646f825be186da276b113c0150aaad26b057c.json differ diff --git a/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json b/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json new file mode 100644 index 0000000..6518f69 Binary files /dev/null and b/.sqlx/query-c138a9c659a7410e9935ad3f6a56c2bc73174fb1921fe1260702f1eab87d979c.json differ diff --git a/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json b/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json new file mode 100644 index 0000000..0626f8d Binary files /dev/null and b/.sqlx/query-cb0d76a3a1cfa439d48056c865cd5bfbfbc785fa795254120822b843ce63ff07.json differ diff --git a/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json b/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json new file mode 100644 index 0000000..cb7c1bd Binary files /dev/null and b/.sqlx/query-eee8820f59927c1560a5fd461b9f4a2d40abdf3843d0c815399ea9d267cade5a.json differ diff --git a/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json b/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json new file mode 100644 index 0000000..8d164fb Binary files /dev/null and b/.sqlx/query-fde0dca1aba5b490a9f5f6006677be750a7bcf5d1185935e8386671c69dc7270.json differ diff --git a/api.v1.yaml b/api.v1.yaml index 67c18f5..9b362a3 100644 --- a/api.v1.yaml +++ b/api.v1.yaml @@ -554,6 +554,12 @@ paths: responses: '200': description: OK + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/macro' operationId: get-api-v1-macros description: Receive a list with all available macros. post: diff --git a/emgauwa-core/src/handlers/v1/macros.rs b/emgauwa-core/src/handlers/v1/macros.rs new file mode 100644 index 0000000..d4ab7eb --- /dev/null +++ b/emgauwa-core/src/handlers/v1/macros.rs @@ -0,0 +1,161 @@ +use actix::Addr; +use actix_web::{delete, get, post, put, web, HttpResponse}; +use emgauwa_lib::db::DbMacro; +use emgauwa_lib::errors::{DatabaseError, EmgauwaError}; +use emgauwa_lib::models::{convert_db_list, FromDbModel, Macro, MacroAction, Relay}; +use emgauwa_lib::types::{ + ControllerWsAction, EmgauwaUid, RequestMacroCreate, RequestMacroExecute, RequestMacroUpdate, +}; +use itertools::Itertools; +use sqlx::{Pool, Sqlite}; + +use crate::app_state; +use crate::app_state::AppState; + +#[get("/macros")] +pub async fn index(pool: web::Data>) -> Result { + let mut pool_conn = pool.acquire().await?; + + let db_macros = DbMacro::get_all(&mut pool_conn).await?; + let macros: Vec = convert_db_list(&mut pool_conn, db_macros)?; + + Ok(HttpResponse::Ok().json(macros)) +} + +#[get("/macros/{macro_id}")] +pub async fn show( + pool: web::Data>, + path: web::Path<(String,)>, +) -> Result { + let mut pool_conn = pool.acquire().await?; + + let (macro_uid,) = path.into_inner(); + let uid = EmgauwaUid::try_from(macro_uid.as_str())?; + + let db_macro = DbMacro::get_by_uid(&mut pool_conn, &uid) + .await? + .ok_or(DatabaseError::NotFound)?; + + let return_macro = Macro::from_db_model(&mut pool_conn, db_macro)?; + Ok(HttpResponse::Ok().json(return_macro)) +} + +#[post("/macros")] +pub async fn add( + pool: web::Data>, + data: web::Json, +) -> Result { + let mut pool_conn = pool.acquire().await?; + + let new_macro = DbMacro::create(&mut pool_conn, EmgauwaUid::default(), &data.name).await?; + + new_macro + .set_actions(&mut pool_conn, data.actions.as_slice()) + .await?; + + let return_macro = Macro::from_db_model(&mut pool_conn, new_macro)?; + Ok(HttpResponse::Created().json(return_macro)) +} + +#[put("/macros/{macro_id}")] +pub async fn update( + pool: web::Data>, + path: web::Path<(String,)>, + data: web::Json, +) -> Result { + let mut pool_conn = pool.acquire().await?; + + let (macro_uid,) = path.into_inner(); + let uid = EmgauwaUid::try_from(macro_uid.as_str())?; + + let db_macro = DbMacro::get_by_uid(&mut pool_conn, &uid) + .await? + .ok_or(DatabaseError::NotFound)?; + + if let Some(name) = &data.name { + db_macro.update(&mut pool_conn, name).await?; + } + + if let Some(actions) = &data.actions { + db_macro + .set_actions(&mut pool_conn, actions.as_slice()) + .await?; + } + + let return_macro = Macro::from_db_model(&mut pool_conn, db_macro)?; + Ok(HttpResponse::Ok().json(return_macro)) +} + +#[delete("/macros/{macro_id}")] +pub async fn delete( + pool: web::Data>, + path: web::Path<(String,)>, +) -> Result { + let mut pool_conn = pool.acquire().await?; + + let (macro_uid,) = path.into_inner(); + let uid = EmgauwaUid::try_from(macro_uid.as_str())?; + + DbMacro::delete_by_uid(&mut pool_conn, uid).await?; + Ok(HttpResponse::Ok().json("macro got deleted")) +} + +#[put("/macros/{macro_id}/execute")] +pub async fn execute( + pool: web::Data>, + app_state: web::Data>, + path: web::Path<(String,)>, + query: web::Query, +) -> Result { + let mut pool_conn = pool.acquire().await?; + + let (macro_uid,) = path.into_inner(); + let uid = EmgauwaUid::try_from(macro_uid.as_str())?; + + let db_macro = DbMacro::get_by_uid(&mut pool_conn, &uid) + .await? + .ok_or(DatabaseError::NotFound)?; + + let actions_db = match query.weekday { + None => db_macro.get_actions(&mut pool_conn).await?, + Some(weekday) => { + db_macro + .get_actions_weekday(&mut pool_conn, weekday) + .await? + } + }; + let mut actions: Vec = convert_db_list(&mut pool_conn, actions_db)?; + + for action in &actions { + action.execute(&mut pool_conn).await?; + } + + let affected_controller_uids: Vec = actions + .iter() + .map(|action| action.relay.controller_id.clone()) + .unique() + .collect(); + + for controller_uid in affected_controller_uids { + let mut affected_relays: Vec = Vec::new(); + let mut affected_relay_ids: Vec = Vec::new(); + + for action in actions.iter_mut() { + if affected_relay_ids.contains(&action.relay.r.id) { + continue; + } + action.relay.reload(&mut pool_conn)?; + affected_relays.push(action.relay.clone()); + affected_relay_ids.push(action.relay.r.id); + } + + app_state + .send(app_state::Action { + controller_uid, + action: ControllerWsAction::Relays(affected_relays.clone()), + }) + .await??; + } + + Ok(HttpResponse::Ok().finish()) // TODO add a message? +} diff --git a/emgauwa-core/src/handlers/v1/mod.rs b/emgauwa-core/src/handlers/v1/mod.rs index dca0eae..9ce232c 100644 --- a/emgauwa-core/src/handlers/v1/mod.rs +++ b/emgauwa-core/src/handlers/v1/mod.rs @@ -1,4 +1,5 @@ pub mod controllers; +pub mod macros; pub mod relays; pub mod schedules; pub mod tags; diff --git a/emgauwa-core/src/main.rs b/emgauwa-core/src/main.rs index cc1bf87..f4e654f 100644 --- a/emgauwa-core/src/main.rs +++ b/emgauwa-core/src/main.rs @@ -108,6 +108,12 @@ async fn main() -> Result<(), std::io::Error> { .service(handlers::v1::tags::show) .service(handlers::v1::tags::delete) .service(handlers::v1::tags::add) + .service(handlers::v1::macros::index) + .service(handlers::v1::macros::show) + .service(handlers::v1::macros::add) + .service(handlers::v1::macros::update) + .service(handlers::v1::macros::delete) + .service(handlers::v1::macros::execute) .service(handlers::v1::ws::ws_controllers) .service(handlers::v1::ws::ws_relays), ) diff --git a/emgauwa-lib/src/db/macro.rs b/emgauwa-lib/src/db/macro.rs new file mode 100644 index 0000000..1ced624 --- /dev/null +++ b/emgauwa-lib/src/db/macro.rs @@ -0,0 +1,166 @@ +use std::ops::DerefMut; + +use serde_derive::{Deserialize, Serialize}; +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; + +use crate::db::{DbController, DbMacroAction, DbRelay, DbSchedule}; +use crate::errors::DatabaseError; +use crate::types::{EmgauwaUid, RequestMacroAction}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DbMacro { + #[serde(skip)] + pub id: i64, + #[serde(rename = "id")] + pub uid: EmgauwaUid, + pub name: String, +} + + +impl DbMacro { + pub async fn get_all(conn: &mut PoolConnection) -> Result, DatabaseError> { + sqlx::query_as!(DbMacro, "SELECT * FROM macros") + .fetch_all(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn get( + conn: &mut PoolConnection, + id: i64, + ) -> Result, DatabaseError> { + sqlx::query_as!(DbMacro, "SELECT * FROM macros WHERE id = ?", id) + .fetch_optional(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn get_by_uid( + conn: &mut PoolConnection, + filter_uid: &EmgauwaUid, + ) -> Result, DatabaseError> { + sqlx::query_as!(DbMacro, "SELECT * FROM macros WHERE uid = ?", filter_uid) + .fetch_optional(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn create( + conn: &mut PoolConnection, + new_uid: EmgauwaUid, + new_name: &str, + ) -> Result { + sqlx::query_as!( + DbMacro, + "INSERT INTO macros (uid, name) VALUES (?, ?) RETURNING *", + new_uid, + new_name + ) + .fetch_optional(conn.deref_mut()) + .await? + .ok_or(DatabaseError::InsertGetError) + } + + pub async fn delete(&self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { + sqlx::query!("DELETE FROM macros WHERE id = ?", self.id) + .execute(conn.deref_mut()) + .await + .map(|res| match res.rows_affected() { + 0 => Err(DatabaseError::DeleteError), + _ => Ok(()), + })? + } + + pub async fn delete_by_uid( + conn: &mut PoolConnection, + filter_uid: EmgauwaUid, + ) -> Result<(), DatabaseError> { + if sqlx::query_scalar!("SELECT 1 FROM macros WHERE uid = ?", filter_uid) + .fetch_optional(conn.deref_mut()) + .await? + .is_none() + { + return Err(DatabaseError::NotFound); + } + + sqlx::query!("DELETE FROM macros WHERE uid = ?", filter_uid) + .execute(conn.deref_mut()) + .await + .map(|res| match res.rows_affected() { + 0 => Err(DatabaseError::DeleteError), + _ => Ok(()), + })? + } + + pub async fn update( + &self, + conn: &mut PoolConnection, + new_name: &str, + ) -> Result { + sqlx::query!("UPDATE relays SET name = ? WHERE id = ?", new_name, self.id,) + .execute(conn.deref_mut()) + .await?; + + DbMacro::get(conn, self.id) + .await? + .ok_or(DatabaseError::UpdateGetError) + } + + pub async fn set_actions( + &self, + conn: &mut PoolConnection, + new_actions: &[RequestMacroAction], + ) -> Result<(), DatabaseError> { + sqlx::query!("DELETE FROM macro_actions WHERE macro_id = ?", self.id) + .execute(conn.deref_mut()) + .await?; + + for new_action in new_actions { + let controller = DbController::get_by_uid(conn, &new_action.relay.controller_id) + .await? + .ok_or(DatabaseError::NotFound)?; + let relay = + DbRelay::get_by_controller_and_num(conn, &controller, new_action.relay.number) + .await? + .ok_or(DatabaseError::NotFound)?; + + let schedule = DbSchedule::get_by_uid(conn, &new_action.schedule.id) + .await? + .ok_or(DatabaseError::NotFound)?; + + DbMacroAction::create(conn, self, &relay, &schedule, new_action.weekday).await?; + } + Ok(()) + } + + pub async fn get_actions( + &self, + conn: &mut PoolConnection, + ) -> Result, DatabaseError> { + sqlx::query_as!( + DbMacroAction, + "SELECT * FROM macro_actions WHERE macro_id = ?", + self.id + ) + .fetch_all(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn get_actions_weekday( + &self, + conn: &mut PoolConnection, + weekday: i64, + ) -> Result, DatabaseError> { + sqlx::query_as!( + DbMacroAction, + "SELECT * FROM macro_actions WHERE macro_id = ? AND weekday = ?", + self.id, + weekday + ) + .fetch_all(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } +} diff --git a/emgauwa-lib/src/db/macro_action.rs b/emgauwa-lib/src/db/macro_action.rs new file mode 100644 index 0000000..4a88c39 --- /dev/null +++ b/emgauwa-lib/src/db/macro_action.rs @@ -0,0 +1,99 @@ +use std::ops::DerefMut; + +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; + +use crate::db::{DbMacro, DbRelay, DbSchedule}; +use crate::errors::DatabaseError; + +#[derive(Debug, Clone)] +pub struct DbMacroAction { + pub id: i64, + pub macro_id: i64, + pub relay_id: i64, + pub schedule_id: i64, + pub weekday: i64, // should be u8, but sqlite will store it as i64 +} + + +impl DbMacroAction { + pub async fn get_all( + conn: &mut PoolConnection, + ) -> Result, DatabaseError> { + sqlx::query_as!(DbMacroAction, "SELECT * FROM macro_actions") + .fetch_all(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn get( + conn: &mut PoolConnection, + id: i64, + ) -> Result, DatabaseError> { + sqlx::query_as!( + DbMacroAction, + "SELECT * FROM macro_actions WHERE id = ?", + id + ) + .fetch_optional(conn.deref_mut()) + .await + .map_err(DatabaseError::from) + } + + pub async fn create( + conn: &mut PoolConnection, + new_macro: &DbMacro, + new_relay: &DbRelay, + new_schedule: &DbSchedule, + new_weekday: i64, + ) -> Result { + sqlx::query_as!( + DbMacroAction, + "INSERT INTO macro_actions (macro_id, relay_id, schedule_id, weekday) VALUES (?, ?, ?, ?) RETURNING *", + new_macro.id, + new_relay.id, + new_schedule.id, + new_weekday + ) + .fetch_optional(conn.deref_mut()) + .await? + .ok_or(DatabaseError::InsertGetError) + } + + pub async fn delete(&self, conn: &mut PoolConnection) -> Result<(), DatabaseError> { + sqlx::query!("DELETE FROM macro_actions WHERE id = ?", self.id) + .execute(conn.deref_mut()) + .await + .map(|res| match res.rows_affected() { + 0 => Err(DatabaseError::DeleteError), + _ => Ok(()), + })? + } + + pub async fn get_relay( + &self, + conn: &mut PoolConnection, + ) -> Result { + DbRelay::get(conn, self.relay_id) + .await? + .ok_or(DatabaseError::NotFound) + } + + pub async fn get_schedule( + &self, + conn: &mut PoolConnection, + ) -> Result { + DbSchedule::get(conn, self.schedule_id) + .await? + .ok_or(DatabaseError::NotFound) + } + + pub async fn get_macro( + &self, + conn: &mut PoolConnection, + ) -> Result { + DbMacro::get(conn, self.macro_id) + .await? + .ok_or(DatabaseError::NotFound) + } +} diff --git a/emgauwa-lib/src/db/mod.rs b/emgauwa-lib/src/db/mod.rs index eeefd57..c4f74b6 100644 --- a/emgauwa-lib/src/db/mod.rs +++ b/emgauwa-lib/src/db/mod.rs @@ -7,6 +7,8 @@ use sqlx::{ConnectOptions, Pool, Sqlite}; mod controllers; mod junction_relay_schedule; mod junction_tag; +mod r#macro; +mod macro_action; mod model_utils; mod relays; mod schedules; @@ -15,6 +17,8 @@ mod tag; pub use controllers::DbController; pub use junction_relay_schedule::DbJunctionRelaySchedule; pub use junction_tag::DbJunctionTag; +pub use macro_action::DbMacroAction; +pub use r#macro::DbMacro; pub use relays::DbRelay; pub use schedules::{DbPeriods, DbSchedule}; pub use tag::DbTag; diff --git a/emgauwa-lib/src/models/macro.rs b/emgauwa-lib/src/models/macro.rs new file mode 100644 index 0000000..fbe9dbb --- /dev/null +++ b/emgauwa-lib/src/models/macro.rs @@ -0,0 +1,42 @@ +use futures::executor::block_on; +use serde_derive::{Deserialize, Serialize}; +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; + +use crate::db::DbMacro; +use crate::errors::DatabaseError; +use crate::models::{convert_db_list, FromDbModel, MacroAction}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct Macro { + #[serde(flatten)] + pub m: DbMacro, + pub actions: Vec, +} + + +impl FromDbModel for Macro { + type DbModel = DbMacro; + type DbModelCache = (); + + fn from_db_model( + conn: &mut PoolConnection, + db_model: Self::DbModel, + ) -> Result { + Self::from_db_model_cache(conn, db_model, ()) + } + + fn from_db_model_cache( + conn: &mut PoolConnection, + db_model: Self::DbModel, + _cache: Self::DbModelCache, + ) -> Result { + let actions_db = block_on(db_model.get_actions(conn))?; + let actions: Vec = convert_db_list(conn, actions_db)?; + + Ok(Macro { + m: db_model, + actions, + }) + } +} diff --git a/emgauwa-lib/src/models/macro_action.rs b/emgauwa-lib/src/models/macro_action.rs new file mode 100644 index 0000000..d7b5aca --- /dev/null +++ b/emgauwa-lib/src/models/macro_action.rs @@ -0,0 +1,56 @@ +use futures::executor::block_on; +use serde_derive::{Deserialize, Serialize}; +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; + +use crate::db::{DbJunctionRelaySchedule, DbMacroAction}; +use crate::errors::{DatabaseError, EmgauwaError}; +use crate::models::{FromDbModel, Relay, Schedule}; + +#[derive(Serialize, Deserialize, Debug, Clone)] +pub struct MacroAction { + pub schedule: Schedule, + pub relay: Relay, + pub weekday: i64, +} + + +impl FromDbModel for MacroAction { + type DbModel = DbMacroAction; + type DbModelCache = (); + + fn from_db_model( + conn: &mut PoolConnection, + db_model: Self::DbModel, + ) -> Result { + Self::from_db_model_cache(conn, db_model, ()) + } + + fn from_db_model_cache( + conn: &mut PoolConnection, + db_model: Self::DbModel, + _cache: Self::DbModelCache, + ) -> Result { + 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)?; + + let weekday = db_model.weekday; + + Ok(MacroAction { + schedule, + relay, + weekday, + }) + } +} + +impl MacroAction { + pub async fn execute(&self, conn: &mut PoolConnection) -> Result<(), EmgauwaError> { + DbJunctionRelaySchedule::set_schedule(conn, &self.relay.r, &self.schedule.s, self.weekday) + .await?; + Ok(()) + } +} diff --git a/emgauwa-lib/src/models/mod.rs b/emgauwa-lib/src/models/mod.rs index 136de53..570bf48 100644 --- a/emgauwa-lib/src/models/mod.rs +++ b/emgauwa-lib/src/models/mod.rs @@ -1,9 +1,13 @@ mod controller; +mod r#macro; +mod macro_action; mod relay; mod schedule; mod tag; pub use controller::Controller; +pub use macro_action::MacroAction; +pub use r#macro::Macro; pub use relay::Relay; pub use schedule::Schedule; use sqlx::pool::PoolConnection; diff --git a/emgauwa-lib/src/types/request.rs b/emgauwa-lib/src/types/request.rs index e1cfced..5c9a927 100644 --- a/emgauwa-lib/src/types/request.rs +++ b/emgauwa-lib/src/types/request.rs @@ -4,7 +4,7 @@ use sqlx::Sqlite; use crate::db::{DbPeriods, DbSchedule}; use crate::errors::DatabaseError; -use crate::types::ScheduleUid; +use crate::types::{EmgauwaUid, ScheduleUid}; #[derive(Debug, Serialize, Deserialize)] pub struct RequestScheduleCreate { @@ -48,6 +48,41 @@ pub struct RequestTagCreate { pub tag: String, } +#[derive(Debug, Serialize, Deserialize)] +pub struct RequestMacroActionRelay { + pub number: i64, + pub controller_id: EmgauwaUid, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct RequestMacroActionSchedule { + pub id: ScheduleUid, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct RequestMacroAction { + pub weekday: i64, + pub relay: RequestMacroActionRelay, + pub schedule: RequestMacroActionSchedule, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct RequestMacroCreate { + pub name: String, + pub actions: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +pub struct RequestMacroUpdate { + pub name: Option, + pub actions: Option>, +} + +#[derive(Debug, Deserialize)] +pub struct RequestMacroExecute { + pub weekday: Option, +} + impl RequestScheduleId { pub async fn get_schedule( &self, diff --git a/migrations/20231120000000_init.up.sql b/migrations/20231120000000_init.up.sql index 1e5f205..6c588eb 100644 --- a/migrations/20231120000000_init.up.sql +++ b/migrations/20231120000000_init.up.sql @@ -125,7 +125,7 @@ CREATE TABLE macros AUTOINCREMENT NOT NULL, uid - VARCHAR(36) + BLOB NOT NULL UNIQUE, name