From 7a87748cf1ae50d54e3d7ef70985b9b1e417057b Mon Sep 17 00:00:00 2001 From: Ivan Li Date: Fri, 28 Apr 2023 00:26:49 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E4=BD=BF=E7=94=A8=20UDP=20=E5=8F=91?= =?UTF-8?q?=E9=80=81=E9=A2=9C=E8=89=B2=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src-tauri/src/ambient_light/publisher.rs | 129 +++++++++++++++++------ src-tauri/src/led_color.rs | 32 +++--- src-tauri/src/main.rs | 4 +- 3 files changed, 114 insertions(+), 51 deletions(-) diff --git a/src-tauri/src/ambient_light/publisher.rs b/src-tauri/src/ambient_light/publisher.rs index a3ad013..6a66e4a 100644 --- a/src-tauri/src/ambient_light/publisher.rs +++ b/src-tauri/src/ambient_light/publisher.rs @@ -1,8 +1,9 @@ -use std::{collections::HashMap, sync::Arc, time::Duration}; +use std::{borrow::Borrow, collections::HashMap, io::Read, sync::Arc, time::Duration}; use paris::warn; use tauri::async_runtime::RwLock; use tokio::{ + net::UdpSocket, sync::{broadcast, watch}, time::sleep, }; @@ -52,6 +53,7 @@ impl LedColorsPublisher { display_id: u32, sample_points: Vec>, bound_scale_factor: f32, + mappers: Vec, display_colors_tx: broadcast::Sender<(u32, Vec)>, ) { let internal_tasks_version = self.inner_tasks_version.clone(); @@ -99,9 +101,50 @@ impl LedColorsPublisher { continue; } - let colors = colors.unwrap(); + let colors: Vec = colors.unwrap(); // let color_len = colors.len(); + let display_led_offset = mappers + .clone() + .iter() + .flat_map(|mapper| [mapper.start, mapper.end]) + .min() + .unwrap(); + + for group in mappers.clone() { + if (group.start.abs_diff(group.end)) > colors.len() { + warn!( + "get_sorted_colors: color_index out of range. color_index: {}, strip len: {}, colors.len(): {}", + group.pos, + group.start.abs_diff(group.end), + colors.len() + ); + return; + } + + let group_size = group.start.abs_diff(group.end); + let mut buffer = Vec::::with_capacity(group_size * 3); + + if group.end > group.start { + for i in group.pos-display_led_offset..group_size + group.pos-display_led_offset { + let bytes = colors[i].as_bytes(); + buffer.append(&mut bytes.to_vec()); + } + } else { + for i in (group.pos-display_led_offset..group_size + group.pos-display_led_offset).rev() { + let bytes = colors[i].as_bytes(); + buffer.append(&mut bytes.to_vec()); + } + } + match Self::send_colors((group.start.min(group.end)) as u16, buffer).await { + Ok(_) => {} + Err(err) => { + warn!("Failed to send colors: {}", err); + } + }; + } + + log::info!("sent colors: #{: >15} {:?}", display_id, colors.len()); match display_colors_tx.send(( display_id, @@ -232,11 +275,11 @@ impl LedColorsPublisher { let display_id = sample_point_group.display_id; let sample_points = sample_point_group.points; let bound_scale_factor = sample_point_group.bound_scale_factor; - publisher.start_one_display_colors_fetcher( display_id, sample_points, bound_scale_factor, + sample_point_group.mappers, display_colors_tx.clone(), ); } @@ -250,33 +293,40 @@ impl LedColorsPublisher { } }); - let rx = self.sorted_colors_rx.clone(); - tokio::spawn(async move { - let mut rx = rx.read().await.clone(); - loop { - if let Err(err) = rx.changed().await { - warn!("rx changed error: {}", err); - sleep(Duration::from_millis(1000)).await; - continue; - } + // let rx = self.sorted_colors_rx.clone(); + // tokio::spawn(async move { + // let mut rx = rx.read().await.clone(); + // loop { + // if let Err(err) = rx.changed().await { + // warn!("rx changed error: {}", err); + // sleep(Duration::from_millis(1000)).await; + // continue; + // } - let colors = rx.borrow().clone(); + // let colors = rx.borrow().clone(); - match Self::send_colors(colors).await { - Ok(_) => { - } - Err(err) => { - warn!("colors send failed: {}", err); - } - } - } - }); + // match Self::send_colors(colors).await { + // Ok(_) => {} + // Err(err) => { + // warn!("colors send failed: {}", err); + // } + // } + // } + // }); } - pub async fn send_colors(payload: Vec) -> anyhow::Result<()> { - let mqtt = MqttRpc::global().await; + pub async fn send_colors(offset: u16, mut payload: Vec) -> anyhow::Result<()> { + // let mqtt = MqttRpc::global().await; - mqtt.publish_led_sub_pixels(payload).await + // mqtt.publish_led_sub_pixels(payload).await; + + let socket = UdpSocket::bind("0.0.0.0:8000").await?; + let mut buffer = vec![2]; + buffer.push((offset >> 8) as u8); + buffer.push((offset & 0xff) as u8); + buffer.append(&mut payload); + socket.send_to(&buffer, "192.168.31.206:23042").await?; + Ok(()) } pub async fn clone_sorted_colors_receiver(&self) -> watch::Receiver> { @@ -326,35 +376,43 @@ impl LedColorsPublisher { screenshots.insert(screenshot.display_id, screenshot); if screenshots.len() == display_ids.len() { + let mut led_start = 0; + for display_id in display_ids { - let led_strip_configs: Vec<_> = configs + let led_strip_configs = configs .strips .iter() - .filter(|c| c.display_id == display_id) - .collect(); - - if led_strip_configs.len() == 0 { - warn!("no led strip config for display_id: {}", display_id); - continue; - } + .enumerate() + .filter(|(_, c)| c.display_id == display_id); let screenshot = screenshots.get(&display_id).unwrap(); log::debug!("screenshot updated: {:?}", display_id); let points: Vec<_> = led_strip_configs - .iter() - .map(|config| screenshot.get_sample_points(&config)) + .clone() + .map(|(_, config)| screenshot.get_sample_points(&config)) .collect(); + if points.len() == 0 { + warn!("no led strip config for display_id: {}", display_id); + continue; + } + let bound_scale_factor = screenshot.bound_scale_factor; + let led_end = led_start + points.iter().map(|p| p.len()).sum::(); + + let mappers = led_strip_configs.map(|(i, _)| mappers[i].clone()).collect(); + let colors_config = DisplaySamplePointGroup { display_id, points, bound_scale_factor, + mappers, }; colors_configs.push(colors_config); + led_start = led_end; } log::debug!("got all colors configs: {:?}", colors_configs.len()); @@ -384,4 +442,5 @@ pub struct DisplaySamplePointGroup { pub display_id: u32, pub points: Vec>, pub bound_scale_factor: f32, + pub mappers: Vec, } diff --git a/src-tauri/src/led_color.rs b/src-tauri/src/led_color.rs index 98c371c..539f4d7 100644 --- a/src-tauri/src/led_color.rs +++ b/src-tauri/src/led_color.rs @@ -1,46 +1,50 @@ +use std::ops::Index; + use color_space::{Hsv, Rgb}; use serde::Serialize; #[derive(Clone, Copy, Debug)] -pub struct LedColor { - bits: [u8; 3], -} +pub struct LedColor([u8; 3]); impl LedColor { pub fn default() -> Self { - Self { bits: [0, 0, 0] } + Self ([0, 0, 0] ) } pub fn new(r: u8, g: u8, b: u8) -> Self { - Self { bits: [r, g, b] } + Self ([r, g, b]) } pub fn from_hsv(h: f64, s: f64, v: f64) -> Self { let rgb = Rgb::from(Hsv::new(h, s, v)); - Self { bits: [rgb.r as u8, rgb.g as u8, rgb.b as u8] } + Self ([rgb.r as u8, rgb.g as u8, rgb.b as u8]) } pub fn get_rgb(&self) -> [u8; 3] { - self.bits + self.0 } pub fn is_empty(&self) -> bool { - self.bits.iter().any(|bit| *bit == 0) + self.0.iter().any(|bit| *bit == 0) } pub fn set_rgb(&mut self, r: u8, g: u8, b: u8) -> &Self { - self.bits = [r, g, b]; + self.0 = [r, g, b]; self } pub fn merge(&mut self, r: u8, g: u8, b: u8) -> &Self { - self.bits = [ - (self.bits[0] / 2 + r / 2), - (self.bits[1] / 2 + g / 2), - (self.bits[2] / 2 + b / 2), + self.0 = [ + (self.0[0] / 2 + r / 2), + (self.0[1] / 2 + g / 2), + (self.0[2] / 2 + b / 2), ]; self } + + pub fn as_bytes (&self) -> [u8; 3] { + self.0 + } } impl Serialize for LedColor { @@ -48,7 +52,7 @@ impl Serialize for LedColor { where S: serde::Serializer, { - let hex = format!("#{}", hex::encode(self.bits)); + let hex = format!("#{}", hex::encode(self.0)); serializer.serialize_str(hex.as_str()) } } diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index 2ea43f9..3dd78b7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -132,8 +132,8 @@ async fn patch_led_strip_len(display_id: u32, border: Border, delta_len: i8) -> } #[tauri::command] -async fn send_colors(buffer: Vec) -> Result<(), String> { - ambient_light::LedColorsPublisher::send_colors(buffer) +async fn send_colors(offset: u16, buffer: Vec) -> Result<(), String> { + ambient_light::LedColorsPublisher::send_colors(offset, buffer) .await .map_err(|e| { error!("can not send colors: {}", e);