mode request/responses to models
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
use models::mgm::MgmData;
|
||||
use models::mgm::response::ModeFailure;
|
||||
use models::mgm::request::ModeRequest;
|
||||
use models::mgm::response::ModeResponse;
|
||||
use models::pcdu::SwitchId;
|
||||
use models::{ComponentId, DeviceMode, HkRequestType, mgm};
|
||||
use satrs::spacepackets::CcsdsPacketIdAndPsc;
|
||||
@@ -56,20 +57,6 @@ pub enum TransitionState {
|
||||
Done,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum ModeRequest {
|
||||
SetMode(DeviceMode),
|
||||
ReadMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub enum ModeReport {
|
||||
/// New mode has been set.
|
||||
Mode(DeviceMode),
|
||||
/// Setting a mode timed out.
|
||||
SetModeTimeout,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct SpiDummyInterface {
|
||||
pub dummy_values: MgmLis3RawValues,
|
||||
@@ -157,7 +144,7 @@ pub struct BufWrapper {
|
||||
/// Helper component for communication with a parent component, which is usually as assembly.
|
||||
pub struct ModeLeafHelper {
|
||||
pub request_rx: mpsc::Receiver<ModeRequest>,
|
||||
pub report_tx: mpsc::SyncSender<ModeReport>,
|
||||
pub report_tx: mpsc::SyncSender<ModeResponse>,
|
||||
}
|
||||
|
||||
/// Example MGM device handler strongly based on the LIS3MDL MEMS device.
|
||||
@@ -254,10 +241,18 @@ impl MgmHandlerLis3Mdl {
|
||||
mgm::request::Request::Hk(hk_request) => {
|
||||
self.handle_hk_request(Some(tc_id), &hk_request)
|
||||
}
|
||||
mgm::request::Request::Mode(device_mode) => {
|
||||
self.mode_helpers.tc_commander = Some(tc_id);
|
||||
self.start_transition(device_mode, false);
|
||||
}
|
||||
mgm::request::Request::Mode(device_mode) => match device_mode {
|
||||
ModeRequest::SetMode(device_mode) => {
|
||||
self.mode_helpers.tc_commander = Some(tc_id);
|
||||
self.start_transition(device_mode, false);
|
||||
}
|
||||
ModeRequest::ReadMode => self.send_telemetry(
|
||||
Some(tc_id),
|
||||
mgm::response::Response::Mode(ModeResponse::Mode(
|
||||
self.mode(),
|
||||
)),
|
||||
),
|
||||
},
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
@@ -414,12 +409,12 @@ impl MgmHandlerLis3Mdl {
|
||||
if tc_commander.is_some() {
|
||||
self.send_telemetry(
|
||||
tc_commander,
|
||||
mgm::response::Response::ModeFailure(ModeFailure::Timeout),
|
||||
mgm::response::Response::Mode(ModeResponse::SetModeTimeout),
|
||||
);
|
||||
}
|
||||
self.mode_leaf_helper
|
||||
.report_tx
|
||||
.send(ModeReport::SetModeTimeout)
|
||||
.send(ModeResponse::SetModeTimeout)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -446,7 +441,7 @@ impl MgmHandlerLis3Mdl {
|
||||
fn report_mode_to_parent(&self) {
|
||||
self.mode_leaf_helper
|
||||
.report_tx
|
||||
.send(ModeReport::Mode(self.mode_helpers.current))
|
||||
.send(ModeResponse::Mode(self.mode_helpers.current))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
@@ -505,7 +500,7 @@ mod tests {
|
||||
#[allow(dead_code)]
|
||||
pub struct MgmTestbench {
|
||||
pub assembly_mode_request_tx: mpsc::SyncSender<ModeRequest>,
|
||||
pub mode_report_rx: mpsc::Receiver<ModeReport>,
|
||||
pub mode_report_rx: mpsc::Receiver<ModeResponse>,
|
||||
pub shared_switch_set: SharedSwitchSet,
|
||||
pub tc_tx: mpsc::SyncSender<CcsdsTcPacketOwned>,
|
||||
pub tm_rx: mpsc::Receiver<CcsdsTmPacketOwned>,
|
||||
@@ -576,7 +571,7 @@ mod tests {
|
||||
.tc_tx
|
||||
.send(create_request_tc(
|
||||
MgmSelect::_0,
|
||||
mgm::request::Request::Mode(DeviceMode::Normal),
|
||||
mgm::request::Request::Mode(ModeRequest::SetMode(DeviceMode::Normal)),
|
||||
))
|
||||
.unwrap();
|
||||
testbench.handler.periodic_operation();
|
||||
@@ -630,7 +625,7 @@ mod tests {
|
||||
.tc_tx
|
||||
.send(create_request_tc(
|
||||
MgmSelect::_0,
|
||||
mgm::request::Request::Mode(DeviceMode::Normal),
|
||||
mgm::request::Request::Mode(ModeRequest::SetMode(DeviceMode::Normal)),
|
||||
))
|
||||
.unwrap();
|
||||
testbench.handler.periodic_operation();
|
||||
@@ -714,7 +709,7 @@ mod tests {
|
||||
.tc_tx
|
||||
.send(create_request_tc(
|
||||
MgmSelect::_0,
|
||||
mgm::request::Request::Mode(DeviceMode::Normal),
|
||||
mgm::request::Request::Mode(ModeRequest::SetMode(DeviceMode::Normal)),
|
||||
))
|
||||
.unwrap();
|
||||
// This simulates one cycle for the power switch to update.
|
||||
|
||||
@@ -1,43 +1,23 @@
|
||||
#![allow(dead_code)]
|
||||
use std::{sync::mpsc, time::Duration};
|
||||
|
||||
use models::{
|
||||
ComponentId, DeviceMode,
|
||||
mgm_assembly::{
|
||||
AssemblyMode,
|
||||
response::{self, ModeCommandFailure},
|
||||
},
|
||||
mgm_assembly::{AssemblyMode, request, response},
|
||||
};
|
||||
use satrs::spacepackets::CcsdsPacketIdAndPsc;
|
||||
use satrs_example::{ModeHelper, TmtcQueues};
|
||||
|
||||
use crate::ccsds::pack_ccsds_tm_packet_for_now;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ModeRequest {
|
||||
SetMode(AssemblyMode),
|
||||
ReadMode,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub enum ModeReport {
|
||||
/// Mode of the assembly.
|
||||
Mode(AssemblyMode),
|
||||
/// Failure setting the children mode.
|
||||
SetModeTimeout([Option<DeviceMode>; 2]),
|
||||
/// An assembly tried modekeeping but can not keep its mode.
|
||||
CanNotKeepMode([Option<DeviceMode>; 2]),
|
||||
}
|
||||
|
||||
pub struct ParentQueueHelper {
|
||||
pub request_rx: mpsc::Receiver<ModeRequest>,
|
||||
pub report_tx: mpsc::SyncSender<ModeReport>,
|
||||
pub request_rx: mpsc::Receiver<request::ModeRequest>,
|
||||
pub report_tx: mpsc::SyncSender<response::ModeReport>,
|
||||
}
|
||||
|
||||
/// Helper component for communication with a parent component, which is usually as assembly.
|
||||
pub struct ChildrenQueueHelper {
|
||||
pub request_tx_queues: [mpsc::SyncSender<super::mgm::ModeRequest>; 2],
|
||||
pub report_rx_queues: [mpsc::Receiver<super::mgm::ModeReport>; 2],
|
||||
pub request_tx_queues: [mpsc::SyncSender<models::mgm::request::ModeRequest>; 2],
|
||||
pub report_rx_queues: [mpsc::Receiver<models::mgm::response::ModeResponse>; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -107,8 +87,18 @@ impl Assembly {
|
||||
models::mgm_assembly::request::Request::Ping => {
|
||||
self.send_telemetry(Some(tc_id), response::Response::Ok)
|
||||
}
|
||||
models::mgm_assembly::request::Request::Mode(assembly_mode) => {
|
||||
self.start_transition(false, assembly_mode, Some(tc_id))
|
||||
models::mgm_assembly::request::Request::Mode(request) => {
|
||||
match request {
|
||||
request::ModeRequest::SetMode(assembly_mode) => {
|
||||
self.start_transition(false, assembly_mode, Some(tc_id))
|
||||
}
|
||||
request::ModeRequest::ReadMode => self.send_telemetry(
|
||||
Some(tc_id),
|
||||
response::Response::Mode(response::ModeReport::Mode(
|
||||
self.mode(),
|
||||
)),
|
||||
),
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
@@ -145,18 +135,18 @@ impl Assembly {
|
||||
loop {
|
||||
match self.parent_queues.request_rx.try_recv() {
|
||||
Ok(request) => match request {
|
||||
ModeRequest::SetMode(assembly_mode) => match assembly_mode {
|
||||
request::ModeRequest::SetMode(assembly_mode) => match assembly_mode {
|
||||
AssemblyMode::Device(_device_mode) => {
|
||||
self.start_transition(false, assembly_mode, None);
|
||||
}
|
||||
AssemblyMode::NoModeKeeping => {
|
||||
self.mode_helper.current = AssemblyMode::NoModeKeeping
|
||||
self.mode_helper.current = AssemblyMode::NoModeKeeping;
|
||||
}
|
||||
},
|
||||
ModeRequest::ReadMode => self
|
||||
request::ModeRequest::ReadMode => self
|
||||
.parent_queues
|
||||
.report_tx
|
||||
.send(ModeReport::Mode(self.mode_helper.current))
|
||||
.send(response::ModeReport::Mode(self.mode_helper.current))
|
||||
.unwrap(),
|
||||
},
|
||||
Err(e) => match e {
|
||||
@@ -175,12 +165,12 @@ impl Assembly {
|
||||
loop {
|
||||
match rx.try_recv() {
|
||||
Ok(report) => match report {
|
||||
super::mgm::ModeReport::Mode(device_mode) => {
|
||||
models::mgm::response::ModeResponse::Mode(device_mode) => {
|
||||
self.mgm_modes[idx].mode = Some(device_mode);
|
||||
self.mgm_modes[idx].reply_received = true;
|
||||
mode_report_received = true;
|
||||
}
|
||||
super::mgm::ModeReport::SetModeTimeout => {
|
||||
models::mgm::response::ModeResponse::SetModeTimeout => {
|
||||
// Ignore, handle this with our own timeout.
|
||||
log::warn!("MGM {} mode timeout", idx);
|
||||
}
|
||||
@@ -199,13 +189,21 @@ impl Assembly {
|
||||
}
|
||||
|
||||
// Transition is active, check for completion.
|
||||
// If at least one child reached the correct mode, we are done.
|
||||
if self.mode_helper.transition_active()
|
||||
&& let AssemblyMode::Device(device_mode) = self.mode_helper.target.unwrap()
|
||||
&& self.mgm_modes.iter().all(|i| i.reply_received)
|
||||
&& self.mgm_modes.iter().any(|i| i.mode == Some(device_mode))
|
||||
&& let AssemblyMode::Device(device_mode) = self.mode_helper.target.unwrap()
|
||||
{
|
||||
self.handle_mode_reached();
|
||||
// If at least one child reached the correct mode, we are done.
|
||||
if self.mgm_modes.iter().any(|i| i.mode == Some(device_mode)) {
|
||||
self.handle_mode_reached(true);
|
||||
} else {
|
||||
let report = if self.mode_keeping_transition {
|
||||
response::ModeReport::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
} else {
|
||||
response::ModeReport::WrongMode(self.mgm_modes.map(|info| info.mode))
|
||||
};
|
||||
self.handle_mode_transition_failure(report);
|
||||
}
|
||||
}
|
||||
|
||||
// Mode keeping active: Check children modes.
|
||||
@@ -223,14 +221,14 @@ impl Assembly {
|
||||
|
||||
pub fn handle_mode_transition(&mut self) {
|
||||
if self.mode_helper.target.is_none() {
|
||||
self.handle_mode_reached();
|
||||
self.handle_mode_reached(true);
|
||||
return;
|
||||
}
|
||||
let target = self.mode_helper.target.unwrap();
|
||||
let device_mode = match target {
|
||||
AssemblyMode::Device(device_mode) => device_mode,
|
||||
AssemblyMode::NoModeKeeping => {
|
||||
self.handle_mode_reached();
|
||||
self.handle_mode_reached(true);
|
||||
return;
|
||||
}
|
||||
};
|
||||
@@ -241,32 +239,34 @@ impl Assembly {
|
||||
if self.mode_helper.transition_state == TransitionState::AwaitingReplies
|
||||
&& self.mode_helper.timed_out()
|
||||
{
|
||||
self.handle_mode_transition_failure();
|
||||
let report = if self.mode_keeping_transition {
|
||||
response::ModeReport::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
} else {
|
||||
response::ModeReport::SetModeTimeout(self.mgm_modes.map(|info| info.mode))
|
||||
};
|
||||
self.handle_mode_transition_failure(report);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mode_reached(&mut self) {
|
||||
let tc_commander = self.mode_helper.finish(true);
|
||||
pub fn handle_mode_reached(&mut self, success: bool) {
|
||||
let tc_commander = self.mode_helper.finish(success);
|
||||
self.announce_mode();
|
||||
if tc_commander.is_some() {
|
||||
self.send_telemetry(tc_commander, response::Response::Ok);
|
||||
}
|
||||
self.parent_queues
|
||||
.report_tx
|
||||
.send(ModeReport::Mode(self.mode_helper.current))
|
||||
.send(response::ModeReport::Mode(self.mode_helper.current))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_mode_transition_failure(&mut self) {
|
||||
let report = if self.mode_keeping_transition {
|
||||
ModeReport::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
} else {
|
||||
ModeReport::SetModeTimeout(self.mgm_modes.map(|info| info.mode))
|
||||
};
|
||||
pub fn handle_mode_transition_failure(&mut self, report: response::ModeReport) {
|
||||
if self.mode_helper.tc_commander.is_some() {
|
||||
self.send_telemetry(
|
||||
self.mode_helper.tc_commander,
|
||||
response::Response::ModeFailure(ModeCommandFailure::Timeout),
|
||||
response::Response::Mode(response::ModeReport::SetModeTimeout(
|
||||
self.mgm_modes.map(|info| info.mode),
|
||||
)),
|
||||
);
|
||||
}
|
||||
self.parent_queues.report_tx.send(report).unwrap();
|
||||
@@ -275,7 +275,8 @@ impl Assembly {
|
||||
|
||||
pub fn command_children(&self, mode: DeviceMode) {
|
||||
for tx in &self.children_queues.request_tx_queues {
|
||||
tx.send(super::mgm::ModeRequest::SetMode(mode)).unwrap();
|
||||
tx.send(models::mgm::request::ModeRequest::SetMode(mode))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -308,7 +309,8 @@ impl Assembly {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mode_transition_active(&self) -> bool {
|
||||
#[cfg(test)]
|
||||
fn mode_transition_active(&self) -> bool {
|
||||
self.mode_helper.transition_active()
|
||||
}
|
||||
}
|
||||
@@ -328,10 +330,10 @@ mod tests {
|
||||
use super::*;
|
||||
|
||||
pub struct Testbench {
|
||||
subsystem_req_tx: mpsc::SyncSender<ModeRequest>,
|
||||
subsystem_report_rx: mpsc::Receiver<ModeReport>,
|
||||
mgm_request_rx: [mpsc::Receiver<crate::mgm::ModeRequest>; 2],
|
||||
mgm_report_tx: [mpsc::SyncSender<crate::mgm::ModeReport>; 2],
|
||||
subsystem_req_tx: mpsc::SyncSender<request::ModeRequest>,
|
||||
subsystem_report_rx: mpsc::Receiver<response::ModeReport>,
|
||||
mgm_request_rx: [mpsc::Receiver<models::mgm::request::ModeRequest>; 2],
|
||||
mgm_report_tx: [mpsc::SyncSender<models::mgm::response::ModeResponse>; 2],
|
||||
tc_tx: mpsc::SyncSender<CcsdsTcPacketOwned>,
|
||||
tm_rx: mpsc::Receiver<CcsdsTmPacketOwned>,
|
||||
assembly: Assembly,
|
||||
@@ -417,7 +419,7 @@ mod tests {
|
||||
let mut tb = Testbench::new();
|
||||
tb.tc_tx
|
||||
.send(create_request_tc(mgm_assembly::request::Request::Mode(
|
||||
AssemblyMode::Device(DeviceMode::Normal),
|
||||
request::ModeRequest::SetMode(AssemblyMode::Device(DeviceMode::Normal)),
|
||||
)))
|
||||
.unwrap();
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -427,14 +429,16 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
crate::mgm::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(crate::mgm::ModeReport::Mode(DeviceMode::Normal))
|
||||
.unwrap();
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -452,7 +456,7 @@ mod tests {
|
||||
fn test_parent_commanded_transition() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -463,14 +467,16 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
crate::mgm::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(crate::mgm::ModeReport::Mode(DeviceMode::Normal))
|
||||
.unwrap();
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -480,7 +486,7 @@ mod tests {
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -488,7 +494,7 @@ mod tests {
|
||||
fn test_one_mgm_is_sufficient() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -499,16 +505,18 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
crate::mgm::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// One device is sufficient.
|
||||
tb.mgm_report_tx[0]
|
||||
.send(crate::mgm::ModeReport::Mode(DeviceMode::Normal))
|
||||
.send(models::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
tb.mgm_report_tx[1]
|
||||
.send(crate::mgm::ModeReport::Mode(DeviceMode::Off))
|
||||
.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -518,7 +526,109 @@ mod tests {
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mode_commanding_fails() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(tb.assembly.mode_transition_active());
|
||||
|
||||
for rx in tb.mgm_request_rx.iter() {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::NoModeKeeping);
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::WrongMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_mode_keeping_fails() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(tb.assembly.mode_transition_active());
|
||||
|
||||
for rx in tb.mgm_request_rx.iter() {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal));
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
);
|
||||
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
}
|
||||
// This should start mode keeping.
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(tb.assembly.mode_transition_active());
|
||||
|
||||
for rx in tb.mgm_request_rx.iter() {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Let the mode keeping fail.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
}
|
||||
tb.assembly.periodic_operation();
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::CanNotKeepMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,9 +144,7 @@ impl<Mode: Copy + Clone, TransitionState: Default> ModeHelper<Mode, TransitionSt
|
||||
}
|
||||
|
||||
pub fn finish(&mut self, success: bool) -> Option<CcsdsPacketIdAndPsc> {
|
||||
if self.target.is_none() {
|
||||
return None;
|
||||
}
|
||||
self.target?;
|
||||
if success {
|
||||
self.current = self.target.take().unwrap();
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user