start adding ACS subsystem
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
use models::mgm::MgmData;
|
||||
use models::mgm::request::ModeRequest;
|
||||
use models::mgm::response::ModeResponse;
|
||||
use models::acs::mgm::SensorData;
|
||||
use models::acs::mgm::request::ModeRequest;
|
||||
use models::acs::mgm::response::ModeResponse;
|
||||
use models::pcdu::SwitchId;
|
||||
use models::{ComponentId, DeviceMode, HkRequestType, mgm};
|
||||
use models::{ComponentId, DeviceMode, HkRequestType, acs::mgm};
|
||||
use satrs::spacepackets::CcsdsPacketIdAndPsc;
|
||||
use satrs_example::{HkHelperSingleSet, ModeHelper, TimestampHelper, TmtcQueues};
|
||||
use satrs_minisim::acs::MgmRequestLis3Mdl;
|
||||
@@ -153,7 +153,7 @@ pub struct MgmHandlerLis3Mdl {
|
||||
switch_helper: PowerSwitchHelper,
|
||||
tmtc_queues: TmtcQueues,
|
||||
pub spi_com: SpiCommunication,
|
||||
shared_mgm_set: Arc<Mutex<MgmData>>,
|
||||
shared_mgm_set: Arc<Mutex<SensorData>>,
|
||||
buffers: BufWrapper,
|
||||
stamp_helper: TimestampHelper,
|
||||
hk_helper: HkHelperSingleSet,
|
||||
@@ -167,7 +167,7 @@ impl MgmHandlerLis3Mdl {
|
||||
tmtc_queues: TmtcQueues,
|
||||
switch_helper: PowerSwitchHelper,
|
||||
spi_com: SpiCommunication,
|
||||
shared_mgm_set: Arc<Mutex<MgmData>>,
|
||||
shared_mgm_set: Arc<Mutex<SensorData>>,
|
||||
mode_leaf_helper: ModeLeafHelper,
|
||||
mode_timeout: Duration,
|
||||
) -> Self {
|
||||
@@ -308,7 +308,7 @@ impl MgmHandlerLis3Mdl {
|
||||
pub fn handle_hk_request(
|
||||
&mut self,
|
||||
tc_id: Option<CcsdsPacketIdAndPsc>,
|
||||
hk_request: &models::mgm::request::HkRequest,
|
||||
hk_request: &models::acs::mgm::request::HkRequest,
|
||||
) {
|
||||
match hk_request.req_type {
|
||||
HkRequestType::OneShot => {
|
||||
@@ -462,8 +462,8 @@ mod tests {
|
||||
use arbitrary_int::u11;
|
||||
use models::{
|
||||
Apid, ComponentId, TcHeader,
|
||||
acs::mgm::request::HkRequest,
|
||||
ccsds::{CcsdsTcPacketOwned, CcsdsTmPacketOwned},
|
||||
mgm::request::HkRequest,
|
||||
pcdu::{SwitchRequest, SwitchState, SwitchStateBinary},
|
||||
};
|
||||
use satrs::{request::GenericMessage, spacepackets::SpacePacketHeader};
|
||||
@@ -490,7 +490,7 @@ mod tests {
|
||||
|
||||
pub fn create_request_tc(
|
||||
select: MgmSelect,
|
||||
request: models::mgm::request::Request,
|
||||
request: models::acs::mgm::request::Request,
|
||||
) -> models::ccsds::CcsdsTcPacketOwned {
|
||||
models::ccsds::CcsdsTcPacketOwned::new_with_request(
|
||||
SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)),
|
||||
@@ -533,7 +533,7 @@ mod tests {
|
||||
SpiCommunication::Test(TestSpiInterface::default()),
|
||||
shared_mgm_set,
|
||||
mode_leaf_helper,
|
||||
Duration::from_millis(200),
|
||||
Duration::from_millis(100),
|
||||
);
|
||||
Self {
|
||||
assembly_mode_request_tx,
|
||||
@@ -601,9 +601,10 @@ mod tests {
|
||||
|
||||
assert_eq!(tm_packet.tm_header.sender_id, ComponentId::AcsMgm0);
|
||||
|
||||
let response = postcard::from_bytes::<models::mgm::response::Response>(&tm_packet.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
matches!(response, models::mgm::response::Response::Ok);
|
||||
let response =
|
||||
postcard::from_bytes::<models::acs::mgm::response::Response>(&tm_packet.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
matches!(response, models::acs::mgm::response::Response::Ok);
|
||||
// The device should have been polled once.
|
||||
assert_eq!(testbench.test_spi_interface().call_count, 1);
|
||||
let mgm_set = *testbench.handler.shared_mgm_set.lock().unwrap();
|
||||
@@ -689,9 +690,10 @@ mod tests {
|
||||
|
||||
assert_eq!(tm_packet.tm_header.sender_id, ComponentId::AcsMgm0);
|
||||
|
||||
let response = postcard::from_bytes::<models::mgm::response::Response>(&tm_packet.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
if let models::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) =
|
||||
let response =
|
||||
postcard::from_bytes::<models::acs::mgm::response::Response>(&tm_packet.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
if let models::acs::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) =
|
||||
response
|
||||
{
|
||||
assert_eq!(data.valid, false);
|
||||
@@ -740,17 +742,18 @@ mod tests {
|
||||
|
||||
assert_eq!(mode_tm.tm_header.sender_id, ComponentId::AcsMgm0);
|
||||
|
||||
let response = postcard::from_bytes::<models::mgm::response::Response>(&mode_tm.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
matches!(response, models::mgm::response::Response::Ok);
|
||||
let response =
|
||||
postcard::from_bytes::<models::acs::mgm::response::Response>(&mode_tm.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
matches!(response, models::acs::mgm::response::Response::Ok);
|
||||
|
||||
let hk_tm = testbench.tm_rx.try_recv().expect("no hk reply generated");
|
||||
|
||||
assert_eq!(hk_tm.tm_header.sender_id, ComponentId::AcsMgm0);
|
||||
|
||||
let response = postcard::from_bytes::<models::mgm::response::Response>(&hk_tm.payload)
|
||||
let response = postcard::from_bytes::<models::acs::mgm::response::Response>(&hk_tm.payload)
|
||||
.expect("failed to deserialize mode reply");
|
||||
if let models::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) =
|
||||
if let models::acs::mgm::response::Response::Hk(mgm::response::HkResponse::MgmData(data)) =
|
||||
response
|
||||
{
|
||||
// Set is now valid.
|
||||
|
||||
@@ -2,7 +2,7 @@ use std::{sync::mpsc, time::Duration};
|
||||
|
||||
use models::{
|
||||
ComponentId, DeviceMode,
|
||||
mgm_assembly::{AssemblyMode, request, response},
|
||||
acs::mgm_assembly::{Mode, request, response},
|
||||
};
|
||||
use satrs::spacepackets::CcsdsPacketIdAndPsc;
|
||||
use satrs_example::{ModeHelper, TmtcQueues};
|
||||
@@ -11,13 +11,13 @@ use crate::ccsds::pack_ccsds_tm_packet_for_now;
|
||||
|
||||
pub struct ParentQueueHelper {
|
||||
pub request_rx: mpsc::Receiver<request::ModeRequest>,
|
||||
pub report_tx: mpsc::SyncSender<response::ModeReport>,
|
||||
pub report_tx: mpsc::SyncSender<response::ModeResponse>,
|
||||
}
|
||||
|
||||
/// Helper component for communication with a parent component, which is usually as assembly.
|
||||
pub struct ChildrenQueueHelper {
|
||||
pub request_tx_queues: [mpsc::SyncSender<models::mgm::request::ModeRequest>; 2],
|
||||
pub report_rx_queues: [mpsc::Receiver<models::mgm::response::ModeResponse>; 2],
|
||||
pub request_tx_queues: [mpsc::SyncSender<models::acs::mgm::request::ModeRequest>; 2],
|
||||
pub report_rx_queues: [mpsc::Receiver<models::acs::mgm::response::ModeResponse>; 2],
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -35,7 +35,7 @@ pub struct MgmInfo {
|
||||
|
||||
/// MGM assembly component.
|
||||
pub struct Assembly {
|
||||
mode_helper: ModeHelper<AssemblyMode, TransitionState>,
|
||||
mode_helper: ModeHelper<Mode, TransitionState>,
|
||||
/// This boolean is used for the distinction between transitions commanded by the parent
|
||||
/// or by ground, and transitions which were commanded autonomously as part of children
|
||||
/// mode keeping.
|
||||
@@ -56,7 +56,7 @@ impl Assembly {
|
||||
mode_timeout: Duration,
|
||||
) -> Self {
|
||||
Self {
|
||||
mode_helper: ModeHelper::new(AssemblyMode::NoModeKeeping, mode_timeout),
|
||||
mode_helper: ModeHelper::new(Mode::NoModeKeeping, mode_timeout),
|
||||
mode_keeping_transition: false,
|
||||
tmtc_queues,
|
||||
mgm_modes: [MgmInfo::default(); 2],
|
||||
@@ -80,21 +80,21 @@ impl Assembly {
|
||||
match self.tmtc_queues.tc_rx.try_recv() {
|
||||
Ok(packet) => {
|
||||
let tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&packet.sp_header);
|
||||
match postcard::from_bytes::<models::mgm_assembly::request::Request>(
|
||||
match postcard::from_bytes::<models::acs::mgm_assembly::request::Request>(
|
||||
&packet.payload,
|
||||
) {
|
||||
Ok(request) => match request {
|
||||
models::mgm_assembly::request::Request::Ping => {
|
||||
models::acs::mgm_assembly::request::Request::Ping => {
|
||||
self.send_telemetry(Some(tc_id), response::Response::Ok)
|
||||
}
|
||||
models::mgm_assembly::request::Request::Mode(request) => {
|
||||
models::acs::mgm_assembly::request::Request::Mode(request) => {
|
||||
match request {
|
||||
request::ModeRequest::SetMode(assembly_mode) => {
|
||||
self.start_transition(false, assembly_mode, Some(tc_id))
|
||||
}
|
||||
request::ModeRequest::ReadMode => self.send_telemetry(
|
||||
Some(tc_id),
|
||||
response::Response::Mode(response::ModeReport::Mode(
|
||||
response::Response::Mode(response::ModeResponse::Mode(
|
||||
self.mode(),
|
||||
)),
|
||||
),
|
||||
@@ -117,7 +117,7 @@ impl Assembly {
|
||||
pub fn send_telemetry(
|
||||
&self,
|
||||
tc_id: Option<CcsdsPacketIdAndPsc>,
|
||||
response: models::mgm_assembly::response::Response,
|
||||
response: models::acs::mgm_assembly::response::Response,
|
||||
) {
|
||||
match pack_ccsds_tm_packet_for_now(Self::ID, tc_id, &response) {
|
||||
Ok(packet) => {
|
||||
@@ -136,17 +136,17 @@ impl Assembly {
|
||||
match self.parent_queues.request_rx.try_recv() {
|
||||
Ok(request) => match request {
|
||||
request::ModeRequest::SetMode(assembly_mode) => match assembly_mode {
|
||||
AssemblyMode::Device(_device_mode) => {
|
||||
Mode::Device(_device_mode) => {
|
||||
self.start_transition(false, assembly_mode, None);
|
||||
}
|
||||
AssemblyMode::NoModeKeeping => {
|
||||
self.mode_helper.current = AssemblyMode::NoModeKeeping;
|
||||
Mode::NoModeKeeping => {
|
||||
self.mode_helper.current = Mode::NoModeKeeping;
|
||||
}
|
||||
},
|
||||
request::ModeRequest::ReadMode => self
|
||||
.parent_queues
|
||||
.report_tx
|
||||
.send(response::ModeReport::Mode(self.mode_helper.current))
|
||||
.send(response::ModeResponse::Mode(self.mode_helper.current))
|
||||
.unwrap(),
|
||||
},
|
||||
Err(e) => match e {
|
||||
@@ -165,12 +165,12 @@ impl Assembly {
|
||||
loop {
|
||||
match rx.try_recv() {
|
||||
Ok(report) => match report {
|
||||
models::mgm::response::ModeResponse::Mode(device_mode) => {
|
||||
models::acs::mgm::response::ModeResponse::Mode(device_mode) => {
|
||||
self.mgm_modes[idx].mode = Some(device_mode);
|
||||
self.mgm_modes[idx].reply_received = true;
|
||||
mode_report_received = true;
|
||||
}
|
||||
models::mgm::response::ModeResponse::SetModeTimeout => {
|
||||
models::acs::mgm::response::ModeResponse::SetModeTimeout => {
|
||||
// Ignore, handle this with our own timeout.
|
||||
log::warn!("MGM {} mode timeout", idx);
|
||||
}
|
||||
@@ -191,23 +191,23 @@ impl Assembly {
|
||||
// Transition is active, check for completion.
|
||||
if self.mode_helper.transition_active()
|
||||
&& self.mgm_modes.iter().all(|i| i.reply_received)
|
||||
&& let AssemblyMode::Device(device_mode) = self.mode_helper.target.unwrap()
|
||||
&& let Mode::Device(device_mode) = self.mode_helper.target.unwrap()
|
||||
{
|
||||
// If at least one child reached the correct mode, we are done.
|
||||
if self.mgm_modes.iter().any(|i| i.mode == Some(device_mode)) {
|
||||
self.handle_mode_reached(true);
|
||||
} else {
|
||||
let report = if self.mode_keeping_transition {
|
||||
response::ModeReport::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
response::ModeResponse::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
} else {
|
||||
response::ModeReport::WrongMode(self.mgm_modes.map(|info| info.mode))
|
||||
response::ModeResponse::WrongMode(self.mgm_modes.map(|info| info.mode))
|
||||
};
|
||||
self.handle_mode_transition_failure(report);
|
||||
}
|
||||
}
|
||||
|
||||
// Mode keeping active: Check children modes.
|
||||
if let AssemblyMode::Device(device_mode) = self.mode_helper.current
|
||||
if let Mode::Device(device_mode) = self.mode_helper.current
|
||||
&& self
|
||||
.mgm_modes
|
||||
.iter()
|
||||
@@ -226,8 +226,8 @@ impl Assembly {
|
||||
}
|
||||
let target = self.mode_helper.target.unwrap();
|
||||
let device_mode = match target {
|
||||
AssemblyMode::Device(device_mode) => device_mode,
|
||||
AssemblyMode::NoModeKeeping => {
|
||||
Mode::Device(device_mode) => device_mode,
|
||||
Mode::NoModeKeeping => {
|
||||
self.handle_mode_reached(true);
|
||||
return;
|
||||
}
|
||||
@@ -240,9 +240,9 @@ impl Assembly {
|
||||
&& self.mode_helper.timed_out()
|
||||
{
|
||||
let report = if self.mode_keeping_transition {
|
||||
response::ModeReport::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
response::ModeResponse::CanNotKeepMode(self.mgm_modes.map(|info| info.mode))
|
||||
} else {
|
||||
response::ModeReport::SetModeTimeout(self.mgm_modes.map(|info| info.mode))
|
||||
response::ModeResponse::SetModeTimeout(self.mgm_modes.map(|info| info.mode))
|
||||
};
|
||||
self.handle_mode_transition_failure(report);
|
||||
}
|
||||
@@ -256,15 +256,15 @@ impl Assembly {
|
||||
}
|
||||
self.parent_queues
|
||||
.report_tx
|
||||
.send(response::ModeReport::Mode(self.mode_helper.current))
|
||||
.send(response::ModeResponse::Mode(self.mode_helper.current))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
pub fn handle_mode_transition_failure(&mut self, report: response::ModeReport) {
|
||||
pub fn handle_mode_transition_failure(&mut self, report: response::ModeResponse) {
|
||||
if self.mode_helper.tc_commander.is_some() {
|
||||
self.send_telemetry(
|
||||
self.mode_helper.tc_commander,
|
||||
response::Response::Mode(response::ModeReport::SetModeTimeout(
|
||||
response::Response::Mode(response::ModeResponse::SetModeTimeout(
|
||||
self.mgm_modes.map(|info| info.mode),
|
||||
)),
|
||||
);
|
||||
@@ -275,7 +275,7 @@ impl Assembly {
|
||||
|
||||
pub fn command_children(&self, mode: DeviceMode) {
|
||||
for tx in &self.children_queues.request_tx_queues {
|
||||
tx.send(models::mgm::request::ModeRequest::SetMode(mode))
|
||||
tx.send(models::acs::mgm::request::ModeRequest::SetMode(mode))
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
@@ -283,7 +283,7 @@ impl Assembly {
|
||||
pub fn start_transition(
|
||||
&mut self,
|
||||
mode_keeping: bool,
|
||||
target: AssemblyMode,
|
||||
target: Mode,
|
||||
tc_id: Option<CcsdsPacketIdAndPsc>,
|
||||
) {
|
||||
self.mode_keeping_transition = mode_keeping;
|
||||
@@ -304,7 +304,7 @@ impl Assembly {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn mode(&self) -> AssemblyMode {
|
||||
pub fn mode(&self) -> Mode {
|
||||
self.mode_helper.current
|
||||
}
|
||||
|
||||
@@ -322,8 +322,8 @@ mod tests {
|
||||
use arbitrary_int::u11;
|
||||
use models::{
|
||||
Apid, Message, MessageType, TcHeader,
|
||||
acs::mgm_assembly,
|
||||
ccsds::{CcsdsTcPacketOwned, CcsdsTmPacketOwned},
|
||||
mgm_assembly,
|
||||
};
|
||||
use satrs::spacepackets::SpacePacketHeader;
|
||||
|
||||
@@ -331,9 +331,9 @@ mod tests {
|
||||
|
||||
pub struct Testbench {
|
||||
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],
|
||||
subsystem_report_rx: mpsc::Receiver<response::ModeResponse>,
|
||||
mgm_request_rx: [mpsc::Receiver<models::acs::mgm::request::ModeRequest>; 2],
|
||||
mgm_report_tx: [mpsc::SyncSender<models::acs::mgm::response::ModeResponse>; 2],
|
||||
tc_tx: mpsc::SyncSender<CcsdsTcPacketOwned>,
|
||||
tm_rx: mpsc::Receiver<CcsdsTmPacketOwned>,
|
||||
assembly: Assembly,
|
||||
@@ -396,7 +396,7 @@ mod tests {
|
||||
}
|
||||
|
||||
pub fn create_request_tc(
|
||||
request: models::mgm_assembly::request::Request,
|
||||
request: models::acs::mgm_assembly::request::Request,
|
||||
) -> models::ccsds::CcsdsTcPacketOwned {
|
||||
models::ccsds::CcsdsTcPacketOwned::new_with_request(
|
||||
SpacePacketHeader::new_from_apid(u11::new(Apid::Acs as u16)),
|
||||
@@ -411,7 +411,7 @@ mod tests {
|
||||
tb.assert_all_queues_empty();
|
||||
tb.assembly.periodic_operation();
|
||||
tb.assert_all_queues_empty();
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::NoModeKeeping);
|
||||
assert_eq!(tb.assembly.mode(), Mode::NoModeKeeping);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -419,7 +419,7 @@ mod tests {
|
||||
let mut tb = Testbench::new();
|
||||
tb.tc_tx
|
||||
.send(create_request_tc(mgm_assembly::request::Request::Mode(
|
||||
request::ModeRequest::SetMode(AssemblyMode::Device(DeviceMode::Normal)),
|
||||
request::ModeRequest::SetMode(Mode::Device(DeviceMode::Normal)),
|
||||
)))
|
||||
.unwrap();
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -429,13 +429,13 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
@@ -443,7 +443,7 @@ mod tests {
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal));
|
||||
assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal));
|
||||
|
||||
let response = tb.tm_rx.try_recv().unwrap();
|
||||
assert_eq!(response.tm_header.sender_id, Assembly::ID);
|
||||
@@ -456,7 +456,7 @@ mod tests {
|
||||
fn test_parent_commanded_transition() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(Mode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -467,13 +467,13 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
@@ -481,12 +481,12 @@ mod tests {
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal));
|
||||
assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal));
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
response::ModeResponse::Mode(Mode::Device(DeviceMode::Normal))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -494,7 +494,7 @@ mod tests {
|
||||
fn test_one_mgm_is_sufficient() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(Mode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -505,28 +505,30 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// One device is sufficient.
|
||||
tb.mgm_report_tx[0]
|
||||
.send(models::mgm::response::ModeResponse::Mode(
|
||||
.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
tb.mgm_report_tx[1]
|
||||
.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Off,
|
||||
))
|
||||
.unwrap();
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal));
|
||||
assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal));
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
response::ModeResponse::Mode(Mode::Device(DeviceMode::Normal))
|
||||
);
|
||||
}
|
||||
|
||||
@@ -534,7 +536,7 @@ mod tests {
|
||||
fn test_mode_commanding_fails() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(Mode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -545,24 +547,26 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Off,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::NoModeKeeping);
|
||||
assert_eq!(tb.assembly.mode(), Mode::NoModeKeeping);
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::WrongMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
response::ModeResponse::WrongMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
);
|
||||
}
|
||||
|
||||
@@ -570,7 +574,7 @@ mod tests {
|
||||
fn test_mode_keeping_fails() {
|
||||
let mut tb = Testbench::new();
|
||||
tb.subsystem_req_tx
|
||||
.send(request::ModeRequest::SetMode(AssemblyMode::Device(
|
||||
.send(request::ModeRequest::SetMode(Mode::Device(
|
||||
DeviceMode::Normal,
|
||||
)))
|
||||
.unwrap();
|
||||
@@ -581,13 +585,13 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Confirm the mode is set.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Normal,
|
||||
))
|
||||
.unwrap();
|
||||
@@ -595,17 +599,19 @@ mod tests {
|
||||
|
||||
tb.assembly.periodic_operation();
|
||||
assert!(!tb.assembly.mode_transition_active());
|
||||
assert_eq!(tb.assembly.mode(), AssemblyMode::Device(DeviceMode::Normal));
|
||||
assert_eq!(tb.assembly.mode(), Mode::Device(DeviceMode::Normal));
|
||||
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::Mode(AssemblyMode::Device(DeviceMode::Normal))
|
||||
response::ModeResponse::Mode(Mode::Device(DeviceMode::Normal))
|
||||
);
|
||||
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Off,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
// This should start mode keeping.
|
||||
tb.assembly.periodic_operation();
|
||||
@@ -615,20 +621,22 @@ mod tests {
|
||||
let request = rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
request,
|
||||
models::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
models::acs::mgm::request::ModeRequest::SetMode(DeviceMode::Normal)
|
||||
);
|
||||
}
|
||||
|
||||
// Let the mode keeping fail.
|
||||
for tx in tb.mgm_report_tx.iter() {
|
||||
tx.send(models::mgm::response::ModeResponse::Mode(DeviceMode::Off))
|
||||
.unwrap();
|
||||
tx.send(models::acs::mgm::response::ModeResponse::Mode(
|
||||
DeviceMode::Off,
|
||||
))
|
||||
.unwrap();
|
||||
}
|
||||
tb.assembly.periodic_operation();
|
||||
let report = tb.subsystem_report_rx.try_recv().unwrap();
|
||||
assert_eq!(
|
||||
report,
|
||||
response::ModeReport::CanNotKeepMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
response::ModeResponse::CanNotKeepMode([Some(DeviceMode::Off), Some(DeviceMode::Off)])
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
pub mod ctrl;
|
||||
|
||||
pub mod mgm;
|
||||
pub mod mgm_assembly;
|
||||
|
||||
pub mod mgt;
|
||||
pub mod subsystem;
|
||||
|
||||
@@ -1 +1,282 @@
|
||||
// TODO: Write subsystem
|
||||
#![allow(dead_code)]
|
||||
use std::{
|
||||
sync::mpsc::{self, Receiver, SyncSender},
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use models::{
|
||||
ComponentId,
|
||||
acs::subsystem::{Mode, response},
|
||||
};
|
||||
use satrs::{
|
||||
mode_tree::{ModeStoreProvider, ModeStoreVec, SequenceModeTables, TargetModeTables},
|
||||
spacepackets::CcsdsPacketIdAndPsc,
|
||||
subsystem::SubsystemCommandingHelper,
|
||||
};
|
||||
use satrs_example::{ModeHelper, TmtcQueues};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TransitionInfo {
|
||||
check_mode_reached: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TransitionState {
|
||||
#[default]
|
||||
Idle,
|
||||
AwaitingReplies,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ChildModes {
|
||||
mgm_assembly_mode: models::acs::mgm_assembly::Mode,
|
||||
mgt_mode: models::acs::mgt::Mode,
|
||||
controller_mode: models::acs::ctrl::Mode,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TransitionCommands {
|
||||
mgm_assembly_mode: Option<(models::acs::mgm_assembly::Mode, TransitionInfo)>,
|
||||
mgt_mode: Option<(models::acs::mgt::Mode, TransitionInfo)>,
|
||||
controller_mode: Option<(models::acs::ctrl::Mode, TransitionInfo)>,
|
||||
}
|
||||
|
||||
const OFF_SEQUENCE: [TransitionCommands; 2] = [
|
||||
TransitionCommands {
|
||||
mgm_assembly_mode: None,
|
||||
mgt_mode: None,
|
||||
controller_mode: Some((
|
||||
models::acs::ctrl::Mode::Passive,
|
||||
TransitionInfo {
|
||||
check_mode_reached: true,
|
||||
},
|
||||
)),
|
||||
},
|
||||
TransitionCommands {
|
||||
mgm_assembly_mode: Some((
|
||||
models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Off),
|
||||
TransitionInfo {
|
||||
check_mode_reached: false,
|
||||
},
|
||||
)),
|
||||
mgt_mode: Some((
|
||||
models::acs::mgt::Mode::Off,
|
||||
TransitionInfo {
|
||||
check_mode_reached: false,
|
||||
},
|
||||
)),
|
||||
controller_mode: None,
|
||||
},
|
||||
];
|
||||
|
||||
const SAFE_SEQUENCE: [TransitionCommands; 2] = [
|
||||
TransitionCommands {
|
||||
mgm_assembly_mode: Some((
|
||||
models::acs::mgm_assembly::Mode::Device(models::DeviceMode::Normal),
|
||||
TransitionInfo {
|
||||
check_mode_reached: false,
|
||||
},
|
||||
)),
|
||||
mgt_mode: Some((
|
||||
models::acs::mgt::Mode::Normal,
|
||||
TransitionInfo {
|
||||
check_mode_reached: false,
|
||||
},
|
||||
)),
|
||||
controller_mode: None,
|
||||
},
|
||||
TransitionCommands {
|
||||
mgm_assembly_mode: None,
|
||||
mgt_mode: None,
|
||||
controller_mode: Some((
|
||||
models::acs::ctrl::Mode::Safe,
|
||||
TransitionInfo {
|
||||
check_mode_reached: false,
|
||||
},
|
||||
)),
|
||||
},
|
||||
];
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModeRequestSenders {
|
||||
pub mode_request_ctrl: SyncSender<models::acs::ctrl::request::ModeRequest>,
|
||||
pub mode_request_assy: SyncSender<models::acs::mgm_assembly::request::ModeRequest>,
|
||||
pub mode_request_mgt: SyncSender<models::acs::mgt::request::ModeRequest>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ModeReportReceivers {
|
||||
pub mode_response_ctrl: Receiver<models::acs::ctrl::response::ModeReport>,
|
||||
pub mode_response_assy: Receiver<models::acs::mgm_assembly::response::ModeResponse>,
|
||||
pub mode_response_mgt: Receiver<models::acs::mgt::response::ModeReport>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Subsystem {
|
||||
mode_helper: ModeHelper<models::acs::subsystem::Mode, TransitionState>,
|
||||
transition_step: usize,
|
||||
current_child_modes: Option<ChildModes>,
|
||||
mode_request_senders: ModeRequestSenders,
|
||||
mode_report_receivers: ModeReportReceivers,
|
||||
tmtc_queues: TmtcQueues,
|
||||
subsystem_helper: SubsystemCommandingHelper,
|
||||
}
|
||||
|
||||
impl Subsystem {
|
||||
pub const ID: ComponentId = ComponentId::AcsSubsystem;
|
||||
|
||||
pub fn new(
|
||||
mode_request_senders: ModeRequestSenders,
|
||||
mode_report_receivers: ModeReportReceivers,
|
||||
tmtc_queues: TmtcQueues,
|
||||
) -> Self {
|
||||
let mut mode_store_vec = ModeStoreVec::default();
|
||||
mode_store_vec
|
||||
.add_component(
|
||||
ComponentId::AcsMgmAssembly as satrs::ComponentId,
|
||||
models::acs::mgm_assembly::Mode::NoModeKeeping.into(),
|
||||
)
|
||||
.unwrap();
|
||||
mode_store_vec
|
||||
.add_component(
|
||||
ComponentId::AcsController as satrs::ComponentId,
|
||||
models::acs::ctrl::Mode::Passive.into(),
|
||||
)
|
||||
.unwrap();
|
||||
mode_store_vec
|
||||
.add_component(
|
||||
ComponentId::AcsMgt as satrs::ComponentId,
|
||||
models::acs::mgt::Mode::Off.into(),
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
let target_tables = TargetModeTables::default();
|
||||
|
||||
let sequence_tables = SequenceModeTables::default();
|
||||
|
||||
Self {
|
||||
mode_helper: ModeHelper::new(
|
||||
models::acs::subsystem::Mode::Off,
|
||||
Duration::from_millis(2000),
|
||||
),
|
||||
current_child_modes: None,
|
||||
mode_request_senders,
|
||||
mode_report_receivers,
|
||||
tmtc_queues,
|
||||
transition_step: 0,
|
||||
subsystem_helper: SubsystemCommandingHelper::new(
|
||||
mode_store_vec,
|
||||
target_tables,
|
||||
sequence_tables,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn periodic_operation(&mut self) {
|
||||
self.handle_telecommands();
|
||||
}
|
||||
|
||||
pub fn handle_telecommands(&mut self) {
|
||||
loop {
|
||||
match self.tmtc_queues.tc_rx.try_recv() {
|
||||
Ok(packet) => {
|
||||
let tc_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(&packet.sp_header);
|
||||
match postcard::from_bytes::<models::acs::subsystem::request::Request>(
|
||||
&packet.payload,
|
||||
) {
|
||||
Ok(request) => match request {
|
||||
models::acs::subsystem::request::Request::Ping => {
|
||||
self.send_telemetry(Some(tc_id), response::Response::Ok)
|
||||
}
|
||||
models::acs::subsystem::request::Request::Mode(mode_request) => {
|
||||
self.handle_mode_request(mode_request);
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
log::warn!("failed to deserialize request: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(e) => match e {
|
||||
mpsc::TryRecvError::Empty => break,
|
||||
mpsc::TryRecvError::Disconnected => log::warn!("packet sender disconnected"),
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn transition_sequence_for_mode(mode: Mode) -> &'static [TransitionCommands] {
|
||||
match mode {
|
||||
Mode::Off => &OFF_SEQUENCE,
|
||||
Mode::Safe => &SAFE_SEQUENCE,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn execute_transition_step(&mut self, step: &TransitionCommands) {
|
||||
if let Some((target_mode, _info)) = &step.mgm_assembly_mode {
|
||||
self.mode_request_senders
|
||||
.mode_request_assy
|
||||
.send(models::acs::mgm_assembly::request::ModeRequest::SetMode(
|
||||
*target_mode,
|
||||
))
|
||||
.expect("failed to send mode request to MGM assembly");
|
||||
}
|
||||
if let Some((target_mode, _info)) = &step.mgt_mode {
|
||||
self.mode_request_senders
|
||||
.mode_request_mgt
|
||||
.send(models::acs::mgt::request::ModeRequest::SetMode(
|
||||
*target_mode,
|
||||
))
|
||||
.expect("failed to send mode request to MGM assembly");
|
||||
}
|
||||
if let Some((target_mode, _info)) = &step.controller_mode {
|
||||
self.mode_request_senders
|
||||
.mode_request_ctrl
|
||||
.send(models::acs::ctrl::request::ModeRequest::SetMode(
|
||||
*target_mode,
|
||||
))
|
||||
.expect("failed to send mode request to MGM assembly");
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_mode_request(
|
||||
&mut self,
|
||||
mode_request: models::acs::subsystem::request::ModeRequest,
|
||||
) {
|
||||
match mode_request {
|
||||
models::acs::subsystem::request::ModeRequest::SetMode(target_mode) => {
|
||||
self.mode_helper.start(target_mode);
|
||||
self.transition_step = 0;
|
||||
let first_step = Self::transition_sequence_for_mode(target_mode)
|
||||
.get(self.transition_step)
|
||||
.expect("empty transition table");
|
||||
self.execute_transition_step(first_step);
|
||||
}
|
||||
models::acs::subsystem::request::ModeRequest::ReadMode => {
|
||||
self.send_telemetry(
|
||||
None,
|
||||
response::Response::Mode(response::ModeResponse::Mode(
|
||||
self.mode_helper.current,
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_telemetry(
|
||||
&self,
|
||||
tc_id: Option<CcsdsPacketIdAndPsc>,
|
||||
response: models::acs::subsystem::response::Response,
|
||||
) {
|
||||
match crate::ccsds::pack_ccsds_tm_packet_for_now(Self::ID, tc_id, &response) {
|
||||
Ok(packet) => {
|
||||
if let Err(e) = self.tmtc_queues.tm_tx.send(packet) {
|
||||
log::warn!("failed to send TM packet: {}", e);
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
log::warn!("failed to pack TM packet: {}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -536,7 +536,6 @@ mod tests {
|
||||
pcdu::{SwitchMapBinary, SwitchStateBinary},
|
||||
};
|
||||
use satrs::{
|
||||
mode::{ModeReply, ModeRequest},
|
||||
request::{GenericMessage, MessageMetadata},
|
||||
spacepackets::SpacePacketHeader,
|
||||
};
|
||||
@@ -590,8 +589,8 @@ mod tests {
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct PcduTestbench {
|
||||
pub mode_request_tx: mpsc::SyncSender<GenericMessage<ModeRequest>>,
|
||||
pub mode_reply_rx_to_parent: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||
pub mode_request_tx: mpsc::SyncSender<models::pcdu::request::Request>,
|
||||
pub mode_reply_rx_to_parent: mpsc::Receiver<models::pcdu::response::Response>,
|
||||
pub tc_tx: mpsc::SyncSender<CcsdsTcPacketOwned>,
|
||||
pub tm_rx: mpsc::Receiver<CcsdsTmPacketOwned>,
|
||||
pub switch_request_tx: mpsc::Sender<GenericMessage<SwitchRequest>>,
|
||||
|
||||
@@ -95,6 +95,7 @@ impl HkHelperSingleSet {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct TmtcQueues {
|
||||
pub tc_rx: mpsc::Receiver<CcsdsTcPacketOwned>,
|
||||
pub tm_tx: mpsc::SyncSender<CcsdsTmPacketOwned>,
|
||||
|
||||
+30
-13
@@ -23,16 +23,13 @@ use logger::setup_logger;
|
||||
use models::{ComponentId, DeviceMode};
|
||||
use satrs::{
|
||||
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
|
||||
mode::{Mode, ModeAndSubmode, ModeRequest},
|
||||
pus::HandlingStatus,
|
||||
request::{GenericMessage, MessageMetadata},
|
||||
spacepackets::time::cds::CdsTime,
|
||||
};
|
||||
use satrs_example::{
|
||||
TmtcQueues,
|
||||
config::{
|
||||
OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
|
||||
components::NO_SENDER,
|
||||
tasks::{FREQ_MS_AOCS, FREQ_MS_CONTROLLER, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS},
|
||||
},
|
||||
};
|
||||
@@ -40,7 +37,7 @@ use tmtc::sender::TmTcSender;
|
||||
use tmtc::{tc_source::TcSourceTask, tm_sink::TmSink};
|
||||
|
||||
use crate::{
|
||||
acs::{mgm, mgm_assembly},
|
||||
acs::{mgm, mgm_assembly, subsystem},
|
||||
control::Controller,
|
||||
eps::pcdu::SwitchSet,
|
||||
event_manager::EventManager,
|
||||
@@ -80,12 +77,19 @@ fn main() {
|
||||
let (mgm_0_handler_tc_tx, mgm_0_handler_tc_rx) = mpsc::sync_channel(10);
|
||||
let (mgm_1_handler_tc_tx, mgm_1_handler_tc_rx) = mpsc::sync_channel(10);
|
||||
let (mgm_assembly_tc_tx, mgm_assembly_tc_rx) = mpsc::sync_channel(10);
|
||||
let (acs_subsystem_tc_tx, acs_subsystem_tc_rx) = mpsc::sync_channel(10);
|
||||
let (pcdu_handler_tc_tx, pcdu_handler_tc_rx) = mpsc::sync_channel(30);
|
||||
let (controller_tc_tx, controller_tc_rx) = mpsc::sync_channel(10);
|
||||
|
||||
let (mgt_request_tx, _mgt_request_rx) = mpsc::sync_channel(5);
|
||||
let (_mgt_report_tx, mgt_report_rx) = mpsc::sync_channel(5);
|
||||
|
||||
let (acs_ctrl_request_tx, _acs_ctrl_request_rx) = mpsc::sync_channel(5);
|
||||
let (_acs_ctrl_response_tx, acs_ctrl_response_rx) = mpsc::sync_channel(5);
|
||||
|
||||
// These message handles need to go into the MGM assembly and ACS subsystem.
|
||||
let (_mgm_assembly_request_tx, mgm_assembly_request_rx) = mpsc::sync_channel(5);
|
||||
let (mgm_assembly_report_tx, _mgm_assembly_report_rx) = mpsc::sync_channel(5);
|
||||
let (mgm_assembly_request_tx, mgm_assembly_request_rx) = mpsc::sync_channel(5);
|
||||
let (mgm_assembly_report_tx, mgm_assembly_report_rx) = mpsc::sync_channel(5);
|
||||
|
||||
// These message handles need to go into the MGM assembly and MGM devices.
|
||||
let (mgm_0_mode_request_tx, mgm_0_mode_request_rx) = mpsc::sync_channel(5);
|
||||
@@ -110,6 +114,7 @@ fn main() {
|
||||
tc_source.add_target(ComponentId::AcsMgm0, mgm_0_handler_tc_tx);
|
||||
tc_source.add_target(ComponentId::AcsMgm1, mgm_1_handler_tc_tx);
|
||||
tc_source.add_target(ComponentId::AcsMgmAssembly, mgm_assembly_tc_tx);
|
||||
tc_source.add_target(ComponentId::AcsSubsystem, acs_subsystem_tc_tx);
|
||||
|
||||
let tc_sender = TmTcSender::Normal(tc_source_tx.clone());
|
||||
let udp_tm_handler = UdpTmHandlerWithChannel {
|
||||
@@ -221,6 +226,23 @@ fn main() {
|
||||
Duration::from_millis(2000),
|
||||
);
|
||||
|
||||
let mut acs_subsystem = subsystem::Subsystem::new(
|
||||
subsystem::ModeRequestSenders {
|
||||
mode_request_ctrl: acs_ctrl_request_tx,
|
||||
mode_request_assy: mgm_assembly_request_tx,
|
||||
mode_request_mgt: mgt_request_tx,
|
||||
},
|
||||
subsystem::ModeReportReceivers {
|
||||
mode_response_ctrl: acs_ctrl_response_rx,
|
||||
mode_response_assy: mgm_assembly_report_rx,
|
||||
mode_response_mgt: mgt_report_rx,
|
||||
},
|
||||
TmtcQueues {
|
||||
tc_rx: acs_subsystem_tc_rx,
|
||||
tm_tx: tm_sink_tx.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
|
||||
sim_client.add_reply_recipient(satrs_minisim::SimComponent::Pcdu, pcdu_sim_reply_tx);
|
||||
SerialSimInterfaceWrapper::Sim(SerialInterfaceToSim::new(
|
||||
@@ -241,13 +263,7 @@ fn main() {
|
||||
|
||||
// The PCDU is a critical component which should be in normal mode immediately.
|
||||
pcdu_handler_mode_tx
|
||||
.send(GenericMessage::new(
|
||||
MessageMetadata::new(0, NO_SENDER),
|
||||
ModeRequest::SetMode {
|
||||
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as Mode, 0),
|
||||
forced: false,
|
||||
},
|
||||
))
|
||||
.send(models::pcdu::request::Request::Mode(DeviceMode::Normal))
|
||||
.expect("sending initial mode request failed");
|
||||
|
||||
info!("Starting TMTC and UDP task");
|
||||
@@ -324,6 +340,7 @@ fn main() {
|
||||
mgm_0_handler.periodic_operation();
|
||||
mgm_1_handler.periodic_operation();
|
||||
mgm_assembly.periodic_operation();
|
||||
acs_subsystem.periodic_operation();
|
||||
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user