sat-rs/satrs/src/power.rs

139 lines
3.7 KiB
Rust
Raw Normal View History

2023-02-05 14:15:48 +01:00
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
2023-02-05 01:18:23 +01:00
2023-02-05 14:15:48 +01:00
/// Generic trait for a device capable of switching itself on or off.
2023-02-05 01:18:23 +01:00
pub trait PowerSwitch {
2023-02-05 14:15:48 +01:00
type Error;
fn switch_on(&mut self) -> Result<(), Self::Error>;
fn switch_off(&mut self) -> Result<(), Self::Error>;
2023-02-05 01:18:23 +01:00
fn is_switch_on(&self) -> bool {
self.switch_state() == SwitchState::On
}
fn switch_state(&self) -> SwitchState;
}
2023-02-05 14:15:48 +01:00
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
2023-02-05 01:18:23 +01:00
pub enum SwitchState {
Off = 0,
On = 1,
2023-02-05 14:15:48 +01:00
Unknown = 2,
2023-02-05 18:59:28 +01:00
Faulty = 3,
2023-02-05 01:18:23 +01:00
}
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum SwitchStateBinary {
Off = 0,
On = 1,
}
impl TryFrom<SwitchState> for SwitchStateBinary {
type Error = ();
fn try_from(value: SwitchState) -> Result<Self, Self::Error> {
match value {
SwitchState::Off => Ok(SwitchStateBinary::Off),
SwitchState::On => Ok(SwitchStateBinary::On),
_ => Err(()),
}
}
}
impl<T: Into<u64>> From<T> for SwitchStateBinary {
fn from(value: T) -> Self {
if value.into() == 0 {
return SwitchStateBinary::Off;
}
SwitchStateBinary::On
}
}
impl From<SwitchStateBinary> for SwitchState {
fn from(value: SwitchStateBinary) -> Self {
match value {
SwitchStateBinary::Off => SwitchState::Off,
SwitchStateBinary::On => SwitchState::On,
}
}
}
2023-02-05 14:15:48 +01:00
pub type SwitchId = u16;
/// Generic trait for a device capable of turning on and off switches.
2023-02-13 09:20:00 +01:00
pub trait PowerSwitcherCommandSender {
2023-02-05 14:15:48 +01:00
type Error;
2023-02-05 01:18:23 +01:00
2023-02-05 14:15:48 +01:00
fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>;
fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error>;
2023-02-13 09:20:00 +01:00
}
pub trait PowerSwitchInfo {
type Error;
2023-02-05 14:15:48 +01:00
/// Retrieve the switch state
fn get_switch_state(&mut self, switch_id: SwitchId) -> Result<SwitchState, Self::Error>;
2023-02-05 14:15:48 +01:00
2023-02-07 16:01:25 +01:00
fn get_is_switch_on(&mut self, switch_id: SwitchId) -> Result<bool, Self::Error> {
Ok(self.get_switch_state(switch_id)? == SwitchState::On)
2023-02-05 14:15:48 +01:00
}
/// The maximum delay it will take to change a switch.
///
/// This may take into account the time to send a command, wait for it to be executed, and
/// see the switch changed.
fn switch_delay_ms(&self) -> u32;
2023-02-05 18:59:28 +01:00
}
2023-02-06 11:38:13 +01:00
#[cfg(test)]
mod tests {
2023-02-27 17:00:21 +01:00
#![allow(dead_code)]
2023-02-06 11:38:13 +01:00
use super::*;
2023-02-14 15:53:14 +01:00
use std::boxed::Box;
2023-02-06 11:38:13 +01:00
struct Pcdu {
2023-02-14 15:53:14 +01:00
switch_rx: std::sync::mpsc::Receiver<(SwitchId, u16)>,
2023-02-06 11:38:13 +01:00
}
2023-02-27 17:00:21 +01:00
#[derive(Eq, PartialEq)]
2023-02-06 11:38:13 +01:00
enum DeviceState {
OFF,
SwitchingPower,
ON,
SETUP,
2023-02-14 15:53:14 +01:00
IDLE,
2023-02-06 11:38:13 +01:00
}
struct MyComplexDevice {
2023-02-14 15:53:14 +01:00
power_switcher: Box<dyn PowerSwitcherCommandSender<Error = ()>>,
2023-02-27 17:00:21 +01:00
power_info: Box<dyn PowerSwitchInfo<Error = ()>>,
2023-02-06 11:38:13 +01:00
switch_id: SwitchId,
some_state: u16,
dev_state: DeviceState,
mode: u32,
submode: u16,
}
impl MyComplexDevice {
pub fn periodic_op(&mut self) {
// .. mode command coming in
let mode = 1;
if mode == 1 {
if self.dev_state == DeviceState::OFF {
2023-02-14 15:53:14 +01:00
self.power_switcher
.send_switch_on_cmd(self.switch_id)
.expect("sending siwthc cmd failed");
2023-02-06 11:38:13 +01:00
self.dev_state = DeviceState::SwitchingPower;
}
if self.dev_state == DeviceState::SwitchingPower {
2023-02-27 17:00:21 +01:00
if self.power_info.get_is_switch_on(0).unwrap() {
2023-02-06 11:38:13 +01:00
self.dev_state = DeviceState::ON;
self.mode = 1;
}
}
}
}
}
2023-02-14 15:53:14 +01:00
}