From 6deb31836f3d0bc6747a9e411b10eaa99abefbcf Mon Sep 17 00:00:00 2001 From: Tobias Ollive Date: Tue, 15 Mar 2022 16:18:29 +0100 Subject: [PATCH] add random stars pattern fix wrong multi devices selection add color section to simplify devices section --- spectacle.yml | 55 +++++++++++------- src/config.rs | 12 +++- src/main.rs | 6 +- src/patterns.rs | 105 +++++++++++++++++++++++----------- src/patterns/blink.rs | 5 +- src/patterns/color_wipe.rs | 25 +------- src/patterns/fade.rs | 4 -- src/patterns/fade_random.rs | 22 +------ src/patterns/fade_unstable.rs | 16 +----- src/patterns/fill_random.rs | 5 +- src/patterns/fill_unstable.rs | 5 +- src/patterns/rain.rs | 21 ++----- src/patterns/rainbow.rs | 5 +- src/patterns/ring.rs | 21 +------ src/patterns/ring_scanner.rs | 21 +------ src/patterns/scanner.rs | 25 +------- src/patterns/stars_random.rs | 85 +++++++++++++++++++++++++++ src/runner.rs | 20 ++----- 18 files changed, 240 insertions(+), 218 deletions(-) create mode 100644 src/patterns/stars_random.rs diff --git a/spectacle.yml b/spectacle.yml index 07accab..9da2d96 100644 --- a/spectacle.yml +++ b/spectacle.yml @@ -1,39 +1,46 @@ +colors: + - &red + red: 255 + green: 0 + blue: 0 + +devices: - name : toto mac_addresses : - C9:81:9C:BA:53:BC sequence: -# - pattern: -# type: Blink -# fade: -# current_iteration: 10 -# nbr_iterations: 20 -# begin_color: &black -# red: 0 -# green: 0 -# blue: 0 -# end_color: &purple -# red: 255 -# green: 0 -# blue: 255 -# max_iteration: 10 -# period: 50 - pattern: type: Rain color: &blue red: 0 green: 0 blue: 255 - background_color: &black + background_color: &yellow red: 0 green: 255 - blue: 0 + blue: 255 stability: 10 lines: 5 period: 200 + - pattern: + type: Blink + fade: + current_iteration: 10 + steps: 20 + begin_color: &black + red: 0 + green: 0 + blue: 0 + end_color: &purple + red: 255 + green: 0 + blue: 255 + max_iteration: 10 + period: 50 - pattern: type: Fade steps: 20 - begin_color: &red + begin_color: red: 255 green: 0 blue: 0 @@ -55,11 +62,15 @@ - name: titi sequence: - pattern: - type: RingScanner + type: StarsRandom color: *green - ring_size: 4 - max_iteration : 50 - period: 100 + ratio: 8 + steps: 20 + background_color: + red: 0 + green: 255 + blue: 100 + period: 50 - pattern: type: Rainbow max_iteration: 200 diff --git a/src/config.rs b/src/config.rs index a4071b9..e962e4d 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,15 @@ +use crate::patterns::PixelColor; use crate::runner::DeviceSequence; use serde_derive::{Deserialize, Serialize}; use std::collections::HashSet; use std::fs; -pub(crate) type Config = Vec>; + +#[derive(Serialize, Deserialize)] +pub struct Config { + devices: Vec>, + colors: Vec, +} #[derive(Deserialize, Serialize)] pub struct Device { @@ -12,8 +18,8 @@ pub struct Device { pub sequence: DeviceSequence, } -pub fn load_from_file(file: &std::path::Path) -> Config { +pub fn load_from_file(file: &std::path::Path) -> Vec> { let file = fs::read_to_string(file).unwrap(); let config: Config = serde_yaml::from_str(&*file).unwrap(); - config + config.devices } diff --git a/src/main.rs b/src/main.rs index 2d67df6..98618f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,10 +6,9 @@ mod patterns; mod runner; mod spectacle; -use pattern_derive; use crate::args::Cli; use crate::audio::play_sound; -use crate::config::{load_from_file, Config}; +use crate::config::load_from_file; use crate::runner::Spectacle; use bluer::gatt::remote::Characteristic; use bluer::{Device, Error}; @@ -30,7 +29,7 @@ async fn main() -> bluer::Result<()> { let command_line = Cli::parse(); let file = Path::new(&command_line.spectacle_file); - let config: Config<25> = load_from_file(file); + let config = load_from_file(file); let spectacle = Spectacle::from(config); let spectacle = Arc::new(Mutex::new(spectacle)); @@ -87,7 +86,6 @@ async fn connect_device( }; } println!("device {} disconnected", &device.address()); - // drop(rx_device); }); } } diff --git a/src/patterns.rs b/src/patterns.rs index f44f0e8..cf3e76b 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -10,6 +10,7 @@ mod rainbow; mod ring; mod ring_scanner; mod scanner; +mod stars_random; use crate::patterns::blink::Blink; use crate::patterns::color_wipe::ColorWipe; @@ -23,11 +24,12 @@ use crate::patterns::rainbow::Rainbow; use crate::patterns::ring::Ring; use crate::patterns::ring_scanner::RingScanner; use crate::patterns::scanner::Scanner; +use crate::patterns::stars_random::StarsRandom; use rand::rngs::ThreadRng; use rand::Rng; use serde_derive::{Deserialize, Serialize}; use std::fmt; -use std::ops::{AddAssign, Div, Index, IndexMut, SubAssign}; +use std::ops::{Add, AddAssign, Div, Index, IndexMut, Sub, SubAssign}; #[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] #[serde(tag = "type")] @@ -44,6 +46,7 @@ pub(crate) enum Patterns { FadeUnstable(FadeUnstable), Ring(Ring), RingScanner(RingScanner), + StarsRandom(StarsRandom), } pub trait Pattern: Iterator { @@ -52,31 +55,38 @@ pub trait Pattern: Iterator { fn init(&mut self) -> Option { None } - fn is_last_iteration(&self) -> bool ; + fn is_last_iteration(&self) -> bool; } #[macro_export] -macro_rules! impl_pattern_none { - ($name:ty, $generic: tt) => { - type Strip = Strip; - - fn init(&mut self) -> Option { +macro_rules! impl_pattern_init_background { + ($generic: tt) => { + fn init(&mut self) -> Option { + if let Some(color) = self.background_color { + Some(Strip::::new(color)) + } else { None } + } + }; +} - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } +#[macro_export] +macro_rules! impl_pattern_last_iteration { + ($name:ty) => { + fn is_last_iteration(&self) -> bool { + match self.max_iteration { + None => false, + Some(max_iter) => { + if self.current_iteration >= max_iter { + true + } else { + false } } } } + }; } impl Iterator for Patterns { @@ -96,6 +106,7 @@ impl Iterator for Patterns { Patterns::FadeUnstable(p) => p.next(), Patterns::Ring(p) => p.next(), Patterns::RingScanner(p) => p.next(), + Patterns::StarsRandom(p) => p.next(), } } } @@ -117,6 +128,7 @@ impl Pattern for Patterns { Patterns::FadeUnstable(p) => p.init(), Patterns::Ring(p) => p.init(), Patterns::RingScanner(p) => p.init(), + Patterns::StarsRandom(p) => p.init(), } } @@ -134,6 +146,7 @@ impl Pattern for Patterns { Patterns::FadeUnstable(p) => p.is_last_iteration(), Patterns::Ring(p) => p.is_last_iteration(), Patterns::RingScanner(p) => p.is_last_iteration(), + Patterns::StarsRandom(p) => p.is_last_iteration(), } } } @@ -165,6 +178,30 @@ impl Div for PixelColor { } } +impl Add for PixelColor { + type Output = Self; + + fn add(self, rhs: Self) -> Self::Output { + PixelColor { + red: self.red.saturating_add(rhs.red), + green: self.green.saturating_add(rhs.green), + blue: self.blue.saturating_add(rhs.blue), + } + } +} + +impl Sub for PixelColor { + type Output = Self; + + fn sub(self, rhs: u8) -> Self::Output { + PixelColor { + red: self.red.saturating_sub(rhs), + green: self.green.saturating_sub(rhs), + blue: self.blue.saturating_sub(rhs), + } + } +} + impl SubAssign for PixelColor { fn sub_assign(&mut self, rhs: Self) { self.red = self.red.saturating_sub(rhs.red); @@ -192,23 +229,27 @@ impl PixelColor { /// returns: PixelColor /// pub fn random_delta(&self, stability: usize, rng: &mut ThreadRng) -> PixelColor { - let red_delta = rng.gen_range(0..stability) as u8; - let green_delta = rng.gen_range(0..stability) as u8; - let blue_delta = rng.gen_range(0..stability) as u8; - let operation = rng.gen_bool(0.5); - let red; - let green; - let blue; - if operation { - red = self.red.saturating_add(red_delta); - green = self.green.saturating_add(green_delta); - blue = self.blue.saturating_add(blue_delta); - } else { - red = self.red.saturating_sub(red_delta); - green = self.green.saturating_sub(green_delta); - blue = self.blue.saturating_sub(blue_delta); + let minus_interval = -(stability as i8); + let max_interval = stability as i8; + let red_delta = rng.gen_range(minus_interval..max_interval) as i8; + let green_delta = rng.gen_range(minus_interval..max_interval) as i8; + let blue_delta = rng.gen_range(minus_interval..max_interval) as i8; + self.delta((red_delta, green_delta, blue_delta)) + } + + pub fn delta(&self, delta: (i8, i8, i8)) -> PixelColor { + let (red, green, blue) = delta; + PixelColor { + red: (self.red as i16 + red as i16) as u8, + green: (self.green as i16 + green as i16) as u8, + blue: (self.blue as i16 + blue as i16) as u8, } - PixelColor { red, green, blue } + } + + pub fn is_closer(&self, pixel: PixelColor, distance: PixelColor) -> bool { + (self.red as i16 - pixel.red as i16).abs() <= distance.red as i16 + && (self.green as i16 - pixel.green as i16).abs() <= distance.green as i16 + && (self.blue as i16 - pixel.blue as i16).abs() <= distance.blue as i16 } } diff --git a/src/patterns/blink.rs b/src/patterns/blink.rs index 06332bb..9b16fc3 100644 --- a/src/patterns/blink.rs +++ b/src/patterns/blink.rs @@ -1,6 +1,6 @@ use crate::patterns::fade::Fade; use crate::patterns::Pattern; -use crate::{impl_pattern_none, Strip}; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # Blink @@ -15,7 +15,8 @@ pub struct Blink { } impl Pattern for Blink { - impl_pattern_none!(FadeRandom, N); + type Strip = Strip; + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for Blink { diff --git a/src/patterns/color_wipe.rs b/src/patterns/color_wipe.rs index 05e5e63..279c050 100644 --- a/src/patterns/color_wipe.rs +++ b/src/patterns/color_wipe.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::Strip; +use crate::{impl_pattern_init_background, impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # Colorwipe pattern @@ -22,27 +22,8 @@ pub struct ColorWipe { impl Pattern for ColorWipe { type Strip = Strip; - - fn init(&mut self) -> Option { - if let Some(color) = self.background_color { - Some(Strip::::new(color)) - } else { - None - } - } - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_init_background!(N); + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for ColorWipe { diff --git a/src/patterns/fade.rs b/src/patterns/fade.rs index ddc8371..b928697 100644 --- a/src/patterns/fade.rs +++ b/src/patterns/fade.rs @@ -20,10 +20,6 @@ fn fade_value(value_start: u8, value_end: u8, index: usize, nbr_iter: usize) -> impl Pattern for Fade { type Strip = Strip; - fn init(&mut self) -> Option { - None - } - fn is_last_iteration(&self) -> bool { self.current_iteration >= self.steps } diff --git a/src/patterns/fade_random.rs b/src/patterns/fade_random.rs index a896e3b..33badd5 100644 --- a/src/patterns/fade_random.rs +++ b/src/patterns/fade_random.rs @@ -1,6 +1,6 @@ use crate::patterns::fade::Fade; use crate::patterns::Pattern; -use crate::{impl_pattern_none, Strip}; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # FadeRandom @@ -16,25 +16,9 @@ pub struct FadeRandom { } impl Pattern for FadeRandom { - impl_pattern_none!(FadeRandom, N); + type Strip = Strip; + impl_pattern_last_iteration!(ColorWipe); } -// -// impl Pattern for FadeRandom { -// type Strip = Strip; -// -// fn is_last_iteration(&self) -> bool { -// match self.max_iteration { -// None => false, -// Some(max_iter) => { -// if self.current_iteration >= max_iter { -// true -// } else { -// false -// } -// } -// } -// } -// } impl Iterator for FadeRandom { type Item = Strip; diff --git a/src/patterns/fade_unstable.rs b/src/patterns/fade_unstable.rs index fbf2166..6761cef 100644 --- a/src/patterns/fade_unstable.rs +++ b/src/patterns/fade_unstable.rs @@ -1,6 +1,6 @@ use crate::patterns::fade::Fade; use crate::patterns::Pattern; -use crate::Strip; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # FadeUnstable @@ -17,19 +17,7 @@ pub struct FadeUnstable { impl Pattern for FadeUnstable { type Strip = Strip; - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for FadeUnstable { diff --git a/src/patterns/fill_random.rs b/src/patterns/fill_random.rs index a294428..f159a9d 100644 --- a/src/patterns/fill_random.rs +++ b/src/patterns/fill_random.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::{impl_pattern_none, Strip}; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # FillRandom @@ -15,7 +15,8 @@ pub struct FillRandom { } impl Pattern for FillRandom { - impl_pattern_none!(FadeRandom, N); + type Strip = Strip; + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for FillRandom { diff --git a/src/patterns/fill_unstable.rs b/src/patterns/fill_unstable.rs index 6271628..1b77fe6 100644 --- a/src/patterns/fill_unstable.rs +++ b/src/patterns/fill_unstable.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::{impl_pattern_none, Strip}; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # FillUnstable @@ -15,7 +15,8 @@ pub struct FillUnstable { } impl Pattern for FillUnstable { - impl_pattern_none!(FadeRandom, N); + type Strip = Strip; + impl_pattern_last_iteration!(FillUnstable); } impl Iterator for FillUnstable { diff --git a/src/patterns/rain.rs b/src/patterns/rain.rs index 973fb4d..e564906 100644 --- a/src/patterns/rain.rs +++ b/src/patterns/rain.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::Strip; +use crate::{impl_pattern_last_iteration, Strip}; use rand::Rng; use serde::{Deserialize, Serialize}; @@ -28,28 +28,15 @@ pub struct Rain { impl Pattern for Rain { type Strip = Strip; - fn init(&mut self) -> Option { if let Some(color) = self.background_color { self.drops = Strip::::new(color); - Some(Strip::::new(color)) + Some(self.drops) } else { None } } - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_last_iteration!(ColorRain); } impl Iterator for Rain { @@ -68,7 +55,7 @@ impl Iterator for Rain { } else { let c = strip[i + self.lines]; if self.background_color != c && c != Some(PixelColor::default()) { - strip[i] = Some(strip[i + self.lines].unwrap() / 2); + strip[i] = Some(c.unwrap() / 2); } else { strip[i] = self.background_color; } diff --git a/src/patterns/rainbow.rs b/src/patterns/rainbow.rs index 8e29973..d3bec86 100644 --- a/src/patterns/rainbow.rs +++ b/src/patterns/rainbow.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::{impl_pattern_none, Strip}; +use crate::{impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # Rainbow pattern @@ -21,7 +21,8 @@ pub struct Rainbow { } impl Pattern for Rainbow { - impl_pattern_none!(FadeRandom, N); + type Strip = Strip; + impl_pattern_last_iteration!(Rainbow); } impl Iterator for Rainbow { diff --git a/src/patterns/ring.rs b/src/patterns/ring.rs index b07a943..d8b58cb 100644 --- a/src/patterns/ring.rs +++ b/src/patterns/ring.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::Strip; +use crate::{impl_pattern_init_background, impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # Ring @@ -17,23 +17,8 @@ pub struct Ring { impl Pattern for Ring { type Strip = Strip; - - fn init(&mut self) -> Option { - None - } //FIXME - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_init_background!(N); + impl_pattern_last_iteration!(Ring); } impl Iterator for Ring { diff --git a/src/patterns/ring_scanner.rs b/src/patterns/ring_scanner.rs index 110f34c..f533413 100644 --- a/src/patterns/ring_scanner.rs +++ b/src/patterns/ring_scanner.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::Strip; +use crate::{impl_pattern_init_background, impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # RingScanner @@ -17,23 +17,8 @@ pub struct RingScanner { impl Pattern for RingScanner { type Strip = Strip; - - fn init(&mut self) -> Option { - None - } //FIXME - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_init_background!(N); + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for RingScanner { diff --git a/src/patterns/scanner.rs b/src/patterns/scanner.rs index 00789dc..cbf72cd 100644 --- a/src/patterns/scanner.rs +++ b/src/patterns/scanner.rs @@ -1,5 +1,5 @@ use crate::patterns::{Pattern, PixelColor}; -use crate::Strip; +use crate::{impl_pattern_init_background, impl_pattern_last_iteration, Strip}; use serde::{Deserialize, Serialize}; /// # scanner pattern @@ -20,27 +20,8 @@ pub struct Scanner { impl Pattern for Scanner { type Strip = Strip; - - fn init(&mut self) -> Option { - if let Some(color) = self.background_color { - Some(Strip::::new(color)) - } else { - None - } - } - - fn is_last_iteration(&self) -> bool { - match self.max_iteration { - None => false, - Some(max_iter) => { - if self.current_iteration >= max_iter { - true - } else { - false - } - } - } - } + impl_pattern_init_background!(N); + impl_pattern_last_iteration!(ColorWipe); } impl Iterator for Scanner { diff --git a/src/patterns/stars_random.rs b/src/patterns/stars_random.rs new file mode 100644 index 0000000..30c4f30 --- /dev/null +++ b/src/patterns/stars_random.rs @@ -0,0 +1,85 @@ +use crate::patterns::{Pattern, PixelColor}; +use crate::{impl_pattern_last_iteration, Strip}; +use rand::Rng; +use serde::{Deserialize, Serialize}; + +/// # StarsRandom +/// +/// fill strip with background color then color random pixel with other color fading to background color +#[derive(Serialize, Deserialize, Debug, Eq, Hash, PartialEq, Copy, Clone)] +pub struct StarsRandom { + pub(crate) color: PixelColor, + pub(crate) ratio: usize, + pub(crate) max_iteration: Option, + pub(crate) background_color: Option, + pub(crate) steps: usize, + #[serde(default)] + pub(crate) current_iteration: usize, + #[serde(skip)] + strip: Strip, + #[serde(skip)] + step: (i8, i8, i8), +} + +impl Pattern for StarsRandom { + type Strip = Strip; + fn init(&mut self) -> Option { + if let Some(color) = self.background_color { + self.strip = Strip::::new(color); + let red = (self.color.red as i16 - color.red as i16) as i8; + let green = (color.green as i16 - self.color.green as i16) as i8; + let blue = (self.color.blue as i16 - color.blue as i16) as i8; + println!("{} {} {}", red, green, blue); + self.step = ( + red / self.steps as i8, + green / self.steps as i8, + blue / self.steps as i8, + ); + Some(self.strip) + } else { + self.step = ( + -((self.color.red / self.steps as u8) as i8), + -((self.color.green / self.steps as u8) as i8), + -((self.color.blue / self.steps as u8) as i8), + ); + None + } + } + impl_pattern_last_iteration!(StarsRandom); +} + +impl Iterator for StarsRandom { + type Item = Strip; + + fn next(&mut self) -> Option { + if self.is_last_iteration() { + return None; + } + + let mut rng = rand::thread_rng(); + for i in 0..N { + let current_color = self.strip[i]; + if current_color == self.background_color { + if rng.gen_bool(1.0 / self.ratio as f64) { + self.strip[i] = Some(self.color); + } + } else { + let color = current_color.unwrap(); + let background = self.background_color.unwrap_or(PixelColor::default()); + let distance = PixelColor { + red: self.step.0.abs() as u8, + green: self.step.1.abs() as u8, + blue: self.step.2.abs() as u8, + }; + if color.is_closer(background, distance) { + self.strip[i] = self.background_color; + } else { + self.strip[i] = Some(color.delta(self.step)); + } + } + } + + self.current_iteration += 1; + Some(self.strip) + } +} diff --git a/src/runner.rs b/src/runner.rs index a714f2b..2db4758 100644 --- a/src/runner.rs +++ b/src/runner.rs @@ -1,4 +1,4 @@ -use crate::config::Config; +use crate::config::Device; use crate::patterns::{Pattern, Patterns, PixelColor}; use crate::Strip; use bluer::Address; @@ -90,7 +90,7 @@ impl Spectacle { blue: 0, })); self.runners.insert(runner.clone(), (tx, rx.clone())); - self.channels.insert(mac_address, rx); + self.channels.insert(mac_address, rx.clone()); } } @@ -100,20 +100,10 @@ impl Spectacle { green: 0, blue: 255, })); - // self.tasks.push(runner.runner_loop(tx)); self.default_runner = Some((runner, tx)); self.default_receiver = Some(rx); } - // pub fn nbr_tasks(&self) -> usize { - // let mut nbr = 0; - // if self.default_receiver.is_some() { - // nbr += 1; - // } - // nbr += self.runners.len(); - // nbr - // } - pub fn get_channel(&self, mac_address: &Address) -> Option>> { let channel = self.channels.get(mac_address); match channel { @@ -143,7 +133,7 @@ impl Spectacle { println!("add default runner loop"); } - for (runner, (tx, _)) in self.runners.drain().take(1) { + for (runner, (tx, _)) in self.runners.drain().into_iter() { joinhandles.push(runner_loop(runner.clone(), tx)); println!("add custom runner loop"); } @@ -151,8 +141,8 @@ impl Spectacle { } } -impl From> for Spectacle { - fn from(config: Config) -> Self { +impl From>> for Spectacle { + fn from(config: Vec>) -> Self { let mut spectacle: Spectacle = Spectacle::default(); for device in config { if let Some(mac_addresses) = device.mac_addresses {