feat: 使用 UDP 发送颜色。

This commit is contained in:
Ivan Li 2023-04-28 00:26:49 +08:00
parent 9d11abfa6e
commit 7a87748cf1
3 changed files with 114 additions and 51 deletions

View File

@ -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<Vec<LedSamplePoints>>,
bound_scale_factor: f32,
mappers: Vec<SamplePointMapper>,
display_colors_tx: broadcast::Sender<(u32, Vec<u8>)>,
) {
let internal_tasks_version = self.inner_tasks_version.clone();
@ -99,9 +101,50 @@ impl LedColorsPublisher {
continue;
}
let colors = colors.unwrap();
let colors: Vec<crate::led_color::LedColor> = 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::<u8>::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<u8>) -> anyhow::Result<()> {
let mqtt = MqttRpc::global().await;
pub async fn send_colors(offset: u16, mut payload: Vec<u8>) -> 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<Vec<u8>> {
@ -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::<usize>();
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<Vec<LedSamplePoints>>,
pub bound_scale_factor: f32,
pub mappers: Vec<config::SamplePointMapper>,
}

View File

@ -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())
}
}

View File

@ -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<u8>) -> Result<(), String> {
ambient_light::LedColorsPublisher::send_colors(buffer)
async fn send_colors(offset: u16, buffer: Vec<u8>) -> Result<(), String> {
ambient_light::LedColorsPublisher::send_colors(offset, buffer)
.await
.map_err(|e| {
error!("can not send colors: {}", e);