diff --git a/Cargo.lock b/Cargo.lock index debef3f..82ca689 100644 Binary files a/Cargo.lock and b/Cargo.lock differ diff --git a/emgauwa-controller.toml b/emgauwa-controller.toml index ee4d72d..eca558f 100644 --- a/emgauwa-controller.toml +++ b/emgauwa-controller.toml @@ -1,4 +1,5 @@ database = "sqlite://emgauwa-controller.sqlite" +name = "Emgauwa Controller" [core] port = 4419 @@ -7,3 +8,8 @@ host = "127.0.0.1" [logging] level = "DEBUG" file = "stdout" + +[[relays]] +driver = "gpio" +pin = 5 +inverted = 1 diff --git a/emgauwa-controller/Cargo.toml b/emgauwa-controller/Cargo.toml index b008756..c90a692 100644 --- a/emgauwa-controller/Cargo.toml +++ b/emgauwa-controller/Cargo.toml @@ -20,4 +20,6 @@ serde = "1.0" serde_json = "1.0" serde_derive = "1.0" +sqlx = { version = "0.7", features = ["sqlite", "runtime-async-std", "macros", "chrono"] } + futures = "0.3" diff --git a/emgauwa-controller/src/driver.rs b/emgauwa-controller/src/driver.rs new file mode 100644 index 0000000..4a7350c --- /dev/null +++ b/emgauwa-controller/src/driver.rs @@ -0,0 +1,18 @@ +use serde::{Deserialize, Deserializer}; + +#[derive(Debug, Clone, Copy)] +pub enum Driver { + Gpio, + Piface, +} + +impl<'de> Deserialize<'de> for Driver { + fn deserialize(deserializer: D) -> Result where D: Deserializer<'de> { + match String::deserialize(deserializer)?.as_str() { + "gpio" => Ok(Driver::Gpio), + "piface" => Ok(Driver::Piface), + _ => Err(serde::de::Error::custom("invalid driver")), + } + + } +} \ No newline at end of file diff --git a/emgauwa-controller/src/main.rs b/emgauwa-controller/src/main.rs index ca61306..c9327dd 100644 --- a/emgauwa-controller/src/main.rs +++ b/emgauwa-controller/src/main.rs @@ -1,19 +1,50 @@ use std::str; -use futures::{future, pin_mut, StreamExt}; +use futures::{future, pin_mut, SinkExt, StreamExt}; use futures::channel::mpsc; +use sqlx::pool::PoolConnection; +use sqlx::Sqlite; use tokio::io::AsyncReadExt; use tokio_tungstenite::{connect_async, tungstenite::protocol::Message}; use tokio_tungstenite::tungstenite::Error; use emgauwa_lib::db; +use emgauwa_lib::db::Controller; +use emgauwa_lib::db::types::ControllerUid; +use crate::settings::Settings; mod settings; +mod driver; + +fn create_this_controller(conn: &mut PoolConnection, settings: &Settings) -> Controller { + futures::executor::block_on(async { + Controller::create( + conn, + &ControllerUid::new(), + &settings.name, + i64::try_from(settings.relays.len()).expect("Too many relays"), + true + ).await.expect("Failed to create controller") + }) +} #[tokio::main] async fn main() { let settings = settings::init(); - let _pool = db::init(&settings.database).await; + let pool = db::init(&settings.database).await; + + let mut conn = pool.acquire().await.unwrap(); + + let this = Controller::get_all(&mut conn) + .await + .expect("Failed to get controller from database") + .pop() + .unwrap_or_else(|| create_this_controller(&mut conn, &settings)); + + let this_json = serde_json::to_string(&this).unwrap(); + + println!("{:?}", this); + println!("{:?}", this_json); let url = format!( "ws://{}:{}/api/v1/ws/controllers", @@ -26,13 +57,14 @@ async fn main() { let (ws_stream, _) = connect_async(url).await.expect("Failed to connect"); - let (write, read) = ws_stream.split(); + let (mut write, read) = ws_stream.split(); - let stdin_to_ws = stdin_rx.map(Ok).forward(write); + write.send(Message::text(this_json)).await.unwrap(); let ws_to_stdout = read.for_each(handle_message); - pin_mut!(stdin_to_ws, ws_to_stdout); - future::select(stdin_to_ws, ws_to_stdout).await; + ws_to_stdout.await; + //pin_mut!(stdin_to_ws, ws_to_stdout); + //future::select(stdin_to_ws, ws_to_stdout).await; } // Our helper method which will read data from stdin and send it along the diff --git a/emgauwa-controller/src/settings.rs b/emgauwa-controller/src/settings.rs index 5faa53f..111debf 100644 --- a/emgauwa-controller/src/settings.rs +++ b/emgauwa-controller/src/settings.rs @@ -1,5 +1,6 @@ use emgauwa_lib::{constants, utils}; use serde_derive::Deserialize; +use crate::driver::Driver; #[derive(Clone, Debug, Deserialize)] #[serde(default)] @@ -17,6 +18,15 @@ pub struct Logging { pub file: String, } +#[derive(Clone, Debug, Deserialize)] +#[serde(default)] +#[allow(unused)] +pub struct Relay { + pub driver: Driver, + pub pin: u8, + pub inverted: bool, +} + #[derive(Clone, Debug, Deserialize)] #[serde(default)] #[allow(unused)] @@ -24,6 +34,8 @@ pub struct Settings { pub core: Core, pub database: String, pub logging: Logging, + pub name: String, + pub relays: Vec, } impl Default for Settings { @@ -32,6 +44,18 @@ impl Default for Settings { core: Core::default(), database: String::from("sqlite://emgauwa-controller.sqlite"), logging: Logging::default(), + name: String::from("Emgauwa Controller"), + relays: Vec::new(), + } + } +} + +impl Default for Relay { + fn default() -> Self { + Relay { + driver: Driver::Gpio, + pin: 0, + inverted: false, } } } diff --git a/emgauwa-lib/src/db/mod.rs b/emgauwa-lib/src/db/mod.rs index 0b31050..054efa7 100644 --- a/emgauwa-lib/src/db/mod.rs +++ b/emgauwa-lib/src/db/mod.rs @@ -8,16 +8,16 @@ use crate::db::errors::DatabaseError; use crate::db::model_utils::Period; use crate::db::types::ScheduleUid; -// export for easier/flatter access -pub use crate::db::schedules::{Periods, Schedule}; - pub mod errors; mod model_utils; mod models; -pub mod schedules; +mod schedules; pub mod tag; pub mod types; -pub mod controllers; +mod controllers; + +pub use controllers::Controller; +pub use schedules::{Periods, Schedule}; static MIGRATOR: Migrator = sqlx::migrate!("../migrations"); // defaults to "./migrations" diff --git a/emgauwa-lib/src/db/types/controller_uid.rs b/emgauwa-lib/src/db/types/controller_uid.rs index 63817f1..91e4a0d 100644 --- a/emgauwa-lib/src/db/types/controller_uid.rs +++ b/emgauwa-lib/src/db/types/controller_uid.rs @@ -9,6 +9,12 @@ use uuid::Uuid; #[derive(Clone, Debug)] pub struct ControllerUid(Uuid); +impl ControllerUid { + pub fn new() -> Self { + Self(Uuid::new_v4()) + } +} + impl Serialize for ControllerUid { fn serialize(&self, serializer: S) -> Result where diff --git a/emgauwa-lib/src/handlers/v1/ws/controllers.rs b/emgauwa-lib/src/handlers/v1/ws/controllers.rs index fea347e..9b3f6e1 100644 --- a/emgauwa-lib/src/handlers/v1/ws/controllers.rs +++ b/emgauwa-lib/src/handlers/v1/ws/controllers.rs @@ -25,10 +25,12 @@ impl StreamHandler> for ControllerWs { fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { let schedules = futures::executor::block_on(get_schedules(&mut self.pool)).unwrap(); let schedules_json = serde_json::to_string(&schedules).unwrap(); - println!("{:?}", msg); match msg { Ok(Message::Ping(msg)) => ctx.pong(&msg), - Ok(Message::Text(_text)) => ctx.text(schedules_json), + Ok(Message::Text(text)) => { + println!("Got text: {}", text.to_string()); + ctx.text(schedules_json) + }, _ => {} } } diff --git a/emgauwa-lib/src/return_models.rs b/emgauwa-lib/src/return_models.rs index 2a56fe8..aed0ae1 100644 --- a/emgauwa-lib/src/return_models.rs +++ b/emgauwa-lib/src/return_models.rs @@ -1,4 +1,4 @@ -use crate::db::schedules::Schedule; +use crate::db::Schedule; use futures::executor; use serde::Serialize; use sqlx::pool::PoolConnection;