Add self-creation for controller
This commit is contained in:
		
							parent
							
								
									d193000aec
								
							
						
					
					
						commit
						4e3df272c3
					
				
					 10 changed files with 105 additions and 14 deletions
				
			
		
							
								
								
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								Cargo.lock
									
										
									
										generated
									
									
									
								
							| 
						 | 
				
			
			@ -867,6 +867,7 @@ dependencies = [
 | 
			
		|||
 "serde_derive",
 | 
			
		||||
 "serde_json",
 | 
			
		||||
 "simple_logger",
 | 
			
		||||
 "sqlx",
 | 
			
		||||
 "tokio",
 | 
			
		||||
 "tokio-tungstenite",
 | 
			
		||||
 "uuid",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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 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<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]
 | 
			
		||||
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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<Relay>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
 | 
			
		||||
        where
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,10 +25,12 @@ impl StreamHandler<Result<Message, ProtocolError>> for ControllerWs {
 | 
			
		|||
	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_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)
 | 
			
		||||
			},
 | 
			
		||||
			_ => {}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,4 +1,4 @@
 | 
			
		|||
use crate::db::schedules::Schedule;
 | 
			
		||||
use crate::db::Schedule;
 | 
			
		||||
use futures::executor;
 | 
			
		||||
use serde::Serialize;
 | 
			
		||||
use sqlx::pool::PoolConnection;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue