#[macro_use] extern crate rocket; //use std::{thread, time::Duration, sync::Arc, io}; use ::std::sync::Arc; mod animations; mod configure; mod render; mod utils; mod db; use animations::Animation; use r2d2::PooledConnection; use utils::{ApiResponse, ApiResponseActiveList}; use rocket::{serde::json::{serde_json::json, self}, State}; use r2d2_sqlite::SqliteConnectionManager; use crate::db::setup_database; //use std::sync::atomic::AtomicBool; use std::{ error::Error, sync::{ mpsc::{self, Receiver, Sender}, Mutex, }, }; pub type DBPool = Arc>; pub type DBConn = PooledConnection; pub type GResult = Result<(), Box>; pub type ASender = Arc>>; pub type AReceiver = Arc>>; #[get("/")] fn index() -> &'static str { "Hello World" } pub enum Action { Reload, Stop, Clear, GetActiveList, } pub enum RenderMessage { ActiveList(Vec), // TODO remove none where other are added None } #[get("/quit")] async fn quit(shutdown: rocket::Shutdown, action: &State>) -> String { println!("Got Shutdown"); let send = action.lock().unwrap().send(Action::Stop); if send.is_err() || send.ok().is_none() { return json!(ApiResponse { code: 500, message: "Failed to stop".to_string() }) .to_string(); } shutdown.notify(); json!(ApiResponse { code: 200, message: "Stoped".to_string() }) .to_string() } #[get("/reload")] async fn reload(action: &State>) -> String { println!("Got Shutdown"); let send = action.lock().unwrap().send(Action::Reload); if send.is_err() || send.ok().is_none() { return json!(ApiResponse { code: 500, message: "Failed to reload".to_string() }) .to_string(); } json!(ApiResponse { code: 200, message: "Reloaded".to_string() }) .to_string() } #[get("/active")] async fn get_active(action: &State>, messages: &State>) -> String { println!("Getting active"); let send = action.lock().unwrap().send(Action::GetActiveList); if send.is_err() || send.ok().is_none() { return json!(ApiResponse{ code: 500, message: "Failed to get list".to_string() }).to_string(); } let data = messages.lock().unwrap().recv(); if data.is_err() || data.as_ref().ok().is_none() { return json!(ApiResponse { code: 500, message: "Failed to get list".to_string() }).to_string(); } if let RenderMessage::ActiveList(list) = data.ok().unwrap() { return json!(ApiResponseActiveList { code: 200, active_animations: list }).to_string(); } return json!(ApiResponse { code: 500, message: "Failed to get list".to_string() }).to_string(); } fn ligth_controll( pool: DBPool, action: Receiver, start_ani: Receiver, stop_ani: Receiver, message_server: Sender, ) { println!("Data loop started"); let render = render::Render::new(pool.clone()); if render.is_err() || render.as_ref().ok().is_none() { println!("something every wrong {:?}", render.err()); return; } let mut render = render.ok().unwrap(); 'mainloop: loop { let action = action.try_recv(); if action.is_ok() { match action.ok().unwrap() { Action::Reload => { let result = render.load_config(); if result.is_err() || result.as_ref().ok().is_none() { println!("Ehh failed to load config i guess: {:?}", result.err()); } } Action::Clear => { render.blank(); } Action::Stop => { render.blank(); render.im_render(); break 'mainloop; } Action::GetActiveList => { if message_server.send(RenderMessage::ActiveList(render.get_active_animations())).is_err() { println!("Failed to send message ups"); } } } } let ani = start_ani.try_recv(); if ani.is_ok() { println!("Added animation"); //TODO render.add_animation(ani.ok().unwrap()); //ani.ok().unwrap(). } let ani = stop_ani.try_recv(); if ani.is_ok() { render.remove_animation(ani.ok().unwrap()); } render.render(); } println!("stoped main loop"); } #[rocket::main] async fn main() -> GResult { println!("Program start"); println!("Try to connect db"); let sqlite_conn_manager = SqliteConnectionManager::file("ligths.db"); let conn_pool = r2d2::Pool::new(sqlite_conn_manager).expect("Failed to create pool"); let conn_pool_arc = Arc::new(conn_pool); { let pool = conn_pool_arc.clone(); let dd = setup_database(pool); println!("{:?}", dd); dd.ok().unwrap(); } let (action_sender, action_receiver): (Sender, Receiver) = mpsc::channel(); let (start_animation_sender, start_animation_receiver): ( Sender, Receiver, ) = mpsc::channel(); let (stop_animation_sender, stop_animation_receiver): (Sender, Receiver) = mpsc::channel(); let (messager_sender, messager_revicer): (Sender, Receiver) = mpsc::channel(); let pool_clone = conn_pool_arc.clone(); let ligths_controll = std::thread::spawn(move || { ligth_controll( pool_clone, action_receiver, start_animation_receiver, stop_animation_receiver, messager_sender ); }); let cfg = rocket::Config::figment() .merge(("port", 3000)) .merge(("address", "0.0.0.0")); let _rocket = rocket::custom(cfg) .mount( "/", routes![ index, quit, reload, configure::configure, animations::animation, animations::start_animation, animations::stop_animation, animations::clear, animations::delete, animations::clear_all, ], ) .manage(conn_pool_arc.clone()) .manage(Arc::new(Mutex::new(action_sender))) .manage(Arc::new(Mutex::new(start_animation_sender))) .manage(Arc::new(Mutex::new(stop_animation_sender))) .manage(Arc::new(Mutex::new(messager_revicer))) .launch() .await?; ligths_controll.join().unwrap(); Ok(()) }