Add self-creation for controller
This commit is contained in:
parent
d193000aec
commit
4e3df272c3
10 changed files with 104 additions and 14 deletions
BIN
Cargo.lock
generated
BIN
Cargo.lock
generated
Binary file not shown.
|
@ -1,4 +1,5 @@
|
||||||
database = "sqlite://emgauwa-controller.sqlite"
|
database = "sqlite://emgauwa-controller.sqlite"
|
||||||
|
name = "Emgauwa Controller"
|
||||||
|
|
||||||
[core]
|
[core]
|
||||||
port = 4419
|
port = 4419
|
||||||
|
@ -7,3 +8,8 @@ host = "127.0.0.1"
|
||||||
[logging]
|
[logging]
|
||||||
level = "DEBUG"
|
level = "DEBUG"
|
||||||
file = "stdout"
|
file = "stdout"
|
||||||
|
|
||||||
|
[[relays]]
|
||||||
|
driver = "gpio"
|
||||||
|
pin = 5
|
||||||
|
inverted = 1
|
||||||
|
|
|
@ -20,4 +20,6 @@ serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
|
|
||||||
|
sqlx = { version = "0.7", features = ["sqlite", "runtime-async-std", "macros", "chrono"] }
|
||||||
|
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
|
|
18
emgauwa-controller/src/driver.rs
Normal file
18
emgauwa-controller/src/driver.rs
Normal file
|
@ -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<D>(deserializer: D) -> Result<Self, D::Error> 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")),
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,19 +1,50 @@
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
use futures::{future, pin_mut, StreamExt};
|
use futures::{future, pin_mut, SinkExt, StreamExt};
|
||||||
use futures::channel::mpsc;
|
use futures::channel::mpsc;
|
||||||
|
use sqlx::pool::PoolConnection;
|
||||||
|
use sqlx::Sqlite;
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
|
use tokio_tungstenite::{connect_async, tungstenite::protocol::Message};
|
||||||
use tokio_tungstenite::tungstenite::Error;
|
use tokio_tungstenite::tungstenite::Error;
|
||||||
use emgauwa_lib::db;
|
use emgauwa_lib::db;
|
||||||
|
use emgauwa_lib::db::Controller;
|
||||||
|
use emgauwa_lib::db::types::ControllerUid;
|
||||||
|
use crate::settings::Settings;
|
||||||
|
|
||||||
mod settings;
|
mod settings;
|
||||||
|
mod driver;
|
||||||
|
|
||||||
|
fn create_this_controller(conn: &mut PoolConnection<Sqlite>, 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]
|
#[tokio::main]
|
||||||
async fn main() {
|
async fn main() {
|
||||||
let settings = settings::init();
|
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!(
|
let url = format!(
|
||||||
"ws://{}:{}/api/v1/ws/controllers",
|
"ws://{}:{}/api/v1/ws/controllers",
|
||||||
|
@ -26,13 +57,14 @@ async fn main() {
|
||||||
|
|
||||||
let (ws_stream, _) = connect_async(url).await.expect("Failed to connect");
|
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);
|
let ws_to_stdout = read.for_each(handle_message);
|
||||||
|
|
||||||
pin_mut!(stdin_to_ws, ws_to_stdout);
|
ws_to_stdout.await;
|
||||||
future::select(stdin_to_ws, 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
|
// Our helper method which will read data from stdin and send it along the
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use emgauwa_lib::{constants, utils};
|
use emgauwa_lib::{constants, utils};
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
|
use crate::driver::Driver;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Deserialize)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
|
@ -17,6 +18,15 @@ pub struct Logging {
|
||||||
pub file: String,
|
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)]
|
#[derive(Clone, Debug, Deserialize)]
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
|
@ -24,6 +34,8 @@ pub struct Settings {
|
||||||
pub core: Core,
|
pub core: Core,
|
||||||
pub database: String,
|
pub database: String,
|
||||||
pub logging: Logging,
|
pub logging: Logging,
|
||||||
|
pub name: String,
|
||||||
|
pub relays: Vec<Relay>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
|
@ -32,6 +44,18 @@ impl Default for Settings {
|
||||||
core: Core::default(),
|
core: Core::default(),
|
||||||
database: String::from("sqlite://emgauwa-controller.sqlite"),
|
database: String::from("sqlite://emgauwa-controller.sqlite"),
|
||||||
logging: Logging::default(),
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,16 @@ use crate::db::errors::DatabaseError;
|
||||||
use crate::db::model_utils::Period;
|
use crate::db::model_utils::Period;
|
||||||
use crate::db::types::ScheduleUid;
|
use crate::db::types::ScheduleUid;
|
||||||
|
|
||||||
// export for easier/flatter access
|
|
||||||
pub use crate::db::schedules::{Periods, Schedule};
|
|
||||||
|
|
||||||
pub mod errors;
|
pub mod errors;
|
||||||
mod model_utils;
|
mod model_utils;
|
||||||
mod models;
|
mod models;
|
||||||
pub mod schedules;
|
mod schedules;
|
||||||
pub mod tag;
|
pub mod tag;
|
||||||
pub mod types;
|
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"
|
static MIGRATOR: Migrator = sqlx::migrate!("../migrations"); // defaults to "./migrations"
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,12 @@ use uuid::Uuid;
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct ControllerUid(Uuid);
|
pub struct ControllerUid(Uuid);
|
||||||
|
|
||||||
|
impl ControllerUid {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self(Uuid::new_v4())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Serialize for ControllerUid {
|
impl Serialize for ControllerUid {
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||||
where
|
where
|
||||||
|
|
|
@ -25,10 +25,12 @@ impl StreamHandler<Result<Message, ProtocolError>> for ControllerWs {
|
||||||
fn handle(&mut self, msg: Result<Message, ProtocolError>, ctx: &mut Self::Context) {
|
fn handle(&mut self, msg: Result<Message, ProtocolError>, ctx: &mut Self::Context) {
|
||||||
let schedules = futures::executor::block_on(get_schedules(&mut self.pool)).unwrap();
|
let schedules = futures::executor::block_on(get_schedules(&mut self.pool)).unwrap();
|
||||||
let schedules_json = serde_json::to_string(&schedules).unwrap();
|
let schedules_json = serde_json::to_string(&schedules).unwrap();
|
||||||
println!("{:?}", msg);
|
|
||||||
match msg {
|
match msg {
|
||||||
Ok(Message::Ping(msg)) => ctx.pong(&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)
|
||||||
|
},
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::db::schedules::Schedule;
|
use crate::db::Schedule;
|
||||||
use futures::executor;
|
use futures::executor;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use sqlx::pool::PoolConnection;
|
use sqlx::pool::PoolConnection;
|
||||||
|
|
Loading…
Reference in a new issue