diff --git a/.cargo/config.toml b/.cargo/config.toml new file mode 120000 index 0000000..e1fd6d8 --- /dev/null +++ b/.cargo/config.toml @@ -0,0 +1 @@ +../config.toml \ No newline at end of file diff --git a/common/src/pattern.rs b/common/src/pattern.rs index bf99a40..265c380 100644 --- a/common/src/pattern.rs +++ b/common/src/pattern.rs @@ -195,6 +195,7 @@ impl Parameters { } pub trait Pattern: std::fmt::Debug + Send + Sync { + fn get_name(&self) -> &'static str; fn init(&mut self, num_lights: u16) -> PatternResult<()>; fn step(&mut self) -> PatternResult; fn get_strip(&self) -> ColorIterator; diff --git a/common/src/pattern/car_rainbow.rs b/common/src/pattern/car_rainbow.rs index 27f803a..e0c12cc 100644 --- a/common/src/pattern/car_rainbow.rs +++ b/common/src/pattern/car_rainbow.rs @@ -50,6 +50,9 @@ impl CarRainbow { } } impl Pattern for CarRainbow { + fn get_name(&self) -> &'static str { + "CarRainbow" + } fn step(&mut self) -> PatternResult { self.lights_buf.rotate_left(1); // TODO: Not sure if we should go forward or backwards diff --git a/common/src/pattern/collide.rs b/common/src/pattern/collide.rs index 21e7b5a..752ce03 100644 --- a/common/src/pattern/collide.rs +++ b/common/src/pattern/collide.rs @@ -71,6 +71,9 @@ impl Collide { } } impl Pattern for Collide { + fn get_name(&self) -> &'static str { + "Collide" + } fn step(&mut self) -> PatternResult { // TODO: Better range storage // Set the left and right color diff --git a/common/src/pattern/custom_visualizer.rs b/common/src/pattern/custom_visualizer.rs index 660ed49..fcda810 100644 --- a/common/src/pattern/custom_visualizer.rs +++ b/common/src/pattern/custom_visualizer.rs @@ -74,6 +74,9 @@ impl CustomVisualizer { } impl Pattern for CustomVisualizer { + fn get_name(&self) -> &'static str { + "CustomVisualizer" + } fn step(&mut self) -> PatternResult { if let Some(c) = &self.cava { let reading = c diff --git a/common/src/pattern/fade.rs b/common/src/pattern/fade.rs index 853930e..9b4e6e2 100644 --- a/common/src/pattern/fade.rs +++ b/common/src/pattern/fade.rs @@ -47,6 +47,9 @@ impl Fade { } } impl Pattern for Fade { + fn get_name(&self) -> &'static str { + "Fade" + } fn step(&mut self) -> PatternResult { if self.direction { if self.step == 254 { diff --git a/common/src/pattern/flashing.rs b/common/src/pattern/flashing.rs index 7a9bbf9..adae2ac 100644 --- a/common/src/pattern/flashing.rs +++ b/common/src/pattern/flashing.rs @@ -59,6 +59,9 @@ impl Flashing { } impl Pattern for Flashing { + fn get_name(&self) -> &'static str { + "Flashing" + } fn step(&mut self) -> PatternResult { self.step = self.step.wrapping_add(1).rem_euclid(self.tick_rate); if self.step != 0 { diff --git a/common/src/pattern/moving_pixel.rs b/common/src/pattern/moving_pixel.rs index 367c407..6cbbaf1 100644 --- a/common/src/pattern/moving_pixel.rs +++ b/common/src/pattern/moving_pixel.rs @@ -48,6 +48,9 @@ impl MovingPixel { } impl Pattern for MovingPixel { + fn get_name(&self) -> &'static str { + "MovingPixel" + } fn step(&mut self) -> PatternResult { let len = self.num_lights; self.lights_buf.swap( diff --git a/common/src/pattern/moving_rainbow.rs b/common/src/pattern/moving_rainbow.rs index 346bf47..a7c2c9a 100644 --- a/common/src/pattern/moving_rainbow.rs +++ b/common/src/pattern/moving_rainbow.rs @@ -63,6 +63,9 @@ impl MovingRainbow { } } impl Pattern for MovingRainbow { + fn get_name(&self) -> &'static str { + "MovingRainbow" + } fn step(&mut self) -> PatternResult { if self.forward { self.lights_buf.rotate_left(1); diff --git a/common/src/pattern/orb.rs b/common/src/pattern/orb.rs index 4c62ca0..88d29eb 100644 --- a/common/src/pattern/orb.rs +++ b/common/src/pattern/orb.rs @@ -75,6 +75,9 @@ impl Orb { } } impl Pattern for Orb { + fn get_name(&self) -> &'static str { + "Orb" + } fn step(&mut self) -> PatternResult { if !self.bounces { // If we don't bounce, then just wrap and we're done diff --git a/common/src/pattern/slide.rs b/common/src/pattern/slide.rs index f59169b..083b713 100644 --- a/common/src/pattern/slide.rs +++ b/common/src/pattern/slide.rs @@ -64,6 +64,9 @@ impl Slide { } impl Pattern for Slide { + fn get_name(&self) -> &'static str { + "Slide" + } fn step(&mut self) -> PatternResult { self.step = self.step.wrapping_add(1); if self.step.rem_euclid(self.speed as usize) != 0 { diff --git a/common/src/pattern/solid.rs b/common/src/pattern/solid.rs index adc8239..11c58b6 100644 --- a/common/src/pattern/solid.rs +++ b/common/src/pattern/solid.rs @@ -43,6 +43,9 @@ impl Solid { } } impl Pattern for Solid { + fn get_name(&self) -> &'static str { + "Solid" + } fn step(&mut self) -> PatternResult { let ret = !self.has_run; self.has_run = true; diff --git a/common/src/pattern/visualizer.rs b/common/src/pattern/visualizer.rs index 6eb0995..cbfa5be 100644 --- a/common/src/pattern/visualizer.rs +++ b/common/src/pattern/visualizer.rs @@ -42,6 +42,9 @@ impl Visualizer { } impl Pattern for Visualizer { + fn get_name(&self) -> &'static str { + "Visualizer" + } fn step(&mut self) -> PatternResult { if let Some(c) = &self.cava { let reading = c diff --git a/common/src/strip.rs b/common/src/strip.rs index aae90cd..16c723f 100644 --- a/common/src/strip.rs +++ b/common/src/strip.rs @@ -7,6 +7,7 @@ use crate::{ #[derive(Debug)] pub enum Message { ClearLights, + TurnOn(Option), ChangePattern(Box), SetNumLights(u16), SetTickTime(u64), @@ -17,22 +18,22 @@ pub enum Message { #[derive(Clone, Debug)] pub struct State { pub on: bool, - pub pattern: Option, + pub pattern: String, // brightnes: u8, pub color: Rgb, // Off, // Pattern } -impl Default for State { - fn default() -> Self { - Self { - on: false, - pattern: None, - color: color::BLACK, - } - } -} +// impl Default for State { +// fn default() -> Self { +// Self { +// on: false, +// pattern: None, +// color: color::BLACK, +// } +// } +// } // impl Debug for Message { // fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/mqtt/src/lib.rs b/mqtt/src/lib.rs index da9f199..f36ca45 100644 --- a/mqtt/src/lib.rs +++ b/mqtt/src/lib.rs @@ -3,7 +3,7 @@ use anyhow::{Context as _, Result}; use common::{ color::{self, Gradient, Rgb}, error::ProgramError, - pattern::{MovingRainbow, Solid, SolidParams}, + pattern::{MovingRainbow, Parameters, Solid, SolidParams}, MqttConfig, }; use homeassistant_mqtt_discovery::{ @@ -150,7 +150,7 @@ impl Mqtt { } } InternalMessage::OutboundStatePacket(p) => { - let state_msg = self.gen_state_message(&p); + let state_msg = self.gen_state_message(p); info!("Sending state message: {:?}", state_msg); @@ -163,7 +163,7 @@ impl Mqtt { false, serde_json::to_vec(&state_msg).unwrap(), ) - .context("Sending initial autodiscovery") + .context("Sending state change") { error!("{e:?}"); } @@ -263,7 +263,12 @@ impl Mqtt { ..Common::default() }, name: Some(FRIENDLY_NAME.to_string()), - effect_list: Some(vec!["Rainbow".into()]), + effect_list: Some( + Parameters::get_names() + .iter() + .map(|s| s.to_string()) + .collect(), + ), brightness: Some(false), effect: Some(true), supported_color_modes: Some(vec![light::ColorMode::Rgb]), @@ -272,7 +277,7 @@ impl Mqtt { } } - fn gen_state_message(&self, state: &strip::State) -> light::JsonIncoming { + fn gen_state_message(&self, state: strip::State) -> light::JsonIncoming { // "/device_trigger/[/]/config", // homeassistant/device_trigger/0x90fd9ffffedf1266/action_arrow_left_click/config light::JsonIncoming { @@ -285,7 +290,7 @@ impl Mqtt { b: Some(state.color.2 as usize), ..IncomingColor::default() }), - effect: state.pattern.clone(), + effect: Some(state.pattern), state: Some( (if state.on { light::STATUS_DEFAULT_LIGHT_ON @@ -311,11 +316,11 @@ fn build_strip_tx_msg(command: &JsonIncoming) -> Option { return Some(Message::ClearLights); } - if let Some(effect) = &command.effect - && effect == "Rainbow" - { - return Some(Message::ChangePattern(Box::new(MovingRainbow::default()))); - } + // if let Some(effect) = &command.effect + // && effect == "Rainbow" + // { + // return Some(Message::ChangePattern(Box::new(MovingRainbow::default()))); + // } if command.effect.is_none() && let Some(color) = &command.color @@ -336,6 +341,14 @@ fn build_strip_tx_msg(command: &JsonIncoming) -> Option { })))); } + if let Some(state) = &command.state + && state == light::STATUS_DEFAULT_LIGHT_ON + { + return Some(Message::TurnOn( + command.effect.as_ref().map(|s| s.to_string()), + )); + } + error!("Not able to parse input as a command: {command:?}"); None } diff --git a/src/strip.rs b/src/strip.rs index 41a6361..53b480f 100644 --- a/src/strip.rs +++ b/src/strip.rs @@ -21,6 +21,7 @@ pub struct LedStrip { pub adapter: Box, pub config: Config, pub pattern: Box, + pub state: common::strip::State, } impl LedStrip { @@ -49,10 +50,20 @@ impl LedStrip { })) }); + let state = common::strip::State { + on: true, + pattern: pattern.get_name().to_string(), + // brightnes: u8, + color: color::WHITE, + // Off, + // Pattern + }; + let mut ret = Self { adapter, config, pattern, + state, }; ret.set_num_lights(num_lights); @@ -138,6 +149,11 @@ impl LedStrip { } } + // pub fn set_state(&self) { + // // let mut state = common::strip::State::default(); + + // } + pub fn strip_loop( &mut self, message_tx: &Sender, @@ -146,8 +162,7 @@ impl LedStrip { strip_terminated: Sender<()>, ) -> Result<(), ProgramError> { let mut exit = false; - let mut state = common::strip::State::default(); - let _ = state_tx.send(state.clone()); + let _ = state_tx.send(self.state.clone()); loop { let target_time = Instant::now().add(Duration::from_millis(self.config.tick_time_ms)); @@ -160,8 +175,9 @@ impl LedStrip { })); if pat.init(self.pattern_num_lights()).is_ok() { self.pattern = pat; - state.on = false; - let _ = state_tx.send(state.clone()); + self.state.pattern = self.pattern.get_name().to_string(); + self.state.on = false; + let _ = state_tx.send(self.state.clone()); info!("Cleared lights"); } else { let _result = message_tx.send(common::Message::String(format!( @@ -177,9 +193,9 @@ impl LedStrip { self.pattern = pat; info!("Changed pattern"); - state.on = true; - state.pattern = Some(format!("Rainbow")); - let _ = state_tx.send(state.clone()); + self.state.on = true; + self.state.pattern = self.pattern.get_name().to_string(); + let _ = state_tx.send(self.state.clone()); } Err(e) => { let _result = message_tx.send(common::Message::String(format!( @@ -187,6 +203,36 @@ impl LedStrip { ))); } }, + Message::TurnOn(pattern_name) => { + // It's already on + if self.state.on { + continue; + } + + if let Err(e) = self.pattern.cleanup() { + error!("Error cleaning up old pattern: {e:?}"); + } + + // Parameters::from_str(pattern_name) + + let mut pat = pattern_name + .and_then(|p| pattern::Parameters::from_str(&p).ok()) + .map(|p| p.to_pattern()) + .unwrap_or_else(|| { + self.state.color = color::WHITE; + Box::new(pattern::Solid::new(&pattern::SolidParams { + color: color::WHITE, + })) + }); + + if pat.init(self.pattern_num_lights()).is_ok() { + self.pattern = pat; + self.state.pattern = self.pattern.get_name().to_string(); + self.state.on = true; + let _ = state_tx.send(self.state.clone()); + info!("Turned on"); + } + } Message::SetNumLights(num_lights) => { self.set_num_lights(num_lights); }