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>>, } pub struct PCDUHandler { switch_rx: Receiver<(SwitchId, SwitchState)>, can_tx: Sender, can_rx: Receiver, device_state_map: Arc>>, } impl PowerSwitcher { pub fn new( switch_tx: Sender<(SwitchId, SwitchState)>, device_state_map: Arc>>, ) -> 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 { 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, can_rx: Receiver, device_state_map: Arc>>, ) -> 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 { 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, can_rx: Receiver, device_state_map: Arc>>, ) { let mut pcdu = PCDUHandler::new(switch_rx, can_tx, can_rx, device_state_map); loop { pcdu.handle_power_requests().unwrap(); } }