diff --git a/src/action.rs b/src/action.rs index 7bf821b..b1e0b34 100644 --- a/src/action.rs +++ b/src/action.rs @@ -1,5 +1,4 @@ use eurosim_obsw::RequestTargetId; -use satrs_core::tmtc::AddressableId; pub type CollectionIntervalFactor = u32; diff --git a/src/can.rs b/src/can.rs index b4e1e92..bae4f5c 100644 --- a/src/can.rs +++ b/src/can.rs @@ -2,7 +2,7 @@ #![allow(unused_variables)] #![allow(unused_imports)] -use crate::device_handler::DeviceState; +use crate::pcdu::DeviceState; use crate::can_ids::{ can_id_to_package_id, package_id_to_can_id, value_to_package_id, DeviceId, PackageId, diff --git a/src/can_ids.rs b/src/can_ids.rs index a92e380..c3913b6 100644 --- a/src/can_ids.rs +++ b/src/can_ids.rs @@ -1,9 +1,6 @@ use embedded_can::{Id, StandardId}; use log::warn; use std::collections::HashMap; -use std::fs; -use std::sync::mpsc::Sender; -use std::thread::Thread; pub use num_derive::{FromPrimitive, ToPrimitive}; pub use num_traits::{FromPrimitive, ToPrimitive}; @@ -93,6 +90,39 @@ pub enum DeviceId { All = 23, } +impl TryFrom for DeviceId { + type Error = (); + + fn try_from(v: u16) -> Result { + match v { + x if x==DeviceId::OBC as u16 => Ok(DeviceId::OBC), + x if x==DeviceId::PCDU as u16 => Ok(DeviceId::PCDU), + x if x==DeviceId::MGM1 as u16 => Ok(DeviceId::MGM1), + x if x==DeviceId::MGM2 as u16 => Ok(DeviceId::MGM2), + x if x==DeviceId::MGM3 as u16 => Ok(DeviceId::MGM3), + x if x==DeviceId::MGM4 as u16 => Ok(DeviceId::MGM4), + x if x==DeviceId::SunSensor1 as u16 => Ok(DeviceId::SunSensor1), + x if x==DeviceId::SunSensor2 as u16 => Ok(DeviceId::SunSensor2), + x if x==DeviceId::SunSensor3 as u16 => Ok(DeviceId::SunSensor3), + x if x==DeviceId::SunSensor4 as u16 => Ok(DeviceId::SunSensor4), + x if x==DeviceId::SunSensor5 as u16 => Ok(DeviceId::SunSensor5), + x if x==DeviceId::SunSensor6 as u16 => Ok(DeviceId::SunSensor6), + x if x==DeviceId::StarTracker as u16 => Ok(DeviceId::StarTracker), + x if x==DeviceId::MGT1 as u16 => Ok(DeviceId::MGT1), + x if x==DeviceId::MGT2 as u16 => Ok(DeviceId::MGT2), + x if x==DeviceId::MGT3 as u16 => Ok(DeviceId::MGT3), + x if x==DeviceId::MGT4 as u16 => Ok(DeviceId::MGT4), + x if x==DeviceId::RWL1 as u16 => Ok(DeviceId::RWL1), + x if x==DeviceId::RWL2 as u16 => Ok(DeviceId::RWL2), + x if x==DeviceId::RWL3 as u16 => Ok(DeviceId::RWL3), + x if x==DeviceId::RWL4 as u16 => Ok(DeviceId::RWL4), + x if x==DeviceId::Camera as u16 => Ok(DeviceId::Camera), + x if x==DeviceId::All as u16 => Ok(DeviceId::All), + _ => Err(()), + } + } +} + #[derive(Debug)] pub struct PackageModel { package_id: PackageId, diff --git a/src/device_handler.rs b/src/device_handler.rs index 16b058a..e69de29 100644 --- a/src/device_handler.rs +++ b/src/device_handler.rs @@ -1,222 +0,0 @@ -use crate::can_ids::{DeviceId, PackageId, PackageModel, ThreadId}; -use log::{info, warn}; -use socketcan::{errors, frame, socket, CanFrame, Socket}; -use std::collections::HashMap; -use std::hash::Hash; -use std::sync::mpsc::{Receiver, RecvError, Sender}; - -use crate::can::{CanRxHandler, CanTxHandler}; -pub use num_derive::{FromPrimitive, ToPrimitive}; -pub use num_traits::{FromPrimitive, ToPrimitive}; -pub use strum::IntoEnumIterator; // 0.17.1 -pub use strum_macros::EnumIter; // 0.17.1 - -#[derive(Copy, Clone, Debug, PartialEq)] -pub enum DeviceState { - On, - Off, - Broken, - Unknown, -} - -pub struct CanDeviceHandler { - device_state_map: HashMap, - can_tx_handler: CanTxHandler, - can_rx_receiver: Receiver, -} - -impl CanDeviceHandler { - pub fn new( - can_tx_handler: CanTxHandler, - can_rx_receiver: Receiver, - ) -> CanDeviceHandler { - let mut device_state_map: HashMap = HashMap::new(); - - for id in DeviceId::iter() { - device_state_map.insert(id, DeviceState::Unknown); - } - CanDeviceHandler { - device_state_map, - can_tx_handler, - can_rx_receiver, - } - } - - pub fn power_on(&mut self, id: DeviceId) -> Result<(), ()> { - if !self.device_state_map.contains_key(&id) { - return Err(()); - } - info!("Powering on device {:?}", id); - - let msg_data: [u8; 1] = [id as u8]; - self.can_tx_handler - .tx_socket(PackageId::DevicePowerOnRequest, &msg_data); - - let request_confirmation = self.can_rx_receiver.recv(); - match request_confirmation { - Ok(confirmation) => { - if confirmation.package_id() != PackageId::DevicePowerOnRequestConfirmation { - warn!("Wrong package ID."); - return Err(()); - } - if confirmation.data()[0] != id as u8 { - warn!("Wrong device ID."); - return Err(()); - } - if confirmation.data()[1] != 1 { - warn!("Request unsuccessful."); - return Err(()); - } - info!("Power on request confirmation received."); - } - Err(_) => { - warn!("Error receiving package."); - return Err(()); - } - } - - let request_success = self.can_rx_receiver.recv(); - match request_success { - Ok(success) => { - if success.package_id() != PackageId::DevicePowerOnConfirmation { - warn!("Wrong package ID."); - return Err(()); - } - if success.data()[0] != id as u8 { - warn!("Wrong device ID."); - return Err(()); - } - if success.data()[1] != 1 { - warn!("Power on unsuccessful."); - return Err(()); - } - info!("Power on confirmation received."); - } - Err(_) => { - warn!("Error receiving package."); - return Err(()); - } - } - - Ok(()) - } - - pub fn power_off(&mut self, id: DeviceId) -> Result<(), ()> { - if !self.device_state_map.contains_key(&id) { - return Err(()); - } - info!("Powering on device {:?}", id); - - let msg_data: [u8; 1] = [id as u8]; - self.can_tx_handler - .tx_socket(PackageId::DevicePowerOffRequest, &msg_data); - - let request_confirmation = self.can_rx_receiver.recv(); - match request_confirmation { - Ok(confirmation) => { - if confirmation.package_id() != PackageId::DevicePowerOffRequestConfirmation { - warn!("Wrong package ID."); - return Err(()); - } - if confirmation.data()[0] != id as u8 { - warn!("Wrong device ID."); - return Err(()); - } - if confirmation.data()[1] != 1 { - warn!("Request unsuccessful."); - return Err(()); - } - info!("Power off request confirmation received."); - } - Err(_) => { - warn!("Error receiving package."); - return Err(()); - } - } - - let request_success = self.can_rx_receiver.recv(); - match request_success { - Ok(success) => { - if success.package_id() != PackageId::DevicePowerOffConfirmation { - warn!("Wrong package ID."); - return Err(()); - } - if success.data()[0] != id as u8 { - warn!("Wrong device ID."); - return Err(()); - } - if success.data()[1] != 1 { - warn!("Power off unsuccessful."); - return Err(()); - } - info!("Power off confirmation received."); - } - Err(_) => { - warn!("Error receiving package."); - return Err(()); - } - } - - Ok(()) - } - - pub fn get_power_states(&mut self) -> HashMap { - for id in DeviceId::iter() { - self.update_power_state(id) - .expect("Error updating power state."); - } - self.device_state_map.clone() - } - - pub fn get_power_state(&mut self, id: DeviceId) -> Option<&DeviceState> { - self.update_power_state(id) - .expect("Error updating power state."); - self.device_state_map.get(&id) - } - - pub fn update_power_state(&mut self, id: DeviceId) -> Result<(), ()> { - if !self.device_state_map.contains_key(&id) { - return Err(()); - } - - let msg_data: [u8; 1] = [id as u8]; - self.can_tx_handler - .tx_socket(PackageId::DevicePowerStatusRequest, &msg_data); - - let response = self.can_rx_receiver.recv(); - if let Ok(response) = response { - let data = response.data(); - - if data[0] == id as u8 { - if data[1] == 1 { - *self.device_state_map.get_mut(&id).unwrap() = DeviceState::On; - } else if data[1] == 0 { - *self.device_state_map.get_mut(&id).unwrap() = DeviceState::Off; - } else { - return Err(()); - } - } - } else { - return Err(()); - } - Ok(()) - } -} - -pub fn power_up_sequence(mut device_handler: CanDeviceHandler) -> HashMap { - for id in DeviceId::iter() { - device_handler - .power_on(id) - .expect("Error powering on device."); - } - device_handler.get_power_states() -} - -pub fn power_down_sequence(mut device_handler: CanDeviceHandler) -> HashMap { - for id in DeviceId::iter() { - device_handler - .power_off(id) - .expect("Error powering on device."); - } - device_handler.get_power_states() -} diff --git a/src/main.rs b/src/main.rs index a922ae6..ca2e54d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ mod logger; mod pus; mod requests; mod tmtc; +mod pcdu; use crate::hk::{AcsHkIds, HkRequest}; use crate::requests::{Request, RequestWithToken}; @@ -41,7 +42,7 @@ use satrs_core::{ spacepackets::{SequenceFlags, SpHeader}, }; -use crate::can_ids::{can_id_to_package_id, load_package_ids, PackageId, PackageModel, ThreadId}; +use crate::can_ids::{can_id_to_package_id, DeviceId, load_package_ids, PackageId, PackageModel, ThreadId}; use embedded_can::{Id, StandardId}; use log::{info, warn}; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; @@ -51,9 +52,11 @@ use std::sync::mpsc::{channel, RecvError, TryRecvError}; use std::sync::{mpsc, Arc, RwLock}; use std::thread; use std::time::Duration; +use satrs_core::power::{SwitchId, SwitchState}; //use libc::time64_t; use crate::action::ActionRequest; use crate::cam::CameraRequest; +use crate::pcdu::core_power_task; #[derive(Clone)] struct EventTmSender { @@ -217,6 +220,16 @@ fn main() { } }); + let (pcdu_tx, pcdu_rx) = mpsc::channel::<(SwitchId, SwitchState)>(); + let pcdu_can_tx = + can::CanTxHandler::new_socket("can0", ThreadId::PowerThread, load_package_ids()).unwrap(); + + info!("Starting power task"); + let builder2 = thread::Builder::new().name("PowerThread".into()); + let jh2 = builder2.spawn(move || { + core_power_task(pcdu_rx, pcdu_can_tx, power_can_rx); + }); + let package_map_aocs_tx = load_package_ids(); let aocs_tm_funnel_tx = tm_funnel_tx.clone(); let mut aocs_tm_store = tm_store.clone(); @@ -319,6 +332,7 @@ fn main() { let PLDCanSocket = can::CanTxHandler::new_socket("can0", ThreadId::PLDThread, package_map_pld_tx).unwrap(); + let mut pcdu_tx_pld_clone = pcdu_tx.clone(); println!("Starting Payload Handling task"); let builder3 = thread::Builder::new().name("PLDThread".into()); let jh3 = builder3.spawn(move || { @@ -328,6 +342,7 @@ fn main() { Ok(request_with_token) => { match request_with_token.0 { Request::ActionRequest(action_id) => { + pcdu_tx_pld_clone.send((DeviceId::Camera as SwitchId, SwitchState::On)).unwrap(); match action_id { ActionRequest::ImageRequest(target_id) => { assert_eq!(target_id, RequestTargetId::PldSubsystem); @@ -408,6 +423,7 @@ fn main() { } } } + pcdu_tx_pld_clone.send((DeviceId::Camera as SwitchId, SwitchState::Off)).unwrap(); } ActionRequest::OrientationRequest(_) => {} _ => {} @@ -444,15 +460,9 @@ fn main() { jh1.unwrap() .join() .expect("Joining CAN Bus Listening thread failed"); - //jh2.unwrap().join().expect("Joing AOCS thread failed"); - jh3.unwrap().join().expect("Joing AOCS thread failed"); - jh4.unwrap().join().expect("Joing AOCS thread failed"); - - /* - jh1.join().expect("Joining TM Funnel thread failed"); - jh2.join().expect("Joining Event Manager thread failed"); - jh3.join().expect("Joining AOCS thread failed"); - */ + jh2.unwrap().join().expect("Joining power thread failed"); + jh3.unwrap().join().expect("Joining PLD thread failed"); + jh4.unwrap().join().expect("Joining TM funnel thread failed"); } #[derive(Default)] struct MgmData { diff --git a/src/pcdu.rs b/src/pcdu.rs index e69de29..d2073d0 100644 --- a/src/pcdu.rs +++ b/src/pcdu.rs @@ -0,0 +1,170 @@ +use std::collections::HashMap; +use std::sync::mpsc::Receiver; +use satrs_core::power::{PowerSwitch, PowerSwitcher, SwitchId, SwitchState}; +use crate::can::{CanRxHandler, CanTxHandler}; +use crate::can_ids::{DeviceId, PackageId, PackageModel}; +use std::convert::TryFrom; +use std::ops::Deref; +use std::time::Duration; +use log::warn; +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, +} + +pub struct PCDU { + switch_rx: Receiver<(SwitchId, SwitchState)>, + can_tx: CanTxHandler, + can_rx: Receiver, + device_state_map: HashMap, +} + +impl PCDU { + pub fn new(switch_rx: Receiver<(SwitchId, SwitchState)>, can_tx: CanTxHandler, can_rx: Receiver) -> PCDU{ + let mut device_state_map: HashMap = HashMap::new(); + for id in DeviceId::iter() { + device_state_map.insert(id, SwitchState::Off); + } + + PCDU{switch_rx, can_tx, can_rx, device_state_map} + } + + 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_switch_off_cmd(switch_id) { + Ok(_) => { + i = i + 1; + } + Err(_) => { + return Err(()); + } + } + } + SwitchState::On => { + match self.send_switch_on_cmd(switch_id) { + Ok(_) => { + i = i + 1; + } + Err(_) => { + return Err(()); + } + } + } + _ => {} + } + } + return Ok(i); + } + +} + +impl PowerSwitcher for PCDU { + type Error = (); + + fn send_switch_on_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> { + return match DeviceId::try_from(switch_id) { + Ok(device_id) => { + let buf: &[u8] = &switch_id.to_be_bytes(); + if buf.len() == 1 { + self.can_tx.tx_socket(PackageId::DevicePowerOnRequest, buf); + let mut i = 0; + while i < 10 { + match self.can_rx.recv() { + Ok(msg) => { + if msg.package_id() + == PackageId::DevicePowerOnConfirmation { + return if msg.data()[0] == device_id as u8 + && msg.data()[1] == 1 { + *self.device_state_map.get_mut(&(device_id)).unwrap() = SwitchState::On; + Ok(()) + } else { + Err(()) + } + } + } + Err(_) => { + warn!("Error receiving Can Bus Message."); + } + } + i = i + 1; + } + Err(()) + } else { + Err(()) + } + } + Err(_) => { Err(()) } + } + } + + fn send_switch_off_cmd(&mut self, switch_id: SwitchId) -> Result<(), Self::Error> { + return match DeviceId::try_from(switch_id) { + Ok(device_id) => { + let buf: &[u8] = &switch_id.to_be_bytes(); + if buf.len() == 1 { + self.can_tx.tx_socket(PackageId::DevicePowerOffRequest, buf); + let mut i = 0; + while i < 10 { + match self.can_rx.recv() { + Ok(msg) => { + if msg.package_id() + == PackageId::DevicePowerOffConfirmation { + return if msg.data()[0] == device_id as u8 + && msg.data()[1] == 1 { + *self.device_state_map.get_mut(&(device_id)).unwrap() = SwitchState::Off; + Ok(()) + } else { + Err(()) + } + } + } + Err(_) => { + warn!("Error receiving Can Bus Message."); + } + } + i = i + 1; + } + Err(()) + } else { + Err(()) + } + } + Err(_) => { Err(()) } + } + } + + fn get_switch_state(&mut self, switch_id: SwitchId) -> Result { + if let Ok(device_id) = DeviceId::try_from(switch_id) { + return match self.device_state_map.get_mut(&device_id) { + None => { Err(()) } + Some(state) => { + let return_state = state.clone(); + Ok(return_state) + } + } + } else { + Err(()) + } + } + + fn switch_delay_ms(&self) -> u32 { + return 0; + } +} + +pub fn core_power_task(switch_rx: Receiver<(SwitchId, SwitchState)>, can_tx: CanTxHandler, can_rx: Receiver) { + let mut pcdu = PCDU::new(switch_rx, can_tx, can_rx); + loop{ + pcdu.handle_power_requests().unwrap(); + } +} \ No newline at end of file diff --git a/src/pus.rs b/src/pus.rs index 41a089a..af344c4 100644 --- a/src/pus.rs +++ b/src/pus.rs @@ -1,10 +1,10 @@ use crate::hk::{CollectionIntervalFactor, HkRequest}; use crate::requests::{Request, RequestWithToken}; use crate::tmtc::{PusTcSource, TmStore}; -use eurosim_obsw::{hk_err, tmtc_err, RequestTargetId}; +use eurosim_obsw::{hk_err, tmtc_err}; use satrs_core::events::EventU32; use satrs_core::pool::StoreAddr; -use satrs_core::pus::event::Subservices; +use satrs_core::pus::event::Subservice; use satrs_core::pus::event_man::{EventRequest, EventRequestWithToken}; use satrs_core::pus::hk; use satrs_core::pus::verification::{ @@ -14,7 +14,7 @@ use satrs_core::res_code::ResultU16; use satrs_core::tmtc::tm_helper::PusTmWithCdsShortHelper; use satrs_core::tmtc::{AddressableId, PusServiceProvider}; use satrs_core::{ - spacepackets, spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, + spacepackets::ecss::PusPacket, spacepackets::tc::PusTc, spacepackets::time::cds::TimeProvider, spacepackets::time::TimeWriter, spacepackets::SpHeader, }; use std::cell::RefCell; @@ -23,7 +23,6 @@ use crate::action; use crate::action::ActionRequest; use eurosim_obsw::RequestTargetId::{AcsSubsystem, PldSubsystem}; use satrs_core::pus::scheduling::PusScheduler; -use satrs_core::spacepackets::ecss::PusServiceId::Action; use std::collections::HashMap; use std::rc::Rc; use std::sync::mpsc::Sender; @@ -188,13 +187,14 @@ impl PusReceiver { .send(RequestWithToken(Request::HkRequest(request), token)) .unwrap_or_else(|_| panic!("Sending HK request {:?} failed", request)); }; - if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableGeneration as u8 { + if PusPacket::subservice(pus_tc) == hk::Subservice::TcEnableHkGeneration as u8 { send_request(HkRequest::Enable(addressable_id)); - } else if PusPacket::subservice(pus_tc) == hk::Subservice::TcDisableGeneration as u8 { + } else if PusPacket::subservice(pus_tc) == hk::Subservice::TcDisableHkGeneration as u8 { send_request(HkRequest::Disable(addressable_id)); } else if PusPacket::subservice(pus_tc) == hk::Subservice::TcGenerateOneShotHk as u8 { send_request(HkRequest::OneShot(addressable_id)); - } else if PusPacket::subservice(pus_tc) == hk::Subservice::TcModifyCollectionInterval as u8 + } else if PusPacket::subservice(pus_tc) + == hk::Subservice::TcModifyHkCollectionInterval as u8 { if user_data.len() < 12 { self.update_time_stamp(); @@ -257,7 +257,7 @@ impl PusReceiver { } let event_id = EventU32::from(u32::from_be_bytes(app_data.try_into().unwrap())); match PusPacket::subservice(pus_tc).try_into() { - Ok(Subservices::TcEnableEventGeneration) => { + Ok(Subservice::TcEnableEventGeneration) => { self.update_time_stamp(); let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp); self.event_request_tx @@ -267,7 +267,7 @@ impl PusReceiver { }) .expect("Sending event request failed"); } - Ok(Subservices::TcDisableEventGeneration) => { + Ok(Subservice::TcDisableEventGeneration) => { self.update_time_stamp(); let start_token = send_start_acceptance(&mut self.verif_reporter, &self.time_stamp); self.event_request_tx diff --git a/src/requests.rs b/src/requests.rs index e739398..df0ade3 100644 --- a/src/requests.rs +++ b/src/requests.rs @@ -1,5 +1,4 @@ use crate::action::ActionRequest; -use crate::cam::CameraRequest; use crate::hk::HkRequest; use satrs_core::pus::verification::{TcStateAccepted, VerificationToken}; diff --git a/src/tmtc.rs b/src/tmtc.rs index bd0ab0b..fc66b22 100644 --- a/src/tmtc.rs +++ b/src/tmtc.rs @@ -8,7 +8,6 @@ use std::fmt::{Display, Formatter}; use std::net::SocketAddr; use std::rc::Rc; use std::sync::mpsc::{Receiver, SendError, Sender, TryRecvError}; -use std::sync::{Arc, LockResult, Mutex}; use std::thread; use std::time::Duration;