eurosim-obsw/src/power_handler.rs
lkoester 322fc70ac7 ...
2023-04-26 17:17:35 +02:00

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();
}
}