use r2d2::PooledConnection; use r2d2_sqlite::{SqliteConnectionManager, rusqlite::Statement}; use rocket::{serde::{json::{Json, serde_json::json}, Deserialize, Serialize}, State}; use crate::{utils::{ApiResponse, get_error_message}, Action, ASender}; use crate::DBPool; #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(crate = "rocket::serde")] #[serde(rename_all = "camelCase")] pub struct LightConfiguration { ledcount: u32, direction_x: u32, direction_y: u32, direction_z: u32, tags: Option } #[derive(Debug, Deserialize, Serialize, Clone)] #[serde(crate = "rocket::serde")] #[serde(rename_all = "camelCase")] pub struct LightConfigurationRequest { lights: Vec } #[post("/configure", data= "")] pub async fn configure(data: Json, db: &State, action: &State>) -> String { let conn = get_conn(db); if let Err(e) = conn { return e; } let conn = conn.unwrap(); let recreate = is_configured(&conn); if let Err(e) = recreate { return e; } let recreate = recreate.unwrap(); if recreate { let stmt = conn.execute("DELETE FROM configuration;", ()); if stmt.is_err() || stmt.as_ref().ok().is_none() { return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 4, {:?}", stmt)}).to_string(); } } for light in data.lights.iter() { let mut tags: String = "".to_string(); if light.tags.is_some() { tags = light.tags.as_ref().unwrap().to_string() } let stmt = conn.execute( "INSERT INTO configuration (ledcount, directionX, directionY, directionZ, tags) VALUES (?1, ?2, ?3, ?4, ?5);", (light.ledcount, light.direction_x, light.direction_y, light.direction_z, tags)); if stmt.is_err() || stmt.as_ref().ok().is_none() { return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 5, {:?}", stmt)}).to_string(); } } 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() } let stmt = conn.execute("UPDATE meta set configured=1 where id=1;", ()); if stmt.is_err() || stmt.as_ref().ok().is_none() { return json!(ApiResponse {code: 500, message: format!("Clould not configure. Err: 5, {:?}", stmt)}).to_string(); } json!(ApiResponse {code: 200, message: "Configuration was successful".to_string()}).to_string() } type Conn = PooledConnection; fn get_conn(db: &State) -> Result { let conn = db.get(); if let Ok(conn) = conn { return Ok(conn); } Err(json!(ApiResponse {code: 500, message: "Clould not conncect to the db.".to_string()}).to_string()) } fn prepare_statement<'a>(conn: &'a Conn, stat: &str) -> Result, String> { let stmt = conn.prepare(stat); if stmt.is_err() || stmt.as_ref().ok().is_none() { println!("stmt: {}", stat); return Err(get_error_message("Could not construct statetment")); } let stmt: Statement<'a> = stmt.unwrap(); return Ok(stmt); } fn is_configured(conn: &Conn) -> Result { let mut stmt = prepare_statement(conn, "SELECT configured from meta;")?; #[derive(Debug)] struct Data { configured: u32, } let version_iter = stmt.query_map([], |row| { Ok(Data { configured: row.get(0)? }) }); if version_iter.is_err() || version_iter.as_ref().ok().is_none() { return Err(json!(ApiResponse {code: 500, message: "Clould not get data of db".to_string()}).to_string()); } let version_iter = version_iter.ok().unwrap(); for data in version_iter { let data = data.unwrap(); if data.configured == 1 { return Ok(true); } } return Ok(false); } #[get("/configure")] pub async fn get_configure(db: &State) -> String { let conn = get_conn(db); if let Err(e) = conn { return e; } let conn = conn.unwrap(); let configured = is_configured(&conn); if let Err(e) = configured { return e; } let configured = configured.unwrap(); if !configured { return get_error_message("Not yet configured"); } let stmt = prepare_statement(&conn, "SELECT id, ledcount, directionX, directionY, directionZ, tags from configuration;"); if let Err(e) = stmt { return e; } let mut stmt = stmt.unwrap(); #[derive(Deserialize, Serialize)] #[serde(crate = "rocket::serde")] #[serde(rename_all = "camelCase")] struct Data { id: u32, ledcount: u32, direction_x: u32, direction_y: u32, direction_z: u32, tags: String, } let configuration = stmt.query_map([], |row| { Ok(Data { id: row.get(0)?, ledcount: row.get(1)?, direction_x: row.get(2)?, direction_y: row.get(3)?, direction_z: row.get(4)?, tags: row.get(5)?, }) }); if configuration.is_err() || configuration.as_ref().ok().is_none() { return json!(ApiResponse {code: 500, message: "Clould not get data of db".to_string()}).to_string(); } let configuration = configuration.unwrap(); let data: Vec = configuration.into_iter().map(|data| { return data.unwrap(); }).collect(); json!(data).to_string() }