diff --git a/satrs/src/dev_mgmt.rs b/satrs/src/dev_mgmt.rs index 1ddefd5..2bbffa9 100644 --- a/satrs/src/dev_mgmt.rs +++ b/satrs/src/dev_mgmt.rs @@ -3,17 +3,22 @@ use crate::{ mode_tree::{ModeStoreProvider, ModeStoreVec}, queue::GenericTargetedMessagingError, request::{GenericMessage, RequestId}, - subsystem::ModeTreeHelperState, ComponentId, }; use core::fmt::Debug; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub struct ActiveModeCommandContext { + pub target_mode: ModeAndSubmode, + pub active_request_id: RequestId, +} + #[derive(Debug, Default)] pub enum DevManagerHelperResult { #[default] Idle, Busy, - ModeCommandingDone, + ModeCommandingDone(ActiveModeCommandContext), } #[derive(Debug)] @@ -24,7 +29,8 @@ pub enum DevManagerHelperError { pub trait DevManagerUserHook: Debug { fn send_mode_cmds_to_children( &self, - parent_mode: ModeAndSubmode, + request_id: RequestId, + commanded_parent_mode: ModeAndSubmode, forced: bool, children_mode_store: &mut ModeStoreVec, mode_req_sender: &impl ModeRequestSender, @@ -37,6 +43,7 @@ pub struct TransparentDevManagerHook {} impl DevManagerUserHook for TransparentDevManagerHook { fn send_mode_cmds_to_children( &self, + request_id: RequestId, commanded_parent_mode: ModeAndSubmode, forced: bool, children_mode_store: &mut ModeStoreVec, @@ -44,7 +51,7 @@ impl DevManagerUserHook for TransparentDevManagerHook { ) -> Result<(), GenericTargetedMessagingError> { for child in children_mode_store { mode_req_sender.send_mode_request( - 0, + request_id, child.id(), ModeRequest::SetMode { mode_and_submode: commanded_parent_mode, @@ -57,31 +64,41 @@ impl DevManagerUserHook for TransparentDevManagerHook { } } +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub enum DevManagerCommandingState { + #[default] + Idle, + AwaitingReplies(ActiveModeCommandContext), +} + +impl DevManagerCommandingState { + fn new_active_cmd(mode_and_submode: ModeAndSubmode, active_request_id: RequestId) -> Self { + DevManagerCommandingState::AwaitingReplies(ActiveModeCommandContext { + target_mode: mode_and_submode, + active_request_id, + }) + } +} + /// A generic helper for manager components which manage child components in a mode tree. /// /// Mode commands are usually forwarded to all children components transparently. /// For example, this could be used in an Assembly component which manages multiple redundant /// child components. It can also be used inside a manager component which only manages one device. -#[derive(Debug)] +#[derive(Debug, Default)] pub struct DevManagerCommandingHelper { /// The IDs, modes and reply awaition status of all children are tracked in this data /// structure. pub children_mode_store: ModeStoreVec, pub user_hook: UserHook, - /// Target mode used for mode commanding. - target_mode: Option, - /// Request ID of active mode commanding request. - active_request_id: Option, - state: ModeTreeHelperState, + pub state: DevManagerCommandingState, } impl DevManagerCommandingHelper { pub fn new(user_hook: UserHook) -> Self { Self { children_mode_store: Default::default(), - target_mode: None, user_hook, - active_request_id: None, state: Default::default(), } } @@ -94,7 +111,7 @@ impl DevManagerCommandingHelper { forced: bool, mode_req_sender: &impl ModeRequestSender, ) -> Result<(), GenericTargetedMessagingError> { - self.target_mode = Some(mode_and_submode); + self.state = DevManagerCommandingState::new_active_cmd(mode_and_submode, request_id); mode_req_sender.send_mode_request( request_id, target_id, @@ -103,8 +120,6 @@ impl DevManagerCommandingHelper { forced, }, )?; - self.active_request_id = Some(request_id); - self.state = ModeTreeHelperState::ModeCommanding; Ok(()) } @@ -115,27 +130,25 @@ impl DevManagerCommandingHelper { forced: bool, mode_req_sender: &impl ModeRequestSender, ) -> Result<(), GenericTargetedMessagingError> { - self.target_mode = Some(mode_and_submode); + self.state = DevManagerCommandingState::new_active_cmd(mode_and_submode, request_id); self.user_hook.send_mode_cmds_to_children( + request_id, mode_and_submode, forced, &mut self.children_mode_store, mode_req_sender, )?; - self.active_request_id = Some(request_id); - self.state = ModeTreeHelperState::ModeCommanding; Ok(()) } pub fn target_mode(&self) -> Option { - self.target_mode + match self.state { + DevManagerCommandingState::Idle => None, + DevManagerCommandingState::AwaitingReplies(context) => Some(context.target_mode), + } } - pub fn active_request_id(&self) -> Option { - self.active_request_id - } - - pub fn state(&self) -> ModeTreeHelperState { + pub fn state(&self) -> DevManagerCommandingState { self.state } @@ -170,22 +183,16 @@ impl DevManagerCommandingHelper { children_in_target_mode } - /// Helper method which counts the number of children which have the mode of the assembly - /// itself. - /// - /// This is useful for device managers where the child or the children devices should have the - /// same mode as the device manager. - pub fn count_number_of_children_with_target_mode(&self) -> Option { - Some(self.count_number_of_children_with_mode(self.target_mode?)) - } - pub fn handle_mode_reply( &mut self, mode_reply: &GenericMessage, ) -> Result { - if self.target_mode().is_none() || self.active_request_id().is_none() { - return Ok(DevManagerHelperResult::Idle); - } + let context = match self.state { + DevManagerCommandingState::Idle => return Ok(DevManagerHelperResult::Idle), + DevManagerCommandingState::AwaitingReplies(active_mode_command_context) => { + Some(active_mode_command_context) + } + }; if !self .children_mode_store .has_component(mode_reply.sender_id()) @@ -197,10 +204,7 @@ impl DevManagerCommandingHelper { // belonging to older requests do not interfere with the completion handling of // the mode commanding. This is important for forced mode commands. let mut handle_awaition = false; - if self.state == ModeTreeHelperState::ModeCommanding - && self.active_request_id.is_some() - && mode_reply.request_id() == self.active_request_id.unwrap() - { + if let DevManagerCommandingState::AwaitingReplies { .. } = self.state { handle_awaition = true; } let still_awating_replies = self.children_mode_store.mode_reply_handler( @@ -210,13 +214,9 @@ impl DevManagerCommandingHelper { ); // It is okay to unwrap: If awaition should be handled, the returned value should // always be some valid value. - if self.state == ModeTreeHelperState::ModeCommanding - && handle_awaition - && !still_awating_replies.unwrap() - { - self.state = ModeTreeHelperState::TargetKeeping; - self.active_request_id = None; - return Ok(DevManagerHelperResult::ModeCommandingDone); + if handle_awaition && !still_awating_replies.unwrap() { + self.state = DevManagerCommandingState::Idle; + return Ok(DevManagerHelperResult::ModeCommandingDone(context.unwrap())); } Ok(DevManagerHelperResult::Busy) }; @@ -247,9 +247,7 @@ mod tests { #[test] fn test_basic() { let assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default()); - assert_eq!(assy_helper.state(), ModeTreeHelperState::Idle); - assert!(assy_helper.active_request_id().is_none()); - assert!(assy_helper.target_mode().is_none()); + assert_eq!(assy_helper.state(), DevManagerCommandingState::Idle); } #[test] diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index bbfe9e9..735ddf2 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -552,17 +552,10 @@ impl MgmAssembly { self.mode_reply_mock.handle_mode_reply(&reply_and_id); match self.commanding_helper.handle_mode_reply(&reply_and_id) { Ok(result) => { - match result { - DevManagerHelperResult::Idle => todo!(), - DevManagerHelperResult::Busy => todo!(), - DevManagerHelperResult::ModeCommandingDone => { - if self.commanding_helper.target_mode().is_some() { - // Complete the mode command. - self.mode_and_submode = - self.commanding_helper.target_mode().unwrap(); - self.handle_mode_reached(self.mode_requestor_info)?; - } - } + if let DevManagerHelperResult::ModeCommandingDone(context) = result { + // Complete the mode command. + self.mode_and_submode = context.target_mode; + self.handle_mode_reached(self.mode_requestor_info)?; } } Err(err) => match err { @@ -742,12 +735,10 @@ impl DeviceManager { match result { DevManagerHelperResult::Idle => todo!(), DevManagerHelperResult::Busy => todo!(), - DevManagerHelperResult::ModeCommandingDone => { - if self.commanding_helper.target_mode().is_some() { - // Complete the mode command. - self.handle_mode_reached(self.mode_requestor_info)?; - self.mode_and_submode = self.commanding_helper.target_mode().unwrap(); - } + DevManagerHelperResult::ModeCommandingDone(context) => { + // Complete the mode command. + self.handle_mode_reached(self.mode_requestor_info)?; + self.mode_and_submode = context.target_mode; } } } @@ -932,6 +923,9 @@ impl ModeRequestHandler for CommonDevice { mode_and_submode: ModeAndSubmode, forced: bool, ) -> Result<(), ModeError> { + if self.id() == TestComponentId::MagnetorquerDevice as u64 { + println!("test"); + } self.mode_and_submode = mode_and_submode; self.handle_mode_reached(Some(requestor))?; self.mode_req_mock