From 9db7acf3554e3eaa3ff38696d6eb92b491881fe1 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 21 Nov 2024 18:35:16 +0100 Subject: [PATCH 1/9] continue --- satrs/src/lib.rs | 5 +- satrs/src/mode_tree.rs | 161 +++++++++++++++++++++++++++++++++-- satrs/src/subsystem.rs | 134 ++++++++++++++++++++++++++++++ satrs/tests/mode_tree.rs | 175 +++++++++++++++++++++++++++++---------- 4 files changed, 423 insertions(+), 52 deletions(-) create mode 100644 satrs/src/subsystem.rs diff --git a/satrs/src/lib.rs b/satrs/src/lib.rs index 8c9fab8..43b1d17 100644 --- a/satrs/src/lib.rs +++ b/satrs/src/lib.rs @@ -36,15 +36,16 @@ pub mod pus; pub mod queue; pub mod request; pub mod res_code; -pub mod time; -pub mod tmtc; #[cfg(feature = "alloc")] pub mod scheduling; +pub mod time; +pub mod tmtc; pub mod action; pub mod hk; pub mod mode; pub mod params; +pub mod subsystem; pub use spacepackets; diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 1cddd32..e0d99ed 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -15,23 +15,168 @@ pub enum TableEntryType { Sequence, } -pub struct ModeTableEntry { +/// Common fields required for both target and sequence table entries. +/// +/// The most important parameters here are the target ID which this entry belongs to, and the mode +/// and submode the entry either will be commanded to for sequence table entries or which will be +/// monitored for target table entries. +#[derive(Debug, Copy, Clone)] +pub struct ModeTableEntryCommon { /// Name of respective table entry. pub name: &'static str, - /// Target channel ID. - pub channel_id: ComponentId, + /// Target component ID. + pub target_id: ComponentId, + /// Has a different meaning depending on whether this is a sequence table or a target table. + /// + /// - For sequence tables, this denotes the mode which will be commanded + /// - For target tables, this is the mode which the target children should have and which + /// might be monitored depending on configuration. pub mode_submode: ModeAndSubmode, + /// This mask allows to specify multiple allowed submodes for a given mode. pub allowed_submode_mask: Option, +} + +impl ModeTableEntryCommon { + pub fn set_allowed_submode_mask(&mut self, mask: Submode) { + self.allowed_submode_mask = Some(mask); + } + + pub fn allowed_submode_mask(&self) -> Option { + self.allowed_submode_mask + } +} + +/// An entry for the target tables. +#[derive(Debug)] +pub struct TargetTableEntry { + pub common: ModeTableEntryCommon, + pub monitor_state: bool, +} + +impl TargetTableEntry { + pub fn new( + name: &'static str, + target_id: ComponentId, + mode_submode: ModeAndSubmode, + monitor_state: bool, + ) -> Self { + Self { + common: ModeTableEntryCommon { + name, + target_id, + mode_submode, + allowed_submode_mask: None, + }, + monitor_state, + } + } + + delegate::delegate! { + to self.common { + pub fn set_allowed_submode_mask(&mut self, mask: Submode); + pub fn allowed_submode_mask(&self) -> Option; + } + } +} + +#[derive(Debug)] +pub struct TargetTableMapValue { + /// Name for a given mode table entry. + pub name: &'static str, + /// These are the rows of the a target table. + pub entries: Vec, +} + +impl TargetTableMapValue { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } + + pub fn add_entry(&mut self, entry: TargetTableEntry) { + self.entries.push(entry); + } +} + +/// An entry for the sequence tables. +/// +/// The `check_success` field instructs the mode sequence executor to verify that the +/// target mode was actually reached before executing the next sequence. +pub struct SequenceTableEntry { + pub common: ModeTableEntryCommon, pub check_success: bool, } -pub struct ModeTableMapValue { - /// Name for a given mode table entry. - pub name: &'static str, - pub entries: Vec, +impl SequenceTableEntry { + pub fn new( + name: &'static str, + target_id: ComponentId, + mode_submode: ModeAndSubmode, + check_success: bool, + ) -> Self { + Self { + common: ModeTableEntryCommon { + name, + target_id, + mode_submode, + allowed_submode_mask: None, + }, + check_success, + } + } + + delegate::delegate! { + to self.common { + pub fn set_allowed_submode_mask(&mut self, mask: Submode); + pub fn allowed_submode_mask(&self) -> Option; + } + } } -pub type ModeTable = HashMap; +pub struct SequenceTableMapTable { + /// Name for a given mode sequence. + pub name: &'static str, + /// These are the rows of the a sequence table. + pub entries: Vec, +} + +impl SequenceTableMapTable { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } + + pub fn add_entry(&mut self, entry: SequenceTableEntry) { + self.entries.push(entry); + } +} + +pub struct SequenceTableMapValue { + /// Name for a given mode sequence. + pub name: &'static str, + /// Each sequence can consists of multiple sequences that are executed consecutively. + pub entries: Vec, +} + +impl SequenceTableMapValue { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } + + pub fn add_sequence_table(&mut self, entry: SequenceTableMapTable) { + self.entries.push(entry); + } +} + +pub struct TargetModeTable(pub HashMap); +pub struct SequenceModeTable(pub HashMap); #[cfg(test)] mod tests {} diff --git a/satrs/src/subsystem.rs b/satrs/src/subsystem.rs new file mode 100644 index 0000000..033821f --- /dev/null +++ b/satrs/src/subsystem.rs @@ -0,0 +1,134 @@ +use crate::{ + mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender}, + mode_tree::{SequenceModeTable, SequenceTableMapTable, SequenceTableMapValue}, + queue::GenericTargetedMessagingError, + request::RequestId, + ComponentId, +}; + +#[derive(Debug, PartialEq, Eq)] +pub enum SequenceExecutionHelperStates { + Idle, + AwaitingCheckSuccess, + Done, +} + +#[derive(Debug)] +pub struct SequenceExecutionHelper { + target_mode: Mode, + state: SequenceExecutionHelperStates, + request_id: RequestId, + current_sequence_index: Option, +} + +pub trait CheckSuccessProvider { + fn mode_request_requires_success_check( + &mut self, + target_id: ComponentId, + target_mode: ModeAndSubmode, + ); +} + +#[derive(Debug)] +pub enum SequenceHandlerResult { + SequenceDone, + SequenceStepDone, + AwaitingSuccessCheck, +} + +impl SequenceExecutionHelper { + pub fn new( + mode: Mode, + request_id: RequestId, + sequence_table: &SequenceModeTable, + ) -> Option { + if !sequence_table.0.contains_key(&mode) { + return None; + } + Some(Self { + target_mode: mode, + state: SequenceExecutionHelperStates::Idle, + request_id, + current_sequence_index: None, + }) + } + + pub fn confirm_sequence_done(&mut self) { + if let SequenceExecutionHelperStates::AwaitingCheckSuccess = self.state { + self.state = SequenceExecutionHelperStates::Idle; + } + } + + pub fn run( + &mut self, + table: &SequenceModeTable, + sender: &impl ModeRequestSender, + ) -> Result { + if self.state == SequenceExecutionHelperStates::AwaitingCheckSuccess { + return Ok(SequenceHandlerResult::AwaitingSuccessCheck); + } + match self.current_sequence_index { + Some(idx) => { + // Execute the sequence. + let seq_table_value = table.0.get(&self.target_mode).unwrap(); + self.execute_sequence_and_map_to_result(seq_table_value, idx, sender) + } + None => { + // Find the first sequence + let seq_table_value = table.0.get(&self.target_mode).unwrap(); + if seq_table_value.entries.is_empty() { + Ok(SequenceHandlerResult::SequenceDone) + } else { + self.current_sequence_index = Some(0); + self.execute_sequence_and_map_to_result(seq_table_value, 0, sender) + } + } + } + } + + pub fn execute_sequence_and_map_to_result( + &mut self, + seq_table_value: &SequenceTableMapValue, + sequence_idx: usize, + sender: &impl ModeRequestSender, + ) -> Result { + if Self::execute_sequence( + self.request_id, + &seq_table_value.entries[sequence_idx], + sender, + )? { + self.state = SequenceExecutionHelperStates::AwaitingCheckSuccess; + Ok(SequenceHandlerResult::AwaitingSuccessCheck) + } else if seq_table_value.entries.len() - 1 == sequence_idx { + return Ok(SequenceHandlerResult::SequenceDone); + } else { + self.current_sequence_index = Some(sequence_idx + 1); + return Ok(SequenceHandlerResult::SequenceStepDone); + } + } + + pub fn execute_sequence( + request_id: RequestId, + map_table: &SequenceTableMapTable, + //sequence_idx: usize, + sender: &impl ModeRequestSender, + ) -> Result { + let mut some_succes_check_required = false; + for entry in &map_table.entries { + sender.send_mode_request( + request_id, + entry.common.target_id, + ModeRequest::SetMode(entry.common.mode_submode), + )?; + if entry.check_success { + some_succes_check_required = true; + } + } + Ok(some_succes_check_required) + } +} + +#[cfg(test)] +mod tests { + pub struct SatSystem {} +} diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 17f9836..d8773c4 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -19,7 +19,8 @@ pub enum TestComponentId { Device1 = 1, Device2 = 2, Assembly = 3, - PusModeService = 4, + Subsystem = 4, + PusModeService = 5, } struct PusModeService { @@ -41,78 +42,86 @@ impl PusModeService { } } -struct TestDevice { +struct TestSubsystem { pub name: String, - pub mode_node: ModeRequestHandlerMpscBounded, + pub mode_node: ModeRequestorAndHandlerMpscBounded, + pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, + pub target_mode_and_submode: Option, } -impl TestDevice { - pub fn run(&mut self) { - self.check_mode_requests().expect("mode messaging error"); - } - - pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { - if let Some(request) = self.mode_node.try_recv_mode_request()? { - self.handle_mode_request(request)? - } - Ok(()) - } -} - -impl ModeProvider for TestDevice { +impl ModeProvider for TestSubsystem { fn mode_and_submode(&self) -> ModeAndSubmode { self.mode_and_submode } } -impl ModeRequestHandler for TestDevice { +impl ModeRequestHandler for TestSubsystem { type Error = ModeError; fn start_transition( &mut self, requestor: MessageMetadata, mode_and_submode: ModeAndSubmode, - ) -> Result<(), ModeError> { - self.mode_and_submode = mode_and_submode; - self.handle_mode_reached(Some(requestor))?; + ) -> Result<(), Self::Error> { + self.mode_requestor_info = Some(requestor); + self.target_mode_and_submode = Some(mode_and_submode); + // Execute mode map by executing the transition table(s). Ok(()) } - fn announce_mode(&self, _requestor_info: Option, _recursive: bool) { + fn announce_mode(&self, requestor_info: Option, recursive: bool) { println!( - "{}: announcing mode: {:?}", - self.name, self.mode_and_submode + "TestAssembly: Announcing mode (recursively: {}): {:?}", + recursive, self.mode_and_submode ); + // self.mode_requestor_info = Some((request_id, sender_id)); + let mut mode_request = ModeRequest::AnnounceMode; + if recursive { + mode_request = ModeRequest::AnnounceModeRecursive; + } + let request_id = requestor_info.map_or(0, |info| info.request_id()); + self.mode_node + .request_sender_map + .0 + .iter() + .for_each(|(_, sender)| { + sender + .send(GenericMessage::new( + MessageMetadata::new(request_id, self.mode_node.local_channel_id_generic()), + mode_request, + )) + .expect("sending mode request failed"); + }); } - fn handle_mode_reached(&mut self, requestor: Option) -> Result<(), ModeError> { - if let Some(requestor) = requestor { + fn handle_mode_reached( + &mut self, + requestor_info: Option, + ) -> Result<(), Self::Error> { + if let Some(requestor) = requestor_info { self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; } Ok(()) } - fn send_mode_reply( - &self, - requestor_info: MessageMetadata, - reply: ModeReply, - ) -> Result<(), ModeError> { - self.mode_node.send_mode_reply(requestor_info, reply)?; - Ok(()) - } fn handle_mode_info( &mut self, requestor_info: MessageMetadata, info: ModeAndSubmode, - ) -> Result<(), ModeError> { - // A device is a leaf in the tree.. so this really should not happen - println!( - "{}: unexpected mode info from {:?} with mode: {:?}", - self.name, - requestor_info.sender_id(), - info - ); + ) -> Result<(), Self::Error> { + // TODO: Need to check whether mode table execution is finished. + // This works by checking the children modes received through replies against the + // mode table after all transition tables were executed. + Ok(()) + } + + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), Self::Error> { + self.mode_node.send_mode_reply(requestor_info, reply)?; Ok(()) } } @@ -253,11 +262,88 @@ impl ModeRequestHandler for TestAssembly { } } +struct TestDevice { + pub name: String, + pub mode_node: ModeRequestHandlerMpscBounded, + pub mode_and_submode: ModeAndSubmode, +} + +impl TestDevice { + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { + if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.handle_mode_request(request)? + } + Ok(()) + } +} + +impl ModeProvider for TestDevice { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} + +impl ModeRequestHandler for TestDevice { + type Error = ModeError; + + fn start_transition( + &mut self, + requestor: MessageMetadata, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), ModeError> { + self.mode_and_submode = mode_and_submode; + self.handle_mode_reached(Some(requestor))?; + Ok(()) + } + + fn announce_mode(&self, _requestor_info: Option, _recursive: bool) { + println!( + "{}: announcing mode: {:?}", + self.name, self.mode_and_submode + ); + } + + fn handle_mode_reached(&mut self, requestor: Option) -> Result<(), ModeError> { + if let Some(requestor) = requestor { + self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; + } + Ok(()) + } + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), ModeError> { + self.mode_node.send_mode_reply(requestor_info, reply)?; + Ok(()) + } + + fn handle_mode_info( + &mut self, + requestor_info: MessageMetadata, + info: ModeAndSubmode, + ) -> Result<(), ModeError> { + // A device is a leaf in the tree.. so this really should not happen + println!( + "{}: unexpected mode info from {:?} with mode: {:?}", + self.name, + requestor_info.sender_id(), + info + ); + Ok(()) + } +} + fn main() { // All request channel handles. let (request_sender_to_dev1, request_receiver_dev1) = mpsc::sync_channel(10); let (request_sender_to_dev2, request_receiver_dev2) = mpsc::sync_channel(10); let (request_sender_to_assy, request_receiver_assy) = mpsc::sync_channel(10); + let (request_sender_to_subsystem, request_receiver_subsystem) = mpsc::sync_channel(10); // All reply channel handles. let (reply_sender_to_assy, reply_receiver_assy) = mpsc::sync_channel(10); @@ -298,6 +384,11 @@ fn main() { TestComponentId::Device2 as ComponentId, request_sender_to_dev2.clone(), ); + mode_node_pus.add_message_target( + TestComponentId::Subsystem as ComponentId, + request_sender_to_subsystem.clone(), + ); + mode_node_assy.add_request_target( TestComponentId::Device1 as ComponentId, request_sender_to_dev1, -- 2.43.0 From 4204b8a7e3617c7dc7b5cac231a70da7c5e196d5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Nov 2024 10:25:56 +0100 Subject: [PATCH 2/9] continue mode tree --- satrs/src/mode_tree.rs | 159 +++++++++---- satrs/src/subsystem.rs | 13 +- satrs/tests/mode_tree.rs | 496 +++++++++++++++++++++++++++++++-------- 3 files changed, 507 insertions(+), 161 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index e0d99ed..2940900 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -6,6 +6,9 @@ use crate::{ ComponentId, }; +#[cfg(feature = "alloc")] +pub use alloc_mod::*; + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum TableEntryType { /// Target table containing information of the expected children modes for given mode. @@ -79,31 +82,11 @@ impl TargetTableEntry { } } -#[derive(Debug)] -pub struct TargetTableMapValue { - /// Name for a given mode table entry. - pub name: &'static str, - /// These are the rows of the a target table. - pub entries: Vec, -} - -impl TargetTableMapValue { - pub fn new(name: &'static str) -> Self { - Self { - name, - entries: Default::default(), - } - } - - pub fn add_entry(&mut self, entry: TargetTableEntry) { - self.entries.push(entry); - } -} - /// An entry for the sequence tables. /// /// The `check_success` field instructs the mode sequence executor to verify that the /// target mode was actually reached before executing the next sequence. +#[derive(Debug)] pub struct SequenceTableEntry { pub common: ModeTableEntryCommon, pub check_success: bool, @@ -135,48 +118,124 @@ impl SequenceTableEntry { } } -pub struct SequenceTableMapTable { - /// Name for a given mode sequence. - pub name: &'static str, - /// These are the rows of the a sequence table. - pub entries: Vec, +pub trait ModeStoreProvider { + fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode); + fn get_mode(&self, target_id: ComponentId) -> Option; + fn set_mode(&mut self, target_id: ComponentId, mode: ModeAndSubmode); } -impl SequenceTableMapTable { - pub fn new(name: &'static str) -> Self { - Self { - name, - entries: Default::default(), +#[cfg(feature = "alloc")] +pub mod alloc_mod { + use super::*; + + #[derive(Debug)] + pub struct TargetTableMapValue { + /// Name for a given mode table entry. + pub name: &'static str, + /// These are the rows of the a target table. + pub entries: Vec, + } + + impl TargetTableMapValue { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } + + pub fn add_entry(&mut self, entry: TargetTableEntry) { + self.entries.push(entry); } } - pub fn add_entry(&mut self, entry: SequenceTableEntry) { - self.entries.push(entry); + #[derive(Debug)] + pub struct SequenceTableMapTable { + /// Name for a given mode sequence. + pub name: &'static str, + /// These are the rows of the a sequence table. + pub entries: Vec, } -} -pub struct SequenceTableMapValue { - /// Name for a given mode sequence. - pub name: &'static str, - /// Each sequence can consists of multiple sequences that are executed consecutively. - pub entries: Vec, -} + impl SequenceTableMapTable { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } -impl SequenceTableMapValue { - pub fn new(name: &'static str) -> Self { - Self { - name, - entries: Default::default(), + pub fn add_entry(&mut self, entry: SequenceTableEntry) { + self.entries.push(entry); } } - pub fn add_sequence_table(&mut self, entry: SequenceTableMapTable) { - self.entries.push(entry); + #[derive(Debug)] + pub struct SequenceTableMapValue { + /// Name for a given mode sequence. + pub name: &'static str, + /// Each sequence can consists of multiple sequences that are executed consecutively. + pub entries: Vec, + } + + impl SequenceTableMapValue { + pub fn new(name: &'static str) -> Self { + Self { + name, + entries: Default::default(), + } + } + + pub fn add_sequence_table(&mut self, entry: SequenceTableMapTable) { + self.entries.push(entry); + } + } + + #[derive(Debug, Default)] + pub struct TargetModeTables(pub HashMap); + #[derive(Debug, Default)] + pub struct SequenceModeTables(pub HashMap); + + #[derive(Debug, Default)] + pub struct ModeStoreVec(pub alloc::vec::Vec<(ComponentId, ModeAndSubmode)>); + #[derive(Debug, Default)] + pub struct ModeStoreMap(pub hashbrown::HashMap); + + impl ModeStoreProvider for ModeStoreVec { + fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) { + self.0.push((target_id, mode)); + } + + fn get_mode(&self, target_id: ComponentId) -> Option { + self.0.iter().find_map(|(id, mode)| { + if *id == target_id { + return Some(*mode); + } + None + }) + } + + fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) { + self.0.iter_mut().for_each(|(id, mode)| { + if *id == target_id { + *mode = mode_to_set; + } + }); + } + } + + impl ModeStoreProvider for ModeStoreMap { + fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) { + self.0.insert(target_id, mode); + } + fn get_mode(&self, target_id: ComponentId) -> Option { + self.0.get(&target_id).copied() + } + fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) { + self.0.insert(target_id, mode_to_set); + } } } -pub struct TargetModeTable(pub HashMap); -pub struct SequenceModeTable(pub HashMap); - #[cfg(test)] mod tests {} diff --git a/satrs/src/subsystem.rs b/satrs/src/subsystem.rs index 033821f..199336d 100644 --- a/satrs/src/subsystem.rs +++ b/satrs/src/subsystem.rs @@ -1,6 +1,6 @@ use crate::{ mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender}, - mode_tree::{SequenceModeTable, SequenceTableMapTable, SequenceTableMapValue}, + mode_tree::{SequenceModeTables, SequenceTableMapTable, SequenceTableMapValue}, queue::GenericTargetedMessagingError, request::RequestId, ComponentId, @@ -40,9 +40,9 @@ impl SequenceExecutionHelper { pub fn new( mode: Mode, request_id: RequestId, - sequence_table: &SequenceModeTable, + sequence_tables: &SequenceModeTables, ) -> Option { - if !sequence_table.0.contains_key(&mode) { + if !sequence_tables.0.contains_key(&mode) { return None; } Some(Self { @@ -61,7 +61,7 @@ impl SequenceExecutionHelper { pub fn run( &mut self, - table: &SequenceModeTable, + table: &SequenceModeTables, sender: &impl ModeRequestSender, ) -> Result { if self.state == SequenceExecutionHelperStates::AwaitingCheckSuccess { @@ -110,7 +110,6 @@ impl SequenceExecutionHelper { pub fn execute_sequence( request_id: RequestId, map_table: &SequenceTableMapTable, - //sequence_idx: usize, sender: &impl ModeRequestSender, ) -> Result { let mut some_succes_check_required = false; @@ -129,6 +128,4 @@ impl SequenceExecutionHelper { } #[cfg(test)] -mod tests { - pub struct SatSystem {} -} +mod tests {} diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index d8773c4..cd98536 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -2,11 +2,15 @@ use core::cell::Cell; use std::{println, sync::mpsc}; use satrs::mode::{ - ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, - ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, - ModeRequestorBoundedMpsc, + Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, + ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender, + ModeRequestorAndHandlerMpscBounded, ModeRequestorBoundedMpsc, }; -use satrs::request::MessageMetadata; +use satrs::mode_tree::alloc_mod::{ + ModeStoreVec, SequenceModeTables, SequenceTableMapValue, TargetModeTables, TargetTableMapValue, +}; +use satrs::mode_tree::ModeStoreProvider; +use satrs::request::{MessageMetadata, MessageSender}; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, queue::GenericTargetedMessagingError, @@ -15,12 +19,63 @@ use satrs::{ }; use std::string::{String, ToString}; +const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff, 0); +const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff - 1, 0); + pub enum TestComponentId { - Device1 = 1, - Device2 = 2, - Assembly = 3, - Subsystem = 4, - PusModeService = 5, + MagnetometerDevice = 1, + MagnetorquerDevice = 2, + ReactionWheelDevice = 3, + StartrackerDevice = 4, + ReactionWheelAssembly = 8, + MagnetometerAssembly = 9, + AcsController = 14, + AcsSubsystem = 15, + PusModeService = 16, +} + +pub type RequestSenderType = mpsc::SyncSender>; +pub type ReplySenderType = mpsc::SyncSender>; + +/// Trait which denotes that an object is a parent in a mode tree. +/// +/// A mode parent is capable of sending mode requests to child objects and has a unique component +/// ID. +pub trait ModeParent { + type Sender: MessageSender; + + fn id(&self) -> ComponentId; + fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender); +} + +/// Trait which denotes that an object is a child in a mode tree. +/// +/// A child is capable of sending mode replies to parent objects and has a unique component ID. +pub trait ModeChild { + type Sender: MessageSender; + + fn id(&self) -> ComponentId; + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender); +} + +/// Utility method which connects a mode tree parent object to a child object by calling +/// [ModeParent::add_mode_child] on the [parent][ModeParent] and calling +/// [ModeChild::add_mode_parent] on the [child][ModeChild]. +/// +/// # Arguments +/// +/// * `parent` - The parent object which implements [ModeParent]. +/// * `request_sender` - Sender object to send mode requests to the child. +/// * `child` - The child object which implements [ModeChild]. +/// * `reply_sender` - Sender object to send mode replies to the parent. +pub fn connect_mode_nodes( + parent: &mut impl ModeParent, + request_sender: ReqSender, + child: &mut impl ModeChild, + reply_sender: ReplySender, +) { + parent.add_mode_child(child.id(), request_sender); + child.add_mode_parent(parent.id(), reply_sender); } struct PusModeService { @@ -29,11 +84,11 @@ struct PusModeService { } impl PusModeService { - pub fn send_announce_mode_cmd_to_assy(&self) { + pub fn send_announce_mode_cmd_to_subsystem(&self) { self.mode_node .send_mode_request( self.request_id_counter.get(), - TestComponentId::Assembly as ComponentId, + TestComponentId::AcsSubsystem as ComponentId, ModeRequest::AnnounceModeRecursive, ) .unwrap(); @@ -42,21 +97,71 @@ impl PusModeService { } } -struct TestSubsystem { - pub name: String, +impl ModeParent for PusModeService { + type Sender = RequestSenderType; + + fn id(&self) -> ComponentId { + TestComponentId::PusModeService as ComponentId + } + + fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { + self.mode_node.add_message_target(id, request_sender); + } +} + +struct AcsSubsystem { pub mode_node: ModeRequestorAndHandlerMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, + pub children_mode_store: ModeStoreVec, + pub target_tables: TargetModeTables, + pub sequence_tables: SequenceModeTables, } -impl ModeProvider for TestSubsystem { +impl AcsSubsystem { + pub fn add_target_and_sequence_table( + &mut self, + mode: Mode, + target_table_val: TargetTableMapValue, + sequence_table_val: SequenceTableMapValue, + ) { + self.target_tables.0.insert(mode, target_table_val); + self.sequence_tables.0.insert(mode, sequence_table_val); + } +} + +impl ModeParent for AcsSubsystem { + type Sender = RequestSenderType; + + fn id(&self) -> ComponentId { + TestComponentId::PusModeService as ComponentId + } + + fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { + self.children_mode_store.add_component(id, UNKNOWN_MODE); + self.mode_node.add_request_target(id, request_sender); + } +} + +impl ModeChild for AcsSubsystem { + type Sender = ReplySenderType; + + fn id(&self) -> ComponentId { + TestComponentId::PusModeService as ComponentId + } + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { + self.mode_node.add_reply_target(id, reply_sender); + } +} + +impl ModeProvider for AcsSubsystem { fn mode_and_submode(&self) -> ModeAndSubmode { self.mode_and_submode } } -impl ModeRequestHandler for TestSubsystem { +impl ModeRequestHandler for AcsSubsystem { type Error = ModeError; fn start_transition( @@ -75,7 +180,6 @@ impl ModeRequestHandler for TestSubsystem { "TestAssembly: Announcing mode (recursively: {}): {:?}", recursive, self.mode_and_submode ); - // self.mode_requestor_info = Some((request_id, sender_id)); let mut mode_request = ModeRequest::AnnounceMode; if recursive { mode_request = ModeRequest::AnnounceModeRecursive; @@ -126,20 +230,14 @@ impl ModeRequestHandler for TestSubsystem { } } -struct TestAssembly { +struct MgmAssembly { pub mode_node: ModeRequestorAndHandlerMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, } -impl ModeProvider for TestAssembly { - fn mode_and_submode(&self) -> ModeAndSubmode { - self.mode_and_submode - } -} - -impl TestAssembly { +impl MgmAssembly { pub fn run(&mut self) { self.check_mode_requests().expect("mode messaging error"); self.check_mode_replies().expect("mode messaging error"); @@ -196,7 +294,37 @@ impl TestAssembly { } } -impl ModeRequestHandler for TestAssembly { +impl ModeParent for MgmAssembly { + type Sender = RequestSenderType; + + fn id(&self) -> ComponentId { + TestComponentId::AcsSubsystem as ComponentId + } + + fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { + self.mode_node.add_request_target(id, request_sender); + } +} + +impl ModeChild for MgmAssembly { + type Sender = ReplySenderType; + + fn id(&self) -> ComponentId { + TestComponentId::PusModeService as ComponentId + } + + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { + self.mode_node.add_reply_target(id, reply_sender); + } +} + +impl ModeProvider for MgmAssembly { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} + +impl ModeRequestHandler for MgmAssembly { type Error = ModeError; fn start_transition( &mut self, @@ -262,13 +390,23 @@ impl ModeRequestHandler for TestAssembly { } } -struct TestDevice { - pub name: String, +struct CommonDevice { + name: String, + pub id: ComponentId, pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, } -impl TestDevice { +impl CommonDevice { + pub fn new(name: String, id: ComponentId, mode_node: ModeRequestHandlerMpscBounded) -> Self { + Self { + name, + id, + mode_node, + mode_and_submode: ModeAndSubmode::new(0, 0), + } + } + pub fn run(&mut self) { self.check_mode_requests().expect("mode messaging error"); } @@ -281,13 +419,25 @@ impl TestDevice { } } -impl ModeProvider for TestDevice { +impl ModeChild for CommonDevice { + type Sender = ReplySenderType; + + fn id(&self) -> ComponentId { + self.id + } + + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { + self.mode_node.add_message_target(id, reply_sender); + } +} + +impl ModeProvider for CommonDevice { fn mode_and_submode(&self) -> ModeAndSubmode { self.mode_and_submode } } -impl ModeRequestHandler for TestDevice { +impl ModeRequestHandler for CommonDevice { type Error = ModeError; fn start_transition( @@ -338,22 +488,120 @@ impl ModeRequestHandler for TestDevice { } } +pub struct AcsController { + pub mode_node: ModeRequestHandlerMpscBounded, + pub mode_and_submode: ModeAndSubmode, +} + +impl AcsController { + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { + if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.handle_mode_request(request)? + } + Ok(()) + } +} + +impl ModeChild for AcsController { + type Sender = ReplySenderType; + + fn id(&self) -> ComponentId { + TestComponentId::AcsController as u64 + } + + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { + self.mode_node.add_message_target(id, reply_sender); + } +} + +impl ModeProvider for AcsController { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} + +impl ModeRequestHandler for AcsController { + type Error = ModeError; + + fn start_transition( + &mut self, + requestor: MessageMetadata, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), Self::Error> { + self.mode_and_submode = mode_and_submode; + self.handle_mode_reached(Some(requestor))?; + Ok(()) + } + + fn announce_mode(&self, requestor_info: Option, recursive: bool) { + println!( + "ACS Controllerj: announcing mode: {:?}", + self.mode_and_submode + ); + } + + fn handle_mode_reached( + &mut self, + requestor_info: Option, + ) -> Result<(), Self::Error> { + if let Some(requestor) = requestor_info { + self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; + } + Ok(()) + } + + fn handle_mode_info( + &mut self, + requestor_info: MessageMetadata, + info: ModeAndSubmode, + ) -> Result<(), Self::Error> { + // The controller is a leaf in the tree.. so this really should not happen + println!( + "ACS Controller: unexpected mode info from {:?} with mode: {:?}", + requestor_info.sender_id(), + info + ); + Ok(()) + } + + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), Self::Error> { + self.mode_node.send_mode_reply(requestor_info, reply)?; + Ok(()) + } +} + +#[test] fn main() { // All request channel handles. - let (request_sender_to_dev1, request_receiver_dev1) = mpsc::sync_channel(10); - let (request_sender_to_dev2, request_receiver_dev2) = mpsc::sync_channel(10); - let (request_sender_to_assy, request_receiver_assy) = mpsc::sync_channel(10); - let (request_sender_to_subsystem, request_receiver_subsystem) = mpsc::sync_channel(10); + let (request_sender_to_mgm_dev, request_receiver_mgm_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgt_dev, request_receiver_mgt_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgm_assy, request_receiver_mgm_assy) = mpsc::sync_channel(10); + let (request_sender_to_acs_subsystem, request_receiver_acs_subsystem) = mpsc::sync_channel(10); + let (request_sender_to_acs_ctrl, request_receiver_acs_ctrl) = mpsc::sync_channel(10); // All reply channel handles. - let (reply_sender_to_assy, reply_receiver_assy) = mpsc::sync_channel(10); + let (reply_sender_to_mgm_assy, reply_receiver_mgm_assy) = mpsc::sync_channel(10); + let (reply_sender_to_acs_subsystem, reply_receiver_acs_subsystem) = mpsc::sync_channel(10); let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); // Mode requestors and handlers. - let mut mode_node_assy = ModeRequestorAndHandlerMpscBounded::new( - TestComponentId::Assembly as ComponentId, - request_receiver_assy, - reply_receiver_assy, + let mut mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( + TestComponentId::MagnetometerAssembly as ComponentId, + request_receiver_mgm_assy, + reply_receiver_mgm_assy, + ); + let mut acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( + TestComponentId::AcsSubsystem as ComponentId, + request_receiver_acs_subsystem, + reply_receiver_acs_subsystem, ); // Mode requestors only. let mut mode_node_pus = ModeRequestorBoundedMpsc::new( @@ -362,88 +610,130 @@ fn main() { ); // Request handlers only. - let mut mode_node_dev1 = ModeRequestHandlerMpscBounded::new( - TestComponentId::Device1 as ComponentId, - request_receiver_dev1, + let mut mgm_dev_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetometerDevice as ComponentId, + request_receiver_mgm_dev, ); - let mut mode_node_dev2 = ModeRequestHandlerMpscBounded::new( - TestComponentId::Device2 as ComponentId, - request_receiver_dev2, + let mut mgt_dev_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetorquerDevice as ComponentId, + request_receiver_mgt_dev, ); - - // Set up mode request senders first. - mode_node_pus.add_message_target( - TestComponentId::Assembly as ComponentId, - request_sender_to_assy, - ); - mode_node_pus.add_message_target( - TestComponentId::Device1 as ComponentId, - request_sender_to_dev1.clone(), - ); - mode_node_pus.add_message_target( - TestComponentId::Device2 as ComponentId, - request_sender_to_dev2.clone(), - ); - mode_node_pus.add_message_target( - TestComponentId::Subsystem as ComponentId, - request_sender_to_subsystem.clone(), - ); - - mode_node_assy.add_request_target( - TestComponentId::Device1 as ComponentId, - request_sender_to_dev1, - ); - mode_node_assy.add_request_target( - TestComponentId::Device2 as ComponentId, - request_sender_to_dev2, + let mut acs_ctrl_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::AcsController as ComponentId, + request_receiver_acs_ctrl, ); // Set up mode reply senders. - mode_node_dev1.add_message_target( - TestComponentId::Assembly as ComponentId, - reply_sender_to_assy.clone(), + mgm_dev_node.add_message_target( + TestComponentId::MagnetometerAssembly as ComponentId, + reply_sender_to_mgm_assy.clone(), ); - mode_node_dev1.add_message_target( + mgt_dev_node.add_message_target( + TestComponentId::MagnetometerAssembly as ComponentId, + reply_sender_to_mgm_assy.clone(), + ); + mgm_assy_node.add_reply_target( TestComponentId::PusModeService as ComponentId, reply_sender_to_pus.clone(), ); - mode_node_dev2.add_message_target( - TestComponentId::Assembly as ComponentId, - reply_sender_to_assy, - ); - mode_node_dev2.add_message_target( - TestComponentId::PusModeService as ComponentId, + mgm_assy_node.add_reply_target( + TestComponentId::AcsSubsystem as ComponentId, reply_sender_to_pus.clone(), ); - mode_node_assy.add_reply_target( - TestComponentId::PusModeService as ComponentId, - reply_sender_to_pus, - ); - let mut device1 = TestDevice { - name: "Test Device 1".to_string(), - mode_node: mode_node_dev1, - mode_and_submode: ModeAndSubmode::new(0, 0), - }; - let mut device2 = TestDevice { - name: "Test Device 2".to_string(), - mode_node: mode_node_dev2, - mode_and_submode: ModeAndSubmode::new(0, 0), - }; - let mut assy = TestAssembly { - mode_node: mode_node_assy, + let mut mode_store_acs_subsystem = ModeStoreVec::default(); + let mut target_tables_acs_subsystem = TargetModeTables::default(); + let mut sequence_tables_acs_subsystem = SequenceModeTables::default(); + + let mut mgm_dev = CommonDevice::new( + "MGM".to_string(), + TestComponentId::MagnetometerDevice as u64, + mgm_dev_node, + ); + let mut mgt_dev = CommonDevice::new( + "MGT".to_string(), + TestComponentId::MagnetorquerDevice as u64, + mgt_dev_node, + ); + let mut mgm_assy = MgmAssembly { + mode_node: mgm_assy_node, mode_requestor_info: None, mode_and_submode: ModeAndSubmode::new(0, 0), target_mode_and_submode: None, }; - let pus_service = PusModeService { + let mut acs_subsystem = AcsSubsystem { + mode_node: acs_subsystem_node, + mode_requestor_info: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + children_mode_store: mode_store_acs_subsystem, + target_tables: target_tables_acs_subsystem, + sequence_tables: sequence_tables_acs_subsystem, + }; + let mut acs_ctrl = AcsController { + mode_node: acs_ctrl_node, + mode_and_submode: ModeAndSubmode::new(0, 0), + }; + let mut pus_service = PusModeService { request_id_counter: Cell::new(0), mode_node: mode_node_pus, }; - pus_service.send_announce_mode_cmd_to_assy(); - assy.run(); - device1.run(); - device2.run(); - assy.run(); + // Connect the PUS mode service to all mode objects. + connect_mode_nodes( + &mut pus_service, + request_sender_to_acs_subsystem, + &mut acs_subsystem, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_acs_ctrl.clone(), + &mut acs_ctrl, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgm_dev.clone(), + &mut mgm_dev, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgm_assy.clone(), + &mut mgm_assy, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgt_dev, + &mut mgt_dev, + reply_sender_to_pus.clone(), + ); + + // Connect the ACS subsystem to all children. + connect_mode_nodes( + &mut acs_subsystem, + request_sender_to_mgm_assy, + &mut mgm_assy, + reply_sender_to_acs_subsystem.clone(), + ); + connect_mode_nodes( + &mut acs_subsystem, + request_sender_to_acs_ctrl, + &mut acs_ctrl, + reply_sender_to_acs_subsystem.clone(), + ); + + connect_mode_nodes( + &mut mgm_assy, + request_sender_to_mgm_dev, + &mut mgm_dev, + reply_sender_to_mgm_assy, + ); + + pus_service.send_announce_mode_cmd_to_subsystem(); + mgm_assy.run(); + mgm_dev.run(); + mgt_dev.run(); } -- 2.43.0 From f7e636644e391c05a494a2538bc16741e313b5f8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Nov 2024 18:11:00 +0100 Subject: [PATCH 3/9] add testbench --- satrs/tests/mode_tree.rs | 603 ++++++++++++++++++++++++++------------- 1 file changed, 407 insertions(+), 196 deletions(-) diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index cd98536..8642fed 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,6 +1,4 @@ use core::cell::Cell; -use std::{println, sync::mpsc}; - use satrs::mode::{ Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender, @@ -17,10 +15,22 @@ use satrs::{ request::GenericMessage, ComponentId, }; +use std::cell::RefCell; +use std::collections::VecDeque; +use std::convert::Infallible; use std::string::{String, ToString}; +use std::{println, sync::mpsc}; const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff, 0); const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff - 1, 0); +pub const OFF_MODE: ModeAndSubmode = ModeAndSubmode::new(0, 0); + +#[derive(Debug)] +pub enum AcsMode { + OFF = 0, + SAFE = 1, + IDLE = 2 +} pub enum TestComponentId { MagnetometerDevice = 1, @@ -37,6 +47,88 @@ pub enum TestComponentId { pub type RequestSenderType = mpsc::SyncSender>; pub type ReplySenderType = mpsc::SyncSender>; +#[derive(Default, Debug)] +pub struct ModeRequestHandlerMock { + get_mode_calls: RefCell, + start_transition_calls: VecDeque<(MessageMetadata, ModeAndSubmode)>, + announce_mode_calls: RefCell>, + handle_mode_info_calls: VecDeque<(MessageMetadata, ModeAndSubmode)>, + handle_mode_reached_calls: RefCell>>, + send_mode_reply_calls: RefCell>, +} + +impl ModeRequestHandlerMock { + pub fn clear(&mut self) { + self.get_mode_calls.replace(0); + self.start_transition_calls.clear(); + self.announce_mode_calls.borrow_mut().clear(); + self.handle_mode_reached_calls.borrow_mut().clear(); + self.handle_mode_info_calls.clear(); + self.send_mode_reply_calls.borrow_mut().clear(); + } +} + +impl ModeProvider for ModeRequestHandlerMock { + fn mode_and_submode(&self) -> ModeAndSubmode { + *self.get_mode_calls.borrow_mut() += 1; + INVALID_MODE + } +} + +impl ModeRequestHandler for ModeRequestHandlerMock { + type Error = Infallible; + + fn start_transition( + &mut self, + requestor: MessageMetadata, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), Self::Error> { + self.start_transition_calls + .push_back((requestor, mode_and_submode)); + Ok(()) + } + + fn announce_mode(&self, requestor_info: Option, recursive: bool) { + self.announce_mode_calls + .borrow_mut() + .push_back(AnnounceModeInfo { + requestor: requestor_info, + recursive, + }); + } + + fn handle_mode_reached( + &mut self, + requestor_info: Option, + ) -> Result<(), Self::Error> { + self.handle_mode_reached_calls + .borrow_mut() + .push_back(requestor_info); + Ok(()) + } + + fn handle_mode_info( + &mut self, + requestor_info: MessageMetadata, + info: ModeAndSubmode, + ) -> Result<(), Self::Error> { + self.handle_mode_info_calls + .push_back((requestor_info, info)); + todo!() + } + + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), Self::Error> { + self.send_mode_reply_calls + .borrow_mut() + .push_back((requestor_info, reply)); + Ok(()) + } +} + /// Trait which denotes that an object is a parent in a mode tree. /// /// A mode parent is capable of sending mode requests to child objects and has a unique component @@ -69,9 +161,9 @@ pub trait ModeChild { /// * `child` - The child object which implements [ModeChild]. /// * `reply_sender` - Sender object to send mode replies to the parent. pub fn connect_mode_nodes( - parent: &mut impl ModeParent, + parent: &mut impl ModeParent, request_sender: ReqSender, - child: &mut impl ModeChild, + child: &mut impl ModeChild, reply_sender: ReplySender, ) { parent.add_mode_child(child.id(), request_sender); @@ -84,7 +176,7 @@ struct PusModeService { } impl PusModeService { - pub fn send_announce_mode_cmd_to_subsystem(&self) { + pub fn announce_modes_recursively(&self) { self.mode_node .send_mode_request( self.request_id_counter.get(), @@ -104,7 +196,7 @@ impl ModeParent for PusModeService { TestComponentId::PusModeService as ComponentId } - fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { + fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender) { self.mode_node.add_message_target(id, request_sender); } } @@ -117,9 +209,20 @@ struct AcsSubsystem { pub children_mode_store: ModeStoreVec, pub target_tables: TargetModeTables, pub sequence_tables: SequenceModeTables, + pub mode_req_handler_mock: ModeRequestHandlerMock, } impl AcsSubsystem { + pub fn run(&mut self) { + if let Some(request) = self.mode_node.try_recv_mode_request().unwrap() { + self.handle_mode_request(request) + .expect("mode messaging error"); + } + } + fn id(&self) -> ComponentId { + TestComponentId::AcsSubsystem as ComponentId + } + pub fn add_target_and_sequence_table( &mut self, mode: Mode, @@ -135,7 +238,7 @@ impl ModeParent for AcsSubsystem { type Sender = RequestSenderType; fn id(&self) -> ComponentId { - TestComponentId::PusModeService as ComponentId + self.id() } fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { @@ -148,8 +251,9 @@ impl ModeChild for AcsSubsystem { type Sender = ReplySenderType; fn id(&self) -> ComponentId { - TestComponentId::PusModeService as ComponentId + self.id() } + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { self.mode_node.add_reply_target(id, reply_sender); } @@ -171,6 +275,9 @@ impl ModeRequestHandler for AcsSubsystem { ) -> Result<(), Self::Error> { self.mode_requestor_info = Some(requestor); self.target_mode_and_submode = Some(mode_and_submode); + self.mode_req_handler_mock + .start_transition(requestor, mode_and_submode) + .unwrap(); // Execute mode map by executing the transition table(s). Ok(()) } @@ -197,6 +304,8 @@ impl ModeRequestHandler for AcsSubsystem { )) .expect("sending mode request failed"); }); + self.mode_req_handler_mock + .announce_mode(requestor_info, recursive); } fn handle_mode_reached( @@ -206,6 +315,9 @@ impl ModeRequestHandler for AcsSubsystem { if let Some(requestor) = requestor_info { self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; } + self.mode_req_handler_mock + .handle_mode_reached(requestor_info) + .unwrap(); Ok(()) } @@ -214,6 +326,9 @@ impl ModeRequestHandler for AcsSubsystem { requestor_info: MessageMetadata, info: ModeAndSubmode, ) -> Result<(), Self::Error> { + self.mode_req_handler_mock + .handle_mode_info(requestor_info, info) + .unwrap(); // TODO: Need to check whether mode table execution is finished. // This works by checking the children modes received through replies against the // mode table after all transition tables were executed. @@ -225,6 +340,9 @@ impl ModeRequestHandler for AcsSubsystem { requestor_info: MessageMetadata, reply: ModeReply, ) -> Result<(), Self::Error> { + self.mode_req_handler_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); self.mode_node.send_mode_reply(requestor_info, reply)?; Ok(()) } @@ -235,6 +353,7 @@ struct MgmAssembly { pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, + pub mode_req_mock: ModeRequestHandlerMock, } impl MgmAssembly { @@ -242,29 +361,13 @@ impl MgmAssembly { self.check_mode_requests().expect("mode messaging error"); self.check_mode_replies().expect("mode messaging error"); } + fn id(&self) -> ComponentId { + TestComponentId::MagnetometerAssembly as u64 + } pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { if let Some(request) = self.mode_node.try_recv_mode_request()? { - match request.message { - ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(request.requestor_info, mode_and_submode) - .unwrap(); - } - ModeRequest::ReadMode => self - .mode_node - .send_mode_reply( - request.requestor_info, - ModeReply::ModeReply(self.mode_and_submode), - ) - .unwrap(), - ModeRequest::AnnounceMode => { - self.announce_mode(Some(request.requestor_info), false) - } - ModeRequest::AnnounceModeRecursive => { - self.announce_mode(Some(request.requestor_info), true) - } - ModeRequest::ModeInfo(_) => todo!(), - } + self.handle_mode_request(request).unwrap(); } Ok(()) } @@ -298,7 +401,7 @@ impl ModeParent for MgmAssembly { type Sender = RequestSenderType; fn id(&self) -> ComponentId { - TestComponentId::AcsSubsystem as ComponentId + self.id() } fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { @@ -310,7 +413,7 @@ impl ModeChild for MgmAssembly { type Sender = ReplySenderType; fn id(&self) -> ComponentId { - TestComponentId::PusModeService as ComponentId + self.id() } fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { @@ -333,6 +436,9 @@ impl ModeRequestHandler for MgmAssembly { ) -> Result<(), Self::Error> { self.mode_requestor_info = Some(requestor); self.target_mode_and_submode = Some(mode_and_submode); + self.mode_req_mock + .start_transition(requestor, mode_and_submode) + .unwrap(); Ok(()) } @@ -341,7 +447,6 @@ impl ModeRequestHandler for MgmAssembly { "TestAssembly: Announcing mode (recursively: {}): {:?}", recursive, self.mode_and_submode ); - // self.mode_requestor_info = Some((request_id, sender_id)); let mut mode_request = ModeRequest::AnnounceMode; if recursive { mode_request = ModeRequest::AnnounceModeRecursive; @@ -359,6 +464,7 @@ impl ModeRequestHandler for MgmAssembly { )) .expect("sending mode request failed"); }); + self.mode_req_mock.announce_mode(requestor_info, recursive); } fn handle_mode_reached( @@ -368,6 +474,9 @@ impl ModeRequestHandler for MgmAssembly { if let Some(requestor) = mode_requestor { self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; } + self.mode_req_mock + .handle_mode_reached(mode_requestor) + .unwrap(); Ok(()) } @@ -377,14 +486,20 @@ impl ModeRequestHandler for MgmAssembly { reply: ModeReply, ) -> Result<(), Self::Error> { self.mode_node.send_mode_reply(requestor, reply)?; + self.mode_req_mock + .send_mode_reply(requestor, reply) + .unwrap(); Ok(()) } fn handle_mode_info( &mut self, - _requestor_info: MessageMetadata, - _info: ModeAndSubmode, + requestor_info: MessageMetadata, + info: ModeAndSubmode, ) -> Result<(), Self::Error> { + self.mode_req_mock + .handle_mode_info(requestor_info, info) + .unwrap(); // TODO: A proper assembly must reach to mode changes of its children.. Ok(()) } @@ -395,6 +510,7 @@ struct CommonDevice { pub id: ComponentId, pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, + pub mode_req_mock: ModeRequestHandlerMock, } impl CommonDevice { @@ -404,6 +520,7 @@ impl CommonDevice { id, mode_node, mode_and_submode: ModeAndSubmode::new(0, 0), + mode_req_mock: Default::default(), } } @@ -447,20 +564,25 @@ impl ModeRequestHandler for CommonDevice { ) -> Result<(), ModeError> { self.mode_and_submode = mode_and_submode; self.handle_mode_reached(Some(requestor))?; + self.mode_req_mock + .start_transition(requestor, mode_and_submode) + .unwrap(); Ok(()) } - fn announce_mode(&self, _requestor_info: Option, _recursive: bool) { + fn announce_mode(&self, requestor_info: Option, recursive: bool) { println!( "{}: announcing mode: {:?}", self.name, self.mode_and_submode ); + self.mode_req_mock.announce_mode(requestor_info, recursive); } fn handle_mode_reached(&mut self, requestor: Option) -> Result<(), ModeError> { if let Some(requestor) = requestor { self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; } + self.mode_req_mock.handle_mode_reached(requestor).unwrap(); Ok(()) } fn send_mode_reply( @@ -469,6 +591,9 @@ impl ModeRequestHandler for CommonDevice { reply: ModeReply, ) -> Result<(), ModeError> { self.mode_node.send_mode_reply(requestor_info, reply)?; + self.mode_req_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); Ok(()) } @@ -484,13 +609,24 @@ impl ModeRequestHandler for CommonDevice { requestor_info.sender_id(), info ); + self.mode_req_mock + .handle_mode_info(requestor_info, info) + .unwrap(); Ok(()) } } +#[derive(Debug, Default)] +pub struct AnnounceModeInfo { + pub requestor: Option, + pub recursive: bool, +} + pub struct AcsController { pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, + pub announce_mode_queue: RefCell>, + pub mode_req_mock: ModeRequestHandlerMock, } impl AcsController { @@ -534,14 +670,20 @@ impl ModeRequestHandler for AcsController { ) -> Result<(), Self::Error> { self.mode_and_submode = mode_and_submode; self.handle_mode_reached(Some(requestor))?; + self.mode_req_mock + .start_transition(requestor, mode_and_submode) + .unwrap(); Ok(()) } fn announce_mode(&self, requestor_info: Option, recursive: bool) { - println!( - "ACS Controllerj: announcing mode: {:?}", - self.mode_and_submode - ); + self.announce_mode_queue + .borrow_mut() + .push_back(AnnounceModeInfo { + requestor: requestor_info, + recursive, + }); + self.mode_req_mock.announce_mode(requestor_info, recursive); } fn handle_mode_reached( @@ -551,6 +693,9 @@ impl ModeRequestHandler for AcsController { if let Some(requestor) = requestor_info { self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; } + self.mode_req_mock + .handle_mode_reached(requestor_info) + .unwrap(); Ok(()) } @@ -565,6 +710,9 @@ impl ModeRequestHandler for AcsController { requestor_info.sender_id(), info ); + self.mode_req_mock + .handle_mode_info(requestor_info, info) + .unwrap(); Ok(()) } @@ -574,166 +722,229 @@ impl ModeRequestHandler for AcsController { reply: ModeReply, ) -> Result<(), Self::Error> { self.mode_node.send_mode_reply(requestor_info, reply)?; + self.mode_req_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); Ok(()) } } -#[test] -fn main() { - // All request channel handles. - let (request_sender_to_mgm_dev, request_receiver_mgm_dev) = mpsc::sync_channel(10); - let (request_sender_to_mgt_dev, request_receiver_mgt_dev) = mpsc::sync_channel(10); - let (request_sender_to_mgm_assy, request_receiver_mgm_assy) = mpsc::sync_channel(10); - let (request_sender_to_acs_subsystem, request_receiver_acs_subsystem) = mpsc::sync_channel(10); - let (request_sender_to_acs_ctrl, request_receiver_acs_ctrl) = mpsc::sync_channel(10); - - // All reply channel handles. - let (reply_sender_to_mgm_assy, reply_receiver_mgm_assy) = mpsc::sync_channel(10); - let (reply_sender_to_acs_subsystem, reply_receiver_acs_subsystem) = mpsc::sync_channel(10); - let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); - - // Mode requestors and handlers. - let mut mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( - TestComponentId::MagnetometerAssembly as ComponentId, - request_receiver_mgm_assy, - reply_receiver_mgm_assy, - ); - let mut acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( - TestComponentId::AcsSubsystem as ComponentId, - request_receiver_acs_subsystem, - reply_receiver_acs_subsystem, - ); - // Mode requestors only. - let mut mode_node_pus = ModeRequestorBoundedMpsc::new( - TestComponentId::PusModeService as ComponentId, - reply_receiver_pus, - ); - - // Request handlers only. - let mut mgm_dev_node = ModeRequestHandlerMpscBounded::new( - TestComponentId::MagnetometerDevice as ComponentId, - request_receiver_mgm_dev, - ); - let mut mgt_dev_node = ModeRequestHandlerMpscBounded::new( - TestComponentId::MagnetorquerDevice as ComponentId, - request_receiver_mgt_dev, - ); - let mut acs_ctrl_node = ModeRequestHandlerMpscBounded::new( - TestComponentId::AcsController as ComponentId, - request_receiver_acs_ctrl, - ); - - // Set up mode reply senders. - mgm_dev_node.add_message_target( - TestComponentId::MagnetometerAssembly as ComponentId, - reply_sender_to_mgm_assy.clone(), - ); - mgt_dev_node.add_message_target( - TestComponentId::MagnetometerAssembly as ComponentId, - reply_sender_to_mgm_assy.clone(), - ); - mgm_assy_node.add_reply_target( - TestComponentId::PusModeService as ComponentId, - reply_sender_to_pus.clone(), - ); - mgm_assy_node.add_reply_target( - TestComponentId::AcsSubsystem as ComponentId, - reply_sender_to_pus.clone(), - ); - - let mut mode_store_acs_subsystem = ModeStoreVec::default(); - let mut target_tables_acs_subsystem = TargetModeTables::default(); - let mut sequence_tables_acs_subsystem = SequenceModeTables::default(); - - let mut mgm_dev = CommonDevice::new( - "MGM".to_string(), - TestComponentId::MagnetometerDevice as u64, - mgm_dev_node, - ); - let mut mgt_dev = CommonDevice::new( - "MGT".to_string(), - TestComponentId::MagnetorquerDevice as u64, - mgt_dev_node, - ); - let mut mgm_assy = MgmAssembly { - mode_node: mgm_assy_node, - mode_requestor_info: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, - }; - let mut acs_subsystem = AcsSubsystem { - mode_node: acs_subsystem_node, - mode_requestor_info: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, - children_mode_store: mode_store_acs_subsystem, - target_tables: target_tables_acs_subsystem, - sequence_tables: sequence_tables_acs_subsystem, - }; - let mut acs_ctrl = AcsController { - mode_node: acs_ctrl_node, - mode_and_submode: ModeAndSubmode::new(0, 0), - }; - let mut pus_service = PusModeService { - request_id_counter: Cell::new(0), - mode_node: mode_node_pus, - }; - - // Connect the PUS mode service to all mode objects. - connect_mode_nodes( - &mut pus_service, - request_sender_to_acs_subsystem, - &mut acs_subsystem, - reply_sender_to_pus.clone(), - ); - connect_mode_nodes( - &mut pus_service, - request_sender_to_acs_ctrl.clone(), - &mut acs_ctrl, - reply_sender_to_pus.clone(), - ); - connect_mode_nodes( - &mut pus_service, - request_sender_to_mgm_dev.clone(), - &mut mgm_dev, - reply_sender_to_pus.clone(), - ); - connect_mode_nodes( - &mut pus_service, - request_sender_to_mgm_assy.clone(), - &mut mgm_assy, - reply_sender_to_pus.clone(), - ); - connect_mode_nodes( - &mut pus_service, - request_sender_to_mgt_dev, - &mut mgt_dev, - reply_sender_to_pus.clone(), - ); - - // Connect the ACS subsystem to all children. - connect_mode_nodes( - &mut acs_subsystem, - request_sender_to_mgm_assy, - &mut mgm_assy, - reply_sender_to_acs_subsystem.clone(), - ); - connect_mode_nodes( - &mut acs_subsystem, - request_sender_to_acs_ctrl, - &mut acs_ctrl, - reply_sender_to_acs_subsystem.clone(), - ); - - connect_mode_nodes( - &mut mgm_assy, - request_sender_to_mgm_dev, - &mut mgm_dev, - reply_sender_to_mgm_assy, - ); - - pus_service.send_announce_mode_cmd_to_subsystem(); - mgm_assy.run(); - mgm_dev.run(); - mgt_dev.run(); +pub struct TreeTestbench { + pus: PusModeService, + subsystem: AcsSubsystem, + ctrl: AcsController, + mgm_assy: MgmAssembly, + mgm_dev: CommonDevice, + mgt_dev: CommonDevice, +} + +impl Default for TreeTestbench { + fn default() -> Self { + Self::new() + } +} + +impl TreeTestbench { + pub fn new() -> Self { + // All request channel handles. + let (request_sender_to_mgm_dev, request_receiver_mgm_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgt_dev, request_receiver_mgt_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgm_assy, request_receiver_mgm_assy) = mpsc::sync_channel(10); + let (request_sender_to_acs_subsystem, request_receiver_acs_subsystem) = + mpsc::sync_channel(10); + let (request_sender_to_acs_ctrl, request_receiver_acs_ctrl) = mpsc::sync_channel(10); + + // All reply channel handles. + let (reply_sender_to_mgm_assy, reply_receiver_mgm_assy) = mpsc::sync_channel(10); + let (reply_sender_to_acs_subsystem, reply_receiver_acs_subsystem) = mpsc::sync_channel(10); + let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); + + // Mode requestors and handlers. + let mut mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( + TestComponentId::MagnetometerAssembly as ComponentId, + request_receiver_mgm_assy, + reply_receiver_mgm_assy, + ); + let acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( + TestComponentId::AcsSubsystem as ComponentId, + request_receiver_acs_subsystem, + reply_receiver_acs_subsystem, + ); + // Mode requestors only. + let mode_node_pus = ModeRequestorBoundedMpsc::new( + TestComponentId::PusModeService as ComponentId, + reply_receiver_pus, + ); + + // Request handlers only. + let mut mgm_dev_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetometerDevice as ComponentId, + request_receiver_mgm_dev, + ); + let mut mgt_dev_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetorquerDevice as ComponentId, + request_receiver_mgt_dev, + ); + let acs_ctrl_node = ModeRequestHandlerMpscBounded::new( + TestComponentId::AcsController as ComponentId, + request_receiver_acs_ctrl, + ); + + // Set up mode reply senders. + mgm_dev_node.add_message_target( + TestComponentId::MagnetometerAssembly as ComponentId, + reply_sender_to_mgm_assy.clone(), + ); + mgt_dev_node.add_message_target( + TestComponentId::MagnetometerAssembly as ComponentId, + reply_sender_to_mgm_assy.clone(), + ); + mgm_assy_node.add_reply_target( + TestComponentId::PusModeService as ComponentId, + reply_sender_to_pus.clone(), + ); + mgm_assy_node.add_reply_target( + TestComponentId::AcsSubsystem as ComponentId, + reply_sender_to_pus.clone(), + ); + + let mut mode_store_acs_subsystem = ModeStoreVec::default(); + let mut target_tables_acs_subsystem = TargetModeTables::default(); + let mut sequence_tables_acs_subsystem = SequenceModeTables::default(); + + let mut mgm_dev = CommonDevice::new( + "MGM".to_string(), + TestComponentId::MagnetometerDevice as u64, + mgm_dev_node, + ); + let mut mgt_dev = CommonDevice::new( + "MGT".to_string(), + TestComponentId::MagnetorquerDevice as u64, + mgt_dev_node, + ); + let mut mgm_assy = MgmAssembly { + mode_node: mgm_assy_node, + mode_requestor_info: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + mode_req_mock: ModeRequestHandlerMock::default(), + }; + let mut acs_subsystem = AcsSubsystem { + mode_node: acs_subsystem_node, + mode_requestor_info: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + children_mode_store: mode_store_acs_subsystem, + target_tables: target_tables_acs_subsystem, + sequence_tables: sequence_tables_acs_subsystem, + mode_req_handler_mock: Default::default(), + }; + let mut acs_ctrl = AcsController { + mode_node: acs_ctrl_node, + mode_and_submode: UNKNOWN_MODE, + announce_mode_queue: RefCell::new(Default::default()), + mode_req_mock: Default::default(), + }; + let mut pus_service = PusModeService { + request_id_counter: Cell::new(0), + mode_node: mode_node_pus, + }; + + // Connect the PUS mode service to all mode objects. + connect_mode_nodes( + &mut pus_service, + request_sender_to_acs_subsystem, + &mut acs_subsystem, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_acs_ctrl.clone(), + &mut acs_ctrl, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgm_dev.clone(), + &mut mgm_dev, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgm_assy.clone(), + &mut mgm_assy, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgt_dev.clone(), + &mut mgt_dev, + reply_sender_to_pus.clone(), + ); + + // Connect the ACS subsystem to all children. + connect_mode_nodes( + &mut acs_subsystem, + request_sender_to_mgm_assy, + &mut mgm_assy, + reply_sender_to_acs_subsystem.clone(), + ); + connect_mode_nodes( + &mut acs_subsystem, + request_sender_to_acs_ctrl, + &mut acs_ctrl, + reply_sender_to_acs_subsystem.clone(), + ); + connect_mode_nodes( + &mut acs_subsystem, + request_sender_to_mgt_dev, + &mut mgt_dev, + reply_sender_to_acs_subsystem.clone(), + ); + + connect_mode_nodes( + &mut mgm_assy, + request_sender_to_mgm_dev, + &mut mgm_dev, + reply_sender_to_mgm_assy, + ); + Self { + pus: pus_service, + subsystem: acs_subsystem, + ctrl: acs_ctrl, + mgm_assy, + mgm_dev, + mgt_dev, + } + } +} + +#[test] +fn announce_recursively() { + let mut tb = TreeTestbench::new(); + tb.pus.announce_modes_recursively(); + tb.subsystem.run(); + tb.ctrl.run(); + tb.mgm_assy.run(); + tb.mgm_dev.run(); + tb.mgt_dev.run(); + let mut announces = tb + .subsystem + .mode_req_handler_mock + .announce_mode_calls + .borrow_mut(); + assert_eq!(announces.len(), 1); + announces = tb.ctrl.mode_req_mock.announce_mode_calls.borrow_mut(); + assert_eq!(tb.ctrl.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(tb.ctrl.mode_and_submode(), UNKNOWN_MODE); + assert_eq!(announces.len(), 1); + announces = tb.mgm_assy.mode_req_mock.announce_mode_calls.borrow_mut(); + assert_eq!(tb.mgm_assy.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(announces.len(), 1); + announces = tb.mgm_dev.mode_req_mock.announce_mode_calls.borrow_mut(); + assert_eq!(tb.mgm_dev.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(announces.len(), 1); + announces = tb.mgt_dev.mode_req_mock.announce_mode_calls.borrow_mut(); + assert_eq!(tb.mgt_dev.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(announces.len(), 1); } -- 2.43.0 From db651ca06fd86a414a2a83643c5c89f7e3fc577b Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 28 Nov 2024 12:36:43 +0100 Subject: [PATCH 4/9] move generic components to library --- satrs/src/mode_tree.rs | 76 ++++++- satrs/src/subsystem.rs | 4 +- satrs/tests/mode_tree.rs | 478 ++++++++++++++++++++++++++------------- 3 files changed, 398 insertions(+), 160 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 2940900..e1063d7 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -2,13 +2,57 @@ use alloc::vec::Vec; use hashbrown::HashMap; use crate::{ - mode::{Mode, ModeAndSubmode, Submode}, + mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, + request::MessageSender, ComponentId, }; #[cfg(feature = "alloc")] pub use alloc_mod::*; +/// Common trait for node modes which can have mode parents or mode children. +pub trait ModeNode { + fn id(&self) -> ComponentId; +} +/// Trait which denotes that an object is a parent in a mode tree. +/// +/// A mode parent is capable of sending mode requests to child objects and has a unique component +/// ID. +pub trait ModeParent: ModeNode { + type Sender: MessageSender; + + fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender); +} + +/// Trait which denotes that an object is a child in a mode tree. +/// +/// A child is capable of sending mode replies to parent objects and has a unique component ID. +pub trait ModeChild: ModeNode { + type Sender: MessageSender; + + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender); +} + +/// Utility method which connects a mode tree parent object to a child object by calling +/// [ModeParent::add_mode_child] on the [parent][ModeParent] and calling +/// [ModeChild::add_mode_parent] on the [child][ModeChild]. +/// +/// # Arguments +/// +/// * `parent` - The parent object which implements [ModeParent]. +/// * `request_sender` - Sender object to send mode requests to the child. +/// * `child` - The child object which implements [ModeChild]. +/// * `reply_sender` - Sender object to send mode replies to the parent. +pub fn connect_mode_nodes( + parent: &mut impl ModeParent, + request_sender: ReqSender, + child: &mut impl ModeChild, + reply_sender: ReplySender, +) { + parent.add_mode_child(child.id(), request_sender); + child.add_mode_parent(parent.id(), reply_sender); +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum TableEntryType { /// Target table containing information of the expected children modes for given mode. @@ -62,6 +106,24 @@ impl TargetTableEntry { target_id: ComponentId, mode_submode: ModeAndSubmode, monitor_state: bool, + allowed_submode_mask: Option, + ) -> Self { + Self { + common: ModeTableEntryCommon { + name, + target_id, + mode_submode, + allowed_submode_mask, + }, + monitor_state, + } + } + + pub fn new_with_precise_submode( + name: &'static str, + target_id: ComponentId, + mode_submode: ModeAndSubmode, + monitor_state: bool, ) -> Self { Self { common: ModeTableEntryCommon { @@ -129,14 +191,14 @@ pub mod alloc_mod { use super::*; #[derive(Debug)] - pub struct TargetTableMapValue { + pub struct TargetTablesMapValue { /// Name for a given mode table entry. pub name: &'static str, /// These are the rows of the a target table. pub entries: Vec, } - impl TargetTableMapValue { + impl TargetTablesMapValue { pub fn new(name: &'static str) -> Self { Self { name, @@ -171,14 +233,14 @@ pub mod alloc_mod { } #[derive(Debug)] - pub struct SequenceTableMapValue { + pub struct SequenceTablesMapValue { /// Name for a given mode sequence. pub name: &'static str, /// Each sequence can consists of multiple sequences that are executed consecutively. pub entries: Vec, } - impl SequenceTableMapValue { + impl SequenceTablesMapValue { pub fn new(name: &'static str) -> Self { Self { name, @@ -192,9 +254,9 @@ pub mod alloc_mod { } #[derive(Debug, Default)] - pub struct TargetModeTables(pub HashMap); + pub struct TargetModeTables(pub HashMap); #[derive(Debug, Default)] - pub struct SequenceModeTables(pub HashMap); + pub struct SequenceModeTables(pub HashMap); #[derive(Debug, Default)] pub struct ModeStoreVec(pub alloc::vec::Vec<(ComponentId, ModeAndSubmode)>); diff --git a/satrs/src/subsystem.rs b/satrs/src/subsystem.rs index 199336d..aecc579 100644 --- a/satrs/src/subsystem.rs +++ b/satrs/src/subsystem.rs @@ -1,6 +1,6 @@ use crate::{ mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestSender}, - mode_tree::{SequenceModeTables, SequenceTableMapTable, SequenceTableMapValue}, + mode_tree::{SequenceModeTables, SequenceTableMapTable, SequenceTablesMapValue}, queue::GenericTargetedMessagingError, request::RequestId, ComponentId, @@ -88,7 +88,7 @@ impl SequenceExecutionHelper { pub fn execute_sequence_and_map_to_result( &mut self, - seq_table_value: &SequenceTableMapValue, + seq_table_value: &SequenceTablesMapValue, sequence_idx: usize, sender: &impl ModeRequestSender, ) -> Result { diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 8642fed..eb4235c 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,14 +1,18 @@ use core::cell::Cell; use satrs::mode::{ Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, - ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender, - ModeRequestorAndHandlerMpscBounded, ModeRequestorBoundedMpsc, + ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, + ModeRequestorBoundedMpsc, }; -use satrs::mode_tree::alloc_mod::{ - ModeStoreVec, SequenceModeTables, SequenceTableMapValue, TargetModeTables, TargetTableMapValue, +use satrs::mode_tree::{ + connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableMapTable, + TargetTableEntry, }; -use satrs::mode_tree::ModeStoreProvider; -use satrs::request::{MessageMetadata, MessageSender}; +use satrs::mode_tree::{ + ModeStoreVec, SequenceModeTables, SequenceTablesMapValue, TargetModeTables, + TargetTablesMapValue, +}; +use satrs::request::MessageMetadata; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, queue::GenericTargetedMessagingError, @@ -18,27 +22,33 @@ use satrs::{ use std::cell::RefCell; use std::collections::VecDeque; use std::convert::Infallible; -use std::string::{String, ToString}; use std::{println, sync::mpsc}; const INVALID_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff, 0); const UNKNOWN_MODE: ModeAndSubmode = ModeAndSubmode::new(0xffffffff - 1, 0); -pub const OFF_MODE: ModeAndSubmode = ModeAndSubmode::new(0, 0); + +pub enum DefaultMode { + OFF = 0, + ON = 1, + NORMAL = 2, +} #[derive(Debug)] pub enum AcsMode { OFF = 0, SAFE = 1, - IDLE = 2 + IDLE = 2, } pub enum TestComponentId { - MagnetometerDevice = 1, - MagnetorquerDevice = 2, - ReactionWheelDevice = 3, - StartrackerDevice = 4, - ReactionWheelAssembly = 8, - MagnetometerAssembly = 9, + MagnetometerDevice0 = 1, + MagnetometerDevice1 = 2, + MagnetorquerDevice = 5, + ReactionWheelDevice = 6, + StartrackerDevice = 7, + MgtDevManager = 8, + ReactionWheelAssembly = 10, + MagnetometerAssembly = 11, AcsController = 14, AcsSubsystem = 15, PusModeService = 16, @@ -47,6 +57,24 @@ pub enum TestComponentId { pub type RequestSenderType = mpsc::SyncSender>; pub type ReplySenderType = mpsc::SyncSender>; +#[derive(Default)] +pub struct SubsystemHelper { + pub children_mode_store: ModeStoreVec, + pub target_tables: TargetModeTables, + pub sequence_tables: SequenceModeTables, +} +impl SubsystemHelper { + pub fn add_target_and_sequence_table( + &mut self, + mode: Mode, + target_table_val: TargetTablesMapValue, + sequence_table_val: SequenceTablesMapValue, + ) { + self.target_tables.0.insert(mode, target_table_val); + self.sequence_tables.0.insert(mode, sequence_table_val); + } +} + #[derive(Default, Debug)] pub struct ModeRequestHandlerMock { get_mode_calls: RefCell, @@ -129,47 +157,6 @@ impl ModeRequestHandler for ModeRequestHandlerMock { } } -/// Trait which denotes that an object is a parent in a mode tree. -/// -/// A mode parent is capable of sending mode requests to child objects and has a unique component -/// ID. -pub trait ModeParent { - type Sender: MessageSender; - - fn id(&self) -> ComponentId; - fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender); -} - -/// Trait which denotes that an object is a child in a mode tree. -/// -/// A child is capable of sending mode replies to parent objects and has a unique component ID. -pub trait ModeChild { - type Sender: MessageSender; - - fn id(&self) -> ComponentId; - fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender); -} - -/// Utility method which connects a mode tree parent object to a child object by calling -/// [ModeParent::add_mode_child] on the [parent][ModeParent] and calling -/// [ModeChild::add_mode_parent] on the [child][ModeChild]. -/// -/// # Arguments -/// -/// * `parent` - The parent object which implements [ModeParent]. -/// * `request_sender` - Sender object to send mode requests to the child. -/// * `child` - The child object which implements [ModeChild]. -/// * `reply_sender` - Sender object to send mode replies to the parent. -pub fn connect_mode_nodes( - parent: &mut impl ModeParent, - request_sender: ReqSender, - child: &mut impl ModeChild, - reply_sender: ReplySender, -) { - parent.add_mode_child(child.id(), request_sender); - child.add_mode_parent(parent.id(), reply_sender); -} - struct PusModeService { pub request_id_counter: Cell, pub mode_node: ModeRequestorBoundedMpsc, @@ -189,12 +176,14 @@ impl PusModeService { } } -impl ModeParent for PusModeService { - type Sender = RequestSenderType; - +impl ModeNode for PusModeService { fn id(&self) -> ComponentId { TestComponentId::PusModeService as ComponentId } +} + +impl ModeParent for PusModeService { + type Sender = RequestSenderType; fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender) { self.mode_node.add_message_target(id, request_sender); @@ -206,43 +195,54 @@ struct AcsSubsystem { pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, - pub children_mode_store: ModeStoreVec, - pub target_tables: TargetModeTables, - pub sequence_tables: SequenceModeTables, + pub subsystem_helper: SubsystemHelper, pub mode_req_handler_mock: ModeRequestHandlerMock, } impl AcsSubsystem { + pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self { + Self { + mode_node, + mode_requestor_info: None, + mode_and_submode: UNKNOWN_MODE, + target_mode_and_submode: None, + subsystem_helper: Default::default(), + mode_req_handler_mock: Default::default(), + } + } pub fn run(&mut self) { if let Some(request) = self.mode_node.try_recv_mode_request().unwrap() { self.handle_mode_request(request) .expect("mode messaging error"); } } - fn id(&self) -> ComponentId { - TestComponentId::AcsSubsystem as ComponentId - } - pub fn add_target_and_sequence_table( &mut self, mode: Mode, - target_table_val: TargetTableMapValue, - sequence_table_val: SequenceTableMapValue, + target_table_val: TargetTablesMapValue, + sequence_table_val: SequenceTablesMapValue, ) { - self.target_tables.0.insert(mode, target_table_val); - self.sequence_tables.0.insert(mode, sequence_table_val); + self.subsystem_helper.add_target_and_sequence_table( + mode, + target_table_val, + sequence_table_val, + ); + } +} + +impl ModeNode for AcsSubsystem { + fn id(&self) -> ComponentId { + TestComponentId::AcsSubsystem as ComponentId } } impl ModeParent for AcsSubsystem { type Sender = RequestSenderType; - fn id(&self) -> ComponentId { - self.id() - } - fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { - self.children_mode_store.add_component(id, UNKNOWN_MODE); + self.subsystem_helper + .children_mode_store + .add_component(id, UNKNOWN_MODE); self.mode_node.add_request_target(id, request_sender); } } @@ -250,10 +250,6 @@ impl ModeParent for AcsSubsystem { impl ModeChild for AcsSubsystem { type Sender = ReplySenderType; - fn id(&self) -> ComponentId { - self.id() - } - fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { self.mode_node.add_reply_target(id, reply_sender); } @@ -397,12 +393,13 @@ impl MgmAssembly { } } -impl ModeParent for MgmAssembly { - type Sender = RequestSenderType; - +impl ModeNode for MgmAssembly { fn id(&self) -> ComponentId { self.id() } +} +impl ModeParent for MgmAssembly { + type Sender = RequestSenderType; fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) { self.mode_node.add_request_target(id, request_sender); @@ -412,10 +409,6 @@ impl ModeParent for MgmAssembly { impl ModeChild for MgmAssembly { type Sender = ReplySenderType; - fn id(&self) -> ComponentId { - self.id() - } - fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { self.mode_node.add_reply_target(id, reply_sender); } @@ -505,8 +498,122 @@ impl ModeRequestHandler for MgmAssembly { } } +struct DeviceManager { + name: &'static str, + pub id: ComponentId, + pub mode_node: ModeRequestorAndHandlerMpscBounded, + pub mode_and_submode: ModeAndSubmode, + pub mode_req_mock: ModeRequestHandlerMock, +} + +impl DeviceManager { + pub fn new( + name: &'static str, + id: ComponentId, + mode_node: ModeRequestorAndHandlerMpscBounded, + ) -> Self { + Self { + name, + id, + mode_node, + mode_and_submode: UNKNOWN_MODE, + mode_req_mock: Default::default(), + } + } +} + +impl ModeNode for DeviceManager { + fn id(&self) -> ComponentId { + self.id + } +} + +impl ModeChild for DeviceManager { + type Sender = ReplySenderType; + + fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { + self.mode_node.add_reply_target(id, reply_sender); + } +} + +impl ModeParent for DeviceManager { + type Sender = RequestSenderType; + + fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender) { + self.mode_node.add_request_target(id, request_sender); + } +} + +impl ModeProvider for DeviceManager { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} + +impl ModeRequestHandler for DeviceManager { + type Error = ModeError; + + fn start_transition( + &mut self, + requestor: MessageMetadata, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), ModeError> { + self.mode_and_submode = mode_and_submode; + self.handle_mode_reached(Some(requestor))?; + self.mode_req_mock + .start_transition(requestor, mode_and_submode) + .unwrap(); + Ok(()) + } + + fn announce_mode(&self, requestor_info: Option, recursive: bool) { + println!( + "{}: announcing mode: {:?}", + self.name, self.mode_and_submode + ); + self.mode_req_mock.announce_mode(requestor_info, recursive); + } + + fn handle_mode_reached(&mut self, requestor: Option) -> Result<(), ModeError> { + if let Some(requestor) = requestor { + self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?; + } + self.mode_req_mock.handle_mode_reached(requestor).unwrap(); + Ok(()) + } + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), ModeError> { + self.mode_node.send_mode_reply(requestor_info, reply)?; + self.mode_req_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); + Ok(()) + } + + fn handle_mode_info( + &mut self, + requestor_info: MessageMetadata, + info: ModeAndSubmode, + ) -> Result<(), ModeError> { + // A device is a leaf in the tree.. so this really should not happen + println!( + "{}: unexpected mode info from {:?} with mode: {:?}", + self.name, + requestor_info.sender_id(), + info + ); + self.mode_req_mock + .handle_mode_info(requestor_info, info) + .unwrap(); + Ok(()) + } +} + struct CommonDevice { - name: String, + name: &'static str, pub id: ComponentId, pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, @@ -514,12 +621,16 @@ struct CommonDevice { } impl CommonDevice { - pub fn new(name: String, id: ComponentId, mode_node: ModeRequestHandlerMpscBounded) -> Self { + pub fn new( + name: &'static str, + id: ComponentId, + mode_node: ModeRequestHandlerMpscBounded, + ) -> Self { Self { name, id, mode_node, - mode_and_submode: ModeAndSubmode::new(0, 0), + mode_and_submode: UNKNOWN_MODE, mode_req_mock: Default::default(), } } @@ -536,12 +647,14 @@ impl CommonDevice { } } -impl ModeChild for CommonDevice { - type Sender = ReplySenderType; - +impl ModeNode for CommonDevice { fn id(&self) -> ComponentId { self.id } +} + +impl ModeChild for CommonDevice { + type Sender = ReplySenderType; fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { self.mode_node.add_message_target(id, reply_sender); @@ -642,12 +755,14 @@ impl AcsController { } } -impl ModeChild for AcsController { - type Sender = ReplySenderType; - +impl ModeNode for AcsController { fn id(&self) -> ComponentId { TestComponentId::AcsController as u64 } +} + +impl ModeChild for AcsController { + type Sender = ReplySenderType; fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) { self.mode_node.add_message_target(id, reply_sender); @@ -733,8 +848,9 @@ pub struct TreeTestbench { pus: PusModeService, subsystem: AcsSubsystem, ctrl: AcsController, + mgt_manager: DeviceManager, mgm_assy: MgmAssembly, - mgm_dev: CommonDevice, + mgm_devs: [CommonDevice; 2], mgt_dev: CommonDevice, } @@ -747,8 +863,10 @@ impl Default for TreeTestbench { impl TreeTestbench { pub fn new() -> Self { // All request channel handles. - let (request_sender_to_mgm_dev, request_receiver_mgm_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgm_dev_0, request_receiver_mgm_dev_0) = mpsc::sync_channel(10); + let (request_sender_to_mgm_dev_1, request_receiver_mgm_dev_1) = mpsc::sync_channel(10); let (request_sender_to_mgt_dev, request_receiver_mgt_dev) = mpsc::sync_channel(10); + let (request_sender_to_mgt_man, request_receiver_mgt_man) = mpsc::sync_channel(10); let (request_sender_to_mgm_assy, request_receiver_mgm_assy) = mpsc::sync_channel(10); let (request_sender_to_acs_subsystem, request_receiver_acs_subsystem) = mpsc::sync_channel(10); @@ -758,6 +876,13 @@ impl TreeTestbench { let (reply_sender_to_mgm_assy, reply_receiver_mgm_assy) = mpsc::sync_channel(10); let (reply_sender_to_acs_subsystem, reply_receiver_acs_subsystem) = mpsc::sync_channel(10); let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); + let (reply_sender_to_mgt_man, reply_receiver_mgt_man) = mpsc::sync_channel(10); + + // Mode requestors only. + let mode_node_pus = ModeRequestorBoundedMpsc::new( + TestComponentId::PusModeService as ComponentId, + reply_receiver_pus, + ); // Mode requestors and handlers. let mut mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( @@ -765,21 +890,25 @@ impl TreeTestbench { request_receiver_mgm_assy, reply_receiver_mgm_assy, ); + let mut mgt_dev_mgmt_node = ModeRequestorAndHandlerMpscBounded::new( + TestComponentId::MgtDevManager as ComponentId, + request_receiver_mgt_man, + reply_receiver_mgt_man, + ); let acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( TestComponentId::AcsSubsystem as ComponentId, request_receiver_acs_subsystem, reply_receiver_acs_subsystem, ); - // Mode requestors only. - let mode_node_pus = ModeRequestorBoundedMpsc::new( - TestComponentId::PusModeService as ComponentId, - reply_receiver_pus, - ); // Request handlers only. - let mut mgm_dev_node = ModeRequestHandlerMpscBounded::new( - TestComponentId::MagnetometerDevice as ComponentId, - request_receiver_mgm_dev, + let mut mgm_dev_node_0 = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetometerDevice0 as ComponentId, + request_receiver_mgm_dev_0, + ); + let mut mgm_dev_node_1 = ModeRequestHandlerMpscBounded::new( + TestComponentId::MagnetometerDevice1 as ComponentId, + request_receiver_mgm_dev_1, ); let mut mgt_dev_node = ModeRequestHandlerMpscBounded::new( TestComponentId::MagnetorquerDevice as ComponentId, @@ -790,55 +919,34 @@ impl TreeTestbench { request_receiver_acs_ctrl, ); - // Set up mode reply senders. - mgm_dev_node.add_message_target( - TestComponentId::MagnetometerAssembly as ComponentId, - reply_sender_to_mgm_assy.clone(), + let mut mgm_dev_0 = CommonDevice::new( + "MGM_0", + TestComponentId::MagnetometerDevice0 as u64, + mgm_dev_node_0, ); - mgt_dev_node.add_message_target( - TestComponentId::MagnetometerAssembly as ComponentId, - reply_sender_to_mgm_assy.clone(), - ); - mgm_assy_node.add_reply_target( - TestComponentId::PusModeService as ComponentId, - reply_sender_to_pus.clone(), - ); - mgm_assy_node.add_reply_target( - TestComponentId::AcsSubsystem as ComponentId, - reply_sender_to_pus.clone(), - ); - - let mut mode_store_acs_subsystem = ModeStoreVec::default(); - let mut target_tables_acs_subsystem = TargetModeTables::default(); - let mut sequence_tables_acs_subsystem = SequenceModeTables::default(); - - let mut mgm_dev = CommonDevice::new( - "MGM".to_string(), - TestComponentId::MagnetometerDevice as u64, - mgm_dev_node, + let mut mgm_dev_1 = CommonDevice::new( + "MGM_1", + TestComponentId::MagnetometerDevice0 as u64, + mgm_dev_node_1, ); let mut mgt_dev = CommonDevice::new( - "MGT".to_string(), + "MGT", TestComponentId::MagnetorquerDevice as u64, mgt_dev_node, ); + let mut mgt_manager = DeviceManager::new( + "MGT_MANAGER", + TestComponentId::MgtDevManager as u64, + mgt_dev_mgmt_node, + ); let mut mgm_assy = MgmAssembly { mode_node: mgm_assy_node, mode_requestor_info: None, - mode_and_submode: ModeAndSubmode::new(0, 0), + mode_and_submode: UNKNOWN_MODE, target_mode_and_submode: None, mode_req_mock: ModeRequestHandlerMock::default(), }; - let mut acs_subsystem = AcsSubsystem { - mode_node: acs_subsystem_node, - mode_requestor_info: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, - children_mode_store: mode_store_acs_subsystem, - target_tables: target_tables_acs_subsystem, - sequence_tables: sequence_tables_acs_subsystem, - mode_req_handler_mock: Default::default(), - }; + let mut acs_subsystem = AcsSubsystem::new(acs_subsystem_node); let mut acs_ctrl = AcsController { mode_node: acs_ctrl_node, mode_and_submode: UNKNOWN_MODE, @@ -850,6 +958,31 @@ impl TreeTestbench { mode_node: mode_node_pus, }; + // ACS subsystem tables + let mut target_table_safe = TargetTablesMapValue::new("SAFE_TARGET_TBL"); + target_table_safe.add_entry(TargetTableEntry::new( + "CTRL_SAFE", + TestComponentId::AcsController as u64, + ModeAndSubmode::new(AcsMode::SAFE as u32, 0), + true, + // All submodes allowed. + Some(0xffff), + )); + target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode( + "MGM_A_NML", + TestComponentId::MagnetometerAssembly as u64, + ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0), + true, + )); + let sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL"); + let sequence_tbl_safe_1 = SequenceTableMapTable::new("SAFE_SEQ_1_TBL"); + let sequence_tbl_safe = SequenceTablesMapValue::new("SAFE_SEQ_TBL"); + acs_subsystem.add_target_and_sequence_table( + AcsMode::SAFE as u32, + target_table_safe, + sequence_tbl_safe, + ); + // Connect the PUS mode service to all mode objects. connect_mode_nodes( &mut pus_service, @@ -865,8 +998,14 @@ impl TreeTestbench { ); connect_mode_nodes( &mut pus_service, - request_sender_to_mgm_dev.clone(), - &mut mgm_dev, + request_sender_to_mgm_dev_0.clone(), + &mut mgm_dev_0, + reply_sender_to_pus.clone(), + ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgm_dev_1.clone(), + &mut mgm_dev_1, reply_sender_to_pus.clone(), ); connect_mode_nodes( @@ -875,6 +1014,12 @@ impl TreeTestbench { &mut mgm_assy, reply_sender_to_pus.clone(), ); + connect_mode_nodes( + &mut pus_service, + request_sender_to_mgt_man.clone(), + &mut mgt_manager, + reply_sender_to_pus.clone(), + ); connect_mode_nodes( &mut pus_service, request_sender_to_mgt_dev.clone(), @@ -897,24 +1042,37 @@ impl TreeTestbench { ); connect_mode_nodes( &mut acs_subsystem, - request_sender_to_mgt_dev, + request_sender_to_mgt_dev.clone(), &mut mgt_dev, reply_sender_to_acs_subsystem.clone(), ); connect_mode_nodes( &mut mgm_assy, - request_sender_to_mgm_dev, - &mut mgm_dev, + request_sender_to_mgm_dev_0, + &mut mgm_dev_0, + reply_sender_to_mgm_assy.clone(), + ); + connect_mode_nodes( + &mut mgm_assy, + request_sender_to_mgm_dev_1, + &mut mgm_dev_1, reply_sender_to_mgm_assy, ); + connect_mode_nodes( + &mut mgt_manager, + request_sender_to_mgt_dev, + &mut mgt_dev, + reply_sender_to_mgt_man, + ); Self { pus: pus_service, subsystem: acs_subsystem, ctrl: acs_ctrl, mgm_assy, - mgm_dev, mgt_dev, + mgt_manager, + mgm_devs: [mgm_dev_0, mgm_dev_1], } } } @@ -926,7 +1084,8 @@ fn announce_recursively() { tb.subsystem.run(); tb.ctrl.run(); tb.mgm_assy.run(); - tb.mgm_dev.run(); + tb.mgm_devs[0].run(); + tb.mgm_devs[1].run(); tb.mgt_dev.run(); let mut announces = tb .subsystem @@ -940,11 +1099,28 @@ fn announce_recursively() { assert_eq!(announces.len(), 1); announces = tb.mgm_assy.mode_req_mock.announce_mode_calls.borrow_mut(); assert_eq!(tb.mgm_assy.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(tb.mgm_assy.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); - announces = tb.mgm_dev.mode_req_mock.announce_mode_calls.borrow_mut(); - assert_eq!(tb.mgm_dev.mode_req_mock.start_transition_calls.len(), 0); + for mgm_dev in &tb.mgm_devs { + announces = mgm_dev.mode_req_mock.announce_mode_calls.borrow_mut(); + assert_eq!(mgm_dev.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(mgm_dev.mode_and_submode(), UNKNOWN_MODE); + assert_eq!(announces.len(), 1); + } assert_eq!(announces.len(), 1); announces = tb.mgt_dev.mode_req_mock.announce_mode_calls.borrow_mut(); assert_eq!(tb.mgt_dev.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(tb.mgt_dev.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); } + +#[test] +fn command_safe_mode() { + let mut tb = TreeTestbench::new(); + tb.subsystem.run(); + tb.ctrl.run(); + tb.mgm_assy.run(); + tb.mgt_dev.run(); + tb.mgm_devs[0].run(); + tb.mgm_devs[1].run(); +} -- 2.43.0 From 5d8787b7fa7945963f5bd5bff6516c8c5cb89da5 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 29 Nov 2024 13:36:53 +0100 Subject: [PATCH 5/9] generic shananigans --- satrs/src/mode.rs | 177 +++++++++++++++++------------ satrs/src/mode_tree.rs | 6 +- satrs/src/pus/action.rs | 56 +++++++--- satrs/src/pus/mode.rs | 8 +- satrs/src/request.rs | 179 +++++++++++++++++++++++------- satrs/tests/mode_tree.rs | 233 ++++++++++++++++++++++++++------------- 6 files changed, 454 insertions(+), 205 deletions(-) diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index 01beac9..1b4d636 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -12,7 +12,9 @@ pub use std_mod::*; use crate::{ queue::GenericTargetedMessagingError, - request::{GenericMessage, MessageMetadata, MessageReceiver, MessageReceiverWithId, RequestId}, + request::{ + GenericMessage, MessageMetadata, MessageReceiverProvider, MessageReceiverWithId, RequestId, + }, ComponentId, }; @@ -156,7 +158,7 @@ pub trait ModeRequestReceiver { ) -> Result>, GenericTargetedMessagingError>; } -impl> ModeRequestReceiver +impl> ModeRequestReceiver for MessageReceiverWithId { fn try_recv_mode_request( @@ -248,7 +250,9 @@ pub trait ModeReplyReceiver { ) -> Result>, GenericTargetedMessagingError>; } -impl> ModeReplyReceiver for MessageReceiverWithId { +impl> ModeReplyReceiver + for MessageReceiverWithId +{ fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -270,12 +274,13 @@ pub trait ModeReplySender { #[cfg(feature = "alloc")] pub mod alloc_mod { use crate::request::{ - MessageSender, MessageSenderAndReceiver, MessageSenderMap, RequestAndReplySenderAndReceiver, + MessageSenderAndReceiver, MessageSenderMap, MessageSenderProvider, + MessageSenderStoreProvider, RequestAndReplySenderAndReceiver, }; use super::*; - impl> MessageSenderMap { + impl> MessageSenderMap { pub fn send_mode_reply( &self, requestor_info: MessageMetadata, @@ -290,8 +295,13 @@ pub mod alloc_mod { } } - impl, R: MessageReceiver> ModeReplySender - for MessageSenderAndReceiver + impl< + From, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > ModeReplySender + for MessageSenderAndReceiver { fn local_channel_id(&self) -> ComponentId { self.local_channel_id_generic() @@ -302,7 +312,7 @@ pub mod alloc_mod { requestor_info: MessageMetadata, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map.send_mode_reply( + self.message_sender_store.send_message( MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()), requestor_info.sender_id(), request, @@ -310,8 +320,13 @@ pub mod alloc_mod { } } - impl, R: MessageReceiver> ModeReplyReceiver - for MessageSenderAndReceiver + impl< + To, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > ModeReplyReceiver + for MessageSenderAndReceiver { fn try_recv_mode_reply( &self, @@ -322,10 +337,10 @@ pub mod alloc_mod { impl< REQUEST, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > RequestAndReplySenderAndReceiver { pub fn add_reply_target(&mut self, target_id: ComponentId, reply_sender: S1) { @@ -336,10 +351,10 @@ pub mod alloc_mod { impl< REQUEST, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > ModeReplySender for RequestAndReplySenderAndReceiver { fn local_channel_id(&self) -> ComponentId { @@ -361,10 +376,10 @@ pub mod alloc_mod { impl< REQUEST, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > ModeReplyReceiver for RequestAndReplySenderAndReceiver { @@ -376,11 +391,14 @@ pub mod alloc_mod { } /// Helper type definition for a mode handler which can handle mode requests. - pub type ModeRequestHandlerInterface = - MessageSenderAndReceiver; + pub type ModeRequestHandlerInterface = + MessageSenderAndReceiver; - impl, R: MessageReceiver> - ModeRequestHandlerInterface + impl< + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, + > ModeRequestHandlerInterface { pub fn try_recv_mode_request( &self, @@ -403,9 +421,15 @@ pub mod alloc_mod { /// Helper type defintion for a mode handler object which can send mode requests and receive /// mode replies. - pub type ModeRequestorInterface = MessageSenderAndReceiver; + pub type ModeRequestorInterface = + MessageSenderAndReceiver; - impl, R: MessageReceiver> ModeRequestorInterface { + impl< + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + RequestSenderStore: MessageSenderStoreProvider, + > ModeRequestorInterface + { pub fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -427,7 +451,7 @@ pub mod alloc_mod { pub type ModeInterface = RequestAndReplySenderAndReceiver; - impl> MessageSenderMap { + impl> MessageSenderMap { pub fn send_mode_request( &self, requestor_info: MessageMetadata, @@ -442,25 +466,13 @@ pub mod alloc_mod { } } - /* - impl> ModeRequestSender for MessageSenderMapWithId { - fn local_channel_id(&self) -> ComponentId { - self.local_channel_id - } - - fn send_mode_request( - &self, - request_id: RequestId, - target_id: ComponentId, - request: ModeRequest, - ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(request_id, target_id, request) - } - } - */ - - impl, R: MessageReceiver> ModeRequestReceiver - for MessageSenderAndReceiver + impl< + To, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > ModeRequestReceiver + for MessageSenderAndReceiver { fn try_recv_mode_request( &self, @@ -469,8 +481,13 @@ pub mod alloc_mod { } } - impl, R: MessageReceiver> ModeRequestSender - for MessageSenderAndReceiver + impl< + From, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > ModeRequestSender + for MessageSenderAndReceiver { fn local_channel_id(&self) -> ComponentId { self.local_channel_id_generic() @@ -482,7 +499,7 @@ pub mod alloc_mod { target_id: ComponentId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map.send_mode_request( + self.message_sender_store.send_message( MessageMetadata::new(request_id, self.local_channel_id()), target_id, request, @@ -492,10 +509,10 @@ pub mod alloc_mod { impl< REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > RequestAndReplySenderAndReceiver { pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S0) { @@ -506,10 +523,10 @@ pub mod alloc_mod { impl< REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > ModeRequestSender for RequestAndReplySenderAndReceiver { @@ -533,10 +550,10 @@ pub mod alloc_mod { impl< REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > ModeRequestReceiver for RequestAndReplySenderAndReceiver { @@ -552,33 +569,55 @@ pub mod alloc_mod { pub mod std_mod { use std::sync::mpsc; + use crate::request::{MessageSenderList, OneMessageSender}; + use super::*; - pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface< + pub type ModeRequestHandlerOneParentMpsc = ModeRequestHandlerInterface< mpsc::Sender>, mpsc::Receiver>, + OneMessageSender>>, >; - pub type ModeRequestHandlerMpscBounded = ModeRequestHandlerInterface< + pub type ModeRequestHandlerOneParentMpscBounded = ModeRequestHandlerInterface< mpsc::SyncSender>, mpsc::Receiver>, + OneMessageSender>>, >; - pub type ModeRequestorMpsc = ModeRequestorInterface< + pub type ModeRequestorOneChildMpsc = ModeRequestorInterface< mpsc::Sender>, mpsc::Receiver>, + OneMessageSender>>, >; - pub type ModeRequestorBoundedMpsc = ModeRequestorInterface< + pub type ModeRequestorOneChildBoundedMpsc = ModeRequestorInterface< mpsc::SyncSender>, mpsc::Receiver>, + OneMessageSender< + ModeRequest, + mpsc::SyncSender>, + >, + >; + pub type ModeRequestorMultiChildListMpsc = ModeRequestorInterface< + mpsc::Sender>, + mpsc::Receiver>, + MessageSenderList>>, + >; + pub type ModeRequestorMultiChildListBoundedMpsc = ModeRequestorInterface< + mpsc::SyncSender>, + mpsc::Receiver>, + MessageSenderList< + ModeRequest, + mpsc::SyncSender>, + >, >; - pub type ModeRequestorAndHandlerMpsc = ModeInterface< + pub type ModeRequestorAndHandlerOneParentMpsc = ModeInterface< mpsc::Sender>, mpsc::Receiver>, mpsc::Sender>, mpsc::Receiver>, >; - pub type ModeRequestorAndHandlerMpscBounded = ModeInterface< + pub type ModeRequestorAndHandlerOneParentMpscBounded = ModeInterface< mpsc::SyncSender>, mpsc::Receiver>, mpsc::SyncSender>, diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index e1063d7..50e17ff 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -3,7 +3,7 @@ use hashbrown::HashMap; use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, - request::MessageSender, + request::MessageSenderProvider, ComponentId, }; @@ -19,7 +19,7 @@ pub trait ModeNode { /// A mode parent is capable of sending mode requests to child objects and has a unique component /// ID. pub trait ModeParent: ModeNode { - type Sender: MessageSender; + type Sender: MessageSenderProvider; fn add_mode_child(&mut self, id: ComponentId, request_sender: Self::Sender); } @@ -28,7 +28,7 @@ pub trait ModeParent: ModeNode { /// /// A child is capable of sending mode replies to parent objects and has a unique component ID. pub trait ModeChild: ModeNode { - type Sender: MessageSender; + type Sender: MessageSenderProvider; fn add_mode_parent(&mut self, id: ComponentId, reply_sender: Self::Sender); } diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 6bcd270..0039609 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -68,7 +68,8 @@ pub mod alloc_mod { action::ActionRequest, queue::GenericTargetedMessagingError, request::{ - GenericMessage, MessageReceiver, MessageSender, MessageSenderAndReceiver, RequestId, + GenericMessage, MessageReceiverProvider, MessageSenderAndReceiver, + MessageSenderProvider, MessageSenderStoreProvider, RequestId, }, ComponentId, }; @@ -76,11 +77,14 @@ pub mod alloc_mod { use super::ActionReplyPus; /// Helper type definition for a mode handler which can handle mode requests. - pub type ActionRequestHandlerInterface = - MessageSenderAndReceiver; + pub type ActionRequestHandlerInterface = + MessageSenderAndReceiver; - impl, R: MessageReceiver> - ActionRequestHandlerInterface + impl< + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + ReplySender: MessageSenderStoreProvider, + > ActionRequestHandlerInterface { pub fn try_recv_action_request( &self, @@ -100,11 +104,20 @@ pub mod alloc_mod { /// Helper type defintion for a mode handler object which can send mode requests and receive /// mode replies. - pub type ActionRequestorInterface = - MessageSenderAndReceiver; + pub type ActionRequestorInterface = + MessageSenderAndReceiver< + ActionRequest, + ActionReplyPus, + Sender, + Receiver, + RequestSenderStore, + >; - impl, R: MessageReceiver> - ActionRequestorInterface + impl< + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + RequestSenderStore: MessageSenderStoreProvider, + > ActionRequestorInterface { pub fn try_recv_action_reply( &self, @@ -132,6 +145,7 @@ pub mod std_mod { verification::{self, TcStateToken}, ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, }, + request::{MessageSenderMap, OneMessageSender}, ComponentId, }; @@ -174,22 +188,38 @@ pub mod std_mod { } pub type DefaultActiveActionRequestMap = DefaultActiveRequestMap; - pub type ActionRequestHandlerMpsc = ActionRequestHandlerInterface< + pub type ActionRequestHandlerOneSenderMpsc = ActionRequestHandlerInterface< mpsc::Sender>, mpsc::Receiver>, + OneMessageSender< + GenericMessage, + mpsc::Sender>, + >, >; - pub type ActionRequestHandlerMpscBounded = ActionRequestHandlerInterface< + pub type ActionRequestHandlerOneSenderMpscBounded = ActionRequestHandlerInterface< mpsc::SyncSender>, mpsc::Receiver>, + OneMessageSender< + GenericMessage, + mpsc::SyncSender>, + >, >; - pub type ActionRequestorMpsc = ActionRequestorInterface< + pub type ActionRequestorWithSenderMapMpsc = ActionRequestorInterface< mpsc::Sender>, mpsc::Receiver>, + MessageSenderMap< + GenericMessage, + mpsc::Sender>, + >, >; - pub type ActionRequestorBoundedMpsc = ActionRequestorInterface< + pub type ActionRequestorWithSenderMapBoundedMpsc = ActionRequestorInterface< mpsc::SyncSender>, mpsc::Receiver>, + MessageSenderMap< + GenericMessage, + mpsc::SyncSender>, + >, >; } diff --git a/satrs/src/pus/mode.rs b/satrs/src/pus/mode.rs index 5ff78bf..75bf40c 100644 --- a/satrs/src/pus/mode.rs +++ b/satrs/src/pus/mode.rs @@ -39,7 +39,7 @@ mod tests { use crate::{ mode::{ ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender, - ModeRequestorAndHandlerMpsc, ModeRequestorMpsc, + ModeRequestorAndHandlerOneParentMpsc, ModeRequestorOneChildMpsc, }, request::{GenericMessage, MessageMetadata}, }; @@ -52,7 +52,7 @@ mod tests { fn test_simple_mode_requestor() { let (reply_sender, reply_receiver) = mpsc::channel(); let (request_sender, request_receiver) = mpsc::channel(); - let mut mode_requestor = ModeRequestorMpsc::new(TEST_COMPONENT_ID_0, reply_receiver); + let mut mode_requestor = ModeRequestorOneChildMpsc::new(TEST_COMPONENT_ID_0, reply_receiver); mode_requestor.add_message_target(TEST_COMPONENT_ID_1, request_sender); // Send a request and verify it arrives at the receiver. @@ -89,7 +89,7 @@ mod tests { let (request_sender_to_channel_1, request_receiver_channel_1) = mpsc::channel(); //let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); - let mut mode_connector = ModeRequestorAndHandlerMpsc::new( + let mut mode_connector = ModeRequestorAndHandlerOneParentMpsc::new( TEST_COMPONENT_ID_0, request_receiver_of_connector, reply_receiver_of_connector, @@ -128,7 +128,7 @@ mod tests { let (_request_sender_to_connector, request_receiver_of_connector) = mpsc::channel(); let (reply_sender_to_channel_2, reply_receiver_channel_2) = mpsc::channel(); - let mut mode_connector = ModeRequestorAndHandlerMpsc::new( + let mut mode_connector = ModeRequestorAndHandlerOneParentMpsc::new( TEST_COMPONENT_ID_0, request_receiver_of_connector, reply_receiver_of_connector, diff --git a/satrs/src/request.rs b/satrs/src/request.rs index f188798..ab80e90 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -140,24 +140,27 @@ impl GenericMessage { } /// Generic trait for objects which can send targeted messages. -pub trait MessageSender: Send { +pub trait MessageSenderProvider: Send { fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError>; } // Generic trait for objects which can receive targeted messages. -pub trait MessageReceiver { +pub trait MessageReceiverProvider { fn try_recv(&self) -> Result>, GenericTargetedMessagingError>; } -pub struct MessageWithSenderIdReceiver>(pub R, PhantomData); +pub struct MessageWithSenderIdReceiver>( + pub R, + PhantomData, +); -impl> From for MessageWithSenderIdReceiver { +impl> From for MessageWithSenderIdReceiver { fn from(receiver: R) -> Self { MessageWithSenderIdReceiver(receiver, PhantomData) } } -impl> MessageWithSenderIdReceiver { +impl> MessageWithSenderIdReceiver { pub fn try_recv_message( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -165,12 +168,12 @@ impl> MessageWithSenderIdReceiver { } } -pub struct MessageReceiverWithId> { +pub struct MessageReceiverWithId> { local_channel_id: ComponentId, reply_receiver: MessageWithSenderIdReceiver, } -impl> MessageReceiverWithId { +impl> MessageReceiverWithId { pub fn new(local_channel_id: ComponentId, reply_receiver: R) -> Self { Self { local_channel_id, @@ -183,7 +186,7 @@ impl> MessageReceiverWithId { } } -impl> MessageReceiverWithId { +impl> MessageReceiverWithId { pub fn try_recv_message( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -191,6 +194,17 @@ impl> MessageReceiverWithId { } } +pub trait MessageSenderStoreProvider: Default { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender); + + fn send_message( + &self, + requestor_info: MessageMetadata, + target_channel_id: ComponentId, + message: Message, + ) -> Result<(), GenericTargetedMessagingError>; +} + #[cfg(feature = "alloc")] pub mod alloc_mod { use crate::queue::GenericSendError; @@ -198,23 +212,99 @@ pub mod alloc_mod { use super::*; use hashbrown::HashMap; - pub struct MessageSenderMap>( - pub HashMap, + pub struct OneMessageSender> { + pub id_and_sender: Option<(ComponentId, S)>, + pub(crate) phantom: PhantomData, + } + + impl> Default for OneMessageSender { + fn default() -> Self { + Self { + id_and_sender: Default::default(), + phantom: Default::default(), + } + } + } + + impl> MessageSenderStoreProvider + for OneMessageSender + { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + if self.id_and_sender.is_some() { + return; + } + self.id_and_sender = Some((target_id, message_sender)); + } + + fn send_message( + &self, + requestor_info: MessageMetadata, + target_channel_id: ComponentId, + message: Msg, + ) -> Result<(), GenericTargetedMessagingError> { + if let Some((current_id, sender)) = &self.id_and_sender { + if *current_id == target_channel_id { + sender.send(GenericMessage::new(requestor_info, message))?; + return Ok(()); + } + } + Err(GenericSendError::TargetDoesNotExist(target_channel_id).into()) + } + } + + pub struct MessageSenderList>( + pub alloc::vec::Vec<(ComponentId, S)>, pub(crate) PhantomData, ); - impl> Default for MessageSenderMap { + impl> Default for MessageSenderList { fn default() -> Self { Self(Default::default(), PhantomData) } } - impl> MessageSenderMap { - pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + impl> MessageSenderStoreProvider + for MessageSenderList + { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + self.0.push((target_id, message_sender)); + } + + fn send_message( + &self, + requestor_info: MessageMetadata, + target_channel_id: ComponentId, + message: MSG, + ) -> Result<(), GenericTargetedMessagingError> { + for (current_id, sender) in &self.0 { + if *current_id == target_channel_id { + sender.send(GenericMessage::new(requestor_info, message))?; + return Ok(()); + } + } + Err(GenericSendError::TargetDoesNotExist(target_channel_id).into()) + } + } + + pub struct MessageSenderMap>( + pub HashMap, + pub(crate) PhantomData, + ); + + impl> Default for MessageSenderMap { + fn default() -> Self { + Self(Default::default(), PhantomData) + } + } + + impl> MessageSenderStoreProvider + for MessageSenderMap + { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { self.0.insert(target_id, message_sender); } - pub fn send_message( + fn send_message( &self, requestor_info: MessageMetadata, target_channel_id: ComponentId, @@ -231,25 +321,38 @@ pub mod alloc_mod { } } - pub struct MessageSenderAndReceiver, R: MessageReceiver> { + pub struct MessageSenderAndReceiver< + To, + From, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > { pub local_channel_id: ComponentId, - pub message_sender_map: MessageSenderMap, - pub message_receiver: MessageWithSenderIdReceiver, + pub message_sender_store: SenderStore, + pub message_receiver: MessageWithSenderIdReceiver, + pub(crate) phantom: PhantomData<(To, Sender)>, } - impl, R: MessageReceiver> - MessageSenderAndReceiver + impl< + To, + From, + Sender: MessageSenderProvider, + Receiver: MessageReceiverProvider, + SenderStore: MessageSenderStoreProvider, + > MessageSenderAndReceiver { - pub fn new(local_channel_id: ComponentId, message_receiver: R) -> Self { + pub fn new(local_channel_id: ComponentId, message_receiver: Receiver) -> Self { Self { local_channel_id, - message_sender_map: Default::default(), + message_sender_store: Default::default(), message_receiver: MessageWithSenderIdReceiver::from(message_receiver), + phantom: PhantomData, } } - pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { - self.message_sender_map + pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) { + self.message_sender_store .add_message_target(target_id, message_sender) } @@ -262,9 +365,9 @@ pub mod alloc_mod { &self, request_id: RequestId, target_id: ComponentId, - message: TO, + message: To, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map.send_message( + self.message_sender_store.send_message( MessageMetadata::new(request_id, self.local_channel_id_generic()), target_id, message, @@ -274,7 +377,7 @@ pub mod alloc_mod { /// Try to receive a message, which can be a reply or a request, depending on the generics. pub fn try_recv_message( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.message_receiver.try_recv_message() } } @@ -282,10 +385,10 @@ pub mod alloc_mod { pub struct RequestAndReplySenderAndReceiver< REQUEST, REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > { pub local_channel_id: ComponentId, // These 2 are a functional group. @@ -299,10 +402,10 @@ pub mod alloc_mod { impl< REQUEST, REPLY, - S0: MessageSender, - R0: MessageReceiver, - S1: MessageSender, - R1: MessageReceiver, + S0: MessageSenderProvider, + R0: MessageReceiverProvider, + S1: MessageSenderProvider, + R1: MessageReceiverProvider, > RequestAndReplySenderAndReceiver { pub fn new( @@ -333,14 +436,14 @@ pub mod std_mod { use crate::queue::{GenericReceiveError, GenericSendError}; - impl MessageSender for mpsc::Sender> { + impl MessageSenderProvider for mpsc::Sender> { fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError> { self.send(message) .map_err(|_| GenericSendError::RxDisconnected)?; Ok(()) } } - impl MessageSender for mpsc::SyncSender> { + impl MessageSenderProvider for mpsc::SyncSender> { fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError> { if let Err(e) = self.try_send(message) { return match e { @@ -357,7 +460,7 @@ pub mod std_mod { pub type MessageSenderMapMpsc = MessageReceiverWithId>; pub type MessageSenderMapBoundedMpsc = MessageReceiverWithId>; - impl MessageReceiver for mpsc::Receiver> { + impl MessageReceiverProvider for mpsc::Receiver> { fn try_recv(&self) -> Result>, GenericTargetedMessagingError> { match self.try_recv() { Ok(msg) => Ok(Some(msg)), @@ -386,7 +489,7 @@ mod tests { use crate::{ queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError}, - request::{MessageMetadata, MessageSenderMap}, + request::{MessageMetadata, MessageSenderMap, MessageSenderStoreProvider}, }; use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId}; diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index eb4235c..93d3213 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,9 +1,5 @@ use core::cell::Cell; -use satrs::mode::{ - Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, - ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, - ModeRequestorBoundedMpsc, -}; +use satrs::mode::{Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, ModeRequestHandlerOneParentMpscBounded, ModeRequestReceiver, ModeRequestSender, ModeRequestorAndHandlerOneParentMpscBounded, ModeRequestorOneChildBoundedMpsc}; use satrs::mode_tree::{ connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableMapTable, TargetTableEntry, @@ -159,7 +155,7 @@ impl ModeRequestHandler for ModeRequestHandlerMock { struct PusModeService { pub request_id_counter: Cell, - pub mode_node: ModeRequestorBoundedMpsc, + pub mode_node: ModeRequestorOneChildBoundedMpsc, } impl PusModeService { @@ -191,16 +187,17 @@ impl ModeParent for PusModeService { } struct AcsSubsystem { - pub mode_node: ModeRequestorAndHandlerMpscBounded, + pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, pub subsystem_helper: SubsystemHelper, pub mode_req_handler_mock: ModeRequestHandlerMock, + pub mode_msgs_recvd: u32, } impl AcsSubsystem { - pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self { + pub fn new(mode_node: ModeRequestorAndHandlerOneParentMpscBounded) -> Self { Self { mode_node, mode_requestor_info: None, @@ -208,13 +205,25 @@ impl AcsSubsystem { target_mode_and_submode: None, subsystem_helper: Default::default(), mode_req_handler_mock: Default::default(), + mode_msgs_recvd: 0, } } + + pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { + let tmp = self.mode_msgs_recvd; + self.mode_msgs_recvd = 0; + tmp + } + pub fn run(&mut self) { if let Some(request) = self.mode_node.try_recv_mode_request().unwrap() { + self.mode_msgs_recvd += 1; self.handle_mode_request(request) .expect("mode messaging error"); } + if let Some(_reply) = self.mode_node.try_recv_mode_reply().unwrap(){ + // TODO: Implementation. + } } pub fn add_target_and_sequence_table( &mut self, @@ -345,20 +354,34 @@ impl ModeRequestHandler for AcsSubsystem { } struct MgmAssembly { - pub mode_node: ModeRequestorAndHandlerMpscBounded, + pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, pub mode_req_mock: ModeRequestHandlerMock, + pub mode_msgs_recvd: u32, } impl MgmAssembly { + pub fn new(mode_node: ModeRequestorAndHandlerOneParentMpscBounded) -> Self { + Self { + mode_node, + mode_requestor_info: None, + mode_and_submode: UNKNOWN_MODE, + target_mode_and_submode: None, + mode_req_mock: Default::default(), + mode_msgs_recvd: 0, + } + } + pub fn run(&mut self) { self.check_mode_requests().expect("mode messaging error"); self.check_mode_replies().expect("mode messaging error"); } - fn id(&self) -> ComponentId { - TestComponentId::MagnetometerAssembly as u64 + pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { + let tmp = self.mode_msgs_recvd; + self.mode_msgs_recvd = 0; + tmp } pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { @@ -395,7 +418,7 @@ impl MgmAssembly { impl ModeNode for MgmAssembly { fn id(&self) -> ComponentId { - self.id() + TestComponentId::MagnetometerAssembly as u64 } } impl ModeParent for MgmAssembly { @@ -473,18 +496,6 @@ impl ModeRequestHandler for MgmAssembly { Ok(()) } - fn send_mode_reply( - &self, - requestor: MessageMetadata, - reply: ModeReply, - ) -> Result<(), Self::Error> { - self.mode_node.send_mode_reply(requestor, reply)?; - self.mode_req_mock - .send_mode_reply(requestor, reply) - .unwrap(); - Ok(()) - } - fn handle_mode_info( &mut self, requestor_info: MessageMetadata, @@ -496,21 +507,34 @@ impl ModeRequestHandler for MgmAssembly { // TODO: A proper assembly must reach to mode changes of its children.. Ok(()) } + + fn send_mode_reply( + &self, + requestor: MessageMetadata, + reply: ModeReply, + ) -> Result<(), Self::Error> { + self.mode_node.send_mode_reply(requestor, reply)?; + self.mode_req_mock + .send_mode_reply(requestor, reply) + .unwrap(); + Ok(()) + } } struct DeviceManager { name: &'static str, pub id: ComponentId, - pub mode_node: ModeRequestorAndHandlerMpscBounded, + pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, pub mode_and_submode: ModeAndSubmode, pub mode_req_mock: ModeRequestHandlerMock, + pub mode_msgs_recvd: u32, } impl DeviceManager { pub fn new( name: &'static str, id: ComponentId, - mode_node: ModeRequestorAndHandlerMpscBounded, + mode_node: ModeRequestorAndHandlerOneParentMpscBounded, ) -> Self { Self { name, @@ -518,8 +542,26 @@ impl DeviceManager { mode_node, mode_and_submode: UNKNOWN_MODE, mode_req_mock: Default::default(), + mode_msgs_recvd: 0, } } + + pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { + let tmp = self.mode_msgs_recvd; + self.mode_msgs_recvd = 0; + tmp + } + + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { + if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.handle_mode_request(request)? + } + Ok(()) + } } impl ModeNode for DeviceManager { @@ -571,6 +613,23 @@ impl ModeRequestHandler for DeviceManager { "{}: announcing mode: {:?}", self.name, self.mode_and_submode ); + let mut mode_request = ModeRequest::AnnounceMode; + if recursive { + mode_request = ModeRequest::AnnounceModeRecursive; + } + let request_id = requestor_info.map_or(0, |info| info.request_id()); + self.mode_node + .request_sender_map + .0 + .iter() + .for_each(|(_, sender)| { + sender + .send(GenericMessage::new( + MessageMetadata::new(request_id, self.mode_node.local_channel_id_generic()), + mode_request, + )) + .expect("sending mode request failed"); + }); self.mode_req_mock.announce_mode(requestor_info, recursive); } @@ -581,18 +640,6 @@ impl ModeRequestHandler for DeviceManager { self.mode_req_mock.handle_mode_reached(requestor).unwrap(); Ok(()) } - fn send_mode_reply( - &self, - requestor_info: MessageMetadata, - reply: ModeReply, - ) -> Result<(), ModeError> { - self.mode_node.send_mode_reply(requestor_info, reply)?; - self.mode_req_mock - .send_mode_reply(requestor_info, reply) - .unwrap(); - Ok(()) - } - fn handle_mode_info( &mut self, requestor_info: MessageMetadata, @@ -610,21 +657,34 @@ impl ModeRequestHandler for DeviceManager { .unwrap(); Ok(()) } + + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), ModeError> { + self.mode_node.send_mode_reply(requestor_info, reply)?; + self.mode_req_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); + Ok(()) + } } struct CommonDevice { name: &'static str, pub id: ComponentId, - pub mode_node: ModeRequestHandlerMpscBounded, + pub mode_node: ModeRequestHandlerOneParentMpscBounded, pub mode_and_submode: ModeAndSubmode, pub mode_req_mock: ModeRequestHandlerMock, + pub num_mode_msgs_recvd: u32, } impl CommonDevice { pub fn new( name: &'static str, id: ComponentId, - mode_node: ModeRequestHandlerMpscBounded, + mode_node: ModeRequestHandlerOneParentMpscBounded, ) -> Self { Self { name, @@ -632,6 +692,7 @@ impl CommonDevice { mode_node, mode_and_submode: UNKNOWN_MODE, mode_req_mock: Default::default(), + num_mode_msgs_recvd: 0, } } @@ -641,10 +702,17 @@ impl CommonDevice { pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.num_mode_msgs_recvd += 1; self.handle_mode_request(request)? } Ok(()) } + + pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { + let tmp = self.num_mode_msgs_recvd; + self.num_mode_msgs_recvd = 0; + tmp + } } impl ModeNode for CommonDevice { @@ -698,18 +766,6 @@ impl ModeRequestHandler for CommonDevice { self.mode_req_mock.handle_mode_reached(requestor).unwrap(); Ok(()) } - fn send_mode_reply( - &self, - requestor_info: MessageMetadata, - reply: ModeReply, - ) -> Result<(), ModeError> { - self.mode_node.send_mode_reply(requestor_info, reply)?; - self.mode_req_mock - .send_mode_reply(requestor_info, reply) - .unwrap(); - Ok(()) - } - fn handle_mode_info( &mut self, requestor_info: MessageMetadata, @@ -727,6 +783,18 @@ impl ModeRequestHandler for CommonDevice { .unwrap(); Ok(()) } + + fn send_mode_reply( + &self, + requestor_info: MessageMetadata, + reply: ModeReply, + ) -> Result<(), ModeError> { + self.mode_node.send_mode_reply(requestor_info, reply)?; + self.mode_req_mock + .send_mode_reply(requestor_info, reply) + .unwrap(); + Ok(()) + } } #[derive(Debug, Default)] @@ -736,7 +804,7 @@ pub struct AnnounceModeInfo { } pub struct AcsController { - pub mode_node: ModeRequestHandlerMpscBounded, + pub mode_node: ModeRequestHandlerOneParentMpscBounded, pub mode_and_submode: ModeAndSubmode, pub announce_mode_queue: RefCell>, pub mode_req_mock: ModeRequestHandlerMock, @@ -879,42 +947,42 @@ impl TreeTestbench { let (reply_sender_to_mgt_man, reply_receiver_mgt_man) = mpsc::sync_channel(10); // Mode requestors only. - let mode_node_pus = ModeRequestorBoundedMpsc::new( + let mode_node_pus = ModeRequestorOneChildBoundedMpsc::new( TestComponentId::PusModeService as ComponentId, reply_receiver_pus, ); // Mode requestors and handlers. - let mut mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( + let mgm_assy_node = ModeRequestorAndHandlerOneParentMpscBounded::new( TestComponentId::MagnetometerAssembly as ComponentId, request_receiver_mgm_assy, reply_receiver_mgm_assy, ); - let mut mgt_dev_mgmt_node = ModeRequestorAndHandlerMpscBounded::new( + let mgt_dev_mgmt_node = ModeRequestorAndHandlerOneParentMpscBounded::new( TestComponentId::MgtDevManager as ComponentId, request_receiver_mgt_man, reply_receiver_mgt_man, ); - let acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( + let acs_subsystem_node = ModeRequestorAndHandlerOneParentMpscBounded::new( TestComponentId::AcsSubsystem as ComponentId, request_receiver_acs_subsystem, reply_receiver_acs_subsystem, ); // Request handlers only. - let mut mgm_dev_node_0 = ModeRequestHandlerMpscBounded::new( + let mgm_dev_node_0 = ModeRequestHandlerOneParentMpscBounded::new( TestComponentId::MagnetometerDevice0 as ComponentId, request_receiver_mgm_dev_0, ); - let mut mgm_dev_node_1 = ModeRequestHandlerMpscBounded::new( + let mgm_dev_node_1 = ModeRequestHandlerOneParentMpscBounded::new( TestComponentId::MagnetometerDevice1 as ComponentId, request_receiver_mgm_dev_1, ); - let mut mgt_dev_node = ModeRequestHandlerMpscBounded::new( + let mgt_dev_node = ModeRequestHandlerOneParentMpscBounded::new( TestComponentId::MagnetorquerDevice as ComponentId, request_receiver_mgt_dev, ); - let acs_ctrl_node = ModeRequestHandlerMpscBounded::new( + let acs_ctrl_node = ModeRequestHandlerOneParentMpscBounded::new( TestComponentId::AcsController as ComponentId, request_receiver_acs_ctrl, ); @@ -926,7 +994,7 @@ impl TreeTestbench { ); let mut mgm_dev_1 = CommonDevice::new( "MGM_1", - TestComponentId::MagnetometerDevice0 as u64, + TestComponentId::MagnetometerDevice1 as u64, mgm_dev_node_1, ); let mut mgt_dev = CommonDevice::new( @@ -939,13 +1007,7 @@ impl TreeTestbench { TestComponentId::MgtDevManager as u64, mgt_dev_mgmt_node, ); - let mut mgm_assy = MgmAssembly { - mode_node: mgm_assy_node, - mode_requestor_info: None, - mode_and_submode: UNKNOWN_MODE, - target_mode_and_submode: None, - mode_req_mock: ModeRequestHandlerMock::default(), - }; + let mut mgm_assy = MgmAssembly::new(mgm_assy_node); let mut acs_subsystem = AcsSubsystem::new(acs_subsystem_node); let mut acs_ctrl = AcsController { mode_node: acs_ctrl_node, @@ -1042,8 +1104,8 @@ impl TreeTestbench { ); connect_mode_nodes( &mut acs_subsystem, - request_sender_to_mgt_dev.clone(), - &mut mgt_dev, + request_sender_to_mgt_man.clone(), + &mut mgt_manager, reply_sender_to_acs_subsystem.clone(), ); @@ -1059,6 +1121,7 @@ impl TreeTestbench { &mut mgm_dev_1, reply_sender_to_mgm_assy, ); + connect_mode_nodes( &mut mgt_manager, request_sender_to_mgt_dev, @@ -1081,12 +1144,16 @@ impl TreeTestbench { fn announce_recursively() { let mut tb = TreeTestbench::new(); tb.pus.announce_modes_recursively(); - tb.subsystem.run(); - tb.ctrl.run(); - tb.mgm_assy.run(); - tb.mgm_devs[0].run(); - tb.mgm_devs[1].run(); - tb.mgt_dev.run(); + // Run everything twice so the order does not matter. + for _ in 0..2 { + tb.subsystem.run(); + tb.ctrl.run(); + tb.mgt_manager.run(); + tb.mgm_assy.run(); + tb.mgm_devs[0].run(); + tb.mgm_devs[1].run(); + tb.mgt_dev.run(); + } let mut announces = tb .subsystem .mode_req_handler_mock @@ -1101,17 +1168,27 @@ fn announce_recursively() { assert_eq!(tb.mgm_assy.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(tb.mgm_assy.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); - for mgm_dev in &tb.mgm_devs { + for mgm_dev in &mut tb.mgm_devs { + assert_eq!(mgm_dev.get_and_clear_num_mode_msgs(), 1); announces = mgm_dev.mode_req_mock.announce_mode_calls.borrow_mut(); assert_eq!(mgm_dev.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(mgm_dev.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); } assert_eq!(announces.len(), 1); + assert_eq!(tb.mgt_dev.get_and_clear_num_mode_msgs(), 1); announces = tb.mgt_dev.mode_req_mock.announce_mode_calls.borrow_mut(); assert_eq!(tb.mgt_dev.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(tb.mgt_dev.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); + announces = tb + .mgt_manager + .mode_req_mock + .announce_mode_calls + .borrow_mut(); + assert_eq!(tb.mgt_manager.mode_req_mock.start_transition_calls.len(), 0); + assert_eq!(tb.mgt_manager.mode_and_submode(), UNKNOWN_MODE); + assert_eq!(announces.len(), 1); } #[test] -- 2.43.0 From ba5c7d4a2f7e211121d46737e501c637532996a2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 2 Dec 2024 16:37:28 +0100 Subject: [PATCH 6/9] continue mode tree feature --- satrs/src/mode.rs | 217 +++++++++++++++++++++++++----------- satrs/src/pus/mode.rs | 3 +- satrs/src/request.rs | 87 +++++++++------ satrs/src/tmtc/tm_helper.rs | 24 ++-- satrs/tests/mode_tree.rs | 109 ++++++++++++------ 5 files changed, 288 insertions(+), 152 deletions(-) diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index 1b4d636..471b36d 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -336,26 +336,51 @@ pub mod alloc_mod { } impl< - REQUEST, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, - > RequestAndReplySenderAndReceiver + Request, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, + > + RequestAndReplySenderAndReceiver< + Request, + ReqSender, + ReqReceiver, + ReqSenderStore, + Reply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { - pub fn add_reply_target(&mut self, target_id: ComponentId, reply_sender: S1) { - self.reply_sender_map + pub fn add_reply_target(&mut self, target_id: ComponentId, reply_sender: ReplySender) { + self.reply_sender_store .add_message_target(target_id, reply_sender) } } impl< - REQUEST, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, - > ModeReplySender for RequestAndReplySenderAndReceiver + Request, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, + > ModeReplySender + for RequestAndReplySenderAndReceiver< + Request, + ReqSender, + ReqReceiver, + ReqSenderStore, + ModeReply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { fn local_channel_id(&self) -> ComponentId { self.local_channel_id_generic() @@ -364,24 +389,35 @@ pub mod alloc_mod { fn send_mode_reply( &self, requestor_info: MessageMetadata, - request: ModeReply, + reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.reply_sender_map.send_mode_reply( + self.reply_sender_store.send_message( MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()), requestor_info.sender_id(), - request, + reply, ) } } impl< - REQUEST, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, + Request, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, > ModeReplyReceiver - for RequestAndReplySenderAndReceiver + for RequestAndReplySenderAndReceiver< + Request, + ReqSender, + ReqReceiver, + ReqSenderStore, + ModeReply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { fn try_recv_mode_reply( &self, @@ -448,8 +484,23 @@ pub mod alloc_mod { /// Helper type defintion for a mode handler object which can both send mode requests and /// process mode requests. - pub type ModeInterface = - RequestAndReplySenderAndReceiver; + pub type ModeInterface< + ReqSender, + ReqReceiver, + ReqSenderStore, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > = RequestAndReplySenderAndReceiver< + ModeRequest, + ReqSender, + ReqReceiver, + ReqSenderStore, + ModeReply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + >; impl> MessageSenderMap { pub fn send_mode_request( @@ -508,27 +559,50 @@ pub mod alloc_mod { } impl< - REPLY, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, - > RequestAndReplySenderAndReceiver + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, + > + RequestAndReplySenderAndReceiver< + ModeRequest, + ReqSender, + ReqReceiver, + ReqSenderStore, + Reply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { - pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S0) { - self.request_sender_map + pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: ReqSender) { + self.request_sender_store .add_message_target(target_id, request_sender) } } impl< - REPLY, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, > ModeRequestSender - for RequestAndReplySenderAndReceiver + for RequestAndReplySenderAndReceiver< + ModeRequest, + ReqSender, + ReqReceiver, + ReqSenderStore, + Reply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { fn local_channel_id(&self) -> ComponentId { self.local_channel_id_generic() @@ -540,7 +614,7 @@ pub mod alloc_mod { target_id: ComponentId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.request_sender_map.send_mode_request( + self.request_sender_store.send_message( MessageMetadata::new(request_id, self.local_channel_id()), target_id, request, @@ -549,13 +623,24 @@ pub mod alloc_mod { } impl< - REPLY, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, > ModeRequestReceiver - for RequestAndReplySenderAndReceiver + for RequestAndReplySenderAndReceiver< + ModeRequest, + ReqSender, + ReqReceiver, + ReqSenderStore, + Reply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { fn try_recv_mode_request( &self, @@ -573,15 +658,15 @@ pub mod std_mod { use super::*; - pub type ModeRequestHandlerOneParentMpsc = ModeRequestHandlerInterface< + pub type ModeRequestHandlerMpsc = ModeRequestHandlerInterface< mpsc::Sender>, mpsc::Receiver>, - OneMessageSender>>, + MessageSenderList>>, >; - pub type ModeRequestHandlerOneParentMpscBounded = ModeRequestHandlerInterface< + pub type ModeRequestHandlerMpscBounded = ModeRequestHandlerInterface< mpsc::SyncSender>, mpsc::Receiver>, - OneMessageSender>>, + MessageSenderList>>, >; pub type ModeRequestorOneChildMpsc = ModeRequestorInterface< @@ -592,36 +677,34 @@ pub mod std_mod { pub type ModeRequestorOneChildBoundedMpsc = ModeRequestorInterface< mpsc::SyncSender>, mpsc::Receiver>, - OneMessageSender< - ModeRequest, - mpsc::SyncSender>, - >, + OneMessageSender>>, >; - pub type ModeRequestorMultiChildListMpsc = ModeRequestorInterface< + pub type ModeRequestorChildListMpsc = ModeRequestorInterface< mpsc::Sender>, mpsc::Receiver>, MessageSenderList>>, >; - pub type ModeRequestorMultiChildListBoundedMpsc = ModeRequestorInterface< + pub type ModeRequestorChildListBoundedMpsc = ModeRequestorInterface< mpsc::SyncSender>, mpsc::Receiver>, - MessageSenderList< - ModeRequest, - mpsc::SyncSender>, - >, + MessageSenderList>>, >; - pub type ModeRequestorAndHandlerOneParentMpsc = ModeInterface< + pub type ModeRequestorAndHandlerMpsc = ModeInterface< mpsc::Sender>, - mpsc::Receiver>, + mpsc::Receiver>, + MessageSenderList>>, mpsc::Sender>, - mpsc::Receiver>, - >; - pub type ModeRequestorAndHandlerOneParentMpscBounded = ModeInterface< - mpsc::SyncSender>, mpsc::Receiver>, - mpsc::SyncSender>, + MessageSenderList>>, + >; + pub type ModeRequestorAndHandlerMpscBounded = ModeInterface< + mpsc::SyncSender>, mpsc::Receiver>, + MessageSenderList>>, + mpsc::SyncSender>, + mpsc::Receiver>, + MessageSenderList>>, >; } diff --git a/satrs/src/pus/mode.rs b/satrs/src/pus/mode.rs index 75bf40c..fea2bff 100644 --- a/satrs/src/pus/mode.rs +++ b/satrs/src/pus/mode.rs @@ -52,7 +52,8 @@ mod tests { fn test_simple_mode_requestor() { let (reply_sender, reply_receiver) = mpsc::channel(); let (request_sender, request_receiver) = mpsc::channel(); - let mut mode_requestor = ModeRequestorOneChildMpsc::new(TEST_COMPONENT_ID_0, reply_receiver); + let mut mode_requestor = + ModeRequestorOneChildMpsc::new(TEST_COMPONENT_ID_0, reply_receiver); mode_requestor.add_message_target(TEST_COMPONENT_ID_1, request_sender); // Send a request and verify it arrives at the receiver. diff --git a/satrs/src/request.rs b/satrs/src/request.rs index ab80e90..027486c 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -149,9 +149,9 @@ pub trait MessageReceiverProvider { fn try_recv(&self) -> Result>, GenericTargetedMessagingError>; } -pub struct MessageWithSenderIdReceiver>( - pub R, - PhantomData, +pub struct MessageWithSenderIdReceiver>( + pub Receiver, + PhantomData, ); impl> From for MessageWithSenderIdReceiver { @@ -208,6 +208,7 @@ pub trait MessageSenderStoreProvider: Default { #[cfg(feature = "alloc")] pub mod alloc_mod { use crate::queue::GenericSendError; + use std::convert::From; use super::*; use hashbrown::HashMap; @@ -226,10 +227,10 @@ pub mod alloc_mod { } } - impl> MessageSenderStoreProvider - for OneMessageSender + impl> MessageSenderStoreProvider + for OneMessageSender { - fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) { if self.id_and_sender.is_some() { return; } @@ -263,10 +264,10 @@ pub mod alloc_mod { } } - impl> MessageSenderStoreProvider - for MessageSenderList + impl> MessageSenderStoreProvider + for MessageSenderList { - fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) { self.0.push((target_id, message_sender)); } @@ -274,7 +275,7 @@ pub mod alloc_mod { &self, requestor_info: MessageMetadata, target_channel_id: ComponentId, - message: MSG, + message: Msg, ) -> Result<(), GenericTargetedMessagingError> { for (current_id, sender) in &self.0 { if *current_id == target_channel_id { @@ -297,10 +298,10 @@ pub mod alloc_mod { } } - impl> MessageSenderStoreProvider - for MessageSenderMap + impl> MessageSenderStoreProvider + for MessageSenderMap { - fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) { + fn add_message_target(&mut self, target_id: ComponentId, message_sender: Sender) { self.0.insert(target_id, message_sender); } @@ -308,7 +309,7 @@ pub mod alloc_mod { &self, requestor_info: MessageMetadata, target_channel_id: ComponentId, - message: MSG, + message: Msg, ) -> Result<(), GenericTargetedMessagingError> { if self.0.contains_key(&target_channel_id) { return self @@ -383,42 +384,58 @@ pub mod alloc_mod { } pub struct RequestAndReplySenderAndReceiver< - REQUEST, - REPLY, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, + Request, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, > { pub local_channel_id: ComponentId, // These 2 are a functional group. - pub request_sender_map: MessageSenderMap, - pub reply_receiver: MessageWithSenderIdReceiver, + pub request_sender_store: ReqSenderStore, + pub reply_receiver: MessageWithSenderIdReceiver, // These 2 are a functional group. - pub request_receiver: MessageWithSenderIdReceiver, - pub reply_sender_map: MessageSenderMap, + pub request_receiver: MessageWithSenderIdReceiver, + pub reply_sender_store: ReplySenderStore, + phantom: PhantomData<(ReqSender, ReplySender)>, } impl< - REQUEST, - REPLY, - S0: MessageSenderProvider, - R0: MessageReceiverProvider, - S1: MessageSenderProvider, - R1: MessageReceiverProvider, - > RequestAndReplySenderAndReceiver + Request, + ReqSender: MessageSenderProvider, + ReqReceiver: MessageReceiverProvider, + ReqSenderStore: MessageSenderStoreProvider, + Reply, + ReplySender: MessageSenderProvider, + ReplyReceiver: MessageReceiverProvider, + ReplySenderStore: MessageSenderStoreProvider, + > + RequestAndReplySenderAndReceiver< + Request, + ReqSender, + ReqReceiver, + ReqSenderStore, + Reply, + ReplySender, + ReplyReceiver, + ReplySenderStore, + > { pub fn new( local_channel_id: ComponentId, - request_receiver: R1, - reply_receiver: R0, + request_receiver: ReqReceiver, + reply_receiver: ReplyReceiver, ) -> Self { Self { local_channel_id, request_receiver: request_receiver.into(), reply_receiver: reply_receiver.into(), - request_sender_map: Default::default(), - reply_sender_map: Default::default(), + request_sender_store: Default::default(), + reply_sender_store: Default::default(), + phantom: PhantomData, } } diff --git a/satrs/src/tmtc/tm_helper.rs b/satrs/src/tmtc/tm_helper.rs index c8c488e..af61904 100644 --- a/satrs/src/tmtc/tm_helper.rs +++ b/satrs/src/tmtc/tm_helper.rs @@ -17,37 +17,37 @@ impl PusTmWithCdsShortHelper { } #[cfg(feature = "std")] - pub fn create_pus_tm_timestamp_now<'a>( - &'a mut self, + pub fn create_pus_tm_timestamp_now<'time, 'src_data>( + &'time mut self, service: u8, subservice: u8, - source_data: &'a [u8], + source_data: &'src_data [u8], seq_count: u16, - ) -> PusTmCreator { + ) -> PusTmCreator<'time, 'src_data> { let time_stamp = CdsTime::now_with_u16_days().unwrap(); time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap(); self.create_pus_tm_common(service, subservice, source_data, seq_count) } - pub fn create_pus_tm_with_stamper<'a>( - &'a mut self, + pub fn create_pus_tm_with_stamper<'time, 'src_data>( + &'time mut self, service: u8, subservice: u8, - source_data: &'a [u8], + source_data: &'src_data [u8], stamper: &CdsTime, seq_count: u16, - ) -> PusTmCreator { + ) -> PusTmCreator<'time, 'src_data> { stamper.write_to_bytes(&mut self.cds_short_buf).unwrap(); self.create_pus_tm_common(service, subservice, source_data, seq_count) } - fn create_pus_tm_common<'a>( - &'a self, + fn create_pus_tm_common<'time, 'src_data>( + &'time self, service: u8, subservice: u8, - source_data: &'a [u8], + source_data: &'src_data [u8], seq_count: u16, - ) -> PusTmCreator { + ) -> PusTmCreator<'time, 'src_data> { let reply_header = SpHeader::new_for_unseg_tm(self.apid, seq_count, 0); let tc_header = PusTmSecondaryHeader::new_simple(service, subservice, &self.cds_short_buf); PusTmCreator::new(reply_header, tc_header, source_data, true) diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 93d3213..00412ed 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,8 +1,12 @@ use core::cell::Cell; -use satrs::mode::{Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, ModeRequestHandlerOneParentMpscBounded, ModeRequestReceiver, ModeRequestSender, ModeRequestorAndHandlerOneParentMpscBounded, ModeRequestorOneChildBoundedMpsc}; +use satrs::mode::{ + Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, + ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, + ModeRequestorOneChildBoundedMpsc, +}; use satrs::mode_tree::{ - connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableMapTable, - TargetTableEntry, + connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableEntry, + SequenceTableMapTable, TargetTableEntry, }; use satrs::mode_tree::{ ModeStoreVec, SequenceModeTables, SequenceTablesMapValue, TargetModeTables, @@ -187,17 +191,17 @@ impl ModeParent for PusModeService { } struct AcsSubsystem { - pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, + pub mode_node: ModeRequestorAndHandlerMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, pub subsystem_helper: SubsystemHelper, pub mode_req_handler_mock: ModeRequestHandlerMock, - pub mode_msgs_recvd: u32, + pub mode_req_recvd: u32, } impl AcsSubsystem { - pub fn new(mode_node: ModeRequestorAndHandlerOneParentMpscBounded) -> Self { + pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self { Self { mode_node, mode_requestor_info: None, @@ -205,23 +209,23 @@ impl AcsSubsystem { target_mode_and_submode: None, subsystem_helper: Default::default(), mode_req_handler_mock: Default::default(), - mode_msgs_recvd: 0, + mode_req_recvd: 0, } } - pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { - let tmp = self.mode_msgs_recvd; - self.mode_msgs_recvd = 0; + pub fn get_and_clear_num_mode_requests(&mut self) -> u32 { + let tmp = self.mode_req_recvd; + self.mode_req_recvd = 0; tmp } pub fn run(&mut self) { if let Some(request) = self.mode_node.try_recv_mode_request().unwrap() { - self.mode_msgs_recvd += 1; + self.mode_req_recvd += 1; self.handle_mode_request(request) .expect("mode messaging error"); } - if let Some(_reply) = self.mode_node.try_recv_mode_reply().unwrap(){ + if let Some(_reply) = self.mode_node.try_recv_mode_reply().unwrap() { // TODO: Implementation. } } @@ -298,7 +302,7 @@ impl ModeRequestHandler for AcsSubsystem { } let request_id = requestor_info.map_or(0, |info| info.request_id()); self.mode_node - .request_sender_map + .request_sender_store .0 .iter() .for_each(|(_, sender)| { @@ -354,7 +358,7 @@ impl ModeRequestHandler for AcsSubsystem { } struct MgmAssembly { - pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, + pub mode_node: ModeRequestorAndHandlerMpscBounded, pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, @@ -363,7 +367,7 @@ struct MgmAssembly { } impl MgmAssembly { - pub fn new(mode_node: ModeRequestorAndHandlerOneParentMpscBounded) -> Self { + pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self { Self { mode_node, mode_requestor_info: None, @@ -386,6 +390,7 @@ impl MgmAssembly { pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.mode_msgs_recvd += 1; self.handle_mode_request(request).unwrap(); } Ok(()) @@ -469,7 +474,7 @@ impl ModeRequestHandler for MgmAssembly { } let request_id = requestor_info.map_or(0, |info| info.request_id()); self.mode_node - .request_sender_map + .request_sender_store .0 .iter() .for_each(|(_, sender)| { @@ -524,17 +529,17 @@ impl ModeRequestHandler for MgmAssembly { struct DeviceManager { name: &'static str, pub id: ComponentId, - pub mode_node: ModeRequestorAndHandlerOneParentMpscBounded, + pub mode_node: ModeRequestorAndHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, pub mode_req_mock: ModeRequestHandlerMock, - pub mode_msgs_recvd: u32, + pub mode_req_recvd: u32, } impl DeviceManager { pub fn new( name: &'static str, id: ComponentId, - mode_node: ModeRequestorAndHandlerOneParentMpscBounded, + mode_node: ModeRequestorAndHandlerMpscBounded, ) -> Self { Self { name, @@ -542,13 +547,13 @@ impl DeviceManager { mode_node, mode_and_submode: UNKNOWN_MODE, mode_req_mock: Default::default(), - mode_msgs_recvd: 0, + mode_req_recvd: 0, } } - pub fn get_and_clear_num_mode_msgs(&mut self) -> u32 { - let tmp = self.mode_msgs_recvd; - self.mode_msgs_recvd = 0; + pub fn get_and_clear_num_mode_requests(&mut self) -> u32 { + let tmp = self.mode_req_recvd; + self.mode_req_recvd = 0; tmp } @@ -558,6 +563,7 @@ impl DeviceManager { pub fn check_mode_requests(&mut self) -> Result<(), ModeError> { if let Some(request) = self.mode_node.try_recv_mode_request()? { + self.mode_req_recvd += 1; self.handle_mode_request(request)? } Ok(()) @@ -619,7 +625,7 @@ impl ModeRequestHandler for DeviceManager { } let request_id = requestor_info.map_or(0, |info| info.request_id()); self.mode_node - .request_sender_map + .request_sender_store .0 .iter() .for_each(|(_, sender)| { @@ -674,7 +680,7 @@ impl ModeRequestHandler for DeviceManager { struct CommonDevice { name: &'static str, pub id: ComponentId, - pub mode_node: ModeRequestHandlerOneParentMpscBounded, + pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, pub mode_req_mock: ModeRequestHandlerMock, pub num_mode_msgs_recvd: u32, @@ -684,7 +690,7 @@ impl CommonDevice { pub fn new( name: &'static str, id: ComponentId, - mode_node: ModeRequestHandlerOneParentMpscBounded, + mode_node: ModeRequestHandlerMpscBounded, ) -> Self { Self { name, @@ -804,7 +810,7 @@ pub struct AnnounceModeInfo { } pub struct AcsController { - pub mode_node: ModeRequestHandlerOneParentMpscBounded, + pub mode_node: ModeRequestHandlerMpscBounded, pub mode_and_submode: ModeAndSubmode, pub announce_mode_queue: RefCell>, pub mode_req_mock: ModeRequestHandlerMock, @@ -953,36 +959,36 @@ impl TreeTestbench { ); // Mode requestors and handlers. - let mgm_assy_node = ModeRequestorAndHandlerOneParentMpscBounded::new( + let mgm_assy_node = ModeRequestorAndHandlerMpscBounded::new( TestComponentId::MagnetometerAssembly as ComponentId, request_receiver_mgm_assy, reply_receiver_mgm_assy, ); - let mgt_dev_mgmt_node = ModeRequestorAndHandlerOneParentMpscBounded::new( + let mgt_dev_mgmt_node = ModeRequestorAndHandlerMpscBounded::new( TestComponentId::MgtDevManager as ComponentId, request_receiver_mgt_man, reply_receiver_mgt_man, ); - let acs_subsystem_node = ModeRequestorAndHandlerOneParentMpscBounded::new( + let acs_subsystem_node = ModeRequestorAndHandlerMpscBounded::new( TestComponentId::AcsSubsystem as ComponentId, request_receiver_acs_subsystem, reply_receiver_acs_subsystem, ); // Request handlers only. - let mgm_dev_node_0 = ModeRequestHandlerOneParentMpscBounded::new( + let mgm_dev_node_0 = ModeRequestHandlerMpscBounded::new( TestComponentId::MagnetometerDevice0 as ComponentId, request_receiver_mgm_dev_0, ); - let mgm_dev_node_1 = ModeRequestHandlerOneParentMpscBounded::new( + let mgm_dev_node_1 = ModeRequestHandlerMpscBounded::new( TestComponentId::MagnetometerDevice1 as ComponentId, request_receiver_mgm_dev_1, ); - let mgt_dev_node = ModeRequestHandlerOneParentMpscBounded::new( + let mgt_dev_node = ModeRequestHandlerMpscBounded::new( TestComponentId::MagnetorquerDevice as ComponentId, request_receiver_mgt_dev, ); - let acs_ctrl_node = ModeRequestHandlerOneParentMpscBounded::new( + let acs_ctrl_node = ModeRequestHandlerMpscBounded::new( TestComponentId::AcsController as ComponentId, request_receiver_acs_ctrl, ); @@ -1036,9 +1042,35 @@ impl TreeTestbench { ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0), true, )); - let sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL"); - let sequence_tbl_safe_1 = SequenceTableMapTable::new("SAFE_SEQ_1_TBL"); - let sequence_tbl_safe = SequenceTablesMapValue::new("SAFE_SEQ_TBL"); + target_table_safe.add_entry(TargetTableEntry::new_with_precise_submode( + "MGT_MAN_NML", + TestComponentId::MgtDevManager as u64, + ModeAndSubmode::new(DefaultMode::NORMAL as u32, 0), + true, + )); + let mut sequence_tbl_safe_0 = SequenceTableMapTable::new("SAFE_SEQ_0_TBL"); + sequence_tbl_safe_0.add_entry(SequenceTableEntry::new( + "SAFE_SEQ_0_MGM_A", + TestComponentId::MagnetometerAssembly as u64, + ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0), + false, + )); + sequence_tbl_safe_0.add_entry(SequenceTableEntry::new( + "SAFE_SEQ_0_MGT_MAN", + TestComponentId::MgtDevManager as u64, + ModeAndSubmode::new(DefaultMode::NORMAL as Mode, 0), + false, + )); + let mut sequence_tbl_safe_1 = SequenceTableMapTable::new("SAFE_SEQ_1_TBL"); + sequence_tbl_safe_1.add_entry(SequenceTableEntry::new( + "SAFE_SEQ_1_ACS_CTRL", + TestComponentId::AcsController as u64, + ModeAndSubmode::new(AcsMode::IDLE as Mode, 0), + false, + )); + let mut sequence_tbl_safe = SequenceTablesMapValue::new("SAFE_SEQ_TBL"); + sequence_tbl_safe.add_sequence_table(sequence_tbl_safe_0); + sequence_tbl_safe.add_sequence_table(sequence_tbl_safe_1); acs_subsystem.add_target_and_sequence_table( AcsMode::SAFE as u32, target_table_safe, @@ -1154,6 +1186,7 @@ fn announce_recursively() { tb.mgm_devs[1].run(); tb.mgt_dev.run(); } + assert_eq!(tb.subsystem.get_and_clear_num_mode_requests(), 1); let mut announces = tb .subsystem .mode_req_handler_mock @@ -1164,6 +1197,7 @@ fn announce_recursively() { assert_eq!(tb.ctrl.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(tb.ctrl.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); + assert_eq!(tb.mgm_assy.get_and_clear_num_mode_msgs(), 1); announces = tb.mgm_assy.mode_req_mock.announce_mode_calls.borrow_mut(); assert_eq!(tb.mgm_assy.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(tb.mgm_assy.mode_and_submode(), UNKNOWN_MODE); @@ -1181,6 +1215,7 @@ fn announce_recursively() { assert_eq!(tb.mgt_dev.mode_req_mock.start_transition_calls.len(), 0); assert_eq!(tb.mgt_dev.mode_and_submode(), UNKNOWN_MODE); assert_eq!(announces.len(), 1); + assert_eq!(tb.mgt_manager.get_and_clear_num_mode_requests(), 1); announces = tb .mgt_manager .mode_req_mock -- 2.43.0 From 09594e17615abd5d65986ee6c964b36f08ea1a1c Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 3 Dec 2024 17:37:17 +0100 Subject: [PATCH 7/9] continue subsystem helper --- satrs/src/subsystem.rs | 27 ++++++++++++++++++--------- satrs/tests/mode_tree.rs | 15 +++++++++++++++ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/satrs/src/subsystem.rs b/satrs/src/subsystem.rs index aecc579..fac02b6 100644 --- a/satrs/src/subsystem.rs +++ b/satrs/src/subsystem.rs @@ -21,6 +21,16 @@ pub struct SequenceExecutionHelper { current_sequence_index: Option, } +impl Default for SequenceExecutionHelper { + fn default() -> Self { + Self { + target_mode: 0, + state: SequenceExecutionHelperStates::Idle, + request_id: 0, + current_sequence_index: todo!(), + } + } +} pub trait CheckSuccessProvider { fn mode_request_requires_success_check( &mut self, @@ -37,20 +47,19 @@ pub enum SequenceHandlerResult { } impl SequenceExecutionHelper { - pub fn new( + pub fn load( + &mut self, mode: Mode, request_id: RequestId, sequence_tables: &SequenceModeTables, - ) -> Option { + ) -> Result<(), ()> { if !sequence_tables.0.contains_key(&mode) { - return None; + return Err(()); } - Some(Self { - target_mode: mode, - state: SequenceExecutionHelperStates::Idle, - request_id, - current_sequence_index: None, - }) + self.target_mode = mode; + self.request_id = request_id; + self.current_sequence_index = None; + Ok(()) } pub fn confirm_sequence_done(&mut self) { diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 00412ed..5134c47 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -13,6 +13,7 @@ use satrs::mode_tree::{ TargetTablesMapValue, }; use satrs::request::MessageMetadata; +use satrs::subsystem::SequenceExecutionHelper; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, queue::GenericTargetedMessagingError, @@ -62,8 +63,22 @@ pub struct SubsystemHelper { pub children_mode_store: ModeStoreVec, pub target_tables: TargetModeTables, pub sequence_tables: SequenceModeTables, + pub helper: SequenceExecutionHelper, } impl SubsystemHelper { + pub fn new( + children_mode_store: ModeStoreVec, + target_tables: TargetModeTables, + sequence_tables: SequenceModeTables, + ) -> Self{ + Self { + children_mode_store, + target_tables, + sequence_tables, + helper: Default::default(), + } + } + pub fn add_target_and_sequence_table( &mut self, mode: Mode, -- 2.43.0 From 8140aa74c63bc06720e354f9bc99fe9391559e46 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 3 Dec 2024 21:08:26 +0100 Subject: [PATCH 8/9] save --- satrs/src/mode_tree.rs | 43 ++++++++++++++++++++++++++-- satrs/src/subsystem.rs | 62 ++++++++++++++++++++++++++-------------- satrs/tests/mode_tree.rs | 47 ++++++++++++++++++++++++++---- 3 files changed, 123 insertions(+), 29 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 50e17ff..6156437 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -180,10 +180,30 @@ impl SequenceTableEntry { } } +#[derive(Debug, thiserror::Error)] +#[error("target {0} not in mode store")] +pub struct TargetNotInModeStoreError(pub ComponentId); + pub trait ModeStoreProvider { fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode); + + fn has_component(&self, target_id: ComponentId) -> bool; + fn get_mode(&self, target_id: ComponentId) -> Option; - fn set_mode(&mut self, target_id: ComponentId, mode: ModeAndSubmode); + + fn set_mode_for_contained_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode); + + fn set_mode( + &mut self, + target_id: ComponentId, + mode: ModeAndSubmode, + ) -> Result<(), TargetNotInModeStoreError> { + if !self.has_component(target_id) { + return Err(TargetNotInModeStoreError(target_id)); + } + self.set_mode_for_contained_component(target_id, mode); + Ok(()) + } } #[cfg(feature = "alloc")] @@ -268,6 +288,10 @@ pub mod alloc_mod { self.0.push((target_id, mode)); } + fn has_component(&self, target_id: ComponentId) -> bool { + self.0.iter().any(|(id, _)| *id == target_id) + } + fn get_mode(&self, target_id: ComponentId) -> Option { self.0.iter().find_map(|(id, mode)| { if *id == target_id { @@ -277,7 +301,11 @@ pub mod alloc_mod { }) } - fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) { + fn set_mode_for_contained_component( + &mut self, + target_id: ComponentId, + mode_to_set: ModeAndSubmode, + ) { self.0.iter_mut().for_each(|(id, mode)| { if *id == target_id { *mode = mode_to_set; @@ -290,10 +318,19 @@ pub mod alloc_mod { fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) { self.0.insert(target_id, mode); } + + fn has_component(&self, target_id: ComponentId) -> bool { + self.0.contains_key(&target_id) + } + fn get_mode(&self, target_id: ComponentId) -> Option { self.0.get(&target_id).copied() } - fn set_mode(&mut self, target_id: ComponentId, mode_to_set: ModeAndSubmode) { + fn set_mode_for_contained_component( + &mut self, + target_id: ComponentId, + mode_to_set: ModeAndSubmode, + ) { self.0.insert(target_id, mode_to_set); } } diff --git a/satrs/src/subsystem.rs b/satrs/src/subsystem.rs index fac02b6..85ded3b 100644 --- a/satrs/src/subsystem.rs +++ b/satrs/src/subsystem.rs @@ -6,31 +6,13 @@ use crate::{ ComponentId, }; -#[derive(Debug, PartialEq, Eq)] +#[derive(Debug, PartialEq, Eq, Copy, Clone)] pub enum SequenceExecutionHelperStates { Idle, AwaitingCheckSuccess, Done, } -#[derive(Debug)] -pub struct SequenceExecutionHelper { - target_mode: Mode, - state: SequenceExecutionHelperStates, - request_id: RequestId, - current_sequence_index: Option, -} - -impl Default for SequenceExecutionHelper { - fn default() -> Self { - Self { - target_mode: 0, - state: SequenceExecutionHelperStates::Idle, - request_id: 0, - current_sequence_index: todo!(), - } - } -} pub trait CheckSuccessProvider { fn mode_request_requires_success_check( &mut self, @@ -46,15 +28,38 @@ pub enum SequenceHandlerResult { AwaitingSuccessCheck, } +#[derive(Debug, thiserror::Error)] +#[error("Mode {0} does not exist")] +pub struct ModeDoesNotExistError(Mode); + +#[derive(Debug)] +pub struct SequenceExecutionHelper { + target_mode: Mode, + state: SequenceExecutionHelperStates, + request_id: RequestId, + current_sequence_index: Option, +} + +impl Default for SequenceExecutionHelper { + fn default() -> Self { + Self { + target_mode: 0, + state: SequenceExecutionHelperStates::Idle, + request_id: 0, + current_sequence_index: None, + } + } +} + impl SequenceExecutionHelper { pub fn load( &mut self, mode: Mode, request_id: RequestId, sequence_tables: &SequenceModeTables, - ) -> Result<(), ()> { + ) -> Result<(), ModeDoesNotExistError> { if !sequence_tables.0.contains_key(&mode) { - return Err(()); + return Err(ModeDoesNotExistError(mode)); } self.target_mode = mode; self.request_id = request_id; @@ -68,6 +73,21 @@ impl SequenceExecutionHelper { } } + pub fn state(&self) -> SequenceExecutionHelperStates { + self.state + } + + pub fn awaiting_check_success(&self) -> bool { + matches!( + self.state, + SequenceExecutionHelperStates::AwaitingCheckSuccess + ) + } + + pub fn current_sequence_index(&self) -> Option { + self.current_sequence_index + } + pub fn run( &mut self, table: &SequenceModeTables, diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 5134c47..6c94dca 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,19 +1,19 @@ use core::cell::Cell; use satrs::mode::{ Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, - ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded, - ModeRequestorOneChildBoundedMpsc, + ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestSender, + ModeRequestorAndHandlerMpscBounded, ModeRequestorOneChildBoundedMpsc, }; use satrs::mode_tree::{ connect_mode_nodes, ModeChild, ModeNode, ModeParent, ModeStoreProvider, SequenceTableEntry, - SequenceTableMapTable, TargetTableEntry, + SequenceTableMapTable, TargetNotInModeStoreError, TargetTableEntry, }; use satrs::mode_tree::{ ModeStoreVec, SequenceModeTables, SequenceTablesMapValue, TargetModeTables, TargetTablesMapValue, }; use satrs::request::MessageMetadata; -use satrs::subsystem::SequenceExecutionHelper; +use satrs::subsystem::{SequenceExecutionHelper, SequenceHandlerResult}; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, queue::GenericTargetedMessagingError, @@ -58,6 +58,10 @@ pub enum TestComponentId { pub type RequestSenderType = mpsc::SyncSender>; pub type ReplySenderType = mpsc::SyncSender>; +// TODO: +// +// 1. Fallback mode? +// 2. State to determine whether we are in sequence execution mode or in target keeping mode. #[derive(Default)] pub struct SubsystemHelper { pub children_mode_store: ModeStoreVec, @@ -70,7 +74,7 @@ impl SubsystemHelper { children_mode_store: ModeStoreVec, target_tables: TargetModeTables, sequence_tables: SequenceModeTables, - ) -> Self{ + ) -> Self { Self { children_mode_store, target_tables, @@ -88,6 +92,39 @@ impl SubsystemHelper { self.target_tables.0.insert(mode, target_table_val); self.sequence_tables.0.insert(mode, sequence_table_val); } + + pub fn update_child_mode( + &mut self, + child: ComponentId, + mode: ModeAndSubmode, + ) -> Result<(), TargetNotInModeStoreError> { + self.children_mode_store.set_mode(child, mode) + } + + pub fn insert_mode_reply(&mut self, reply: &ModeReply) { + // 1. Update child mode store (also, do we really need one?) + // 2. If a sequence is active, check whether this completes the sequence. How do we best + // do this? We would have to remember which IDs need a mode confirmation. We could + // extend the mode store for this. + // 3. If no sequence is active and we are in target mode, we need to check whether the + // target mode table is violated. If it is, we need to command the fallback mode. + } + + pub fn run( + &mut self, + req_sender: &impl ModeRequestSender, + ) -> Result { + //if self.helper.awaiting_check_success() { + //self.check_current_sequence_against_mode_store(); + //} + self.helper.run(&self.sequence_tables, req_sender) + } + + //pub fn check_current_sequence_against_mode_store(&self) { + // TODO: Check whether current sequence requires success checks and if some are required, + // check mode store content against the sequence target mode. + + //} } #[derive(Default, Debug)] -- 2.43.0 From 0dacad0bbc84577ad1145bbad43173325524c233 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 4 Dec 2024 16:59:09 +0100 Subject: [PATCH 9/9] continue mode tree helper --- satrs/src/mode.rs | 2 + satrs/tests/mode_tree.rs | 93 ++++++++++++++++++++++++++++++++-------- 2 files changed, 77 insertions(+), 18 deletions(-) diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index 471b36d..a18a19d 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -129,6 +129,8 @@ pub struct TargetedModeRequest { #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub enum ModeReply { + /// Mode information. Can be used to notify other components of changed modes. + ModeInfo(ModeAndSubmode), /// Reply to a mode request to confirm the commanded mode was reached. ModeReply(ModeAndSubmode), // Can not reach the commanded mode. Contains a reason as a [ResultU16]. diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 6c94dca..27d87c0 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -58,24 +58,51 @@ pub enum TestComponentId { pub type RequestSenderType = mpsc::SyncSender>; pub type ReplySenderType = mpsc::SyncSender>; +#[derive(Debug)] +pub enum ModeTreeHelperState { + Idle, + TargetKeeping = 1, + SequenceCommanding = 2, +} + +#[derive(Debug)] +pub enum ModeTreeHelperResult { + Idle, + TargetKeeping, + SequenceCommanding(SequenceHandlerResult), +} + +impl From for ModeTreeHelperResult { + fn from(value: SequenceHandlerResult) -> Self { + Self::SequenceCommanding(value) + } +} + +#[derive(Debug, thiserror::Error)] +pub enum ModeTreeHelperError { + #[error("generic targeted messaging error: {0}")] + Message(#[from] GenericTargetedMessagingError), +} // TODO: // -// 1. Fallback mode? +// 1. Fallback mode? Needs to be a part of the target mode table.. // 2. State to determine whether we are in sequence execution mode or in target keeping mode. -#[derive(Default)] -pub struct SubsystemHelper { +pub struct ModeTreeCommandingHelper { + pub state: ModeTreeHelperState, pub children_mode_store: ModeStoreVec, pub target_tables: TargetModeTables, pub sequence_tables: SequenceModeTables, pub helper: SequenceExecutionHelper, } -impl SubsystemHelper { + +impl ModeTreeCommandingHelper { pub fn new( children_mode_store: ModeStoreVec, target_tables: TargetModeTables, sequence_tables: SequenceModeTables, ) -> Self { Self { + state: ModeTreeHelperState::Idle, children_mode_store, target_tables, sequence_tables, @@ -101,23 +128,53 @@ impl SubsystemHelper { self.children_mode_store.set_mode(child, mode) } - pub fn insert_mode_reply(&mut self, reply: &ModeReply) { - // 1. Update child mode store (also, do we really need one?) - // 2. If a sequence is active, check whether this completes the sequence. How do we best - // do this? We would have to remember which IDs need a mode confirmation. We could - // extend the mode store for this. - // 3. If no sequence is active and we are in target mode, we need to check whether the - // target mode table is violated. If it is, we need to command the fallback mode. + pub fn handle_mode_reply(&mut self, reply: &GenericMessage) { + let mut update_mode_store = |target_id, mode_and_submode| { + if !self.children_mode_store.has_component(target_id) { + return; + } + self.children_mode_store + .set_mode_for_contained_component(target_id, mode_and_submode); + // TODO: + // 1. If we are in IDLE Mode, we are done. + // 2. If we are in sequencing mode, check whether this completes the sequence. How do + // we best do this? We would have to remember which IDs need a mode confirmation. + // We could extend the mode store for this. + // 3. If we are in target keeping mode, we have to check whether the target keeping was + // violated. + }; + match reply.message { + ModeReply::ModeInfo(mode_and_submode) => { + update_mode_store(reply.sender_id(), mode_and_submode); + } + ModeReply::ModeReply(mode_and_submode) => { + update_mode_store(reply.sender_id(), mode_and_submode); + } + ModeReply::CantReachMode(_) => (), + ModeReply::WrongMode { reached, .. } => { + update_mode_store(reply.sender_id(), reached); + } + }; } - pub fn run( + pub fn state_machine( &mut self, + opt_reply: Option<&GenericMessage>, req_sender: &impl ModeRequestSender, - ) -> Result { - //if self.helper.awaiting_check_success() { - //self.check_current_sequence_against_mode_store(); - //} - self.helper.run(&self.sequence_tables, req_sender) + ) -> Result { + if let Some(reply) = opt_reply { + self.handle_mode_reply(reply); + } + match self.state { + ModeTreeHelperState::Idle => todo!(), + ModeTreeHelperState::TargetKeeping => { + // TODO: Verify children modes against target table where applicable. + Ok(ModeTreeHelperResult::TargetKeeping) + } + ModeTreeHelperState::SequenceCommanding => { + Ok(self.helper.run(&self.sequence_tables, req_sender)?.into()) + } + } } //pub fn check_current_sequence_against_mode_store(&self) { @@ -247,7 +304,7 @@ struct AcsSubsystem { pub mode_requestor_info: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, - pub subsystem_helper: SubsystemHelper, + pub subsystem_helper: ModeTreeCommandingHelper, pub mode_req_handler_mock: ModeRequestHandlerMock, pub mode_req_recvd: u32, } -- 2.43.0