1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use async_trait::async_trait;

use crate::{color::AnsiDisplayExt, models};

use super::{common::*, DeviceError};

pub type DummyDevice = Rewriter<DummyDeviceImpl>;

pub struct DummyDeviceImpl {
    leds: Vec<models::Color>,
    mode: models::DummyDeviceMode,
    ansi_buf: String,
}

#[async_trait]
impl WritingDevice for DummyDeviceImpl {
    type Config = models::Dummy;

    fn new(config: &Self::Config) -> Result<Self, DeviceError> {
        Ok(Self {
            leds: vec![Default::default(); config.hardware_led_count as _],
            mode: config.mode,
            ansi_buf: String::new(),
        })
    }

    async fn set_let_data(
        &mut self,
        _config: &Self::Config,
        led_data: &[models::Color],
    ) -> Result<(), DeviceError> {
        self.leds.copy_from_slice(led_data);
        Ok(())
    }

    async fn write(&mut self) -> Result<(), DeviceError> {
        // Write to log when we get new data
        match self.mode {
            models::DummyDeviceMode::Text => {
                for (i, led) in self.leds.iter().enumerate() {
                    info!(
                        led = %format_args!("{:3}", i),
                        red = %format_args!("{:3}", led.red),
                        green = %format_args!("{:3}", led.green),
                        blue = %format_args!("{:3}", led.blue),
                    );
                }
            }

            models::DummyDeviceMode::Ansi => {
                // Build a truecolor ANSI sequence for all LEDs
                self.ansi_buf.clear();

                self.leds
                    .iter()
                    .copied()
                    .to_ansi_truecolor(&mut self.ansi_buf);

                // Output
                info!("{}", &self.ansi_buf);
            }
        }

        Ok(())
    }
}