diff --git a/satrs-example/client/src/main.rs b/satrs-example/client/src/main.rs index f6af5fa..178ead2 100644 --- a/satrs-example/client/src/main.rs +++ b/satrs-example/client/src/main.rs @@ -1,7 +1,7 @@ use anyhow::bail; use arbitrary_int::u11; use clap::Parser as _; -use models::{Apid, MessageType, TcHeader, mgm::request::HkRequest}; +use models::{Apid, MessageType, TcHeader, acs::mgm::request::HkRequest}; use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT}; use spacepackets::{CcsdsPacketIdAndPsc, SpacePacketHeader}; use std::{ @@ -136,7 +136,7 @@ fn main() -> anyhow::Result<()> { let request = models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), TcHeader::new(cmd.target_id(), models::MessageType::Ping), - models::mgm::request::Request::Ping, + models::acs::mgm::request::Request::Ping, ); let sent_tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&request.sp_header); log::info!( @@ -151,8 +151,8 @@ fn main() -> anyhow::Result<()> { let request = models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), TcHeader::new(target_id, models::MessageType::Hk), - models::mgm::request::Request::Hk(HkRequest { - id: models::mgm::request::HkId::Sensor, + models::acs::mgm::request::Request::Hk(HkRequest { + id: models::acs::mgm::request::HkId::Sensor, req_type: models::HkRequestType::OneShot, }), ); @@ -174,8 +174,8 @@ fn main() -> anyhow::Result<()> { let request = models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), TcHeader::new(target_id, models::MessageType::Mode), - models::mgm::request::Request::Mode( - models::mgm::request::ModeRequest::SetMode(dev_mode), + models::acs::mgm::request::Request::Mode( + models::acs::mgm::request::ModeRequest::SetMode(dev_mode), ), ); let sent_tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&request.sp_header); @@ -193,7 +193,7 @@ fn main() -> anyhow::Result<()> { let request = models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), TcHeader::new(cmd.target_id(), models::MessageType::Ping), - models::mgm::request::Request::Ping, + models::acs::mgm::request::Request::Ping, ); let sent_tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&request.sp_header); log::info!( @@ -207,21 +207,23 @@ fn main() -> anyhow::Result<()> { if let Some(mode) = mgm_assembly_args.mode { let assembly_mode = match mode { AssemblyModeSelect::NoModeKeeping => { - models::mgm_assembly::AssemblyMode::NoModeKeeping + models::acs::mgm_assembly::Mode::NoModeKeeping } AssemblyModeSelect::Off => { - models::mgm_assembly::AssemblyMode::Device(models::DeviceMode::Off) + models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Off) } AssemblyModeSelect::Normal => { - models::mgm_assembly::AssemblyMode::Device(models::DeviceMode::Normal) + models::acs::mgm_assembly::Mode::Device( + models::DeviceMode::Normal, + ) } }; let request = models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), TcHeader::new(target_id, models::MessageType::Mode), - models::mgm_assembly::request::Request::Mode( - models::mgm_assembly::request::ModeRequest::SetMode(assembly_mode), + models::acs::mgm_assembly::request::Request::Mode( + models::acs::mgm_assembly::request::ModeRequest::SetMode(assembly_mode), ), ); let sent_tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&request.sp_header); @@ -304,8 +306,9 @@ fn handle_raw_tm_packet(data: &[u8]) -> anyhow::Result<()> { } models::ComponentId::AcsSubsystem => todo!(), models::ComponentId::AcsMgmAssembly => { - let response = - postcard::from_bytes::(remainder); + let response = postcard::from_bytes::< + models::acs::mgm_assembly::response::Response, + >(remainder); log::info!( "Received response from MGM Assembly: {:?}", response.unwrap() @@ -313,12 +316,12 @@ fn handle_raw_tm_packet(data: &[u8]) -> anyhow::Result<()> { } models::ComponentId::AcsMgm0 => { let response = - postcard::from_bytes::(remainder); + postcard::from_bytes::(remainder); log::info!("Received response from MGM0: {:?}", response.unwrap()); } models::ComponentId::AcsMgm1 => { let response = - postcard::from_bytes::(remainder); + postcard::from_bytes::(remainder); log::info!("Received response from MGM1: {:?}", response.unwrap()); } models::ComponentId::EpsSubsystem => todo!(), diff --git a/satrs-example/models/src/acs/ctrl.rs b/satrs-example/models/src/acs/ctrl.rs new file mode 100644 index 0000000..9b901cb --- /dev/null +++ b/satrs-example/models/src/acs/ctrl.rs @@ -0,0 +1,28 @@ +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +pub enum Mode { + Passive, + Safe, + Idle, +} + +pub mod request { + use super::Mode; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub enum ModeRequest { + SetMode(Mode), + ReadMode, + } +} + +pub mod response { + use super::Mode; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub enum ModeReport { + /// Mode of the assembly. + Mode(super::Mode), + /// Children are in wrong mode after commanding. + WrongMode([Option; 2]), + } +} diff --git a/satrs-example/models/src/mgm.rs b/satrs-example/models/src/acs/mgm.rs similarity index 95% rename from satrs-example/models/src/mgm.rs rename to satrs-example/models/src/acs/mgm.rs index 0584542..8868f30 100644 --- a/satrs-example/models/src/mgm.rs +++ b/satrs-example/models/src/acs/mgm.rs @@ -42,7 +42,7 @@ pub mod request { } #[derive(Default, Debug, Copy, Clone, serde::Serialize, serde::Deserialize)] -pub struct MgmData { +pub struct SensorData { pub valid: bool, pub x: f32, pub y: f32, @@ -50,11 +50,11 @@ pub struct MgmData { } pub mod response { - use crate::{DeviceMode, Message, mgm::MgmData}; + use crate::{DeviceMode, Message, acs::mgm::SensorData}; #[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)] pub enum HkResponse { - MgmData(MgmData), + MgmData(SensorData), } #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy)] diff --git a/satrs-example/models/src/mgm_assembly.rs b/satrs-example/models/src/acs/mgm_assembly.rs similarity index 86% rename from satrs-example/models/src/mgm_assembly.rs rename to satrs-example/models/src/acs/mgm_assembly.rs index f0f7417..f96fd06 100644 --- a/satrs-example/models/src/mgm_assembly.rs +++ b/satrs-example/models/src/acs/mgm_assembly.rs @@ -3,7 +3,7 @@ use core::str::FromStr; use crate::DeviceMode; #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)] -pub enum AssemblyMode { +pub enum Mode { /// The assembly mode ressembles the modes of the devices it controls. It also tries to keep /// the children in the correct mode by re-commanding them into the correct mode. Device(DeviceMode), @@ -11,22 +11,22 @@ pub enum AssemblyMode { NoModeKeeping, } -impl FromStr for AssemblyMode { +impl FromStr for Mode { type Err = (); fn from_str(s: &str) -> Result { match s.to_lowercase().as_str() { - "off" => Ok(AssemblyMode::Device(DeviceMode::Off)), - "on" => Ok(AssemblyMode::Device(DeviceMode::On)), - "normal" => Ok(AssemblyMode::Device(DeviceMode::Normal)), - "no_mode_keeping" => Ok(AssemblyMode::NoModeKeeping), + "off" => Ok(Mode::Device(DeviceMode::Off)), + "on" => Ok(Mode::Device(DeviceMode::On)), + "normal" => Ok(Mode::Device(DeviceMode::Normal)), + "no_mode_keeping" => Ok(Mode::NoModeKeeping), _ => Err(()), } } } pub mod request { - use crate::{HkRequestType, Message, mgm_assembly::AssemblyMode}; + use crate::{HkRequestType, Message, acs::mgm_assembly::Mode}; #[derive(Debug, PartialEq, Eq, Clone, Copy, serde::Serialize, serde::Deserialize)] pub enum HkId { @@ -35,7 +35,7 @@ pub mod request { #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum ModeRequest { - SetMode(AssemblyMode), + SetMode(Mode), ReadMode, } @@ -77,7 +77,7 @@ pub mod response { #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum ModeReport { /// Mode of the assembly. - Mode(super::AssemblyMode), + Mode(super::Mode), /// Timeout failure setting the children modes. SetModeTimeout([Option; 2]), /// Children are in wrong mode after commanding. diff --git a/satrs-example/models/src/acs/mgt.rs b/satrs-example/models/src/acs/mgt.rs new file mode 100644 index 0000000..1450214 --- /dev/null +++ b/satrs-example/models/src/acs/mgt.rs @@ -0,0 +1,27 @@ +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +pub enum Mode { + Off, + Normal, +} + +pub mod request { + use super::*; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub enum ModeRequest { + SetMode(Mode), + ReadMode, + } +} + +pub mod response { + use super::*; + + #[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)] + pub enum ModeReport { + /// Mode of the assembly. + Mode(super::Mode), + /// Children are in wrong mode after commanding. + WrongMode([Option; 2]), + } +} diff --git a/satrs-example/models/src/acs/mod.rs b/satrs-example/models/src/acs/mod.rs new file mode 100644 index 0000000..c7cb38d --- /dev/null +++ b/satrs-example/models/src/acs/mod.rs @@ -0,0 +1,5 @@ +pub mod ctrl; +pub mod mgm; +pub mod mgm_assembly; +pub mod mgt; +pub mod subsystem; diff --git a/satrs-example/models/src/acs/subsystem.rs b/satrs-example/models/src/acs/subsystem.rs new file mode 100644 index 0000000..2bfab26 --- /dev/null +++ b/satrs-example/models/src/acs/subsystem.rs @@ -0,0 +1,15 @@ +#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, Copy, PartialEq, Eq)] +pub enum Mode { + Off, + Safe, +} + +impl Mode { + /// Each subsystem mode has a fallback mode to allow clean transitions. + pub const fn fallback_mode(&self) -> Self { + match self { + Mode::Off => Mode::Safe, + Mode::Safe => Mode::Safe, + } + } +} diff --git a/satrs-example/models/src/lib.rs b/satrs-example/models/src/lib.rs index f7351c4..ac4cbc5 100644 --- a/satrs-example/models/src/lib.rs +++ b/satrs-example/models/src/lib.rs @@ -6,10 +6,9 @@ use spacepackets::{ time::cds::{CdsTime, MIN_CDS_FIELD_LEN}, }; +pub mod acs; pub mod ccsds; pub mod control; -pub mod mgm; -pub mod mgm_assembly; pub mod pcdu; #[derive( diff --git a/satrs-example/src/acs/mgm.rs b/satrs-example/src/acs/mgm.rs index e65923f..af98218 100644 --- a/satrs-example/src/acs/mgm.rs +++ b/satrs-example/src/acs/mgm.rs @@ -1,8 +1,8 @@ -use models::mgm::MgmData; -use models::mgm::request::ModeRequest; -use models::mgm::response::ModeResponse; +use models::acs::mgm::SensorData; +use models::acs::mgm::request::ModeRequest; +use models::acs::mgm::response::ModeResponse; use models::pcdu::SwitchId; -use models::{ComponentId, DeviceMode, HkRequestType, mgm}; +use models::{ComponentId, DeviceMode, HkRequestType, acs::mgm}; use satrs::spacepackets::CcsdsPacketIdAndPsc; use satrs_example::{HkHelperSingleSet, ModeHelper, TimestampHelper, TmtcQueues}; use satrs_minisim::acs::MgmRequestLis3Mdl; @@ -153,7 +153,7 @@ pub struct MgmHandlerLis3Mdl { switch_helper: PowerSwitchHelper, tmtc_queues: TmtcQueues, pub spi_com: SpiCommunication, - shared_mgm_set: Arc>, + shared_mgm_set: Arc>, buffers: BufWrapper, stamp_helper: TimestampHelper, hk_helper: HkHelperSingleSet, @@ -167,9 +167,9 @@ impl MgmHandlerLis3Mdl { tmtc_queues: TmtcQueues, switch_helper: PowerSwitchHelper, spi_com: SpiCommunication, - shared_mgm_set: Arc>, + shared_mgm_set: Arc>, mode_leaf_helper: ModeLeafHelper, - mode_timeout: Duration + mode_timeout: Duration, ) -> Self { Self { id, @@ -308,7 +308,7 @@ impl MgmHandlerLis3Mdl { pub fn handle_hk_request( &mut self, tc_id: Option, - hk_request: &models::mgm::request::HkRequest, + hk_request: &models::acs::mgm::request::HkRequest, ) { match hk_request.req_type { HkRequestType::OneShot => { @@ -462,8 +462,8 @@ mod tests { use arbitrary_int::u11; use models::{ Apid, ComponentId, TcHeader, + acs::mgm::request::HkRequest, ccsds::{CcsdsTcPacketOwned, CcsdsTmPacketOwned}, - mgm::request::HkRequest, pcdu::{SwitchRequest, SwitchState, SwitchStateBinary}, }; use satrs::{request::GenericMessage, spacepackets::SpacePacketHeader}; @@ -490,7 +490,7 @@ mod tests { pub fn create_request_tc( select: MgmSelect, - request: models::mgm::request::Request, + request: models::acs::mgm::request::Request, ) -> models::ccsds::CcsdsTcPacketOwned { models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), @@ -533,6 +533,7 @@ mod tests { SpiCommunication::Test(TestSpiInterface::default()), shared_mgm_set, mode_leaf_helper, + Duration::from_millis(100), ); Self { assembly_mode_request_tx, @@ -600,9 +601,10 @@ mod tests { assert_eq!(tm_packet.tm_header.sender_id, ComponentId::AcsMgm0); - let response = postcard::from_bytes::(&tm_packet.payload) - .expect("failed to deserialize mode reply"); - matches!(response, models::mgm::response::Response::Ok); + let response = + postcard::from_bytes::(&tm_packet.payload) + .expect("failed to deserialize mode reply"); + matches!(response, models::acs::mgm::response::Response::Ok); // The device should have been polled once. assert_eq!(testbench.test_spi_interface().call_count, 1); let mgm_set = *testbench.handler.shared_mgm_set.lock().unwrap(); @@ -688,9 +690,10 @@ mod tests { assert_eq!(tm_packet.tm_header.sender_id, ComponentId::AcsMgm0); - let response = postcard::from_bytes::(&tm_packet.payload) - .expect("failed to deserialize mode reply"); - if let models::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) = + let response = + postcard::from_bytes::(&tm_packet.payload) + .expect("failed to deserialize mode reply"); + if let models::acs::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) = response { assert_eq!(data.valid, false); @@ -739,17 +742,18 @@ mod tests { assert_eq!(mode_tm.tm_header.sender_id, ComponentId::AcsMgm0); - let response = postcard::from_bytes::(&mode_tm.payload) - .expect("failed to deserialize mode reply"); - matches!(response, models::mgm::response::Response::Ok); + let response = + postcard::from_bytes::(&mode_tm.payload) + .expect("failed to deserialize mode reply"); + matches!(response, models::acs::mgm::response::Response::Ok); let hk_tm = testbench.tm_rx.try_recv().expect("no hk reply generated"); assert_eq!(hk_tm.tm_header.sender_id, ComponentId::AcsMgm0); - let response = postcard::from_bytes::(&hk_tm.payload) + let response = postcard::from_bytes::(&hk_tm.payload) .expect("failed to deserialize mode reply"); - if let models::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) = + if let models::acs::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) = response { // Set is now valid. diff --git a/satrs-example/src/acs/mgm_assembly.rs b/satrs-example/src/acs/mgm_assembly.rs index 7d1683f..ebea489 100644 --- a/satrs-example/src/acs/mgm_assembly.rs +++ b/satrs-example/src/acs/mgm_assembly.rs @@ -2,7 +2,7 @@ use std::{sync::mpsc, time::Duration}; use models::{ ComponentId, DeviceMode, - mgm_assembly::{AssemblyMode, request, response}, + acs::mgm_assembly::{Mode, request, response}, }; use satrs::spacepackets::CcsdsPacketIdAndPsc; use satrs_example::{ModeHelper, TmtcQueues}; @@ -16,8 +16,8 @@ pub struct ParentQueueHelper { /// Helper component for communication with a parent component, which is usually as assembly. pub struct ChildrenQueueHelper { - pub request_tx_queues: [mpsc::SyncSender; 2], - pub report_rx_queues: [mpsc::Receiver; 2], + pub request_tx_queues: [mpsc::SyncSender; 2], + pub report_rx_queues: [mpsc::Receiver; 2], } #[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] @@ -35,7 +35,7 @@ pub struct MgmInfo { /// MGM assembly component. pub struct Assembly { - mode_helper: ModeHelper, + mode_helper: ModeHelper, /// This boolean is used for the distinction between transitions commanded by the parent /// or by ground, and transitions which were commanded autonomously as part of children /// mode keeping. @@ -56,7 +56,7 @@ impl Assembly { mode_timeout: Duration, ) -> Self { Self { - mode_helper: ModeHelper::new(AssemblyMode::NoModeKeeping, mode_timeout), + mode_helper: ModeHelper::new(Mode::NoModeKeeping, mode_timeout), mode_keeping_transition: false, tmtc_queues, mgm_modes: [MgmInfo::default(); 2], @@ -80,14 +80,14 @@ impl Assembly { match self.tmtc_queues.tc_rx.try_recv() { Ok(packet) => { let tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&packet.sp_header); - match postcard::from_bytes::( + match postcard::from_bytes::( &packet.payload, ) { Ok(request) => match request { - models::mgm_assembly::request::Request::Ping => { + models::acs::mgm_assembly::request::Request::Ping => { self.send_telemetry(Some(tc_id), response::Response::Ok) } - models::mgm_assembly::request::Request::Mode(request) => { + models::acs::mgm_assembly::request::Request::Mode(request) => { match request { request::ModeRequest::SetMode(assembly_mode) => { self.start_transition(false, assembly_mode, Some(tc_id)) @@ -117,7 +117,7 @@ impl Assembly { pub fn send_telemetry( &self, tc_id: Option, - response: models::mgm_assembly::response::Response, + response: models::acs::mgm_assembly::response::Response, ) { match pack_ccsds_tm_packet_for_now(Self::ID, tc_id, &response) { Ok(packet) => { @@ -136,11 +136,11 @@ impl Assembly { match self.parent_queues.request_rx.try_recv() { Ok(request) => match request { request::ModeRequest::SetMode(assembly_mode) => match assembly_mode { - AssemblyMode::Device(_device_mode) => { + Mode::Device(_device_mode) => { self.start_transition(false, assembly_mode, None); } - AssemblyMode::NoModeKeeping => { - self.mode_helper.current = AssemblyMode::NoModeKeeping; + Mode::NoModeKeeping => { + self.mode_helper.current = Mode::NoModeKeeping; } }, request::ModeRequest::ReadMode => self @@ -165,12 +165,12 @@ impl Assembly { loop { match rx.try_recv() { Ok(report) => match report { - models::mgm::response::ModeResponse::Mode(device_mode) => { + models::acs::mgm::response::ModeResponse::Mode(device_mode) => { self.mgm_modes[idx].mode = Some(device_mode); self.mgm_modes[idx].reply_received = true; mode_report_received = true; } - models::mgm::response::ModeResponse::SetModeTimeout => { + models::acs::mgm::response::ModeResponse::SetModeTimeout => { // Ignore, handle this with our own timeout. log::warn!("MGM {} mode timeout", idx); } @@ -191,7 +191,7 @@ impl Assembly { // Transition is active, check for completion. if self.mode_helper.transition_active() && self.mgm_modes.iter().all(|i| i.reply_received) - && let AssemblyMode::Device(device_mode) = self.mode_helper.target.unwrap() + && let Mode::Device(device_mode) = self.mode_helper.target.unwrap() { // If at least one child reached the correct mode, we are done. if self.mgm_modes.iter().any(|i| i.mode == Some(device_mode)) { @@ -207,7 +207,7 @@ impl Assembly { } // Mode keeping active: Check children modes. - if let AssemblyMode::Device(device_mode) = self.mode_helper.current + if let Mode::Device(device_mode) = self.mode_helper.current && self .mgm_modes .iter() @@ -226,8 +226,8 @@ impl Assembly { } let target = self.mode_helper.target.unwrap(); let device_mode = match target { - AssemblyMode::Device(device_mode) => device_mode, - AssemblyMode::NoModeKeeping => { + Mode::Device(device_mode) => device_mode, + Mode::NoModeKeeping => { self.handle_mode_reached(true); return; } @@ -275,7 +275,7 @@ impl Assembly { pub fn command_children(&self, mode: DeviceMode) { for tx in &self.children_queues.request_tx_queues { - tx.send(models::mgm::request::ModeRequest::SetMode(mode)) + tx.send(models::acs::mgm::request::ModeRequest::SetMode(mode)) .unwrap(); } } @@ -283,7 +283,7 @@ impl Assembly { pub fn start_transition( &mut self, mode_keeping: bool, - target: AssemblyMode, + target: Mode, tc_id: Option, ) { self.mode_keeping_transition = mode_keeping; @@ -304,7 +304,7 @@ impl Assembly { } #[inline] - pub fn mode(&self) -> AssemblyMode { + pub fn mode(&self) -> Mode { self.mode_helper.current } @@ -322,8 +322,8 @@ mod tests { use arbitrary_int::u11; use models::{ Apid, Message, MessageType, TcHeader, + acs::mgm_assembly, ccsds::{CcsdsTcPacketOwned, CcsdsTmPacketOwned}, - mgm_assembly, }; use satrs::spacepackets::SpacePacketHeader; @@ -332,8 +332,8 @@ mod tests { pub struct Testbench { subsystem_req_tx: mpsc::SyncSender, subsystem_report_rx: mpsc::Receiver, - mgm_request_rx: [mpsc::Receiver; 2], - mgm_report_tx: [mpsc::SyncSender; 2], + mgm_request_rx: [mpsc::Receiver; 2], + mgm_report_tx: [mpsc::SyncSender; 2], tc_tx: mpsc::SyncSender, tm_rx: mpsc::Receiver, assembly: Assembly, @@ -396,7 +396,7 @@ mod tests { } pub fn create_request_tc( - request: models::mgm_assembly::request::Request, + request: models::acs::mgm_assembly::request::Request, ) -> models::ccsds::CcsdsTcPacketOwned { models::ccsds::CcsdsTcPacketOwned::new_with_request( SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)), @@ -411,7 +411,7 @@ mod tests { tb.assert_all_queues_empty(); tb.assembly.periodic_operation(); tb.assert_all_queues_empty(); - assert_eq!(tb.assembly.mode(), AssemblyMode::NoModeKeeping); + assert_eq!(tb.assembly.mode(), Mode::NoModeKeeping); } #[test] @@ -419,7 +419,7 @@ mod tests { let mut tb = Testbench::new(); tb.tc_tx .send(create_request_tc(mgm_assembly::request::Request::Mode( - request::ModeRequest::SetMode(AssemblyMode::Device(DeviceMode::Normal)), + request::ModeRequest::SetMode(Mode::Device(DeviceMode::Normal)), ))) .unwrap(); tb.assembly.periodic_operation(); @@ -429,13 +429,13 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // Confirm the mode is set. for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode( + tx.send(models::acs::mgm::response::ModeResponse::Mode( DeviceMode::Normal, )) .unwrap(); @@ -443,7 +443,7 @@ mod tests { tb.assembly.periodic_operation(); assert!(!tb.assembly.mode_transition_active()); - assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal)); + assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal)); let response = tb.tm_rx.try_recv().unwrap(); assert_eq!(response.tm_header.sender_id, Assembly::ID); @@ -456,7 +456,7 @@ mod tests { fn test_parent_commanded_transition() { let mut tb = Testbench::new(); tb.subsystem_req_tx - .send(request::ModeRequest::SetMode(AssemblyMode::Device( + .send(request::ModeRequest::SetMode(Mode::Device( DeviceMode::Normal, ))) .unwrap(); @@ -467,13 +467,13 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // Confirm the mode is set. for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode( + tx.send(models::acs::mgm::response::ModeResponse::Mode( DeviceMode::Normal, )) .unwrap(); @@ -481,12 +481,12 @@ mod tests { tb.assembly.periodic_operation(); assert!(!tb.assembly.mode_transition_active()); - assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal)); + assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal)); let report = tb.subsystem_report_rx.try_recv().unwrap(); assert_eq!( report, - response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal)) + response::ModeReport::Mode(Mode::Device(DeviceMode::Normal)) ); } @@ -494,7 +494,7 @@ mod tests { fn test_one_mgm_is_sufficient() { let mut tb = Testbench::new(); tb.subsystem_req_tx - .send(request::ModeRequest::SetMode(AssemblyMode::Device( + .send(request::ModeRequest::SetMode(Mode::Device( DeviceMode::Normal, ))) .unwrap(); @@ -505,28 +505,30 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // One device is sufficient. tb.mgm_report_tx[0] - .send(models::mgm::response::ModeResponse::Mode( + .send(models::acs::mgm::response::ModeResponse::Mode( DeviceMode::Normal, )) .unwrap(); tb.mgm_report_tx[1] - .send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off)) + .send(models::acs::mgm::response::ModeResponse::Mode( + DeviceMode::Off, + )) .unwrap(); tb.assembly.periodic_operation(); assert!(!tb.assembly.mode_transition_active()); - assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal)); + assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal)); let report = tb.subsystem_report_rx.try_recv().unwrap(); assert_eq!( report, - response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal)) + response::ModeReport::Mode(Mode::Device(DeviceMode::Normal)) ); } @@ -534,7 +536,7 @@ mod tests { fn test_mode_commanding_fails() { let mut tb = Testbench::new(); tb.subsystem_req_tx - .send(request::ModeRequest::SetMode(AssemblyMode::Device( + .send(request::ModeRequest::SetMode(Mode::Device( DeviceMode::Normal, ))) .unwrap(); @@ -545,19 +547,21 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // Confirm the mode is set. for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off)) - .unwrap(); + tx.send(models::acs::mgm::response::ModeResponse::Mode( + DeviceMode::Off, + )) + .unwrap(); } tb.assembly.periodic_operation(); assert!(!tb.assembly.mode_transition_active()); - assert_eq!(tb.assembly.mode(), AssemblyMode::NoModeKeeping); + assert_eq!(tb.assembly.mode(), Mode::NoModeKeeping); let report = tb.subsystem_report_rx.try_recv().unwrap(); assert_eq!( @@ -570,7 +574,7 @@ mod tests { fn test_mode_keeping_fails() { let mut tb = Testbench::new(); tb.subsystem_req_tx - .send(request::ModeRequest::SetMode(AssemblyMode::Device( + .send(request::ModeRequest::SetMode(Mode::Device( DeviceMode::Normal, ))) .unwrap(); @@ -581,13 +585,13 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // Confirm the mode is set. for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode( + tx.send(models::acs::mgm::response::ModeResponse::Mode( DeviceMode::Normal, )) .unwrap(); @@ -595,17 +599,19 @@ mod tests { tb.assembly.periodic_operation(); assert!(!tb.assembly.mode_transition_active()); - assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal)); + assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal)); let report = tb.subsystem_report_rx.try_recv().unwrap(); assert_eq!( report, - response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal)) + response::ModeReport::Mode(Mode::Device(DeviceMode::Normal)) ); for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off)) - .unwrap(); + tx.send(models::acs::mgm::response::ModeResponse::Mode( + DeviceMode::Off, + )) + .unwrap(); } // This should start mode keeping. tb.assembly.periodic_operation(); @@ -615,14 +621,16 @@ mod tests { let request = rx.try_recv().unwrap(); assert_eq!( request, - models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) + models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal) ); } // Let the mode keeping fail. for tx in tb.mgm_report_tx.iter() { - tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off)) - .unwrap(); + tx.send(models::acs::mgm::response::ModeResponse::Mode( + DeviceMode::Off, + )) + .unwrap(); } tb.assembly.periodic_operation(); let report = tb.subsystem_report_rx.try_recv().unwrap(); diff --git a/satrs-example/src/acs/mgt.rs b/satrs-example/src/acs/mgt.rs new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/satrs-example/src/acs/mgt.rs @@ -0,0 +1 @@ + diff --git a/satrs-example/src/acs/mod.rs b/satrs-example/src/acs/mod.rs index 60382dd..c7cb38d 100644 --- a/satrs-example/src/acs/mod.rs +++ b/satrs-example/src/acs/mod.rs @@ -1,6 +1,5 @@ pub mod ctrl; - pub mod mgm; pub mod mgm_assembly; - +pub mod mgt; pub mod subsystem; diff --git a/satrs-example/src/acs/subsystem.rs b/satrs-example/src/acs/subsystem.rs index ec11077..07169e8 100644 --- a/satrs-example/src/acs/subsystem.rs +++ b/satrs-example/src/acs/subsystem.rs @@ -1 +1,116 @@ -// TODO: Write subsystem +use std::sync::mpsc::SyncSender; + +use models::ComponentId; + +#[derive(Debug)] +pub struct TransitionInfo { + check_mode_reached: bool, +} + +#[derive(Debug)] +pub struct ChildModes { + mgm_assembly_mode: models::acs::mgm_assembly::Mode, + mgt_mode: models::acs::mgt::Mode, + controller_mode: models::acs::ctrl::Mode, +} + +#[derive(Debug)] +pub struct TransitionCommands { + mgm_assembly_mode: Option<(models::acs::mgm_assembly::Mode, TransitionInfo)>, + mgt_mode: Option<(models::acs::mgt::Mode, TransitionInfo)>, + controller_mode: Option<(models::acs::ctrl::Mode, TransitionInfo)>, +} + +const OFF_SEQUENCE: [TransitionCommands; 2] = [ + TransitionCommands { + mgm_assembly_mode: None, + mgt_mode: None, + controller_mode: Some(( + models::acs::ctrl::Mode::Passive, + TransitionInfo { + check_mode_reached: true, + }, + )), + }, + TransitionCommands { + mgm_assembly_mode: Some(( + models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Off), + TransitionInfo { + check_mode_reached: false, + }, + )), + mgt_mode: Some(( + models::acs::mgt::Mode::Off, + TransitionInfo { + check_mode_reached: false, + }, + )), + controller_mode: None, + }, +]; + +const SAFE_SEQUENCE: [TransitionCommands; 2] = [ + TransitionCommands { + mgm_assembly_mode: Some(( + models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Normal), + TransitionInfo { + check_mode_reached: false, + }, + )), + mgt_mode: Some(( + models::acs::mgt::Mode::Normal, + TransitionInfo { + check_mode_reached: false, + }, + )), + controller_mode: None, + }, + TransitionCommands { + mgm_assembly_mode: None, + mgt_mode: None, + controller_mode: Some(( + models::acs::ctrl::Mode::Safe, + TransitionInfo { + check_mode_reached: false, + }, + )), + }, +]; + +#[derive(Debug)] +pub struct ModeRequestSenders { + mode_request_ctrl: SyncSender, + mode_request_assy: SyncSender, + mode_request_mgt: SyncSender, +} + +#[derive(Debug)] +pub struct ModeReportReceivers { + mode_response_ctrl: SyncSender, + mode_response_assy: SyncSender, + mode_response_mgt: SyncSender, +} + +#[derive(Debug)] +pub struct Subsystem { + current_mode: models::acs::subsystem::Mode, + current_child_modes: Option, + mode_request_senders: ModeRequestSenders, + mode_report_receivers: ModeReportReceivers, +} + +impl Subsystem { + pub const ID: ComponentId = ComponentId::AcsSubsystem; + + pub fn new( + mode_request_senders: ModeRequestSenders, + mode_report_receivers: ModeReportReceivers, + ) -> Self { + Self { + current_mode: models::acs::subsystem::Mode::Off, + current_child_modes: None, + mode_request_senders, + mode_report_receivers, + } + } +} diff --git a/satrs-example/src/main.rs b/satrs-example/src/main.rs index 922f8ba..bdef7f4 100644 --- a/satrs-example/src/main.rs +++ b/satrs-example/src/main.rs @@ -188,7 +188,7 @@ fn main() { request_rx: mgm_0_mode_request_rx, report_tx: mgm_0_mode_report_tx, }, - Duration::from_millis(1000) + Duration::from_millis(1000), ); let mut mgm_1_handler = mgm::MgmHandlerLis3Mdl::new( mgm::MgmId::_1, @@ -203,7 +203,7 @@ fn main() { request_rx: mgm_1_mode_request_rx, report_tx: mgm_1_mode_report_tx, }, - Duration::from_millis(1000) + Duration::from_millis(1000), ); let mut mgm_assembly = mgm_assembly::Assembly::new( mgm_assembly::ParentQueueHelper {