hyperion/instance/device/
common.rs1use std::time::Instant;
2
3use async_trait::async_trait;
4
5use super::{DeviceError, DeviceImpl};
6use crate::models::{self, DeviceConfig};
7
8#[async_trait]
9pub trait WritingDevice: Send + Sized {
10 type Config: DeviceConfig;
11
12 fn new(config: &Self::Config) -> Result<Self, DeviceError>;
13
14 async fn set_let_data(
15 &mut self,
16 config: &Self::Config,
17 led_data: &[models::Color],
18 ) -> Result<(), DeviceError>;
19
20 async fn write(&mut self) -> Result<(), DeviceError>;
21}
22
23pub struct Rewriter<D: WritingDevice> {
24 inner: D,
25 config: D::Config,
26 last_write_time: Option<Instant>,
27 next_write_time: Option<Instant>,
28}
29
30impl<D: WritingDevice> Rewriter<D> {
31 pub fn new(config: D::Config) -> Result<Self, DeviceError> {
32 let inner = D::new(&config)?;
33
34 Ok(Self {
35 inner,
36 config,
37 last_write_time: None,
38 next_write_time: None,
39 })
40 }
41
42 async fn write(&mut self) -> Result<(), DeviceError> {
43 self.inner.write().await?;
44 self.last_write_time = Some(Instant::now());
45 self.next_write_time = None;
46 Ok(())
47 }
48
49 async fn latching_write(&mut self) -> Result<(), DeviceError> {
50 let latch_time = self.config.latch_time();
51 if latch_time.is_zero() {
52 self.write().await?;
54 } else if let Some(lwt) = self.last_write_time {
55 let now = Instant::now();
57 let next_write_time = lwt + latch_time;
58
59 if next_write_time < now {
60 self.write().await?;
62 } else {
63 self.next_write_time = Some(next_write_time);
65 }
66 } else {
67 self.write().await?;
69 }
70
71 Ok(())
72 }
73}
74
75#[async_trait]
76impl<D: WritingDevice> DeviceImpl for Rewriter<D> {
77 async fn set_led_data(&mut self, led_data: &[models::Color]) -> Result<(), DeviceError> {
78 self.inner.set_let_data(&self.config, led_data).await?;
79 self.latching_write().await?;
80 Ok(())
81 }
82
83 async fn update(&mut self) -> Result<(), DeviceError> {
84 if let Some(next_write_time) = self.next_write_time {
86 let now = Instant::now();
88
89 if next_write_time > now {
90 tokio::time::sleep_until(next_write_time.into()).await;
92 }
93
94 self.write().await?;
96 }
97
98 if let Some(rewrite_time) = self.config.rewrite_time() {
99 let now = Instant::now();
100 let next_rewrite_time = self
101 .last_write_time
102 .map(|lwt| lwt + rewrite_time)
103 .unwrap_or(now);
104
105 if next_rewrite_time > now {
107 tokio::time::sleep_until(next_rewrite_time.into()).await;
108 }
109
110 self.latching_write().await?;
112
113 Ok(())
114 } else {
115 futures::future::pending().await
116 }
117 }
118}