238 lines
7.8 KiB
Rust
238 lines
7.8 KiB
Rust
use crate::can_ids::{DeviceId, MessageId, MessageModel};
|
|
use satrs_core::power::{PowerSwitchInfo, PowerSwitcherCommandSender, SwitchId, SwitchState};
|
|
use std::collections::HashMap;
|
|
use std::convert::TryFrom;
|
|
use std::sync::mpsc::{Receiver, Sender};
|
|
use std::sync::{Arc, Mutex};
|
|
use std::vec;
|
|
pub use strum::IntoEnumIterator; // 0.17.1
|
|
pub use strum_macros::EnumIter; // 0.17.1
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, EnumIter)]
|
|
pub enum DeviceState {
|
|
On,
|
|
Off,
|
|
SwitchingPower,
|
|
Setup,
|
|
Idle,
|
|
}
|
|
|
|
#[derive(Clone)]
|
|
pub struct PowerSwitcher {
|
|
switch_tx: Sender<(SwitchId, SwitchState)>,
|
|
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
|
|
}
|
|
|
|
pub struct PCDUHandler {
|
|
switch_rx: Receiver<(SwitchId, SwitchState)>,
|
|
can_tx: Sender<MessageModel>,
|
|
can_rx: Receiver<MessageModel>,
|
|
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
|
|
}
|
|
|
|
impl PowerSwitcher {
|
|
pub fn new(
|
|
switch_tx: Sender<(SwitchId, SwitchState)>,
|
|
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
|
|
) -> PowerSwitcher {
|
|
PowerSwitcher {
|
|
switch_tx,
|
|
device_state_map,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl PowerSwitcherCommandSender for PowerSwitcher {
|
|
type Error = ();
|
|
|
|
fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> {
|
|
return match self.switch_tx.send((switch_id, SwitchState::On)) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => Err(()),
|
|
};
|
|
}
|
|
|
|
fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> {
|
|
return match self.switch_tx.send((switch_id, SwitchState::Off)) {
|
|
Ok(_) => Ok(()),
|
|
Err(_) => Err(()),
|
|
};
|
|
}
|
|
}
|
|
|
|
impl PowerSwitchInfo for PowerSwitcher {
|
|
type Error = ();
|
|
|
|
fn get_switch_state(&mut self, switch_id: SwitchId) -> Result<SwitchState, Self::Error> {
|
|
let map_locked = self.device_state_map.lock().unwrap();
|
|
if let Ok(dev_id) = DeviceId::try_from(switch_id) {
|
|
return if let Some(state) = map_locked.get(&dev_id) {
|
|
Ok(*state)
|
|
} else {
|
|
Err(())
|
|
};
|
|
} else {
|
|
Err(())
|
|
}
|
|
}
|
|
|
|
fn switch_delay_ms(&self) -> u32 {
|
|
0
|
|
}
|
|
}
|
|
|
|
impl PCDUHandler {
|
|
pub fn new(
|
|
switch_rx: Receiver<(SwitchId, SwitchState)>,
|
|
can_tx: Sender<MessageModel>,
|
|
can_rx: Receiver<MessageModel>,
|
|
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
|
|
) -> PCDUHandler {
|
|
PCDUHandler {
|
|
switch_rx,
|
|
can_tx,
|
|
can_rx,
|
|
device_state_map,
|
|
}
|
|
}
|
|
|
|
pub fn send_power_on(&mut self, switch_id: SwitchId) -> Result<(), ()> {
|
|
return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
|
|
let dev_id_bytes = dev_id as u8;
|
|
let buf: &[u8] = &dev_id_bytes.to_be_bytes();
|
|
self.can_tx
|
|
.send(MessageModel::new(MessageId::DevicePowerOnRequest, buf).unwrap())
|
|
.unwrap();
|
|
let mut map_lock = self.device_state_map.lock().unwrap();
|
|
*map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown;
|
|
// TODO: potentially change bus logic -> remove acceptance and verification of power off/on, since status is simply called in next step anyway
|
|
Ok(())
|
|
} else {
|
|
Err(())
|
|
};
|
|
}
|
|
|
|
pub fn send_power_off(&mut self, switch_id: SwitchId) -> Result<(), ()> {
|
|
return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
|
|
let dev_id_bytes = dev_id as u8;
|
|
let buf: &[u8] = &dev_id_bytes.to_be_bytes();
|
|
self.can_tx
|
|
.send(MessageModel::new(MessageId::DevicePowerOffRequest, buf).unwrap())
|
|
.unwrap();
|
|
let mut map_lock = self.device_state_map.lock().unwrap();
|
|
*map_lock.get_mut(&dev_id).unwrap() = SwitchState::Unknown;
|
|
Ok(())
|
|
} else {
|
|
Err(())
|
|
};
|
|
}
|
|
|
|
pub fn update_states_helper(&mut self, dev_id: &DeviceId) -> Result<(), ()> {
|
|
/*let _switch_id: SwitchId = *dev_id as u16;
|
|
let dev_id_bytes = *dev_id as u8;
|
|
let buf: &[u8] = &dev_id_bytes.to_be_bytes();
|
|
self.can_tx
|
|
.send(PackageModel::new(PackageId::DevicePowerStatusRequest, buf).unwrap())
|
|
.unwrap();
|
|
match self.can_rx.recv_timeout(Duration::from_secs(10)) {
|
|
Ok(msg) => {
|
|
if msg.package_id() == PackageId::DevicePowerStatusResponse
|
|
&& msg.data()[0] == dev_id_bytes
|
|
{
|
|
debug!("received power status response");
|
|
let mut map_lock = self.device_state_map.lock().unwrap();
|
|
let state: SwitchState;
|
|
match msg.data()[1] {
|
|
0 => state = SwitchState::Off,
|
|
1 => state = SwitchState::On,
|
|
2 => state = SwitchState::Faulty,
|
|
_ => {
|
|
return Err(());
|
|
}
|
|
}
|
|
*map_lock.get_mut(&dev_id).unwrap() = state;
|
|
debug!("{:?}", map_lock);
|
|
Ok(())
|
|
} else {
|
|
Err(())
|
|
}
|
|
}
|
|
Err(_) => Err(()),
|
|
}
|
|
|
|
*/
|
|
Ok(())
|
|
}
|
|
|
|
pub fn update_all_states_helper(&mut self) -> Result<(), ()> {
|
|
let map_lock = self.device_state_map.lock().unwrap();
|
|
let mut device_list = vec::Vec::new();
|
|
for key in map_lock.keys() {
|
|
device_list.push(key.clone());
|
|
}
|
|
drop(map_lock);
|
|
for dev_id in device_list {
|
|
self.update_states_helper(&dev_id)?;
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub fn update_switch_states(&mut self, switch_id: SwitchId, mut switch_state: SwitchState) -> Result<(), ()> {
|
|
return if let Ok(dev_id) = DeviceId::try_from(switch_id) {
|
|
match dev_id {
|
|
//DeviceId::All => self.update_all_states_helper(),
|
|
DeviceId::All => {Ok(())}
|
|
_ => {
|
|
let mut map = self.device_state_map.lock().expect("error locking data map");
|
|
if let Some(mut val) = map.get_mut(&dev_id) {
|
|
val = &mut switch_state;
|
|
}
|
|
Ok(())
|
|
},
|
|
}
|
|
} else {
|
|
Err(())
|
|
};
|
|
}
|
|
|
|
pub fn handle_power_requests(&mut self) -> Result<u16, ()> {
|
|
let mut i = 0;
|
|
while let Ok((switch_id, switch_state)) = self.switch_rx.recv() {
|
|
match switch_state {
|
|
SwitchState::Off => match self.send_power_off(switch_id) {
|
|
Ok(_) => {
|
|
self.update_switch_states(switch_id, switch_state).expect("error updating switch states");
|
|
i = i + 1;
|
|
}
|
|
Err(_) => {
|
|
return Err(());
|
|
}
|
|
},
|
|
SwitchState::On => match self.send_power_on(switch_id) {
|
|
Ok(_) => {
|
|
self.update_switch_states(switch_id, switch_state).expect("error updating switch states");
|
|
i = i + 1;
|
|
}
|
|
Err(_) => {
|
|
return Err(());
|
|
}
|
|
},
|
|
_ => {}
|
|
}
|
|
}
|
|
return Ok(i);
|
|
}
|
|
}
|
|
|
|
pub fn core_power_task(
|
|
switch_rx: Receiver<(SwitchId, SwitchState)>,
|
|
can_tx: Sender<MessageModel>,
|
|
can_rx: Receiver<MessageModel>,
|
|
device_state_map: Arc<Mutex<HashMap<DeviceId, SwitchState>>>,
|
|
) {
|
|
let mut pcdu = PCDUHandler::new(switch_rx, can_tx, can_rx, device_state_map);
|
|
loop {
|
|
pcdu.handle_power_requests().unwrap();
|
|
}
|
|
}
|