chore: added option to get list of active animations
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
6a6e171f62
commit
5c84875dd9
161
src/db.rs
Normal file
161
src/db.rs
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
use std::error::Error;
|
||||||
|
|
||||||
|
use crate::DBPool;
|
||||||
|
|
||||||
|
pub type GResult = Result<(), Box<dyn Error>>;
|
||||||
|
const DATAVERSION: &str = "0.0.10";
|
||||||
|
|
||||||
|
fn create_database(pool: DBPool) -> GResult {
|
||||||
|
let conn = pool.get()?;
|
||||||
|
|
||||||
|
println!("Createing the database");
|
||||||
|
|
||||||
|
println!("Createing new meta table. With version {}", DATAVERSION);
|
||||||
|
println!("Drop old meta table");
|
||||||
|
conn.execute("DROP TABLE IF EXISTS meta;", ())?;
|
||||||
|
// Create the database
|
||||||
|
println!("create new meta table");
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE meta (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
version TEXT,
|
||||||
|
configured Boolean
|
||||||
|
);",
|
||||||
|
(),
|
||||||
|
)?;
|
||||||
|
println!("insert data");
|
||||||
|
conn.execute(
|
||||||
|
"INSERT INTO meta (version, configured) VALUES (?1, ?2);",
|
||||||
|
(&DATAVERSION, false),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Createing new configuration table. With version {}",
|
||||||
|
DATAVERSION
|
||||||
|
);
|
||||||
|
println!("Drop configuration table");
|
||||||
|
conn.execute("DROP TABLE IF EXISTS configuration", ())?;
|
||||||
|
println!("Create new configuration table");
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE configuration (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
ledcount INTEGER,
|
||||||
|
directionX INTEGER,
|
||||||
|
directionY INTEGER,
|
||||||
|
directionZ INTEGER,
|
||||||
|
tags VARCHAR(255)
|
||||||
|
);",
|
||||||
|
(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Createing new Animation table. With version {}",
|
||||||
|
DATAVERSION
|
||||||
|
);
|
||||||
|
println!("Drop Animation table and references");
|
||||||
|
conn.execute("DROP TABLE IF EXISTS lightsetting", ())?;
|
||||||
|
conn.execute("DROP TABLE IF EXISTS keyframe", ())?;
|
||||||
|
conn.execute("DROP TABLE IF EXISTS animation", ())?;
|
||||||
|
println!("Create new animation table");
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE animation (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
priority INTEGER,
|
||||||
|
name VARCHAR(255),
|
||||||
|
repeat BOOLEAN
|
||||||
|
);",
|
||||||
|
(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Createing new key_frame table. With version {}",
|
||||||
|
DATAVERSION
|
||||||
|
);
|
||||||
|
println!("Drop key_frame table");
|
||||||
|
println!("Create new key_frame table");
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE keyframe (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
i INTEGER,
|
||||||
|
duration INTEGER,
|
||||||
|
animation INTEGER,
|
||||||
|
FOREIGN KEY(animation) REFERENCES animation(id) ON DELETE CASCADE
|
||||||
|
);",
|
||||||
|
(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Createing new LigthSetting table. With version {}",
|
||||||
|
DATAVERSION
|
||||||
|
);
|
||||||
|
println!("Drop LigthSetting table");
|
||||||
|
println!("Create new light_setting table");
|
||||||
|
conn.execute(
|
||||||
|
"CREATE TABLE lightsetting (
|
||||||
|
id INTEGER PRIMARY KEY,
|
||||||
|
start INTEGER,
|
||||||
|
end INTEGER,
|
||||||
|
tags VARCHAR(255),
|
||||||
|
r INTEGER,
|
||||||
|
b INTEGER,
|
||||||
|
g INTEGER,
|
||||||
|
keyframe INTEGER,
|
||||||
|
FOREIGN KEY(keyframe) REFERENCES keyframe(id) ON DELETE CASCADE
|
||||||
|
);",
|
||||||
|
(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn setup_database(pool: DBPool) -> GResult {
|
||||||
|
let conn = pool.get()?;
|
||||||
|
|
||||||
|
println!("Trying to get meta data");
|
||||||
|
|
||||||
|
let stmt = conn.prepare("SELECT version from meta");
|
||||||
|
|
||||||
|
if stmt.is_err() || stmt.as_ref().ok().is_none() {
|
||||||
|
return create_database(pool);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut stmt = stmt?;
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
version: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
let version_iter = stmt.query_map([], |row| {
|
||||||
|
Ok(Data {
|
||||||
|
version: row.get(0)?,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
println!("Process meta");
|
||||||
|
|
||||||
|
if version_iter.is_err() || version_iter.as_ref().ok().is_none() {
|
||||||
|
create_database(pool)?;
|
||||||
|
} else {
|
||||||
|
let version_iter = version_iter.ok().unwrap();
|
||||||
|
|
||||||
|
let mut recreate = true;
|
||||||
|
|
||||||
|
for data in version_iter {
|
||||||
|
let version = data.unwrap().version;
|
||||||
|
println!("Found version {}", version);
|
||||||
|
|
||||||
|
if !DATAVERSION.to_string().eq(&version) {
|
||||||
|
println!("Mismatched versions recreating database");
|
||||||
|
recreate = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
recreate = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if recreate {
|
||||||
|
create_database(pool)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
218
src/main.rs
218
src/main.rs
@ -7,15 +7,18 @@ mod animations;
|
|||||||
mod configure;
|
mod configure;
|
||||||
mod render;
|
mod render;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod db;
|
||||||
|
|
||||||
use animations::Animation;
|
use animations::Animation;
|
||||||
use r2d2::PooledConnection;
|
use r2d2::PooledConnection;
|
||||||
use utils::ApiResponse;
|
use utils::{ApiResponse, ApiResponseActiveList};
|
||||||
|
|
||||||
use rocket::{serde::json::serde_json::json, State};
|
use rocket::{serde::json::{serde_json::json, self}, State};
|
||||||
|
|
||||||
use r2d2_sqlite::SqliteConnectionManager;
|
use r2d2_sqlite::SqliteConnectionManager;
|
||||||
|
|
||||||
|
use crate::db::setup_database;
|
||||||
|
|
||||||
//use std::sync::atomic::AtomicBool;
|
//use std::sync::atomic::AtomicBool;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
@ -30,6 +33,7 @@ pub type DBPool = Arc<r2d2::Pool<r2d2_sqlite::SqliteConnectionManager>>;
|
|||||||
pub type DBConn = PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
pub type DBConn = PooledConnection<r2d2_sqlite::SqliteConnectionManager>;
|
||||||
pub type GResult = Result<(), Box<dyn Error>>;
|
pub type GResult = Result<(), Box<dyn Error>>;
|
||||||
pub type ASender<T> = Arc<Mutex<Sender<T>>>;
|
pub type ASender<T> = Arc<Mutex<Sender<T>>>;
|
||||||
|
pub type AReceiver<T> = Arc<Mutex<Receiver<T>>>;
|
||||||
|
|
||||||
#[get("/")]
|
#[get("/")]
|
||||||
fn index() -> &'static str {
|
fn index() -> &'static str {
|
||||||
@ -40,6 +44,13 @@ pub enum Action {
|
|||||||
Reload,
|
Reload,
|
||||||
Stop,
|
Stop,
|
||||||
Clear,
|
Clear,
|
||||||
|
GetActiveList,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum RenderMessage {
|
||||||
|
ActiveList(Vec<String>),
|
||||||
|
// TODO remove none where other are added
|
||||||
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[get("/quit")]
|
#[get("/quit")]
|
||||||
@ -86,11 +97,48 @@ async fn reload(action: &State<ASender<Action>>) -> String {
|
|||||||
.to_string()
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[get("/active")]
|
||||||
|
async fn get_active(action: &State<ASender<Action>>, messages: &State<AReceiver<RenderMessage>>) -> 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(
|
fn ligth_controll(
|
||||||
pool: DBPool,
|
pool: DBPool,
|
||||||
action: Receiver<Action>,
|
action: Receiver<Action>,
|
||||||
start_ani: Receiver<Animation>,
|
start_ani: Receiver<Animation>,
|
||||||
stop_ani: Receiver<String>,
|
stop_ani: Receiver<String>,
|
||||||
|
message_server: Sender<RenderMessage>,
|
||||||
) {
|
) {
|
||||||
println!("Data loop started");
|
println!("Data loop started");
|
||||||
|
|
||||||
@ -122,6 +170,11 @@ fn ligth_controll(
|
|||||||
render.im_render();
|
render.im_render();
|
||||||
break 'mainloop;
|
break 'mainloop;
|
||||||
}
|
}
|
||||||
|
Action::GetActiveList => {
|
||||||
|
if message_server.send(RenderMessage::ActiveList(render.get_active_animations())).is_err() {
|
||||||
|
println!("Failed to send message ups");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -146,162 +199,6 @@ fn ligth_controll(
|
|||||||
println!("stoped main loop");
|
println!("stoped main loop");
|
||||||
}
|
}
|
||||||
|
|
||||||
const DATAVERSION: &str = "0.0.10";
|
|
||||||
|
|
||||||
fn setup_database(pool: DBPool) -> GResult {
|
|
||||||
let conn = pool.get()?;
|
|
||||||
|
|
||||||
println!("Trying to get meta data");
|
|
||||||
|
|
||||||
let stmt = conn.prepare("SELECT version from meta");
|
|
||||||
|
|
||||||
if stmt.is_err() || stmt.as_ref().ok().is_none() {
|
|
||||||
return create_database(pool);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut stmt = stmt?;
|
|
||||||
|
|
||||||
struct Data {
|
|
||||||
version: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
let version_iter = stmt.query_map([], |row| {
|
|
||||||
Ok(Data {
|
|
||||||
version: row.get(0)?,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
println!("Process meta");
|
|
||||||
|
|
||||||
if version_iter.is_err() || version_iter.as_ref().ok().is_none() {
|
|
||||||
create_database(pool)?;
|
|
||||||
} else {
|
|
||||||
let version_iter = version_iter.ok().unwrap();
|
|
||||||
|
|
||||||
let mut recreate = true;
|
|
||||||
|
|
||||||
for data in version_iter {
|
|
||||||
let version = data.unwrap().version;
|
|
||||||
println!("Found version {}", version);
|
|
||||||
|
|
||||||
if !DATAVERSION.to_string().eq(&version) {
|
|
||||||
println!("Mismatched versions recreating database");
|
|
||||||
recreate = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
recreate = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if recreate {
|
|
||||||
create_database(pool)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_database(pool: DBPool) -> GResult {
|
|
||||||
let conn = pool.get()?;
|
|
||||||
|
|
||||||
println!("Createing the database");
|
|
||||||
|
|
||||||
println!("Createing new meta table. With version {}", DATAVERSION);
|
|
||||||
println!("Drop old meta table");
|
|
||||||
conn.execute("DROP TABLE IF EXISTS meta;", ())?;
|
|
||||||
// Create the database
|
|
||||||
println!("create new meta table");
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE meta (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
version TEXT,
|
|
||||||
configured Boolean
|
|
||||||
);",
|
|
||||||
(),
|
|
||||||
)?;
|
|
||||||
println!("insert data");
|
|
||||||
conn.execute(
|
|
||||||
"INSERT INTO meta (version, configured) VALUES (?1, ?2);",
|
|
||||||
(&DATAVERSION, false),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Createing new configuration table. With version {}",
|
|
||||||
DATAVERSION
|
|
||||||
);
|
|
||||||
println!("Drop configuration table");
|
|
||||||
conn.execute("DROP TABLE IF EXISTS configuration", ())?;
|
|
||||||
println!("Create new configuration table");
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE configuration (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
ledcount INTEGER,
|
|
||||||
directionX INTEGER,
|
|
||||||
directionY INTEGER,
|
|
||||||
directionZ INTEGER,
|
|
||||||
tags VARCHAR(255)
|
|
||||||
);",
|
|
||||||
(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Createing new Animation table. With version {}",
|
|
||||||
DATAVERSION
|
|
||||||
);
|
|
||||||
println!("Drop Animation table and references");
|
|
||||||
conn.execute("DROP TABLE IF EXISTS lightsetting", ())?;
|
|
||||||
conn.execute("DROP TABLE IF EXISTS keyframe", ())?;
|
|
||||||
conn.execute("DROP TABLE IF EXISTS animation", ())?;
|
|
||||||
println!("Create new animation table");
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE animation (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
priority INTEGER,
|
|
||||||
name VARCHAR(255),
|
|
||||||
repeat BOOLEAN
|
|
||||||
);",
|
|
||||||
(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Createing new key_frame table. With version {}",
|
|
||||||
DATAVERSION
|
|
||||||
);
|
|
||||||
println!("Drop key_frame table");
|
|
||||||
println!("Create new key_frame table");
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE keyframe (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
i INTEGER,
|
|
||||||
duration INTEGER,
|
|
||||||
animation INTEGER,
|
|
||||||
FOREIGN KEY(animation) REFERENCES animation(id) ON DELETE CASCADE
|
|
||||||
);",
|
|
||||||
(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
println!(
|
|
||||||
"Createing new LigthSetting table. With version {}",
|
|
||||||
DATAVERSION
|
|
||||||
);
|
|
||||||
println!("Drop LigthSetting table");
|
|
||||||
println!("Create new light_setting table");
|
|
||||||
conn.execute(
|
|
||||||
"CREATE TABLE lightsetting (
|
|
||||||
id INTEGER PRIMARY KEY,
|
|
||||||
start INTEGER,
|
|
||||||
end INTEGER,
|
|
||||||
tags VARCHAR(255),
|
|
||||||
r INTEGER,
|
|
||||||
b INTEGER,
|
|
||||||
g INTEGER,
|
|
||||||
keyframe INTEGER,
|
|
||||||
FOREIGN KEY(keyframe) REFERENCES keyframe(id) ON DELETE CASCADE
|
|
||||||
);",
|
|
||||||
(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[rocket::main]
|
#[rocket::main]
|
||||||
async fn main() -> GResult {
|
async fn main() -> GResult {
|
||||||
@ -327,6 +224,9 @@ async fn main() -> GResult {
|
|||||||
let (stop_animation_sender, stop_animation_receiver): (Sender<String>, Receiver<String>) =
|
let (stop_animation_sender, stop_animation_receiver): (Sender<String>, Receiver<String>) =
|
||||||
mpsc::channel();
|
mpsc::channel();
|
||||||
|
|
||||||
|
let (messager_sender, messager_revicer): (Sender<RenderMessage>, Receiver<RenderMessage>) =
|
||||||
|
mpsc::channel();
|
||||||
|
|
||||||
let pool_clone = conn_pool_arc.clone();
|
let pool_clone = conn_pool_arc.clone();
|
||||||
|
|
||||||
let ligths_controll = std::thread::spawn(move || {
|
let ligths_controll = std::thread::spawn(move || {
|
||||||
@ -335,6 +235,7 @@ async fn main() -> GResult {
|
|||||||
action_receiver,
|
action_receiver,
|
||||||
start_animation_receiver,
|
start_animation_receiver,
|
||||||
stop_animation_receiver,
|
stop_animation_receiver,
|
||||||
|
messager_sender
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -362,6 +263,7 @@ async fn main() -> GResult {
|
|||||||
.manage(Arc::new(Mutex::new(action_sender)))
|
.manage(Arc::new(Mutex::new(action_sender)))
|
||||||
.manage(Arc::new(Mutex::new(start_animation_sender)))
|
.manage(Arc::new(Mutex::new(start_animation_sender)))
|
||||||
.manage(Arc::new(Mutex::new(stop_animation_sender)))
|
.manage(Arc::new(Mutex::new(stop_animation_sender)))
|
||||||
|
.manage(Arc::new(Mutex::new(messager_revicer)))
|
||||||
.launch()
|
.launch()
|
||||||
.await?;
|
.await?;
|
||||||
ligths_controll.join().unwrap();
|
ligths_controll.join().unwrap();
|
||||||
|
@ -91,6 +91,10 @@ impl Render {
|
|||||||
return Ok(render);
|
return Ok(render);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_active_animations(&mut self) -> Vec<String> {
|
||||||
|
self.animations.iter().map(|animation| animation.name.clone()).collect()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn load_config(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn load_config(&mut self) -> Result<(), Box<dyn Error>> {
|
||||||
println!("Load config");
|
println!("Load config");
|
||||||
// GPIO Pin 10 is SPI
|
// GPIO Pin 10 is SPI
|
||||||
|
@ -7,5 +7,12 @@ pub struct ApiResponse {
|
|||||||
pub message: String
|
pub message: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
|
#[serde(crate="rocket::serde")]
|
||||||
|
pub struct ApiResponseActiveList {
|
||||||
|
pub code: u32,
|
||||||
|
pub active_animations: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Responder)]
|
#[derive(Responder)]
|
||||||
pub struct ApiResponder(String);
|
pub struct ApiResponder(String);
|
||||||
|
Loading…
Reference in New Issue
Block a user