1#[cfg(feature = "serde")]
2use serde::{Deserialize, Serialize};
3
4pub trait PowerSwitch {
6    type Error;
7
8    fn switch_on(&mut self) -> Result<(), Self::Error>;
9    fn switch_off(&mut self) -> Result<(), Self::Error>;
10
11    fn is_switch_on(&self) -> bool {
12        self.switch_state() == SwitchState::On
13    }
14
15    fn switch_state(&self) -> SwitchState;
16}
17
18#[derive(Debug, Eq, PartialEq, Copy, Clone)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub enum SwitchState {
21    Off = 0,
22    On = 1,
23    Unknown = 2,
24    Faulty = 3,
25}
26
27pub type SwitchId = u16;
28
29pub trait PowerSwitcherCommandSender {
31    type Error;
32
33    fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>;
34    fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>;
35}
36
37pub trait PowerSwitchInfo {
38    type Error;
39
40    fn get_switch_state(&mut self, switch_id: SwitchId) -> Result<SwitchState, Self::Error>;
42
43    fn get_is_switch_on(&mut self, switch_id: SwitchId) -> Result<bool, Self::Error> {
44        Ok(self.get_switch_state(switch_id)? == SwitchState::On)
45    }
46
47    fn switch_delay_ms(&self) -> u32;
52}
53
54#[cfg(test)]
55mod tests {
56    #![allow(dead_code)]
57    use super::*;
58    use std::boxed::Box;
59
60    struct Pcdu {
61        switch_rx: std::sync::mpsc::Receiver<(SwitchId, u16)>,
62    }
63
64    #[derive(Eq, PartialEq)]
65    enum DeviceState {
66        OFF,
67        SwitchingPower,
68        ON,
69        SETUP,
70        IDLE,
71    }
72    struct MyComplexDevice {
73        power_switcher: Box<dyn PowerSwitcherCommandSender<Error = ()>>,
74        power_info: Box<dyn PowerSwitchInfo<Error = ()>>,
75        switch_id: SwitchId,
76        some_state: u16,
77        dev_state: DeviceState,
78        mode: u32,
79        submode: u16,
80    }
81
82    impl MyComplexDevice {
83        pub fn periodic_op(&mut self) {
84            let mode = 1;
86            if mode == 1 {
87                if self.dev_state == DeviceState::OFF {
88                    self.power_switcher
89                        .send_switch_on_cmd(self.switch_id)
90                        .expect("sending siwthc cmd failed");
91                    self.dev_state = DeviceState::SwitchingPower;
92                }
93                if self.dev_state == DeviceState::SwitchingPower {
94                    if self.power_info.get_is_switch_on(0).unwrap() {
95                        self.dev_state = DeviceState::ON;
96                        self.mode = 1;
97                    }
98                }
99            }
100        }
101    }
102}