From 3996e1b09ffe76e36ea7c30e0bc3efd5774f4b4e Mon Sep 17 00:00:00 2001 From: Tobias Ollive Date: Wed, 23 Feb 2022 13:40:56 +0100 Subject: [PATCH] add hotreplug function for devices --- src/bluetooth.rs | 17 ++++++++-- src/main.rs | 83 +++++++++++++++++++++++++++--------------------- src/patterns.rs | 47 ++++++++++++++++----------- 3 files changed, 89 insertions(+), 58 deletions(-) diff --git a/src/bluetooth.rs b/src/bluetooth.rs index e098437..d6fb4b2 100644 --- a/src/bluetooth.rs +++ b/src/bluetooth.rs @@ -27,13 +27,19 @@ async fn has_service(device: &Device, uuid: &Uuid) -> Result { Ok(false) } -async fn bluetooth_scan(tx: mpsc::Sender, adapter: Adapter, uuid: Uuid) -> Result<()> { +pub(crate) async fn bluetooth_scan( + tx: mpsc::Sender, + adapter: Adapter, + uuid: Uuid, +) -> Result<()> { println!("start bluetooth scan"); let discover = adapter.discover_devices().await?; let mut already_scanned: HashSet
= HashSet::new(); pin_mut!(discover); while let Some(evt) = discover.next().await { - if let AdapterEvent::DeviceAdded(addr) = evt { + match evt { + AdapterEvent::DeviceAdded(addr) => { + println!("new device {}", addr); if already_scanned.contains(&addr) { continue; } @@ -49,6 +55,13 @@ async fn bluetooth_scan(tx: mpsc::Sender, adapter: Adapter, uuid: Uuid) Err(_) => continue, } } + AdapterEvent::DeviceRemoved(addr) => { + already_scanned.remove(&addr); + adapter.remove_device(addr).await; + println!("device {} removed", addr); + } + AdapterEvent::PropertyChanged(_) => {} + } } Ok(()) } diff --git a/src/main.rs b/src/main.rs index c07107f..f5c2d44 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,8 +4,8 @@ mod patterns; use crate::patterns::{ColorWipe, Fade, PixelColor, Rainbow}; use bluer::gatt::remote::Characteristic; use patterns::Strip; -use std::convert::TryFrom; use std::time::Duration; +use tokio::sync::mpsc; use tokio::sync::watch; const SERVICE_UUID: bluer::Uuid = bluer::Uuid::from_u128(0xadaf0900c33242a893bd25e905756cb8); @@ -17,10 +17,39 @@ const BASE_STRIP_DATA: [u8; 3] = [0x00, 0x00, 0x01]; async fn main() -> bluer::Result<()> { let adapter = bluetooth::create_session().await?; - let devices = bluetooth::scan_devices(adapter, SERVICE_UUID).await; + let (tx_scan, mut rx_scan) = mpsc::channel(3); + + tokio::spawn(bluetooth::bluetooth_scan( + tx_scan, + adapter.clone(), + SERVICE_UUID, + )); + + let (tx, rx) = watch::channel(Strip::::default()); + + tokio::spawn(async move { + while let Some(device) = rx_scan.recv().await { + bluetooth::connect(&device, 3).await?; + let char = bluetooth::get_char(&device, SERVICE_UUID, PIXEL_DATA_UUID).await?; + if let Some(char) = char { + let mut rx_device = rx.clone(); + tokio::spawn(async move { + println!("device connected : {}", &device.address()); + while rx_device.changed().await.is_ok() { + let strip = *rx_device.borrow(); + if write_strip(&strip, &char).await.is_err() { + break; + }; + } + println!("device {} disconnected", &device.address()); + // drop(rx_device); + }); + } + } + bluer::Result::Ok(()) + }); let mut pixels = Vec::::new(); - for _ in 0..STRIP_SIZE { pixels.push(PixelColor { red: 255, @@ -29,73 +58,53 @@ async fn main() -> bluer::Result<()> { }) } - // let strip = Strip:: { - // strip: <[PixelColor; 25]>::try_from(pixels).unwrap(), - // }; - - let (tx, rx) = watch::channel(Strip::::default()); - - for device in devices { - bluetooth::connect(&device, 3).await?; - let char = bluetooth::get_char(&device, SERVICE_UUID, PIXEL_DATA_UUID).await?; - if let Some(char) = char { - let mut rx_device = rx.clone(); - tokio::spawn(async move { - println!("device connected : {}", &device.address()); - while rx_device.changed().await.is_ok() { - let strip = *rx_device.borrow(); - write_strip(&strip, &char).await.unwrap(); - } - }); - } - } - - let mut colorwipe = ColorWipe::<25>{ + let mut _colorwipe = ColorWipe::<25> { current_iteration: 0, color: PixelColor { red: 0, green: 255, - blue: 0 + blue: 0, }, - infinite: true + infinite: true, }; - let mut fade = Fade::<25> { current_iteration: 0, nbr_iterations: 25, begin_color: PixelColor { red: 255, green: 0, - blue: 0 + blue: 0, }, end_color: PixelColor { red: 0, green: 0, - blue: 255 + blue: 255, }, }; - let mut pattern = Rainbow::<25>{ + let mut pattern = Rainbow::<25> { current_iteration: 0, max_iteration: None, step: Some(10), }; let mut strip = fade.next().unwrap(); - - while tx.send(strip).is_ok() { + tokio::time::sleep(Duration::from_secs(5)).await; + println!("starting"); + while tx.send(strip).is_ok() { if let Some(value) = fade.next() { strip = value; } else { break; } - tokio::time::sleep(Duration::from_millis(200)).await; + tokio::time::sleep(Duration::from_millis(1000)).await; } - - while tx.send(pattern.next().unwrap()).is_ok() { - tokio::time::sleep(Duration::from_millis(10)).await; + println!("starting rainbow"); + while tx.send(pattern.next().unwrap()).is_ok() { + tokio::time::sleep(Duration::from_millis(100)).await; } + println!("error sending value"); Ok(()) } diff --git a/src/patterns.rs b/src/patterns.rs index 159853b..8392fae 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -69,7 +69,7 @@ impl Iterator for Rainbow { } } let mut strip = Strip::default(); - let step = self.step.unwrap_or( 255 / N ); + let step = self.step.unwrap_or(255 / N); for i in 0..N { let pos = (i * step + self.current_iteration) as u8; strip.strip[i] = wheel(pos) @@ -106,15 +106,14 @@ fn wheel(index: u8) -> PixelColor { } } - ////////////////////////////////////////////////////////////////////////// /// Colorwipe pattern //////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////// -pub struct ColorWipe { +pub struct ColorWipe { pub(crate) current_iteration: usize, - pub (crate) color: PixelColor, - pub (crate) infinite: bool, + pub(crate) color: PixelColor, + pub(crate) infinite: bool, } impl Iterator for ColorWipe { @@ -125,10 +124,9 @@ impl Iterator for ColorWipe { if self.infinite { self.current_iteration %= N; } else if self.current_iteration >= N { - return None; + return None; } - for i in 0..self.current_iteration { strip.strip[i] = self.color; } @@ -148,8 +146,8 @@ pub struct Fade { pub(crate) end_color: PixelColor, } -fn fadeValue(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 +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 { @@ -159,22 +157,33 @@ impl Iterator for Fade { let mut strip = Strip::default(); if self.current_iteration >= self.nbr_iterations { - return None; + return None; } - let red = fadeValue(self.begin_color.red, self.end_color.red, self.current_iteration, self.nbr_iterations); - let green = fadeValue(self.begin_color.green, self.end_color.green, self.current_iteration, self.nbr_iterations); - let blue = fadeValue(self.begin_color.blue, self.end_color.blue, self.current_iteration, self.nbr_iterations); + 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 - }; + let current_color = PixelColor { red, green, blue }; strip.fill(current_color); self.current_iteration += 1; Some(strip) } -} \ No newline at end of file +}