add health module
This commit is contained in:
parent
9325707fe8
commit
f2648fb3b6
@ -6,25 +6,68 @@ use crate::{
|
|||||||
subsystem::ModeTreeHelperState,
|
subsystem::ModeTreeHelperState,
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
use core::fmt::Debug;
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub enum AssemblyHelperResult {
|
pub enum DevManagerHelperResult {
|
||||||
#[default]
|
#[default]
|
||||||
Idle,
|
Idle,
|
||||||
TargetKeepingViolation(ComponentId),
|
Busy,
|
||||||
ModeCommandingDone,
|
ModeCommandingDone,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum DevManagerHelperError {
|
||||||
|
ChildNotInStore,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait DevManagerUserHook: Debug {
|
||||||
|
fn send_mode_cmds_to_children(
|
||||||
|
&self,
|
||||||
|
parent_mode: ModeAndSubmode,
|
||||||
|
forced: bool,
|
||||||
|
children_mode_store: &mut ModeStoreVec,
|
||||||
|
mode_req_sender: &impl ModeRequestSender,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct TransparentDevManagerHook {}
|
||||||
|
|
||||||
|
impl DevManagerUserHook for TransparentDevManagerHook {
|
||||||
|
fn send_mode_cmds_to_children(
|
||||||
|
&self,
|
||||||
|
commanded_parent_mode: ModeAndSubmode,
|
||||||
|
forced: bool,
|
||||||
|
children_mode_store: &mut ModeStoreVec,
|
||||||
|
mode_req_sender: &impl ModeRequestSender,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
|
for child in children_mode_store {
|
||||||
|
mode_req_sender.send_mode_request(
|
||||||
|
0,
|
||||||
|
child.id(),
|
||||||
|
ModeRequest::SetMode {
|
||||||
|
mode_and_submode: commanded_parent_mode,
|
||||||
|
forced,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
child.awaiting_reply = true;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A generic helper for manager components which manage child components in a mode tree.
|
/// A generic helper for manager components which manage child components in a mode tree.
|
||||||
///
|
///
|
||||||
/// Mode commands are usually forwarded to all children components transparently.
|
/// Mode commands are usually forwarded to all children components transparently.
|
||||||
/// For example, this could be used in an Assembly component which manages multiple redundant
|
/// 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.
|
/// child components. It can also be used inside a manager component which only manages one device.
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug)]
|
||||||
pub struct AssemblyCommandingHelper {
|
pub struct DevManagerCommandingHelper<UserHook: DevManagerUserHook> {
|
||||||
/// The IDs, modes and reply awaition status of all children are tracked in this data
|
/// The IDs, modes and reply awaition status of all children are tracked in this data
|
||||||
/// structure.
|
/// structure.
|
||||||
pub children_mode_store: ModeStoreVec,
|
pub children_mode_store: ModeStoreVec,
|
||||||
|
pub user_hook: UserHook,
|
||||||
/// Target mode used for mode commanding.
|
/// Target mode used for mode commanding.
|
||||||
target_mode: Option<ModeAndSubmode>,
|
target_mode: Option<ModeAndSubmode>,
|
||||||
/// Request ID of active mode commanding request.
|
/// Request ID of active mode commanding request.
|
||||||
@ -32,10 +75,40 @@ pub struct AssemblyCommandingHelper {
|
|||||||
state: ModeTreeHelperState,
|
state: ModeTreeHelperState,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type DevManagerCommandingHelper = AssemblyCommandingHelper;
|
impl<UserHook: DevManagerUserHook> DevManagerCommandingHelper<UserHook> {
|
||||||
|
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(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AssemblyCommandingHelper {
|
pub fn send_mode_cmd_to_one_child(
|
||||||
pub fn send_mode_cmd_to_all_children_with_reply_awaition(
|
&mut self,
|
||||||
|
request_id: RequestId,
|
||||||
|
target_id: ComponentId,
|
||||||
|
mode_and_submode: ModeAndSubmode,
|
||||||
|
forced: bool,
|
||||||
|
mode_req_sender: &impl ModeRequestSender,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
|
self.target_mode = Some(mode_and_submode);
|
||||||
|
mode_req_sender.send_mode_request(
|
||||||
|
request_id,
|
||||||
|
target_id,
|
||||||
|
ModeRequest::SetMode {
|
||||||
|
mode_and_submode,
|
||||||
|
forced,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
self.active_request_id = Some(request_id);
|
||||||
|
self.state = ModeTreeHelperState::ModeCommanding;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_mode_cmd_to_all_children(
|
||||||
&mut self,
|
&mut self,
|
||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
@ -43,17 +116,12 @@ impl AssemblyCommandingHelper {
|
|||||||
mode_req_sender: &impl ModeRequestSender,
|
mode_req_sender: &impl ModeRequestSender,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.target_mode = Some(mode_and_submode);
|
self.target_mode = Some(mode_and_submode);
|
||||||
for child in self.children_mode_store.0.iter_mut() {
|
self.user_hook.send_mode_cmds_to_children(
|
||||||
mode_req_sender.send_mode_request(
|
mode_and_submode,
|
||||||
request_id,
|
forced,
|
||||||
child.id(),
|
&mut self.children_mode_store,
|
||||||
ModeRequest::SetMode {
|
mode_req_sender,
|
||||||
mode_and_submode,
|
)?;
|
||||||
forced,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
child.awaiting_reply = true;
|
|
||||||
}
|
|
||||||
self.active_request_id = Some(request_id);
|
self.active_request_id = Some(request_id);
|
||||||
self.state = ModeTreeHelperState::ModeCommanding;
|
self.state = ModeTreeHelperState::ModeCommanding;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -91,27 +159,38 @@ impl AssemblyCommandingHelper {
|
|||||||
self.children_mode_store.add_component(target_id, mode);
|
self.children_mode_store.add_component(target_id, mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn count_number_of_children_with_target_mode(&self) -> Option<usize> {
|
/// Helper method which counts the number of children which have a certain mode.
|
||||||
self.target_mode?;
|
pub fn count_number_of_children_with_mode(&self, mode_and_submode: ModeAndSubmode) -> usize {
|
||||||
let target_mode = self.target_mode.unwrap();
|
|
||||||
let mut children_in_target_mode = 0;
|
let mut children_in_target_mode = 0;
|
||||||
for child in self.children_mode_store.0.iter() {
|
for child in &self.children_mode_store {
|
||||||
if child.mode_and_submode() == target_mode {
|
if child.mode_and_submode() == mode_and_submode {
|
||||||
children_in_target_mode += 1;
|
children_in_target_mode += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(children_in_target_mode)
|
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<usize> {
|
||||||
|
Some(self.count_number_of_children_with_mode(self.target_mode?))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_mode_reply(
|
pub fn handle_mode_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
mode_reply: &GenericMessage<ModeReply>,
|
mode_reply: &GenericMessage<ModeReply>,
|
||||||
) -> AssemblyHelperResult {
|
) -> Result<DevManagerHelperResult, DevManagerHelperError> {
|
||||||
|
if self.target_mode().is_none() || self.active_request_id().is_none() {
|
||||||
|
return Ok(DevManagerHelperResult::Idle);
|
||||||
|
}
|
||||||
if !self
|
if !self
|
||||||
.children_mode_store
|
.children_mode_store
|
||||||
.has_component(mode_reply.sender_id())
|
.has_component(mode_reply.sender_id())
|
||||||
{
|
{
|
||||||
return AssemblyHelperResult::Idle;
|
return Err(DevManagerHelperError::ChildNotInStore);
|
||||||
}
|
}
|
||||||
let mut generic_mode_reply_handler = |mode_and_submode: Option<ModeAndSubmode>| {
|
let mut generic_mode_reply_handler = |mode_and_submode: Option<ModeAndSubmode>| {
|
||||||
// Tying the reply awaition to the request ID ensures that something like replies
|
// Tying the reply awaition to the request ID ensures that something like replies
|
||||||
@ -129,13 +208,6 @@ impl AssemblyCommandingHelper {
|
|||||||
mode_and_submode,
|
mode_and_submode,
|
||||||
handle_awaition,
|
handle_awaition,
|
||||||
);
|
);
|
||||||
if self.state == ModeTreeHelperState::TargetKeeping
|
|
||||||
&& mode_and_submode.is_some()
|
|
||||||
&& self.target_mode.is_some()
|
|
||||||
&& mode_and_submode.unwrap() != self.target_mode.unwrap()
|
|
||||||
{
|
|
||||||
return AssemblyHelperResult::TargetKeepingViolation(mode_reply.sender_id());
|
|
||||||
}
|
|
||||||
// It is okay to unwrap: If awaition should be handled, the returned value should
|
// It is okay to unwrap: If awaition should be handled, the returned value should
|
||||||
// always be some valid value.
|
// always be some valid value.
|
||||||
if self.state == ModeTreeHelperState::ModeCommanding
|
if self.state == ModeTreeHelperState::ModeCommanding
|
||||||
@ -144,9 +216,9 @@ impl AssemblyCommandingHelper {
|
|||||||
{
|
{
|
||||||
self.state = ModeTreeHelperState::TargetKeeping;
|
self.state = ModeTreeHelperState::TargetKeeping;
|
||||||
self.active_request_id = None;
|
self.active_request_id = None;
|
||||||
return AssemblyHelperResult::ModeCommandingDone;
|
return Ok(DevManagerHelperResult::ModeCommandingDone);
|
||||||
}
|
}
|
||||||
AssemblyHelperResult::Idle
|
Ok(DevManagerHelperResult::Busy)
|
||||||
};
|
};
|
||||||
match mode_reply.message {
|
match mode_reply.message {
|
||||||
ModeReply::ModeInfo(mode_and_submode) | ModeReply::ModeReply(mode_and_submode) => {
|
ModeReply::ModeInfo(mode_and_submode) | ModeReply::ModeReply(mode_and_submode) => {
|
||||||
@ -174,7 +246,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let assy_helper = AssemblyCommandingHelper::default();
|
let assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
assert_eq!(assy_helper.state(), ModeTreeHelperState::Idle);
|
assert_eq!(assy_helper.state(), ModeTreeHelperState::Idle);
|
||||||
assert!(assy_helper.active_request_id().is_none());
|
assert!(assy_helper.active_request_id().is_none());
|
||||||
assert!(assy_helper.target_mode().is_none());
|
assert!(assy_helper.target_mode().is_none());
|
||||||
@ -182,7 +254,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mode_announce() {
|
fn test_mode_announce() {
|
||||||
let mut assy_helper = AssemblyCommandingHelper::default();
|
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
||||||
@ -202,7 +274,7 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mode_announce_recursive() {
|
fn test_mode_announce_recursive() {
|
||||||
let mut assy_helper = AssemblyCommandingHelper::default();
|
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id1 as u64, UNKNOWN_MODE);
|
||||||
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
assy_helper.add_mode_child(ExampleId::Id2 as u64, UNKNOWN_MODE);
|
||||||
@ -221,10 +293,9 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mode_commanding() {
|
fn test_mode_commanding_one_child() {
|
||||||
let mut assy_helper = AssemblyCommandingHelper::default();
|
let mut assy_helper = DevManagerCommandingHelper::new(TransparentDevManagerHook::default());
|
||||||
let mode_req_sender = ModeReqSenderMock::default();
|
let mode_req_sender = ModeReqSenderMock::default();
|
||||||
assy_helper.send_mode_cmd_to_all_children_with_reply_awaition(1, , forced, mode_req_sender)
|
//assy_helper.send_mode_cmd_to_all_children_with_reply_awaition(1, , forced, mode_req_sender)
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
39
satrs/src/health.rs
Normal file
39
satrs/src/health.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use crate::ComponentId;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum HealthState {
|
||||||
|
Healthy = 1,
|
||||||
|
Faulty = 2,
|
||||||
|
PermanentFaulty = 3,
|
||||||
|
ExternalControl = 4,
|
||||||
|
NeedsRecovery = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait HealthTableProvider {
|
||||||
|
fn health(&self, id: ComponentId) -> Option<HealthState>;
|
||||||
|
fn set_health(&mut self, id: ComponentId, health: HealthState);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct HealthTableMapSync(
|
||||||
|
std::sync::Arc<std::sync::Mutex<hashbrown::HashMap<ComponentId, HealthState>>>,
|
||||||
|
);
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl HealthTableMapSync {
|
||||||
|
pub fn new(health_table: hashbrown::HashMap<ComponentId, HealthState>) -> Self {
|
||||||
|
Self(std::sync::Arc::new(std::sync::Mutex::new(health_table)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
impl HealthTableProvider for HealthTableMapSync {
|
||||||
|
fn health(&self, id: ComponentId) -> Option<HealthState> {
|
||||||
|
self.0.lock().unwrap().get(&id).copied()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_health(&mut self, id: ComponentId, health: HealthState) {
|
||||||
|
self.0.lock().unwrap().insert(id, health);
|
||||||
|
}
|
||||||
|
}
|
@ -31,6 +31,7 @@ pub mod events;
|
|||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod executable;
|
pub mod executable;
|
||||||
pub mod hal;
|
pub mod hal;
|
||||||
|
pub mod health;
|
||||||
pub mod hk;
|
pub mod hk;
|
||||||
pub mod mode;
|
pub mod mode;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
|
@ -360,10 +360,37 @@ pub mod alloc_mod {
|
|||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ModeStoreVec(pub alloc::vec::Vec<ModeStoreValue>);
|
pub struct ModeStoreVec(pub alloc::vec::Vec<ModeStoreValue>);
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a ModeStoreVec {
|
||||||
|
type Item = &'a ModeStoreValue;
|
||||||
|
type IntoIter = std::slice::Iter<'a, ModeStoreValue>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a mut ModeStoreVec {
|
||||||
|
type Item = &'a mut ModeStoreValue;
|
||||||
|
type IntoIter = std::slice::IterMut<'a, ModeStoreValue>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter_mut()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Mode store which tracks the mode information inside a [hashbrown::HashMap]
|
/// Mode store which tracks the mode information inside a [hashbrown::HashMap]
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeStoreValue>);
|
pub struct ModeStoreMap(pub hashbrown::HashMap<ComponentId, ModeStoreValue>);
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a ModeStoreMap {
|
||||||
|
type Item = (&'a ComponentId, &'a ModeStoreValue);
|
||||||
|
type IntoIter = hashbrown::hash_map::Iter<'a, ComponentId, ModeStoreValue>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
self.0.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl ModeStoreProvider for ModeStoreVec {
|
impl ModeStoreProvider for ModeStoreVec {
|
||||||
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
|
fn add_component(&mut self, target_id: ComponentId, mode: ModeAndSubmode) {
|
||||||
self.0.push(ModeStoreValue::new(target_id, mode));
|
self.0.push(ModeStoreValue::new(target_id, mode));
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
|
health::{HealthState, HealthTableProvider},
|
||||||
mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, ModeRequestSender, UNKNOWN_MODE_VAL},
|
mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, ModeRequestSender, UNKNOWN_MODE_VAL},
|
||||||
mode_tree::{
|
mode_tree::{
|
||||||
ModeStoreProvider, ModeStoreVec, SequenceModeTables, SequenceTableMapTable,
|
ModeStoreProvider, ModeStoreVec, SequenceModeTables, SequenceTableMapTable,
|
||||||
@ -70,6 +71,20 @@ impl Default for SequenceExecutionHelper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait IsChildCommandable {
|
||||||
|
fn is_commandable(&self, id: ComponentId) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> IsChildCommandable for T
|
||||||
|
where
|
||||||
|
T: HealthTableProvider,
|
||||||
|
{
|
||||||
|
fn is_commandable(&self, id: ComponentId) -> bool {
|
||||||
|
self.health(id)
|
||||||
|
.is_some_and(|h| h != HealthState::ExternalControl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl SequenceExecutionHelper {
|
impl SequenceExecutionHelper {
|
||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Default::default()
|
Default::default()
|
||||||
@ -127,6 +142,7 @@ impl SequenceExecutionHelper {
|
|||||||
table: &SequenceModeTables,
|
table: &SequenceModeTables,
|
||||||
sender: &impl ModeRequestSender,
|
sender: &impl ModeRequestSender,
|
||||||
children_mode_store: &mut ModeStoreVec,
|
children_mode_store: &mut ModeStoreVec,
|
||||||
|
is_commandable: &impl IsChildCommandable,
|
||||||
) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
||||||
if self.state == SequenceExecutionHelperState::Idle {
|
if self.state == SequenceExecutionHelperState::Idle {
|
||||||
return Ok(ModeCommandingResult::Done);
|
return Ok(ModeCommandingResult::Done);
|
||||||
@ -146,6 +162,7 @@ impl SequenceExecutionHelper {
|
|||||||
idx,
|
idx,
|
||||||
sender,
|
sender,
|
||||||
children_mode_store,
|
children_mode_store,
|
||||||
|
is_commandable,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
@ -161,6 +178,7 @@ impl SequenceExecutionHelper {
|
|||||||
0,
|
0,
|
||||||
sender,
|
sender,
|
||||||
children_mode_store,
|
children_mode_store,
|
||||||
|
is_commandable,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,6 +236,7 @@ impl SequenceExecutionHelper {
|
|||||||
sequence_idx: usize,
|
sequence_idx: usize,
|
||||||
sender: &impl ModeRequestSender,
|
sender: &impl ModeRequestSender,
|
||||||
mode_store_vec: &mut ModeStoreVec,
|
mode_store_vec: &mut ModeStoreVec,
|
||||||
|
is_commandable: &impl IsChildCommandable,
|
||||||
) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
||||||
if self.state() == SequenceExecutionHelperState::Idle || self.request_id.is_none() {
|
if self.state() == SequenceExecutionHelperState::Idle || self.request_id.is_none() {
|
||||||
return Ok(ModeCommandingResult::Done);
|
return Ok(ModeCommandingResult::Done);
|
||||||
@ -227,6 +246,7 @@ impl SequenceExecutionHelper {
|
|||||||
&seq_table_value.entries[sequence_idx],
|
&seq_table_value.entries[sequence_idx],
|
||||||
sender,
|
sender,
|
||||||
mode_store_vec,
|
mode_store_vec,
|
||||||
|
is_commandable,
|
||||||
)? {
|
)? {
|
||||||
self.state = SequenceExecutionHelperState::AwaitingSuccessCheck;
|
self.state = SequenceExecutionHelperState::AwaitingSuccessCheck;
|
||||||
Ok(ModeCommandingResult::AwaitingSuccessCheck)
|
Ok(ModeCommandingResult::AwaitingSuccessCheck)
|
||||||
@ -255,9 +275,13 @@ impl SequenceExecutionHelper {
|
|||||||
map_table: &SequenceTableMapTable,
|
map_table: &SequenceTableMapTable,
|
||||||
sender: &impl ModeRequestSender,
|
sender: &impl ModeRequestSender,
|
||||||
children_mode_store: &mut ModeStoreVec,
|
children_mode_store: &mut ModeStoreVec,
|
||||||
|
commandable: &impl IsChildCommandable,
|
||||||
) -> Result<bool, GenericTargetedMessagingError> {
|
) -> Result<bool, GenericTargetedMessagingError> {
|
||||||
let mut some_succes_check_required = false;
|
let mut some_succes_check_required = false;
|
||||||
for entry in &map_table.entries {
|
for entry in &map_table.entries {
|
||||||
|
if !commandable.is_commandable(entry.common.target_id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
sender.send_mode_request(
|
sender.send_mode_request(
|
||||||
request_id,
|
request_id,
|
||||||
entry.common.target_id,
|
entry.common.target_id,
|
||||||
@ -485,6 +509,7 @@ impl SubsystemCommandingHelper {
|
|||||||
&mut self,
|
&mut self,
|
||||||
opt_reply: Option<GenericMessage<ModeReply>>,
|
opt_reply: Option<GenericMessage<ModeReply>>,
|
||||||
req_sender: &impl ModeRequestSender,
|
req_sender: &impl ModeRequestSender,
|
||||||
|
is_commandable: &impl IsChildCommandable,
|
||||||
) -> Result<SubsystemHelperResult, ModeTreeHelperError> {
|
) -> Result<SubsystemHelperResult, ModeTreeHelperError> {
|
||||||
if let Some(reply) = opt_reply {
|
if let Some(reply) = opt_reply {
|
||||||
if self.handle_mode_reply(&reply)? {
|
if self.handle_mode_reply(&reply)? {
|
||||||
@ -513,6 +538,7 @@ impl SubsystemCommandingHelper {
|
|||||||
&self.sequence_tables,
|
&self.sequence_tables,
|
||||||
req_sender,
|
req_sender,
|
||||||
&mut self.children_mode_store,
|
&mut self.children_mode_store,
|
||||||
|
is_commandable,
|
||||||
)?;
|
)?;
|
||||||
match result {
|
match result {
|
||||||
ModeCommandingResult::Done => {
|
ModeCommandingResult::Done => {
|
||||||
@ -657,7 +683,8 @@ mod tests {
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
mode::{
|
mode::{
|
||||||
tests::{ModeReqSenderMock, ModeReqWrapper}, Mode, ModeAndSubmode, ModeReply, ModeRequest, UNKNOWN_MODE,
|
tests::{ModeReqSenderMock, ModeReqWrapper},
|
||||||
|
Mode, ModeAndSubmode, ModeReply, ModeRequest, UNKNOWN_MODE,
|
||||||
},
|
},
|
||||||
mode_tree::{
|
mode_tree::{
|
||||||
ModeStoreProvider, ModeStoreVec, SequenceModeTables, SequenceTableEntry,
|
ModeStoreProvider, ModeStoreVec, SequenceModeTables, SequenceTableEntry,
|
||||||
@ -683,11 +710,23 @@ mod tests {
|
|||||||
Mode2 = 3,
|
Mode2 = 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
pub struct IsCommandableMock {
|
||||||
|
pub commandable_map: std::collections::HashMap<ComponentId, bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IsChildCommandable for IsCommandableMock {
|
||||||
|
fn is_commandable(&self, id: ComponentId) -> bool {
|
||||||
|
self.commandable_map.get(&id).copied().unwrap_or(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct SequenceExecutorTestbench {
|
pub struct SequenceExecutorTestbench {
|
||||||
pub sender: ModeReqSenderMock,
|
pub sender: ModeReqSenderMock,
|
||||||
pub mode_store: ModeStoreVec,
|
pub mode_store: ModeStoreVec,
|
||||||
pub seq_tables: SequenceModeTables,
|
pub seq_tables: SequenceModeTables,
|
||||||
pub execution_helper: SequenceExecutionHelper,
|
pub execution_helper: SequenceExecutionHelper,
|
||||||
|
pub is_commandable_mock: IsCommandableMock,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SequenceExecutorTestbench {
|
impl SequenceExecutorTestbench {
|
||||||
@ -699,6 +738,7 @@ mod tests {
|
|||||||
mode_store,
|
mode_store,
|
||||||
seq_tables,
|
seq_tables,
|
||||||
execution_helper: SequenceExecutionHelper::new(),
|
execution_helper: SequenceExecutionHelper::new(),
|
||||||
|
is_commandable_mock: IsCommandableMock::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,15 +747,24 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(&mut self) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
pub fn run(&mut self) -> Result<ModeCommandingResult, GenericTargetedMessagingError> {
|
||||||
self.execution_helper
|
self.execution_helper.run(
|
||||||
.run(&self.seq_tables, &self.sender, &mut self.mode_store)
|
&self.seq_tables,
|
||||||
|
&self.sender,
|
||||||
|
&mut self.mode_store,
|
||||||
|
&self.is_commandable_mock,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_run_is_no_op(&mut self) {
|
fn check_run_is_no_op(&mut self) {
|
||||||
// Assure that no unexpected behaviour occurs.
|
// Assure that no unexpected behaviour occurs.
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
self.execution_helper
|
self.execution_helper
|
||||||
.run(&self.seq_tables, &self.sender, &mut self.mode_store)
|
.run(
|
||||||
|
&self.seq_tables,
|
||||||
|
&self.sender,
|
||||||
|
&mut self.mode_store,
|
||||||
|
&self.is_commandable_mock
|
||||||
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ModeCommandingResult::Done
|
ModeCommandingResult::Done
|
||||||
);
|
);
|
||||||
@ -861,6 +910,7 @@ mod tests {
|
|||||||
pub struct SubsystemHelperTestbench {
|
pub struct SubsystemHelperTestbench {
|
||||||
pub sender: ModeReqSenderMock,
|
pub sender: ModeReqSenderMock,
|
||||||
pub helper: SubsystemCommandingHelper,
|
pub helper: SubsystemCommandingHelper,
|
||||||
|
pub is_commandable_mock: IsCommandableMock,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SubsystemHelperTestbench {
|
impl SubsystemHelperTestbench {
|
||||||
@ -873,6 +923,7 @@ mod tests {
|
|||||||
target_tables,
|
target_tables,
|
||||||
sequence_tables,
|
sequence_tables,
|
||||||
),
|
),
|
||||||
|
is_commandable_mock: IsCommandableMock::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -905,7 +956,8 @@ mod tests {
|
|||||||
&mut self,
|
&mut self,
|
||||||
opt_reply: Option<GenericMessage<ModeReply>>,
|
opt_reply: Option<GenericMessage<ModeReply>>,
|
||||||
) -> Result<SubsystemHelperResult, ModeTreeHelperError> {
|
) -> Result<SubsystemHelperResult, ModeTreeHelperError> {
|
||||||
self.helper.state_machine(opt_reply, &self.sender)
|
self.helper
|
||||||
|
.state_machine(opt_reply, &self.sender, &self.is_commandable_mock)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generic_checks_subsystem_md0(&mut self, expected_req_id: RequestId) {
|
pub fn generic_checks_subsystem_md0(&mut self, expected_req_id: RequestId) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use num_enum::TryFromPrimitive;
|
use num_enum::TryFromPrimitive;
|
||||||
use satrs::dev_mgmt::{AssemblyCommandingHelper, AssemblyHelperResult};
|
use satrs::dev_mgmt::{
|
||||||
|
DevManagerCommandingHelper, DevManagerHelperResult, TransparentDevManagerHook,
|
||||||
|
};
|
||||||
use satrs::mode::{
|
use satrs::mode::{
|
||||||
Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
|
Mode, ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
|
||||||
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded,
|
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded,
|
||||||
@ -14,8 +16,8 @@ use satrs::mode_tree::{SequenceTablesMapValue, TargetTablesMapValue};
|
|||||||
use satrs::request::{MessageMetadata, RequestId};
|
use satrs::request::{MessageMetadata, RequestId};
|
||||||
use satrs::res_code::ResultU16;
|
use satrs::res_code::ResultU16;
|
||||||
use satrs::subsystem::{
|
use satrs::subsystem::{
|
||||||
ModeCommandingResult, ModeTreeHelperError, ModeTreeHelperState, StartSequenceError,
|
IsChildCommandable, ModeCommandingResult, ModeTreeHelperError, ModeTreeHelperState,
|
||||||
SubsystemCommandingHelper, SubsystemHelperResult,
|
StartSequenceError, SubsystemCommandingHelper, SubsystemHelperResult,
|
||||||
};
|
};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
||||||
@ -276,11 +278,21 @@ impl ModeParent for PusModeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default)]
|
||||||
|
struct IsCommandableDummy {}
|
||||||
|
|
||||||
|
impl IsChildCommandable for IsCommandableDummy {
|
||||||
|
fn is_commandable(&self, _id: ComponentId) -> bool {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AcsSubsystem {
|
struct AcsSubsystem {
|
||||||
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
||||||
pub mode_requestor_info: Option<MessageMetadata>,
|
pub mode_requestor_info: Option<MessageMetadata>,
|
||||||
pub target_mode_and_submode: Option<ModeAndSubmode>,
|
pub target_mode_and_submode: Option<ModeAndSubmode>,
|
||||||
pub subsystem_helper: SubsystemCommandingHelper,
|
pub subsystem_helper: SubsystemCommandingHelper,
|
||||||
|
is_commandable_dummy: IsCommandableDummy,
|
||||||
pub mode_req_mock: ModeRequestHandlerMock,
|
pub mode_req_mock: ModeRequestHandlerMock,
|
||||||
pub mode_reply_mock: ModeReplyHandlerMock,
|
pub mode_reply_mock: ModeReplyHandlerMock,
|
||||||
}
|
}
|
||||||
@ -295,6 +307,7 @@ impl AcsSubsystem {
|
|||||||
mode_node,
|
mode_node,
|
||||||
mode_requestor_info: None,
|
mode_requestor_info: None,
|
||||||
target_mode_and_submode: None,
|
target_mode_and_submode: None,
|
||||||
|
is_commandable_dummy: IsCommandableDummy::default(),
|
||||||
subsystem_helper: SubsystemCommandingHelper::default(),
|
subsystem_helper: SubsystemCommandingHelper::default(),
|
||||||
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
|
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
|
||||||
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
|
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
|
||||||
@ -345,13 +358,19 @@ impl AcsSubsystem {
|
|||||||
while let Some(mode_reply) = self.mode_node.try_recv_mode_reply().unwrap() {
|
while let Some(mode_reply) = self.mode_node.try_recv_mode_reply().unwrap() {
|
||||||
received_reply = true;
|
received_reply = true;
|
||||||
self.mode_reply_mock.handle_mode_reply(&mode_reply);
|
self.mode_reply_mock.handle_mode_reply(&mode_reply);
|
||||||
let result = self
|
let result = self.subsystem_helper.state_machine(
|
||||||
.subsystem_helper
|
Some(mode_reply),
|
||||||
.state_machine(Some(mode_reply), &self.mode_node);
|
&self.mode_node,
|
||||||
|
&self.is_commandable_dummy,
|
||||||
|
);
|
||||||
self.handle_subsystem_helper_result(result);
|
self.handle_subsystem_helper_result(result);
|
||||||
}
|
}
|
||||||
if !received_reply {
|
if !received_reply {
|
||||||
let result = self.subsystem_helper.state_machine(None, &self.mode_node);
|
let result = self.subsystem_helper.state_machine(
|
||||||
|
None,
|
||||||
|
&self.mode_node,
|
||||||
|
&self.is_commandable_dummy,
|
||||||
|
);
|
||||||
self.handle_subsystem_helper_result(result);
|
self.handle_subsystem_helper_result(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -492,7 +511,7 @@ struct MgmAssembly {
|
|||||||
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
||||||
pub mode_requestor_info: Option<MessageMetadata>,
|
pub mode_requestor_info: Option<MessageMetadata>,
|
||||||
pub mode_and_submode: ModeAndSubmode,
|
pub mode_and_submode: ModeAndSubmode,
|
||||||
pub commanding_helper: AssemblyCommandingHelper,
|
pub commanding_helper: DevManagerCommandingHelper<TransparentDevManagerHook>,
|
||||||
pub mode_req_mock: ModeRequestHandlerMock,
|
pub mode_req_mock: ModeRequestHandlerMock,
|
||||||
pub mode_reply_mock: ModeReplyHandlerMock,
|
pub mode_reply_mock: ModeReplyHandlerMock,
|
||||||
}
|
}
|
||||||
@ -506,7 +525,7 @@ impl MgmAssembly {
|
|||||||
mode_node,
|
mode_node,
|
||||||
mode_requestor_info: None,
|
mode_requestor_info: None,
|
||||||
mode_and_submode: UNKNOWN_MODE,
|
mode_and_submode: UNKNOWN_MODE,
|
||||||
commanding_helper: Default::default(),
|
commanding_helper: DevManagerCommandingHelper::new(TransparentDevManagerHook::default()),
|
||||||
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
|
mode_req_mock: ModeRequestHandlerMock::new(Self::id()),
|
||||||
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
|
mode_reply_mock: ModeReplyHandlerMock::new(Self::id()),
|
||||||
}
|
}
|
||||||
@ -532,18 +551,23 @@ impl MgmAssembly {
|
|||||||
while let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
|
while let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
|
||||||
self.mode_reply_mock.handle_mode_reply(&reply_and_id);
|
self.mode_reply_mock.handle_mode_reply(&reply_and_id);
|
||||||
match self.commanding_helper.handle_mode_reply(&reply_and_id) {
|
match self.commanding_helper.handle_mode_reply(&reply_and_id) {
|
||||||
AssemblyHelperResult::Idle => (),
|
Ok(result) => {
|
||||||
AssemblyHelperResult::TargetKeepingViolation(_id) => {
|
match result {
|
||||||
// TODO: Check whether enough children are available to keep the mode.
|
DevManagerHelperResult::Idle => todo!(),
|
||||||
// Otherwise, we command everything OFF, because we can not keep the mode.
|
DevManagerHelperResult::Busy => todo!(),
|
||||||
}
|
DevManagerHelperResult::ModeCommandingDone => {
|
||||||
AssemblyHelperResult::ModeCommandingDone => {
|
if self.commanding_helper.target_mode().is_some() {
|
||||||
if self.commanding_helper.target_mode().is_some() {
|
// Complete the mode command.
|
||||||
// Complete the mode command.
|
self.mode_and_submode =
|
||||||
self.mode_and_submode = self.commanding_helper.target_mode().unwrap();
|
self.commanding_helper.target_mode().unwrap();
|
||||||
self.handle_mode_reached(self.mode_requestor_info)?;
|
self.handle_mode_reached(self.mode_requestor_info)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(err) => match err {
|
||||||
|
satrs::dev_mgmt::DevManagerHelperError::ChildNotInStore => todo!(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -597,13 +621,12 @@ impl ModeRequestHandler for MgmAssembly {
|
|||||||
self.mode_req_mock
|
self.mode_req_mock
|
||||||
.start_transition(requestor, mode_and_submode, forced)
|
.start_transition(requestor, mode_and_submode, forced)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.commanding_helper
|
self.commanding_helper.send_mode_cmd_to_all_children(
|
||||||
.send_mode_cmd_to_all_children_with_reply_awaition(
|
requestor.request_id(),
|
||||||
requestor.request_id(),
|
mode_and_submode,
|
||||||
mode_and_submode,
|
forced,
|
||||||
forced,
|
&self.mode_node,
|
||||||
&self.mode_node,
|
)?;
|
||||||
)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -660,7 +683,7 @@ impl ModeRequestHandler for MgmAssembly {
|
|||||||
struct DeviceManager {
|
struct DeviceManager {
|
||||||
name: &'static str,
|
name: &'static str,
|
||||||
pub id: ComponentId,
|
pub id: ComponentId,
|
||||||
pub commanding_helper: AssemblyCommandingHelper,
|
pub commanding_helper: DevManagerCommandingHelper<TransparentDevManagerHook>,
|
||||||
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
||||||
pub mode_requestor_info: Option<MessageMetadata>,
|
pub mode_requestor_info: Option<MessageMetadata>,
|
||||||
pub mode_and_submode: ModeAndSubmode,
|
pub mode_and_submode: ModeAndSubmode,
|
||||||
@ -679,7 +702,7 @@ impl DeviceManager {
|
|||||||
id,
|
id,
|
||||||
mode_node,
|
mode_node,
|
||||||
mode_requestor_info: None,
|
mode_requestor_info: None,
|
||||||
commanding_helper: Default::default(),
|
commanding_helper: DevManagerCommandingHelper::new(TransparentDevManagerHook::default()),
|
||||||
mode_and_submode: UNKNOWN_MODE,
|
mode_and_submode: UNKNOWN_MODE,
|
||||||
mode_req_mock: ModeRequestHandlerMock::new(id),
|
mode_req_mock: ModeRequestHandlerMock::new(id),
|
||||||
mode_reply_mock: ModeReplyHandlerMock::new(id),
|
mode_reply_mock: ModeReplyHandlerMock::new(id),
|
||||||
@ -715,30 +738,22 @@ impl DeviceManager {
|
|||||||
) -> Result<(), ModeError> {
|
) -> Result<(), ModeError> {
|
||||||
self.mode_reply_mock.handle_mode_reply(mode_reply);
|
self.mode_reply_mock.handle_mode_reply(mode_reply);
|
||||||
match self.commanding_helper.handle_mode_reply(mode_reply) {
|
match self.commanding_helper.handle_mode_reply(mode_reply) {
|
||||||
AssemblyHelperResult::Idle => (),
|
Ok(result) => {
|
||||||
AssemblyHelperResult::TargetKeepingViolation(_id) => {
|
match result {
|
||||||
// TODO: Check whether enough children are available to keep the mode.
|
DevManagerHelperResult::Idle => todo!(),
|
||||||
// Otherwise, we command everything OFF, because we can not keep the mode.
|
DevManagerHelperResult::Busy => todo!(),
|
||||||
if self
|
DevManagerHelperResult::ModeCommandingDone => {
|
||||||
.commanding_helper
|
if self.commanding_helper.target_mode().is_some() {
|
||||||
.count_number_of_children_with_target_mode()
|
// Complete the mode command.
|
||||||
.unwrap()
|
self.handle_mode_reached(self.mode_requestor_info)?;
|
||||||
< 1
|
self.mode_and_submode = self.commanding_helper.target_mode().unwrap();
|
||||||
{
|
}
|
||||||
if let Err(_e) = self.start_transition(
|
}
|
||||||
MessageMetadata::new(0, self.id()),
|
|
||||||
ModeAndSubmode::new(DefaultMode::OFF as Mode, 0),
|
|
||||||
false,
|
|
||||||
) {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AssemblyHelperResult::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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Err(e) => match e {
|
||||||
|
satrs::dev_mgmt::DevManagerHelperError::ChildNotInStore => todo!(),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -789,13 +804,12 @@ impl ModeRequestHandler for DeviceManager {
|
|||||||
self.mode_req_mock
|
self.mode_req_mock
|
||||||
.start_transition(requestor, mode_and_submode, forced)
|
.start_transition(requestor, mode_and_submode, forced)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.commanding_helper
|
self.commanding_helper.send_mode_cmd_to_all_children(
|
||||||
.send_mode_cmd_to_all_children_with_reply_awaition(
|
requestor.request_id(),
|
||||||
requestor.request_id(),
|
mode_and_submode,
|
||||||
mode_and_submode,
|
forced,
|
||||||
forced,
|
&self.mode_node,
|
||||||
&self.mode_node,
|
)?;
|
||||||
)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user