Working app
This commit is contained in:
parent
dd978179df
commit
058a076414
1
.cargo/config.toml
Symbolic link
1
.cargo/config.toml
Symbolic link
@ -0,0 +1 @@
|
||||
../config.toml
|
@ -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<bool>;
|
||||
fn get_strip(&self) -> ColorIterator;
|
||||
|
@ -50,6 +50,9 @@ impl CarRainbow {
|
||||
}
|
||||
}
|
||||
impl Pattern for CarRainbow {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"CarRainbow"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
self.lights_buf.rotate_left(1);
|
||||
// TODO: Not sure if we should go forward or backwards
|
||||
|
@ -71,6 +71,9 @@ impl Collide {
|
||||
}
|
||||
}
|
||||
impl Pattern for Collide {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Collide"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
// TODO: Better range storage
|
||||
// Set the left and right color
|
||||
|
@ -74,6 +74,9 @@ impl CustomVisualizer {
|
||||
}
|
||||
|
||||
impl Pattern for CustomVisualizer {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"CustomVisualizer"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
if let Some(c) = &self.cava {
|
||||
let reading = c
|
||||
|
@ -47,6 +47,9 @@ impl Fade {
|
||||
}
|
||||
}
|
||||
impl Pattern for Fade {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Fade"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
if self.direction {
|
||||
if self.step == 254 {
|
||||
|
@ -59,6 +59,9 @@ impl Flashing {
|
||||
}
|
||||
|
||||
impl Pattern for Flashing {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Flashing"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
self.step = self.step.wrapping_add(1).rem_euclid(self.tick_rate);
|
||||
if self.step != 0 {
|
||||
|
@ -48,6 +48,9 @@ impl MovingPixel {
|
||||
}
|
||||
|
||||
impl Pattern for MovingPixel {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"MovingPixel"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
let len = self.num_lights;
|
||||
self.lights_buf.swap(
|
||||
|
@ -63,6 +63,9 @@ impl MovingRainbow {
|
||||
}
|
||||
}
|
||||
impl Pattern for MovingRainbow {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"MovingRainbow"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
if self.forward {
|
||||
self.lights_buf.rotate_left(1);
|
||||
|
@ -75,6 +75,9 @@ impl Orb {
|
||||
}
|
||||
}
|
||||
impl Pattern for Orb {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Orb"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
if !self.bounces {
|
||||
// If we don't bounce, then just wrap and we're done
|
||||
|
@ -64,6 +64,9 @@ impl Slide {
|
||||
}
|
||||
|
||||
impl Pattern for Slide {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Slide"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
self.step = self.step.wrapping_add(1);
|
||||
if self.step.rem_euclid(self.speed as usize) != 0 {
|
||||
|
@ -43,6 +43,9 @@ impl Solid {
|
||||
}
|
||||
}
|
||||
impl Pattern for Solid {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Solid"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
let ret = !self.has_run;
|
||||
self.has_run = true;
|
||||
|
@ -42,6 +42,9 @@ impl Visualizer {
|
||||
}
|
||||
|
||||
impl Pattern for Visualizer {
|
||||
fn get_name(&self) -> &'static str {
|
||||
"Visualizer"
|
||||
}
|
||||
fn step(&mut self) -> PatternResult<bool> {
|
||||
if let Some(c) = &self.cava {
|
||||
let reading = c
|
||||
|
@ -7,6 +7,7 @@ use crate::{
|
||||
#[derive(Debug)]
|
||||
pub enum Message {
|
||||
ClearLights,
|
||||
TurnOn(Option<String>),
|
||||
ChangePattern(Box<dyn Pattern + Send + Sync>),
|
||||
SetNumLights(u16),
|
||||
SetTickTime(u64),
|
||||
@ -17,22 +18,22 @@ pub enum Message {
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct State {
|
||||
pub on: bool,
|
||||
pub pattern: Option<String>,
|
||||
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 {
|
||||
|
@ -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 {
|
||||
// "<discovery_prefix>/device_trigger/[<node_id>/]<object_id>/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<strip::Message> {
|
||||
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<strip::Message> {
|
||||
}))));
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
60
src/strip.rs
60
src/strip.rs
@ -21,6 +21,7 @@ pub struct LedStrip {
|
||||
pub adapter: Box<dyn Ws28xxAdapter>,
|
||||
pub config: Config,
|
||||
pub pattern: Box<dyn Pattern + Send + Sync>,
|
||||
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<common::Message>,
|
||||
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user