From 2ce2b09ad7ba1d6bc760145052eebfe21dbca9e2 Mon Sep 17 00:00:00 2001 From: Austen Adler Date: Sun, 8 Aug 2021 15:24:40 -0400 Subject: [PATCH] Send color commands to pi from actix; add string to Rgb parser --- Cargo.toml | 1 + src/color.rs | 34 ++++++++++++++++++++++++++++++++++ src/main.rs | 5 +++-- src/webui.rs | 26 ++++++++++++++++++++------ 4 files changed, 58 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5bb3503..707fb30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,6 +10,7 @@ ws2818-rgb-led-spi-driver = { path = "lib-ws2818-rgb-led-spi-driver/" } serde = {version = "1.0", features = ["derive"]} actix-web = {version = "3", default_features = false} rust-embed="6.0.0" +hex = "0.4.3" [target.armv7-unknown-linux-gnueabihf] linker = "armv7-unknown-linux-gnueabihf" diff --git a/src/color.rs b/src/color.rs index af4386f..a55c1d0 100644 --- a/src/color.rs +++ b/src/color.rs @@ -1,3 +1,7 @@ +use hex; +use std::num::ParseIntError; +use std::str::FromStr; + #[derive(Copy, Clone, Debug, PartialEq)] pub struct Rgb(pub u8, pub u8, pub u8); impl Rgb { @@ -12,6 +16,36 @@ impl Rgb { // ) // } } + +impl FromStr for Rgb { + type Err = ParseIntError; + + fn from_str(s: &str) -> Result { + if let [r, g, b] = s.split(" ").collect::>().as_slice() { + return Ok(Rgb(r.parse::()?, g.parse::()?, b.parse::()?)); + } + + hex::decode( + s.trim_start_matches('#') + .trim_start_matches("0x") + .trim_start_matches("0X"), + ) + .map_err(|_| ()) + .and_then(|v| { + Ok(Rgb( + *v.get(0).ok_or(())?, + *v.get(1).ok_or(())?, + *v.get(2).ok_or(())?, + )) + }) + .or_else(|_| { + // TODO: Return a proper error here + let color_value = s.parse::()?; + Ok(Rgb(color_value, color_value, color_value)) + }) + } +} + #[allow(dead_code)] pub const BLACK: Rgb = Rgb(0, 0, 0); #[allow(dead_code)] diff --git a/src/main.rs b/src/main.rs index 1e5ea51..7dbb9c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,12 +55,13 @@ fn main() -> Result<(), ProgramError> { }); // I do not care if the console ui crashes + let (g, h) = (tx.clone(), tx.clone()); let _console_ui_handle = - thread::spawn(move || -> Result<(), ProgramError> { console_ui_loop(&tx) }); + thread::spawn(move || -> Result<(), ProgramError> { console_ui_loop(&g) }); // I do not care if the web ui crashes let _web_ui_handle = thread::spawn(move || -> Result<(), io::Error> { - webui::start() + webui::start(h) // TODO: Do not join -- this is just because we are running on a computer with no spi env }) .join()?; diff --git a/src/webui.rs b/src/webui.rs index 8b1d5ce..8ccdf20 100644 --- a/src/webui.rs +++ b/src/webui.rs @@ -1,7 +1,14 @@ +use crate::color::Rgb; +use crate::pattern; +use crate::strip; use actix_web::web::Form; use actix_web::{get, post, web, App, HttpRequest, HttpServer, Responder}; use rust_embed::RustEmbed; use serde::Deserialize; +use std::str::FromStr; +use std::sync::{Arc, Mutex}; + +use std::sync::mpsc::Sender; // TODO: Pre-compute binary somehow? So do not have to unwrap #[derive(RustEmbed)] @@ -9,7 +16,7 @@ use serde::Deserialize; struct Asset; struct AppState { - app_name: String, + strip_tx: Arc>>, } #[derive(Deserialize, Debug)] @@ -19,24 +26,31 @@ struct ColorForm { #[post("/setcolor")] async fn set_color(data: web::Data, params: Form) -> impl Responder { + data.strip_tx + .lock() + .unwrap() + .send(strip::Message::ChangePattern(Box::new( + pattern::Solid::new(Rgb::from_str(¶ms.color).unwrap()), + ))) + .unwrap(); format!("{:?}", params) } #[get("/")] -async fn test(data: web::Data, req: HttpRequest) -> impl Responder { +async fn index(_data: web::Data, _req: HttpRequest) -> impl Responder { // TODO: This is probably the ugliest possible way to do it. Make this better String::from_utf8((&Asset::get("index.html").unwrap().data).to_vec()).unwrap() } #[actix_web::main] -pub async fn start() -> std::io::Result<()> { +pub async fn start(tx: Sender) -> std::io::Result<()> { println!("Starting webui"); - HttpServer::new(|| { + HttpServer::new(move || { App::new() .data(AppState { - app_name: String::from("abawse"), + strip_tx: Arc::new(Mutex::new(tx.clone())), }) - .service(test) + .service(index) .service(set_color) // App::new() // .route("/", web::get().to(greet))