From b718334392e00d07312cb1db9d68ab9a037597db Mon Sep 17 00:00:00 2001 From: Tobias Ollive Date: Fri, 11 Mar 2022 12:40:12 +0100 Subject: [PATCH] refactor patterns --- spectacle.yml | 58 ++---- src/main.rs | 7 +- src/patterns.rs | 367 ++-------------------------------- src/patterns/blink.rs | 36 ++++ src/patterns/color_wipe.rs | 44 ++++ src/patterns/fade.rs | 56 ++++++ src/patterns/fill_random.rs | 52 +++++ src/patterns/fill_unstable.rs | 49 +++++ src/patterns/rainbow.rs | 76 +++++++ src/patterns/scanner.rs | 45 +++++ src/runner.rs | 28 ++- 11 files changed, 417 insertions(+), 401 deletions(-) create mode 100644 src/patterns/blink.rs create mode 100644 src/patterns/color_wipe.rs create mode 100644 src/patterns/fade.rs create mode 100644 src/patterns/fill_random.rs create mode 100644 src/patterns/fill_unstable.rs create mode 100644 src/patterns/rainbow.rs create mode 100644 src/patterns/scanner.rs diff --git a/spectacle.yml b/spectacle.yml index 098af97..43689f7 100644 --- a/spectacle.yml +++ b/spectacle.yml @@ -7,83 +7,55 @@ fade: current_iteration: 10 nbr_iterations: 20 - begin_color: + begin_color: &black red: 0 green: 0 blue: 0 - end_color: + end_color: &purple red: 255 green: 0 blue: 255 - current_iteration: 0 max_iteration: 10 - period: - secs: 0 - nanos: 50000000 + period: 50 - pattern: type: Fade - current_iteration: 0 nbr_iterations: 20 - begin_color: + begin_color: &red red: 255 green: 0 blue: 0 - end_color: + end_color: &blue red: 0 green: 0 blue: 255 - period: - secs: 0 - nanos: 200000000 + period: 200 - pattern: type: ColorWipe max_iteration: 25 - current_iteration: 0 - color: + color: &green red: 0 green: 255 blue: 0 - background_color: - red: 255 - green: 0 - blue: 255 - period: - secs: 0 - nanos: 100000000 + background_color: *purple + period: 100 - pattern: type: FillRandom - color: - red: 0 - green: 0 - blue: 255 + color: *blue stability: 40 - period: - secs: 0 - nanos: 800000000 - + period: 80 - name: titi sequence: - pattern: type: Blink fade : - current_iteration: 0 nbr_iterations: 20 - begin_color: - red: 0 - green: 0 - blue: 0 - end_color: + begin_color: *black + end_color: &cyan red: 0 green: 255 blue: 255 - current_iteration: 0 max_iteration : 10 - period: - secs: 0 - nanos: 100000000 + period: 50 - pattern: type: Rainbow - current_iteration: 0 - period: - secs: 0 - nanos: 100000000 \ No newline at end of file + period: 100 \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 984f4b4..b156f7e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,7 +19,6 @@ use std::sync::{Arc, Mutex}; use std::time::Duration; use tokio::sync::mpsc; use tokio::sync::watch; -use tokio::sync::Notify; const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8); const PIXEL_DATA_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0903c33242a893bd25e905756cb8); @@ -35,8 +34,6 @@ async fn main() -> bluer::Result<()> { let spectacle = Spectacle::from(config); let spectacle = Arc::new(Mutex::new(spectacle)); - let musique_file = command_line.musique_file; - let musique = tokio::task::spawn_blocking(move || play_sound(Path::new(&musique_file))); let adapter = bluetooth::create_session().await?; let (tx_scan, rx_scan) = mpsc::channel(3); @@ -49,9 +46,9 @@ async fn main() -> bluer::Result<()> { tokio::spawn(connect_device(spectacle.clone(), rx_scan)); - tokio::time::sleep(Duration::from_secs(5)).await; - println!("starting"); + let musique_file = command_line.musique_file; + let musique = tokio::task::spawn_blocking(move || play_sound(Path::new(&musique_file))); let futures; { let mut spectacle = spectacle.lock().unwrap(); diff --git a/src/patterns.rs b/src/patterns.rs index 13814d7..614669f 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -1,7 +1,21 @@ -use rand::Rng; +mod scanner; +mod fade; +mod color_wipe; +mod rainbow; +mod fill_random; +mod fill_unstable; +mod blink; + use serde_derive::{Deserialize, Serialize}; use std::fmt; use std::ops::{Div, Index, IndexMut, SubAssign}; +use crate::patterns::blink::Blink; +use crate::patterns::color_wipe::ColorWipe; +use crate::patterns::fade::Fade; +use crate::patterns::fill_random::FillRandom; +use crate::patterns::fill_unstable::FillUnstable; +use crate::patterns::rainbow::Rainbow; +use crate::patterns::scanner::Scanner; #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] #[serde(tag = "type")] @@ -110,353 +124,4 @@ impl Strip { pub fn fill(&mut self, color: PixelColor) { self.0.fill(color); } -} - -/// # Rainbow pattern -/// -/// every pattern implement the iterator trait -/// -/// This pattern display a moving rainbow over the strip -/// -/// ### Note -/// -/// If max iteration is let to None, it's an infinite pattern. -/// -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct Rainbow { - #[serde(default)] - pub(crate) current_iteration: usize, - pub(crate) max_iteration: Option, - pub(crate) step: Option, -} - -impl Iterator for Rainbow { - type Item = Strip; - - fn next(&mut self) -> Option { - if let Some(nbr_iteration) = self.max_iteration { - if nbr_iteration == self.current_iteration { - return None; - } - } - let mut strip = Strip::default(); - let step = self.step.unwrap_or(255 / N); - for i in 0..N { - let pos = (i * step + self.current_iteration) as u8; - strip[i] = wheel(pos) - } - self.current_iteration += 1; - Some(strip) - } -} - -/// compute **rgb** pixel color according to the **hsv** wheel -/// -/// # Arguments -/// -/// * `index`: position in the hsv wheel -/// -/// returns: PixelColor -/// -fn wheel(index: u8) -> PixelColor { - let pos = 255 - index; - match pos { - 0..=85 => PixelColor { - red: 255 - (pos * 3), - green: 0, - blue: pos * 3, - }, - 86..=170 => { - let pos = pos - 85; - PixelColor { - red: 0, - green: pos * 3, - blue: 255 - (pos * 3), - } - } - _ => { - let pos = pos - 170; - PixelColor { - red: pos * 3, - green: 255 - (pos * 3), - blue: 0, - } - } - } -} - -/// # Colorwipe pattern -/// every pattern implement the iterator trait -/// -/// This pattern fill the strip with a specific color, one by one. -/// -/// ### Note -/// -/// setting max_iteration to None lead the pattern to loop infinitely -/// -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct ColorWipe { - #[serde(default)] - pub(crate) current_iteration: usize, - pub(crate) max_iteration: Option, - pub(crate) color: PixelColor, - pub(crate) background_color: Option, -} - -impl Iterator for ColorWipe { - type Item = Strip; - - fn next(&mut self) -> Option { - let mut strip = Strip::default(); - if let Some(c) = self.background_color { - strip.fill(c); - } - let iteration = self.current_iteration % N; - if let Some(max_iteration) = self.max_iteration { - if self.current_iteration >= max_iteration { - return None; - } - } - - for i in 0..iteration { - strip[i] = self.color; - } - self.current_iteration += 1; - Some(strip) - } -} - -/// # fade pattern -/// fade from one color to an other -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct Fade { - #[serde(default)] - pub(crate) current_iteration: usize, - pub(crate) nbr_iterations: usize, - pub(crate) begin_color: PixelColor, - pub(crate) end_color: PixelColor, -} - -fn fade_value(value_start: u8, value_end: u8, index: usize, nbr_iter: usize) -> u8 { - ((value_start as usize * (nbr_iter - index) + value_end as usize * index) / nbr_iter) as u8 -} - -impl Iterator for Fade { - type Item = Strip; - - fn next(&mut self) -> Option { - let mut strip = Strip::default(); - - if self.current_iteration >= self.nbr_iterations { - return None; - } - - let red = fade_value( - self.begin_color.red, - self.end_color.red, - self.current_iteration, - self.nbr_iterations, - ); - let green = fade_value( - self.begin_color.green, - self.end_color.green, - self.current_iteration, - self.nbr_iterations, - ); - let blue = fade_value( - self.begin_color.blue, - self.end_color.blue, - self.current_iteration, - self.nbr_iterations, - ); - - let current_color = PixelColor { red, green, blue }; - - strip.fill(current_color); - - self.current_iteration += 1; - Some(strip) - } -} - -/// # scanner pattern -/// color one pixel with a color and leave a train of this color fading to black -/// -/// # note -/// -/// background_color work only for color not set by scanner pattern -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct Scanner { - #[serde(default)] - pub(crate) current_iteration: usize, - pub(crate) color: PixelColor, - pub(crate) background_color: Option, -} - -impl Iterator for Scanner { - type Item = Strip; - - fn next(&mut self) -> Option { - let mut strip = Strip::::default(); - if let Some(c) = self.background_color { - strip.fill(c); - } else { - strip.fill(PixelColor::default()); - } - - let current_led = self.current_iteration % N; - let min_led; - if current_led < 8 { - min_led = 0; - } else { - min_led = current_led - 8; - } - let mut c = self.color; - for i in min_led..current_led { - strip[i] = c; - c = c / 2; - } - self.current_iteration += 1; - Some(strip) - } -} - -/// # FillRandom -/// -/// fill strip with color then apply random variation to each pixel -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct FillRandom { - pub(crate) color: PixelColor, - pub(crate) stability: usize, - pub(crate) max_iteration: Option, -} - -impl Iterator for FillRandom { - type Item = Strip; - - fn next(&mut self) -> Option { - if let Some(iteration) = self.max_iteration { - if iteration == 0 { - return None; - } else { - self.max_iteration = Some(iteration - 1); - } - } - - let mut strip = Strip::::default(); - let mut rng = rand::thread_rng(); - for i in 0..N { - let red_delta = rng.gen_range(0..self.stability) as u8; - let green_delta = rng.gen_range(0..self.stability) as u8; - let blue_delta = rng.gen_range(0..self.stability) as u8; - let operation = rng.gen_bool(0.5); - let red; - let green; - let blue; - if operation { - red = self.color.red.saturating_add(red_delta); - green = self.color.green.saturating_add(green_delta); - blue = self.color.blue.saturating_add(blue_delta); - } else { - red = self.color.red.saturating_sub(red_delta); - green = self.color.green.saturating_sub(green_delta); - blue = self.color.blue.saturating_sub(blue_delta); - } - let c = PixelColor { red, green, blue }; - strip[i] = c; - } - Some(strip) - } -} - -/// # FillUnstable -/// -/// fill strip with color then apply same random variation to all pixel -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct FillUnstable { - pub(crate) color: PixelColor, - pub(crate) stability: usize, - pub(crate) max_iteration: Option, -} - -impl Iterator for FillUnstable { - type Item = Strip; - - fn next(&mut self) -> Option { - if let Some(iteration) = self.max_iteration { - if iteration == 0 { - return None; - } else { - self.max_iteration = Some(iteration - 1); - } - } - - let mut strip = Strip::::default(); - let mut rng = rand::thread_rng(); - let red_delta = rng.gen_range(0..self.stability) as u8; - let green_delta = rng.gen_range(0..self.stability) as u8; - let blue_delta = rng.gen_range(0..self.stability) as u8; - let operation = rng.gen_bool(0.5); - let red; - let green; - let blue; - if operation { - red = self.color.red.saturating_add(red_delta); - green = self.color.green.saturating_add(green_delta); - blue = self.color.blue.saturating_add(blue_delta); - } else { - red = self.color.red.saturating_sub(red_delta); - green = self.color.green.saturating_sub(green_delta); - blue = self.color.blue.saturating_sub(blue_delta); - } - strip.fill(PixelColor { red, green, blue }); - Some(strip) - } -} - -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -enum Direction { - there, - back, -} - -impl Default for Direction { - fn default() -> Self { - Direction::there - } -} - -/// # Blink -/// -/// fade from one color to an other then go back several times -#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] -pub struct Blink { - #[serde(default)] - pub(crate) current_iteration: usize, - pub(crate) max_iteration: Option, - fade: Fade, - #[serde(default)] - direction: Direction, -} - -impl Iterator for Blink { - type Item = Strip; - - fn next(&mut self) -> Option { - let value = self.fade.next(); - match value { - None => { - if let Some(iter_max) = self.max_iteration { - if self.current_iteration >= iter_max { - return None; - } - self.current_iteration += 1; - } - self.fade.current_iteration = 0; - std::mem::swap(&mut self.fade.begin_color, &mut self.fade.end_color); - self.fade.next() - } - Some(value) => Some(value), - } - } -} +} \ No newline at end of file diff --git a/src/patterns/blink.rs b/src/patterns/blink.rs new file mode 100644 index 0000000..45ffdcf --- /dev/null +++ b/src/patterns/blink.rs @@ -0,0 +1,36 @@ +use crate::patterns::fade::Fade; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # Blink +/// +/// fade from one color to an other then go back several times +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct Blink { + #[serde(default)] + pub(crate) current_iteration: usize, + pub(crate) max_iteration: Option, + fade: Fade, +} + +impl Iterator for Blink { + type Item = Strip; + + fn next(&mut self) -> Option { + let value = self.fade.next(); + match value { + None => { + if let Some(iter_max) = self.max_iteration { + if self.current_iteration >= iter_max { + return None; + } + self.current_iteration += 1; + } + self.fade.current_iteration = 0; + std::mem::swap(&mut self.fade.begin_color, &mut self.fade.end_color); + self.fade.next() + } + Some(value) => Some(value), + } + } +} \ No newline at end of file diff --git a/src/patterns/color_wipe.rs b/src/patterns/color_wipe.rs new file mode 100644 index 0000000..167e96a --- /dev/null +++ b/src/patterns/color_wipe.rs @@ -0,0 +1,44 @@ +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # Colorwipe pattern +/// every pattern implement the iterator trait +/// +/// This pattern fill the strip with a specific color, one by one. +/// +/// ### Note +/// +/// setting max_iteration to None lead the pattern to loop infinitely +/// +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct ColorWipe { + #[serde(default)] + pub(crate) current_iteration: usize, + pub(crate) max_iteration: Option, + pub(crate) color: PixelColor, + pub(crate) background_color: Option, +} + +impl Iterator for ColorWipe { + type Item = Strip; + + fn next(&mut self) -> Option { + let mut strip = Strip::default(); + if let Some(c) = self.background_color { + strip.fill(c); + } + let iteration = self.current_iteration % N; + if let Some(max_iteration) = self.max_iteration { + if self.current_iteration >= max_iteration { + return None; + } + } + + for i in 0..iteration { + strip[i] = self.color; + } + self.current_iteration += 1; + Some(strip) + } +} \ No newline at end of file diff --git a/src/patterns/fade.rs b/src/patterns/fade.rs new file mode 100644 index 0000000..dd490a5 --- /dev/null +++ b/src/patterns/fade.rs @@ -0,0 +1,56 @@ +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # fade pattern +/// fade from one color to an other +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct Fade { + #[serde(default)] + pub(crate) current_iteration: usize, + pub(crate) nbr_iterations: usize, + pub(crate) begin_color: PixelColor, + pub(crate) end_color: PixelColor, +} + +fn fade_value(value_start: u8, value_end: u8, index: usize, nbr_iter: usize) -> u8 { + ((value_start as usize * (nbr_iter - index) + value_end as usize * index) / nbr_iter) as u8 +} + +impl Iterator for Fade { + type Item = Strip; + + fn next(&mut self) -> Option { + let mut strip = Strip::default(); + + if self.current_iteration >= self.nbr_iterations { + return None; + } + + let red = fade_value( + self.begin_color.red, + self.end_color.red, + self.current_iteration, + self.nbr_iterations, + ); + let green = fade_value( + self.begin_color.green, + self.end_color.green, + self.current_iteration, + self.nbr_iterations, + ); + let blue = fade_value( + self.begin_color.blue, + self.end_color.blue, + self.current_iteration, + self.nbr_iterations, + ); + + let current_color = PixelColor { red, green, blue }; + + strip.fill(current_color); + + self.current_iteration += 1; + Some(strip) + } +} diff --git a/src/patterns/fill_random.rs b/src/patterns/fill_random.rs new file mode 100644 index 0000000..7b9b435 --- /dev/null +++ b/src/patterns/fill_random.rs @@ -0,0 +1,52 @@ +use rand::Rng; +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # FillRandom +/// +/// fill strip with color then apply random variation to each pixel +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct FillRandom { + pub(crate) color: PixelColor, + pub(crate) stability: usize, + pub(crate) max_iteration: Option, +} + +impl Iterator for FillRandom { + type Item = Strip; + + fn next(&mut self) -> Option { + if let Some(iteration) = self.max_iteration { + if iteration == 0 { + return None; + } else { + self.max_iteration = Some(iteration - 1); + } + } + + let mut strip = Strip::::default(); + let mut rng = rand::thread_rng(); + for i in 0..N { + let red_delta = rng.gen_range(0..self.stability) as u8; + let green_delta = rng.gen_range(0..self.stability) as u8; + let blue_delta = rng.gen_range(0..self.stability) as u8; + let operation = rng.gen_bool(0.5); + let red; + let green; + let blue; + if operation { + red = self.color.red.saturating_add(red_delta); + green = self.color.green.saturating_add(green_delta); + blue = self.color.blue.saturating_add(blue_delta); + } else { + red = self.color.red.saturating_sub(red_delta); + green = self.color.green.saturating_sub(green_delta); + blue = self.color.blue.saturating_sub(blue_delta); + } + let c = PixelColor { red, green, blue }; + strip[i] = c; + } + Some(strip) + } +} \ No newline at end of file diff --git a/src/patterns/fill_unstable.rs b/src/patterns/fill_unstable.rs new file mode 100644 index 0000000..e23e493 --- /dev/null +++ b/src/patterns/fill_unstable.rs @@ -0,0 +1,49 @@ +use rand::Rng; +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # FillUnstable +/// +/// fill strip with color then apply same random variation to all pixel +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct FillUnstable { + pub(crate) color: PixelColor, + pub(crate) stability: usize, + pub(crate) max_iteration: Option, +} + +impl Iterator for FillUnstable { + type Item = Strip; + + fn next(&mut self) -> Option { + if let Some(iteration) = self.max_iteration { + if iteration == 0 { + return None; + } else { + self.max_iteration = Some(iteration - 1); + } + } + + let mut strip = Strip::::default(); + let mut rng = rand::thread_rng(); + let red_delta = rng.gen_range(0..self.stability) as u8; + let green_delta = rng.gen_range(0..self.stability) as u8; + let blue_delta = rng.gen_range(0..self.stability) as u8; + let operation = rng.gen_bool(0.5); + let red; + let green; + let blue; + if operation { + red = self.color.red.saturating_add(red_delta); + green = self.color.green.saturating_add(green_delta); + blue = self.color.blue.saturating_add(blue_delta); + } else { + red = self.color.red.saturating_sub(red_delta); + green = self.color.green.saturating_sub(green_delta); + blue = self.color.blue.saturating_sub(blue_delta); + } + strip.fill(PixelColor { red, green, blue }); + Some(strip) + } +} \ No newline at end of file diff --git a/src/patterns/rainbow.rs b/src/patterns/rainbow.rs new file mode 100644 index 0000000..6b15ee7 --- /dev/null +++ b/src/patterns/rainbow.rs @@ -0,0 +1,76 @@ +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # Rainbow pattern +/// +/// every pattern implement the iterator trait +/// +/// This pattern display a moving rainbow over the strip +/// +/// ### Note +/// +/// If max iteration is let to None, it's an infinite pattern. +/// +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct Rainbow { + #[serde(default)] + pub(crate) current_iteration: usize, + pub(crate) max_iteration: Option, + pub(crate) step: Option, +} + +impl Iterator for Rainbow { + type Item = Strip; + + fn next(&mut self) -> Option { + if let Some(nbr_iteration) = self.max_iteration { + if nbr_iteration == self.current_iteration { + return None; + } + } + let mut strip = Strip::default(); + let step = self.step.unwrap_or(255 / N); + for i in 0..N { + let pos = (i * step + self.current_iteration) as u8; + strip[i] = wheel(pos) + } + self.current_iteration += 1; + Some(strip) + } +} + +/// compute **rgb** pixel color according to the **hsv** wheel +/// +/// # Arguments +/// +/// * `index`: position in the hsv wheel +/// +/// returns: PixelColor +/// +fn wheel(index: u8) -> PixelColor { + let pos = 255 - index; + match pos { + 0..=85 => PixelColor { + red: 255 - (pos * 3), + green: 0, + blue: pos * 3, + }, + 86..=170 => { + let pos = pos - 85; + PixelColor { + red: 0, + green: pos * 3, + blue: 255 - (pos * 3), + } + } + _ => { + let pos = pos - 170; + PixelColor { + red: pos * 3, + green: 255 - (pos * 3), + blue: 0, + } + } + } +} \ No newline at end of file diff --git a/src/patterns/scanner.rs b/src/patterns/scanner.rs new file mode 100644 index 0000000..1a2809d --- /dev/null +++ b/src/patterns/scanner.rs @@ -0,0 +1,45 @@ +use crate::patterns::PixelColor; +use crate::Strip; +use serde::{Serialize, Deserialize}; + +/// # scanner pattern +/// color one pixel with a color and leave a train of this color fading to black +/// +/// # note +/// +/// background_color work only for color not set by scanner pattern +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct Scanner { + #[serde(default)] + pub(crate) current_iteration: usize, + pub(crate) color: PixelColor, + pub(crate) background_color: Option, +} + +impl Iterator for Scanner { + type Item = Strip; + + fn next(&mut self) -> Option { + let mut strip = Strip::::default(); + if let Some(c) = self.background_color { + strip.fill(c); + } else { + strip.fill(PixelColor::default()); + } + + let current_led = self.current_iteration % N; + let min_led; + if current_led < 8 { + min_led = 0; + } else { + min_led = current_led - 8; + } + let mut c = self.color; + for i in min_led..current_led { + strip[i] = c; + c = c / 2; + } + self.current_iteration += 1; + Some(strip) + } +} \ No newline at end of file diff --git a/src/runner.rs b/src/runner.rs index 2b6fcfd..d08c13f 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -9,9 +9,33 @@ use std::str::FromStr; use std::time::Duration; use tokio::sync::watch::{Receiver, Sender}; +pub(crate) mod period { + use std::time::Duration; + use serde::{de::Error as _, Deserialize, Deserializer}; + + + /// Custom deserializer for period from millisecond value + /// + /// # Arguments + /// + /// * `deserializer`: + /// + /// returns: Result::Error> + /// + pub fn deserialize<'de, D>(deserializer: D) -> Result + where + D: Deserializer<'de>, + { + String::deserialize(deserializer)? + .parse::().and_then(|d| Ok(Duration::from_millis(d))) + .map_err(|e| D::Error::custom(format!("{}", e))) + } +} + #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] pub struct Context { pub(crate) pattern: Patterns, + #[serde(deserialize_with = "period::deserialize")] pub period: Duration, } @@ -42,7 +66,7 @@ pub struct Spectacle { impl Spectacle { pub fn add(&mut self, mac_address: Address, runner: &DeviceSequence) { - if let Some((_, rx)) = self.runners.get(&runner as &DeviceSequence) { + if let Some((_, rx)) = self.runners.get(runner as &DeviceSequence) { self.channels.insert(mac_address, rx.clone()); } else { let (tx, rx) = tokio::sync::watch::channel(Strip::::new(PixelColor { @@ -98,7 +122,7 @@ impl Spectacle { pub fn run(&mut self) -> Vec> { let mut joinhandles = vec![]; - if let Some(_) = &self.default_runner { + if self.default_runner.is_some() { let d = std::mem::take(&mut self.default_runner).unwrap(); joinhandles.push(runner_loop(d.0.clone(), d.1)); println!("add default runner loop");