lights/src/configure.rs
Andre Henriques d5859d0c7e
All checks were successful
continuous-integration/drone/push Build is passing
chore: update field name
2023-07-10 11:49:54 +01:00

187 lines
5.5 KiB
Rust

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<String>
}
#[derive(Debug, Deserialize, Serialize, Clone)]
#[serde(crate = "rocket::serde")]
#[serde(rename_all = "camelCase")]
pub struct LightConfigurationRequest {
lights: Vec<LightConfiguration>
}
#[post("/configure", data= "<data>")]
pub async fn configure(data: Json<LightConfigurationRequest>, db: &State<DBPool>, action: &State<ASender<Action>>) -> 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<SqliteConnectionManager>;
fn get_conn(db: &State<DBPool>) -> Result<Conn, String> {
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<Statement<'a>, 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<bool, String> {
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<DBPool>) -> 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<Data> = configuration.into_iter().map(|data| {
return data.unwrap();
}).collect();
json!(data).to_string()
}