hyperion/instance/device/
file.rs1use async_trait::async_trait;
2use chrono::Utc;
3use std::{fmt::Write, time};
4use tokio::{fs::File, io::AsyncWriteExt};
5
6use crate::models;
7
8use super::{common::*, DeviceError};
9
10pub type FileDevice = Rewriter<FileDeviceImpl>;
11
12pub struct FileDeviceImpl {
13 leds: Vec<models::Color>,
14 print_timestamp: bool,
15 file_handle: File,
16 last_write_time: time::Instant,
17 str_buf: String,
18}
19
20#[async_trait]
21impl WritingDevice for FileDeviceImpl {
22 type Config = models::File;
23
24 fn new(config: &Self::Config) -> Result<Self, DeviceError> {
25 let file_handle = std::fs::OpenOptions::new()
26 .create(true)
27 .append(true)
28 .open(&config.output)?;
29
30 Ok(Self {
31 leds: vec![Default::default(); config.hardware_led_count as _],
32 print_timestamp: config.print_time_stamp,
33 file_handle: File::from_std(file_handle),
34 last_write_time: time::Instant::now(),
35 str_buf: String::new(),
36 })
37 }
38
39 async fn set_let_data(
40 &mut self,
41 _config: &Self::Config,
42 led_data: &[models::Color],
43 ) -> Result<(), DeviceError> {
44 self.leds.copy_from_slice(led_data);
45 Ok(())
46 }
47
48 async fn write(&mut self) -> Result<(), DeviceError> {
49 self.str_buf.clear();
50
51 if self.print_timestamp {
52 let now = Utc::now();
54 let elapsed_time_ms = self.last_write_time.elapsed().as_millis();
55 self.last_write_time = time::Instant::now();
56
57 write!(self.str_buf, "{} | +{}", now, elapsed_time_ms)?;
58 }
59
60 write!(self.str_buf, " [")?;
61 for led in &self.leds {
62 write!(self.str_buf, "{{{},{},{}}}", led.red, led.green, led.blue)?;
63 }
64 writeln!(self.str_buf, "]")?;
65
66 self.file_handle.write_all(self.str_buf.as_bytes()).await?;
67 self.file_handle.flush().await?;
68
69 Ok(())
70 }
71}