feat: 使用 UDP 发送颜色。
This commit is contained in:
parent
9d11abfa6e
commit
7a87748cf1
@ -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>,
|
||||
}
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user