Continue update
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
Some checks failed
Rust/sat-rs/pipeline/pr-main There was a failure building this commit
This commit is contained in:
parent
5c1acfe912
commit
bc04275763
@ -18,14 +18,15 @@ csv = "1"
|
|||||||
num_enum = "0.7"
|
num_enum = "0.7"
|
||||||
thiserror = "1"
|
thiserror = "1"
|
||||||
derive-new = "0.5"
|
derive-new = "0.5"
|
||||||
|
serde = { version = "1", features = ["derive"] }
|
||||||
|
serde_json = "1"
|
||||||
|
|
||||||
[dependencies.satrs]
|
[dependencies.satrs]
|
||||||
# version = "0.2.0-rc.0"
|
|
||||||
path = "../satrs"
|
path = "../satrs"
|
||||||
features = ["test_util"]
|
features = ["test_util"]
|
||||||
|
|
||||||
[dependencies.satrs-mib]
|
[dependencies.satrs-mib]
|
||||||
# version = "0.1.1"
|
version = "0.1.1"
|
||||||
path = "../satrs-mib"
|
path = "../satrs-mib"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -1,44 +1,123 @@
|
|||||||
// TODO: Remove this at a later stage.
|
// TODO: Remove this at a later stage.
|
||||||
#![allow(dead_code)]
|
#![allow(dead_code)]
|
||||||
|
use derive_new::new;
|
||||||
|
use satrs::hk::HkRequestVariant;
|
||||||
|
use satrs::spacepackets::ecss::hk;
|
||||||
|
use satrs::spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
||||||
|
use satrs::spacepackets::SpHeader;
|
||||||
|
use satrs_example::TimeStampHelper;
|
||||||
use std::sync::mpsc::{self};
|
use std::sync::mpsc::{self};
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
use satrs::mode::{ModeAndSubmode, ModeProvider, ModeReply, ModeRequest, ModeRequestHandler};
|
use satrs::mode::{ModeAndSubmode, ModeProvider, ModeReply, ModeRequest, ModeRequestHandler};
|
||||||
use satrs::pus::EcssTmSenderCore;
|
use satrs::pus::{EcssTmSenderCore, PusTmVariant};
|
||||||
use satrs::request::GenericMessage;
|
use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
|
use satrs_example::config::components::PUS_MODE_SERVICE;
|
||||||
|
|
||||||
use crate::pus::hk::HkReply;
|
use crate::pus::hk::{HkReply, HkReplyVariant};
|
||||||
use crate::requests::CompositeRequest;
|
use crate::requests::CompositeRequest;
|
||||||
|
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
pub trait SpiInterface {
|
pub trait SpiInterface {
|
||||||
type Error;
|
type Error;
|
||||||
fn transfer(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
|
fn transfer(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Default)]
|
||||||
|
pub struct SpiDummyInterface {}
|
||||||
|
|
||||||
|
impl SpiInterface for SpiDummyInterface {
|
||||||
|
type Error = ();
|
||||||
|
|
||||||
|
fn transfer(&mut self, _data: &mut [u8]) -> Result<(), Self::Error> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default, Debug, Copy, Clone, Serialize, Deserialize)]
|
||||||
pub struct MgmData {
|
pub struct MgmData {
|
||||||
pub x: f32,
|
pub x: f32,
|
||||||
pub y: f32,
|
pub y: f32,
|
||||||
pub z: f32,
|
pub z: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(new)]
|
||||||
pub struct MgmHandler<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> {
|
pub struct MgmHandler<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> {
|
||||||
id: ComponentId,
|
id: UniqueApidTargetId,
|
||||||
dev_str: &'static str,
|
dev_str: &'static str,
|
||||||
mode_request_receiver: mpsc::Receiver<GenericMessage<ModeRequest>>,
|
mode_request_receiver: mpsc::Receiver<GenericMessage<ModeRequest>>,
|
||||||
|
composite_request_receiver: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
mode_reply_sender_to_pus: mpsc::Sender<GenericMessage<ModeReply>>,
|
mode_reply_sender_to_pus: mpsc::Sender<GenericMessage<ModeReply>>,
|
||||||
mode_reply_sender_to_parent: mpsc::Sender<GenericMessage<ModeReply>>,
|
mode_reply_sender_to_parent: mpsc::Sender<GenericMessage<ModeReply>>,
|
||||||
composite_request_receiver: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
|
||||||
hk_reply_sender: mpsc::Sender<GenericMessage<HkReply>>,
|
hk_reply_sender: mpsc::Sender<GenericMessage<HkReply>>,
|
||||||
hk_tm_sender: TmSender,
|
hk_tm_sender: TmSender,
|
||||||
mode: ModeAndSubmode,
|
|
||||||
spi_interface: ComInterface,
|
spi_interface: ComInterface,
|
||||||
shared_mgm_set: Arc<Mutex<MgmData>>,
|
shared_mgm_set: Arc<Mutex<MgmData>>,
|
||||||
|
#[new(value = "ModeAndSubmode::new(satrs_example::DeviceMode::Off as u32, 0)")]
|
||||||
|
mode: ModeAndSubmode,
|
||||||
|
#[new(default)]
|
||||||
|
stamp_helper: TimeStampHelper,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> MgmHandler<ComInterface, TmSender> {
|
impl<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> MgmHandler<ComInterface, TmSender> {
|
||||||
pub fn perform_operation(&mut self) {}
|
pub fn periodic_operation(&mut self) {
|
||||||
|
self.stamp_helper.update_from_now();
|
||||||
|
// Handle messages.
|
||||||
|
match self.composite_request_receiver.try_recv() {
|
||||||
|
Ok(ref msg) => match &msg.message {
|
||||||
|
CompositeRequest::Hk(hk_req) => match hk_req.variant {
|
||||||
|
HkRequestVariant::OneShot => {
|
||||||
|
self.hk_reply_sender
|
||||||
|
.send(GenericMessage::new(
|
||||||
|
msg.requestor_info,
|
||||||
|
HkReply::new(hk_req.unique_id, HkReplyVariant::Ack),
|
||||||
|
))
|
||||||
|
.expect("failed to send HK reply");
|
||||||
|
let mut sp_header = SpHeader::tm_unseg(self.id.apid, 0, 0).unwrap();
|
||||||
|
let sec_header = PusTmSecondaryHeader::new(
|
||||||
|
3,
|
||||||
|
hk::Subservice::TmHkPacket as u8,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
Some(self.stamp_helper.stamp()),
|
||||||
|
);
|
||||||
|
// Let's serialize it as JSON for now.. This is a lot simpler than binary
|
||||||
|
// serialization.
|
||||||
|
let mgm_data_serialized =
|
||||||
|
serde_json::to_vec(&*self.shared_mgm_set.lock().unwrap()).unwrap();
|
||||||
|
let hk_tm = PusTmCreator::new(
|
||||||
|
&mut sp_header,
|
||||||
|
sec_header,
|
||||||
|
&mgm_data_serialized,
|
||||||
|
true,
|
||||||
|
);
|
||||||
|
self.hk_tm_sender
|
||||||
|
.send_tm(self.id.id(), PusTmVariant::Direct(hk_tm))
|
||||||
|
.expect("failed to send HK TM");
|
||||||
|
}
|
||||||
|
HkRequestVariant::EnablePeriodic => todo!(),
|
||||||
|
HkRequestVariant::DisablePeriodic => todo!(),
|
||||||
|
HkRequestVariant::ModifyCollectionInterval(_) => todo!(),
|
||||||
|
},
|
||||||
|
// This object does not have actions (yet).. Still send back completion failure
|
||||||
|
// reply.
|
||||||
|
CompositeRequest::Action(action_req) => {}
|
||||||
|
},
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
match self.mode_request_receiver.try_recv() {
|
||||||
|
Ok(msg) => match msg.message {
|
||||||
|
ModeRequest::SetMode(_) => todo!(),
|
||||||
|
ModeRequest::ReadMode => todo!(),
|
||||||
|
ModeRequest::AnnounceMode => todo!(),
|
||||||
|
ModeRequest::AnnounceModeRecursive => todo!(),
|
||||||
|
ModeRequest::ModeInfo(_) => todo!(),
|
||||||
|
},
|
||||||
|
Err(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> ModeProvider
|
impl<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> ModeProvider
|
||||||
@ -54,23 +133,37 @@ impl<ComInterface: SpiInterface, TmSender: EcssTmSenderCore> ModeRequestHandler
|
|||||||
{
|
{
|
||||||
fn start_transition(
|
fn start_transition(
|
||||||
&mut self,
|
&mut self,
|
||||||
request_id: satrs::request::RequestId,
|
requestor: MessageMetadata,
|
||||||
sender_id: ComponentId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
) -> Result<(), satrs::mode::ModeError> {
|
) -> Result<(), satrs::mode::ModeError> {
|
||||||
todo!()
|
self.mode = mode_and_submode;
|
||||||
|
self.handle_mode_reached(Some(requestor))?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn announce_mode(
|
fn announce_mode(&self, _requestor_info: MessageMetadata, _recursive: bool) {
|
||||||
&self,
|
|
||||||
request_id: satrs::request::RequestId,
|
|
||||||
sender_id: satrs::ComponentId,
|
|
||||||
recursive: bool,
|
|
||||||
) {
|
|
||||||
log::info!("{} announcing mode: {:?}", self.dev_str, self.mode);
|
log::info!("{} announcing mode: {:?}", self.dev_str, self.mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mode_reached(&mut self) -> Result<(), satrs::queue::GenericTargetedMessagingError> {
|
fn handle_mode_reached(
|
||||||
todo!()
|
&mut self,
|
||||||
|
requestor: Option<MessageMetadata>,
|
||||||
|
) -> Result<(), satrs::queue::GenericTargetedMessagingError> {
|
||||||
|
if let Some(requestor) = requestor {
|
||||||
|
if requestor.sender_id() == PUS_MODE_SERVICE.raw() {
|
||||||
|
// self.mode_reply_sender_to_pus.send(
|
||||||
|
//GenericMessage::new(requestor.request_id, requestor.sender_id, ModeReply::ModeReply(self.mode))
|
||||||
|
// )?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_mode_reply(
|
||||||
|
&self,
|
||||||
|
_requestor: MessageMetadata,
|
||||||
|
_reply: ModeReply,
|
||||||
|
) -> Result<(), satrs::queue::GenericTargetedMessagingError> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
mod mgm;
|
pub mod mgm;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
pub struct AcsTask<VerificationReporter: VerificationReportingProvider> {
|
pub struct AcsTask<VerificationReporter: VerificationReportingProvider> {
|
||||||
timestamp: [u8; 7],
|
timestamp: [u8; 7],
|
||||||
time_provider: TimeProvider<DaysLen16Bits>,
|
time_provider: CdsTime<DaysLen16Bits>,
|
||||||
verif_reporter: VerificationReporter,
|
verif_reporter: VerificationReporter,
|
||||||
tm_sender: Box<dyn EcssTmSender>,
|
tm_sender: Box<dyn EcssTmSender>,
|
||||||
request_rx: mpsc::Receiver<RequestWithToken>,
|
request_rx: mpsc::Receiver<RequestWithToken>,
|
||||||
@ -17,7 +17,7 @@ impl<VerificationReporter: VerificationReportingProvider> AcsTask<VerificationRe
|
|||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
timestamp: [0; 7],
|
timestamp: [0; 7],
|
||||||
time_provider: TimeProvider::new_with_u16_days(0, 0),
|
time_provider: CdsTime::new_with_u16_days(0, 0),
|
||||||
verif_reporter,
|
verif_reporter,
|
||||||
tm_sender: Box::new(tm_sender),
|
tm_sender: Box::new(tm_sender),
|
||||||
request_rx,
|
request_rx,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use satrs::pus::ReceivesEcssPusTc;
|
use satrs::pus::ReceivesEcssPusTc;
|
||||||
use satrs::spacepackets::{CcsdsPacket, SpHeader};
|
use satrs::spacepackets::{CcsdsPacket, SpHeader};
|
||||||
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
|
use satrs::tmtc::{CcsdsPacketHandler, ReceivesCcsdsTc};
|
||||||
use satrs_example::config::PUS_APID;
|
use satrs_example::config::components::Apid;
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct CcsdsReceiver<
|
pub struct CcsdsReceiver<
|
||||||
@ -19,7 +19,12 @@ impl<
|
|||||||
type Error = E;
|
type Error = E;
|
||||||
|
|
||||||
fn valid_apids(&self) -> &'static [u16] {
|
fn valid_apids(&self) -> &'static [u16] {
|
||||||
&[PUS_APID]
|
&[
|
||||||
|
Apid::GenericPus as u16,
|
||||||
|
Apid::Acs as u16,
|
||||||
|
Apid::Sched as u16,
|
||||||
|
Apid::EventTm as u16,
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_known_apid(
|
fn handle_known_apid(
|
||||||
@ -27,7 +32,8 @@ impl<
|
|||||||
sp_header: &SpHeader,
|
sp_header: &SpHeader,
|
||||||
tc_raw: &[u8],
|
tc_raw: &[u8],
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
if sp_header.apid() == PUS_APID {
|
if sp_header.apid() == Apid::Cfdp as u16 {
|
||||||
|
} else {
|
||||||
return self.tc_source.pass_ccsds(sp_header, tc_raw);
|
return self.tc_source.pass_ccsds(sp_header, tc_raw);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -9,8 +9,6 @@ use satrs::{
|
|||||||
pool::{StaticMemoryPool, StaticPoolConfig},
|
pool::{StaticMemoryPool, StaticPoolConfig},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const PUS_APID: u16 = 0x02;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Debug, TryFromPrimitive, IntoPrimitive)]
|
#[derive(Copy, Clone, PartialEq, Eq, Debug, TryFromPrimitive, IntoPrimitive)]
|
||||||
#[repr(u8)]
|
#[repr(u8)]
|
||||||
pub enum CustomPusServiceId {
|
pub enum CustomPusServiceId {
|
||||||
@ -102,14 +100,51 @@ pub mod mode_err {
|
|||||||
pub const WRONG_MODE: ResultU16 = ResultU16::new(GroupId::Mode as u8, 0);
|
pub const WRONG_MODE: ResultU16 = ResultU16::new(GroupId::Mode as u8, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq)]
|
pub mod components {
|
||||||
pub enum ComponentIdList {
|
use satrs::request::UniqueApidTargetId;
|
||||||
PusVerification = 0,
|
|
||||||
EventManagement = 1,
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
PusTest = 2,
|
pub enum Apid {
|
||||||
PusAction = 3,
|
VerificationTm = 1,
|
||||||
PusSched = 4,
|
Sched = 2,
|
||||||
PusHk = 5,
|
EventTm = 3,
|
||||||
|
HkTm = 4,
|
||||||
|
GenericPus = 5,
|
||||||
|
Acs = 6,
|
||||||
|
Cfdp = 7,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Component IDs for components with the PUS APID.
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum PusId {
|
||||||
|
PusRouting = 0,
|
||||||
|
PusTest = 1,
|
||||||
|
PusAction = 2,
|
||||||
|
PusMode = 3,
|
||||||
|
PusHk = 4,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, PartialEq, Eq)]
|
||||||
|
pub enum AcsId {
|
||||||
|
Mgm0 = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
|
||||||
|
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::EventTm as u16, 0);
|
||||||
|
pub const PUS_ROUTING_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32);
|
||||||
|
pub const PUS_TEST_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusTest as u32);
|
||||||
|
pub const PUS_MODE_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusMode as u32);
|
||||||
|
pub const PUS_HK_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusHk as u32);
|
||||||
|
pub const PUS_SCHED_SERVICE: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::Sched as u16, 0);
|
||||||
|
pub const MGM_HANDLER_0: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod pool {
|
pub mod pool {
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
use std::sync::mpsc::{self};
|
use std::sync::mpsc::{self};
|
||||||
|
|
||||||
|
use crate::pus::create_verification_reporter;
|
||||||
|
use satrs::pus::verification::VerificationReporter;
|
||||||
|
use satrs::pus::EcssTmSenderCore;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
event_man::{
|
event_man::{
|
||||||
EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded,
|
EventManagerWithBoundedMpsc, EventSendProvider, EventU32SenderMpscBounded,
|
||||||
@ -12,44 +15,51 @@ use satrs::{
|
|||||||
DefaultPusEventU32Dispatcher, EventReporter, EventRequest, EventRequestWithToken,
|
DefaultPusEventU32Dispatcher, EventReporter, EventRequest, EventRequestWithToken,
|
||||||
},
|
},
|
||||||
verification::{TcStateStarted, VerificationReportingProvider, VerificationToken},
|
verification::{TcStateStarted, VerificationReportingProvider, VerificationToken},
|
||||||
EcssTmSender,
|
|
||||||
},
|
},
|
||||||
spacepackets::time::cds::{self, TimeProvider},
|
spacepackets::time::cds::CdsTime,
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
use satrs_example::config::{ComponentIdList, PUS_APID};
|
use satrs_example::config::components;
|
||||||
|
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
||||||
|
|
||||||
use crate::update_time;
|
use crate::update_time;
|
||||||
|
|
||||||
/// The PUS event handler subscribes for all events and converts them into ECSS PUS 5 event
|
/// The PUS event handler subscribes for all events and converts them into ECSS PUS 5 event
|
||||||
/// packets. It also handles the verification completion of PUS event service requests.
|
/// packets. It also handles the verification completion of PUS event service requests.
|
||||||
pub struct PusEventHandler<VerificationReporter: VerificationReportingProvider> {
|
pub struct PusEventHandler<TmSender: EcssTmSenderCore> {
|
||||||
|
id: ComponentId,
|
||||||
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
||||||
pus_event_dispatcher: DefaultPusEventU32Dispatcher<()>,
|
pus_event_dispatcher: DefaultPusEventU32Dispatcher<()>,
|
||||||
pus_event_man_rx: mpsc::Receiver<(EventU32, Option<Params>)>,
|
pus_event_man_rx: mpsc::Receiver<(EventU32, Option<Params>)>,
|
||||||
tm_sender: Box<dyn EcssTmSender>,
|
tm_sender: TmSender,
|
||||||
time_provider: TimeProvider,
|
time_provider: CdsTime,
|
||||||
timestamp: [u8; 7],
|
timestamp: [u8; 7],
|
||||||
verif_handler: VerificationReporter,
|
verif_handler: VerificationReporter,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<VerificationReporter> {
|
impl<TmSender: EcssTmSenderCore> PusEventHandler<TmSender> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: ComponentId,
|
||||||
|
tm_sender: TmSender,
|
||||||
verif_handler: VerificationReporter,
|
verif_handler: VerificationReporter,
|
||||||
event_manager: &mut EventManagerWithBoundedMpsc,
|
event_manager: &mut EventManagerWithBoundedMpsc,
|
||||||
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
||||||
tm_sender: impl EcssTmSender,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let event_queue_cap = 30;
|
let event_queue_cap = 30;
|
||||||
let (pus_event_man_tx, pus_event_man_rx) = mpsc::sync_channel(event_queue_cap);
|
let (pus_event_man_tx, pus_event_man_rx) = mpsc::sync_channel(event_queue_cap);
|
||||||
|
|
||||||
// All events sent to the manager are routed to the PUS event manager, which generates PUS event
|
// All events sent to the manager are routed to the PUS event manager, which generates PUS event
|
||||||
// telemetry for each event.
|
// telemetry for each event.
|
||||||
let event_reporter = EventReporter::new(PUS_APID, 128).unwrap();
|
let event_reporter = EventReporter::new(
|
||||||
|
PUS_EVENT_MANAGEMENT.raw(),
|
||||||
|
components::Apid::EventTm as u16,
|
||||||
|
128,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
let pus_event_dispatcher =
|
let pus_event_dispatcher =
|
||||||
DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter);
|
DefaultPusEventU32Dispatcher::new_with_default_backend(event_reporter);
|
||||||
let pus_event_man_send_provider = EventU32SenderMpscBounded::new(
|
let pus_event_man_send_provider = EventU32SenderMpscBounded::new(
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
PUS_EVENT_MANAGEMENT.raw(),
|
||||||
pus_event_man_tx,
|
pus_event_man_tx,
|
||||||
event_queue_cap,
|
event_queue_cap,
|
||||||
);
|
);
|
||||||
@ -58,13 +68,14 @@ impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<Verifi
|
|||||||
event_manager.add_sender(pus_event_man_send_provider);
|
event_manager.add_sender(pus_event_man_send_provider);
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
id,
|
||||||
event_request_rx,
|
event_request_rx,
|
||||||
pus_event_dispatcher,
|
pus_event_dispatcher,
|
||||||
pus_event_man_rx,
|
pus_event_man_rx,
|
||||||
time_provider: cds::TimeProvider::new_with_u16_days(0, 0),
|
time_provider: CdsTime::new_with_u16_days(0, 0),
|
||||||
timestamp: [0; 7],
|
timestamp: [0; 7],
|
||||||
verif_handler,
|
verif_handler,
|
||||||
tm_sender: Box::new(tm_sender),
|
tm_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,7 +86,7 @@ impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<Verifi
|
|||||||
.try_into()
|
.try_into()
|
||||||
.expect("expected start verification token");
|
.expect("expected start verification token");
|
||||||
self.verif_handler
|
self.verif_handler
|
||||||
.completion_success(started_token, timestamp)
|
.completion_success(self.id, &self.tm_sender, started_token, timestamp)
|
||||||
.expect("Sending completion success failed");
|
.expect("Sending completion success failed");
|
||||||
};
|
};
|
||||||
// handle event requests
|
// handle event requests
|
||||||
@ -104,12 +115,7 @@ impl<VerificationReporter: VerificationReportingProvider> PusEventHandler<Verifi
|
|||||||
if let Ok((event, _param)) = self.pus_event_man_rx.try_recv() {
|
if let Ok((event, _param)) = self.pus_event_man_rx.try_recv() {
|
||||||
update_time(&mut self.time_provider, &mut self.timestamp);
|
update_time(&mut self.time_provider, &mut self.timestamp);
|
||||||
self.pus_event_dispatcher
|
self.pus_event_dispatcher
|
||||||
.generate_pus_event_tm_generic(
|
.generate_pus_event_tm_generic(&mut self.tm_sender, &self.timestamp, event, None)
|
||||||
self.tm_sender.upcast_mut(),
|
|
||||||
&self.timestamp,
|
|
||||||
event,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.expect("Sending TM as event failed");
|
.expect("Sending TM as event failed");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,23 +157,23 @@ impl EventManagerWrapper {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct EventHandler<VerificationReporter: VerificationReportingProvider> {
|
pub struct EventHandler<TmSender: EcssTmSenderCore> {
|
||||||
pub event_man_wrapper: EventManagerWrapper,
|
pub event_man_wrapper: EventManagerWrapper,
|
||||||
pub pus_event_handler: PusEventHandler<VerificationReporter>,
|
pub pus_event_handler: PusEventHandler<TmSender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<VerificationReporter: VerificationReportingProvider> EventHandler<VerificationReporter> {
|
impl<TmSender: EcssTmSenderCore> EventHandler<TmSender> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tm_sender: impl EcssTmSender,
|
tm_sender: TmSender,
|
||||||
verif_handler: VerificationReporter,
|
|
||||||
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
event_request_rx: mpsc::Receiver<EventRequestWithToken>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut event_man_wrapper = EventManagerWrapper::new();
|
let mut event_man_wrapper = EventManagerWrapper::new();
|
||||||
let pus_event_handler = PusEventHandler::new(
|
let pus_event_handler = PusEventHandler::new(
|
||||||
verif_handler,
|
PUS_EVENT_MANAGEMENT.raw(),
|
||||||
|
tm_sender,
|
||||||
|
create_verification_reporter(PUS_EVENT_MANAGEMENT.apid),
|
||||||
event_man_wrapper.event_manager(),
|
event_man_wrapper.event_manager(),
|
||||||
event_request_rx,
|
event_request_rx,
|
||||||
tm_sender,
|
|
||||||
);
|
);
|
||||||
Self {
|
Self {
|
||||||
event_man_wrapper,
|
event_man_wrapper,
|
||||||
|
@ -1,27 +1,25 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
use satrs::hk::UniqueId;
|
||||||
|
use satrs::request::UniqueApidTargetId;
|
||||||
use satrs::spacepackets::ByteConversionError;
|
use satrs::spacepackets::ByteConversionError;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
|
||||||
pub enum AcsHkIds {
|
|
||||||
TestMgmSet = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, new, Copy, Clone)]
|
#[derive(Debug, new, Copy, Clone)]
|
||||||
pub struct HkUniqueId {
|
pub struct HkUniqueId {
|
||||||
target_id: u32,
|
target_id: UniqueApidTargetId,
|
||||||
set_id: u32,
|
set_id: UniqueId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HkUniqueId {
|
impl HkUniqueId {
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn target_id(&self) -> u32 {
|
pub fn target_id(&self) -> UniqueApidTargetId {
|
||||||
self.target_id
|
self.target_id
|
||||||
}
|
}
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn set_id(&self) -> u32 {
|
pub fn set_id(&self) -> UniqueId {
|
||||||
self.set_id
|
self.set_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
pub fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result<usize, ByteConversionError> {
|
||||||
if buf.len() < 8 {
|
if buf.len() < 8 {
|
||||||
return Err(ByteConversionError::ToSliceTooSmall {
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
@ -29,7 +27,7 @@ impl HkUniqueId {
|
|||||||
expected: 8,
|
expected: 8,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
buf[0..4].copy_from_slice(&self.target_id.to_be_bytes());
|
buf[0..4].copy_from_slice(&self.target_id.unique_id.to_be_bytes());
|
||||||
buf[4..8].copy_from_slice(&self.set_id.to_be_bytes());
|
buf[4..8].copy_from_slice(&self.set_id.to_be_bytes());
|
||||||
|
|
||||||
Ok(8)
|
Ok(8)
|
||||||
|
@ -1 +1,39 @@
|
|||||||
|
use satrs::spacepackets::time::{cds::CdsTime, TimeWriter};
|
||||||
|
|
||||||
pub mod config;
|
pub mod config;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
||||||
|
pub enum DeviceMode {
|
||||||
|
Off = 0,
|
||||||
|
On = 1,
|
||||||
|
Normal = 2,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct TimeStampHelper {
|
||||||
|
stamper: CdsTime,
|
||||||
|
time_stamp: [u8; 7],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeStampHelper {
|
||||||
|
pub fn stamp(&self) -> &[u8] {
|
||||||
|
&self.time_stamp
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update_from_now(&mut self) {
|
||||||
|
self.stamper
|
||||||
|
.update_from_now()
|
||||||
|
.expect("Updating timestamp failed");
|
||||||
|
self.stamper
|
||||||
|
.write_to_bytes(&mut self.time_stamp)
|
||||||
|
.expect("Writing timestamp failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for TimeStampHelper {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
stamper: CdsTime::now_with_u16_days().expect("creating time stamper failed"),
|
||||||
|
time_stamp: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -17,24 +17,23 @@ use log::info;
|
|||||||
use pus::test::create_test_service_dynamic;
|
use pus::test::create_test_service_dynamic;
|
||||||
use satrs::hal::std::tcp_server::ServerConfig;
|
use satrs::hal::std::tcp_server::ServerConfig;
|
||||||
use satrs::hal::std::udp_server::UdpTcServer;
|
use satrs::hal::std::udp_server::UdpTcServer;
|
||||||
use satrs::request::{GenericMessage, TargetAndApidId};
|
use satrs::request::GenericMessage;
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
use satrs::tmtc::tm_helper::SharedTmPool;
|
||||||
use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools};
|
use satrs_example::config::pool::{create_sched_tc_pool, create_static_pools};
|
||||||
use satrs_example::config::tasks::{
|
use satrs_example::config::tasks::{
|
||||||
FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC,
|
FREQ_MS_AOCS, FREQ_MS_EVENT_HANDLING, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC,
|
||||||
};
|
};
|
||||||
use satrs_example::config::{
|
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
|
||||||
ComponentIdList, RequestTargetId, OBSW_SERVER_ADDR, PUS_APID, SERVER_PORT,
|
|
||||||
};
|
|
||||||
use tmtc::PusTcSourceProviderDynamic;
|
use tmtc::PusTcSourceProviderDynamic;
|
||||||
use udp::DynamicUdpTmHandler;
|
use udp::DynamicUdpTmHandler;
|
||||||
|
|
||||||
// use crate::acs::AcsTask;
|
use crate::acs::mgm::{MgmHandler, SpiDummyInterface};
|
||||||
use crate::ccsds::CcsdsReceiver;
|
use crate::ccsds::CcsdsReceiver;
|
||||||
use crate::logger::setup_logger;
|
use crate::logger::setup_logger;
|
||||||
use crate::pus::action::{create_action_service_dynamic, create_action_service_static};
|
use crate::pus::action::{create_action_service_dynamic, create_action_service_static};
|
||||||
use crate::pus::event::{create_event_service_dynamic, create_event_service_static};
|
use crate::pus::event::{create_event_service_dynamic, create_event_service_static};
|
||||||
use crate::pus::hk::{create_hk_service_dynamic, create_hk_service_static};
|
use crate::pus::hk::{create_hk_service_dynamic, create_hk_service_static};
|
||||||
|
use crate::pus::mode::{create_mode_service_dynamic, create_mode_service_static};
|
||||||
use crate::pus::scheduler::{create_scheduler_service_dynamic, create_scheduler_service_static};
|
use crate::pus::scheduler::{create_scheduler_service_dynamic, create_scheduler_service_static};
|
||||||
use crate::pus::test::create_test_service_static;
|
use crate::pus::test::create_test_service_static;
|
||||||
use crate::pus::{PusReceiver, PusTcMpscRouter};
|
use crate::pus::{PusReceiver, PusTcMpscRouter};
|
||||||
@ -44,27 +43,18 @@ use crate::tmtc::{
|
|||||||
PusTcSourceProviderSharedPool, SharedTcPool, TcSourceTaskDynamic, TcSourceTaskStatic,
|
PusTcSourceProviderSharedPool, SharedTcPool, TcSourceTaskDynamic, TcSourceTaskStatic,
|
||||||
};
|
};
|
||||||
use crate::udp::{StaticUdpTmHandler, UdpTmtcServer};
|
use crate::udp::{StaticUdpTmHandler, UdpTmtcServer};
|
||||||
|
use satrs::mode::ModeRequest;
|
||||||
use satrs::pus::event_man::EventRequestWithToken;
|
use satrs::pus::event_man::EventRequestWithToken;
|
||||||
use satrs::pus::verification::{VerificationReporterCfg, VerificationReporterWithSender};
|
use satrs::pus::TmInSharedPoolSender;
|
||||||
use satrs::pus::{EcssTmSender, TmAsVecSenderWithId, TmInSharedPoolSenderWithId};
|
use satrs::spacepackets::{time::cds::CdsTime, time::TimeWriter};
|
||||||
use satrs::spacepackets::{time::cds::TimeProvider, time::TimeWriter};
|
|
||||||
use satrs::tmtc::CcsdsDistributor;
|
use satrs::tmtc::CcsdsDistributor;
|
||||||
use satrs::ComponentId;
|
use satrs_example::config::components::MGM_HANDLER_0;
|
||||||
use std::net::{IpAddr, SocketAddr};
|
use std::net::{IpAddr, SocketAddr};
|
||||||
use std::sync::mpsc::{self, channel};
|
use std::sync::mpsc;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
fn create_verification_reporter<Sender: EcssTmSender + Clone>(
|
|
||||||
verif_sender: Sender,
|
|
||||||
) -> VerificationReporterWithSender<Sender> {
|
|
||||||
let verif_cfg = VerificationReporterCfg::new(PUS_APID, 1, 2, 8).unwrap();
|
|
||||||
// Every software component which needs to generate verification telemetry, gets a cloned
|
|
||||||
// verification reporter.
|
|
||||||
VerificationReporterWithSender::new(&verif_cfg, verif_sender)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn static_tmtc_pool_main() {
|
fn static_tmtc_pool_main() {
|
||||||
let (tm_pool, tc_pool) = create_static_pools();
|
let (tm_pool, tc_pool) = create_static_pools();
|
||||||
@ -76,20 +66,21 @@ fn static_tmtc_pool_main() {
|
|||||||
let (tm_funnel_tx, tm_funnel_rx) = mpsc::sync_channel(50);
|
let (tm_funnel_tx, tm_funnel_rx) = mpsc::sync_channel(50);
|
||||||
let (tm_server_tx, tm_server_rx) = mpsc::sync_channel(50);
|
let (tm_server_tx, tm_server_rx) = mpsc::sync_channel(50);
|
||||||
|
|
||||||
// Every software component which needs to generate verification telemetry, receives a cloned
|
let tm_funnel_tx_sender =
|
||||||
// verification reporter.
|
TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_funnel_tx.clone());
|
||||||
let verif_reporter = create_verification_reporter(TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::PusVerification as ComponentId,
|
let (mgm_handler_composite_tx, mgm_handler_composite_rx) =
|
||||||
"verif_sender",
|
mpsc::channel::<GenericMessage<CompositeRequest>>();
|
||||||
shared_tm_pool.clone(),
|
let (mgm_handler_mode_tx, mgm_handler_mode_rx) = mpsc::channel::<GenericMessage<ModeRequest>>();
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let acs_target_id = TargetAndApidId::new(PUS_APID, RequestTargetId::AcsSubsystem as u32);
|
|
||||||
let (acs_thread_tx, acs_thread_rx) = channel::<GenericMessage<CompositeRequest>>();
|
|
||||||
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
let mut request_map = GenericRequestRouter::default();
|
let mut request_map = GenericRequestRouter::default();
|
||||||
request_map.0.insert(acs_target_id.into(), acs_thread_tx);
|
request_map
|
||||||
|
.composite_router_map
|
||||||
|
.insert(MGM_HANDLER_0.id(), mgm_handler_composite_tx);
|
||||||
|
request_map
|
||||||
|
.mode_router_map
|
||||||
|
.insert(MGM_HANDLER_0.id(), mgm_handler_mode_tx);
|
||||||
|
|
||||||
// This helper structure is used by all telecommand providers which need to send telecommands
|
// This helper structure is used by all telecommand providers which need to send telecommands
|
||||||
// to the TC source.
|
// to the TC source.
|
||||||
@ -105,88 +96,80 @@ fn static_tmtc_pool_main() {
|
|||||||
|
|
||||||
// The event task is the core handler to perform the event routing and TM handling as specified
|
// The event task is the core handler to perform the event routing and TM handling as specified
|
||||||
// in the sat-rs documentation.
|
// in the sat-rs documentation.
|
||||||
let mut event_handler = EventHandler::new(
|
let mut event_handler = EventHandler::new(tm_funnel_tx.clone(), event_request_rx);
|
||||||
TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"ALL_EVENTS_TX",
|
|
||||||
shared_tm_pool.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
event_request_rx,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (pus_test_tx, pus_test_rx) = channel();
|
let (pus_test_tx, pus_test_rx) = mpsc::channel();
|
||||||
let (pus_event_tx, pus_event_rx) = channel();
|
let (pus_event_tx, pus_event_rx) = mpsc::channel();
|
||||||
let (pus_sched_tx, pus_sched_rx) = channel();
|
let (pus_sched_tx, pus_sched_rx) = mpsc::channel();
|
||||||
let (pus_hk_tx, pus_hk_rx) = channel();
|
let (pus_hk_tx, pus_hk_rx) = mpsc::channel();
|
||||||
let (pus_action_tx, pus_action_rx) = channel();
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_tx, pus_mode_rx) = mpsc::channel();
|
||||||
|
|
||||||
let (pus_action_reply_tx, pus_action_reply_rx) = channel();
|
let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel();
|
||||||
let (pus_hk_reply_tx, pus_hk_reply_rx) = channel();
|
let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel();
|
||||||
|
|
||||||
let pus_router = PusTcMpscRouter {
|
let pus_router = PusTcMpscRouter {
|
||||||
test_service_receiver: pus_test_tx,
|
test_tc_sender: pus_test_tx,
|
||||||
event_service_receiver: pus_event_tx,
|
event_tc_sender: pus_event_tx,
|
||||||
sched_service_receiver: pus_sched_tx,
|
sched_tc_sender: pus_sched_tx,
|
||||||
hk_service_receiver: pus_hk_tx,
|
hk_tc_sender: pus_hk_tx,
|
||||||
action_service_receiver: pus_action_tx,
|
action_tc_sender: pus_action_tx,
|
||||||
|
mode_tc_sender: pus_mode_tx,
|
||||||
};
|
};
|
||||||
let pus_test_service = create_test_service_static(
|
let pus_test_service = create_test_service_static(
|
||||||
shared_tm_pool.clone(),
|
tm_funnel_tx_sender.clone(),
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
shared_tc_pool.pool.clone(),
|
shared_tc_pool.pool.clone(),
|
||||||
event_handler.clone_event_sender(),
|
event_handler.clone_event_sender(),
|
||||||
pus_test_rx,
|
pus_test_rx,
|
||||||
);
|
);
|
||||||
let pus_scheduler_service = create_scheduler_service_static(
|
let pus_scheduler_service = create_scheduler_service_static(
|
||||||
shared_tm_pool.clone(),
|
tm_funnel_tx_sender.clone(),
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
tc_source.clone(),
|
tc_source.clone(),
|
||||||
pus_sched_rx,
|
pus_sched_rx,
|
||||||
create_sched_tc_pool(),
|
create_sched_tc_pool(),
|
||||||
);
|
);
|
||||||
let pus_event_service = create_event_service_static(
|
let pus_event_service = create_event_service_static(
|
||||||
shared_tm_pool.clone(),
|
tm_funnel_tx_sender.clone(),
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
shared_tc_pool.pool.clone(),
|
shared_tc_pool.pool.clone(),
|
||||||
pus_event_rx,
|
pus_event_rx,
|
||||||
event_request_tx,
|
event_request_tx,
|
||||||
);
|
);
|
||||||
let pus_action_service = create_action_service_static(
|
let pus_action_service = create_action_service_static(
|
||||||
shared_tm_pool.clone(),
|
tm_funnel_tx_sender.clone(),
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
shared_tc_pool.pool.clone(),
|
shared_tc_pool.pool.clone(),
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
request_map.clone(),
|
request_map.clone(),
|
||||||
pus_action_reply_rx,
|
pus_action_reply_rx,
|
||||||
);
|
);
|
||||||
let pus_hk_service = create_hk_service_static(
|
let pus_hk_service = create_hk_service_static(
|
||||||
shared_tm_pool.clone(),
|
tm_funnel_tx_sender.clone(),
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
shared_tc_pool.pool.clone(),
|
shared_tc_pool.pool.clone(),
|
||||||
pus_hk_rx,
|
pus_hk_rx,
|
||||||
request_map,
|
request_map.clone(),
|
||||||
pus_hk_reply_rx,
|
pus_hk_reply_rx,
|
||||||
);
|
);
|
||||||
|
let pus_mode_service = create_mode_service_static(
|
||||||
|
tm_funnel_tx_sender.clone(),
|
||||||
|
shared_tc_pool.pool.clone(),
|
||||||
|
pus_mode_rx,
|
||||||
|
request_map,
|
||||||
|
pus_mode_reply_rx,
|
||||||
|
);
|
||||||
let mut pus_stack = PusStack::new(
|
let mut pus_stack = PusStack::new(
|
||||||
|
pus_test_service,
|
||||||
pus_hk_service,
|
pus_hk_service,
|
||||||
pus_event_service,
|
pus_event_service,
|
||||||
pus_action_service,
|
pus_action_service,
|
||||||
pus_scheduler_service,
|
pus_scheduler_service,
|
||||||
pus_test_service,
|
pus_mode_service,
|
||||||
);
|
);
|
||||||
|
|
||||||
let ccsds_receiver = CcsdsReceiver { tc_source };
|
let ccsds_receiver = CcsdsReceiver { tc_source };
|
||||||
let mut tmtc_task = TcSourceTaskStatic::new(
|
let mut tmtc_task = TcSourceTaskStatic::new(
|
||||||
shared_tc_pool.clone(),
|
shared_tc_pool.clone(),
|
||||||
tc_source_rx,
|
tc_source_rx,
|
||||||
PusReceiver::new(verif_reporter.clone(), pus_router),
|
PusReceiver::new(tm_funnel_tx_sender, pus_router),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
@ -211,19 +194,6 @@ fn static_tmtc_pool_main() {
|
|||||||
)
|
)
|
||||||
.expect("tcp server creation failed");
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
/*
|
|
||||||
let mut acs_task = AcsTask::new(
|
|
||||||
TmInSharedPoolSenderWithId::new(
|
|
||||||
TmSenderId::AcsSubsystem as ChannelId,
|
|
||||||
"ACS_TASK_SENDER",
|
|
||||||
shared_tm_pool.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
),
|
|
||||||
acs_thread_rx,
|
|
||||||
verif_reporter,
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
|
|
||||||
let mut tm_funnel = TmFunnelStatic::new(
|
let mut tm_funnel = TmFunnelStatic::new(
|
||||||
shared_tm_pool,
|
shared_tm_pool,
|
||||||
sync_tm_tcp_source,
|
sync_tm_tcp_source,
|
||||||
@ -231,6 +201,24 @@ fn static_tmtc_pool_main() {
|
|||||||
tm_server_tx,
|
tm_server_tx,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) =
|
||||||
|
mpsc::channel();
|
||||||
|
|
||||||
|
let dummy_spi_interface = SpiDummyInterface::default();
|
||||||
|
let shared_mgm_set = Arc::default();
|
||||||
|
let mut mgm_handler = MgmHandler::new(
|
||||||
|
MGM_HANDLER_0,
|
||||||
|
"MGM_0",
|
||||||
|
mgm_handler_mode_rx,
|
||||||
|
mgm_handler_composite_rx,
|
||||||
|
pus_mode_reply_tx,
|
||||||
|
mgm_handler_mode_reply_to_parent_tx,
|
||||||
|
pus_hk_reply_tx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
dummy_spi_interface,
|
||||||
|
shared_mgm_set,
|
||||||
|
);
|
||||||
|
|
||||||
info!("Starting TMTC and UDP task");
|
info!("Starting TMTC and UDP task");
|
||||||
let jh_udp_tmtc = thread::Builder::new()
|
let jh_udp_tmtc = thread::Builder::new()
|
||||||
.name("TMTC and UDP".to_string())
|
.name("TMTC and UDP".to_string())
|
||||||
@ -276,7 +264,7 @@ fn static_tmtc_pool_main() {
|
|||||||
let jh_aocs = thread::Builder::new()
|
let jh_aocs = thread::Builder::new()
|
||||||
.name("AOCS".to_string())
|
.name("AOCS".to_string())
|
||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
// acs_task.periodic_operation();
|
mgm_handler.periodic_operation();
|
||||||
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -310,22 +298,23 @@ fn static_tmtc_pool_main() {
|
|||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn dyn_tmtc_pool_main() {
|
fn dyn_tmtc_pool_main() {
|
||||||
let (tc_source_tx, tc_source_rx) = channel();
|
let (tc_source_tx, tc_source_rx) = mpsc::channel();
|
||||||
let (tm_funnel_tx, tm_funnel_rx) = channel();
|
let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel();
|
||||||
let (tm_server_tx, tm_server_rx) = channel();
|
let (tm_server_tx, tm_server_rx) = mpsc::channel();
|
||||||
// Every software component which needs to generate verification telemetry, gets a cloned
|
|
||||||
// verification reporter.
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
let verif_reporter = create_verification_reporter(TmAsVecSenderWithId::new(
|
let (mgm_handler_composite_tx, mgm_handler_composite_rx) =
|
||||||
ComponentIdList::PusVerification as ComponentId,
|
mpsc::channel::<GenericMessage<CompositeRequest>>();
|
||||||
"verif_sender",
|
let (mgm_handler_mode_tx, mgm_handler_mode_rx) = mpsc::channel::<GenericMessage<ModeRequest>>();
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
));
|
|
||||||
|
|
||||||
let acs_target_id = TargetAndApidId::new(PUS_APID, RequestTargetId::AcsSubsystem as u32);
|
|
||||||
let (acs_thread_tx, acs_thread_rx) = channel::<GenericMessage<CompositeRequest>>();
|
|
||||||
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
// Some request are targetable. This map is used to retrieve sender handles based on a target ID.
|
||||||
let mut request_map = GenericRequestRouter::default();
|
let mut request_map = GenericRequestRouter::default();
|
||||||
request_map.0.insert(acs_target_id.into(), acs_thread_tx);
|
request_map
|
||||||
|
.composite_router_map
|
||||||
|
.insert(MGM_HANDLER_0.raw(), mgm_handler_composite_tx);
|
||||||
|
request_map
|
||||||
|
.mode_router_map
|
||||||
|
.insert(MGM_HANDLER_0.raw(), mgm_handler_mode_tx);
|
||||||
|
|
||||||
let tc_source = PusTcSourceProviderDynamic(tc_source_tx);
|
let tc_source = PusTcSourceProviderDynamic(tc_source_tx);
|
||||||
|
|
||||||
@ -335,80 +324,74 @@ fn dyn_tmtc_pool_main() {
|
|||||||
let (event_request_tx, event_request_rx) = mpsc::channel::<EventRequestWithToken>();
|
let (event_request_tx, event_request_rx) = mpsc::channel::<EventRequestWithToken>();
|
||||||
// The event task is the core handler to perform the event routing and TM handling as specified
|
// The event task is the core handler to perform the event routing and TM handling as specified
|
||||||
// in the sat-rs documentation.
|
// in the sat-rs documentation.
|
||||||
let mut event_handler = EventHandler::new(
|
let mut event_handler = EventHandler::new(tm_funnel_tx.clone(), event_request_rx);
|
||||||
TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"ALL_EVENTS_TX",
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
),
|
|
||||||
verif_reporter.clone(),
|
|
||||||
event_request_rx,
|
|
||||||
);
|
|
||||||
|
|
||||||
let (pus_test_tx, pus_test_rx) = channel();
|
let (pus_test_tx, pus_test_rx) = mpsc::channel();
|
||||||
let (pus_event_tx, pus_event_rx) = channel();
|
let (pus_event_tx, pus_event_rx) = mpsc::channel();
|
||||||
let (pus_sched_tx, pus_sched_rx) = channel();
|
let (pus_sched_tx, pus_sched_rx) = mpsc::channel();
|
||||||
let (pus_hk_tx, pus_hk_rx) = channel();
|
let (pus_hk_tx, pus_hk_rx) = mpsc::channel();
|
||||||
let (pus_action_tx, pus_action_rx) = channel();
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_tx, pus_mode_rx) = mpsc::channel();
|
||||||
|
|
||||||
let (pus_action_reply_tx, pus_action_reply_rx) = channel();
|
let (_pus_action_reply_tx, pus_action_reply_rx) = mpsc::channel();
|
||||||
let (pus_hk_reply_tx, pus_hk_reply_rx) = channel();
|
let (pus_hk_reply_tx, pus_hk_reply_rx) = mpsc::channel();
|
||||||
|
let (pus_mode_reply_tx, pus_mode_reply_rx) = mpsc::channel();
|
||||||
|
|
||||||
let pus_router = PusTcMpscRouter {
|
let pus_router = PusTcMpscRouter {
|
||||||
test_service_receiver: pus_test_tx,
|
test_tc_sender: pus_test_tx,
|
||||||
event_service_receiver: pus_event_tx,
|
event_tc_sender: pus_event_tx,
|
||||||
sched_service_receiver: pus_sched_tx,
|
sched_tc_sender: pus_sched_tx,
|
||||||
hk_service_receiver: pus_hk_tx,
|
hk_tc_sender: pus_hk_tx,
|
||||||
action_service_receiver: pus_action_tx,
|
action_tc_sender: pus_action_tx,
|
||||||
|
mode_tc_sender: pus_mode_tx,
|
||||||
};
|
};
|
||||||
|
|
||||||
let pus_test_service = create_test_service_dynamic(
|
let pus_test_service = create_test_service_dynamic(
|
||||||
tm_funnel_tx.clone(),
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter.clone(),
|
|
||||||
event_handler.clone_event_sender(),
|
event_handler.clone_event_sender(),
|
||||||
pus_test_rx,
|
pus_test_rx,
|
||||||
);
|
);
|
||||||
let pus_scheduler_service = create_scheduler_service_dynamic(
|
let pus_scheduler_service = create_scheduler_service_dynamic(
|
||||||
tm_funnel_tx.clone(),
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter.clone(),
|
|
||||||
tc_source.0.clone(),
|
tc_source.0.clone(),
|
||||||
pus_sched_rx,
|
pus_sched_rx,
|
||||||
create_sched_tc_pool(),
|
create_sched_tc_pool(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let pus_event_service = create_event_service_dynamic(
|
let pus_event_service =
|
||||||
tm_funnel_tx.clone(),
|
create_event_service_dynamic(tm_funnel_tx.clone(), pus_event_rx, event_request_tx);
|
||||||
verif_reporter.clone(),
|
|
||||||
pus_event_rx,
|
|
||||||
event_request_tx,
|
|
||||||
);
|
|
||||||
let pus_action_service = create_action_service_dynamic(
|
let pus_action_service = create_action_service_dynamic(
|
||||||
tm_funnel_tx.clone(),
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter.clone(),
|
|
||||||
pus_action_rx,
|
pus_action_rx,
|
||||||
request_map.clone(),
|
request_map.clone(),
|
||||||
pus_action_reply_rx,
|
pus_action_reply_rx,
|
||||||
);
|
);
|
||||||
let pus_hk_service = create_hk_service_dynamic(
|
let pus_hk_service = create_hk_service_dynamic(
|
||||||
tm_funnel_tx.clone(),
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter.clone(),
|
|
||||||
pus_hk_rx,
|
pus_hk_rx,
|
||||||
request_map,
|
request_map.clone(),
|
||||||
pus_hk_reply_rx,
|
pus_hk_reply_rx,
|
||||||
);
|
);
|
||||||
|
let pus_mode_service = create_mode_service_dynamic(
|
||||||
|
tm_funnel_tx.clone(),
|
||||||
|
pus_mode_rx,
|
||||||
|
request_map,
|
||||||
|
pus_mode_reply_rx,
|
||||||
|
);
|
||||||
let mut pus_stack = PusStack::new(
|
let mut pus_stack = PusStack::new(
|
||||||
|
pus_test_service,
|
||||||
pus_hk_service,
|
pus_hk_service,
|
||||||
pus_event_service,
|
pus_event_service,
|
||||||
pus_action_service,
|
pus_action_service,
|
||||||
pus_scheduler_service,
|
pus_scheduler_service,
|
||||||
pus_test_service,
|
pus_mode_service,
|
||||||
);
|
);
|
||||||
|
|
||||||
let ccsds_receiver = CcsdsReceiver { tc_source };
|
let ccsds_receiver = CcsdsReceiver { tc_source };
|
||||||
|
|
||||||
let mut tmtc_task = TcSourceTaskDynamic::new(
|
let mut tmtc_task = TcSourceTaskDynamic::new(
|
||||||
tc_source_rx,
|
tc_source_rx,
|
||||||
PusReceiver::new(verif_reporter.clone(), pus_router),
|
PusReceiver::new(tm_funnel_tx.clone(), pus_router),
|
||||||
);
|
);
|
||||||
|
|
||||||
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
let sock_addr = SocketAddr::new(IpAddr::V4(OBSW_SERVER_ADDR), SERVER_PORT);
|
||||||
@ -432,19 +415,25 @@ fn dyn_tmtc_pool_main() {
|
|||||||
)
|
)
|
||||||
.expect("tcp server creation failed");
|
.expect("tcp server creation failed");
|
||||||
|
|
||||||
/*
|
|
||||||
let mut acs_task = AcsTask::new(
|
|
||||||
TmAsVecSenderWithId::new(
|
|
||||||
TmSenderId::AcsSubsystem as ComponentId,
|
|
||||||
"ACS_TASK_SENDER",
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
),
|
|
||||||
acs_thread_rx,
|
|
||||||
verif_reporter,
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
let mut tm_funnel = TmFunnelDynamic::new(sync_tm_tcp_source, tm_funnel_rx, tm_server_tx);
|
let mut tm_funnel = TmFunnelDynamic::new(sync_tm_tcp_source, tm_funnel_rx, tm_server_tx);
|
||||||
|
|
||||||
|
let (mgm_handler_mode_reply_to_parent_tx, _mgm_handler_mode_reply_to_parent_rx) =
|
||||||
|
mpsc::channel();
|
||||||
|
let dummy_spi_interface = SpiDummyInterface::default();
|
||||||
|
let shared_mgm_set = Arc::default();
|
||||||
|
let mut mgm_handler = MgmHandler::new(
|
||||||
|
MGM_HANDLER_0,
|
||||||
|
"MGM_0",
|
||||||
|
mgm_handler_mode_rx,
|
||||||
|
mgm_handler_composite_rx,
|
||||||
|
pus_mode_reply_tx,
|
||||||
|
mgm_handler_mode_reply_to_parent_tx,
|
||||||
|
pus_hk_reply_tx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
dummy_spi_interface,
|
||||||
|
shared_mgm_set,
|
||||||
|
);
|
||||||
|
|
||||||
info!("Starting TMTC and UDP task");
|
info!("Starting TMTC and UDP task");
|
||||||
let jh_udp_tmtc = thread::Builder::new()
|
let jh_udp_tmtc = thread::Builder::new()
|
||||||
.name("TMTC and UDP".to_string())
|
.name("TMTC and UDP".to_string())
|
||||||
@ -490,7 +479,7 @@ fn dyn_tmtc_pool_main() {
|
|||||||
let jh_aocs = thread::Builder::new()
|
let jh_aocs = thread::Builder::new()
|
||||||
.name("AOCS".to_string())
|
.name("AOCS".to_string())
|
||||||
.spawn(move || loop {
|
.spawn(move || loop {
|
||||||
// acs_task.periodic_operation();
|
mgm_handler.periodic_operation();
|
||||||
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -531,7 +520,7 @@ fn main() {
|
|||||||
dyn_tmtc_pool_main();
|
dyn_tmtc_pool_main();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_time(time_provider: &mut TimeProvider, timestamp: &mut [u8]) {
|
pub fn update_time(time_provider: &mut CdsTime, timestamp: &mut [u8]) {
|
||||||
time_provider
|
time_provider
|
||||||
.update_from_now()
|
.update_from_now()
|
||||||
.expect("Could not get current time");
|
.expect("Could not get current time");
|
||||||
|
@ -1,34 +1,35 @@
|
|||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use satrs::action::{ActionRequest, ActionRequestVariant};
|
use satrs::action::{ActionRequest, ActionRequestVariant};
|
||||||
use satrs::params::WritableToBeBytes;
|
use satrs::params::WritableToBeBytes;
|
||||||
use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::action::{
|
use satrs::pus::action::{
|
||||||
ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap, PusActionReply,
|
ActionReplyVariant, ActivePusActionRequestStd, DefaultActiveActionRequestMap, PusActionReply,
|
||||||
};
|
};
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
FailParams, FailParamsWithStep, TcStateAccepted, TcStateStarted,
|
FailParams, FailParamsWithStep, TcStateAccepted, TcStateStarted, VerificationReporter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
VerificationReportingProvider, VerificationToken,
|
VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
||||||
EcssTcInVecConverter, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError,
|
EcssTcInVecConverter, EcssTmSenderCore, EcssTmtcError, GenericConversionError, MpscTcReceiver,
|
||||||
GenericConversionError, MpscTcReceiver, PusPacketHandlerResult, PusReplyHandler,
|
MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusReplyHandler,
|
||||||
PusServiceHelper, PusTcToRequestConverter, TmAsVecSenderWithId, TmAsVecSenderWithMpsc,
|
PusServiceHelper, PusTcToRequestConverter, PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithId,
|
|
||||||
};
|
};
|
||||||
use satrs::request::{GenericMessage, TargetAndApidId};
|
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket};
|
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket};
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs_example::config::{tmtc_err, ComponentIdList, PUS_APID};
|
use satrs_example::config::components::PUS_ACTION_SERVICE;
|
||||||
use std::sync::mpsc::{self};
|
use satrs_example::config::tmtc_err;
|
||||||
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
|
|
||||||
use super::{generic_pus_request_timeout_handler, PusTargetedRequestService, TargetedPusService};
|
use super::{
|
||||||
|
create_verification_reporter, generic_pus_request_timeout_handler, PusTargetedRequestService,
|
||||||
|
TargetedPusService,
|
||||||
|
};
|
||||||
|
|
||||||
pub struct ActionReplyHandler {
|
pub struct ActionReplyHandler {
|
||||||
fail_data_buf: [u8; 128],
|
fail_data_buf: [u8; 128],
|
||||||
@ -47,20 +48,22 @@ impl PusReplyHandler<ActivePusActionRequestStd, PusActionReply> for ActionReplyH
|
|||||||
|
|
||||||
fn handle_unrequested_reply(
|
fn handle_unrequested_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
_caller_id: ComponentId,
|
||||||
reply: &GenericMessage<PusActionReply>,
|
reply: &GenericMessage<PusActionReply>,
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
_tm_sender: &impl EcssTmSenderCore,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
log::warn!("received unexpected reply for service 8: {reply:?}");
|
warn!("received unexpected reply for service 8: {reply:?}");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_reply(
|
fn handle_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
reply: &satrs::request::GenericMessage<PusActionReply>,
|
caller_id: ComponentId,
|
||||||
|
reply: &GenericMessage<PusActionReply>,
|
||||||
active_request: &ActivePusActionRequestStd,
|
active_request: &ActivePusActionRequestStd,
|
||||||
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<bool, Self::Error> {
|
) -> Result<bool, Self::Error> {
|
||||||
let verif_token: VerificationToken<TcStateStarted> = active_request
|
let verif_token: VerificationToken<TcStateStarted> = active_request
|
||||||
.token()
|
.token()
|
||||||
@ -72,16 +75,12 @@ impl PusReplyHandler<ActivePusActionRequestStd, PusActionReply> for ActionReplyH
|
|||||||
if let Some(params) = params {
|
if let Some(params) = params {
|
||||||
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
|
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
|
||||||
}
|
}
|
||||||
verification_handler
|
verification_handler.completion_failure(
|
||||||
.completion_failure(
|
caller_id,
|
||||||
verif_token,
|
tm_sender,
|
||||||
FailParams::new(
|
verif_token,
|
||||||
time_stamp,
|
FailParams::new(time_stamp, error_code, &self.fail_data_buf[..fail_data_len]),
|
||||||
error_code,
|
)?;
|
||||||
&self.fail_data_buf[..fail_data_len],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map_err(|e| e.0)?;
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ActionReplyVariant::StepFailed {
|
ActionReplyVariant::StepFailed {
|
||||||
@ -93,27 +92,32 @@ impl PusReplyHandler<ActivePusActionRequestStd, PusActionReply> for ActionReplyH
|
|||||||
if let Some(params) = params {
|
if let Some(params) = params {
|
||||||
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
|
fail_data_len = params.write_to_be_bytes(&mut self.fail_data_buf)?;
|
||||||
}
|
}
|
||||||
verification_handler
|
verification_handler.step_failure(
|
||||||
.step_failure(
|
caller_id,
|
||||||
verif_token,
|
tm_sender,
|
||||||
FailParamsWithStep::new(
|
verif_token,
|
||||||
time_stamp,
|
FailParamsWithStep::new(
|
||||||
&EcssEnumU16::new(*step),
|
time_stamp,
|
||||||
error_code,
|
&EcssEnumU16::new(*step),
|
||||||
&self.fail_data_buf[..fail_data_len],
|
error_code,
|
||||||
),
|
&self.fail_data_buf[..fail_data_len],
|
||||||
)
|
),
|
||||||
.map_err(|e| e.0)?;
|
)?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ActionReplyVariant::Completed => {
|
ActionReplyVariant::Completed => {
|
||||||
verification_handler
|
verification_handler.completion_success(
|
||||||
.completion_success(verif_token, time_stamp)
|
caller_id,
|
||||||
.map_err(|e| e.0)?;
|
tm_sender,
|
||||||
|
verif_token,
|
||||||
|
time_stamp,
|
||||||
|
)?;
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
ActionReplyVariant::StepSuccess { step } => {
|
ActionReplyVariant::StepSuccess { step } => {
|
||||||
verification_handler.step_success(
|
verification_handler.step_success(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
&verif_token,
|
&verif_token,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
EcssEnumU16::new(*step),
|
EcssEnumU16::new(*step),
|
||||||
@ -127,12 +131,15 @@ impl PusReplyHandler<ActivePusActionRequestStd, PusActionReply> for ActionReplyH
|
|||||||
|
|
||||||
fn handle_request_timeout(
|
fn handle_request_timeout(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
active_request: &ActivePusActionRequestStd,
|
active_request: &ActivePusActionRequestStd,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
generic_pus_request_timeout_handler(
|
generic_pus_request_timeout_handler(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
active_request,
|
active_request,
|
||||||
verification_handler,
|
verification_handler,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -149,16 +156,20 @@ impl PusTcToRequestConverter<ActivePusActionRequestStd, ActionRequest> for Actio
|
|||||||
|
|
||||||
fn convert(
|
fn convert(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
tc: &PusTcReader,
|
tc: &PusTcReader,
|
||||||
time_stamp: &[u8],
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verif_reporter: &impl VerificationReportingProvider,
|
verif_reporter: &impl VerificationReportingProvider,
|
||||||
|
time_stamp: &[u8],
|
||||||
) -> Result<(ActivePusActionRequestStd, ActionRequest), Self::Error> {
|
) -> Result<(ActivePusActionRequestStd, ActionRequest), Self::Error> {
|
||||||
let subservice = tc.subservice();
|
let subservice = tc.subservice();
|
||||||
let user_data = tc.user_data();
|
let user_data = tc.user_data();
|
||||||
if user_data.len() < 8 {
|
if user_data.len() < 8 {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA),
|
FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA),
|
||||||
)
|
)
|
||||||
@ -168,7 +179,7 @@ impl PusTcToRequestConverter<ActivePusActionRequestStd, ActionRequest> for Actio
|
|||||||
found: user_data.len(),
|
found: user_data.len(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).unwrap();
|
let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).unwrap();
|
||||||
let action_id = u32::from_be_bytes(user_data[4..8].try_into().unwrap());
|
let action_id = u32::from_be_bytes(user_data[4..8].try_into().unwrap());
|
||||||
if subservice == 128 {
|
if subservice == 128 {
|
||||||
let req_variant = if user_data.len() == 8 {
|
let req_variant = if user_data.len() == 8 {
|
||||||
@ -188,6 +199,8 @@ impl PusTcToRequestConverter<ActivePusActionRequestStd, ActionRequest> for Actio
|
|||||||
} else {
|
} else {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE),
|
FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE),
|
||||||
)
|
)
|
||||||
@ -198,37 +211,18 @@ impl PusTcToRequestConverter<ActivePusActionRequestStd, ActionRequest> for Actio
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_action_service_static(
|
pub fn create_action_service_static(
|
||||||
shared_tm_store: SharedTmPool,
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
tm_funnel_tx: mpsc::SyncSender<StoreAddr>,
|
|
||||||
verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
tc_pool: SharedStaticMemoryPool,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
action_router: GenericRequestRouter,
|
action_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<PusActionReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<PusActionReply>>,
|
||||||
) -> Pus8Wrapper<
|
) -> ActionServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
|
||||||
EcssTcInSharedStoreConverter,
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
> {
|
|
||||||
let action_srv_tm_sender = TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
"PUS_8_TM_SENDER",
|
|
||||||
shared_tm_store.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let action_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
"PUS_8_TC_RECV",
|
|
||||||
pus_action_rx,
|
|
||||||
);
|
|
||||||
let action_request_handler = PusTargetedRequestService::new(
|
let action_request_handler = PusTargetedRequestService::new(
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
action_srv_receiver,
|
PUS_ACTION_SERVICE.raw(),
|
||||||
action_srv_tm_sender.clone(),
|
pus_action_rx,
|
||||||
PUS_APID,
|
tm_sender,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_ACTION_SERVICE.apid),
|
||||||
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
||||||
),
|
),
|
||||||
ActionRequestConverter::default(),
|
ActionRequestConverter::default(),
|
||||||
@ -239,40 +233,23 @@ pub fn create_action_service_static(
|
|||||||
action_router,
|
action_router,
|
||||||
reply_receiver,
|
reply_receiver,
|
||||||
);
|
);
|
||||||
Pus8Wrapper {
|
ActionServiceWrapper {
|
||||||
service: action_request_handler,
|
service: action_request_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_action_service_dynamic(
|
pub fn create_action_service_dynamic(
|
||||||
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
verif_reporter: VerificationReporterWithVecMpscSender,
|
|
||||||
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
action_router: GenericRequestRouter,
|
action_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<PusActionReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<PusActionReply>>,
|
||||||
) -> Pus8Wrapper<
|
) -> ActionServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
EcssTcInVecConverter,
|
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
> {
|
|
||||||
let action_srv_tm_sender = TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
"PUS_8_TM_SENDER",
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let action_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
"PUS_8_TC_RECV",
|
|
||||||
pus_action_rx,
|
|
||||||
);
|
|
||||||
let action_request_handler = PusTargetedRequestService::new(
|
let action_request_handler = PusTargetedRequestService::new(
|
||||||
ComponentIdList::PusAction as ComponentId,
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
action_srv_receiver,
|
PUS_ACTION_SERVICE.raw(),
|
||||||
action_srv_tm_sender.clone(),
|
pus_action_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_ACTION_SERVICE.apid),
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
ActionRequestConverter::default(),
|
ActionRequestConverter::default(),
|
||||||
@ -281,19 +258,15 @@ pub fn create_action_service_dynamic(
|
|||||||
action_router,
|
action_router,
|
||||||
reply_receiver,
|
reply_receiver,
|
||||||
);
|
);
|
||||||
Pus8Wrapper {
|
ActionServiceWrapper {
|
||||||
service: action_request_handler,
|
service: action_request_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pus8Wrapper<
|
pub struct ActionServiceWrapper<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
{
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> {
|
|
||||||
pub(crate) service: PusTargetedRequestService<
|
pub(crate) service: PusTargetedRequestService<
|
||||||
TcReceiver,
|
MpscTcReceiver,
|
||||||
TmSender,
|
TmSender,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
@ -306,13 +279,8 @@ pub struct Pus8Wrapper<
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> TargetedPusService
|
||||||
TcReceiver: EcssTcReceiverCore,
|
for ActionServiceWrapper<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> TargetedPusService
|
|
||||||
for Pus8Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
/// Returns [true] if the packet handling is finished.
|
/// Returns [true] if the packet handling is finished.
|
||||||
fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
@ -340,13 +308,12 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool {
|
fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
match self.service.poll_and_check_next_reply(time_stamp) {
|
self.service
|
||||||
Ok(packet_handled) => packet_handled,
|
.poll_and_check_next_reply(time_stamp)
|
||||||
Err(e) => {
|
.unwrap_or_else(|e| {
|
||||||
log::warn!("PUS 8: Handling reply failed with error {e:?}");
|
warn!("PUS 8: Handling reply failed with error {e:?}");
|
||||||
false
|
false
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_for_request_timeouts(&mut self) {
|
fn check_for_request_timeouts(&mut self) {
|
||||||
@ -356,8 +323,10 @@ impl<
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID, TEST_UNIQUE_ID};
|
||||||
|
use satrs::pus::verification::test_util::TestVerificationReporter;
|
||||||
|
use satrs::request::MessageMetadata;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
pus::verification::VerificationReporterCfg,
|
|
||||||
res_code::ResultU16,
|
res_code::ResultU16,
|
||||||
spacepackets::{
|
spacepackets::{
|
||||||
ecss::{
|
ecss::{
|
||||||
@ -370,10 +339,7 @@ mod tests {
|
|||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
pus::tests::{
|
pus::tests::{PusConverterTestbench, ReplyHandlerTestbench, TargetedPusRequestTestbench},
|
||||||
PusConverterTestbench, ReplyHandlerTestbench, TargetedPusRequestTestbench, TARGET_ID,
|
|
||||||
TEST_APID, TEST_APID_TARGET_ID,
|
|
||||||
},
|
|
||||||
requests::CompositeRequest,
|
requests::CompositeRequest,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -391,31 +357,22 @@ mod tests {
|
|||||||
{
|
{
|
||||||
pub fn new_for_action() -> Self {
|
pub fn new_for_action() -> Self {
|
||||||
let _ = env_logger::builder().is_test(true).try_init();
|
let _ = env_logger::builder().is_test(true).try_init();
|
||||||
let target_and_apid_id = TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID);
|
|
||||||
let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel();
|
let (tm_funnel_tx, tm_funnel_rx) = mpsc::channel();
|
||||||
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
let (pus_action_tx, pus_action_rx) = mpsc::channel();
|
||||||
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
let (action_reply_tx, action_reply_rx) = mpsc::channel();
|
||||||
let (action_req_tx, action_req_rx) = mpsc::channel();
|
let (action_req_tx, action_req_rx) = mpsc::channel();
|
||||||
let verif_reporter_cfg = VerificationReporterCfg::new(TEST_APID, 2, 2, 64).unwrap();
|
let verif_reporter = TestVerificationReporter::default();
|
||||||
let tm_as_vec_sender =
|
|
||||||
TmAsVecSenderWithMpsc::new(1, "VERIF_SENDER", tm_funnel_tx.clone());
|
|
||||||
let verif_reporter =
|
|
||||||
VerificationReporterWithVecMpscSender::new(&verif_reporter_cfg, tm_as_vec_sender);
|
|
||||||
let mut generic_req_router = GenericRequestRouter::default();
|
let mut generic_req_router = GenericRequestRouter::default();
|
||||||
generic_req_router
|
generic_req_router
|
||||||
.0
|
.composite_router_map
|
||||||
.insert(target_and_apid_id.into(), action_req_tx);
|
.insert(TEST_APID.into(), action_req_tx);
|
||||||
let action_srv_tm_sender =
|
|
||||||
TmAsVecSenderWithId::new(0, "TESTBENCH", tm_funnel_tx.clone());
|
|
||||||
let action_srv_receiver = MpscTcReceiver::new(0, "TESTBENCH", pus_action_rx);
|
|
||||||
Self {
|
Self {
|
||||||
service: PusTargetedRequestService::new(
|
service: PusTargetedRequestService::new(
|
||||||
0,
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
action_srv_receiver,
|
0,
|
||||||
action_srv_tm_sender.clone(),
|
pus_action_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx.clone(),
|
||||||
verif_reporter.clone(),
|
verif_reporter,
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
ActionRequestConverter::default(),
|
ActionRequestConverter::default(),
|
||||||
@ -424,7 +381,6 @@ mod tests {
|
|||||||
generic_req_router,
|
generic_req_router,
|
||||||
action_reply_rx,
|
action_reply_rx,
|
||||||
),
|
),
|
||||||
verif_reporter,
|
|
||||||
pus_packet_tx: pus_action_tx,
|
pus_packet_tx: pus_action_tx,
|
||||||
tm_funnel_rx,
|
tm_funnel_rx,
|
||||||
reply_tx: action_reply_tx,
|
reply_tx: action_reply_tx,
|
||||||
@ -434,7 +390,7 @@ mod tests {
|
|||||||
|
|
||||||
pub fn verify_packet_verification(&self, subservice: u8) {
|
pub fn verify_packet_verification(&self, subservice: u8) {
|
||||||
let next_tm = self.tm_funnel_rx.try_recv().unwrap();
|
let next_tm = self.tm_funnel_rx.try_recv().unwrap();
|
||||||
let verif_tm = PusTmReader::new(&next_tm, 7).unwrap().0;
|
let verif_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0;
|
||||||
assert_eq!(verif_tm.apid(), TEST_APID);
|
assert_eq!(verif_tm.apid(), TEST_APID);
|
||||||
assert_eq!(verif_tm.service(), 1);
|
assert_eq!(verif_tm.service(), 1);
|
||||||
assert_eq!(verif_tm.subservice(), subservice);
|
assert_eq!(verif_tm.subservice(), subservice);
|
||||||
@ -445,7 +401,7 @@ mod tests {
|
|||||||
if let Err(mpsc::TryRecvError::Empty) = packet {
|
if let Err(mpsc::TryRecvError::Empty) = packet {
|
||||||
} else {
|
} else {
|
||||||
let tm = packet.unwrap();
|
let tm = packet.unwrap();
|
||||||
let unexpected_tm = PusTmReader::new(&tm, 7).unwrap().0;
|
let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap().0;
|
||||||
panic!("unexpected TM packet {unexpected_tm:?}");
|
panic!("unexpected TM packet {unexpected_tm:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,19 +439,26 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_tc(&mut self, tc: &PusTcCreator) {
|
pub fn add_tc(&mut self, tc: &PusTcCreator) {
|
||||||
let token = self.verif_reporter.add_tc(tc);
|
let token = self.service.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
let accepted_token = self
|
let accepted_token = self
|
||||||
.verif_reporter
|
.service
|
||||||
.acceptance_success(token, &[0; 7])
|
.service_helper
|
||||||
|
.verif_reporter()
|
||||||
|
.acceptance_success(
|
||||||
|
self.service.service_helper.id(),
|
||||||
|
self.service.service_helper.tm_sender(),
|
||||||
|
token,
|
||||||
|
&[0; 7],
|
||||||
|
)
|
||||||
.expect("TC acceptance failed");
|
.expect("TC acceptance failed");
|
||||||
let next_tm = self.tm_funnel_rx.try_recv().unwrap();
|
let next_tm = self.tm_funnel_rx.try_recv().unwrap();
|
||||||
let verif_tm = PusTmReader::new(&next_tm, 7).unwrap().0;
|
let verif_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0;
|
||||||
assert_eq!(verif_tm.apid(), TEST_APID);
|
assert_eq!(verif_tm.apid(), TEST_APID);
|
||||||
assert_eq!(verif_tm.service(), 1);
|
assert_eq!(verif_tm.service(), 1);
|
||||||
assert_eq!(verif_tm.subservice(), 1);
|
assert_eq!(verif_tm.subservice(), 1);
|
||||||
if let Err(mpsc::TryRecvError::Empty) = self.tm_funnel_rx.try_recv() {
|
if let Err(mpsc::TryRecvError::Empty) = self.tm_funnel_rx.try_recv() {
|
||||||
} else {
|
} else {
|
||||||
let unexpected_tm = PusTmReader::new(&next_tm, 7).unwrap().0;
|
let unexpected_tm = PusTmReader::new(&next_tm.packet, 7).unwrap().0;
|
||||||
panic!("unexpected TM packet {unexpected_tm:?}");
|
panic!("unexpected TM packet {unexpected_tm:?}");
|
||||||
}
|
}
|
||||||
self.pus_packet_tx
|
self.pus_packet_tx
|
||||||
@ -512,7 +475,7 @@ mod tests {
|
|||||||
let sec_header = PusTcSecondaryHeader::new_simple(8, 128);
|
let sec_header = PusTcSecondaryHeader::new_simple(8, 128);
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
testbench.add_tc(&pus8_packet);
|
testbench.add_tc(&pus8_packet);
|
||||||
@ -531,11 +494,7 @@ mod tests {
|
|||||||
let action_reply = PusActionReply::new(action_id, ActionReplyVariant::Completed);
|
let action_reply = PusActionReply::new(action_id, ActionReplyVariant::Completed);
|
||||||
testbench
|
testbench
|
||||||
.reply_tx
|
.reply_tx
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(req.requestor_info, action_reply))
|
||||||
req.request_id,
|
|
||||||
TARGET_ID.into(),
|
|
||||||
action_reply,
|
|
||||||
))
|
|
||||||
.unwrap();
|
.unwrap();
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected request type");
|
panic!("unexpected request type");
|
||||||
@ -556,7 +515,7 @@ mod tests {
|
|||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
// Invalid ID, routing should fail.
|
// Invalid ID, routing should fail.
|
||||||
app_data[0..4].copy_from_slice(&(TEST_APID_TARGET_ID + 1).to_be_bytes());
|
app_data[0..4].copy_from_slice(&(TEST_UNIQUE_ID + 1).to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
testbench.add_tc(&pus8_packet);
|
testbench.add_tc(&pus8_packet);
|
||||||
@ -575,11 +534,11 @@ mod tests {
|
|||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
// Invalid ID, routing should fail.
|
// Invalid ID, routing should fail.
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&pus8_packet);
|
let token = testbench.add_tc(&pus8_packet);
|
||||||
let result = testbench.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID);
|
let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let (active_req, request) = result.unwrap();
|
let (active_req, request) = result.unwrap();
|
||||||
if let ActionRequestVariant::NoData = request.variant {
|
if let ActionRequestVariant::NoData = request.variant {
|
||||||
@ -587,7 +546,7 @@ mod tests {
|
|||||||
assert_eq!(active_req.action_id, action_id);
|
assert_eq!(active_req.action_id, action_id);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
active_req.target_id(),
|
active_req.target_id(),
|
||||||
TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID).raw()
|
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID).raw()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
active_req.token().request_id(),
|
active_req.token().request_id(),
|
||||||
@ -606,14 +565,14 @@ mod tests {
|
|||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let mut app_data: [u8; 16] = [0; 16];
|
let mut app_data: [u8; 16] = [0; 16];
|
||||||
// Invalid ID, routing should fail.
|
// Invalid ID, routing should fail.
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
app_data[4..8].copy_from_slice(&action_id.to_be_bytes());
|
||||||
for i in 0..8 {
|
for i in 0..8 {
|
||||||
app_data[i + 8] = i as u8;
|
app_data[i + 8] = i as u8;
|
||||||
}
|
}
|
||||||
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let pus8_packet = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&pus8_packet);
|
let token = testbench.add_tc(&pus8_packet);
|
||||||
let result = testbench.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID);
|
let result = testbench.convert(token, &[], TEST_APID, TEST_UNIQUE_ID);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let (active_req, request) = result.unwrap();
|
let (active_req, request) = result.unwrap();
|
||||||
if let ActionRequestVariant::VecData(vec) = request.variant {
|
if let ActionRequestVariant::VecData(vec) = request.variant {
|
||||||
@ -629,24 +588,26 @@ mod tests {
|
|||||||
fn reply_handling_completion_success() {
|
fn reply_handling_completion_success() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
|
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
let active_action_req =
|
let active_action_req =
|
||||||
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
||||||
let reply = PusActionReply::new(action_id, ActionReplyVariant::Completed);
|
let reply = PusActionReply::new(action_id, ActionReplyVariant::Completed);
|
||||||
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
|
let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply);
|
||||||
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert!(result.unwrap());
|
assert!(result.unwrap());
|
||||||
testbench
|
testbench.verif_reporter.assert_full_completion_success(
|
||||||
.verif_reporter
|
TEST_COMPONENT_ID.raw(),
|
||||||
.assert_full_completion_success(&req_id, None);
|
req_id,
|
||||||
|
None,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_completion_failure() {
|
fn reply_handling_completion_failure() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
|
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
let active_action_req =
|
let active_action_req =
|
||||||
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
||||||
let error_code = ResultU16::new(2, 3);
|
let error_code = ResultU16::new(2, 3);
|
||||||
@ -657,40 +618,48 @@ mod tests {
|
|||||||
params: None,
|
params: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
|
let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply);
|
||||||
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert!(result.unwrap());
|
assert!(result.unwrap());
|
||||||
testbench
|
testbench.verif_reporter.assert_completion_failure(
|
||||||
.verif_reporter
|
TEST_COMPONENT_ID.into(),
|
||||||
.assert_completion_failure(&req_id, None, error_code.raw() as u64);
|
req_id,
|
||||||
|
None,
|
||||||
|
error_code.raw() as u64,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_step_success() {
|
fn reply_handling_step_success() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
|
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
let active_action_req =
|
let active_action_req =
|
||||||
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
||||||
let reply = PusActionReply::new(action_id, ActionReplyVariant::StepSuccess { step: 1 });
|
let reply = PusActionReply::new(action_id, ActionReplyVariant::StepSuccess { step: 1 });
|
||||||
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
|
let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply);
|
||||||
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
// Entry should not be removed, completion not done yet.
|
// Entry should not be removed, completion not done yet.
|
||||||
assert!(!result.unwrap());
|
assert!(!result.unwrap());
|
||||||
let verif_info = testbench.verif_reporter.verification_info(&req_id);
|
testbench.verif_reporter.check_next_was_added(req_id);
|
||||||
assert!(verif_info.is_some());
|
testbench
|
||||||
let verif_info = verif_info.unwrap();
|
.verif_reporter
|
||||||
assert!(verif_info.step_status.unwrap());
|
.check_next_is_acceptance_success(TEST_COMPONENT_ID.raw(), req_id);
|
||||||
assert_eq!(verif_info.step, 1);
|
testbench
|
||||||
|
.verif_reporter
|
||||||
|
.check_next_is_started_success(TEST_COMPONENT_ID.raw(), req_id);
|
||||||
|
testbench
|
||||||
|
.verif_reporter
|
||||||
|
.check_next_is_step_success(TEST_COMPONENT_ID.raw(), req_id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_step_failure() {
|
fn reply_handling_step_failure() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
let action_id = 5_u32;
|
let action_id = 5_u32;
|
||||||
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_APID_TARGET_ID, &[]);
|
let (req_id, active_req) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
let active_action_req =
|
let active_action_req =
|
||||||
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
ActivePusActionRequestStd::new_from_common_req(action_id, active_req);
|
||||||
let error_code = ResultU16::new(2, 3);
|
let error_code = ResultU16::new(2, 3);
|
||||||
@ -702,22 +671,28 @@ mod tests {
|
|||||||
params: None,
|
params: None,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
let generic_reply = GenericMessage::new(req_id.into(), 0, reply);
|
let generic_reply = GenericMessage::new(MessageMetadata::new(req_id.into(), 0), reply);
|
||||||
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
let result = testbench.handle_reply(&generic_reply, &active_action_req, &[]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert!(result.unwrap());
|
assert!(result.unwrap());
|
||||||
let verif_info = testbench.verif_reporter.verification_info(&req_id);
|
testbench.verif_reporter.check_next_was_added(req_id);
|
||||||
assert!(verif_info.is_some());
|
testbench
|
||||||
let verif_info = verif_info.unwrap();
|
.verif_reporter
|
||||||
assert!(!verif_info.step_status.unwrap());
|
.check_next_is_acceptance_success(TEST_COMPONENT_ID.raw(), req_id);
|
||||||
assert_eq!(verif_info.step, 1);
|
testbench
|
||||||
|
.verif_reporter
|
||||||
|
.check_next_is_started_success(TEST_COMPONENT_ID.raw(), req_id);
|
||||||
|
testbench
|
||||||
|
.verif_reporter
|
||||||
|
.check_next_is_step_success(TEST_COMPONENT_ID.raw(), req_id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_unrequested_reply() {
|
fn reply_handling_unrequested_reply() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
let action_reply = PusActionReply::new(5_u32, ActionReplyVariant::Completed);
|
let action_reply = PusActionReply::new(5_u32, ActionReplyVariant::Completed);
|
||||||
let unrequested_reply = GenericMessage::new(10_u32, 15_u64, action_reply);
|
let unrequested_reply =
|
||||||
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
@ -727,9 +702,18 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_reply_timeout() {
|
fn reply_handling_reply_timeout() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ActionReplyHandler::default());
|
||||||
// TODO: Start a request, then time it out with the API and check verification completion
|
let action_id = 5_u32;
|
||||||
// failure.
|
let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
// testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender)
|
let result = testbench.handle_request_timeout(
|
||||||
// testbench.default_timeout = Duration::from_millis(50);
|
&ActivePusActionRequestStd::new_from_common_req(action_id, active_request),
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
assert!(result.is_ok());
|
||||||
|
testbench.verif_reporter.assert_completion_failure(
|
||||||
|
TEST_COMPONENT_ID.raw(),
|
||||||
|
req_id,
|
||||||
|
None,
|
||||||
|
tmtc_err::REQUEST_TIMEOUT.raw() as u64,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,114 +1,66 @@
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
|
|
||||||
|
use crate::pus::create_verification_reporter;
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::event_man::EventRequestWithToken;
|
use satrs::pus::event_man::EventRequestWithToken;
|
||||||
use satrs::pus::event_srv::PusService5EventHandler;
|
use satrs::pus::event_srv::PusEventServiceHandler;
|
||||||
use satrs::pus::verification::std_mod::{
|
use satrs::pus::verification::VerificationReporter;
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
};
|
|
||||||
use satrs::pus::verification::VerificationReportingProvider;
|
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
||||||
EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper,
|
EcssTmSenderCore, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded,
|
||||||
TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
|
PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
TmInSharedPoolSenderWithId,
|
|
||||||
};
|
};
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
use satrs_example::config::components::PUS_EVENT_MANAGEMENT;
|
||||||
use satrs::ComponentId;
|
|
||||||
use satrs_example::config::{ComponentIdList, PUS_APID};
|
|
||||||
|
|
||||||
pub fn create_event_service_static(
|
pub fn create_event_service_static(
|
||||||
shared_tm_store: SharedTmPool,
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
tm_funnel_tx: mpsc::SyncSender<StoreAddr>,
|
|
||||||
verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
tc_pool: SharedStaticMemoryPool,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||||
) -> Pus5Wrapper<
|
) -> EventServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
MpscTcReceiver,
|
let pus_5_handler = PusEventServiceHandler::new(
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
|
||||||
EcssTcInSharedStoreConverter,
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
> {
|
|
||||||
let event_srv_tm_sender = TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"PUS_5_TM_SENDER",
|
|
||||||
shared_tm_store.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let event_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"PUS_5_TC_RECV",
|
|
||||||
pus_event_rx,
|
|
||||||
);
|
|
||||||
let pus_5_handler = PusService5EventHandler::new(
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
event_srv_receiver,
|
PUS_EVENT_MANAGEMENT.raw(),
|
||||||
event_srv_tm_sender,
|
pus_event_rx,
|
||||||
PUS_APID,
|
tm_sender,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_EVENT_MANAGEMENT.apid),
|
||||||
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
EcssTcInSharedStoreConverter::new(tc_pool.clone(), 2048),
|
||||||
),
|
),
|
||||||
event_request_tx,
|
event_request_tx,
|
||||||
);
|
);
|
||||||
Pus5Wrapper {
|
EventServiceWrapper {
|
||||||
handler: pus_5_handler,
|
handler: pus_5_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_event_service_dynamic(
|
pub fn create_event_service_dynamic(
|
||||||
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
verif_reporter: VerificationReporterWithVecMpscSender,
|
|
||||||
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_event_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
event_request_tx: mpsc::Sender<EventRequestWithToken>,
|
||||||
) -> Pus5Wrapper<
|
) -> EventServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
MpscTcReceiver,
|
let pus_5_handler = PusEventServiceHandler::new(
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
EcssTcInVecConverter,
|
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
> {
|
|
||||||
let event_srv_tm_sender = TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"PUS_5_TM_SENDER",
|
|
||||||
tm_funnel_tx,
|
|
||||||
);
|
|
||||||
let event_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::EventManagement as ComponentId,
|
|
||||||
"PUS_5_TC_RECV",
|
|
||||||
pus_event_rx,
|
|
||||||
);
|
|
||||||
let pus_5_handler = PusService5EventHandler::new(
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
event_srv_receiver,
|
PUS_EVENT_MANAGEMENT.raw(),
|
||||||
event_srv_tm_sender,
|
pus_event_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_EVENT_MANAGEMENT.apid),
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
event_request_tx,
|
event_request_tx,
|
||||||
);
|
);
|
||||||
Pus5Wrapper {
|
EventServiceWrapper {
|
||||||
handler: pus_5_handler,
|
handler: pus_5_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pus5Wrapper<
|
pub struct EventServiceWrapper<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
TcReceiver: EcssTcReceiverCore,
|
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> {
|
|
||||||
pub handler:
|
pub handler:
|
||||||
PusService5EventHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
PusEventServiceHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
EventServiceWrapper<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> Pus5Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
match self.handler.poll_and_handle_next_tc(time_stamp) {
|
match self.handler.poll_and_handle_next_tc(time_stamp) {
|
||||||
|
@ -1,30 +1,28 @@
|
|||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use log::{error, warn};
|
use log::{error, warn};
|
||||||
use satrs::hk::{CollectionIntervalFactor, HkRequest, HkRequestVariant, UniqueId};
|
use satrs::hk::{CollectionIntervalFactor, HkRequest, HkRequestVariant, UniqueId};
|
||||||
use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
FailParams, TcStateAccepted, TcStateStarted,
|
FailParams, TcStateAccepted, TcStateStarted, VerificationReporter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
VerificationReportingProvider, VerificationToken,
|
VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, EcssTcAndToken,
|
ActivePusRequestStd, ActiveRequestProvider, DefaultActiveRequestMap, EcssTcAndToken,
|
||||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTmSenderCore,
|
||||||
EcssTmSenderCore, EcssTmtcError, GenericConversionError, MpscTcReceiver,
|
EcssTmtcError, GenericConversionError, MpscTcReceiver, MpscTmAsVecSender,
|
||||||
PusPacketHandlerResult, PusReplyHandler, PusServiceHelper, PusTcToRequestConverter,
|
MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusReplyHandler, PusServiceHelper,
|
||||||
TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
|
PusTcToRequestConverter, PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
TmInSharedPoolSenderWithId,
|
|
||||||
};
|
};
|
||||||
use satrs::request::{GenericMessage, TargetAndApidId};
|
use satrs::request::{GenericMessage, UniqueApidTargetId};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::{hk, PusPacket};
|
use satrs::spacepackets::ecss::{hk, PusPacket};
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
use satrs_example::config::{hk_err, tmtc_err, ComponentIdList, PUS_APID};
|
use satrs_example::config::components::PUS_HK_SERVICE;
|
||||||
use std::sync::mpsc::{self};
|
use satrs_example::config::{hk_err, tmtc_err};
|
||||||
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
use crate::pus::generic_pus_request_timeout_handler;
|
use crate::pus::{create_verification_reporter, generic_pus_request_timeout_handler};
|
||||||
use crate::requests::GenericRequestRouter;
|
use crate::requests::GenericRequestRouter;
|
||||||
|
|
||||||
use super::PusTargetedRequestService;
|
use super::PusTargetedRequestService;
|
||||||
@ -48,7 +46,8 @@ impl PusReplyHandler<ActivePusRequestStd, HkReply> for HkReplyHandler {
|
|||||||
|
|
||||||
fn handle_unrequested_reply(
|
fn handle_unrequested_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
reply: &satrs::request::GenericMessage<HkReply>,
|
_caller_id: ComponentId,
|
||||||
|
reply: &GenericMessage<HkReply>,
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
_tm_sender: &impl EcssTmSenderCore,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
log::warn!("received unexpected reply for service 3: {reply:?}");
|
log::warn!("received unexpected reply for service 3: {reply:?}");
|
||||||
@ -57,11 +56,12 @@ impl PusReplyHandler<ActivePusRequestStd, HkReply> for HkReplyHandler {
|
|||||||
|
|
||||||
fn handle_reply(
|
fn handle_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
reply: &satrs::request::GenericMessage<HkReply>,
|
caller_id: ComponentId,
|
||||||
|
reply: &GenericMessage<HkReply>,
|
||||||
active_request: &ActivePusRequestStd,
|
active_request: &ActivePusRequestStd,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<bool, Self::Error> {
|
) -> Result<bool, Self::Error> {
|
||||||
let started_token: VerificationToken<TcStateStarted> = active_request
|
let started_token: VerificationToken<TcStateStarted> = active_request
|
||||||
.token()
|
.token()
|
||||||
@ -70,8 +70,8 @@ impl PusReplyHandler<ActivePusRequestStd, HkReply> for HkReplyHandler {
|
|||||||
match reply.message.variant {
|
match reply.message.variant {
|
||||||
HkReplyVariant::Ack => {
|
HkReplyVariant::Ack => {
|
||||||
verification_handler
|
verification_handler
|
||||||
.completion_success(started_token, time_stamp)
|
.completion_success(caller_id, tm_sender, started_token, time_stamp)
|
||||||
.expect("sending completio success verification failed");
|
.expect("sending completion success verification failed");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -79,12 +79,15 @@ impl PusReplyHandler<ActivePusRequestStd, HkReply> for HkReplyHandler {
|
|||||||
|
|
||||||
fn handle_request_timeout(
|
fn handle_request_timeout(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
active_request: &ActivePusRequestStd,
|
active_request: &ActivePusRequestStd,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
generic_pus_request_timeout_handler(
|
generic_pus_request_timeout_handler(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
active_request,
|
active_request,
|
||||||
verification_handler,
|
verification_handler,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -111,10 +114,12 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
|
|
||||||
fn convert(
|
fn convert(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
tc: &PusTcReader,
|
tc: &PusTcReader,
|
||||||
time_stamp: &[u8],
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verif_reporter: &impl VerificationReportingProvider,
|
verif_reporter: &impl VerificationReportingProvider,
|
||||||
|
time_stamp: &[u8],
|
||||||
) -> Result<(ActivePusRequestStd, HkRequest), Self::Error> {
|
) -> Result<(ActivePusRequestStd, HkRequest), Self::Error> {
|
||||||
let user_data = tc.user_data();
|
let user_data = tc.user_data();
|
||||||
if user_data.is_empty() {
|
if user_data.is_empty() {
|
||||||
@ -122,6 +127,8 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
let user_data_len_raw = user_data_len.to_be_bytes();
|
let user_data_len_raw = user_data_len.to_be_bytes();
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new(
|
FailParams::new(
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -144,7 +151,12 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
let user_data_len = user_data.len() as u32;
|
let user_data_len = user_data.len() as u32;
|
||||||
let user_data_len_raw = user_data_len.to_be_bytes();
|
let user_data_len_raw = user_data_len.to_be_bytes();
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(token, FailParams::new(time_stamp, err, &user_data_len_raw))
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
|
token,
|
||||||
|
FailParams::new(time_stamp, err, &user_data_len_raw),
|
||||||
|
)
|
||||||
.expect("Sending start failure TM failed");
|
.expect("Sending start failure TM failed");
|
||||||
return Err(GenericConversionError::NotEnoughAppData {
|
return Err(GenericConversionError::NotEnoughAppData {
|
||||||
expected: 8,
|
expected: 8,
|
||||||
@ -152,13 +164,15 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
let subservice = tc.subservice();
|
let subservice = tc.subservice();
|
||||||
let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).expect("invalid tc format");
|
let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).expect("invalid tc format");
|
||||||
let unique_id = u32::from_be_bytes(tc.user_data()[4..8].try_into().unwrap());
|
let unique_id = u32::from_be_bytes(tc.user_data()[4..8].try_into().unwrap());
|
||||||
|
|
||||||
let standard_subservice = hk::Subservice::try_from(subservice);
|
let standard_subservice = hk::Subservice::try_from(subservice);
|
||||||
if standard_subservice.is_err() {
|
if standard_subservice.is_err() {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE, &[subservice]),
|
FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE, &[subservice]),
|
||||||
)
|
)
|
||||||
@ -167,10 +181,10 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
}
|
}
|
||||||
let request = match standard_subservice.unwrap() {
|
let request = match standard_subservice.unwrap() {
|
||||||
hk::Subservice::TcEnableHkGeneration | hk::Subservice::TcEnableDiagGeneration => {
|
hk::Subservice::TcEnableHkGeneration | hk::Subservice::TcEnableDiagGeneration => {
|
||||||
HkRequest::new(unique_id, HkRequestVariant::Enable)
|
HkRequest::new(unique_id, HkRequestVariant::EnablePeriodic)
|
||||||
}
|
}
|
||||||
hk::Subservice::TcDisableHkGeneration | hk::Subservice::TcDisableDiagGeneration => {
|
hk::Subservice::TcDisableHkGeneration | hk::Subservice::TcDisableDiagGeneration => {
|
||||||
HkRequest::new(unique_id, HkRequestVariant::Disable)
|
HkRequest::new(unique_id, HkRequestVariant::DisablePeriodic)
|
||||||
}
|
}
|
||||||
hk::Subservice::TcReportHkReportStructures => todo!(),
|
hk::Subservice::TcReportHkReportStructures => todo!(),
|
||||||
hk::Subservice::TmHkPacket => todo!(),
|
hk::Subservice::TmHkPacket => todo!(),
|
||||||
@ -182,6 +196,8 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
if user_data.len() < 12 {
|
if user_data.len() < 12 {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new_no_fail_data(
|
FailParams::new_no_fail_data(
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -206,6 +222,8 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
_ => {
|
_ => {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new(
|
FailParams::new(
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -225,37 +243,18 @@ impl PusTcToRequestConverter<ActivePusRequestStd, HkRequest> for HkRequestConver
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_hk_service_static(
|
pub fn create_hk_service_static(
|
||||||
shared_tm_store: SharedTmPool,
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
tm_funnel_tx: mpsc::SyncSender<StoreAddr>,
|
|
||||||
verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
tc_pool: SharedStaticMemoryPool,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
request_router: GenericRequestRouter,
|
request_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
) -> Pus3Wrapper<
|
) -> HkServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
|
||||||
EcssTcInSharedStoreConverter,
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
> {
|
|
||||||
let hk_srv_tm_sender = TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
"PUS_3_TM_SENDER",
|
|
||||||
shared_tm_store.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let hk_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
"PUS_8_TC_RECV",
|
|
||||||
pus_hk_rx,
|
|
||||||
);
|
|
||||||
let pus_3_handler = PusTargetedRequestService::new(
|
let pus_3_handler = PusTargetedRequestService::new(
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
hk_srv_receiver,
|
PUS_HK_SERVICE.raw(),
|
||||||
hk_srv_tm_sender,
|
pus_hk_rx,
|
||||||
PUS_APID,
|
tm_sender,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_HK_SERVICE.apid),
|
||||||
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
),
|
),
|
||||||
HkRequestConverter::default(),
|
HkRequestConverter::default(),
|
||||||
@ -264,40 +263,23 @@ pub fn create_hk_service_static(
|
|||||||
request_router,
|
request_router,
|
||||||
reply_receiver,
|
reply_receiver,
|
||||||
);
|
);
|
||||||
Pus3Wrapper {
|
HkServiceWrapper {
|
||||||
service: pus_3_handler,
|
service: pus_3_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_hk_service_dynamic(
|
pub fn create_hk_service_dynamic(
|
||||||
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
verif_reporter: VerificationReporterWithVecMpscSender,
|
|
||||||
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_hk_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
request_router: GenericRequestRouter,
|
request_router: GenericRequestRouter,
|
||||||
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<HkReply>>,
|
||||||
) -> Pus3Wrapper<
|
) -> HkServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
EcssTcInVecConverter,
|
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
> {
|
|
||||||
let hk_srv_tm_sender = TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
"PUS_3_TM_SENDER",
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let hk_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
"PUS_8_TC_RECV",
|
|
||||||
pus_hk_rx,
|
|
||||||
);
|
|
||||||
let pus_3_handler = PusTargetedRequestService::new(
|
let pus_3_handler = PusTargetedRequestService::new(
|
||||||
ComponentIdList::PusHk as ComponentId,
|
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
hk_srv_receiver,
|
PUS_HK_SERVICE.raw(),
|
||||||
hk_srv_tm_sender,
|
pus_hk_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_HK_SERVICE.apid),
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
HkRequestConverter::default(),
|
HkRequestConverter::default(),
|
||||||
@ -306,19 +288,14 @@ pub fn create_hk_service_dynamic(
|
|||||||
request_router,
|
request_router,
|
||||||
reply_receiver,
|
reply_receiver,
|
||||||
);
|
);
|
||||||
Pus3Wrapper {
|
HkServiceWrapper {
|
||||||
service: pus_3_handler,
|
service: pus_3_handler,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pus3Wrapper<
|
pub struct HkServiceWrapper<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
TcReceiver: EcssTcReceiverCore,
|
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> {
|
|
||||||
pub(crate) service: PusTargetedRequestService<
|
pub(crate) service: PusTargetedRequestService<
|
||||||
TcReceiver,
|
MpscTcReceiver,
|
||||||
TmSender,
|
TmSender,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
@ -331,12 +308,8 @@ pub struct Pus3Wrapper<
|
|||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
HkServiceWrapper<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> Pus3Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
pub fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
match self.service.poll_and_handle_next_tc(time_stamp) {
|
match self.service.poll_and_handle_next_tc(time_stamp) {
|
||||||
@ -363,13 +336,12 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool {
|
pub fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
match self.service.poll_and_check_next_reply(time_stamp) {
|
self.service
|
||||||
Ok(packet_handled) => packet_handled,
|
.poll_and_check_next_reply(time_stamp)
|
||||||
Err(e) => {
|
.unwrap_or_else(|e| {
|
||||||
log::warn!("PUS 3: Handling reply failed with error {e:?}");
|
warn!("PUS 3: Handling reply failed with error {e:?}");
|
||||||
false
|
false
|
||||||
}
|
})
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_for_request_timeouts(&mut self) {
|
pub fn check_for_request_timeouts(&mut self) {
|
||||||
@ -379,6 +351,8 @@ impl<
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use satrs::pus::test_util::{TEST_COMPONENT_ID, TEST_UNIQUE_ID};
|
||||||
|
use satrs::request::MessageMetadata;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
hk::HkRequestVariant,
|
hk::HkRequestVariant,
|
||||||
pus::test_util::TEST_APID,
|
pus::test_util::TEST_APID,
|
||||||
@ -388,10 +362,11 @@ mod tests {
|
|||||||
SpHeader,
|
SpHeader,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use satrs_example::config::tmtc_err;
|
||||||
|
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
hk::HkReplyVariant,
|
hk::HkReplyVariant,
|
||||||
tests::{PusConverterTestbench, ReplyHandlerTestbench, TEST_APID_TARGET_ID},
|
tests::{PusConverterTestbench, ReplyHandlerTestbench},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{HkReply, HkReplyHandler, HkRequestConverter};
|
use super::{HkReply, HkReplyHandler, HkRequestConverter};
|
||||||
@ -400,7 +375,7 @@ mod tests {
|
|||||||
fn hk_converter_one_shot_req() {
|
fn hk_converter_one_shot_req() {
|
||||||
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let target_id = TEST_APID_TARGET_ID;
|
let target_id = TEST_UNIQUE_ID;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
||||||
@ -415,7 +390,7 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let accepted_token = hk_bench.add_tc(&hk_req);
|
let accepted_token = hk_bench.add_tc(&hk_req);
|
||||||
let (_active_req, req) = hk_bench
|
let (_active_req, req) = hk_bench
|
||||||
.convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion failed");
|
.expect("conversion failed");
|
||||||
|
|
||||||
assert_eq!(req.unique_id, unique_id);
|
assert_eq!(req.unique_id, unique_id);
|
||||||
@ -429,7 +404,7 @@ mod tests {
|
|||||||
fn hk_converter_enable_periodic_generation() {
|
fn hk_converter_enable_periodic_generation() {
|
||||||
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let target_id = TEST_APID_TARGET_ID;
|
let target_id = TEST_UNIQUE_ID;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
||||||
@ -437,10 +412,10 @@ mod tests {
|
|||||||
let mut generic_check = |tc: &PusTcCreator| {
|
let mut generic_check = |tc: &PusTcCreator| {
|
||||||
let accepted_token = hk_bench.add_tc(tc);
|
let accepted_token = hk_bench.add_tc(tc);
|
||||||
let (_active_req, req) = hk_bench
|
let (_active_req, req) = hk_bench
|
||||||
.convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion failed");
|
.expect("conversion failed");
|
||||||
assert_eq!(req.unique_id, unique_id);
|
assert_eq!(req.unique_id, unique_id);
|
||||||
if let HkRequestVariant::Enable = req.variant {
|
if let HkRequestVariant::EnablePeriodic = req.variant {
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected HK request")
|
panic!("unexpected HK request")
|
||||||
}
|
}
|
||||||
@ -467,7 +442,7 @@ mod tests {
|
|||||||
fn hk_conversion_disable_periodic_generation() {
|
fn hk_conversion_disable_periodic_generation() {
|
||||||
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let target_id = TEST_APID_TARGET_ID;
|
let target_id = TEST_UNIQUE_ID;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 8] = [0; 8];
|
let mut app_data: [u8; 8] = [0; 8];
|
||||||
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
app_data[0..4].copy_from_slice(&target_id.to_be_bytes());
|
||||||
@ -475,10 +450,10 @@ mod tests {
|
|||||||
let mut generic_check = |tc: &PusTcCreator| {
|
let mut generic_check = |tc: &PusTcCreator| {
|
||||||
let accepted_token = hk_bench.add_tc(tc);
|
let accepted_token = hk_bench.add_tc(tc);
|
||||||
let (_active_req, req) = hk_bench
|
let (_active_req, req) = hk_bench
|
||||||
.convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion failed");
|
.expect("conversion failed");
|
||||||
assert_eq!(req.unique_id, unique_id);
|
assert_eq!(req.unique_id, unique_id);
|
||||||
if let HkRequestVariant::Disable = req.variant {
|
if let HkRequestVariant::DisablePeriodic = req.variant {
|
||||||
} else {
|
} else {
|
||||||
panic!("unexpected HK request")
|
panic!("unexpected HK request")
|
||||||
}
|
}
|
||||||
@ -505,7 +480,7 @@ mod tests {
|
|||||||
fn hk_conversion_modify_interval() {
|
fn hk_conversion_modify_interval() {
|
||||||
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
let mut hk_bench = PusConverterTestbench::new(HkRequestConverter::default());
|
||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let target_id = TEST_APID_TARGET_ID;
|
let target_id = TEST_UNIQUE_ID;
|
||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let mut app_data: [u8; 12] = [0; 12];
|
let mut app_data: [u8; 12] = [0; 12];
|
||||||
let collection_interval_factor = 5_u32;
|
let collection_interval_factor = 5_u32;
|
||||||
@ -516,7 +491,7 @@ mod tests {
|
|||||||
let mut generic_check = |tc: &PusTcCreator| {
|
let mut generic_check = |tc: &PusTcCreator| {
|
||||||
let accepted_token = hk_bench.add_tc(tc);
|
let accepted_token = hk_bench.add_tc(tc);
|
||||||
let (_active_req, req) = hk_bench
|
let (_active_req, req) = hk_bench
|
||||||
.convert(accepted_token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(accepted_token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion failed");
|
.expect("conversion failed");
|
||||||
assert_eq!(req.unique_id, unique_id);
|
assert_eq!(req.unique_id, unique_id);
|
||||||
if let HkRequestVariant::ModifyCollectionInterval(interval_factor) = req.variant {
|
if let HkRequestVariant::ModifyCollectionInterval(interval_factor) = req.variant {
|
||||||
@ -551,24 +526,23 @@ mod tests {
|
|||||||
let unique_id = 5_u32;
|
let unique_id = 5_u32;
|
||||||
let (req_id, active_req) = reply_testbench.add_tc(TEST_APID, apid_target_id, &[]);
|
let (req_id, active_req) = reply_testbench.add_tc(TEST_APID, apid_target_id, &[]);
|
||||||
let reply = GenericMessage::new(
|
let reply = GenericMessage::new(
|
||||||
req_id.into(),
|
MessageMetadata::new(req_id.into(), sender_id),
|
||||||
sender_id,
|
|
||||||
HkReply::new(unique_id, HkReplyVariant::Ack),
|
HkReply::new(unique_id, HkReplyVariant::Ack),
|
||||||
);
|
);
|
||||||
let result = reply_testbench.handle_reply(&reply, &active_req, &[]);
|
let result = reply_testbench.handle_reply(&reply, &active_req, &[]);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
assert!(result.unwrap());
|
assert!(result.unwrap());
|
||||||
assert!(reply_testbench
|
reply_testbench
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
.completion_status(&req_id)
|
.assert_full_completion_success(TEST_COMPONENT_ID.raw(), req_id, None);
|
||||||
.unwrap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_unrequested_reply() {
|
fn reply_handling_unrequested_reply() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default());
|
||||||
let action_reply = HkReply::new(5_u32, HkReplyVariant::Ack);
|
let action_reply = HkReply::new(5_u32, HkReplyVariant::Ack);
|
||||||
let unrequested_reply = GenericMessage::new(10_u32, 15_u64, action_reply);
|
let unrequested_reply =
|
||||||
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), action_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
@ -578,9 +552,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_reply_timeout() {
|
fn reply_handling_reply_timeout() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(HkReplyHandler::default());
|
||||||
// TODO: Start a request, then time it out with the API and check verification completion
|
let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
// failure.
|
let result = testbench.handle_request_timeout(&active_request, &[]);
|
||||||
// testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender)
|
assert!(result.is_ok());
|
||||||
// testbench.default_timeout = Duration::from_millis(50);
|
testbench.verif_reporter.assert_completion_failure(
|
||||||
|
TEST_COMPONENT_ID.raw(),
|
||||||
|
req_id,
|
||||||
|
None,
|
||||||
|
tmtc_err::REQUEST_TIMEOUT.raw() as u64,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,8 +2,8 @@ use crate::requests::GenericRequestRouter;
|
|||||||
use crate::tmtc::MpscStoreAndSendError;
|
use crate::tmtc::MpscStoreAndSendError;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
self, FailParams, TcStateAccepted, TcStateStarted, VerificationReportingProvider,
|
self, FailParams, TcStateAccepted, TcStateStarted, VerificationReporter,
|
||||||
VerificationToken,
|
VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
ActiveRequestMapProvider, ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter,
|
ActiveRequestMapProvider, ActiveRequestProvider, EcssTcAndToken, EcssTcInMemConverter,
|
||||||
@ -12,13 +12,13 @@ use satrs::pus::{
|
|||||||
PusRequestRouter, PusServiceHelper, PusTcToRequestConverter, TcInMemory,
|
PusRequestRouter, PusServiceHelper, PusTcToRequestConverter, TcInMemory,
|
||||||
};
|
};
|
||||||
use satrs::queue::GenericReceiveError;
|
use satrs::queue::GenericReceiveError;
|
||||||
use satrs::request::GenericMessage;
|
use satrs::request::{Apid, GenericMessage, MessageMetadata};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::PusServiceId;
|
use satrs::spacepackets::ecss::PusServiceId;
|
||||||
use satrs::spacepackets::time::cds::TimeProvider;
|
|
||||||
use satrs::spacepackets::time::TimeWriter;
|
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
|
use satrs_example::config::components::PUS_ROUTING_SERVICE;
|
||||||
use satrs_example::config::{tmtc_err, CustomPusServiceId};
|
use satrs_example::config::{tmtc_err, CustomPusServiceId};
|
||||||
|
use satrs_example::TimeStampHelper;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::sync::mpsc::{self, Sender};
|
use std::sync::mpsc::{self, Sender};
|
||||||
|
|
||||||
@ -30,58 +30,125 @@ pub mod scheduler;
|
|||||||
pub mod stack;
|
pub mod stack;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
|
|
||||||
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
pub fn create_verification_reporter(apid: Apid) -> VerificationReporter {
|
||||||
pub struct PusTcMpscRouter {
|
let verif_cfg = VerificationReporterCfg::new(apid, 1, 2, 8).unwrap();
|
||||||
pub test_service_receiver: Sender<EcssTcAndToken>,
|
// Every software component which needs to generate verification telemetry, gets a cloned
|
||||||
pub event_service_receiver: Sender<EcssTcAndToken>,
|
// verification reporter.
|
||||||
pub sched_service_receiver: Sender<EcssTcAndToken>,
|
VerificationReporter::new(&verif_cfg)
|
||||||
pub hk_service_receiver: Sender<EcssTcAndToken>,
|
|
||||||
pub action_service_receiver: Sender<EcssTcAndToken>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PusReceiver<VerificationReporter: VerificationReportingProvider> {
|
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
||||||
|
pub struct PusTcMpscRouter {
|
||||||
|
pub test_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
pub event_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
pub sched_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
pub hk_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
pub action_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
pub mode_tc_sender: Sender<EcssTcAndToken>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct PusReceiver<TmSender: EcssTmSenderCore> {
|
||||||
|
pub id: ComponentId,
|
||||||
|
pub tm_sender: TmSender,
|
||||||
pub verif_reporter: VerificationReporter,
|
pub verif_reporter: VerificationReporter,
|
||||||
pub pus_router: PusTcMpscRouter,
|
pub pus_router: PusTcMpscRouter,
|
||||||
stamp_helper: TimeStampHelper,
|
stamp_helper: TimeStampHelper,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TimeStampHelper {
|
impl<TmSender: EcssTmSenderCore> PusReceiver<TmSender> {
|
||||||
stamper: TimeProvider,
|
pub fn new(tm_sender: TmSender, pus_router: PusTcMpscRouter) -> Self {
|
||||||
time_stamp: [u8; 7],
|
|
||||||
}
|
|
||||||
|
|
||||||
impl TimeStampHelper {
|
|
||||||
pub fn stamp(&self) -> &[u8] {
|
|
||||||
&self.time_stamp
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn update_from_now(&mut self) {
|
|
||||||
self.stamper
|
|
||||||
.update_from_now()
|
|
||||||
.expect("Updating timestamp failed");
|
|
||||||
self.stamper
|
|
||||||
.write_to_bytes(&mut self.time_stamp)
|
|
||||||
.expect("Writing timestamp failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for TimeStampHelper {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
stamper: TimeProvider::from_now_with_u16_days().expect("creating time stamper failed"),
|
id: PUS_ROUTING_SERVICE.raw(),
|
||||||
time_stamp: Default::default(),
|
tm_sender,
|
||||||
}
|
verif_reporter: create_verification_reporter(PUS_ROUTING_SERVICE.apid),
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<VerificationReporter: VerificationReportingProvider> PusReceiver<VerificationReporter> {
|
|
||||||
pub fn new(verif_reporter: VerificationReporter, pus_router: PusTcMpscRouter) -> Self {
|
|
||||||
Self {
|
|
||||||
verif_reporter,
|
|
||||||
pus_router,
|
pus_router,
|
||||||
stamp_helper: TimeStampHelper::default(),
|
stamp_helper: TimeStampHelper::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn handle_tc_packet(
|
||||||
|
&mut self,
|
||||||
|
tc_in_memory: TcInMemory,
|
||||||
|
service: u8,
|
||||||
|
pus_tc: &PusTcReader,
|
||||||
|
) -> Result<PusPacketHandlerResult, MpscStoreAndSendError> {
|
||||||
|
let init_token = self.verif_reporter.add_tc(pus_tc);
|
||||||
|
self.stamp_helper.update_from_now();
|
||||||
|
let accepted_token = self
|
||||||
|
.verif_reporter
|
||||||
|
.acceptance_success(
|
||||||
|
self.id,
|
||||||
|
&self.tm_sender,
|
||||||
|
init_token,
|
||||||
|
self.stamp_helper.stamp(),
|
||||||
|
)
|
||||||
|
.expect("Acceptance success failure");
|
||||||
|
let service = PusServiceId::try_from(service);
|
||||||
|
match service {
|
||||||
|
Ok(standard_service) => match standard_service {
|
||||||
|
PusServiceId::Test => self.pus_router.test_tc_sender.send(EcssTcAndToken {
|
||||||
|
tc_in_memory,
|
||||||
|
token: Some(accepted_token.into()),
|
||||||
|
})?,
|
||||||
|
PusServiceId::Housekeeping => {
|
||||||
|
self.pus_router.hk_tc_sender.send(EcssTcAndToken {
|
||||||
|
tc_in_memory,
|
||||||
|
token: Some(accepted_token.into()),
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
PusServiceId::Event => self.pus_router.event_tc_sender.send(EcssTcAndToken {
|
||||||
|
tc_in_memory,
|
||||||
|
token: Some(accepted_token.into()),
|
||||||
|
})?,
|
||||||
|
PusServiceId::Scheduling => {
|
||||||
|
self.pus_router.sched_tc_sender.send(EcssTcAndToken {
|
||||||
|
tc_in_memory,
|
||||||
|
token: Some(accepted_token.into()),
|
||||||
|
})?
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
let result = self.verif_reporter.start_failure(
|
||||||
|
self.id,
|
||||||
|
&self.tm_sender,
|
||||||
|
accepted_token,
|
||||||
|
FailParams::new(
|
||||||
|
self.stamp_helper.stamp(),
|
||||||
|
&tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED,
|
||||||
|
&[standard_service as u8],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if result.is_err() {
|
||||||
|
warn!("Sending verification failure failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(e) => {
|
||||||
|
if let Ok(custom_service) = CustomPusServiceId::try_from(e.number) {
|
||||||
|
match custom_service {
|
||||||
|
CustomPusServiceId::Mode => {
|
||||||
|
// TODO: Fix mode service.
|
||||||
|
//self.handle_mode_service(pus_tc, accepted_token)
|
||||||
|
}
|
||||||
|
CustomPusServiceId::Health => {}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.verif_reporter
|
||||||
|
.start_failure(
|
||||||
|
self.id,
|
||||||
|
&self.tm_sender,
|
||||||
|
accepted_token,
|
||||||
|
FailParams::new(
|
||||||
|
self.stamp_helper.stamp(),
|
||||||
|
&tmtc_err::INVALID_PUS_SUBSERVICE,
|
||||||
|
&[e.number],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.expect("Start failure verification failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(PusPacketHandlerResult::RequestHandled)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TargetedPusService {
|
pub trait TargetedPusService {
|
||||||
@ -123,7 +190,6 @@ pub struct PusTargetedRequestService<
|
|||||||
RequestType,
|
RequestType,
|
||||||
ReplyType,
|
ReplyType,
|
||||||
> {
|
> {
|
||||||
pub id: ComponentId,
|
|
||||||
pub service_helper:
|
pub service_helper:
|
||||||
PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
pub request_router: GenericRequestRouter,
|
pub request_router: GenericRequestRouter,
|
||||||
@ -162,7 +228,6 @@ where
|
|||||||
GenericRequestRouter: PusRequestRouter<RequestType, Error = GenericRoutingError>,
|
GenericRequestRouter: PusRequestRouter<RequestType, Error = GenericRoutingError>,
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: ComponentId,
|
|
||||||
service_helper: PusServiceHelper<
|
service_helper: PusServiceHelper<
|
||||||
TcReceiver,
|
TcReceiver,
|
||||||
TmSender,
|
TmSender,
|
||||||
@ -176,7 +241,6 @@ where
|
|||||||
reply_receiver: mpsc::Receiver<GenericMessage<ReplyType>>,
|
reply_receiver: mpsc::Receiver<GenericMessage<ReplyType>>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id,
|
|
||||||
service_helper,
|
service_helper,
|
||||||
request_converter,
|
request_converter,
|
||||||
active_request_map,
|
active_request_map,
|
||||||
@ -201,10 +265,12 @@ where
|
|||||||
.cache(&ecss_tc_and_token.tc_in_memory)?;
|
.cache(&ecss_tc_and_token.tc_in_memory)?;
|
||||||
let tc = self.service_helper.tc_in_mem_converter().convert()?;
|
let tc = self.service_helper.tc_in_mem_converter().convert()?;
|
||||||
let (mut request_info, request) = match self.request_converter.convert(
|
let (mut request_info, request) = match self.request_converter.convert(
|
||||||
|
self.service_helper.id(),
|
||||||
ecss_tc_and_token.token,
|
ecss_tc_and_token.token,
|
||||||
&tc,
|
&tc,
|
||||||
time_stamp,
|
self.service_helper.tm_sender(),
|
||||||
&self.service_helper.common.verif_reporter,
|
&self.service_helper.common.verif_reporter,
|
||||||
|
time_stamp,
|
||||||
) {
|
) {
|
||||||
Ok((info, req)) => (info, req),
|
Ok((info, req)) => (info, req),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@ -218,8 +284,7 @@ where
|
|||||||
.expect("token not in expected accepted state");
|
.expect("token not in expected accepted state");
|
||||||
let verif_request_id = verification::RequestId::new(&tc).raw();
|
let verif_request_id = verification::RequestId::new(&tc).raw();
|
||||||
match self.request_router.route(
|
match self.request_router.route(
|
||||||
verif_request_id,
|
MessageMetadata::new(verif_request_id, self.service_helper.id()),
|
||||||
self.id,
|
|
||||||
request_info.target_id(),
|
request_info.target_id(),
|
||||||
request,
|
request,
|
||||||
) {
|
) {
|
||||||
@ -227,7 +292,12 @@ where
|
|||||||
let started_token = self
|
let started_token = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(accepted_token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.id(),
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
accepted_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Start success failure");
|
.expect("Start success failure");
|
||||||
request_info.set_token(started_token.into());
|
request_info.set_token(started_token.into());
|
||||||
self.active_request_map
|
self.active_request_map
|
||||||
@ -238,8 +308,9 @@ where
|
|||||||
&request_info,
|
&request_info,
|
||||||
&tc,
|
&tc,
|
||||||
e.clone(),
|
e.clone(),
|
||||||
time_stamp,
|
self.service_helper.tm_sender(),
|
||||||
self.service_helper.verif_reporter(),
|
self.service_helper.verif_reporter(),
|
||||||
|
time_stamp,
|
||||||
);
|
);
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
@ -259,6 +330,8 @@ where
|
|||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
self.service_helper.id(),
|
||||||
|
self.service_helper.tm_sender(),
|
||||||
token,
|
token,
|
||||||
FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SERVICE, &service_slice),
|
FailParams::new(time_stamp, &tmtc_err::INVALID_PUS_SERVICE, &service_slice),
|
||||||
)
|
)
|
||||||
@ -269,6 +342,8 @@ where
|
|||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
self.service_helper.id(),
|
||||||
|
self.service_helper.tm_sender(),
|
||||||
token,
|
token,
|
||||||
FailParams::new(
|
FailParams::new(
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -284,6 +359,8 @@ where
|
|||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
self.service_helper.id(),
|
||||||
|
self.service_helper.tm_sender(),
|
||||||
token,
|
token,
|
||||||
FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info),
|
FailParams::new(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA, &context_info),
|
||||||
)
|
)
|
||||||
@ -314,25 +391,29 @@ where
|
|||||||
reply: &GenericMessage<ReplyType>,
|
reply: &GenericMessage<ReplyType>,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
let active_req_opt = self.active_request_map.get(reply.request_id);
|
let active_req_opt = self.active_request_map.get(reply.request_id());
|
||||||
if active_req_opt.is_none() {
|
if active_req_opt.is_none() {
|
||||||
self.reply_handler
|
self.reply_handler.handle_unrequested_reply(
|
||||||
.handle_unrequested_reply(reply, &self.service_helper.common.tm_sender)?;
|
self.service_helper.id(),
|
||||||
|
reply,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
)?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let active_request = active_req_opt.unwrap();
|
let active_request = active_req_opt.unwrap();
|
||||||
let request_finished = self
|
let request_finished = self
|
||||||
.reply_handler
|
.reply_handler
|
||||||
.handle_reply(
|
.handle_reply(
|
||||||
|
self.service_helper.id(),
|
||||||
reply,
|
reply,
|
||||||
active_request,
|
active_request,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
&self.service_helper.common.verif_reporter,
|
&self.service_helper.common.verif_reporter,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
&self.service_helper.common.tm_sender,
|
|
||||||
)
|
)
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
if request_finished {
|
if request_finished {
|
||||||
self.active_request_map.remove(reply.request_id);
|
self.active_request_map.remove(reply.request_id());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -356,6 +437,8 @@ where
|
|||||||
/// Generic timeout handling: Handle the verification failure with a dedicated return code
|
/// Generic timeout handling: Handle the verification failure with a dedicated return code
|
||||||
/// and also log the error.
|
/// and also log the error.
|
||||||
pub fn generic_pus_request_timeout_handler(
|
pub fn generic_pus_request_timeout_handler(
|
||||||
|
sender_id: ComponentId,
|
||||||
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
active_request: &(impl ActiveRequestProvider + Debug),
|
active_request: &(impl ActiveRequestProvider + Debug),
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
@ -366,118 +449,27 @@ pub fn generic_pus_request_timeout_handler(
|
|||||||
.token()
|
.token()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("token not in expected started state");
|
.expect("token not in expected started state");
|
||||||
verification_handler
|
verification_handler.completion_failure(
|
||||||
.completion_failure(
|
sender_id,
|
||||||
started_token,
|
sender,
|
||||||
FailParams::new(
|
started_token,
|
||||||
time_stamp,
|
FailParams::new(time_stamp, &tmtc_err::REQUEST_TIMEOUT, &[]),
|
||||||
&satrs_example::config::tmtc_err::REQUEST_TIMEOUT,
|
)?;
|
||||||
&[],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map_err(|e| e.0)?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<VerificationReporter: VerificationReportingProvider> PusReceiver<VerificationReporter> {
|
|
||||||
pub fn handle_tc_packet(
|
|
||||||
&mut self,
|
|
||||||
tc_in_memory: TcInMemory,
|
|
||||||
service: u8,
|
|
||||||
pus_tc: &PusTcReader,
|
|
||||||
) -> Result<PusPacketHandlerResult, MpscStoreAndSendError> {
|
|
||||||
let init_token = self.verif_reporter.add_tc(pus_tc);
|
|
||||||
self.stamp_helper.update_from_now();
|
|
||||||
let accepted_token = self
|
|
||||||
.verif_reporter
|
|
||||||
.acceptance_success(init_token, self.stamp_helper.stamp())
|
|
||||||
.expect("Acceptance success failure");
|
|
||||||
let service = PusServiceId::try_from(service);
|
|
||||||
match service {
|
|
||||||
Ok(standard_service) => match standard_service {
|
|
||||||
PusServiceId::Test => {
|
|
||||||
self.pus_router.test_service_receiver.send(EcssTcAndToken {
|
|
||||||
tc_in_memory,
|
|
||||||
token: Some(accepted_token.into()),
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
PusServiceId::Housekeeping => {
|
|
||||||
self.pus_router.hk_service_receiver.send(EcssTcAndToken {
|
|
||||||
tc_in_memory,
|
|
||||||
token: Some(accepted_token.into()),
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
PusServiceId::Event => {
|
|
||||||
self.pus_router
|
|
||||||
.event_service_receiver
|
|
||||||
.send(EcssTcAndToken {
|
|
||||||
tc_in_memory,
|
|
||||||
token: Some(accepted_token.into()),
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
PusServiceId::Scheduling => {
|
|
||||||
self.pus_router
|
|
||||||
.sched_service_receiver
|
|
||||||
.send(EcssTcAndToken {
|
|
||||||
tc_in_memory,
|
|
||||||
token: Some(accepted_token.into()),
|
|
||||||
})?
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
let result = self.verif_reporter.start_failure(
|
|
||||||
accepted_token,
|
|
||||||
FailParams::new(
|
|
||||||
self.stamp_helper.stamp(),
|
|
||||||
&tmtc_err::PUS_SERVICE_NOT_IMPLEMENTED,
|
|
||||||
&[standard_service as u8],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
if result.is_err() {
|
|
||||||
warn!("Sending verification failure failed");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Err(e) => {
|
|
||||||
if let Ok(custom_service) = CustomPusServiceId::try_from(e.number) {
|
|
||||||
match custom_service {
|
|
||||||
CustomPusServiceId::Mode => {
|
|
||||||
// TODO: Fix mode service.
|
|
||||||
//self.handle_mode_service(pus_tc, accepted_token)
|
|
||||||
}
|
|
||||||
CustomPusServiceId::Health => {}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
self.verif_reporter
|
|
||||||
.start_failure(
|
|
||||||
accepted_token,
|
|
||||||
FailParams::new(
|
|
||||||
self.stamp_helper.stamp(),
|
|
||||||
&tmtc_err::INVALID_PUS_SUBSERVICE,
|
|
||||||
&[e.number],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.expect("Start failure verification failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(PusPacketHandlerResult::RequestHandled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use satrs::pus::test_util::TEST_COMPONENT_ID;
|
||||||
|
use satrs::pus::{MpscTmAsVecSender, PusTmAsVec, PusTmVariant};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
pus::{
|
pus::{
|
||||||
verification::{
|
verification::test_util::TestVerificationReporter, ActivePusRequestStd,
|
||||||
test_util::{SharedVerificationMap, TestVerificationReporter},
|
ActiveRequestMapProvider, EcssTcInVecConverter, MpscTcReceiver,
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
},
|
|
||||||
ActivePusRequestStd, ActiveRequestMapProvider, EcssTcInVecConverter, MpscTcReceiver,
|
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
},
|
},
|
||||||
request::TargetAndApidId,
|
request::UniqueApidTargetId,
|
||||||
spacepackets::{
|
spacepackets::{
|
||||||
ecss::{
|
ecss::{
|
||||||
tc::{PusTcCreator, PusTcSecondaryHeader},
|
tc::{PusTcCreator, PusTcSecondaryHeader},
|
||||||
@ -491,22 +483,18 @@ pub(crate) mod tests {
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub const TEST_APID: u16 = 0x23;
|
|
||||||
pub const TEST_APID_TARGET_ID: u32 = 5;
|
|
||||||
pub const TARGET_ID: TargetAndApidId = TargetAndApidId::new(TEST_APID, TEST_APID_TARGET_ID);
|
|
||||||
|
|
||||||
// Testbench dedicated to the testing of [PusReplyHandler]s
|
// Testbench dedicated to the testing of [PusReplyHandler]s
|
||||||
pub struct ReplyHandlerTestbench<
|
pub struct ReplyHandlerTestbench<
|
||||||
ReplyHandler: PusReplyHandler<ActiveRequestInfo, Reply, Error = EcssTmtcError>,
|
ReplyHandler: PusReplyHandler<ActiveRequestInfo, Reply, Error = EcssTmtcError>,
|
||||||
ActiveRequestInfo: ActiveRequestProvider,
|
ActiveRequestInfo: ActiveRequestProvider,
|
||||||
Reply,
|
Reply,
|
||||||
> {
|
> {
|
||||||
pub shared_verif_map: SharedVerificationMap,
|
pub id: ComponentId,
|
||||||
pub verif_reporter: TestVerificationReporter,
|
pub verif_reporter: TestVerificationReporter,
|
||||||
pub reply_handler: ReplyHandler,
|
pub reply_handler: ReplyHandler,
|
||||||
pub tm_receiver: mpsc::Receiver<Vec<u8>>,
|
pub tm_receiver: mpsc::Receiver<PusTmAsVec>,
|
||||||
pub default_timeout: Duration,
|
pub default_timeout: Duration,
|
||||||
tm_sender: TmAsVecSenderWithMpsc,
|
tm_sender: MpscTmAsVecSender,
|
||||||
phantom: std::marker::PhantomData<(ActiveRequestInfo, Reply)>,
|
phantom: std::marker::PhantomData<(ActiveRequestInfo, Reply)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -517,15 +505,14 @@ pub(crate) mod tests {
|
|||||||
> ReplyHandlerTestbench<ReplyHandler, ActiveRequestInfo, Reply>
|
> ReplyHandlerTestbench<ReplyHandler, ActiveRequestInfo, Reply>
|
||||||
{
|
{
|
||||||
pub fn new(reply_handler: ReplyHandler) -> Self {
|
pub fn new(reply_handler: ReplyHandler) -> Self {
|
||||||
let shared_verif_map = SharedVerificationMap::default();
|
let test_verif_reporter = TestVerificationReporter::default();
|
||||||
let test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone());
|
|
||||||
let (tm_sender, tm_receiver) = mpsc::channel();
|
let (tm_sender, tm_receiver) = mpsc::channel();
|
||||||
Self {
|
Self {
|
||||||
shared_verif_map,
|
id: TEST_COMPONENT_ID.raw(),
|
||||||
verif_reporter: test_verif_reporter,
|
verif_reporter: test_verif_reporter,
|
||||||
reply_handler,
|
reply_handler,
|
||||||
default_timeout: Duration::from_secs(30),
|
default_timeout: Duration::from_secs(30),
|
||||||
tm_sender: TmAsVecSenderWithMpsc::new(0, "TEST_SENDER", tm_sender),
|
tm_sender,
|
||||||
tm_receiver,
|
tm_receiver,
|
||||||
phantom: std::marker::PhantomData,
|
phantom: std::marker::PhantomData,
|
||||||
}
|
}
|
||||||
@ -547,16 +534,16 @@ pub(crate) mod tests {
|
|||||||
));
|
));
|
||||||
let accepted = self
|
let accepted = self
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
.acceptance_success(init, time_stamp)
|
.acceptance_success(self.id, &self.tm_sender, init, time_stamp)
|
||||||
.expect("acceptance failed");
|
.expect("acceptance failed");
|
||||||
let started = self
|
let started = self
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
.start_success(accepted, time_stamp)
|
.start_success(self.id, &self.tm_sender, accepted, time_stamp)
|
||||||
.expect("start failed");
|
.expect("start failed");
|
||||||
(
|
(
|
||||||
started.request_id(),
|
started.request_id(),
|
||||||
ActivePusRequestStd::new(
|
ActivePusRequestStd::new(
|
||||||
TargetAndApidId::new(apid, apid_target).raw(),
|
UniqueApidTargetId::new(apid, apid_target).raw(),
|
||||||
started,
|
started,
|
||||||
self.default_timeout,
|
self.default_timeout,
|
||||||
),
|
),
|
||||||
@ -570,11 +557,12 @@ pub(crate) mod tests {
|
|||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
) -> Result<bool, ReplyHandler::Error> {
|
) -> Result<bool, ReplyHandler::Error> {
|
||||||
self.reply_handler.handle_reply(
|
self.reply_handler.handle_reply(
|
||||||
|
self.id,
|
||||||
reply,
|
reply,
|
||||||
active_request,
|
active_request,
|
||||||
|
&self.tm_sender,
|
||||||
&self.verif_reporter,
|
&self.verif_reporter,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
&self.tm_sender,
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -583,7 +571,32 @@ pub(crate) mod tests {
|
|||||||
reply: &GenericMessage<Reply>,
|
reply: &GenericMessage<Reply>,
|
||||||
) -> Result<(), ReplyHandler::Error> {
|
) -> Result<(), ReplyHandler::Error> {
|
||||||
self.reply_handler
|
self.reply_handler
|
||||||
.handle_unrequested_reply(reply, &self.tm_sender)
|
.handle_unrequested_reply(self.id, reply, &self.tm_sender)
|
||||||
|
}
|
||||||
|
pub fn handle_request_timeout(
|
||||||
|
&mut self,
|
||||||
|
active_request_info: &ActiveRequestInfo,
|
||||||
|
time_stamp: &[u8],
|
||||||
|
) -> Result<(), ReplyHandler::Error> {
|
||||||
|
self.reply_handler.handle_request_timeout(
|
||||||
|
self.id,
|
||||||
|
active_request_info,
|
||||||
|
&self.tm_sender,
|
||||||
|
&self.verif_reporter,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct DummySender {}
|
||||||
|
|
||||||
|
/// Dummy sender component which does nothing on the [Self::send_tm] call.
|
||||||
|
///
|
||||||
|
/// Useful for unit tests.
|
||||||
|
impl EcssTmSenderCore for DummySender {
|
||||||
|
fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -593,9 +606,10 @@ pub(crate) mod tests {
|
|||||||
ActiveRequestInfo: ActiveRequestProvider,
|
ActiveRequestInfo: ActiveRequestProvider,
|
||||||
Request,
|
Request,
|
||||||
> {
|
> {
|
||||||
pub shared_verif_map: SharedVerificationMap,
|
pub id: ComponentId,
|
||||||
pub verif_reporter: TestVerificationReporter,
|
pub verif_reporter: TestVerificationReporter,
|
||||||
pub converter: Converter,
|
pub converter: Converter,
|
||||||
|
dummy_sender: DummySender,
|
||||||
current_request_id: Option<verification::RequestId>,
|
current_request_id: Option<verification::RequestId>,
|
||||||
current_packet: Option<Vec<u8>>,
|
current_packet: Option<Vec<u8>>,
|
||||||
phantom: std::marker::PhantomData<(ActiveRequestInfo, Request)>,
|
phantom: std::marker::PhantomData<(ActiveRequestInfo, Request)>,
|
||||||
@ -608,12 +622,12 @@ pub(crate) mod tests {
|
|||||||
> PusConverterTestbench<Converter, ActiveRequestInfo, Request>
|
> PusConverterTestbench<Converter, ActiveRequestInfo, Request>
|
||||||
{
|
{
|
||||||
pub fn new(converter: Converter) -> Self {
|
pub fn new(converter: Converter) -> Self {
|
||||||
let shared_verif_map = SharedVerificationMap::default();
|
let test_verif_reporter = TestVerificationReporter::default();
|
||||||
let test_verif_reporter = TestVerificationReporter::new(shared_verif_map.clone());
|
|
||||||
Self {
|
Self {
|
||||||
shared_verif_map,
|
id: TEST_COMPONENT_ID.raw(),
|
||||||
verif_reporter: test_verif_reporter,
|
verif_reporter: test_verif_reporter,
|
||||||
converter,
|
converter,
|
||||||
|
dummy_sender: DummySender::default(),
|
||||||
current_request_id: None,
|
current_request_id: None,
|
||||||
current_packet: None,
|
current_packet: None,
|
||||||
phantom: std::marker::PhantomData,
|
phantom: std::marker::PhantomData,
|
||||||
@ -625,7 +639,7 @@ pub(crate) mod tests {
|
|||||||
self.current_request_id = Some(verification::RequestId::new(tc));
|
self.current_request_id = Some(verification::RequestId::new(tc));
|
||||||
self.current_packet = Some(tc.to_vec().unwrap());
|
self.current_packet = Some(tc.to_vec().unwrap());
|
||||||
self.verif_reporter
|
self.verif_reporter
|
||||||
.acceptance_success(token, &[])
|
.acceptance_success(self.id, &self.dummy_sender, token, &[])
|
||||||
.expect("acceptance failed")
|
.expect("acceptance failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,16 +661,21 @@ pub(crate) mod tests {
|
|||||||
}
|
}
|
||||||
let current_packet = self.current_packet.take().unwrap();
|
let current_packet = self.current_packet.take().unwrap();
|
||||||
let tc_reader = PusTcReader::new(¤t_packet).unwrap();
|
let tc_reader = PusTcReader::new(¤t_packet).unwrap();
|
||||||
let (active_info, request) =
|
let (active_info, request) = self.converter.convert(
|
||||||
self.converter
|
self.id,
|
||||||
.convert(token, &tc_reader.0, time_stamp, &self.verif_reporter)?;
|
token,
|
||||||
|
&tc_reader.0,
|
||||||
|
&self.dummy_sender,
|
||||||
|
&self.verif_reporter,
|
||||||
|
time_stamp,
|
||||||
|
)?;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
active_info.token().request_id(),
|
active_info.token().request_id(),
|
||||||
self.request_id().expect("no request id is set")
|
self.request_id().expect("no request id is set")
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
active_info.target_id(),
|
active_info.target_id(),
|
||||||
TargetAndApidId::new(expected_apid, expected_apid_target).raw()
|
UniqueApidTargetId::new(expected_apid, expected_apid_target).raw()
|
||||||
);
|
);
|
||||||
Ok((active_info, request))
|
Ok((active_info, request))
|
||||||
}
|
}
|
||||||
@ -672,9 +691,9 @@ pub(crate) mod tests {
|
|||||||
> {
|
> {
|
||||||
pub service: PusTargetedRequestService<
|
pub service: PusTargetedRequestService<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
MpscTmAsVecSender,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscSender,
|
TestVerificationReporter,
|
||||||
RequestConverter,
|
RequestConverter,
|
||||||
ReplyHandler,
|
ReplyHandler,
|
||||||
ActiveRequestMap,
|
ActiveRequestMap,
|
||||||
@ -682,8 +701,7 @@ pub(crate) mod tests {
|
|||||||
RequestType,
|
RequestType,
|
||||||
ReplyType,
|
ReplyType,
|
||||||
>,
|
>,
|
||||||
pub verif_reporter: VerificationReporterWithVecMpscSender,
|
pub tm_funnel_rx: mpsc::Receiver<PusTmAsVec>,
|
||||||
pub tm_funnel_rx: mpsc::Receiver<Vec<u8>>,
|
|
||||||
pub pus_packet_tx: mpsc::Sender<EcssTcAndToken>,
|
pub pus_packet_tx: mpsc::Sender<EcssTcAndToken>,
|
||||||
pub reply_tx: mpsc::Sender<GenericMessage<ReplyType>>,
|
pub reply_tx: mpsc::Sender<GenericMessage<ReplyType>>,
|
||||||
pub request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
pub request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
|
||||||
|
@ -1,5 +1,16 @@
|
|||||||
|
use log::{error, warn};
|
||||||
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::requests::GenericRequestRouter;
|
||||||
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
|
use satrs::pus::verification::VerificationReporter;
|
||||||
|
use satrs::pus::{
|
||||||
|
DefaultActiveRequestMap, EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter,
|
||||||
|
EcssTcInVecConverter, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded,
|
||||||
|
PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
|
};
|
||||||
|
use satrs::request::GenericMessage;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
||||||
pus::{
|
pus::{
|
||||||
@ -9,9 +20,9 @@ use satrs::{
|
|||||||
VerificationToken,
|
VerificationToken,
|
||||||
},
|
},
|
||||||
ActivePusRequestStd, ActiveRequestProvider, EcssTmSenderCore, EcssTmtcError,
|
ActivePusRequestStd, ActiveRequestProvider, EcssTmSenderCore, EcssTmtcError,
|
||||||
GenericConversionError, PusReplyHandler, PusTcToRequestConverter, PusTmWrapper,
|
GenericConversionError, PusReplyHandler, PusTcToRequestConverter, PusTmVariant,
|
||||||
},
|
},
|
||||||
request::TargetAndApidId,
|
request::UniqueApidTargetId,
|
||||||
spacepackets::{
|
spacepackets::{
|
||||||
ecss::{
|
ecss::{
|
||||||
tc::PusTcReader,
|
tc::PusTcReader,
|
||||||
@ -20,10 +31,15 @@ use satrs::{
|
|||||||
},
|
},
|
||||||
SpHeader,
|
SpHeader,
|
||||||
},
|
},
|
||||||
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
use satrs_example::config::components::PUS_MODE_SERVICE;
|
||||||
use satrs_example::config::{mode_err, tmtc_err};
|
use satrs_example::config::{mode_err, tmtc_err};
|
||||||
|
|
||||||
use super::generic_pus_request_timeout_handler;
|
use super::{
|
||||||
|
create_verification_reporter, generic_pus_request_timeout_handler, PusTargetedRequestService,
|
||||||
|
TargetedPusService,
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct ModeReplyHandler {}
|
pub struct ModeReplyHandler {}
|
||||||
@ -33,7 +49,8 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
|
|
||||||
fn handle_unrequested_reply(
|
fn handle_unrequested_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
reply: &satrs::request::GenericMessage<ModeReply>,
|
_caller_id: ComponentId,
|
||||||
|
reply: &GenericMessage<ModeReply>,
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
_tm_sender: &impl EcssTmSenderCore,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
log::warn!("received unexpected reply for mode service 5: {reply:?}");
|
log::warn!("received unexpected reply for mode service 5: {reply:?}");
|
||||||
@ -42,30 +59,24 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
|
|
||||||
fn handle_reply(
|
fn handle_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
reply: &satrs::request::GenericMessage<ModeReply>,
|
caller_id: ComponentId,
|
||||||
|
reply: &GenericMessage<ModeReply>,
|
||||||
active_request: &ActivePusRequestStd,
|
active_request: &ActivePusRequestStd,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<bool, Self::Error> {
|
) -> Result<bool, Self::Error> {
|
||||||
let started_token: VerificationToken<TcStateStarted> = active_request
|
let started_token: VerificationToken<TcStateStarted> = active_request
|
||||||
.token()
|
.token()
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("invalid token state");
|
.expect("invalid token state");
|
||||||
match reply.message {
|
match reply.message {
|
||||||
ModeReply::ModeInfo(info) => {
|
|
||||||
log::warn!(
|
|
||||||
"received unrequest mode information for active request {:?}: {:?}",
|
|
||||||
active_request,
|
|
||||||
info
|
|
||||||
);
|
|
||||||
}
|
|
||||||
ModeReply::ModeReply(mode_reply) => {
|
ModeReply::ModeReply(mode_reply) => {
|
||||||
let mut source_data: [u8; 12] = [0; 12];
|
let mut source_data: [u8; 12] = [0; 12];
|
||||||
mode_reply
|
mode_reply
|
||||||
.write_to_be_bytes(&mut source_data)
|
.write_to_be_bytes(&mut source_data)
|
||||||
.expect("writing mode reply failed");
|
.expect("writing mode reply failed");
|
||||||
let req_id = verification::RequestId::from(reply.request_id);
|
let req_id = verification::RequestId::from(reply.request_id());
|
||||||
let mut sp_header = SpHeader::tm_unseg(req_id.packet_id().apid(), 0, 0)
|
let mut sp_header = SpHeader::tm_unseg(req_id.packet_id().apid(), 0, 0)
|
||||||
.expect("generating SP header failed");
|
.expect("generating SP header failed");
|
||||||
let sec_header = PusTmSecondaryHeader::new(
|
let sec_header = PusTmSecondaryHeader::new(
|
||||||
@ -76,18 +87,21 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
Some(time_stamp),
|
Some(time_stamp),
|
||||||
);
|
);
|
||||||
let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &source_data, true);
|
let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &source_data, true);
|
||||||
tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?;
|
tm_sender.send_tm(caller_id, PusTmVariant::Direct(pus_tm))?;
|
||||||
verification_handler
|
verification_handler.completion_success(
|
||||||
.completion_success(started_token, time_stamp)
|
caller_id,
|
||||||
.map_err(|e| e.0)?;
|
tm_sender,
|
||||||
|
started_token,
|
||||||
|
time_stamp,
|
||||||
|
)?;
|
||||||
}
|
}
|
||||||
ModeReply::CantReachMode(error_code) => {
|
ModeReply::CantReachMode(error_code) => {
|
||||||
verification_handler
|
verification_handler.completion_failure(
|
||||||
.completion_failure(
|
caller_id,
|
||||||
started_token,
|
tm_sender,
|
||||||
FailParams::new(time_stamp, &error_code, &[]),
|
started_token,
|
||||||
)
|
FailParams::new(time_stamp, &error_code, &[]),
|
||||||
.map_err(|e| e.0)?;
|
)?;
|
||||||
}
|
}
|
||||||
ModeReply::WrongMode { expected, reached } => {
|
ModeReply::WrongMode { expected, reached } => {
|
||||||
let mut error_info: [u8; 24] = [0; 24];
|
let mut error_info: [u8; 24] = [0; 24];
|
||||||
@ -97,16 +111,16 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
written_len += reached
|
written_len += reached
|
||||||
.write_to_be_bytes(&mut error_info[ModeAndSubmode::RAW_LEN..])
|
.write_to_be_bytes(&mut error_info[ModeAndSubmode::RAW_LEN..])
|
||||||
.expect("writing reached mode failed");
|
.expect("writing reached mode failed");
|
||||||
verification_handler
|
verification_handler.completion_failure(
|
||||||
.completion_failure(
|
caller_id,
|
||||||
started_token,
|
tm_sender,
|
||||||
FailParams::new(
|
started_token,
|
||||||
time_stamp,
|
FailParams::new(
|
||||||
&mode_err::WRONG_MODE,
|
time_stamp,
|
||||||
&error_info[..written_len],
|
&mode_err::WRONG_MODE,
|
||||||
),
|
&error_info[..written_len],
|
||||||
)
|
),
|
||||||
.map_err(|e| e.0)?;
|
)?;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Ok(true)
|
Ok(true)
|
||||||
@ -114,12 +128,15 @@ impl PusReplyHandler<ActivePusRequestStd, ModeReply> for ModeReplyHandler {
|
|||||||
|
|
||||||
fn handle_request_timeout(
|
fn handle_request_timeout(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
active_request: &ActivePusRequestStd,
|
active_request: &ActivePusRequestStd,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
_tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
generic_pus_request_timeout_handler(
|
generic_pus_request_timeout_handler(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
active_request,
|
active_request,
|
||||||
verification_handler,
|
verification_handler,
|
||||||
time_stamp,
|
time_stamp,
|
||||||
@ -137,16 +154,21 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
|
|
||||||
fn convert(
|
fn convert(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
|
||||||
|
caller_id: ComponentId,
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
tc: &PusTcReader,
|
tc: &PusTcReader,
|
||||||
time_stamp: &[u8],
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verif_reporter: &impl VerificationReportingProvider,
|
verif_reporter: &impl VerificationReportingProvider,
|
||||||
|
time_stamp: &[u8],
|
||||||
) -> Result<(ActivePusRequestStd, ModeRequest), Self::Error> {
|
) -> Result<(ActivePusRequestStd, ModeRequest), Self::Error> {
|
||||||
let subservice = tc.subservice();
|
let subservice = tc.subservice();
|
||||||
let user_data = tc.user_data();
|
let user_data = tc.user_data();
|
||||||
let not_enough_app_data = |expected: usize| {
|
let not_enough_app_data = |expected: usize| {
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA),
|
FailParams::new_no_fail_data(time_stamp, &tmtc_err::NOT_ENOUGH_APP_DATA),
|
||||||
)
|
)
|
||||||
@ -159,7 +181,7 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
if user_data.len() < core::mem::size_of::<u32>() {
|
if user_data.len() < core::mem::size_of::<u32>() {
|
||||||
return not_enough_app_data(4);
|
return not_enough_app_data(4);
|
||||||
}
|
}
|
||||||
let target_id_and_apid = TargetAndApidId::from_pus_tc(tc).unwrap();
|
let target_id_and_apid = UniqueApidTargetId::from_pus_tc(tc).unwrap();
|
||||||
let active_request =
|
let active_request =
|
||||||
ActivePusRequestStd::new(target_id_and_apid.into(), token, Duration::from_secs(30));
|
ActivePusRequestStd::new(target_id_and_apid.into(), token, Duration::from_secs(30));
|
||||||
let subservice_typed = Subservice::try_from(subservice);
|
let subservice_typed = Subservice::try_from(subservice);
|
||||||
@ -167,6 +189,8 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
// Invalid subservice
|
// Invalid subservice
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
caller_id,
|
||||||
|
tm_sender,
|
||||||
token,
|
token,
|
||||||
FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE),
|
FailParams::new_no_fail_data(time_stamp, &tmtc_err::INVALID_PUS_SUBSERVICE),
|
||||||
)
|
)
|
||||||
@ -196,8 +220,117 @@ impl PusTcToRequestConverter<ActivePusRequestStd, ModeRequest> for ModeRequestCo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_mode_service_static(
|
||||||
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
|
tc_pool: SharedStaticMemoryPool,
|
||||||
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
mode_router: GenericRequestRouter,
|
||||||
|
reply_receiver: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
|
) -> ModeServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
|
let mode_request_handler = PusTargetedRequestService::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_MODE_SERVICE.raw(),
|
||||||
|
pus_action_rx,
|
||||||
|
tm_sender,
|
||||||
|
create_verification_reporter(PUS_MODE_SERVICE.apid),
|
||||||
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
|
),
|
||||||
|
ModeRequestConverter::default(),
|
||||||
|
DefaultActiveRequestMap::default(),
|
||||||
|
ModeReplyHandler::default(),
|
||||||
|
mode_router,
|
||||||
|
reply_receiver,
|
||||||
|
);
|
||||||
|
ModeServiceWrapper {
|
||||||
|
service: mode_request_handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_mode_service_dynamic(
|
||||||
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
|
pus_action_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
|
mode_router: GenericRequestRouter,
|
||||||
|
reply_receiver: mpsc::Receiver<GenericMessage<ModeReply>>,
|
||||||
|
) -> ModeServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
|
let mode_request_handler = PusTargetedRequestService::new(
|
||||||
|
PusServiceHelper::new(
|
||||||
|
PUS_MODE_SERVICE.raw(),
|
||||||
|
pus_action_rx,
|
||||||
|
tm_funnel_tx,
|
||||||
|
create_verification_reporter(PUS_MODE_SERVICE.apid),
|
||||||
|
EcssTcInVecConverter::default(),
|
||||||
|
),
|
||||||
|
ModeRequestConverter::default(),
|
||||||
|
DefaultActiveRequestMap::default(),
|
||||||
|
ModeReplyHandler::default(),
|
||||||
|
mode_router,
|
||||||
|
reply_receiver,
|
||||||
|
);
|
||||||
|
ModeServiceWrapper {
|
||||||
|
service: mode_request_handler,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ModeServiceWrapper<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
|
pub(crate) service: PusTargetedRequestService<
|
||||||
|
MpscTcReceiver,
|
||||||
|
TmSender,
|
||||||
|
TcInMemConverter,
|
||||||
|
VerificationReporter,
|
||||||
|
ModeRequestConverter,
|
||||||
|
ModeReplyHandler,
|
||||||
|
DefaultActiveRequestMap<ActivePusRequestStd>,
|
||||||
|
ActivePusRequestStd,
|
||||||
|
ModeRequest,
|
||||||
|
ModeReply,
|
||||||
|
>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> TargetedPusService
|
||||||
|
for ModeServiceWrapper<TmSender, TcInMemConverter>
|
||||||
|
{
|
||||||
|
/// Returns [true] if the packet handling is finished.
|
||||||
|
fn poll_and_handle_next_tc(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
|
match self.service.poll_and_handle_next_tc(time_stamp) {
|
||||||
|
Ok(result) => match result {
|
||||||
|
PusPacketHandlerResult::RequestHandled => {}
|
||||||
|
PusPacketHandlerResult::RequestHandledPartialSuccess(e) => {
|
||||||
|
warn!("PUS mode service: partial packet handling success: {e:?}")
|
||||||
|
}
|
||||||
|
PusPacketHandlerResult::CustomSubservice(invalid, _) => {
|
||||||
|
warn!("PUS mode service: invalid subservice {invalid}");
|
||||||
|
}
|
||||||
|
PusPacketHandlerResult::SubserviceNotImplemented(subservice, _) => {
|
||||||
|
warn!("PUS mode service: {subservice} not implemented");
|
||||||
|
}
|
||||||
|
PusPacketHandlerResult::Empty => {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(error) => {
|
||||||
|
error!("PUS mode service: packet handling error: {error:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn poll_and_handle_next_reply(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
|
self.service
|
||||||
|
.poll_and_check_next_reply(time_stamp)
|
||||||
|
.unwrap_or_else(|e| {
|
||||||
|
warn!("PUS action service: Handling reply failed with error {e:?}");
|
||||||
|
false
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_for_request_timeouts(&mut self) {
|
||||||
|
self.service.check_for_request_timeouts();
|
||||||
|
}
|
||||||
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
use satrs::pus::test_util::{TEST_APID, TEST_COMPONENT_ID, TEST_UNIQUE_ID};
|
||||||
|
use satrs::request::MessageMetadata;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
||||||
pus::mode::Subservice,
|
pus::mode::Subservice,
|
||||||
@ -207,10 +340,11 @@ mod tests {
|
|||||||
SpHeader,
|
SpHeader,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use satrs_example::config::tmtc_err;
|
||||||
|
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
mode::ModeReplyHandler,
|
mode::ModeReplyHandler,
|
||||||
tests::{PusConverterTestbench, ReplyHandlerTestbench, TEST_APID, TEST_APID_TARGET_ID},
|
tests::{PusConverterTestbench, ReplyHandlerTestbench},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::ModeRequestConverter;
|
use super::ModeRequestConverter;
|
||||||
@ -221,11 +355,11 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcReadMode as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion has failed");
|
.expect("conversion has failed");
|
||||||
assert_eq!(req, ModeRequest::ReadMode);
|
assert_eq!(req, ModeRequest::ReadMode);
|
||||||
}
|
}
|
||||||
@ -237,14 +371,14 @@ mod tests {
|
|||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcSetMode as u8);
|
||||||
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
|
let mut app_data: [u8; 4 + ModeAndSubmode::RAW_LEN] = [0; 4 + ModeAndSubmode::RAW_LEN];
|
||||||
let mode_and_submode = ModeAndSubmode::new(2, 1);
|
let mode_and_submode = ModeAndSubmode::new(2, 1);
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
mode_and_submode
|
mode_and_submode
|
||||||
.write_to_be_bytes(&mut app_data[4..])
|
.write_to_be_bytes(&mut app_data[4..])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion has failed");
|
.expect("conversion has failed");
|
||||||
assert_eq!(req, ModeRequest::SetMode(mode_and_submode));
|
assert_eq!(req, ModeRequest::SetMode(mode_and_submode));
|
||||||
}
|
}
|
||||||
@ -255,11 +389,11 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8);
|
let sec_header = PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceMode as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion has failed");
|
.expect("conversion has failed");
|
||||||
assert_eq!(req, ModeRequest::AnnounceMode);
|
assert_eq!(req, ModeRequest::AnnounceMode);
|
||||||
}
|
}
|
||||||
@ -271,11 +405,11 @@ mod tests {
|
|||||||
let sec_header =
|
let sec_header =
|
||||||
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
|
PusTcSecondaryHeader::new_simple(200, Subservice::TcAnnounceModeRecursive as u8);
|
||||||
let mut app_data: [u8; 4] = [0; 4];
|
let mut app_data: [u8; 4] = [0; 4];
|
||||||
app_data[0..4].copy_from_slice(&TEST_APID_TARGET_ID.to_be_bytes());
|
app_data[0..4].copy_from_slice(&TEST_UNIQUE_ID.to_be_bytes());
|
||||||
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = testbench.add_tc(&tc);
|
let token = testbench.add_tc(&tc);
|
||||||
let (_active_req, req) = testbench
|
let (_active_req, req) = testbench
|
||||||
.convert(token, &[], TEST_APID, TEST_APID_TARGET_ID)
|
.convert(token, &[], TEST_APID, TEST_UNIQUE_ID)
|
||||||
.expect("conversion has failed");
|
.expect("conversion has failed");
|
||||||
assert_eq!(req, ModeRequest::AnnounceModeRecursive);
|
assert_eq!(req, ModeRequest::AnnounceModeRecursive);
|
||||||
}
|
}
|
||||||
@ -283,8 +417,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_unrequested_reply() {
|
fn reply_handling_unrequested_reply() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default());
|
||||||
let mode_reply = ModeReply::ModeInfo(ModeAndSubmode::new(5, 1));
|
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(5, 1));
|
||||||
let unrequested_reply = GenericMessage::new(10_u32, 15_u64, mode_reply);
|
let unrequested_reply =
|
||||||
|
GenericMessage::new(MessageMetadata::new(10_u32, 15_u64), mode_reply);
|
||||||
// Right now this function does not do a lot. We simply check that it does not panic or do
|
// Right now this function does not do a lot. We simply check that it does not panic or do
|
||||||
// weird stuff.
|
// weird stuff.
|
||||||
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
let result = testbench.handle_unrequested_reply(&unrequested_reply);
|
||||||
@ -294,9 +429,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn reply_handling_reply_timeout() {
|
fn reply_handling_reply_timeout() {
|
||||||
let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default());
|
let mut testbench = ReplyHandlerTestbench::new(ModeReplyHandler::default());
|
||||||
// TODO: Start a request, then time it out with the API and check verification completion
|
let (req_id, active_request) = testbench.add_tc(TEST_APID, TEST_UNIQUE_ID, &[]);
|
||||||
// failure.
|
let result = testbench.handle_request_timeout(&active_request, &[]);
|
||||||
// testbench.reply_handler.handle_request_timeout(active_request, verification_handler, time_stamp, tm_sender)
|
assert!(result.is_ok());
|
||||||
// testbench.default_timeout = Duration::from_millis(50);
|
testbench.verif_reporter.assert_completion_failure(
|
||||||
|
TEST_COMPONENT_ID.raw(),
|
||||||
|
req_id,
|
||||||
|
None,
|
||||||
|
tmtc_err::REQUEST_TIMEOUT.raw() as u64,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,23 +1,18 @@
|
|||||||
use std::sync::mpsc;
|
use std::sync::mpsc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use crate::pus::create_verification_reporter;
|
||||||
use log::{error, info, warn};
|
use log::{error, info, warn};
|
||||||
use satrs::pool::{PoolProvider, StaticMemoryPool, StoreAddr};
|
use satrs::pool::{PoolProvider, StaticMemoryPool};
|
||||||
use satrs::pus::scheduler::{PusScheduler, TcInfo};
|
use satrs::pus::scheduler::{PusScheduler, TcInfo};
|
||||||
use satrs::pus::scheduler_srv::PusService11SchedHandler;
|
use satrs::pus::scheduler_srv::PusSchedServiceHandler;
|
||||||
use satrs::pus::verification::std_mod::{
|
use satrs::pus::verification::VerificationReporter;
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
};
|
|
||||||
use satrs::pus::verification::VerificationReportingProvider;
|
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
EcssTcAndToken, EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter,
|
||||||
EcssTcReceiverCore, EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper,
|
EcssTmSenderCore, MpscTcReceiver, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded,
|
||||||
TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
|
PusPacketHandlerResult, PusServiceHelper, PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
TmInSharedPoolSenderWithId,
|
|
||||||
};
|
};
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
use satrs_example::config::components::PUS_SCHED_SERVICE;
|
||||||
use satrs::ComponentId;
|
|
||||||
use satrs_example::config::{ComponentIdList, PUS_APID};
|
|
||||||
|
|
||||||
use crate::tmtc::PusTcSourceProviderSharedPool;
|
use crate::tmtc::PusTcSourceProviderSharedPool;
|
||||||
|
|
||||||
@ -55,14 +50,12 @@ impl TcReleaser for mpsc::Sender<Vec<u8>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Pus11Wrapper<
|
pub struct SchedulingServiceWrapper<
|
||||||
TcReceiver: EcssTcReceiverCore,
|
|
||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> {
|
> {
|
||||||
pub pus_11_handler: PusService11SchedHandler<
|
pub pus_11_handler: PusSchedServiceHandler<
|
||||||
TcReceiver,
|
MpscTcReceiver,
|
||||||
TmSender,
|
TmSender,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
@ -73,12 +66,8 @@ pub struct Pus11Wrapper<
|
|||||||
pub tc_releaser: Box<dyn TcReleaser + Send>,
|
pub tc_releaser: Box<dyn TcReleaser + Send>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
SchedulingServiceWrapper<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> Pus11Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
pub fn release_tcs(&mut self) {
|
pub fn release_tcs(&mut self) {
|
||||||
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
|
let releaser = |enabled: bool, info: &TcInfo, tc: &[u8]| -> bool {
|
||||||
@ -132,42 +121,24 @@ impl<
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_scheduler_service_static(
|
pub fn create_scheduler_service_static(
|
||||||
shared_tm_store: SharedTmPool,
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
tm_funnel_tx: mpsc::SyncSender<StoreAddr>,
|
|
||||||
verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
tc_releaser: PusTcSourceProviderSharedPool,
|
tc_releaser: PusTcSourceProviderSharedPool,
|
||||||
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
sched_tc_pool: StaticMemoryPool,
|
sched_tc_pool: StaticMemoryPool,
|
||||||
) -> Pus11Wrapper<
|
) -> SchedulingServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
|
||||||
EcssTcInSharedStoreConverter,
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
> {
|
|
||||||
let sched_srv_tm_sender = TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::PusSched as ComponentId,
|
|
||||||
"PUS_11_TM_SENDER",
|
|
||||||
shared_tm_store.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let sched_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusSched as ComponentId,
|
|
||||||
"PUS_11_TC_RECV",
|
|
||||||
pus_sched_rx,
|
|
||||||
);
|
|
||||||
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
||||||
.expect("Creating PUS Scheduler failed");
|
.expect("Creating PUS Scheduler failed");
|
||||||
let pus_11_handler = PusService11SchedHandler::new(
|
let pus_11_handler = PusSchedServiceHandler::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
sched_srv_receiver,
|
PUS_SCHED_SERVICE.raw(),
|
||||||
sched_srv_tm_sender,
|
pus_sched_rx,
|
||||||
PUS_APID,
|
tm_sender,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_SCHED_SERVICE.apid),
|
||||||
EcssTcInSharedStoreConverter::new(tc_releaser.clone_backing_pool(), 2048),
|
EcssTcInSharedStoreConverter::new(tc_releaser.clone_backing_pool(), 2048),
|
||||||
),
|
),
|
||||||
scheduler,
|
scheduler,
|
||||||
);
|
);
|
||||||
Pus11Wrapper {
|
SchedulingServiceWrapper {
|
||||||
pus_11_handler,
|
pus_11_handler,
|
||||||
sched_tc_pool,
|
sched_tc_pool,
|
||||||
releaser_buf: [0; 4096],
|
releaser_buf: [0; 4096],
|
||||||
@ -176,40 +147,26 @@ pub fn create_scheduler_service_static(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_scheduler_service_dynamic(
|
pub fn create_scheduler_service_dynamic(
|
||||||
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
verif_reporter: VerificationReporterWithVecMpscSender,
|
|
||||||
tc_source_sender: mpsc::Sender<Vec<u8>>,
|
tc_source_sender: mpsc::Sender<Vec<u8>>,
|
||||||
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
sched_tc_pool: StaticMemoryPool,
|
sched_tc_pool: StaticMemoryPool,
|
||||||
) -> Pus11Wrapper<
|
) -> SchedulingServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
MpscTcReceiver,
|
//let sched_srv_receiver =
|
||||||
TmAsVecSenderWithMpsc,
|
//MpscTcReceiver::new(PUS_SCHED_SERVICE.raw(), "PUS_11_TC_RECV", pus_sched_rx);
|
||||||
EcssTcInVecConverter,
|
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
> {
|
|
||||||
let sched_srv_tm_sender = TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::PusSched as ComponentId,
|
|
||||||
"PUS_11_TM_SENDER",
|
|
||||||
tm_funnel_tx,
|
|
||||||
);
|
|
||||||
let sched_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusSched as ComponentId,
|
|
||||||
"PUS_11_TC_RECV",
|
|
||||||
pus_sched_rx,
|
|
||||||
);
|
|
||||||
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5))
|
||||||
.expect("Creating PUS Scheduler failed");
|
.expect("Creating PUS Scheduler failed");
|
||||||
let pus_11_handler = PusService11SchedHandler::new(
|
let pus_11_handler = PusSchedServiceHandler::new(
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
sched_srv_receiver,
|
PUS_SCHED_SERVICE.raw(),
|
||||||
sched_srv_tm_sender,
|
pus_sched_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_SCHED_SERVICE.apid),
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
),
|
),
|
||||||
scheduler,
|
scheduler,
|
||||||
);
|
);
|
||||||
Pus11Wrapper {
|
SchedulingServiceWrapper {
|
||||||
pus_11_handler,
|
pus_11_handler,
|
||||||
sched_tc_pool,
|
sched_tc_pool,
|
||||||
releaser_buf: [0; 4096],
|
releaser_buf: [0; 4096],
|
||||||
|
@ -1,62 +1,33 @@
|
|||||||
|
use crate::pus::mode::ModeServiceWrapper;
|
||||||
|
use derive_new::new;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
pus::{
|
pus::{EcssTcInMemConverter, EcssTmSenderCore},
|
||||||
verification::VerificationReportingProvider, EcssTcInMemConverter, EcssTcReceiverCore,
|
|
||||||
EcssTmSenderCore,
|
|
||||||
},
|
|
||||||
spacepackets::time::{cds, TimeWriter},
|
spacepackets::time::{cds, TimeWriter},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
action::Pus8Wrapper, event::Pus5Wrapper, hk::Pus3Wrapper, scheduler::Pus11Wrapper,
|
action::ActionServiceWrapper, event::EventServiceWrapper, hk::HkServiceWrapper,
|
||||||
test::Service17CustomWrapper, TargetedPusService,
|
scheduler::SchedulingServiceWrapper, test::TestCustomServiceWrapper, TargetedPusService,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PusStack<
|
#[derive(new)]
|
||||||
TcReceiver: EcssTcReceiverCore,
|
pub struct PusStack<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter> {
|
||||||
TmSender: EcssTmSenderCore,
|
test_srv: TestCustomServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
hk_srv_wrapper: HkServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
event_srv: EventServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
> {
|
action_srv_wrapper: ActionServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
event_srv: Pus5Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
schedule_srv: SchedulingServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
hk_srv_wrapper: Pus3Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
mode_srv: ModeServiceWrapper<TmSender, TcInMemConverter>,
|
||||||
action_srv_wrapper: Pus8Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
schedule_srv: Pus11Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
test_srv: Service17CustomWrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
PusStack<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> PusStack<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
pub fn new(
|
|
||||||
hk_srv: Pus3Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
event_srv: Pus5Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
action_srv: Pus8Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
schedule_srv: Pus11Wrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
|
||||||
test_srv: Service17CustomWrapper<
|
|
||||||
TcReceiver,
|
|
||||||
TmSender,
|
|
||||||
TcInMemConverter,
|
|
||||||
VerificationReporter,
|
|
||||||
>,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
|
||||||
event_srv,
|
|
||||||
action_srv_wrapper: action_srv,
|
|
||||||
schedule_srv,
|
|
||||||
test_srv,
|
|
||||||
hk_srv_wrapper: hk_srv,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn periodic_operation(&mut self) {
|
pub fn periodic_operation(&mut self) {
|
||||||
// Release all telecommands which reached their release time before calling the service
|
// Release all telecommands which reached their release time before calling the service
|
||||||
// handlers.
|
// handlers.
|
||||||
self.schedule_srv.release_tcs();
|
self.schedule_srv.release_tcs();
|
||||||
let time_stamp = cds::TimeProvider::from_now_with_u16_days()
|
let time_stamp = cds::CdsTime::now_with_u16_days()
|
||||||
.expect("time stamp generation error")
|
.expect("time stamp generation error")
|
||||||
.to_vec()
|
.to_vec()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
@ -84,10 +55,15 @@ impl<
|
|||||||
self.hk_srv_wrapper.poll_and_handle_next_tc(&time_stamp),
|
self.hk_srv_wrapper.poll_and_handle_next_tc(&time_stamp),
|
||||||
Some(self.hk_srv_wrapper.poll_and_handle_next_reply(&time_stamp)),
|
Some(self.hk_srv_wrapper.poll_and_handle_next_reply(&time_stamp)),
|
||||||
);
|
);
|
||||||
|
is_srv_finished(
|
||||||
|
self.mode_srv.poll_and_handle_next_tc(&time_stamp),
|
||||||
|
Some(self.mode_srv.poll_and_handle_next_reply(&time_stamp)),
|
||||||
|
);
|
||||||
if nothing_to_do {
|
if nothing_to_do {
|
||||||
// Timeout checking is only done once.
|
// Timeout checking is only done once.
|
||||||
self.action_srv_wrapper.check_for_request_timeouts();
|
self.action_srv_wrapper.check_for_request_timeouts();
|
||||||
self.hk_srv_wrapper.check_for_request_timeouts();
|
self.hk_srv_wrapper.check_for_request_timeouts();
|
||||||
|
self.mode_srv.check_for_request_timeouts();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,115 +1,71 @@
|
|||||||
|
use crate::pus::create_verification_reporter;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use satrs::params::Params;
|
use satrs::params::Params;
|
||||||
use satrs::pool::{SharedStaticMemoryPool, StoreAddr};
|
use satrs::pool::SharedStaticMemoryPool;
|
||||||
use satrs::pus::test::PusService17TestHandler;
|
use satrs::pus::test::PusService17TestHandler;
|
||||||
use satrs::pus::verification::{FailParams, VerificationReportingProvider};
|
use satrs::pus::verification::{FailParams, VerificationReporter, VerificationReportingProvider};
|
||||||
use satrs::pus::verification::{
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
};
|
|
||||||
use satrs::pus::{
|
use satrs::pus::{
|
||||||
EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
EcssTcAndToken, EcssTcInMemConverter, EcssTcInVecConverter, EcssTmSenderCore, MpscTcReceiver,
|
||||||
EcssTmSenderCore, MpscTcReceiver, PusPacketHandlerResult, PusServiceHelper,
|
MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult, PusServiceHelper,
|
||||||
TmAsVecSenderWithId, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
|
PusTmAsVec, PusTmInPool, TmInSharedPoolSender,
|
||||||
TmInSharedPoolSenderWithId,
|
|
||||||
};
|
};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::PusPacket;
|
use satrs::spacepackets::ecss::PusPacket;
|
||||||
use satrs::spacepackets::time::cds::TimeProvider;
|
use satrs::spacepackets::time::cds::CdsTime;
|
||||||
use satrs::spacepackets::time::TimeWriter;
|
use satrs::spacepackets::time::TimeWriter;
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
|
||||||
use satrs::ComponentId;
|
|
||||||
use satrs::{events::EventU32, pus::EcssTcInSharedStoreConverter};
|
use satrs::{events::EventU32, pus::EcssTcInSharedStoreConverter};
|
||||||
use satrs_example::config::{tmtc_err, ComponentIdList, PUS_APID, TEST_EVENT};
|
use satrs_example::config::components::PUS_TEST_SERVICE;
|
||||||
use std::sync::mpsc::{self, Sender};
|
use satrs_example::config::{tmtc_err, TEST_EVENT};
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
pub fn create_test_service_static(
|
pub fn create_test_service_static(
|
||||||
shared_tm_store: SharedTmPool,
|
tm_sender: TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>,
|
||||||
tm_funnel_tx: mpsc::SyncSender<StoreAddr>,
|
|
||||||
verif_reporter: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
tc_pool: SharedStaticMemoryPool,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
|
event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
|
||||||
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
) -> Service17CustomWrapper<
|
) -> TestCustomServiceWrapper<MpscTmInSharedPoolSenderBounded, EcssTcInSharedStoreConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
|
||||||
EcssTcInSharedStoreConverter,
|
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
> {
|
|
||||||
let test_srv_tm_sender = TmInSharedPoolSenderWithId::new(
|
|
||||||
ComponentIdList::PusTest as ComponentId,
|
|
||||||
"PUS_17_TM_SENDER",
|
|
||||||
shared_tm_store.clone(),
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let test_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusTest as ComponentId,
|
|
||||||
"PUS_17_TC_RECV",
|
|
||||||
pus_test_rx,
|
|
||||||
);
|
|
||||||
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
||||||
test_srv_receiver,
|
PUS_TEST_SERVICE.raw(),
|
||||||
test_srv_tm_sender,
|
pus_test_rx,
|
||||||
PUS_APID,
|
tm_sender,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_TEST_SERVICE.apid),
|
||||||
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
EcssTcInSharedStoreConverter::new(tc_pool, 2048),
|
||||||
));
|
));
|
||||||
Service17CustomWrapper {
|
TestCustomServiceWrapper {
|
||||||
handler: pus17_handler,
|
handler: pus17_handler,
|
||||||
test_srv_event_sender: event_sender,
|
test_srv_event_sender: event_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_test_service_dynamic(
|
pub fn create_test_service_dynamic(
|
||||||
tm_funnel_tx: mpsc::Sender<Vec<u8>>,
|
tm_funnel_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
verif_reporter: VerificationReporterWithVecMpscSender,
|
|
||||||
event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
|
event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
|
||||||
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
|
||||||
) -> Service17CustomWrapper<
|
) -> TestCustomServiceWrapper<MpscTmAsVecSender, EcssTcInVecConverter> {
|
||||||
MpscTcReceiver,
|
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
EcssTcInVecConverter,
|
|
||||||
VerificationReporterWithVecMpscSender,
|
|
||||||
> {
|
|
||||||
let test_srv_tm_sender = TmAsVecSenderWithId::new(
|
|
||||||
ComponentIdList::PusTest as ComponentId,
|
|
||||||
"PUS_17_TM_SENDER",
|
|
||||||
tm_funnel_tx.clone(),
|
|
||||||
);
|
|
||||||
let test_srv_receiver = MpscTcReceiver::new(
|
|
||||||
ComponentIdList::PusTest as ComponentId,
|
|
||||||
"PUS_17_TC_RECV",
|
|
||||||
pus_test_rx,
|
|
||||||
);
|
|
||||||
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
|
||||||
test_srv_receiver,
|
PUS_TEST_SERVICE.raw(),
|
||||||
test_srv_tm_sender,
|
pus_test_rx,
|
||||||
PUS_APID,
|
tm_funnel_tx,
|
||||||
verif_reporter.clone(),
|
create_verification_reporter(PUS_TEST_SERVICE.apid),
|
||||||
EcssTcInVecConverter::default(),
|
EcssTcInVecConverter::default(),
|
||||||
));
|
));
|
||||||
Service17CustomWrapper {
|
TestCustomServiceWrapper {
|
||||||
handler: pus17_handler,
|
handler: pus17_handler,
|
||||||
test_srv_event_sender: event_sender,
|
test_srv_event_sender: event_sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Service17CustomWrapper<
|
pub struct TestCustomServiceWrapper<
|
||||||
TcReceiver: EcssTcReceiverCore,
|
|
||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> {
|
> {
|
||||||
pub handler:
|
pub handler:
|
||||||
PusService17TestHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
PusService17TestHandler<MpscTcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
|
||||||
pub test_srv_event_sender: Sender<(EventU32, Option<Params>)>,
|
pub test_srv_event_sender: mpsc::Sender<(EventU32, Option<Params>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<
|
impl<TmSender: EcssTmSenderCore, TcInMemConverter: EcssTcInMemConverter>
|
||||||
TcReceiver: EcssTcReceiverCore,
|
TestCustomServiceWrapper<TmSender, TcInMemConverter>
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
> Service17CustomWrapper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
|
||||||
{
|
{
|
||||||
pub fn poll_and_handle_next_packet(&mut self, time_stamp: &[u8]) -> bool {
|
pub fn poll_and_handle_next_packet(&mut self, time_stamp: &[u8]) -> bool {
|
||||||
let res = self.handler.poll_and_handle_next_tc(time_stamp);
|
let res = self.handler.poll_and_handle_next_tc(time_stamp);
|
||||||
@ -139,7 +95,7 @@ impl<
|
|||||||
.tc_slice_raw(),
|
.tc_slice_raw(),
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let time_stamper = TimeProvider::from_now_with_u16_days().unwrap();
|
let time_stamper = CdsTime::now_with_u16_days().unwrap();
|
||||||
let mut stamp_buf: [u8; 7] = [0; 7];
|
let mut stamp_buf: [u8; 7] = [0; 7];
|
||||||
time_stamper.write_to_bytes(&mut stamp_buf).unwrap();
|
time_stamper.write_to_bytes(&mut stamp_buf).unwrap();
|
||||||
if subservice == 128 {
|
if subservice == 128 {
|
||||||
@ -151,12 +107,22 @@ impl<
|
|||||||
.handler
|
.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(token, &stamp_buf)
|
.start_success(
|
||||||
|
self.handler.service_helper.common.id,
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
token,
|
||||||
|
&stamp_buf,
|
||||||
|
)
|
||||||
.expect("Error sending start success");
|
.expect("Error sending start success");
|
||||||
self.handler
|
self.handler
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, &stamp_buf)
|
.completion_success(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
start_token,
|
||||||
|
&stamp_buf,
|
||||||
|
)
|
||||||
.expect("Error sending completion success");
|
.expect("Error sending completion success");
|
||||||
} else {
|
} else {
|
||||||
let fail_data = [tc.subservice()];
|
let fail_data = [tc.subservice()];
|
||||||
@ -164,6 +130,8 @@ impl<
|
|||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_failure(
|
.start_failure(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
token,
|
token,
|
||||||
FailParams::new(
|
FailParams::new(
|
||||||
&stamp_buf,
|
&stamp_buf,
|
||||||
|
@ -4,15 +4,17 @@ use std::sync::mpsc;
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
use satrs::action::ActionRequest;
|
use satrs::action::ActionRequest;
|
||||||
use satrs::hk::HkRequest;
|
use satrs::hk::HkRequest;
|
||||||
|
use satrs::mode::ModeRequest;
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken,
|
FailParams, TcStateAccepted, VerificationReportingProvider, VerificationToken,
|
||||||
};
|
};
|
||||||
use satrs::pus::{ActiveRequestProvider, GenericRoutingError, PusRequestRouter};
|
use satrs::pus::{ActiveRequestProvider, EcssTmSenderCore, GenericRoutingError, PusRequestRouter};
|
||||||
use satrs::queue::GenericSendError;
|
use satrs::queue::GenericSendError;
|
||||||
use satrs::request::{GenericMessage, RequestId};
|
use satrs::request::{GenericMessage, MessageMetadata};
|
||||||
use satrs::spacepackets::ecss::tc::PusTcReader;
|
use satrs::spacepackets::ecss::tc::PusTcReader;
|
||||||
use satrs::spacepackets::ecss::PusPacket;
|
use satrs::spacepackets::ecss::PusPacket;
|
||||||
use satrs::ComponentId;
|
use satrs::ComponentId;
|
||||||
|
use satrs_example::config::components::PUS_ROUTING_SERVICE;
|
||||||
use satrs_example::config::tmtc_err;
|
use satrs_example::config::tmtc_err;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
@ -22,19 +24,32 @@ pub enum CompositeRequest {
|
|||||||
Action(ActionRequest),
|
Action(ActionRequest),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Clone)]
|
||||||
pub struct GenericRequestRouter(
|
pub struct GenericRequestRouter {
|
||||||
pub HashMap<ComponentId, mpsc::Sender<GenericMessage<CompositeRequest>>>,
|
pub id: ComponentId,
|
||||||
);
|
// All messages which do not have a dedicated queue.
|
||||||
|
pub composite_router_map: HashMap<ComponentId, mpsc::Sender<GenericMessage<CompositeRequest>>>,
|
||||||
|
pub mode_router_map: HashMap<ComponentId, mpsc::Sender<GenericMessage<ModeRequest>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for GenericRequestRouter {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
id: PUS_ROUTING_SERVICE.raw(),
|
||||||
|
composite_router_map: Default::default(),
|
||||||
|
mode_router_map: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
impl GenericRequestRouter {
|
impl GenericRequestRouter {
|
||||||
pub(crate) fn handle_error_generic(
|
pub(crate) fn handle_error_generic(
|
||||||
&self,
|
&self,
|
||||||
active_request: &impl ActiveRequestProvider,
|
active_request: &impl ActiveRequestProvider,
|
||||||
tc: &PusTcReader,
|
tc: &PusTcReader,
|
||||||
error: GenericRoutingError,
|
error: GenericRoutingError,
|
||||||
time_stamp: &[u8],
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verif_reporter: &impl VerificationReportingProvider,
|
verif_reporter: &impl VerificationReportingProvider,
|
||||||
|
time_stamp: &[u8],
|
||||||
) {
|
) {
|
||||||
warn!(
|
warn!(
|
||||||
"Routing request for service {} failed: {error:?}",
|
"Routing request for service {} failed: {error:?}",
|
||||||
@ -50,6 +65,8 @@ impl GenericRequestRouter {
|
|||||||
fail_data.copy_from_slice(&id.to_be_bytes());
|
fail_data.copy_from_slice(&id.to_be_bytes());
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
self.id,
|
||||||
|
tm_sender,
|
||||||
accepted_token,
|
accepted_token,
|
||||||
FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data),
|
FailParams::new(time_stamp, &tmtc_err::UNKNOWN_TARGET_ID, &fail_data),
|
||||||
)
|
)
|
||||||
@ -60,6 +77,8 @@ impl GenericRequestRouter {
|
|||||||
fail_data.copy_from_slice(&active_request.target_id().to_be_bytes());
|
fail_data.copy_from_slice(&active_request.target_id().to_be_bytes());
|
||||||
verif_reporter
|
verif_reporter
|
||||||
.completion_failure(
|
.completion_failure(
|
||||||
|
self.id,
|
||||||
|
tm_sender,
|
||||||
accepted_token,
|
accepted_token,
|
||||||
FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data),
|
FailParams::new(time_stamp, &tmtc_err::ROUTING_ERROR, &fail_data),
|
||||||
)
|
)
|
||||||
@ -73,16 +92,14 @@ impl PusRequestRouter<HkRequest> for GenericRequestRouter {
|
|||||||
|
|
||||||
fn route(
|
fn route(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
source_id: ComponentId,
|
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
hk_request: HkRequest,
|
hk_request: HkRequest,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
if let Some(sender) = self.0.get(&target_id) {
|
if let Some(sender) = self.composite_router_map.get(&target_id) {
|
||||||
sender
|
sender
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
request_id,
|
requestor_info,
|
||||||
source_id,
|
|
||||||
CompositeRequest::Hk(hk_request),
|
CompositeRequest::Hk(hk_request),
|
||||||
))
|
))
|
||||||
.map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?;
|
.map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?;
|
||||||
@ -97,16 +114,14 @@ impl PusRequestRouter<ActionRequest> for GenericRequestRouter {
|
|||||||
|
|
||||||
fn route(
|
fn route(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
source_id: ComponentId,
|
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
action_request: ActionRequest,
|
action_request: ActionRequest,
|
||||||
) -> Result<(), Self::Error> {
|
) -> Result<(), Self::Error> {
|
||||||
if let Some(sender) = self.0.get(&target_id) {
|
if let Some(sender) = self.composite_router_map.get(&target_id) {
|
||||||
sender
|
sender
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
request_id,
|
requestor_info,
|
||||||
source_id,
|
|
||||||
CompositeRequest::Action(action_request),
|
CompositeRequest::Action(action_request),
|
||||||
))
|
))
|
||||||
.map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?;
|
.map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?;
|
||||||
@ -115,3 +130,22 @@ impl PusRequestRouter<ActionRequest> for GenericRequestRouter {
|
|||||||
Err(GenericRoutingError::UnknownTargetId(target_id))
|
Err(GenericRoutingError::UnknownTargetId(target_id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PusRequestRouter<ModeRequest> for GenericRequestRouter {
|
||||||
|
type Error = GenericRoutingError;
|
||||||
|
|
||||||
|
fn route(
|
||||||
|
&self,
|
||||||
|
requestor_info: MessageMetadata,
|
||||||
|
target_id: ComponentId,
|
||||||
|
request: ModeRequest,
|
||||||
|
) -> Result<(), Self::Error> {
|
||||||
|
if let Some(sender) = self.mode_router_map.get(&target_id) {
|
||||||
|
sender
|
||||||
|
.send(GenericMessage::new(requestor_info, request))
|
||||||
|
.map_err(|_| GenericRoutingError::Send(GenericSendError::RxDisconnected))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Err(GenericRoutingError::UnknownTargetId(target_id))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -10,11 +10,16 @@ use satrs::{
|
|||||||
spacepackets::PacketId,
|
spacepackets::PacketId,
|
||||||
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
|
tmtc::{CcsdsDistributor, CcsdsError, ReceivesCcsdsTc, TmPacketSourceCore},
|
||||||
};
|
};
|
||||||
use satrs_example::config::PUS_APID;
|
use satrs_example::config::components;
|
||||||
|
|
||||||
use crate::ccsds::CcsdsReceiver;
|
use crate::ccsds::CcsdsReceiver;
|
||||||
|
|
||||||
pub const PACKET_ID_LOOKUP: &[PacketId] = &[PacketId::const_tc(true, PUS_APID)];
|
pub const PACKET_ID_LOOKUP: &[PacketId] = &[
|
||||||
|
PacketId::const_tc(true, components::Apid::GenericPus as u16),
|
||||||
|
PacketId::const_tc(true, components::Apid::EventTm as u16),
|
||||||
|
PacketId::const_tc(true, components::Apid::Acs as u16),
|
||||||
|
PacketId::const_tc(true, components::Apid::Sched as u16),
|
||||||
|
];
|
||||||
|
|
||||||
#[derive(Default, Clone)]
|
#[derive(Default, Clone)]
|
||||||
pub struct SyncTcpTmSource {
|
pub struct SyncTcpTmSource {
|
||||||
|
@ -4,8 +4,9 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
use log::info;
|
use log::info;
|
||||||
|
use satrs::pus::{PusTmAsVec, PusTmInPool};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
pool::{PoolProvider, StoreAddr},
|
pool::PoolProvider,
|
||||||
seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore},
|
seq_count::{CcsdsSimpleSeqCountProvider, SequenceCountProviderCore},
|
||||||
spacepackets::{
|
spacepackets::{
|
||||||
ecss::{tm::PusTmZeroCopyWriter, PusPacket},
|
ecss::{tm::PusTmZeroCopyWriter, PusPacket},
|
||||||
@ -77,16 +78,16 @@ impl TmFunnelCommon {
|
|||||||
pub struct TmFunnelStatic {
|
pub struct TmFunnelStatic {
|
||||||
common: TmFunnelCommon,
|
common: TmFunnelCommon,
|
||||||
shared_tm_store: SharedTmPool,
|
shared_tm_store: SharedTmPool,
|
||||||
tm_funnel_rx: mpsc::Receiver<StoreAddr>,
|
tm_funnel_rx: mpsc::Receiver<PusTmInPool>,
|
||||||
tm_server_tx: mpsc::SyncSender<StoreAddr>,
|
tm_server_tx: mpsc::SyncSender<PusTmInPool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TmFunnelStatic {
|
impl TmFunnelStatic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_tm_store: SharedTmPool,
|
shared_tm_store: SharedTmPool,
|
||||||
sync_tm_tcp_source: SyncTcpTmSource,
|
sync_tm_tcp_source: SyncTcpTmSource,
|
||||||
tm_funnel_rx: mpsc::Receiver<StoreAddr>,
|
tm_funnel_rx: mpsc::Receiver<PusTmInPool>,
|
||||||
tm_server_tx: mpsc::SyncSender<StoreAddr>,
|
tm_server_tx: mpsc::SyncSender<PusTmInPool>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
||||||
@ -97,14 +98,14 @@ impl TmFunnelStatic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn operation(&mut self) {
|
pub fn operation(&mut self) {
|
||||||
if let Ok(addr) = self.tm_funnel_rx.recv() {
|
if let Ok(pus_tm_in_pool) = self.tm_funnel_rx.recv() {
|
||||||
// Read the TM, set sequence counter and message counter, and finally update
|
// Read the TM, set sequence counter and message counter, and finally update
|
||||||
// the CRC.
|
// the CRC.
|
||||||
let shared_pool = self.shared_tm_store.clone_backing_pool();
|
let shared_pool = self.shared_tm_store.clone_backing_pool();
|
||||||
let mut pool_guard = shared_pool.write().expect("Locking TM pool failed");
|
let mut pool_guard = shared_pool.write().expect("Locking TM pool failed");
|
||||||
let mut tm_copy = Vec::new();
|
let mut tm_copy = Vec::new();
|
||||||
pool_guard
|
pool_guard
|
||||||
.modify(&addr, |buf| {
|
.modify(&pus_tm_in_pool.store_addr, |buf| {
|
||||||
let zero_copy_writer = PusTmZeroCopyWriter::new(buf, MIN_CDS_FIELD_LEN)
|
let zero_copy_writer = PusTmZeroCopyWriter::new(buf, MIN_CDS_FIELD_LEN)
|
||||||
.expect("Creating TM zero copy writer failed");
|
.expect("Creating TM zero copy writer failed");
|
||||||
self.common.apply_packet_processing(zero_copy_writer);
|
self.common.apply_packet_processing(zero_copy_writer);
|
||||||
@ -112,7 +113,7 @@ impl TmFunnelStatic {
|
|||||||
})
|
})
|
||||||
.expect("Reading TM from pool failed");
|
.expect("Reading TM from pool failed");
|
||||||
self.tm_server_tx
|
self.tm_server_tx
|
||||||
.send(addr)
|
.send(pus_tm_in_pool)
|
||||||
.expect("Sending TM to server failed");
|
.expect("Sending TM to server failed");
|
||||||
// We could also do this step in the update closure, but I'd rather avoid this, could
|
// We could also do this step in the update closure, but I'd rather avoid this, could
|
||||||
// lead to nested locking.
|
// lead to nested locking.
|
||||||
@ -123,15 +124,15 @@ impl TmFunnelStatic {
|
|||||||
|
|
||||||
pub struct TmFunnelDynamic {
|
pub struct TmFunnelDynamic {
|
||||||
common: TmFunnelCommon,
|
common: TmFunnelCommon,
|
||||||
tm_funnel_rx: mpsc::Receiver<Vec<u8>>,
|
tm_funnel_rx: mpsc::Receiver<PusTmAsVec>,
|
||||||
tm_server_tx: mpsc::Sender<Vec<u8>>,
|
tm_server_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TmFunnelDynamic {
|
impl TmFunnelDynamic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
sync_tm_tcp_source: SyncTcpTmSource,
|
sync_tm_tcp_source: SyncTcpTmSource,
|
||||||
tm_funnel_rx: mpsc::Receiver<Vec<u8>>,
|
tm_funnel_rx: mpsc::Receiver<PusTmAsVec>,
|
||||||
tm_server_tx: mpsc::Sender<Vec<u8>>,
|
tm_server_tx: mpsc::Sender<PusTmAsVec>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
common: TmFunnelCommon::new(sync_tm_tcp_source),
|
||||||
@ -144,13 +145,13 @@ impl TmFunnelDynamic {
|
|||||||
if let Ok(mut tm) = self.tm_funnel_rx.recv() {
|
if let Ok(mut tm) = self.tm_funnel_rx.recv() {
|
||||||
// Read the TM, set sequence counter and message counter, and finally update
|
// Read the TM, set sequence counter and message counter, and finally update
|
||||||
// the CRC.
|
// the CRC.
|
||||||
let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm, MIN_CDS_FIELD_LEN)
|
let zero_copy_writer = PusTmZeroCopyWriter::new(&mut tm.packet, MIN_CDS_FIELD_LEN)
|
||||||
.expect("Creating TM zero copy writer failed");
|
.expect("Creating TM zero copy writer failed");
|
||||||
self.common.apply_packet_processing(zero_copy_writer);
|
self.common.apply_packet_processing(zero_copy_writer);
|
||||||
|
self.common.sync_tm_tcp_source.add_tm(&tm.packet);
|
||||||
self.tm_server_tx
|
self.tm_server_tx
|
||||||
.send(tm.clone())
|
.send(tm)
|
||||||
.expect("Sending TM to server failed");
|
.expect("Sending TM to server failed");
|
||||||
self.common.sync_tm_tcp_source.add_tm(&tm);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use log::warn;
|
use log::warn;
|
||||||
use satrs::pus::verification::std_mod::{
|
use satrs::pus::{
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
EcssTcAndToken, MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, ReceivesEcssPusTc,
|
||||||
};
|
};
|
||||||
use satrs::pus::{EcssTcAndToken, ReceivesEcssPusTc};
|
|
||||||
use satrs::spacepackets::SpHeader;
|
use satrs::spacepackets::SpHeader;
|
||||||
use std::sync::mpsc::{self, Receiver, SendError, Sender, SyncSender, TryRecvError};
|
use std::sync::mpsc::{self, Receiver, SendError, Sender, SyncSender, TryRecvError};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
@ -100,14 +99,14 @@ pub struct TcSourceTaskStatic {
|
|||||||
shared_tc_pool: SharedTcPool,
|
shared_tc_pool: SharedTcPool,
|
||||||
tc_receiver: Receiver<StoreAddr>,
|
tc_receiver: Receiver<StoreAddr>,
|
||||||
tc_buf: [u8; 4096],
|
tc_buf: [u8; 4096],
|
||||||
pus_receiver: PusReceiver<VerificationReporterWithSharedPoolMpscBoundedSender>,
|
pus_receiver: PusReceiver<MpscTmInSharedPoolSenderBounded>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcSourceTaskStatic {
|
impl TcSourceTaskStatic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
shared_tc_pool: SharedTcPool,
|
shared_tc_pool: SharedTcPool,
|
||||||
tc_receiver: Receiver<StoreAddr>,
|
tc_receiver: Receiver<StoreAddr>,
|
||||||
pus_receiver: PusReceiver<VerificationReporterWithSharedPoolMpscBoundedSender>,
|
pus_receiver: PusReceiver<MpscTmInSharedPoolSenderBounded>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
shared_tc_pool,
|
shared_tc_pool,
|
||||||
@ -164,13 +163,13 @@ impl TcSourceTaskStatic {
|
|||||||
// TC source components where the heap is the backing memory of the received telecommands.
|
// TC source components where the heap is the backing memory of the received telecommands.
|
||||||
pub struct TcSourceTaskDynamic {
|
pub struct TcSourceTaskDynamic {
|
||||||
pub tc_receiver: Receiver<Vec<u8>>,
|
pub tc_receiver: Receiver<Vec<u8>>,
|
||||||
pus_receiver: PusReceiver<VerificationReporterWithVecMpscSender>,
|
pus_receiver: PusReceiver<MpscTmAsVecSender>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TcSourceTaskDynamic {
|
impl TcSourceTaskDynamic {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tc_receiver: Receiver<Vec<u8>>,
|
tc_receiver: Receiver<Vec<u8>>,
|
||||||
pus_receiver: PusReceiver<VerificationReporterWithVecMpscSender>,
|
pus_receiver: PusReceiver<MpscTmAsVecSender>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
use std::{
|
use std::net::{SocketAddr, UdpSocket};
|
||||||
net::{SocketAddr, UdpSocket},
|
use std::sync::mpsc;
|
||||||
sync::mpsc::Receiver,
|
|
||||||
};
|
|
||||||
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
|
use satrs::pus::{PusTmAsVec, PusTmInPool};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
hal::std::udp_server::{ReceiveResult, UdpTcServer},
|
hal::std::udp_server::{ReceiveResult, UdpTcServer},
|
||||||
pool::{PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr},
|
pool::{PoolProviderWithGuards, SharedStaticMemoryPool},
|
||||||
tmtc::CcsdsError,
|
tmtc::CcsdsError,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -15,20 +14,20 @@ pub trait UdpTmHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct StaticUdpTmHandler {
|
pub struct StaticUdpTmHandler {
|
||||||
pub tm_rx: Receiver<StoreAddr>,
|
pub tm_rx: mpsc::Receiver<PusTmInPool>,
|
||||||
pub tm_store: SharedStaticMemoryPool,
|
pub tm_store: SharedStaticMemoryPool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpTmHandler for StaticUdpTmHandler {
|
impl UdpTmHandler for StaticUdpTmHandler {
|
||||||
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, &recv_addr: &SocketAddr) {
|
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, &recv_addr: &SocketAddr) {
|
||||||
while let Ok(addr) = self.tm_rx.try_recv() {
|
while let Ok(pus_tm_in_pool) = self.tm_rx.try_recv() {
|
||||||
let store_lock = self.tm_store.write();
|
let store_lock = self.tm_store.write();
|
||||||
if store_lock.is_err() {
|
if store_lock.is_err() {
|
||||||
warn!("Locking TM store failed");
|
warn!("Locking TM store failed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let mut store_lock = store_lock.unwrap();
|
let mut store_lock = store_lock.unwrap();
|
||||||
let pg = store_lock.read_with_guard(addr);
|
let pg = store_lock.read_with_guard(pus_tm_in_pool.store_addr);
|
||||||
let read_res = pg.read_as_vec();
|
let read_res = pg.read_as_vec();
|
||||||
if read_res.is_err() {
|
if read_res.is_err() {
|
||||||
warn!("Error reading TM pool data");
|
warn!("Error reading TM pool data");
|
||||||
@ -44,20 +43,20 @@ impl UdpTmHandler for StaticUdpTmHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub struct DynamicUdpTmHandler {
|
pub struct DynamicUdpTmHandler {
|
||||||
pub tm_rx: Receiver<Vec<u8>>,
|
pub tm_rx: mpsc::Receiver<PusTmAsVec>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UdpTmHandler for DynamicUdpTmHandler {
|
impl UdpTmHandler for DynamicUdpTmHandler {
|
||||||
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, recv_addr: &SocketAddr) {
|
fn send_tm_to_udp_client(&mut self, socket: &UdpSocket, recv_addr: &SocketAddr) {
|
||||||
while let Ok(tm) = self.tm_rx.try_recv() {
|
while let Ok(tm) = self.tm_rx.try_recv() {
|
||||||
if tm.len() > 9 {
|
if tm.packet.len() > 9 {
|
||||||
let service = tm[7];
|
let service = tm.packet[7];
|
||||||
let subservice = tm[8];
|
let subservice = tm.packet[8];
|
||||||
info!("Sending PUS TM[{service},{subservice}]")
|
info!("Sending PUS TM[{service},{subservice}]")
|
||||||
} else {
|
} else {
|
||||||
info!("Sending PUS TM");
|
info!("Sending PUS TM");
|
||||||
}
|
}
|
||||||
let result = socket.send_to(&tm, recv_addr);
|
let result = socket.send_to(&tm.packet, recv_addr);
|
||||||
if let Err(e) = result {
|
if let Err(e) = result {
|
||||||
warn!("Sending TM with UDP socket failed: {e}")
|
warn!("Sending TM with UDP socket failed: {e}")
|
||||||
}
|
}
|
||||||
@ -120,7 +119,7 @@ mod tests {
|
|||||||
},
|
},
|
||||||
tmtc::ReceivesTcCore,
|
tmtc::ReceivesTcCore,
|
||||||
};
|
};
|
||||||
use satrs_example::config::{OBSW_SERVER_ADDR, PUS_APID};
|
use satrs_example::config::{components, OBSW_SERVER_ADDR};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -178,7 +177,7 @@ mod tests {
|
|||||||
udp_tc_server,
|
udp_tc_server,
|
||||||
tm_handler,
|
tm_handler,
|
||||||
};
|
};
|
||||||
let mut sph = SpHeader::tc_unseg(PUS_APID, 0, 0).unwrap();
|
let mut sph = SpHeader::tc_unseg(components::Apid::GenericPus as u16, 0, 0).unwrap();
|
||||||
let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true)
|
let ping_tc = PusTcCreator::new_simple(&mut sph, 17, 1, None, true)
|
||||||
.to_vec()
|
.to_vec()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
@ -28,7 +28,6 @@ features = ["full"]
|
|||||||
trybuild = { version = "1", features = ["diff"] }
|
trybuild = { version = "1", features = ["diff"] }
|
||||||
|
|
||||||
[dev-dependencies.satrs-shared]
|
[dev-dependencies.satrs-shared]
|
||||||
# satrs-shared = "0.1.2"
|
|
||||||
path = "../../satrs-shared"
|
path = "../../satrs-shared"
|
||||||
version = "0.1.3"
|
version = "0.1.3"
|
||||||
|
|
||||||
|
@ -18,7 +18,9 @@ default-features = false
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.spacepackets]
|
[dependencies.spacepackets]
|
||||||
|
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||||
version = "0.11.0-rc.0"
|
version = "0.11.0-rc.0"
|
||||||
|
branch = "main"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
@ -71,7 +71,9 @@ features = ["all"]
|
|||||||
optional = true
|
optional = true
|
||||||
|
|
||||||
[dependencies.spacepackets]
|
[dependencies.spacepackets]
|
||||||
|
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
|
||||||
version = "0.11.0-rc.0"
|
version = "0.11.0-rc.0"
|
||||||
|
branch = "main"
|
||||||
default-features = false
|
default-features = false
|
||||||
|
|
||||||
[dependencies.cobs]
|
[dependencies.cobs]
|
||||||
|
@ -19,8 +19,8 @@ impl HkRequest {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
pub enum HkRequestVariant {
|
pub enum HkRequestVariant {
|
||||||
OneShot,
|
OneShot,
|
||||||
Enable,
|
EnablePeriodic,
|
||||||
Disable,
|
DisablePeriodic,
|
||||||
ModifyCollectionInterval(CollectionIntervalFactor),
|
ModifyCollectionInterval(CollectionIntervalFactor),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ pub use std_mod::*;
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
queue::GenericTargetedMessagingError,
|
queue::GenericTargetedMessagingError,
|
||||||
request::{GenericMessage, MessageReceiver, MessageReceiverWithId, RequestId},
|
request::{GenericMessage, MessageMetadata, MessageReceiver, MessageReceiverWithId, RequestId},
|
||||||
ComponentId,
|
ComponentId,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -109,6 +109,8 @@ impl TargetedModeCommand {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum ModeRequest {
|
pub enum ModeRequest {
|
||||||
|
/// Mode information. Can be used to notify other components of changed modes.
|
||||||
|
ModeInfo(ModeAndSubmode),
|
||||||
SetMode(ModeAndSubmode),
|
SetMode(ModeAndSubmode),
|
||||||
ReadMode,
|
ReadMode,
|
||||||
AnnounceMode,
|
AnnounceMode,
|
||||||
@ -125,8 +127,6 @@ pub struct TargetedModeRequest {
|
|||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum ModeReply {
|
pub enum ModeReply {
|
||||||
/// Unrequest mode information. Can be used to notify other components of changed modes.
|
|
||||||
ModeInfo(ModeAndSubmode),
|
|
||||||
/// Reply to a mode request to confirm the commanded mode was reached.
|
/// Reply to a mode request to confirm the commanded mode was reached.
|
||||||
ModeReply(ModeAndSubmode),
|
ModeReply(ModeAndSubmode),
|
||||||
// Can not reach the commanded mode. Contains a reason as a [ResultU16].
|
// Can not reach the commanded mode. Contains a reason as a [ResultU16].
|
||||||
@ -184,13 +184,20 @@ impl From<GenericTargetedMessagingError> for ModeError {
|
|||||||
pub trait ModeRequestHandler: ModeProvider {
|
pub trait ModeRequestHandler: ModeProvider {
|
||||||
fn start_transition(
|
fn start_transition(
|
||||||
&mut self,
|
&mut self,
|
||||||
request_id: RequestId,
|
requestor: MessageMetadata,
|
||||||
sender_id: ComponentId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
) -> Result<(), ModeError>;
|
) -> Result<(), ModeError>;
|
||||||
|
|
||||||
fn announce_mode(&self, request_id: RequestId, sender_id: ComponentId, recursive: bool);
|
fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool);
|
||||||
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>;
|
fn handle_mode_reached(
|
||||||
|
&mut self,
|
||||||
|
requestor_info: Option<MessageMetadata>,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
|
fn send_mode_reply(
|
||||||
|
&self,
|
||||||
|
requestor_info: MessageMetadata,
|
||||||
|
reply: ModeReply,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ModeReplyReceiver {
|
pub trait ModeReplyReceiver {
|
||||||
@ -210,10 +217,10 @@ impl<R: MessageReceiver<ModeReply>> ModeReplyReceiver for MessageReceiverWithId<
|
|||||||
pub trait ModeReplySender {
|
pub trait ModeReplySender {
|
||||||
fn local_channel_id(&self) -> ComponentId;
|
fn local_channel_id(&self) -> ComponentId;
|
||||||
|
|
||||||
|
/// The requestor is assumed to be the target of the reply.
|
||||||
fn send_mode_reply(
|
fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
|
||||||
reply: ModeReply,
|
reply: ModeReply,
|
||||||
) -> Result<(), GenericTargetedMessagingError>;
|
) -> Result<(), GenericTargetedMessagingError>;
|
||||||
}
|
}
|
||||||
@ -225,7 +232,7 @@ pub mod alloc_mod {
|
|||||||
mode::ModeRequest,
|
mode::ModeRequest,
|
||||||
queue::GenericTargetedMessagingError,
|
queue::GenericTargetedMessagingError,
|
||||||
request::{
|
request::{
|
||||||
MessageSender, MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId,
|
MessageMetadata, MessageSender, MessageSenderAndReceiver, MessageSenderMap,
|
||||||
RequestAndReplySenderAndReceiver, RequestId,
|
RequestAndReplySenderAndReceiver, RequestId,
|
||||||
},
|
},
|
||||||
ComponentId,
|
ComponentId,
|
||||||
@ -236,12 +243,11 @@ pub mod alloc_mod {
|
|||||||
impl<S: MessageSender<ModeReply>> MessageSenderMap<ModeReply, S> {
|
impl<S: MessageSender<ModeReply>> MessageSenderMap<ModeReply, S> {
|
||||||
pub fn send_mode_reply(
|
pub fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
local_id: ComponentId,
|
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, local_id, target_id, request)
|
self.send_message(requestor_info, target_id, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_reply_target(&mut self, target_id: ComponentId, request_sender: S) {
|
pub fn add_reply_target(&mut self, target_id: ComponentId, request_sender: S) {
|
||||||
@ -249,6 +255,7 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
impl<S: MessageSender<ModeReply>> ModeReplySender for MessageSenderMapWithId<ModeReply, S> {
|
impl<S: MessageSender<ModeReply>> ModeReplySender for MessageSenderMapWithId<ModeReply, S> {
|
||||||
fn send_mode_reply(
|
fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
@ -263,6 +270,7 @@ pub mod alloc_mod {
|
|||||||
self.local_channel_id
|
self.local_channel_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
impl<FROM, S: MessageSender<ModeReply>, R: MessageReceiver<FROM>> ModeReplySender
|
impl<FROM, S: MessageSender<ModeReply>, R: MessageReceiver<FROM>> ModeReplySender
|
||||||
for MessageSenderAndReceiver<ModeReply, FROM, S, R>
|
for MessageSenderAndReceiver<ModeReply, FROM, S, R>
|
||||||
@ -273,14 +281,12 @@ pub mod alloc_mod {
|
|||||||
|
|
||||||
fn send_mode_reply(
|
fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
|
||||||
request: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_map.send_mode_reply(
|
self.message_sender_map.send_mode_reply(
|
||||||
request_id,
|
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
||||||
self.local_channel_id(),
|
requestor_info.sender_id(),
|
||||||
target_id,
|
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -324,14 +330,12 @@ pub mod alloc_mod {
|
|||||||
|
|
||||||
fn send_mode_reply(
|
fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
|
||||||
request: ModeReply,
|
request: ModeReply,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.reply_sender_map.send_mode_reply(
|
self.reply_sender_map.send_mode_reply(
|
||||||
request_id,
|
MessageMetadata::new(requestor_info.request_id(), self.local_channel_id()),
|
||||||
self.local_channel_id(),
|
requestor_info.sender_id(),
|
||||||
target_id,
|
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -368,11 +372,14 @@ pub mod alloc_mod {
|
|||||||
|
|
||||||
pub fn send_mode_reply(
|
pub fn send_mode_reply(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
target_id: ComponentId,
|
|
||||||
reply: ModeReply,
|
reply: ModeReply,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, target_id, reply)
|
self.send_message(
|
||||||
|
requestor_info.request_id(),
|
||||||
|
requestor_info.sender_id(),
|
||||||
|
reply,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -405,12 +412,11 @@ pub mod alloc_mod {
|
|||||||
impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
|
impl<S: MessageSender<ModeRequest>> MessageSenderMap<ModeRequest, S> {
|
||||||
pub fn send_mode_request(
|
pub fn send_mode_request(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
local_id: ComponentId,
|
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.send_message(request_id, local_id, target_id, request)
|
self.send_message(requestor_info, target_id, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S) {
|
pub fn add_request_target(&mut self, target_id: ComponentId, request_sender: S) {
|
||||||
@ -418,6 +424,7 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
|
impl<S: MessageSender<ModeRequest>> ModeRequestSender for MessageSenderMapWithId<ModeRequest, S> {
|
||||||
fn local_channel_id(&self) -> ComponentId {
|
fn local_channel_id(&self) -> ComponentId {
|
||||||
self.local_channel_id
|
self.local_channel_id
|
||||||
@ -432,6 +439,7 @@ pub mod alloc_mod {
|
|||||||
self.send_message(request_id, target_id, request)
|
self.send_message(request_id, target_id, request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
|
impl<TO, S: MessageSender<TO>, R: MessageReceiver<ModeRequest>> ModeRequestReceiver
|
||||||
for MessageSenderAndReceiver<TO, ModeRequest, S, R>
|
for MessageSenderAndReceiver<TO, ModeRequest, S, R>
|
||||||
@ -457,8 +465,7 @@ pub mod alloc_mod {
|
|||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_map.send_mode_request(
|
self.message_sender_map.send_mode_request(
|
||||||
request_id,
|
MessageMetadata::new(request_id, self.local_channel_id()),
|
||||||
self.local_channel_id(),
|
|
||||||
target_id,
|
target_id,
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
@ -499,8 +506,7 @@ pub mod alloc_mod {
|
|||||||
request: ModeRequest,
|
request: ModeRequest,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.request_sender_map.send_mode_request(
|
self.request_sender_map.send_mode_request(
|
||||||
request_id,
|
MessageMetadata::new(request_id, self.local_channel_id()),
|
||||||
self.local_channel_id(),
|
|
||||||
target_id,
|
target_id,
|
||||||
request,
|
request,
|
||||||
)
|
)
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
action::{ActionId, ActionRequest},
|
action::{ActionId, ActionRequest},
|
||||||
params::Params,
|
params::Params,
|
||||||
request::{GenericMessage, RequestId},
|
request::{GenericMessage, MessageMetadata, RequestId},
|
||||||
ComponentId,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
use satrs_shared::res_code::ResultU16;
|
use satrs_shared::res_code::ResultU16;
|
||||||
@ -57,12 +56,11 @@ pub type GenericActionReplyPus = GenericMessage<PusActionReply>;
|
|||||||
|
|
||||||
impl GenericActionReplyPus {
|
impl GenericActionReplyPus {
|
||||||
pub fn new_action_reply(
|
pub fn new_action_reply(
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
sender_id: ComponentId,
|
|
||||||
action_id: ActionId,
|
action_id: ActionId,
|
||||||
reply: ActionReplyVariant,
|
reply: ActionReplyVariant,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::new(request_id, sender_id, PusActionReply::new(action_id, reply))
|
Self::new(requestor_info, PusActionReply::new(action_id, reply))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ use crate::pus::{source_buffer_large_enough, EcssTmtcError};
|
|||||||
use spacepackets::ecss::tm::PusTmCreator;
|
use spacepackets::ecss::tm::PusTmCreator;
|
||||||
use spacepackets::ecss::tm::PusTmSecondaryHeader;
|
use spacepackets::ecss::tm::PusTmSecondaryHeader;
|
||||||
use spacepackets::ecss::{EcssEnumeration, PusError};
|
use spacepackets::ecss::{EcssEnumeration, PusError};
|
||||||
|
use spacepackets::ByteConversionError;
|
||||||
use spacepackets::{SpHeader, MAX_APID};
|
use spacepackets::{SpHeader, MAX_APID};
|
||||||
|
|
||||||
use crate::pus::EcssTmSenderCore;
|
use crate::pus::EcssTmSenderCore;
|
||||||
@ -9,145 +10,125 @@ use crate::pus::EcssTmSenderCore;
|
|||||||
pub use alloc_mod::EventReporter;
|
pub use alloc_mod::EventReporter;
|
||||||
pub use spacepackets::ecss::event::*;
|
pub use spacepackets::ecss::event::*;
|
||||||
|
|
||||||
pub struct EventReporterBase {
|
pub struct EventReportCreator {
|
||||||
msg_count: u16,
|
|
||||||
apid: u16,
|
apid: u16,
|
||||||
pub dest_id: u16,
|
pub dest_id: u16,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventReporterBase {
|
impl EventReportCreator {
|
||||||
pub fn new(apid: u16) -> Option<Self> {
|
pub fn new(apid: u16) -> Option<Self> {
|
||||||
if apid > MAX_APID {
|
if apid > MAX_APID {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
Some(Self {
|
Some(Self {
|
||||||
msg_count: 0,
|
// msg_count: 0,
|
||||||
dest_id: 0,
|
dest_id: 0,
|
||||||
apid,
|
apid,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_info(
|
pub fn event_info<'time, 'src_data>(
|
||||||
&mut self,
|
&self,
|
||||||
buf: &mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
time_stamp: &'time [u8],
|
||||||
time_stamp: &[u8],
|
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
buf,
|
src_data_buf,
|
||||||
Subservice::TmInfoReport,
|
Subservice::TmInfoReport,
|
||||||
sender,
|
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
aux_data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_low_severity(
|
pub fn event_low_severity<'time, 'src_data>(
|
||||||
&mut self,
|
&self,
|
||||||
buf: &mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
time_stamp: &'time [u8],
|
||||||
time_stamp: &[u8],
|
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
buf,
|
src_data_buf,
|
||||||
Subservice::TmLowSeverityReport,
|
Subservice::TmLowSeverityReport,
|
||||||
sender,
|
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
aux_data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_medium_severity(
|
pub fn event_medium_severity<'time, 'src_data>(
|
||||||
&mut self,
|
&self,
|
||||||
buf: &mut [u8],
|
buf: &'src_data mut [u8],
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
time_stamp: &'time [u8],
|
||||||
time_stamp: &[u8],
|
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
buf,
|
buf,
|
||||||
Subservice::TmMediumSeverityReport,
|
Subservice::TmMediumSeverityReport,
|
||||||
sender,
|
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
aux_data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_high_severity(
|
pub fn event_high_severity<'time, 'src_data>(
|
||||||
&mut self,
|
&self,
|
||||||
buf: &mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
time_stamp: &'time [u8],
|
||||||
time_stamp: &[u8],
|
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
self.generate_and_send_generic_tm(
|
self.generate_and_send_generic_tm(
|
||||||
buf,
|
src_data_buf,
|
||||||
Subservice::TmHighSeverityReport,
|
Subservice::TmHighSeverityReport,
|
||||||
sender,
|
|
||||||
time_stamp,
|
time_stamp,
|
||||||
event_id,
|
event_id,
|
||||||
aux_data,
|
aux_data,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_and_send_generic_tm(
|
fn generate_and_send_generic_tm<'time, 'src_data>(
|
||||||
&mut self,
|
&self,
|
||||||
buf: &mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
subservice: Subservice,
|
subservice: Subservice,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
time_stamp: &'time [u8],
|
||||||
time_stamp: &[u8],
|
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
let tm = self.generate_generic_event_tm(buf, subservice, time_stamp, event_id, aux_data)?;
|
self.generate_generic_event_tm(src_data_buf, subservice, time_stamp, event_id, aux_data)
|
||||||
sender.send_tm(tm.into())?;
|
|
||||||
self.msg_count += 1;
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_generic_event_tm<'a>(
|
fn generate_generic_event_tm<'time, 'src_data>(
|
||||||
&'a self,
|
&self,
|
||||||
buf: &'a mut [u8],
|
src_data_buf: &'src_data mut [u8],
|
||||||
subservice: Subservice,
|
subservice: Subservice,
|
||||||
time_stamp: &'a [u8],
|
time_stamp: &'time [u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&'src_data [u8]>,
|
||||||
) -> Result<PusTmCreator, EcssTmtcError> {
|
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
|
||||||
let mut src_data_len = event_id.size();
|
let mut src_data_len = event_id.size();
|
||||||
if let Some(aux_data) = aux_data {
|
if let Some(aux_data) = aux_data {
|
||||||
src_data_len += aux_data.len();
|
src_data_len += aux_data.len();
|
||||||
}
|
}
|
||||||
source_buffer_large_enough(buf.len(), src_data_len)?;
|
source_buffer_large_enough(src_data_buf.len(), src_data_len)?;
|
||||||
let mut sp_header = SpHeader::tm_unseg(self.apid, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tm_unseg(self.apid, 0, 0).unwrap();
|
||||||
let sec_header = PusTmSecondaryHeader::new(
|
let sec_header =
|
||||||
5,
|
PusTmSecondaryHeader::new(5, subservice.into(), 0, self.dest_id, Some(time_stamp));
|
||||||
subservice.into(),
|
|
||||||
self.msg_count,
|
|
||||||
self.dest_id,
|
|
||||||
Some(time_stamp),
|
|
||||||
);
|
|
||||||
let mut current_idx = 0;
|
let mut current_idx = 0;
|
||||||
event_id
|
event_id.write_to_be_bytes(&mut src_data_buf[0..event_id.size()])?;
|
||||||
.write_to_be_bytes(&mut buf[0..event_id.size()])
|
|
||||||
.map_err(PusError::ByteConversion)?;
|
|
||||||
current_idx += event_id.size();
|
current_idx += event_id.size();
|
||||||
if let Some(aux_data) = aux_data {
|
if let Some(aux_data) = aux_data {
|
||||||
buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
|
src_data_buf[current_idx..current_idx + aux_data.len()].copy_from_slice(aux_data);
|
||||||
current_idx += aux_data.len();
|
current_idx += aux_data.len();
|
||||||
}
|
}
|
||||||
Ok(PusTmCreator::new(
|
Ok(PusTmCreator::new(
|
||||||
&mut sp_header,
|
&mut sp_header,
|
||||||
sec_header,
|
sec_header,
|
||||||
&buf[0..current_idx],
|
&src_data_buf[0..current_idx],
|
||||||
true,
|
true,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
@ -156,84 +137,95 @@ impl EventReporterBase {
|
|||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
mod alloc_mod {
|
mod alloc_mod {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use crate::ComponentId;
|
||||||
use alloc::vec;
|
use alloc::vec;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
use core::cell::RefCell;
|
||||||
|
|
||||||
pub struct EventReporter {
|
pub struct EventReporter {
|
||||||
source_data_buf: Vec<u8>,
|
id: ComponentId,
|
||||||
pub reporter: EventReporterBase,
|
// Use interior mutability pattern here. This is just an intermediate buffer to the PUS event packet
|
||||||
|
// generation.
|
||||||
|
source_data_buf: RefCell<Vec<u8>>,
|
||||||
|
pub report_creator: EventReportCreator,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventReporter {
|
impl EventReporter {
|
||||||
pub fn new(apid: u16, max_event_id_and_aux_data_size: usize) -> Option<Self> {
|
pub fn new(
|
||||||
let reporter = EventReporterBase::new(apid)?;
|
id: ComponentId,
|
||||||
|
apid: u16,
|
||||||
|
max_event_id_and_aux_data_size: usize,
|
||||||
|
) -> Option<Self> {
|
||||||
|
let reporter = EventReportCreator::new(apid)?;
|
||||||
Some(Self {
|
Some(Self {
|
||||||
source_data_buf: vec![0; max_event_id_and_aux_data_size],
|
id,
|
||||||
reporter,
|
source_data_buf: RefCell::new(vec![0; max_event_id_and_aux_data_size]),
|
||||||
|
report_creator: reporter,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_info(
|
pub fn event_info(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
self.reporter.event_info(
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
self.source_data_buf.as_mut_slice(),
|
let tm_creator = self
|
||||||
sender,
|
.report_creator
|
||||||
time_stamp,
|
.event_info(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
|
||||||
event_id,
|
.map_err(PusError::ByteConversion)?;
|
||||||
aux_data,
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_low_severity(
|
pub fn event_low_severity(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
self.reporter.event_low_severity(
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
self.source_data_buf.as_mut_slice(),
|
let tm_creator = self
|
||||||
sender,
|
.report_creator
|
||||||
time_stamp,
|
.event_low_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
|
||||||
event_id,
|
.map_err(PusError::ByteConversion)?;
|
||||||
aux_data,
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_medium_severity(
|
pub fn event_medium_severity(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
self.reporter.event_medium_severity(
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
self.source_data_buf.as_mut_slice(),
|
let tm_creator = self
|
||||||
sender,
|
.report_creator
|
||||||
time_stamp,
|
.event_medium_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
|
||||||
event_id,
|
.map_err(PusError::ByteConversion)?;
|
||||||
aux_data,
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
)
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn event_high_severity(
|
pub fn event_high_severity(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event_id: impl EcssEnumeration,
|
event_id: impl EcssEnumeration,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
) -> Result<(), EcssTmtcError> {
|
) -> Result<(), EcssTmtcError> {
|
||||||
self.reporter.event_high_severity(
|
let mut mut_buf = self.source_data_buf.borrow_mut();
|
||||||
self.source_data_buf.as_mut_slice(),
|
let tm_creator = self
|
||||||
sender,
|
.report_creator
|
||||||
time_stamp,
|
.event_high_severity(mut_buf.as_mut_slice(), time_stamp, event_id, aux_data)
|
||||||
event_id,
|
.map_err(PusError::ByteConversion)?;
|
||||||
aux_data,
|
sender.send_tm(self.id, tm_creator.into())?;
|
||||||
)
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -243,7 +235,7 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::events::{EventU32, Severity};
|
use crate::events::{EventU32, Severity};
|
||||||
use crate::pus::tests::CommonTmInfo;
|
use crate::pus::tests::CommonTmInfo;
|
||||||
use crate::pus::{EcssChannel, PusTmWrapper};
|
use crate::pus::{ChannelWithId, PusTmVariant};
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use spacepackets::ByteConversionError;
|
use spacepackets::ByteConversionError;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -268,19 +260,19 @@ mod tests {
|
|||||||
pub service_queue: RefCell<VecDeque<TmInfo>>,
|
pub service_queue: RefCell<VecDeque<TmInfo>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssChannel for TestSender {
|
impl ChannelWithId for TestSender {
|
||||||
fn id(&self) -> ComponentId {
|
fn id(&self) -> ComponentId {
|
||||||
0
|
0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for TestSender {
|
impl EcssTmSenderCore for TestSender {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(&self, sender_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(_) => {
|
PusTmVariant::InStore(_) => {
|
||||||
panic!("TestSender: unexpected call with address");
|
panic!("TestSender: unexpected call with address");
|
||||||
}
|
}
|
||||||
PusTmWrapper::Direct(tm) => {
|
PusTmVariant::Direct(tm) => {
|
||||||
assert!(!tm.source_data().is_empty());
|
assert!(!tm.source_data().is_empty());
|
||||||
let src_data = tm.source_data();
|
let src_data = tm.source_data();
|
||||||
assert!(src_data.len() >= 4);
|
assert!(src_data.len() >= 4);
|
||||||
@ -348,7 +340,7 @@ mod tests {
|
|||||||
error_data: Option<&[u8]>,
|
error_data: Option<&[u8]>,
|
||||||
) {
|
) {
|
||||||
let mut sender = TestSender::default();
|
let mut sender = TestSender::default();
|
||||||
let reporter = EventReporter::new(EXAMPLE_APID, max_event_aux_data_buf);
|
let reporter = EventReporter::new(0, EXAMPLE_APID, max_event_aux_data_buf);
|
||||||
assert!(reporter.is_some());
|
assert!(reporter.is_some());
|
||||||
let mut reporter = reporter.unwrap();
|
let mut reporter = reporter.unwrap();
|
||||||
let time_stamp_empty: [u8; 7] = [0; 7];
|
let time_stamp_empty: [u8; 7] = [0; 7];
|
||||||
@ -440,7 +432,7 @@ mod tests {
|
|||||||
fn insufficient_buffer() {
|
fn insufficient_buffer() {
|
||||||
let mut sender = TestSender::default();
|
let mut sender = TestSender::default();
|
||||||
for i in 0..3 {
|
for i in 0..3 {
|
||||||
let reporter = EventReporter::new(EXAMPLE_APID, i);
|
let reporter = EventReporter::new(0, EXAMPLE_APID, i);
|
||||||
assert!(reporter.is_some());
|
assert!(reporter.is_some());
|
||||||
let mut reporter = reporter.unwrap();
|
let mut reporter = reporter.unwrap();
|
||||||
check_buf_too_small(&mut reporter, &mut sender, i);
|
check_buf_too_small(&mut reporter, &mut sender, i);
|
||||||
|
@ -177,8 +177,8 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_pus_event_tm_generic(
|
pub fn generate_pus_event_tm_generic(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event: EV,
|
event: EV,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
@ -239,8 +239,8 @@ pub mod alloc_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_pus_event_tm<Severity: HasSeverity>(
|
pub fn generate_pus_event_tm<Severity: HasSeverity>(
|
||||||
&mut self,
|
&self,
|
||||||
sender: &mut (impl EcssTmSenderCore + ?Sized),
|
sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
event: EventU32TypedSev<Severity>,
|
event: EventU32TypedSev<Severity>,
|
||||||
aux_data: Option<&[u8]>,
|
aux_data: Option<&[u8]>,
|
||||||
@ -257,20 +257,26 @@ pub mod alloc_mod {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{events::SeverityInfo, pus::TmAsVecSenderWithMpsc};
|
use crate::events::SeverityInfo;
|
||||||
|
use crate::pus::PusTmAsVec;
|
||||||
|
use crate::request::UniqueApidTargetId;
|
||||||
use std::sync::mpsc::{self, TryRecvError};
|
use std::sync::mpsc::{self, TryRecvError};
|
||||||
|
|
||||||
const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
|
const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
|
||||||
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
|
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
|
||||||
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
|
const TEST_APID: u16 = 0x02;
|
||||||
|
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
|
||||||
|
|
||||||
fn create_basic_man_1() -> DefaultPusEventU32Dispatcher<()> {
|
fn create_basic_man_1() -> DefaultPusEventU32Dispatcher<()> {
|
||||||
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
|
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128)
|
||||||
|
.expect("Creating event repoter failed");
|
||||||
PusEventDispatcher::new_with_default_backend(reporter)
|
PusEventDispatcher::new_with_default_backend(reporter)
|
||||||
}
|
}
|
||||||
fn create_basic_man_2() -> DefaultPusEventU32Dispatcher<()> {
|
fn create_basic_man_2() -> DefaultPusEventU32Dispatcher<()> {
|
||||||
let reporter = EventReporter::new(0x02, 128).expect("Creating event repoter failed");
|
let reporter = EventReporter::new(TEST_ID.raw(), TEST_APID, 128)
|
||||||
|
.expect("Creating event repoter failed");
|
||||||
let backend = DefaultPusEventMgmtBackend::default();
|
let backend = DefaultPusEventMgmtBackend::default();
|
||||||
PusEventDispatcher::new(reporter, backend)
|
PusEventDispatcher::new(reporter, backend)
|
||||||
}
|
}
|
||||||
@ -278,10 +284,9 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_basic() {
|
fn test_basic() {
|
||||||
let mut event_man = create_basic_man_1();
|
let mut event_man = create_basic_man_1();
|
||||||
let (event_tx, event_rx) = mpsc::channel();
|
let (mut event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||||
let mut sender = TmAsVecSenderWithMpsc::new(0, "test_sender", event_tx);
|
|
||||||
let event_sent = event_man
|
let event_sent = event_man
|
||||||
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
|
.generate_pus_event_tm(&mut event_tx, &EMPTY_STAMP, INFO_EVENT, None)
|
||||||
.expect("Sending info event failed");
|
.expect("Sending info event failed");
|
||||||
|
|
||||||
assert!(event_sent);
|
assert!(event_sent);
|
||||||
@ -292,13 +297,13 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_disable_event() {
|
fn test_disable_event() {
|
||||||
let mut event_man = create_basic_man_2();
|
let mut event_man = create_basic_man_2();
|
||||||
let (event_tx, event_rx) = mpsc::channel();
|
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||||
let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
|
// let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
|
||||||
let res = event_man.disable_tm_for_event(&LOW_SEV_EVENT);
|
let res = event_man.disable_tm_for_event(&LOW_SEV_EVENT);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap());
|
assert!(res.unwrap());
|
||||||
let mut event_sent = event_man
|
let mut event_sent = event_man
|
||||||
.generate_pus_event_tm_generic(&mut sender, &EMPTY_STAMP, LOW_SEV_EVENT, None)
|
.generate_pus_event_tm_generic(&event_tx, &EMPTY_STAMP, LOW_SEV_EVENT, None)
|
||||||
.expect("Sending low severity event failed");
|
.expect("Sending low severity event failed");
|
||||||
assert!(!event_sent);
|
assert!(!event_sent);
|
||||||
let res = event_rx.try_recv();
|
let res = event_rx.try_recv();
|
||||||
@ -306,7 +311,7 @@ mod tests {
|
|||||||
assert!(matches!(res.unwrap_err(), TryRecvError::Empty));
|
assert!(matches!(res.unwrap_err(), TryRecvError::Empty));
|
||||||
// Check that only the low severity event was disabled
|
// Check that only the low severity event was disabled
|
||||||
event_sent = event_man
|
event_sent = event_man
|
||||||
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
|
.generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None)
|
||||||
.expect("Sending info event failed");
|
.expect("Sending info event failed");
|
||||||
assert!(event_sent);
|
assert!(event_sent);
|
||||||
event_rx.try_recv().expect("No info event received");
|
event_rx.try_recv().expect("No info event received");
|
||||||
@ -315,8 +320,7 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_reenable_event() {
|
fn test_reenable_event() {
|
||||||
let mut event_man = create_basic_man_1();
|
let mut event_man = create_basic_man_1();
|
||||||
let (event_tx, event_rx) = mpsc::channel();
|
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||||
let mut sender = TmAsVecSenderWithMpsc::new(0, "test", event_tx);
|
|
||||||
let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT);
|
let mut res = event_man.disable_tm_for_event_with_sev(&INFO_EVENT);
|
||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap());
|
assert!(res.unwrap());
|
||||||
@ -324,7 +328,7 @@ mod tests {
|
|||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
assert!(res.unwrap());
|
assert!(res.unwrap());
|
||||||
let event_sent = event_man
|
let event_sent = event_man
|
||||||
.generate_pus_event_tm(&mut sender, &EMPTY_STAMP, INFO_EVENT, None)
|
.generate_pus_event_tm(&event_tx, &EMPTY_STAMP, INFO_EVENT, None)
|
||||||
.expect("Sending info event failed");
|
.expect("Sending info event failed");
|
||||||
assert!(event_sent);
|
assert!(event_sent);
|
||||||
event_rx.try_recv().expect("No info event received");
|
event_rx.try_recv().expect("No info event received");
|
||||||
|
@ -13,7 +13,7 @@ use super::{
|
|||||||
GenericRoutingError, PusServiceHelper,
|
GenericRoutingError, PusServiceHelper,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct PusService5EventHandler<
|
pub struct PusEventServiceHandler<
|
||||||
TcReceiver: EcssTcReceiverCore,
|
TcReceiver: EcssTcReceiverCore,
|
||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
@ -29,7 +29,7 @@ impl<
|
|||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> PusService5EventHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
> PusEventServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
service_helper: PusServiceHelper<
|
service_helper: PusServiceHelper<
|
||||||
@ -83,7 +83,12 @@ impl<
|
|||||||
.service_helper
|
.service_helper
|
||||||
.common
|
.common
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.map_err(|_| PartialPusHandlingError::Verification);
|
.map_err(|_| PartialPusHandlingError::Verification);
|
||||||
let partial_error = start_token.clone().err();
|
let partial_error = start_token.clone().err();
|
||||||
let mut token: TcStateToken = ecss_tc_and_token.token.into();
|
let mut token: TcStateToken = ecss_tc_and_token.token.into();
|
||||||
@ -161,9 +166,9 @@ mod tests {
|
|||||||
use crate::pus::event_man::EventRequest;
|
use crate::pus::event_man::EventRequest;
|
||||||
use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
|
use crate::pus::test_util::{PusTestHarness, SimplePusPacketHandler, TEST_APID};
|
||||||
use crate::pus::verification::{
|
use crate::pus::verification::{
|
||||||
RequestId, VerificationReporterWithSharedPoolMpscBoundedSender,
|
RequestId, VerificationReporter, VerificationReportingProvider,
|
||||||
};
|
};
|
||||||
use crate::pus::{GenericConversionError, MpscTcReceiver, TmInSharedPoolSenderWithBoundedMpsc};
|
use crate::pus::{GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSenderBounded};
|
||||||
use crate::{
|
use crate::{
|
||||||
events::EventU32,
|
events::EventU32,
|
||||||
pus::{
|
pus::{
|
||||||
@ -174,34 +179,48 @@ mod tests {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::PusService5EventHandler;
|
use super::PusEventServiceHandler;
|
||||||
|
|
||||||
const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25);
|
const TEST_EVENT_0: EventU32 = EventU32::const_new(crate::events::Severity::INFO, 5, 25);
|
||||||
|
|
||||||
struct Pus5HandlerWithStoreTester {
|
struct Pus5HandlerWithStoreTester {
|
||||||
common: PusServiceHandlerWithSharedStoreCommon,
|
common: PusServiceHandlerWithSharedStoreCommon,
|
||||||
handler: PusService5EventHandler<
|
handler: PusEventServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pus5HandlerWithStoreTester {
|
impl Pus5HandlerWithStoreTester {
|
||||||
pub fn new(event_request_tx: Sender<EventRequestWithToken>) -> Self {
|
pub fn new(event_request_tx: Sender<EventRequestWithToken>) -> Self {
|
||||||
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
|
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0);
|
||||||
Self {
|
Self {
|
||||||
common,
|
common,
|
||||||
handler: PusService5EventHandler::new(srv_handler, event_request_tx),
|
handler: PusEventServiceHandler::new(srv_handler, event_request_tx),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus5HandlerWithStoreTester {
|
impl PusTestHarness for Pus5HandlerWithStoreTester {
|
||||||
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
|
self.handler
|
||||||
|
.service_helper
|
||||||
|
.verif_reporter()
|
||||||
|
.acceptance_success(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
init_token,
|
||||||
|
&[0; 7],
|
||||||
|
)
|
||||||
|
.expect("acceptance success failure")
|
||||||
|
}
|
||||||
|
|
||||||
delegate! {
|
delegate! {
|
||||||
to self.common {
|
to self.common {
|
||||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
||||||
@ -212,7 +231,7 @@ mod tests {
|
|||||||
|
|
||||||
impl SimplePusPacketHandler for Pus5HandlerWithStoreTester {
|
impl SimplePusPacketHandler for Pus5HandlerWithStoreTester {
|
||||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||||
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
|
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||||
self.handler.poll_and_handle_next_tc(&time_stamp)
|
self.handler.poll_and_handle_next_tc(&time_stamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -230,7 +249,8 @@ mod tests {
|
|||||||
.write_to_be_bytes(&mut app_data)
|
.write_to_be_bytes(&mut app_data)
|
||||||
.expect("writing test event failed");
|
.expect("writing test event failed");
|
||||||
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &app_data, true);
|
||||||
let token = test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
test_harness.handle_one_tc().unwrap();
|
test_harness.handle_one_tc().unwrap();
|
||||||
test_harness.check_next_verification_tm(1, request_id);
|
test_harness.check_next_verification_tm(1, request_id);
|
||||||
@ -287,7 +307,8 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
|
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||||
test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let result = result.unwrap();
|
let result = result.unwrap();
|
||||||
@ -306,7 +327,8 @@ mod tests {
|
|||||||
let sec_header =
|
let sec_header =
|
||||||
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
|
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
|
||||||
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &[0, 1, 2], true);
|
let ping_tc = PusTcCreator::new(&mut sp_header, sec_header, &[0, 1, 2], true);
|
||||||
test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let result = result.unwrap_err();
|
let result = result.unwrap_err();
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
use crate::pool::{StoreAddr, StoreError};
|
use crate::pool::{StoreAddr, StoreError};
|
||||||
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
|
use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken};
|
||||||
use crate::queue::{GenericReceiveError, GenericSendError};
|
use crate::queue::{GenericReceiveError, GenericSendError};
|
||||||
use crate::request::{GenericMessage, RequestId};
|
use crate::request::{GenericMessage, MessageMetadata, RequestId};
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
use core::fmt::{Display, Formatter};
|
use core::fmt::{Display, Formatter};
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
@ -43,19 +43,19 @@ pub use std_mod::*;
|
|||||||
use self::verification::VerificationReportingProvider;
|
use self::verification::VerificationReportingProvider;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq, Clone)]
|
#[derive(Debug, PartialEq, Eq, Clone)]
|
||||||
pub enum PusTmWrapper<'tm> {
|
pub enum PusTmVariant<'time, 'src_data> {
|
||||||
InStore(StoreAddr),
|
InStore(StoreAddr),
|
||||||
Direct(PusTmCreator<'tm>),
|
Direct(PusTmCreator<'time, 'src_data>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<StoreAddr> for PusTmWrapper<'_> {
|
impl From<StoreAddr> for PusTmVariant<'_, '_> {
|
||||||
fn from(value: StoreAddr) -> Self {
|
fn from(value: StoreAddr) -> Self {
|
||||||
Self::InStore(value)
|
Self::InStore(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tm> From<PusTmCreator<'tm>> for PusTmWrapper<'tm> {
|
impl<'time, 'src_data> From<PusTmCreator<'time, 'src_data>> for PusTmVariant<'time, 'src_data> {
|
||||||
fn from(value: PusTmCreator<'tm>) -> Self {
|
fn from(value: PusTmCreator<'time, 'src_data>) -> Self {
|
||||||
Self::Direct(value)
|
Self::Direct(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,7 +142,7 @@ impl Error for EcssTmtcError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pub trait EcssChannel: Send {
|
pub trait ChannelWithId: Send {
|
||||||
/// Each sender can have an ID associated with it
|
/// Each sender can have an ID associated with it
|
||||||
fn id(&self) -> ComponentId;
|
fn id(&self) -> ComponentId;
|
||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
@ -154,7 +154,7 @@ pub trait EcssChannel: Send {
|
|||||||
///
|
///
|
||||||
/// This sender object is responsible for sending PUS telemetry to a TM sink.
|
/// This sender object is responsible for sending PUS telemetry to a TM sink.
|
||||||
pub trait EcssTmSenderCore: Send {
|
pub trait EcssTmSenderCore: Send {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError>;
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for a user supplied sender object.
|
/// Generic trait for a user supplied sender object.
|
||||||
@ -165,6 +165,16 @@ pub trait EcssTcSenderCore {
|
|||||||
fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
|
fn send_tc(&self, tc: PusTcCreator, token: Option<TcStateToken>) -> Result<(), EcssTmtcError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Dummy object which can be useful for tests.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct EcssTmDummySender {}
|
||||||
|
|
||||||
|
impl EcssTmSenderCore for EcssTmDummySender {
|
||||||
|
fn send_tm(&self, _source_id: ComponentId, _tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A PUS telecommand packet can be stored in memory using different methods. Right now,
|
/// A PUS telecommand packet can be stored in memory using different methods. Right now,
|
||||||
/// storage inside a pool structure like [crate::pool::StaticMemoryPool], and storage inside a
|
/// storage inside a pool structure like [crate::pool::StaticMemoryPool], and storage inside a
|
||||||
/// `Vec<u8>` are supported.
|
/// `Vec<u8>` are supported.
|
||||||
@ -259,7 +269,7 @@ impl From<StoreError> for TryRecvTmtcError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for a user supplied receiver object.
|
/// Generic trait for a user supplied receiver object.
|
||||||
pub trait EcssTcReceiverCore: EcssChannel {
|
pub trait EcssTcReceiverCore {
|
||||||
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
|
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,8 +311,7 @@ pub trait PusRequestRouter<Request> {
|
|||||||
|
|
||||||
fn route(
|
fn route(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
source_id: ComponentId,
|
|
||||||
target_id: ComponentId,
|
target_id: ComponentId,
|
||||||
request: Request,
|
request: Request,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
@ -315,15 +324,17 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
|
|||||||
/// is finished. A finished PUS request will be removed from the active request map.
|
/// is finished. A finished PUS request will be removed from the active request map.
|
||||||
fn handle_reply(
|
fn handle_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
reply: &GenericMessage<ReplyType>,
|
reply: &GenericMessage<ReplyType>,
|
||||||
active_request: &ActiveRequestInfo,
|
active_request: &ActiveRequestInfo,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<bool, Self::Error>;
|
) -> Result<bool, Self::Error>;
|
||||||
|
|
||||||
fn handle_unrequested_reply(
|
fn handle_unrequested_reply(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
reply: &GenericMessage<ReplyType>,
|
reply: &GenericMessage<ReplyType>,
|
||||||
tm_sender: &impl EcssTmSenderCore,
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
@ -331,10 +342,11 @@ pub trait PusReplyHandler<ActiveRequestInfo: ActiveRequestProvider, ReplyType> {
|
|||||||
/// Handle the timeout of an active request.
|
/// Handle the timeout of an active request.
|
||||||
fn handle_request_timeout(
|
fn handle_request_timeout(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
active_request: &ActiveRequestInfo,
|
active_request: &ActiveRequestInfo,
|
||||||
|
tm_sender: &impl EcssTmSenderCore,
|
||||||
verification_handler: &impl VerificationReportingProvider,
|
verification_handler: &impl VerificationReportingProvider,
|
||||||
time_stamp: &[u8],
|
time_stamp: &[u8],
|
||||||
tm_sender: &impl EcssTmSenderCore,
|
|
||||||
) -> Result<(), Self::Error>;
|
) -> Result<(), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,10 +457,12 @@ pub mod alloc_mod {
|
|||||||
type Error;
|
type Error;
|
||||||
fn convert(
|
fn convert(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
caller_id: ComponentId,
|
||||||
token: VerificationToken<TcStateAccepted>,
|
token: VerificationToken<TcStateAccepted>,
|
||||||
tc: &PusTcReader,
|
tc: &PusTcReader,
|
||||||
time_stamp: &[u8],
|
tm_sender: &(impl EcssTmSenderCore + ?Sized),
|
||||||
verif_reporter: &impl VerificationReportingProvider,
|
verif_reporter: &impl VerificationReportingProvider,
|
||||||
|
time_stamp: &[u8],
|
||||||
) -> Result<(ActiveRequestInfo, Request), Self::Error>;
|
) -> Result<(ActiveRequestInfo, Request), Self::Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,8 +661,8 @@ pub mod std_mod {
|
|||||||
};
|
};
|
||||||
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError,
|
EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, GenericReceiveError,
|
||||||
GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError,
|
GenericSendError, PusTmVariant, TryRecvTmtcError,
|
||||||
};
|
};
|
||||||
use crate::tmtc::tm_helper::SharedTmPool;
|
use crate::tmtc::tm_helper::SharedTmPool;
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
@ -670,54 +684,82 @@ pub mod std_mod {
|
|||||||
use super::verification::{TcStateToken, VerificationReportingProvider};
|
use super::verification::{TcStateToken, VerificationReportingProvider};
|
||||||
use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory};
|
use super::{AcceptedEcssTcAndToken, ActiveRequestProvider, TcInMemory};
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct PusTmInPool {
|
||||||
|
pub source_id: ComponentId,
|
||||||
|
pub store_addr: StoreAddr,
|
||||||
|
}
|
||||||
|
|
||||||
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
|
impl From<mpsc::SendError<StoreAddr>> for EcssTmtcError {
|
||||||
fn from(_: mpsc::SendError<StoreAddr>) -> Self {
|
fn from(_: mpsc::SendError<StoreAddr>) -> Self {
|
||||||
Self::Send(GenericSendError::RxDisconnected)
|
Self::Send(GenericSendError::RxDisconnected)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for mpsc::Sender<StoreAddr> {
|
impl EcssTmSenderCore for mpsc::Sender<PusTmInPool> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => self
|
PusTmVariant::InStore(store_addr) => self
|
||||||
.send(addr)
|
.send(PusTmInPool {
|
||||||
|
source_id,
|
||||||
|
store_addr,
|
||||||
|
})
|
||||||
.map_err(|_| GenericSendError::RxDisconnected)?,
|
.map_err(|_| GenericSendError::RxDisconnected)?,
|
||||||
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for mpsc::SyncSender<StoreAddr> {
|
impl EcssTmSenderCore for mpsc::SyncSender<PusTmInPool> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => self
|
PusTmVariant::InStore(store_addr) => self
|
||||||
.try_send(addr)
|
.try_send(PusTmInPool {
|
||||||
|
source_id,
|
||||||
|
store_addr,
|
||||||
|
})
|
||||||
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
||||||
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for mpsc::Sender<Vec<u8>> {
|
#[derive(Debug)]
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
pub struct PusTmAsVec {
|
||||||
|
pub source_id: ComponentId,
|
||||||
|
pub packet: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type MpscTmAsVecSender = mpsc::Sender<PusTmAsVec>;
|
||||||
|
|
||||||
|
impl EcssTmSenderCore for MpscTmAsVecSender {
|
||||||
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
||||||
PusTmWrapper::Direct(tm) => self
|
PusTmVariant::Direct(tm) => self
|
||||||
.send(tm.to_vec()?)
|
.send(PusTmAsVec {
|
||||||
|
source_id,
|
||||||
|
packet: tm.to_vec()?,
|
||||||
|
})
|
||||||
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for mpsc::SyncSender<Vec<u8>> {
|
pub type MpscTmAsVecSenderBounded = mpsc::SyncSender<PusTmAsVec>;
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
|
||||||
|
impl EcssTmSenderCore for MpscTmAsVecSenderBounded {
|
||||||
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
||||||
PusTmWrapper::Direct(tm) => self
|
PusTmVariant::Direct(tm) => self
|
||||||
.send(tm.to_vec()?)
|
.send(PusTmAsVec {
|
||||||
|
source_id,
|
||||||
|
packet: tm.to_vec()?,
|
||||||
|
})
|
||||||
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -725,67 +767,52 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TmInSharedPoolSenderWithId<Sender: EcssTmSenderCore> {
|
pub struct TmInSharedPoolSender<Sender: EcssTmSenderCore> {
|
||||||
channel_id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
shared_tm_store: SharedTmPool,
|
shared_tm_store: SharedTmPool,
|
||||||
sender: Sender,
|
sender: Sender,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> EcssChannel for TmInSharedPoolSenderWithId<Sender> {
|
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
|
||||||
fn id(&self) -> ComponentId {
|
pub fn send_direct_tm(
|
||||||
self.channel_id
|
&self,
|
||||||
}
|
source_id: ComponentId,
|
||||||
|
tm: PusTmCreator,
|
||||||
fn name(&self) -> &'static str {
|
) -> Result<(), EcssTmtcError> {
|
||||||
self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> TmInSharedPoolSenderWithId<Sender> {
|
|
||||||
pub fn send_direct_tm(&self, tm: PusTmCreator) -> Result<(), EcssTmtcError> {
|
|
||||||
let addr = self.shared_tm_store.add_pus_tm(&tm)?;
|
let addr = self.shared_tm_store.add_pus_tm(&tm)?;
|
||||||
self.sender.send_tm(PusTmWrapper::InStore(addr))
|
self.sender.send_tm(source_id, PusTmVariant::InStore(addr))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmInSharedPoolSenderWithId<Sender> {
|
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmInSharedPoolSender<Sender> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(&self, source_id: ComponentId, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
if let PusTmWrapper::Direct(tm) = tm {
|
if let PusTmVariant::Direct(tm) = tm {
|
||||||
return self.send_direct_tm(tm);
|
return self.send_direct_tm(source_id, tm);
|
||||||
}
|
}
|
||||||
self.sender.send_tm(tm)
|
self.sender.send_tm(source_id, tm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> TmInSharedPoolSenderWithId<Sender> {
|
impl<Sender: EcssTmSenderCore> TmInSharedPoolSender<Sender> {
|
||||||
pub fn new(
|
pub fn new(shared_tm_store: SharedTmPool, sender: Sender) -> Self {
|
||||||
id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
shared_tm_store: SharedTmPool,
|
|
||||||
sender: Sender,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
channel_id: id,
|
|
||||||
name,
|
|
||||||
shared_tm_store,
|
shared_tm_store,
|
||||||
sender,
|
sender,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TmInSharedPoolSenderWithMpsc = TmInSharedPoolSenderWithId<mpsc::Sender<StoreAddr>>;
|
pub type MpscTmInSharedPoolSender = TmInSharedPoolSender<mpsc::Sender<PusTmInPool>>;
|
||||||
pub type TmInSharedPoolSenderWithBoundedMpsc =
|
pub type MpscTmInSharedPoolSenderBounded = TmInSharedPoolSender<mpsc::SyncSender<PusTmInPool>>;
|
||||||
TmInSharedPoolSenderWithId<mpsc::SyncSender<StoreAddr>>;
|
|
||||||
|
|
||||||
|
/*
|
||||||
/// This class can be used if frequent heap allocations during run-time are not an issue.
|
/// This class can be used if frequent heap allocations during run-time are not an issue.
|
||||||
/// PUS TM packets will be sent around as [Vec]s. Please note that the current implementation
|
/// PUS TM packets will be sent around as [Vec]s. Please note that the current implementation
|
||||||
/// of this class can not deal with store addresses, so it is assumed that is is always
|
/// of this class can not deal with store addresses, so it is assumed that is is always
|
||||||
/// going to be called with direct packets.
|
/// going to be called with direct packets.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct TmAsVecSenderWithId<Sender: EcssTmSenderCore> {
|
pub struct TmAsVecSenderWithId<Sender: EcssTmSenderCore> {
|
||||||
id: ComponentId,
|
// id: ComponentId,
|
||||||
name: &'static str,
|
//name: &'static str,
|
||||||
sender: Sender,
|
sender: Sender,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,7 +828,7 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> EcssChannel for TmAsVecSenderWithId<Sender> {
|
impl<Sender: EcssTmSenderCore> ChannelWithId for TmAsVecSenderWithId<Sender> {
|
||||||
fn id(&self) -> ComponentId {
|
fn id(&self) -> ComponentId {
|
||||||
self.id
|
self.id
|
||||||
}
|
}
|
||||||
@ -811,58 +838,34 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmAsVecSenderWithId<Sender> {
|
impl<Sender: EcssTmSenderCore> EcssTmSenderCore for TmAsVecSenderWithId<Sender> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(&self, tm: PusTmVariant) -> Result<(), EcssTmtcError> {
|
||||||
self.sender.send_tm(tm)
|
self.sender.send_tm(tm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TmAsVecSenderWithMpsc = TmAsVecSenderWithId<mpsc::Sender<Vec<u8>>>;
|
pub type TmAsVecSenderWithMpsc = TmAsVecSenderWithId<mpsc::Sender<Vec<u8>>>;
|
||||||
pub type TmAsVecSenderWithBoundedMpsc = TmAsVecSenderWithId<mpsc::SyncSender<Vec<u8>>>;
|
pub type TmAsVecSenderWithBoundedMpsc = TmAsVecSenderWithId<mpsc::SyncSender<Vec<u8>>>;
|
||||||
|
*/
|
||||||
|
|
||||||
pub struct MpscTcReceiver {
|
pub type MpscTcReceiver = mpsc::Receiver<EcssTcAndToken>;
|
||||||
id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
receiver: mpsc::Receiver<EcssTcAndToken>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssChannel for MpscTcReceiver {
|
|
||||||
fn id(&self) -> ComponentId {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssTcReceiverCore for MpscTcReceiver {
|
impl EcssTcReceiverCore for MpscTcReceiver {
|
||||||
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
|
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
|
||||||
self.receiver.try_recv().map_err(|e| match e {
|
self.try_recv().map_err(|e| match e {
|
||||||
TryRecvError::Empty => TryRecvTmtcError::Empty,
|
TryRecvError::Empty => TryRecvTmtcError::Empty,
|
||||||
TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
|
TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
|
||||||
GenericReceiveError::TxDisconnected(Some(self.id())),
|
GenericReceiveError::TxDisconnected(None),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MpscTcReceiver {
|
|
||||||
pub fn new(
|
|
||||||
id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
receiver: mpsc::Receiver<EcssTcAndToken>,
|
|
||||||
) -> Self {
|
|
||||||
Self { id, name, receiver }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(feature = "crossbeam")]
|
#[cfg(feature = "crossbeam")]
|
||||||
pub mod cb_mod {
|
pub mod cb_mod {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crossbeam_channel as cb;
|
use crossbeam_channel as cb;
|
||||||
|
|
||||||
pub type TmInSharedPoolSenderWithCrossbeam =
|
pub type TmInSharedPoolSenderWithCrossbeam = TmInSharedPoolSender<cb::Sender<PusTmInPool>>;
|
||||||
TmInSharedPoolSenderWithId<cb::Sender<StoreAddr>>;
|
|
||||||
|
|
||||||
impl From<cb::SendError<StoreAddr>> for EcssTmtcError {
|
impl From<cb::SendError<StoreAddr>> for EcssTmtcError {
|
||||||
fn from(_: cb::SendError<StoreAddr>) -> Self {
|
fn from(_: cb::SendError<StoreAddr>) -> Self {
|
||||||
@ -881,65 +884,44 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EcssTmSenderCore for cb::Sender<StoreAddr> {
|
impl EcssTmSenderCore for cb::Sender<PusTmInPool> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(
|
||||||
|
&self,
|
||||||
|
source_id: ComponentId,
|
||||||
|
tm: PusTmVariant,
|
||||||
|
) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => self
|
PusTmVariant::InStore(addr) => self
|
||||||
.try_send(addr)
|
.try_send(PusTmInPool {
|
||||||
|
source_id,
|
||||||
|
store_addr: addr,
|
||||||
|
})
|
||||||
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
||||||
PusTmWrapper::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
PusTmVariant::Direct(_) => return Err(EcssTmtcError::CantSendDirectTm),
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl EcssTmSenderCore for cb::Sender<Vec<u8>> {
|
impl EcssTmSenderCore for cb::Sender<PusTmAsVec> {
|
||||||
fn send_tm(&self, tm: PusTmWrapper) -> Result<(), EcssTmtcError> {
|
fn send_tm(
|
||||||
|
&self,
|
||||||
|
source_id: ComponentId,
|
||||||
|
tm: PusTmVariant,
|
||||||
|
) -> Result<(), EcssTmtcError> {
|
||||||
match tm {
|
match tm {
|
||||||
PusTmWrapper::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
PusTmVariant::InStore(addr) => return Err(EcssTmtcError::CantSendAddr(addr)),
|
||||||
PusTmWrapper::Direct(tm) => self
|
PusTmVariant::Direct(tm) => self
|
||||||
.send(tm.to_vec()?)
|
.send(PusTmAsVec {
|
||||||
|
source_id,
|
||||||
|
packet: tm.to_vec()?,
|
||||||
|
})
|
||||||
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
.map_err(|e| EcssTmtcError::Send(e.into()))?,
|
||||||
};
|
};
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct CrossbeamTcReceiver {
|
pub type CrossbeamTcReceiver = cb::Receiver<EcssTcAndToken>;
|
||||||
id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
receiver: cb::Receiver<EcssTcAndToken>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl CrossbeamTcReceiver {
|
|
||||||
pub fn new(
|
|
||||||
id: ComponentId,
|
|
||||||
name: &'static str,
|
|
||||||
receiver: cb::Receiver<EcssTcAndToken>,
|
|
||||||
) -> Self {
|
|
||||||
Self { id, name, receiver }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssChannel for CrossbeamTcReceiver {
|
|
||||||
fn id(&self) -> ComponentId {
|
|
||||||
self.id
|
|
||||||
}
|
|
||||||
|
|
||||||
fn name(&self) -> &'static str {
|
|
||||||
self.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl EcssTcReceiverCore for CrossbeamTcReceiver {
|
|
||||||
fn recv_tc(&self) -> Result<EcssTcAndToken, TryRecvTmtcError> {
|
|
||||||
self.receiver.try_recv().map_err(|e| match e {
|
|
||||||
cb::TryRecvError::Empty => TryRecvTmtcError::Empty,
|
|
||||||
cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from(
|
|
||||||
GenericReceiveError::TxDisconnected(Some(self.id())),
|
|
||||||
)),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is a high-level handler for the generic PUS services which need to convert PUS
|
/// This is a high-level handler for the generic PUS services which need to convert PUS
|
||||||
@ -1294,9 +1276,9 @@ pub mod std_mod {
|
|||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
> {
|
> {
|
||||||
|
pub id: ComponentId,
|
||||||
pub tc_receiver: TcReceiver,
|
pub tc_receiver: TcReceiver,
|
||||||
pub tm_sender: TmSender,
|
pub tm_sender: TmSender,
|
||||||
pub tm_apid: u16,
|
|
||||||
pub verif_reporter: VerificationReporter,
|
pub verif_reporter: VerificationReporter,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1327,23 +1309,31 @@ pub mod std_mod {
|
|||||||
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
> PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
|
id: ComponentId,
|
||||||
tc_receiver: TcReceiver,
|
tc_receiver: TcReceiver,
|
||||||
tm_sender: TmSender,
|
tm_sender: TmSender,
|
||||||
tm_apid: u16,
|
|
||||||
verification_handler: VerificationReporter,
|
verification_handler: VerificationReporter,
|
||||||
tc_in_mem_converter: TcInMemConverter,
|
tc_in_mem_converter: TcInMemConverter,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
common: PusServiceBase {
|
common: PusServiceBase {
|
||||||
|
id,
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
tm_sender,
|
tm_sender,
|
||||||
tm_apid,
|
|
||||||
verif_reporter: verification_handler,
|
verif_reporter: verification_handler,
|
||||||
},
|
},
|
||||||
tc_in_mem_converter,
|
tc_in_mem_converter,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn id(&self) -> ComponentId {
|
||||||
|
self.common.id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tm_sender(&self) -> &TmSender {
|
||||||
|
&self.common.tm_sender
|
||||||
|
}
|
||||||
|
|
||||||
/// This function can be used to poll the internal [EcssTcReceiverCore] object for the next
|
/// This function can be used to poll the internal [EcssTcReceiverCore] object for the next
|
||||||
/// telecommand packet. It will return `Ok(None)` if there are not packets available.
|
/// telecommand packet. It will return `Ok(None)` if there are not packets available.
|
||||||
/// In any other case, it will perform the acceptance of the ECSS TC packet using the
|
/// In any other case, it will perform the acceptance of the ECSS TC packet using the
|
||||||
@ -1378,6 +1368,9 @@ pub mod std_mod {
|
|||||||
pub fn verif_reporter(&self) -> &VerificationReporter {
|
pub fn verif_reporter(&self) -> &VerificationReporter {
|
||||||
&self.common.verif_reporter
|
&self.common.verif_reporter
|
||||||
}
|
}
|
||||||
|
pub fn verif_reporter_mut(&mut self) -> &mut VerificationReporter {
|
||||||
|
&mut self.common.verif_reporter
|
||||||
|
}
|
||||||
|
|
||||||
pub fn tc_in_mem_converter(&self) -> &TcInMemConverter {
|
pub fn tc_in_mem_converter(&self) -> &TcInMemConverter {
|
||||||
&self.tc_in_mem_converter
|
&self.tc_in_mem_converter
|
||||||
@ -1388,50 +1381,47 @@ pub mod std_mod {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PusServiceHelperDynWithMpsc<TcInMemConverter, VerificationReporter> = PusServiceHelper<
|
pub type PusServiceHelperDynWithMpsc<TcInMemConverter, VerificationReporter> =
|
||||||
MpscTcReceiver,
|
PusServiceHelper<MpscTcReceiver, MpscTmAsVecSender, TcInMemConverter, VerificationReporter>;
|
||||||
TmAsVecSenderWithMpsc,
|
|
||||||
TcInMemConverter,
|
|
||||||
VerificationReporter,
|
|
||||||
>;
|
|
||||||
pub type PusServiceHelperDynWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
|
pub type PusServiceHelperDynWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
|
||||||
PusServiceHelper<
|
PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithBoundedMpsc,
|
MpscTmAsVecSenderBounded,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
pub type PusServiceHelperStaticWithMpsc<TcInMemConverter, VerificationReporter> =
|
pub type PusServiceHelperStaticWithMpsc<TcInMemConverter, VerificationReporter> =
|
||||||
PusServiceHelper<
|
PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithMpsc,
|
MpscTmInSharedPoolSender,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
pub type PusServiceHelperStaticWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
|
pub type PusServiceHelperStaticWithBoundedMpsc<TcInMemConverter, VerificationReporter> =
|
||||||
PusServiceHelper<
|
PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
TcInMemConverter,
|
TcInMemConverter,
|
||||||
VerificationReporter,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn source_buffer_large_enough(cap: usize, len: usize) -> Result<(), EcssTmtcError> {
|
pub(crate) fn source_buffer_large_enough(
|
||||||
|
cap: usize,
|
||||||
|
len: usize,
|
||||||
|
) -> Result<(), ByteConversionError> {
|
||||||
if len > cap {
|
if len > cap {
|
||||||
return Err(
|
return Err(ByteConversionError::ToSliceTooSmall {
|
||||||
PusError::ByteConversion(ByteConversionError::ToSliceTooSmall {
|
found: cap,
|
||||||
found: cap,
|
expected: len,
|
||||||
expected: len,
|
});
|
||||||
})
|
|
||||||
.into(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(any(feature = "test_util", test))]
|
#[cfg(any(feature = "test_util", test))]
|
||||||
pub mod test_util {
|
pub mod test_util {
|
||||||
|
use crate::request::UniqueApidTargetId;
|
||||||
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
use spacepackets::ecss::{tc::PusTcCreator, tm::PusTmReader};
|
||||||
|
|
||||||
use super::{
|
use super::{
|
||||||
@ -1440,9 +1430,13 @@ pub mod test_util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub const TEST_APID: u16 = 0x101;
|
pub const TEST_APID: u16 = 0x101;
|
||||||
|
pub const TEST_UNIQUE_ID: u32 = 0x05;
|
||||||
|
pub const TEST_COMPONENT_ID: UniqueApidTargetId =
|
||||||
|
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID);
|
||||||
|
|
||||||
pub trait PusTestHarness {
|
pub trait PusTestHarness {
|
||||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
||||||
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
fn check_next_verification_tm(
|
fn check_next_verification_tm(
|
||||||
@ -1471,22 +1465,16 @@ pub mod tests {
|
|||||||
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
use spacepackets::ecss::{PusPacket, WritablePusPacket};
|
||||||
use spacepackets::CcsdsPacket;
|
use spacepackets::CcsdsPacket;
|
||||||
|
|
||||||
use crate::pool::{
|
use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig};
|
||||||
PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StaticPoolConfig, StoreAddr,
|
use crate::pus::verification::{RequestId, VerificationReporter};
|
||||||
};
|
|
||||||
use crate::pus::verification::RequestId;
|
|
||||||
use crate::tmtc::tm_helper::SharedTmPool;
|
use crate::tmtc::tm_helper::SharedTmPool;
|
||||||
use crate::ComponentId;
|
use crate::ComponentId;
|
||||||
|
|
||||||
use super::test_util::TEST_APID;
|
use super::test_util::{TEST_APID, TEST_COMPONENT_ID};
|
||||||
|
|
||||||
use super::verification::std_mod::{
|
use super::verification::test_util::TestVerificationReporter;
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
|
||||||
};
|
|
||||||
use super::verification::test_util::{SharedVerificationMap, TestVerificationReporter};
|
|
||||||
use super::verification::{
|
use super::verification::{
|
||||||
TcStateAccepted, VerificationReporterCfg, VerificationReporterWithSender,
|
TcStateAccepted, VerificationReporterCfg, VerificationReportingProvider, VerificationToken,
|
||||||
VerificationReportingProvider, VerificationToken,
|
|
||||||
};
|
};
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
@ -1515,20 +1503,19 @@ pub mod tests {
|
|||||||
|
|
||||||
/// Common fields for a PUS service test harness.
|
/// Common fields for a PUS service test harness.
|
||||||
pub struct PusServiceHandlerWithSharedStoreCommon {
|
pub struct PusServiceHandlerWithSharedStoreCommon {
|
||||||
pus_buf: [u8; 2048],
|
pus_buf: RefCell<[u8; 2048]>,
|
||||||
tm_buf: [u8; 2048],
|
tm_buf: [u8; 2048],
|
||||||
tc_pool: SharedStaticMemoryPool,
|
tc_pool: SharedStaticMemoryPool,
|
||||||
tm_pool: SharedTmPool,
|
tm_pool: SharedTmPool,
|
||||||
tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
||||||
tm_receiver: mpsc::Receiver<StoreAddr>,
|
tm_receiver: mpsc::Receiver<PusTmInPool>,
|
||||||
verification_handler: VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PusServiceHelperStatic = PusServiceHelper<
|
pub type PusServiceHelperStatic = PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl PusServiceHandlerWithSharedStoreCommon {
|
impl PusServiceHandlerWithSharedStoreCommon {
|
||||||
@ -1536,7 +1523,7 @@ pub mod tests {
|
|||||||
/// [PusServiceHandler] which might be required for a specific PUS service handler.
|
/// [PusServiceHandler] which might be required for a specific PUS service handler.
|
||||||
///
|
///
|
||||||
/// The PUS service handler is instantiated with a [EcssTcInStoreConverter].
|
/// The PUS service handler is instantiated with a [EcssTcInStoreConverter].
|
||||||
pub fn new() -> (Self, PusServiceHelperStatic) {
|
pub fn new(id: ComponentId) -> (Self, PusServiceHelperStatic) {
|
||||||
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
|
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
|
||||||
let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
|
let tc_pool = StaticMemoryPool::new(pool_cfg.clone());
|
||||||
let tm_pool = StaticMemoryPool::new(pool_cfg);
|
let tm_pool = StaticMemoryPool::new(pool_cfg);
|
||||||
@ -1545,62 +1532,47 @@ pub mod tests {
|
|||||||
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10);
|
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::sync_channel(10);
|
||||||
let (tm_tx, tm_rx) = mpsc::sync_channel(10);
|
let (tm_tx, tm_rx) = mpsc::sync_channel(10);
|
||||||
|
|
||||||
let verif_sender = TmInSharedPoolSenderWithBoundedMpsc::new(
|
|
||||||
0,
|
|
||||||
"verif_sender",
|
|
||||||
shared_tm_pool.clone(),
|
|
||||||
tm_tx.clone(),
|
|
||||||
);
|
|
||||||
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
||||||
let verification_handler =
|
let verification_handler = VerificationReporter::new(&verif_cfg);
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender::new(&verif_cfg, verif_sender);
|
let test_srv_tm_sender = TmInSharedPoolSender::new(shared_tm_pool.clone(), tm_tx);
|
||||||
let test_srv_tm_sender =
|
|
||||||
TmInSharedPoolSenderWithId::new(0, "TEST_SENDER", shared_tm_pool.clone(), tm_tx);
|
|
||||||
let test_srv_tc_receiver = MpscTcReceiver::new(0, "TEST_RECEIVER", test_srv_tc_rx);
|
|
||||||
let in_store_converter =
|
let in_store_converter =
|
||||||
EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
|
EcssTcInSharedStoreConverter::new(shared_tc_pool.clone(), 2048);
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
pus_buf: [0; 2048],
|
pus_buf: RefCell::new([0; 2048]),
|
||||||
tm_buf: [0; 2048],
|
tm_buf: [0; 2048],
|
||||||
tc_pool: shared_tc_pool,
|
tc_pool: shared_tc_pool,
|
||||||
tm_pool: shared_tm_pool,
|
tm_pool: shared_tm_pool,
|
||||||
tc_sender: test_srv_tc_tx,
|
tc_sender: test_srv_tc_tx,
|
||||||
tm_receiver: tm_rx,
|
tm_receiver: tm_rx,
|
||||||
verification_handler: verification_handler.clone(),
|
|
||||||
},
|
},
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
test_srv_tc_receiver,
|
id,
|
||||||
|
test_srv_tc_rx,
|
||||||
test_srv_tm_sender,
|
test_srv_tm_sender,
|
||||||
TEST_APID,
|
|
||||||
verification_handler,
|
verification_handler,
|
||||||
in_store_converter,
|
in_store_converter,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||||
let token = self.verification_handler.add_tc(tc);
|
let mut mut_buf = self.pus_buf.borrow_mut();
|
||||||
let token = self
|
let tc_size = tc.write_to_bytes(mut_buf.as_mut_slice()).unwrap();
|
||||||
.verification_handler
|
|
||||||
.acceptance_success(token, &[0; 7])
|
|
||||||
.unwrap();
|
|
||||||
let tc_size = tc.write_to_bytes(&mut self.pus_buf).unwrap();
|
|
||||||
let mut tc_pool = self.tc_pool.write().unwrap();
|
let mut tc_pool = self.tc_pool.write().unwrap();
|
||||||
let addr = tc_pool.add(&self.pus_buf[..tc_size]).unwrap();
|
let addr = tc_pool.add(&mut_buf[..tc_size]).unwrap();
|
||||||
drop(tc_pool);
|
drop(tc_pool);
|
||||||
// Send accepted TC to test service handler.
|
// Send accepted TC to test service handler.
|
||||||
self.tc_sender
|
self.tc_sender
|
||||||
.send(EcssTcAndToken::new(addr, token))
|
.send(EcssTcAndToken::new(addr, *token))
|
||||||
.expect("sending tc failed");
|
.expect("sending tc failed");
|
||||||
token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
|
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
|
||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
let tm_addr = next_msg.unwrap();
|
let tm_in_pool = next_msg.unwrap();
|
||||||
let tm_pool = self.tm_pool.0.read().unwrap();
|
let tm_pool = self.tm_pool.0.read().unwrap();
|
||||||
let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap();
|
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
||||||
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
|
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
|
||||||
PusTmReader::new(&self.tm_buf, 7).unwrap().0
|
PusTmReader::new(&self.tm_buf, 7).unwrap().0
|
||||||
}
|
}
|
||||||
@ -1616,9 +1588,9 @@ pub mod tests {
|
|||||||
pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) {
|
pub fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId) {
|
||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
let tm_addr = next_msg.unwrap();
|
let tm_in_pool = next_msg.unwrap();
|
||||||
let tm_pool = self.tm_pool.0.read().unwrap();
|
let tm_pool = self.tm_pool.0.read().unwrap();
|
||||||
let tm_raw = tm_pool.read_as_vec(&tm_addr).unwrap();
|
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
|
||||||
let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
|
let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
|
||||||
assert_eq!(PusPacket::service(&tm), 1);
|
assert_eq!(PusPacket::service(&tm), 1);
|
||||||
assert_eq!(PusPacket::subservice(&tm), subservice);
|
assert_eq!(PusPacket::subservice(&tm), subservice);
|
||||||
@ -1629,56 +1601,49 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct PusServiceHandlerWithVecCommon<VerificationReporter: VerificationReportingProvider> {
|
pub struct PusServiceHandlerWithVecCommon {
|
||||||
current_tm: Option<alloc::vec::Vec<u8>>,
|
current_tm: Option<Vec<u8>>,
|
||||||
tc_sender: mpsc::Sender<EcssTcAndToken>,
|
tc_sender: mpsc::Sender<EcssTcAndToken>,
|
||||||
tm_receiver: mpsc::Receiver<alloc::vec::Vec<u8>>,
|
tm_receiver: mpsc::Receiver<PusTmAsVec>,
|
||||||
pub verification_handler: VerificationReporter,
|
|
||||||
}
|
}
|
||||||
pub type PusServiceHelperDynamic = PusServiceHelper<
|
pub type PusServiceHelperDynamic = PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
MpscTmAsVecSender,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscSender,
|
TestVerificationReporter,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
impl PusServiceHandlerWithVecCommon<VerificationReporterWithVecMpscSender> {
|
impl PusServiceHandlerWithVecCommon {
|
||||||
pub fn new_with_standard_verif_reporter() -> (Self, PusServiceHelperDynamic) {
|
pub fn new_with_standard_verif_reporter(
|
||||||
|
id: ComponentId,
|
||||||
|
) -> (Self, PusServiceHelperDynamic) {
|
||||||
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
||||||
let (tm_tx, tm_rx) = mpsc::channel();
|
let (tm_tx, tm_rx) = mpsc::channel();
|
||||||
|
|
||||||
let verif_sender = TmAsVecSenderWithId::new(0, "verififcatio-sender", tm_tx.clone());
|
|
||||||
let verif_cfg = VerificationReporterCfg::new(TEST_APID, 1, 2, 8).unwrap();
|
|
||||||
let verification_handler =
|
|
||||||
VerificationReporterWithSender::new(&verif_cfg, verif_sender);
|
|
||||||
|
|
||||||
let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx);
|
|
||||||
let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx);
|
|
||||||
let in_store_converter = EcssTcInVecConverter::default();
|
let in_store_converter = EcssTcInVecConverter::default();
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
current_tm: None,
|
current_tm: None,
|
||||||
tc_sender: test_srv_tc_tx,
|
tc_sender: test_srv_tc_tx,
|
||||||
tm_receiver: tm_rx,
|
tm_receiver: tm_rx,
|
||||||
verification_handler: verification_handler.clone(),
|
|
||||||
},
|
},
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
test_srv_tc_receiver,
|
id,
|
||||||
test_srv_tm_sender,
|
test_srv_tc_rx,
|
||||||
TEST_APID,
|
tm_tx,
|
||||||
verification_handler,
|
TestVerificationReporter::default(),
|
||||||
in_store_converter,
|
in_store_converter,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusServiceHandlerWithVecCommon<TestVerificationReporter> {
|
impl PusServiceHandlerWithVecCommon {
|
||||||
pub fn new_with_test_verif_sender() -> (
|
pub fn new_with_test_verif_sender() -> (
|
||||||
Self,
|
Self,
|
||||||
PusServiceHelper<
|
PusServiceHelper<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
MpscTmAsVecSender,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
TestVerificationReporter,
|
TestVerificationReporter,
|
||||||
>,
|
>,
|
||||||
@ -1686,22 +1651,19 @@ pub mod tests {
|
|||||||
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
let (test_srv_tc_tx, test_srv_tc_rx) = mpsc::channel();
|
||||||
let (tm_tx, tm_rx) = mpsc::channel();
|
let (tm_tx, tm_rx) = mpsc::channel();
|
||||||
|
|
||||||
let test_srv_tm_sender = TmAsVecSenderWithId::new(0, "test-sender", tm_tx);
|
|
||||||
let test_srv_tc_receiver = MpscTcReceiver::new(0, "test-receiver", test_srv_tc_rx);
|
|
||||||
let in_store_converter = EcssTcInVecConverter::default();
|
let in_store_converter = EcssTcInVecConverter::default();
|
||||||
let shared_verif_map = SharedVerificationMap::default();
|
let verification_handler = TestVerificationReporter::default();
|
||||||
let verification_handler = TestVerificationReporter::new(shared_verif_map);
|
|
||||||
(
|
(
|
||||||
Self {
|
Self {
|
||||||
current_tm: None,
|
current_tm: None,
|
||||||
tc_sender: test_srv_tc_tx,
|
tc_sender: test_srv_tc_tx,
|
||||||
tm_receiver: tm_rx,
|
tm_receiver: tm_rx,
|
||||||
verification_handler: verification_handler.clone(),
|
//verification_handler: verification_handler.clone(),
|
||||||
},
|
},
|
||||||
PusServiceHelper::new(
|
PusServiceHelper::new(
|
||||||
test_srv_tc_receiver,
|
TEST_COMPONENT_ID.raw(),
|
||||||
test_srv_tm_sender,
|
test_srv_tc_rx,
|
||||||
TEST_APID,
|
tm_tx,
|
||||||
verification_handler,
|
verification_handler,
|
||||||
in_store_converter,
|
in_store_converter,
|
||||||
),
|
),
|
||||||
@ -1709,29 +1671,21 @@ pub mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<VerificationReporter: VerificationReportingProvider>
|
impl PusServiceHandlerWithVecCommon {
|
||||||
PusServiceHandlerWithVecCommon<VerificationReporter>
|
pub fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator) {
|
||||||
{
|
|
||||||
pub fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
|
||||||
let token = self.verification_handler.add_tc(tc);
|
|
||||||
let token = self
|
|
||||||
.verification_handler
|
|
||||||
.acceptance_success(token, &[0; 7])
|
|
||||||
.unwrap();
|
|
||||||
// Send accepted TC to test service handler.
|
// Send accepted TC to test service handler.
|
||||||
self.tc_sender
|
self.tc_sender
|
||||||
.send(EcssTcAndToken::new(
|
.send(EcssTcAndToken::new(
|
||||||
TcInMemory::Vec(tc.to_vec().expect("pus tc conversion to vec failed")),
|
TcInMemory::Vec(tc.to_vec().expect("pus tc conversion to vec failed")),
|
||||||
token,
|
*token,
|
||||||
))
|
))
|
||||||
.expect("sending tc failed");
|
.expect("sending tc failed");
|
||||||
token
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
|
pub fn read_next_tm(&mut self) -> PusTmReader<'_> {
|
||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
self.current_tm = Some(next_msg.unwrap());
|
self.current_tm = Some(next_msg.unwrap().packet);
|
||||||
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
|
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.0
|
.0
|
||||||
@ -1749,7 +1703,7 @@ pub mod tests {
|
|||||||
let next_msg = self.tm_receiver.try_recv();
|
let next_msg = self.tm_receiver.try_recv();
|
||||||
assert!(next_msg.is_ok());
|
assert!(next_msg.is_ok());
|
||||||
let next_msg = next_msg.unwrap();
|
let next_msg = next_msg.unwrap();
|
||||||
let tm = PusTmReader::new(next_msg.as_slice(), 7).unwrap().0;
|
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0;
|
||||||
assert_eq!(PusPacket::service(&tm), 1);
|
assert_eq!(PusPacket::service(&tm), 1);
|
||||||
assert_eq!(PusPacket::subservice(&tm), subservice);
|
assert_eq!(PusPacket::subservice(&tm), subservice);
|
||||||
assert_eq!(tm.apid(), TEST_APID);
|
assert_eq!(tm.apid(), TEST_APID);
|
||||||
|
@ -31,139 +31,7 @@ pub mod alloc_mod {}
|
|||||||
|
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
|
||||||
pub mod std_mod {
|
pub mod std_mod {}
|
||||||
/*
|
|
||||||
use spacepackets::{
|
|
||||||
ecss::tm::{PusTmCreator, PusTmSecondaryHeader},
|
|
||||||
util::UnsignedEnum,
|
|
||||||
SpHeader,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub trait ModeReplyHook: ReplyHandlerHook<ActivePusRequest, ModeReply> {
|
|
||||||
fn wrong_mode_result_code(&self) -> ResultU16;
|
|
||||||
fn can_not_reach_mode_result_code(&self) -> ResultU16;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Type definition for a PUS mode servicd reply handler which constrains the
|
|
||||||
/// [PusServiceReplyHandler] active request and reply generics to the [ActiveActionRequest] and
|
|
||||||
/// [ActionReplyPusWithIds] type.
|
|
||||||
pub type PusModeServiceReplyHandler<
|
|
||||||
VerificationReporter,
|
|
||||||
ActiveRequestMap,
|
|
||||||
UserHook,
|
|
||||||
TmSender,
|
|
||||||
> = PusServiceReplyHandler<
|
|
||||||
VerificationReporter,
|
|
||||||
ActiveRequestMap,
|
|
||||||
UserHook,
|
|
||||||
TmSender,
|
|
||||||
ActivePusRequest,
|
|
||||||
ModeReply,
|
|
||||||
>;
|
|
||||||
|
|
||||||
impl<
|
|
||||||
VerificationReporter: VerificationReportingProvider,
|
|
||||||
ActiveRequestMap: ActiveRequestMapProvider<ActivePusRequest>,
|
|
||||||
UserHook: ModeReplyHook,
|
|
||||||
TmSender: EcssTmSenderCore,
|
|
||||||
> PusModeServiceReplyHandler<VerificationReporter, ActiveRequestMap, UserHook, TmSender>
|
|
||||||
{
|
|
||||||
/// Helper method to register a recently routed action request.
|
|
||||||
pub fn add_routed_mode_request(
|
|
||||||
&mut self,
|
|
||||||
request_id: verification::RequestId,
|
|
||||||
target_id: TargetId,
|
|
||||||
token: VerificationToken<TcStateStarted>,
|
|
||||||
timeout: Duration,
|
|
||||||
) {
|
|
||||||
self.active_request_map.insert(
|
|
||||||
&request_id.into(),
|
|
||||||
ActivePusRequest {
|
|
||||||
target_id,
|
|
||||||
token,
|
|
||||||
start_time: self.current_time,
|
|
||||||
timeout,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Main handler function to handle all received action replies.
|
|
||||||
pub fn handle_mode_reply(
|
|
||||||
&mut self,
|
|
||||||
mode_reply_with_id: &GenericModeReply,
|
|
||||||
time_stamp: &[u8],
|
|
||||||
) -> Result<(), EcssTmtcError> {
|
|
||||||
let active_req = self.active_request_map.get(mode_reply_with_id.request_id);
|
|
||||||
if active_req.is_none() {
|
|
||||||
self.user_hook.handle_unexpected_reply(mode_reply_with_id);
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
let active_req = active_req.unwrap().clone();
|
|
||||||
let remove_entry = match mode_reply_with_id.message {
|
|
||||||
ModeReply::ModeReply(reply) => {
|
|
||||||
reply.write_to_be_bytes(&mut self.tm_buf)?;
|
|
||||||
let req_id = verification::RequestId::from(mode_reply_with_id.request_id);
|
|
||||||
let mut sp_header = SpHeader::tm_unseg(
|
|
||||||
req_id.packet_id().apid(),
|
|
||||||
req_id.packet_seq_ctrl().seq_count(),
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
.expect("space packet header creation error");
|
|
||||||
let sec_header = PusTmSecondaryHeader::new(
|
|
||||||
MODE_SERVICE_ID,
|
|
||||||
Subservice::TmModeReply as u8,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
Some(time_stamp),
|
|
||||||
);
|
|
||||||
let pus_tm = PusTmCreator::new(&mut sp_header, sec_header, &self.tm_buf, true);
|
|
||||||
self.tm_sender.send_tm(PusTmWrapper::Direct(pus_tm))?;
|
|
||||||
self.verification_reporter
|
|
||||||
.completion_success(active_req.token, time_stamp)
|
|
||||||
.map_err(|e| e.0)?;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
ModeReply::CantReachMode(reason) => {
|
|
||||||
let fail_data_len = reason.write_to_be_bytes(&mut self.tm_buf)?;
|
|
||||||
self.verification_reporter
|
|
||||||
.completion_failure(
|
|
||||||
active_req.token,
|
|
||||||
FailParams::new(
|
|
||||||
time_stamp,
|
|
||||||
&self.user_hook.can_not_reach_mode_result_code(),
|
|
||||||
&self.tm_buf[0..fail_data_len],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map_err(|e| e.0)?;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
ModeReply::WrongMode { expected, reached } => {
|
|
||||||
let expected_len = expected.write_to_be_bytes(&mut self.tm_buf)?;
|
|
||||||
let reached_len =
|
|
||||||
reached.write_to_be_bytes(&mut self.tm_buf[expected_len..])?;
|
|
||||||
self.verification_reporter
|
|
||||||
.completion_failure(
|
|
||||||
active_req.token,
|
|
||||||
FailParams::new(
|
|
||||||
time_stamp,
|
|
||||||
&self.user_hook.can_not_reach_mode_result_code(),
|
|
||||||
&self.tm_buf[0..expected_len + reached_len],
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.map_err(|e| e.0)?;
|
|
||||||
true
|
|
||||||
}
|
|
||||||
_ => true,
|
|
||||||
};
|
|
||||||
if remove_entry {
|
|
||||||
self.active_request_map
|
|
||||||
.remove(mode_reply_with_id.request_id);
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
@ -175,7 +43,7 @@ mod tests {
|
|||||||
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
ModeAndSubmode, ModeReply, ModeReplySender, ModeRequest, ModeRequestSender,
|
||||||
ModeRequestorAndHandlerMpsc, ModeRequestorMpsc,
|
ModeRequestorAndHandlerMpsc, ModeRequestorMpsc,
|
||||||
},
|
},
|
||||||
request::GenericMessage,
|
request::{GenericMessage, MessageMetadata},
|
||||||
};
|
};
|
||||||
|
|
||||||
const TEST_COMPONENT_ID_0: u64 = 5;
|
const TEST_COMPONENT_ID_0: u64 = 5;
|
||||||
@ -196,24 +64,23 @@ mod tests {
|
|||||||
.send_mode_request(request_id, TEST_COMPONENT_ID_1, sent_request)
|
.send_mode_request(request_id, TEST_COMPONENT_ID_1, sent_request)
|
||||||
.expect("send failed");
|
.expect("send failed");
|
||||||
let request = request_receiver.recv().expect("recv failed");
|
let request = request_receiver.recv().expect("recv failed");
|
||||||
assert_eq!(request.request_id, 2);
|
assert_eq!(request.request_id(), 2);
|
||||||
assert_eq!(request.sender_id, TEST_COMPONENT_ID_0);
|
assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0);
|
||||||
assert_eq!(request.message, sent_request);
|
assert_eq!(request.message, sent_request);
|
||||||
|
|
||||||
// Send a reply and verify it arrives at the requestor.
|
// Send a reply and verify it arrives at the requestor.
|
||||||
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5));
|
let mode_reply = ModeReply::ModeReply(ModeAndSubmode::new(1, 5));
|
||||||
reply_sender
|
reply_sender
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
request_id,
|
MessageMetadata::new(request_id, TEST_COMPONENT_ID_1),
|
||||||
TEST_COMPONENT_ID_1,
|
|
||||||
mode_reply,
|
mode_reply,
|
||||||
))
|
))
|
||||||
.expect("send failed");
|
.expect("send failed");
|
||||||
let reply = mode_requestor.try_recv_mode_reply().expect("recv failed");
|
let reply = mode_requestor.try_recv_mode_reply().expect("recv failed");
|
||||||
assert!(reply.is_some());
|
assert!(reply.is_some());
|
||||||
let reply = reply.unwrap();
|
let reply = reply.unwrap();
|
||||||
assert_eq!(reply.sender_id, TEST_COMPONENT_ID_1);
|
assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_1);
|
||||||
assert_eq!(reply.request_id, 2);
|
assert_eq!(reply.request_id(), 2);
|
||||||
assert_eq!(reply.message, mode_reply);
|
assert_eq!(reply.message, mode_reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -252,8 +119,8 @@ mod tests {
|
|||||||
.expect("send failed");
|
.expect("send failed");
|
||||||
|
|
||||||
let request = request_receiver_channel_1.recv().expect("recv failed");
|
let request = request_receiver_channel_1.recv().expect("recv failed");
|
||||||
assert_eq!(request.request_id, 2);
|
assert_eq!(request.request_id(), 2);
|
||||||
assert_eq!(request.sender_id, TEST_COMPONENT_ID_0);
|
assert_eq!(request.sender_id(), TEST_COMPONENT_ID_0);
|
||||||
assert_eq!(request.message, ModeRequest::ReadMode);
|
assert_eq!(request.message, ModeRequest::ReadMode);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,13 +139,16 @@ mod tests {
|
|||||||
|
|
||||||
// Send a request and verify it arrives at the receiver.
|
// Send a request and verify it arrives at the receiver.
|
||||||
let request_id = 2;
|
let request_id = 2;
|
||||||
let sent_reply = ModeReply::ModeInfo(ModeAndSubmode::new(3, 5));
|
let sent_reply = ModeReply::ModeReply(ModeAndSubmode::new(3, 5));
|
||||||
mode_connector
|
mode_connector
|
||||||
.send_mode_reply(request_id, TEST_COMPONENT_ID_2, sent_reply)
|
.send_mode_reply(
|
||||||
|
MessageMetadata::new(request_id, TEST_COMPONENT_ID_0),
|
||||||
|
sent_reply,
|
||||||
|
)
|
||||||
.expect("send failed");
|
.expect("send failed");
|
||||||
let reply = reply_receiver_channel_2.recv().expect("recv failed");
|
let reply = reply_receiver_channel_2.recv().expect("recv failed");
|
||||||
assert_eq!(reply.request_id, 2);
|
assert_eq!(reply.request_id(), 2);
|
||||||
assert_eq!(reply.sender_id, TEST_COMPONENT_ID_0);
|
assert_eq!(reply.sender_id(), TEST_COMPONENT_ID_0);
|
||||||
assert_eq!(reply.message, sent_reply);
|
assert_eq!(reply.message, sent_reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,19 +1,16 @@
|
|||||||
use super::scheduler::PusSchedulerProvider;
|
use super::scheduler::PusSchedulerProvider;
|
||||||
use super::verification::{
|
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender,
|
|
||||||
VerificationReporterWithVecMpscSender, VerificationReportingProvider,
|
|
||||||
};
|
|
||||||
use super::{
|
use super::{
|
||||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
||||||
EcssTmSenderCore, MpscTcReceiver, PusServiceHelper, TmAsVecSenderWithBoundedMpsc,
|
EcssTmSenderCore, MpscTcReceiver, MpscTmInSharedPoolSender, MpscTmInSharedPoolSenderBounded,
|
||||||
TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc, TmInSharedPoolSenderWithMpsc,
|
PusServiceHelper, PusTmAsVec,
|
||||||
};
|
};
|
||||||
use crate::pool::PoolProvider;
|
use crate::pool::PoolProvider;
|
||||||
use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError};
|
use crate::pus::{PusPacketHandlerResult, PusPacketHandlingError};
|
||||||
use alloc::string::ToString;
|
use alloc::string::ToString;
|
||||||
use spacepackets::ecss::{scheduling, PusPacket};
|
use spacepackets::ecss::{scheduling, PusPacket};
|
||||||
use spacepackets::time::cds::TimeProvider;
|
use spacepackets::time::cds::CdsTime;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
/// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service)
|
/// This is a helper class for [std] environments to handle generic PUS 11 (scheduling service)
|
||||||
/// packets. This handler is able to handle the most important PUS requests for a scheduling
|
/// packets. This handler is able to handle the most important PUS requests for a scheduling
|
||||||
@ -23,7 +20,7 @@ use spacepackets::time::cds::TimeProvider;
|
|||||||
/// telecommands inside the scheduler. The user can retrieve the wrapped scheduler via the
|
/// telecommands inside the scheduler. The user can retrieve the wrapped scheduler via the
|
||||||
/// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release
|
/// [Self::scheduler] and [Self::scheduler_mut] function and then use the scheduler API to release
|
||||||
/// telecommands when applicable.
|
/// telecommands when applicable.
|
||||||
pub struct PusService11SchedHandler<
|
pub struct PusSchedServiceHandler<
|
||||||
TcReceiver: EcssTcReceiverCore,
|
TcReceiver: EcssTcReceiverCore,
|
||||||
TmSender: EcssTmSenderCore,
|
TmSender: EcssTmSenderCore,
|
||||||
TcInMemConverter: EcssTcInMemConverter,
|
TcInMemConverter: EcssTcInMemConverter,
|
||||||
@ -42,13 +39,7 @@ impl<
|
|||||||
VerificationReporter: VerificationReportingProvider,
|
VerificationReporter: VerificationReportingProvider,
|
||||||
Scheduler: PusSchedulerProvider,
|
Scheduler: PusSchedulerProvider,
|
||||||
>
|
>
|
||||||
PusService11SchedHandler<
|
PusSchedServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter, Scheduler>
|
||||||
TcReceiver,
|
|
||||||
TmSender,
|
|
||||||
TcInMemConverter,
|
|
||||||
VerificationReporter,
|
|
||||||
Scheduler,
|
|
||||||
>
|
|
||||||
{
|
{
|
||||||
pub fn new(
|
pub fn new(
|
||||||
service_helper: PusServiceHelper<
|
service_helper: PusServiceHelper<
|
||||||
@ -101,14 +92,24 @@ impl<
|
|||||||
let start_token = self
|
let start_token = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending start success");
|
.expect("Error sending start success");
|
||||||
|
|
||||||
self.scheduler.enable();
|
self.scheduler.enable();
|
||||||
if self.scheduler.is_enabled() {
|
if self.scheduler.is_enabled() {
|
||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, time_stamp)
|
.completion_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
start_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending completion success");
|
.expect("Error sending completion success");
|
||||||
} else {
|
} else {
|
||||||
return Err(PusPacketHandlingError::Other(
|
return Err(PusPacketHandlingError::Other(
|
||||||
@ -120,14 +121,24 @@ impl<
|
|||||||
let start_token = self
|
let start_token = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending start success");
|
.expect("Error sending start success");
|
||||||
|
|
||||||
self.scheduler.disable();
|
self.scheduler.disable();
|
||||||
if !self.scheduler.is_enabled() {
|
if !self.scheduler.is_enabled() {
|
||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, time_stamp)
|
.completion_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
start_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending completion success");
|
.expect("Error sending completion success");
|
||||||
} else {
|
} else {
|
||||||
return Err(PusPacketHandlingError::Other(
|
return Err(PusPacketHandlingError::Other(
|
||||||
@ -139,7 +150,12 @@ impl<
|
|||||||
let start_token = self
|
let start_token = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending start success");
|
.expect("Error sending start success");
|
||||||
|
|
||||||
self.scheduler
|
self.scheduler
|
||||||
@ -148,7 +164,12 @@ impl<
|
|||||||
|
|
||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, time_stamp)
|
.completion_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
start_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("Error sending completion success");
|
.expect("Error sending completion success");
|
||||||
}
|
}
|
||||||
scheduling::Subservice::TcInsertActivity => {
|
scheduling::Subservice::TcInsertActivity => {
|
||||||
@ -156,17 +177,27 @@ impl<
|
|||||||
.service_helper
|
.service_helper
|
||||||
.common
|
.common
|
||||||
.verif_reporter
|
.verif_reporter
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("error sending start success");
|
.expect("error sending start success");
|
||||||
|
|
||||||
// let mut pool = self.sched_tc_pool.write().expect("locking pool failed");
|
// let mut pool = self.sched_tc_pool.write().expect("locking pool failed");
|
||||||
self.scheduler
|
self.scheduler
|
||||||
.insert_wrapped_tc::<TimeProvider>(&tc, sched_tc_pool)
|
.insert_wrapped_tc::<CdsTime>(&tc, sched_tc_pool)
|
||||||
.expect("insertion of activity into pool failed");
|
.expect("insertion of activity into pool failed");
|
||||||
|
|
||||||
self.service_helper
|
self.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, time_stamp)
|
.completion_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
start_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.expect("sending completion success failed");
|
.expect("sending completion success failed");
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
@ -187,38 +218,38 @@ impl<
|
|||||||
}
|
}
|
||||||
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and regular
|
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and regular
|
||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusService11SchedHandler<
|
pub type PusService11SchedHandlerDynWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
mpsc::Sender<PusTmAsVec>,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscSender,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and bounded MPSC
|
/// Helper type definition for a PUS 11 handler with a dynamic TMTC memory backend and bounded MPSC
|
||||||
/// queues.
|
/// queues.
|
||||||
pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusService11SchedHandler<
|
pub type PusService11SchedHandlerDynWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithBoundedMpsc,
|
mpsc::SyncSender<PusTmAsVec>,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscBoundedSender,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and regular
|
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and regular
|
||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusService11SchedHandler<
|
pub type PusService11SchedHandlerStaticWithMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithMpsc,
|
MpscTmInSharedPoolSender,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscSender,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and bounded
|
/// Helper type definition for a PUS 11 handler with a shared store TMTC memory backend and bounded
|
||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusService11SchedHandler<
|
pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
PusScheduler,
|
PusScheduler,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
@ -226,7 +257,8 @@ pub type PusService11SchedHandlerStaticWithBoundedMpsc<PusScheduler> = PusServic
|
|||||||
mod tests {
|
mod tests {
|
||||||
use crate::pool::{StaticMemoryPool, StaticPoolConfig};
|
use crate::pool::{StaticMemoryPool, StaticPoolConfig};
|
||||||
use crate::pus::test_util::{PusTestHarness, TEST_APID};
|
use crate::pus::test_util::{PusTestHarness, TEST_APID};
|
||||||
use crate::pus::verification::VerificationReporterWithSharedPoolMpscBoundedSender;
|
use crate::pus::verification::{VerificationReporter, VerificationReportingProvider};
|
||||||
|
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
scheduler::{self, PusSchedulerProvider, TcInfo},
|
scheduler::{self, PusSchedulerProvider, TcInfo},
|
||||||
tests::PusServiceHandlerWithSharedStoreCommon,
|
tests::PusServiceHandlerWithSharedStoreCommon,
|
||||||
@ -234,8 +266,8 @@ mod tests {
|
|||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
};
|
};
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
MpscTcReceiver, PusPacketHandlerResult, PusPacketHandlingError,
|
MpscTcReceiver, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
PusPacketHandlingError,
|
||||||
};
|
};
|
||||||
use alloc::collections::VecDeque;
|
use alloc::collections::VecDeque;
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
@ -249,15 +281,15 @@ mod tests {
|
|||||||
time::cds,
|
time::cds,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::PusService11SchedHandler;
|
use super::PusSchedServiceHandler;
|
||||||
|
|
||||||
struct Pus11HandlerWithStoreTester {
|
struct Pus11HandlerWithStoreTester {
|
||||||
common: PusServiceHandlerWithSharedStoreCommon,
|
common: PusServiceHandlerWithSharedStoreCommon,
|
||||||
handler: PusService11SchedHandler<
|
handler: PusSchedServiceHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
TestScheduler,
|
TestScheduler,
|
||||||
>,
|
>,
|
||||||
sched_tc_pool: StaticMemoryPool,
|
sched_tc_pool: StaticMemoryPool,
|
||||||
@ -268,25 +300,39 @@ mod tests {
|
|||||||
let test_scheduler = TestScheduler::default();
|
let test_scheduler = TestScheduler::default();
|
||||||
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
|
let pool_cfg = StaticPoolConfig::new(alloc::vec![(16, 16), (8, 32), (4, 64)], false);
|
||||||
let sched_tc_pool = StaticMemoryPool::new(pool_cfg.clone());
|
let sched_tc_pool = StaticMemoryPool::new(pool_cfg.clone());
|
||||||
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
|
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(0);
|
||||||
Self {
|
Self {
|
||||||
common,
|
common,
|
||||||
handler: PusService11SchedHandler::new(srv_handler, test_scheduler),
|
handler: PusSchedServiceHandler::new(srv_handler, test_scheduler),
|
||||||
sched_tc_pool,
|
sched_tc_pool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
pub fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||||
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
|
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||||
self.handler
|
self.handler
|
||||||
.poll_and_handle_next_tc(&time_stamp, &mut self.sched_tc_pool)
|
.poll_and_handle_next_tc(&time_stamp, &mut self.sched_tc_pool)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus11HandlerWithStoreTester {
|
impl PusTestHarness for Pus11HandlerWithStoreTester {
|
||||||
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
|
self.handler
|
||||||
|
.service_helper
|
||||||
|
.verif_reporter()
|
||||||
|
.acceptance_success(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
init_token,
|
||||||
|
&[0; 7],
|
||||||
|
)
|
||||||
|
.expect("acceptance success failure")
|
||||||
|
}
|
||||||
|
|
||||||
delegate! {
|
delegate! {
|
||||||
to self.common {
|
to self.common {
|
||||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
fn check_next_verification_tm(&self, subservice: u8, expected_request_id: RequestId);
|
||||||
@ -304,7 +350,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusSchedulerProvider for TestScheduler {
|
impl PusSchedulerProvider for TestScheduler {
|
||||||
type TimeProvider = cds::TimeProvider;
|
type TimeProvider = cds::CdsTime;
|
||||||
|
|
||||||
fn reset(
|
fn reset(
|
||||||
&mut self,
|
&mut self,
|
||||||
@ -330,7 +376,7 @@ mod tests {
|
|||||||
|
|
||||||
fn insert_unwrapped_and_stored_tc(
|
fn insert_unwrapped_and_stored_tc(
|
||||||
&mut self,
|
&mut self,
|
||||||
_time_stamp: spacepackets::time::UnixTimestamp,
|
_time_stamp: spacepackets::time::UnixTime,
|
||||||
info: crate::pus::scheduler::TcInfo,
|
info: crate::pus::scheduler::TcInfo,
|
||||||
) -> Result<(), crate::pus::scheduler::ScheduleError> {
|
) -> Result<(), crate::pus::scheduler::ScheduleError> {
|
||||||
self.inserted_tcs.push_back(info);
|
self.inserted_tcs.push_back(info);
|
||||||
@ -345,10 +391,11 @@ mod tests {
|
|||||||
let mut reply_header = SpHeader::tm_unseg(TEST_APID, 0, 0).unwrap();
|
let mut reply_header = SpHeader::tm_unseg(TEST_APID, 0, 0).unwrap();
|
||||||
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
|
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
|
||||||
let enable_scheduling = PusTcCreator::new(&mut reply_header, tc_header, &[0; 7], true);
|
let enable_scheduling = PusTcCreator::new(&mut reply_header, tc_header, &[0; 7], true);
|
||||||
let token = test_harness.send_tc(&enable_scheduling);
|
let token = test_harness.init_verification(&enable_scheduling);
|
||||||
|
test_harness.send_tc(&token, &enable_scheduling);
|
||||||
|
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
|
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||||
test_harness
|
test_harness
|
||||||
.handler
|
.handler
|
||||||
.poll_and_handle_next_tc(&time_stamp, &mut test_harness.sched_tc_pool)
|
.poll_and_handle_next_tc(&time_stamp, &mut test_harness.sched_tc_pool)
|
||||||
@ -392,7 +439,7 @@ mod tests {
|
|||||||
let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
let mut sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||||
let ping_tc = PusTcCreator::new(&mut reply_header, sec_header, &[], true);
|
let ping_tc = PusTcCreator::new(&mut reply_header, sec_header, &[], true);
|
||||||
let req_id_ping_tc = scheduler::RequestId::from_tc(&ping_tc);
|
let req_id_ping_tc = scheduler::RequestId::from_tc(&ping_tc);
|
||||||
let stamper = cds::TimeProvider::from_now_with_u16_days().expect("time provider failed");
|
let stamper = cds::CdsTime::now_with_u16_days().expect("time provider failed");
|
||||||
let mut sched_app_data: [u8; 64] = [0; 64];
|
let mut sched_app_data: [u8; 64] = [0; 64];
|
||||||
let mut written_len = stamper.write_to_bytes(&mut sched_app_data).unwrap();
|
let mut written_len = stamper.write_to_bytes(&mut sched_app_data).unwrap();
|
||||||
let ping_raw = ping_tc.to_vec().expect("generating raw tc failed");
|
let ping_raw = ping_tc.to_vec().expect("generating raw tc failed");
|
||||||
@ -406,7 +453,8 @@ mod tests {
|
|||||||
&sched_app_data[..written_len],
|
&sched_app_data[..written_len],
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
let token = test_harness.send_tc(&enable_scheduling);
|
let token = test_harness.init_verification(&enable_scheduling);
|
||||||
|
test_harness.send_tc(&token, &enable_scheduling);
|
||||||
|
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
test_harness.handle_one_tc().unwrap();
|
test_harness.handle_one_tc().unwrap();
|
||||||
|
@ -1,20 +1,17 @@
|
|||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmWrapper,
|
PartialPusHandlingError, PusPacketHandlerResult, PusPacketHandlingError, PusTmAsVec,
|
||||||
|
PusTmInPool, PusTmVariant,
|
||||||
};
|
};
|
||||||
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
||||||
use spacepackets::ecss::PusPacket;
|
use spacepackets::ecss::PusPacket;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
|
use std::sync::mpsc;
|
||||||
|
|
||||||
use super::verification::{
|
use super::verification::{VerificationReporter, VerificationReportingProvider};
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
|
||||||
VerificationReporterWithSharedPoolMpscSender, VerificationReporterWithVecMpscBoundedSender,
|
|
||||||
VerificationReporterWithVecMpscSender, VerificationReportingProvider,
|
|
||||||
};
|
|
||||||
use super::{
|
use super::{
|
||||||
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
EcssTcInMemConverter, EcssTcInSharedStoreConverter, EcssTcInVecConverter, EcssTcReceiverCore,
|
||||||
EcssTmSenderCore, GenericConversionError, MpscTcReceiver, PusServiceHelper,
|
EcssTmSenderCore, GenericConversionError, MpscTcReceiver, MpscTmInSharedPoolSender,
|
||||||
TmAsVecSenderWithBoundedMpsc, TmAsVecSenderWithMpsc, TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded, PusServiceHelper,
|
||||||
TmInSharedPoolSenderWithMpsc,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
/// This is a helper class for [std] environments to handle generic PUS 17 (test service) packets.
|
||||||
@ -68,7 +65,12 @@ impl<
|
|||||||
let result = self
|
let result = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.start_success(ecss_tc_and_token.token, time_stamp)
|
.start_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
ecss_tc_and_token.token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.map_err(|_| PartialPusHandlingError::Verification);
|
.map_err(|_| PartialPusHandlingError::Verification);
|
||||||
let start_token = if let Ok(result) = result {
|
let start_token = if let Ok(result) = result {
|
||||||
Some(result)
|
Some(result)
|
||||||
@ -78,14 +80,14 @@ impl<
|
|||||||
};
|
};
|
||||||
// Sequence count will be handled centrally in TM funnel.
|
// Sequence count will be handled centrally in TM funnel.
|
||||||
let mut reply_header =
|
let mut reply_header =
|
||||||
SpHeader::tm_unseg(self.service_helper.common.tm_apid, 0, 0).unwrap();
|
SpHeader::tm_unseg(self.service_helper.verif_reporter().apid(), 0, 0).unwrap();
|
||||||
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, time_stamp);
|
let tc_header = PusTmSecondaryHeader::new_simple(17, 2, time_stamp);
|
||||||
let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true);
|
let ping_reply = PusTmCreator::new(&mut reply_header, tc_header, &[], true);
|
||||||
let result = self
|
let result = self
|
||||||
.service_helper
|
.service_helper
|
||||||
.common
|
.common
|
||||||
.tm_sender
|
.tm_sender
|
||||||
.send_tm(PusTmWrapper::Direct(ping_reply))
|
.send_tm(self.service_helper.id(), PusTmVariant::Direct(ping_reply))
|
||||||
.map_err(PartialPusHandlingError::TmSend);
|
.map_err(PartialPusHandlingError::TmSend);
|
||||||
if let Err(err) = result {
|
if let Err(err) = result {
|
||||||
partial_error = Some(err);
|
partial_error = Some(err);
|
||||||
@ -95,7 +97,12 @@ impl<
|
|||||||
if self
|
if self
|
||||||
.service_helper
|
.service_helper
|
||||||
.verif_reporter()
|
.verif_reporter()
|
||||||
.completion_success(start_token, time_stamp)
|
.completion_success(
|
||||||
|
self.service_helper.common.id,
|
||||||
|
&self.service_helper.common.tm_sender,
|
||||||
|
start_token,
|
||||||
|
time_stamp,
|
||||||
|
)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
partial_error = Some(PartialPusHandlingError::Verification)
|
partial_error = Some(PartialPusHandlingError::Verification)
|
||||||
@ -120,33 +127,33 @@ impl<
|
|||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler<
|
pub type PusService17TestHandlerDynWithMpsc = PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
mpsc::Sender<PusTmAsVec>,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscSender,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and bounded MPSC
|
/// Helper type definition for a PUS 17 handler with a dynamic TMTC memory backend and bounded MPSC
|
||||||
/// queues.
|
/// queues.
|
||||||
pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler<
|
pub type PusService17TestHandlerDynWithBoundedMpsc = PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithBoundedMpsc,
|
mpsc::SyncSender<PusTmInPool>,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscBoundedSender,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and regular
|
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and regular
|
||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService17TestHandlerStaticWithMpsc = PusService17TestHandler<
|
pub type PusService17TestHandlerStaticWithMpsc = PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithMpsc,
|
MpscTmInSharedPoolSender,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscSender,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and bounded
|
/// Helper type definition for a PUS 17 handler with a shared store TMTC memory backend and bounded
|
||||||
/// mpsc queues.
|
/// mpsc queues.
|
||||||
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
pub type PusService17TestHandlerStaticWithBoundedMpsc = PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
>;
|
>;
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
@ -155,16 +162,17 @@ mod tests {
|
|||||||
use crate::pus::tests::{
|
use crate::pus::tests::{
|
||||||
PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon,
|
PusServiceHandlerWithSharedStoreCommon, PusServiceHandlerWithVecCommon,
|
||||||
};
|
};
|
||||||
use crate::pus::verification::std_mod::{
|
use crate::pus::verification::test_util::TestVerificationReporter;
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender, VerificationReporterWithVecMpscSender,
|
use crate::pus::verification::{
|
||||||
|
RequestId, VerificationReporter, VerificationReportingProvider,
|
||||||
};
|
};
|
||||||
use crate::pus::verification::RequestId;
|
|
||||||
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
use crate::pus::verification::{TcStateAccepted, VerificationToken};
|
||||||
use crate::pus::{
|
use crate::pus::{
|
||||||
EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, MpscTcReceiver,
|
EcssTcInSharedStoreConverter, EcssTcInVecConverter, GenericConversionError, MpscTcReceiver,
|
||||||
PusPacketHandlerResult, PusPacketHandlingError, TmAsVecSenderWithMpsc,
|
MpscTmAsVecSender, MpscTmInSharedPoolSenderBounded, PusPacketHandlerResult,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
PusPacketHandlingError,
|
||||||
};
|
};
|
||||||
|
use crate::ComponentId;
|
||||||
use delegate::delegate;
|
use delegate::delegate;
|
||||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
|
use spacepackets::ecss::tc::{PusTcCreator, PusTcSecondaryHeader};
|
||||||
use spacepackets::ecss::tm::PusTmReader;
|
use spacepackets::ecss::tm::PusTmReader;
|
||||||
@ -178,15 +186,15 @@ mod tests {
|
|||||||
common: PusServiceHandlerWithSharedStoreCommon,
|
common: PusServiceHandlerWithSharedStoreCommon,
|
||||||
handler: PusService17TestHandler<
|
handler: PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmInSharedPoolSenderWithBoundedMpsc,
|
MpscTmInSharedPoolSenderBounded,
|
||||||
EcssTcInSharedStoreConverter,
|
EcssTcInSharedStoreConverter,
|
||||||
VerificationReporterWithSharedPoolMpscBoundedSender,
|
VerificationReporter,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pus17HandlerWithStoreTester {
|
impl Pus17HandlerWithStoreTester {
|
||||||
pub fn new() -> Self {
|
pub fn new(id: ComponentId) -> Self {
|
||||||
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new();
|
let (common, srv_handler) = PusServiceHandlerWithSharedStoreCommon::new(id);
|
||||||
let pus_17_handler = PusService17TestHandler::new(srv_handler);
|
let pus_17_handler = PusService17TestHandler::new(srv_handler);
|
||||||
Self {
|
Self {
|
||||||
common,
|
common,
|
||||||
@ -196,10 +204,24 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus17HandlerWithStoreTester {
|
impl PusTestHarness for Pus17HandlerWithStoreTester {
|
||||||
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
|
self.handler
|
||||||
|
.service_helper
|
||||||
|
.verif_reporter()
|
||||||
|
.acceptance_success(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
init_token,
|
||||||
|
&[0; 7],
|
||||||
|
)
|
||||||
|
.expect("acceptance success failure")
|
||||||
|
}
|
||||||
|
|
||||||
delegate! {
|
delegate! {
|
||||||
to self.common {
|
to self.common {
|
||||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
fn check_next_verification_tm(
|
fn check_next_verification_tm(
|
||||||
&self,
|
&self,
|
||||||
@ -211,25 +233,25 @@ mod tests {
|
|||||||
}
|
}
|
||||||
impl SimplePusPacketHandler for Pus17HandlerWithStoreTester {
|
impl SimplePusPacketHandler for Pus17HandlerWithStoreTester {
|
||||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||||
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
|
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||||
self.handler.poll_and_handle_next_tc(&time_stamp)
|
self.handler.poll_and_handle_next_tc(&time_stamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Pus17HandlerWithVecTester {
|
struct Pus17HandlerWithVecTester {
|
||||||
common: PusServiceHandlerWithVecCommon<VerificationReporterWithVecMpscSender>,
|
common: PusServiceHandlerWithVecCommon,
|
||||||
handler: PusService17TestHandler<
|
handler: PusService17TestHandler<
|
||||||
MpscTcReceiver,
|
MpscTcReceiver,
|
||||||
TmAsVecSenderWithMpsc,
|
MpscTmAsVecSender,
|
||||||
EcssTcInVecConverter,
|
EcssTcInVecConverter,
|
||||||
VerificationReporterWithVecMpscSender,
|
TestVerificationReporter,
|
||||||
>,
|
>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Pus17HandlerWithVecTester {
|
impl Pus17HandlerWithVecTester {
|
||||||
pub fn new() -> Self {
|
pub fn new(id: ComponentId) -> Self {
|
||||||
let (common, srv_handler) =
|
let (common, srv_handler) =
|
||||||
PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter();
|
PusServiceHandlerWithVecCommon::new_with_standard_verif_reporter(id);
|
||||||
Self {
|
Self {
|
||||||
common,
|
common,
|
||||||
handler: PusService17TestHandler::new(srv_handler),
|
handler: PusService17TestHandler::new(srv_handler),
|
||||||
@ -238,9 +260,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl PusTestHarness for Pus17HandlerWithVecTester {
|
impl PusTestHarness for Pus17HandlerWithVecTester {
|
||||||
|
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
|
||||||
|
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
|
||||||
|
self.handler
|
||||||
|
.service_helper
|
||||||
|
.verif_reporter()
|
||||||
|
.acceptance_success(
|
||||||
|
self.handler.service_helper.id(),
|
||||||
|
self.handler.service_helper.tm_sender(),
|
||||||
|
init_token,
|
||||||
|
&[0; 7],
|
||||||
|
)
|
||||||
|
.expect("acceptance success failure")
|
||||||
|
}
|
||||||
|
|
||||||
delegate! {
|
delegate! {
|
||||||
to self.common {
|
to self.common {
|
||||||
fn send_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
|
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
|
||||||
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
fn read_next_tm(&mut self) -> PusTmReader<'_>;
|
||||||
fn check_no_tm_available(&self) -> bool;
|
fn check_no_tm_available(&self) -> bool;
|
||||||
fn check_next_verification_tm(
|
fn check_next_verification_tm(
|
||||||
@ -253,7 +289,7 @@ mod tests {
|
|||||||
}
|
}
|
||||||
impl SimplePusPacketHandler for Pus17HandlerWithVecTester {
|
impl SimplePusPacketHandler for Pus17HandlerWithVecTester {
|
||||||
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
fn handle_one_tc(&mut self) -> Result<PusPacketHandlerResult, PusPacketHandlingError> {
|
||||||
let time_stamp = cds::TimeProvider::new_with_u16_days(0, 0).to_vec().unwrap();
|
let time_stamp = cds::CdsTime::new_with_u16_days(0, 0).to_vec().unwrap();
|
||||||
self.handler.poll_and_handle_next_tc(&time_stamp)
|
self.handler.poll_and_handle_next_tc(&time_stamp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -263,7 +299,8 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||||
let token = test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let request_id = token.request_id();
|
let request_id = token.request_id();
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
@ -288,19 +325,19 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_ping_processing_using_store() {
|
fn test_basic_ping_processing_using_store() {
|
||||||
let mut test_harness = Pus17HandlerWithStoreTester::new();
|
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
|
||||||
ping_test(&mut test_harness);
|
ping_test(&mut test_harness);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_ping_processing_using_vec() {
|
fn test_basic_ping_processing_using_vec() {
|
||||||
let mut test_harness = Pus17HandlerWithVecTester::new();
|
let mut test_harness = Pus17HandlerWithVecTester::new(0);
|
||||||
ping_test(&mut test_harness);
|
ping_test(&mut test_harness);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_empty_tc_queue() {
|
fn test_empty_tc_queue() {
|
||||||
let mut test_harness = Pus17HandlerWithStoreTester::new();
|
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let result = result.unwrap();
|
let result = result.unwrap();
|
||||||
@ -312,11 +349,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sending_unsupported_service() {
|
fn test_sending_unsupported_service() {
|
||||||
let mut test_harness = Pus17HandlerWithStoreTester::new();
|
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
|
||||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
|
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||||
test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
@ -332,11 +370,12 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sending_custom_subservice() {
|
fn test_sending_custom_subservice() {
|
||||||
let mut test_harness = Pus17HandlerWithStoreTester::new();
|
let mut test_harness = Pus17HandlerWithStoreTester::new(0);
|
||||||
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
let mut sp_header = SpHeader::tc(TEST_APID, SequenceFlags::Unsegmented, 0, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
|
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
|
||||||
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
let ping_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||||
test_harness.send_tc(&ping_tc);
|
let token = test_harness.init_verification(&ping_tc);
|
||||||
|
test_harness.send_tc(&token, &ping_tc);
|
||||||
let result = test_harness.handle_one_tc();
|
let result = test_harness.handle_one_tc();
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
let result = result.unwrap();
|
let result = result.unwrap();
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -25,21 +25,24 @@ pub type RequestId = u32;
|
|||||||
pub type Apid = u16;
|
pub type Apid = u16;
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
pub struct TargetAndApidId {
|
pub struct UniqueApidTargetId {
|
||||||
pub apid: Apid,
|
pub apid: Apid,
|
||||||
pub target: u32,
|
pub unique_id: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TargetAndApidId {
|
impl UniqueApidTargetId {
|
||||||
pub const fn new(apid: Apid, target: u32) -> Self {
|
pub const fn new(apid: Apid, target: u32) -> Self {
|
||||||
Self { apid, target }
|
Self {
|
||||||
|
apid,
|
||||||
|
unique_id: target,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn raw(&self) -> ComponentId {
|
pub fn raw(&self) -> ComponentId {
|
||||||
((self.apid as u64) << 32) | (self.target as u64)
|
((self.apid as u64) << 32) | (self.unique_id as u64)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn full_target_id(&self) -> ComponentId {
|
pub fn id(&self) -> ComponentId {
|
||||||
self.raw()
|
self.raw()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -61,49 +64,78 @@ impl TargetAndApidId {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<u64> for TargetAndApidId {
|
impl From<u64> for UniqueApidTargetId {
|
||||||
fn from(raw: u64) -> Self {
|
fn from(raw: u64) -> Self {
|
||||||
Self {
|
Self {
|
||||||
apid: (raw >> 32) as u16,
|
apid: (raw >> 32) as u16,
|
||||||
target: raw as u32,
|
unique_id: raw as u32,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<TargetAndApidId> for u64 {
|
impl From<UniqueApidTargetId> for u64 {
|
||||||
fn from(target_and_apid_id: TargetAndApidId) -> Self {
|
fn from(target_and_apid_id: UniqueApidTargetId) -> Self {
|
||||||
target_and_apid_id.raw()
|
target_and_apid_id.raw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Display for TargetAndApidId {
|
impl fmt::Display for UniqueApidTargetId {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(
|
write!(
|
||||||
f,
|
f,
|
||||||
"Target and APID ID with APID {:#03x} and target {}",
|
"Target and APID ID with APID {:#03x} and target {}",
|
||||||
self.apid, self.target
|
self.apid, self.unique_id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, PartialEq, Eq, Clone)]
|
||||||
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
pub struct MessageMetadata {
|
||||||
|
request_id: RequestId,
|
||||||
|
sender_id: ComponentId,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MessageMetadata {
|
||||||
|
pub const fn new(request_id: RequestId, sender_id: ComponentId) -> Self {
|
||||||
|
Self {
|
||||||
|
request_id,
|
||||||
|
sender_id,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn request_id(&self) -> RequestId {
|
||||||
|
self.request_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn sender_id(&self) -> ComponentId {
|
||||||
|
self.sender_id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generic message type which is associated with a sender using a [ChannelId] and associated
|
/// Generic message type which is associated with a sender using a [ChannelId] and associated
|
||||||
/// with a request using a [RequestId].
|
/// with a request using a [RequestId].
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct GenericMessage<MSG> {
|
pub struct GenericMessage<MSG> {
|
||||||
pub request_id: RequestId,
|
pub requestor_info: MessageMetadata,
|
||||||
pub sender_id: ComponentId,
|
|
||||||
pub message: MSG,
|
pub message: MSG,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<MSG> GenericMessage<MSG> {
|
impl<MSG> GenericMessage<MSG> {
|
||||||
pub fn new(request_id: RequestId, sender_id: ComponentId, message: MSG) -> Self {
|
pub fn new(requestor_info: MessageMetadata, message: MSG) -> Self {
|
||||||
Self {
|
Self {
|
||||||
request_id,
|
requestor_info,
|
||||||
sender_id,
|
|
||||||
message,
|
message,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delegate::delegate! {
|
||||||
|
to self.requestor_info {
|
||||||
|
pub fn request_id(&self) -> RequestId;
|
||||||
|
pub fn sender_id(&self) -> ComponentId;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generic trait for objects which can send targeted messages.
|
/// Generic trait for objects which can send targeted messages.
|
||||||
@ -186,8 +218,7 @@ pub mod alloc_mod {
|
|||||||
|
|
||||||
pub fn send_message(
|
pub fn send_message(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
requestor_info: MessageMetadata,
|
||||||
local_channel_id: ComponentId,
|
|
||||||
target_channel_id: ComponentId,
|
target_channel_id: ComponentId,
|
||||||
message: MSG,
|
message: MSG,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
@ -196,45 +227,12 @@ pub mod alloc_mod {
|
|||||||
.0
|
.0
|
||||||
.get(&target_channel_id)
|
.get(&target_channel_id)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.send(GenericMessage::new(request_id, local_channel_id, message));
|
.send(GenericMessage::new(requestor_info, message));
|
||||||
}
|
}
|
||||||
Err(GenericSendError::TargetDoesNotExist(target_channel_id).into())
|
Err(GenericSendError::TargetDoesNotExist(target_channel_id).into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MessageSenderMapWithId<MSG, S: MessageSender<MSG>> {
|
|
||||||
pub local_channel_id: ComponentId,
|
|
||||||
pub message_sender_map: MessageSenderMap<MSG, S>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<MSG, S: MessageSender<MSG>> MessageSenderMapWithId<MSG, S> {
|
|
||||||
pub fn new(local_channel_id: ComponentId) -> Self {
|
|
||||||
Self {
|
|
||||||
local_channel_id,
|
|
||||||
message_sender_map: Default::default(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn send_message(
|
|
||||||
&self,
|
|
||||||
request_id: RequestId,
|
|
||||||
target_channel_id: ComponentId,
|
|
||||||
message: MSG,
|
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
|
||||||
self.message_sender_map.send_message(
|
|
||||||
request_id,
|
|
||||||
self.local_channel_id,
|
|
||||||
target_channel_id,
|
|
||||||
message,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add_message_target(&mut self, target_id: ComponentId, message_sender: S) {
|
|
||||||
self.message_sender_map
|
|
||||||
.add_message_target(target_id, message_sender)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct MessageSenderAndReceiver<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>> {
|
pub struct MessageSenderAndReceiver<TO, FROM, S: MessageSender<TO>, R: MessageReceiver<FROM>> {
|
||||||
pub local_channel_id: ComponentId,
|
pub local_channel_id: ComponentId,
|
||||||
pub message_sender_map: MessageSenderMap<TO, S>,
|
pub message_sender_map: MessageSenderMap<TO, S>,
|
||||||
@ -265,13 +263,12 @@ pub mod alloc_mod {
|
|||||||
pub fn send_message(
|
pub fn send_message(
|
||||||
&self,
|
&self,
|
||||||
request_id: RequestId,
|
request_id: RequestId,
|
||||||
target_channel_id: ComponentId,
|
target_id: ComponentId,
|
||||||
message: TO,
|
message: TO,
|
||||||
) -> Result<(), GenericTargetedMessagingError> {
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
self.message_sender_map.send_message(
|
self.message_sender_map.send_message(
|
||||||
request_id,
|
MessageMetadata::new(request_id, self.local_channel_id_generic()),
|
||||||
self.local_channel_id_generic(),
|
target_id,
|
||||||
target_channel_id,
|
|
||||||
message,
|
message,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -390,9 +387,12 @@ mod tests {
|
|||||||
ByteConversionError, SpHeader,
|
ByteConversionError, SpHeader,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError};
|
use crate::{
|
||||||
|
queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError},
|
||||||
|
request::{MessageMetadata, MessageSenderMap},
|
||||||
|
};
|
||||||
|
|
||||||
use super::{GenericMessage, MessageReceiverWithId, MessageSenderMapWithId, TargetAndApidId};
|
use super::{GenericMessage, MessageReceiverWithId, UniqueApidTargetId};
|
||||||
|
|
||||||
const TEST_CHANNEL_ID_0: u64 = 1;
|
const TEST_CHANNEL_ID_0: u64 = 1;
|
||||||
const TEST_CHANNEL_ID_1: u64 = 2;
|
const TEST_CHANNEL_ID_1: u64 = 2;
|
||||||
@ -400,15 +400,15 @@ mod tests {
|
|||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_basic_target_id_with_apid() {
|
fn test_basic_target_id_with_apid() {
|
||||||
let id = TargetAndApidId::new(0x111, 0x01);
|
let id = UniqueApidTargetId::new(0x111, 0x01);
|
||||||
assert_eq!(id.apid, 0x111);
|
assert_eq!(id.apid, 0x111);
|
||||||
assert_eq!(id.target, 0x01);
|
assert_eq!(id.unique_id, 0x01);
|
||||||
assert_eq!(id.full_target_id(), id.raw());
|
assert_eq!(id.id(), id.raw());
|
||||||
assert_eq!(u64::from(id), id.raw());
|
assert_eq!(u64::from(id), id.raw());
|
||||||
let id_raw = id.raw();
|
let id_raw = id.raw();
|
||||||
let id_from_raw = TargetAndApidId::from(id_raw);
|
let id_from_raw = UniqueApidTargetId::from(id_raw);
|
||||||
assert_eq!(id_from_raw, id);
|
assert_eq!(id_from_raw, id);
|
||||||
assert_eq!(id.full_target_id(), (0x111 << 32) | 0x01);
|
assert_eq!(id.id(), (0x111 << 32) | 0x01);
|
||||||
let string = id.to_string();
|
let string = id.to_string();
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
string,
|
string,
|
||||||
@ -421,9 +421,9 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
|
||||||
let app_data = 1_u32.to_be_bytes();
|
let app_data = 1_u32.to_be_bytes();
|
||||||
let pus_tc = PusTcCreator::new_simple(&mut sp_header, 17, 1, Some(&app_data), true);
|
let pus_tc = PusTcCreator::new_simple(&mut sp_header, 17, 1, Some(&app_data), true);
|
||||||
let id = TargetAndApidId::from_pus_tc(&pus_tc).unwrap();
|
let id = UniqueApidTargetId::from_pus_tc(&pus_tc).unwrap();
|
||||||
assert_eq!(id.apid, 0x111);
|
assert_eq!(id.apid, 0x111);
|
||||||
assert_eq!(id.target, 1);
|
assert_eq!(id.unique_id, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -431,7 +431,7 @@ mod tests {
|
|||||||
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
|
let mut sp_header = SpHeader::tc_unseg(0x111, 5, 0).unwrap();
|
||||||
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
|
||||||
let pus_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
let pus_tc = PusTcCreator::new_no_app_data(&mut sp_header, sec_header, true);
|
||||||
let error = TargetAndApidId::from_pus_tc(&pus_tc);
|
let error = UniqueApidTargetId::from_pus_tc(&pus_tc);
|
||||||
assert!(error.is_err());
|
assert!(error.is_err());
|
||||||
let error = error.unwrap_err();
|
let error = error.unwrap_err();
|
||||||
if let ByteConversionError::FromSliceTooSmall { found, expected } = error {
|
if let ByteConversionError::FromSliceTooSmall { found, expected } = error {
|
||||||
@ -449,14 +449,17 @@ mod tests {
|
|||||||
let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
|
let receiver = MessageReceiverWithId::new(TEST_CHANNEL_ID_0, receiver);
|
||||||
let request_id = 5;
|
let request_id = 5;
|
||||||
sender
|
sender
|
||||||
.send(GenericMessage::new(request_id, TEST_CHANNEL_ID_1, 5))
|
.send(GenericMessage::new(
|
||||||
|
MessageMetadata::new(request_id, TEST_CHANNEL_ID_1),
|
||||||
|
5,
|
||||||
|
))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let reply = receiver.try_recv_message().unwrap();
|
let reply = receiver.try_recv_message().unwrap();
|
||||||
assert!(reply.is_some());
|
assert!(reply.is_some());
|
||||||
assert_eq!(receiver.local_channel_id(), TEST_CHANNEL_ID_0);
|
assert_eq!(receiver.local_channel_id(), TEST_CHANNEL_ID_0);
|
||||||
let reply = reply.unwrap();
|
let reply = reply.unwrap();
|
||||||
assert_eq!(reply.request_id, request_id);
|
assert_eq!(reply.requestor_info.request_id, request_id);
|
||||||
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_1);
|
assert_eq!(reply.requestor_info.sender_id, TEST_CHANNEL_ID_1);
|
||||||
assert_eq!(reply.message, 5);
|
assert_eq!(reply.message, 5);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -490,31 +493,43 @@ mod tests {
|
|||||||
fn test_sender_map() {
|
fn test_sender_map() {
|
||||||
let (sender0, receiver0) = mpsc::channel();
|
let (sender0, receiver0) = mpsc::channel();
|
||||||
let (sender1, receiver1) = mpsc::channel();
|
let (sender1, receiver1) = mpsc::channel();
|
||||||
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
|
let mut sender_map_with_id = MessageSenderMap::default();
|
||||||
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
||||||
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_2, sender1);
|
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_2, sender1);
|
||||||
sender_map_with_id
|
sender_map_with_id
|
||||||
.send_message(1, TEST_CHANNEL_ID_1, 5)
|
.send_message(
|
||||||
|
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
|
||||||
|
TEST_CHANNEL_ID_1,
|
||||||
|
5,
|
||||||
|
)
|
||||||
.expect("sending message failed");
|
.expect("sending message failed");
|
||||||
let mut reply = receiver0.recv().expect("receiving message failed");
|
let mut reply = receiver0.recv().expect("receiving message failed");
|
||||||
assert_eq!(reply.request_id, 1);
|
assert_eq!(reply.request_id(), 1);
|
||||||
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
|
assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
|
||||||
assert_eq!(reply.message, 5);
|
assert_eq!(reply.message, 5);
|
||||||
sender_map_with_id
|
sender_map_with_id
|
||||||
.send_message(2, TEST_CHANNEL_ID_2, 10)
|
.send_message(
|
||||||
|
MessageMetadata::new(2, TEST_CHANNEL_ID_1),
|
||||||
|
TEST_CHANNEL_ID_2,
|
||||||
|
10,
|
||||||
|
)
|
||||||
.expect("sending message failed");
|
.expect("sending message failed");
|
||||||
reply = receiver1.recv().expect("receiving message failed");
|
reply = receiver1.recv().expect("receiving message failed");
|
||||||
assert_eq!(reply.request_id, 2);
|
assert_eq!(reply.request_id(), 2);
|
||||||
assert_eq!(reply.sender_id, TEST_CHANNEL_ID_0);
|
assert_eq!(reply.sender_id(), TEST_CHANNEL_ID_0);
|
||||||
assert_eq!(reply.message, 10);
|
assert_eq!(reply.message, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sender_map_target_does_not_exist() {
|
fn test_sender_map_target_does_not_exist() {
|
||||||
let (sender0, _) = mpsc::channel();
|
let (sender0, _) = mpsc::channel();
|
||||||
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
|
let mut sender_map_with_id = MessageSenderMap::default();
|
||||||
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
||||||
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_2, 5);
|
let result = sender_map_with_id.send_message(
|
||||||
|
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
|
||||||
|
TEST_CHANNEL_ID_2,
|
||||||
|
5,
|
||||||
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) =
|
if let GenericTargetedMessagingError::Send(GenericSendError::TargetDoesNotExist(target)) =
|
||||||
@ -528,12 +543,20 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_sender_map_queue_full() {
|
fn test_sender_map_queue_full() {
|
||||||
let (sender0, _receiver0) = mpsc::sync_channel(1);
|
let (sender0, _receiver0) = mpsc::sync_channel(1);
|
||||||
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
|
let mut sender_map_with_id = MessageSenderMap::default();
|
||||||
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
||||||
sender_map_with_id
|
sender_map_with_id
|
||||||
.send_message(1, TEST_CHANNEL_ID_1, 5)
|
.send_message(
|
||||||
|
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
|
||||||
|
TEST_CHANNEL_ID_1,
|
||||||
|
5,
|
||||||
|
)
|
||||||
.expect("sending message failed");
|
.expect("sending message failed");
|
||||||
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5);
|
let result = sender_map_with_id.send_message(
|
||||||
|
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
|
||||||
|
TEST_CHANNEL_ID_1,
|
||||||
|
5,
|
||||||
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error {
|
if let GenericTargetedMessagingError::Send(GenericSendError::QueueFull(capacity)) = error {
|
||||||
@ -546,10 +569,14 @@ mod tests {
|
|||||||
#[test]
|
#[test]
|
||||||
fn test_sender_map_queue_receiver_disconnected() {
|
fn test_sender_map_queue_receiver_disconnected() {
|
||||||
let (sender0, receiver0) = mpsc::sync_channel(1);
|
let (sender0, receiver0) = mpsc::sync_channel(1);
|
||||||
let mut sender_map_with_id = MessageSenderMapWithId::new(TEST_CHANNEL_ID_0);
|
let mut sender_map_with_id = MessageSenderMap::default();
|
||||||
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
sender_map_with_id.add_message_target(TEST_CHANNEL_ID_1, sender0);
|
||||||
drop(receiver0);
|
drop(receiver0);
|
||||||
let result = sender_map_with_id.send_message(1, TEST_CHANNEL_ID_1, 5);
|
let result = sender_map_with_id.send_message(
|
||||||
|
MessageMetadata::new(1, TEST_CHANNEL_ID_0),
|
||||||
|
TEST_CHANNEL_ID_1,
|
||||||
|
5,
|
||||||
|
);
|
||||||
assert!(result.is_err());
|
assert!(result.is_err());
|
||||||
let error = result.unwrap_err();
|
let error = result.unwrap_err();
|
||||||
if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error {
|
if let GenericTargetedMessagingError::Send(GenericSendError::RxDisconnected) = error {
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
//! use satrs::tmtc::{ReceivesTc, ReceivesTcCore};
|
//! use satrs::tmtc::{ReceivesTc, ReceivesTcCore};
|
||||||
//! use spacepackets::{CcsdsPacket, SpHeader};
|
//! use spacepackets::{CcsdsPacket, SpHeader};
|
||||||
//! use spacepackets::ecss::WritablePusPacket;
|
//! use spacepackets::ecss::WritablePusPacket;
|
||||||
//! use spacepackets::ecss::tc::{PusTc, PusTcCreator};
|
//! use spacepackets::ecss::tc::PusTcCreator;
|
||||||
//!
|
//!
|
||||||
//! #[derive (Default)]
|
//! #[derive (Default)]
|
||||||
//! struct ConcreteApidHandler {
|
//! struct ConcreteApidHandler {
|
||||||
@ -96,6 +96,7 @@ use std::error::Error;
|
|||||||
pub trait CcsdsPacketHandler {
|
pub trait CcsdsPacketHandler {
|
||||||
type Error;
|
type Error;
|
||||||
|
|
||||||
|
// TODO: Rework this to return a boolean based on u16 input..
|
||||||
fn valid_apids(&self) -> &'static [u16];
|
fn valid_apids(&self) -> &'static [u16];
|
||||||
fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
|
fn handle_known_apid(&mut self, sp_header: &SpHeader, tc_raw: &[u8])
|
||||||
-> Result<(), Self::Error>;
|
-> Result<(), Self::Error>;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
use spacepackets::ecss::tm::{PusTmCreator, PusTmSecondaryHeader};
|
||||||
use spacepackets::time::cds::TimeProvider;
|
use spacepackets::time::cds::CdsTime;
|
||||||
use spacepackets::time::TimeWriter;
|
use spacepackets::time::TimeWriter;
|
||||||
use spacepackets::SpHeader;
|
use spacepackets::SpHeader;
|
||||||
|
|
||||||
@ -68,7 +68,7 @@ impl PusTmWithCdsShortHelper {
|
|||||||
source_data: &'a [u8],
|
source_data: &'a [u8],
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
) -> PusTmCreator {
|
) -> PusTmCreator {
|
||||||
let time_stamp = TimeProvider::from_now_with_u16_days().unwrap();
|
let time_stamp = CdsTime::now_with_u16_days().unwrap();
|
||||||
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
time_stamp.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
||||||
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
self.create_pus_tm_common(service, subservice, source_data, seq_count)
|
||||||
}
|
}
|
||||||
@ -78,7 +78,7 @@ impl PusTmWithCdsShortHelper {
|
|||||||
service: u8,
|
service: u8,
|
||||||
subservice: u8,
|
subservice: u8,
|
||||||
source_data: &'a [u8],
|
source_data: &'a [u8],
|
||||||
stamper: &TimeProvider,
|
stamper: &CdsTime,
|
||||||
seq_count: u16,
|
seq_count: u16,
|
||||||
) -> PusTmCreator {
|
) -> PusTmCreator {
|
||||||
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
stamper.write_to_bytes(&mut self.cds_short_buf).unwrap();
|
||||||
@ -100,14 +100,14 @@ impl PusTmWithCdsShortHelper {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use spacepackets::{ecss::PusPacket, time::cds::TimeProvider, CcsdsPacket};
|
use spacepackets::{ecss::PusPacket, time::cds::CdsTime, CcsdsPacket};
|
||||||
|
|
||||||
use super::PusTmWithCdsShortHelper;
|
use super::PusTmWithCdsShortHelper;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_helper_with_stamper() {
|
fn test_helper_with_stamper() {
|
||||||
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123);
|
let mut pus_tm_helper = PusTmWithCdsShortHelper::new(0x123);
|
||||||
let stamper = TimeProvider::new_with_u16_days(0, 0);
|
let stamper = CdsTime::new_with_u16_days(0, 0);
|
||||||
let tm = pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, 25);
|
let tm = pus_tm_helper.create_pus_tm_with_stamper(17, 1, &[1, 2, 3, 4], &stamper, 25);
|
||||||
assert_eq!(tm.service(), 17);
|
assert_eq!(tm.service(), 17);
|
||||||
assert_eq!(tm.subservice(), 1);
|
assert_eq!(tm.subservice(), 1);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
use core::mem::size_of;
|
use core::mem::size_of;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use spacepackets::ecss::{PfcReal, PfcUnsigned, Ptc};
|
use spacepackets::ecss::{PfcReal, PfcUnsigned, Ptc};
|
||||||
use spacepackets::time::cds::TimeProvider;
|
use spacepackets::time::cds::CdsTime;
|
||||||
use spacepackets::time::{CcsdsTimeProvider, TimeWriter};
|
use spacepackets::time::{CcsdsTimeProvider, TimeWriter};
|
||||||
|
|
||||||
enum NumOfParamsInfo {
|
enum NumOfParamsInfo {
|
||||||
@ -36,7 +36,7 @@ struct TestMgmHkWithIndividualValidity {
|
|||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct TestMgmHkWithGroupValidity {
|
struct TestMgmHkWithGroupValidity {
|
||||||
last_valid_stamp: TimeProvider,
|
last_valid_stamp: CdsTime,
|
||||||
valid: bool,
|
valid: bool,
|
||||||
temp: f32,
|
temp: f32,
|
||||||
mgm_vals: [u16; 3],
|
mgm_vals: [u16; 3],
|
||||||
@ -150,7 +150,7 @@ pub fn main() {
|
|||||||
// The easiest and probably best approach, trading off big advantages for TM downlink capacity:
|
// The easiest and probably best approach, trading off big advantages for TM downlink capacity:
|
||||||
// Use a JSON format
|
// Use a JSON format
|
||||||
let mgm_hk_group_validity = TestMgmHkWithGroupValidity {
|
let mgm_hk_group_validity = TestMgmHkWithGroupValidity {
|
||||||
last_valid_stamp: TimeProvider::from_now_with_u16_days().unwrap(),
|
last_valid_stamp: CdsTime::now_with_u16_days().unwrap(),
|
||||||
valid: false,
|
valid: false,
|
||||||
temp: 20.0,
|
temp: 20.0,
|
||||||
mgm_vals: [0x1f1f, 0x2f2f, 0x3f3f],
|
mgm_vals: [0x1f1f, 0x2f2f, 0x3f3f],
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use std::{println, sync::mpsc};
|
use std::{println, sync::mpsc};
|
||||||
|
|
||||||
use satrs::action::ActionRequest;
|
|
||||||
use satrs::mode::{
|
use satrs::mode::{
|
||||||
ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
|
ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler,
|
||||||
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded,
|
ModeRequestHandlerMpscBounded, ModeRequestReceiver, ModeRequestorAndHandlerMpscBounded,
|
||||||
ModeRequestorBoundedMpsc,
|
ModeRequestorBoundedMpsc,
|
||||||
};
|
};
|
||||||
use satrs::request::RequestId;
|
use satrs::request::{MessageMetadata, RequestId};
|
||||||
use satrs::{
|
use satrs::{
|
||||||
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
mode::{ModeAndSubmode, ModeReply, ModeRequest},
|
||||||
queue::GenericTargetedMessagingError,
|
queue::GenericTargetedMessagingError,
|
||||||
@ -46,11 +45,30 @@ struct TestDevice {
|
|||||||
pub name: String,
|
pub name: String,
|
||||||
pub mode_node: ModeRequestHandlerMpscBounded,
|
pub mode_node: ModeRequestHandlerMpscBounded,
|
||||||
pub mode_and_submode: ModeAndSubmode,
|
pub mode_and_submode: ModeAndSubmode,
|
||||||
pub mode_requestor_info: Option<(RequestId, ComponentId)>,
|
pub mode_requestor_info: Option<MessageMetadata>,
|
||||||
// pub action_queue: mpsc::Receiver<GenericMessage<ActionRequest>>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ModeLeafDeviceHelper {}
|
fn mode_leaf_node_req_handler(
|
||||||
|
handler: &mut impl ModeRequestHandler,
|
||||||
|
request: GenericMessage<ModeRequest>,
|
||||||
|
) {
|
||||||
|
match request.message {
|
||||||
|
ModeRequest::SetMode(mode_and_submode) => {
|
||||||
|
handler
|
||||||
|
.start_transition(request.requestor_info, mode_and_submode)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
ModeRequest::ReadMode => handler
|
||||||
|
.send_mode_reply(
|
||||||
|
request.requestor_info,
|
||||||
|
ModeReply::ModeReply(handler.mode_and_submode()),
|
||||||
|
)
|
||||||
|
.unwrap(),
|
||||||
|
ModeRequest::AnnounceMode => handler.announce_mode(request.requestor_info, false),
|
||||||
|
ModeRequest::AnnounceModeRecursive => handler.announce_mode(request.requestor_info, true),
|
||||||
|
ModeRequest::ModeInfo(_) => todo!(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl TestDevice {
|
impl TestDevice {
|
||||||
pub fn run(&mut self) {
|
pub fn run(&mut self) {
|
||||||
@ -61,24 +79,22 @@ impl TestDevice {
|
|||||||
if let Some(request) = self.mode_node.try_recv_mode_request()? {
|
if let Some(request) = self.mode_node.try_recv_mode_request()? {
|
||||||
match request.message {
|
match request.message {
|
||||||
ModeRequest::SetMode(mode_and_submode) => {
|
ModeRequest::SetMode(mode_and_submode) => {
|
||||||
self.start_transition(request.request_id, request.sender_id, mode_and_submode)
|
self.start_transition(request.requestor_info, mode_and_submode)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
self.mode_requestor_info = Some((request.request_id, request.sender_id));
|
self.mode_requestor_info = Some(request.requestor_info);
|
||||||
}
|
}
|
||||||
ModeRequest::ReadMode => self
|
ModeRequest::ReadMode => self
|
||||||
.mode_node
|
.mode_node
|
||||||
.send_mode_reply(
|
.send_mode_reply(
|
||||||
request.request_id,
|
request.requestor_info,
|
||||||
request.sender_id,
|
|
||||||
ModeReply::ModeReply(self.mode_and_submode),
|
ModeReply::ModeReply(self.mode_and_submode),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ModeRequest::AnnounceMode => {
|
ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false),
|
||||||
self.announce_mode(request.request_id, request.sender_id, false)
|
|
||||||
}
|
|
||||||
ModeRequest::AnnounceModeRecursive => {
|
ModeRequest::AnnounceModeRecursive => {
|
||||||
self.announce_mode(request.request_id, request.sender_id, true)
|
self.announce_mode(request.requestor_info, true)
|
||||||
}
|
}
|
||||||
|
ModeRequest::ModeInfo(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -90,39 +106,49 @@ impl ModeProvider for TestDevice {
|
|||||||
self.mode_and_submode
|
self.mode_and_submode
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ModeRequestHandler for TestDevice {
|
impl ModeRequestHandler for TestDevice {
|
||||||
fn start_transition(
|
fn start_transition(
|
||||||
&mut self,
|
&mut self,
|
||||||
_request_id: RequestId,
|
requestor: MessageMetadata,
|
||||||
_sender_id: ComponentId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
) -> Result<(), ModeError> {
|
) -> Result<(), ModeError> {
|
||||||
self.mode_and_submode = mode_and_submode;
|
self.mode_and_submode = mode_and_submode;
|
||||||
self.handle_mode_reached()?;
|
self.handle_mode_reached(Some(requestor))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn announce_mode(&self, _request_id: RequestId, _sender_id: ComponentId, _recursive: bool) {
|
fn announce_mode(&self, requestor_info: MessageMetadata, _recursive: bool) {
|
||||||
println!(
|
println!(
|
||||||
"{}: announcing mode: {:?}",
|
"{}: announcing mode: {:?}",
|
||||||
self.name, self.mode_and_submode
|
self.name, self.mode_and_submode
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> {
|
fn handle_mode_reached(
|
||||||
let (req_id, sender_id) = self.mode_requestor_info.unwrap();
|
&mut self,
|
||||||
self.mode_node.send_mode_reply(
|
|
||||||
req_id,
|
requestor: Option<MessageMetadata>,
|
||||||
sender_id,
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
ModeReply::ModeReply(self.mode_and_submode),
|
if let Some(requestor) = requestor {
|
||||||
)?;
|
self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn send_mode_reply(
|
||||||
|
&self,
|
||||||
|
requestor_info: MessageMetadata,
|
||||||
|
reply: ModeReply,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
|
self.mode_node
|
||||||
|
.send_mode_reply(requestor_info, ModeReply::ModeReply(self.mode_and_submode))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestAssembly {
|
struct TestAssembly {
|
||||||
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
pub mode_node: ModeRequestorAndHandlerMpscBounded,
|
||||||
pub mode_requestor_info: Option<(RequestId, ComponentId)>,
|
pub mode_requestor_info: Option<MessageMetadata>,
|
||||||
pub mode_and_submode: ModeAndSubmode,
|
pub mode_and_submode: ModeAndSubmode,
|
||||||
pub target_mode_and_submode: Option<ModeAndSubmode>,
|
pub target_mode_and_submode: Option<ModeAndSubmode>,
|
||||||
}
|
}
|
||||||
@ -143,23 +169,21 @@ impl TestAssembly {
|
|||||||
if let Some(request) = self.mode_node.try_recv_mode_request()? {
|
if let Some(request) = self.mode_node.try_recv_mode_request()? {
|
||||||
match request.message {
|
match request.message {
|
||||||
ModeRequest::SetMode(mode_and_submode) => {
|
ModeRequest::SetMode(mode_and_submode) => {
|
||||||
self.start_transition(request.request_id, request.sender_id, mode_and_submode)
|
self.start_transition(request.requestor_info, mode_and_submode)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
ModeRequest::ReadMode => self
|
ModeRequest::ReadMode => self
|
||||||
.mode_node
|
.mode_node
|
||||||
.send_mode_reply(
|
.send_mode_reply(
|
||||||
request.request_id,
|
request.requestor_info,
|
||||||
request.sender_id,
|
|
||||||
ModeReply::ModeReply(self.mode_and_submode),
|
ModeReply::ModeReply(self.mode_and_submode),
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
ModeRequest::AnnounceMode => {
|
ModeRequest::AnnounceMode => self.announce_mode(request.requestor_info, false),
|
||||||
self.announce_mode(request.request_id, request.sender_id, false)
|
|
||||||
}
|
|
||||||
ModeRequest::AnnounceModeRecursive => {
|
ModeRequest::AnnounceModeRecursive => {
|
||||||
self.announce_mode(request.request_id, request.sender_id, true)
|
self.announce_mode(request.requestor_info, true)
|
||||||
}
|
}
|
||||||
|
ModeRequest::ModeInfo(_) => todo!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -168,18 +192,20 @@ impl TestAssembly {
|
|||||||
pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> {
|
pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> {
|
||||||
if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
|
if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
|
||||||
match reply_and_id.message {
|
match reply_and_id.message {
|
||||||
ModeReply::ModeInfo(_) => todo!(),
|
|
||||||
ModeReply::ModeReply(reply) => {
|
ModeReply::ModeReply(reply) => {
|
||||||
println!(
|
println!(
|
||||||
"TestAssembly: Received mode reply from {:?}, reached: {:?}",
|
"TestAssembly: Received mode reply from {:?}, reached: {:?}",
|
||||||
reply_and_id.sender_id, reply
|
reply_and_id.sender_id(),
|
||||||
|
reply
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ModeReply::CantReachMode(_) => todo!(),
|
ModeReply::CantReachMode(_) => todo!(),
|
||||||
ModeReply::WrongMode { expected, reached } => {
|
ModeReply::WrongMode { expected, reached } => {
|
||||||
println!(
|
println!(
|
||||||
"TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}",
|
"TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}",
|
||||||
reply_and_id.sender_id, reached, expected
|
reply_and_id.sender_id(),
|
||||||
|
reached,
|
||||||
|
expected
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -191,16 +217,15 @@ impl TestAssembly {
|
|||||||
impl ModeRequestHandler for TestAssembly {
|
impl ModeRequestHandler for TestAssembly {
|
||||||
fn start_transition(
|
fn start_transition(
|
||||||
&mut self,
|
&mut self,
|
||||||
request_id: RequestId,
|
requestor: MessageMetadata,
|
||||||
sender_id: ComponentId,
|
|
||||||
mode_and_submode: ModeAndSubmode,
|
mode_and_submode: ModeAndSubmode,
|
||||||
) -> Result<(), ModeError> {
|
) -> Result<(), ModeError> {
|
||||||
self.mode_requestor_info = Some((request_id, sender_id));
|
self.mode_requestor_info = Some(requestor);
|
||||||
self.target_mode_and_submode = Some(mode_and_submode);
|
self.target_mode_and_submode = Some(mode_and_submode);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn announce_mode(&self, request_id: RequestId, _sender_id: ComponentId, recursive: bool) {
|
fn announce_mode(&self, requestor_info: MessageMetadata, recursive: bool) {
|
||||||
println!(
|
println!(
|
||||||
"TestAssembly: Announcing mode (recursively: {}): {:?}",
|
"TestAssembly: Announcing mode (recursively: {}): {:?}",
|
||||||
recursive, self.mode_and_submode
|
recursive, self.mode_and_submode
|
||||||
@ -217,21 +242,33 @@ impl ModeRequestHandler for TestAssembly {
|
|||||||
.for_each(|(_, sender)| {
|
.for_each(|(_, sender)| {
|
||||||
sender
|
sender
|
||||||
.send(GenericMessage::new(
|
.send(GenericMessage::new(
|
||||||
request_id,
|
MessageMetadata::new(
|
||||||
self.mode_node.local_channel_id_generic(),
|
requestor_info.request_id(),
|
||||||
|
self.mode_node.local_channel_id_generic(),
|
||||||
|
),
|
||||||
mode_request,
|
mode_request,
|
||||||
))
|
))
|
||||||
.expect("sending mode request failed");
|
.expect("sending mode request failed");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> {
|
fn handle_mode_reached(
|
||||||
let (req_id, sender_id) = self.mode_requestor_info.unwrap();
|
&mut self,
|
||||||
self.mode_node.send_mode_reply(
|
mode_requestor: Option<MessageMetadata>,
|
||||||
req_id,
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
sender_id,
|
if let Some(requestor) = mode_requestor {
|
||||||
ModeReply::ModeReply(self.mode_and_submode),
|
self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
|
||||||
)?;
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn send_mode_reply(
|
||||||
|
&self,
|
||||||
|
requestor: MessageMetadata,
|
||||||
|
reply: ModeReply,
|
||||||
|
) -> Result<(), GenericTargetedMessagingError> {
|
||||||
|
self.mode_node
|
||||||
|
.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,8 @@ use satrs::events::{EventU32, EventU32TypedSev, Severity, SeverityInfo};
|
|||||||
use satrs::params::U32Pair;
|
use satrs::params::U32Pair;
|
||||||
use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
|
use satrs::params::{Params, ParamsHeapless, WritableToBeBytes};
|
||||||
use satrs::pus::event_man::{DefaultPusEventMgmtBackend, EventReporter, PusEventDispatcher};
|
use satrs::pus::event_man::{DefaultPusEventMgmtBackend, EventReporter, PusEventDispatcher};
|
||||||
use satrs::pus::TmAsVecSenderWithMpsc;
|
use satrs::pus::PusTmAsVec;
|
||||||
|
use satrs::request::UniqueApidTargetId;
|
||||||
use spacepackets::ecss::tm::PusTmReader;
|
use spacepackets::ecss::tm::PusTmReader;
|
||||||
use spacepackets::ecss::{PusError, PusPacket};
|
use spacepackets::ecss::{PusError, PusPacket};
|
||||||
use std::sync::mpsc::{self, SendError, TryRecvError};
|
use std::sync::mpsc::{self, SendError, TryRecvError};
|
||||||
@ -15,6 +16,8 @@ const INFO_EVENT: EventU32TypedSev<SeverityInfo> =
|
|||||||
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
|
EventU32TypedSev::<SeverityInfo>::const_new(1, 0);
|
||||||
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
const LOW_SEV_EVENT: EventU32 = EventU32::const_new(Severity::LOW, 1, 5);
|
||||||
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
const EMPTY_STAMP: [u8; 7] = [0; 7];
|
||||||
|
const TEST_APID: u16 = 0x02;
|
||||||
|
const TEST_ID: UniqueApidTargetId = UniqueApidTargetId::new(TEST_APID, 0x05);
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum CustomTmSenderError {
|
pub enum CustomTmSenderError {
|
||||||
@ -32,13 +35,12 @@ fn test_threaded_usage() {
|
|||||||
let pus_event_man_send_provider = EventU32SenderMpsc::new(1, pus_event_man_tx);
|
let pus_event_man_send_provider = EventU32SenderMpsc::new(1, pus_event_man_tx);
|
||||||
event_man.subscribe_all(pus_event_man_send_provider.target_id());
|
event_man.subscribe_all(pus_event_man_send_provider.target_id());
|
||||||
event_man.add_sender(pus_event_man_send_provider);
|
event_man.add_sender(pus_event_man_send_provider);
|
||||||
let (event_tx, event_rx) = mpsc::channel();
|
let (event_tx, event_rx) = mpsc::channel::<PusTmAsVec>();
|
||||||
let reporter = EventReporter::new(0x02, 128).expect("Creating event reporter failed");
|
let reporter =
|
||||||
let mut pus_event_man =
|
EventReporter::new(TEST_ID.raw(), 0x02, 128).expect("Creating event reporter failed");
|
||||||
PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default());
|
let pus_event_man = PusEventDispatcher::new(reporter, DefaultPusEventMgmtBackend::default());
|
||||||
// PUS + Generic event manager thread
|
// PUS + Generic event manager thread
|
||||||
let jh0 = thread::spawn(move || {
|
let jh0 = thread::spawn(move || {
|
||||||
let mut sender = TmAsVecSenderWithMpsc::new(0, "event_sender", event_tx);
|
|
||||||
let mut event_cnt = 0;
|
let mut event_cnt = 0;
|
||||||
let mut params_array: [u8; 128] = [0; 128];
|
let mut params_array: [u8; 128] = [0; 128];
|
||||||
loop {
|
loop {
|
||||||
@ -46,9 +48,9 @@ fn test_threaded_usage() {
|
|||||||
assert!(res.is_ok());
|
assert!(res.is_ok());
|
||||||
match pus_event_man_rx.try_recv() {
|
match pus_event_man_rx.try_recv() {
|
||||||
Ok((event, aux_data)) => {
|
Ok((event, aux_data)) => {
|
||||||
let mut gen_event = |aux_data| {
|
let gen_event = |aux_data| {
|
||||||
pus_event_man.generate_pus_event_tm_generic(
|
pus_event_man.generate_pus_event_tm_generic(
|
||||||
&mut sender,
|
&event_tx,
|
||||||
&EMPTY_STAMP,
|
&EMPTY_STAMP,
|
||||||
event,
|
event,
|
||||||
aux_data,
|
aux_data,
|
||||||
@ -101,8 +103,8 @@ fn test_threaded_usage() {
|
|||||||
match event_rx.try_recv() {
|
match event_rx.try_recv() {
|
||||||
// Event TM received successfully
|
// Event TM received successfully
|
||||||
Ok(event_tm) => {
|
Ok(event_tm) => {
|
||||||
let tm =
|
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
||||||
PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed");
|
.expect("Deserializing TM failed");
|
||||||
assert_eq!(tm.0.service(), 5);
|
assert_eq!(tm.0.service(), 5);
|
||||||
assert_eq!(tm.0.subservice(), 1);
|
assert_eq!(tm.0.subservice(), 1);
|
||||||
let src_data = tm.0.source_data();
|
let src_data = tm.0.source_data();
|
||||||
@ -127,8 +129,8 @@ fn test_threaded_usage() {
|
|||||||
match event_rx.try_recv() {
|
match event_rx.try_recv() {
|
||||||
// Event TM received successfully
|
// Event TM received successfully
|
||||||
Ok(event_tm) => {
|
Ok(event_tm) => {
|
||||||
let tm =
|
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
|
||||||
PusTmReader::new(event_tm.as_slice(), 7).expect("Deserializing TM failed");
|
.expect("Deserializing TM failed");
|
||||||
assert_eq!(tm.0.service(), 5);
|
assert_eq!(tm.0.service(), 5);
|
||||||
assert_eq!(tm.0.subservice(), 2);
|
assert_eq!(tm.0.subservice(), 2);
|
||||||
let src_data = tm.0.source_data();
|
let src_data = tm.0.source_data();
|
||||||
|
@ -3,10 +3,11 @@ pub mod crossbeam_test {
|
|||||||
use hashbrown::HashMap;
|
use hashbrown::HashMap;
|
||||||
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
|
use satrs::pool::{PoolProvider, PoolProviderWithGuards, StaticMemoryPool, StaticPoolConfig};
|
||||||
use satrs::pus::verification::{
|
use satrs::pus::verification::{
|
||||||
FailParams, RequestId, VerificationReporterCfg, VerificationReporterWithSender,
|
FailParams, RequestId, VerificationReporter, VerificationReporterCfg,
|
||||||
VerificationReportingProvider,
|
VerificationReportingProvider,
|
||||||
};
|
};
|
||||||
use satrs::pus::TmInSharedPoolSenderWithCrossbeam;
|
use satrs::pus::TmInSharedPoolSenderWithCrossbeam;
|
||||||
|
use satrs::request::UniqueApidTargetId;
|
||||||
use satrs::tmtc::tm_helper::SharedTmPool;
|
use satrs::tmtc::tm_helper::SharedTmPool;
|
||||||
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
|
use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader};
|
||||||
use spacepackets::ecss::tm::PusTmReader;
|
use spacepackets::ecss::tm::PusTmReader;
|
||||||
@ -17,6 +18,8 @@ pub mod crossbeam_test {
|
|||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
const TEST_APID: u16 = 0x03;
|
const TEST_APID: u16 = 0x03;
|
||||||
|
const TEST_ID: TargetAndApidId = TargetAndApidId::new(TEST_APID, 0x05);
|
||||||
|
|
||||||
const FIXED_STAMP: [u8; 7] = [0; 7];
|
const FIXED_STAMP: [u8; 7] = [0; 7];
|
||||||
const PACKETS_SENT: u8 = 8;
|
const PACKETS_SENT: u8 = 8;
|
||||||
|
|
||||||
@ -40,13 +43,9 @@ pub mod crossbeam_test {
|
|||||||
let shared_tc_pool_0 = Arc::new(RwLock::new(StaticMemoryPool::new(pool_cfg)));
|
let shared_tc_pool_0 = Arc::new(RwLock::new(StaticMemoryPool::new(pool_cfg)));
|
||||||
let shared_tc_pool_1 = shared_tc_pool_0.clone();
|
let shared_tc_pool_1 = shared_tc_pool_0.clone();
|
||||||
let (tx, rx) = crossbeam_channel::bounded(10);
|
let (tx, rx) = crossbeam_channel::bounded(10);
|
||||||
let sender = TmInSharedPoolSenderWithCrossbeam::new(
|
let sender_0 = TmInSharedPoolSenderWithCrossbeam::new(shared_tm_pool.clone(), tx.clone());
|
||||||
0,
|
let sender_1 = sender_0.clone();
|
||||||
"verif_sender",
|
let mut reporter_with_sender_0 = VerificationReporter::new(&cfg);
|
||||||
shared_tm_pool.clone(),
|
|
||||||
tx.clone(),
|
|
||||||
);
|
|
||||||
let mut reporter_with_sender_0 = VerificationReporterWithSender::new(&cfg, sender);
|
|
||||||
let mut reporter_with_sender_1 = reporter_with_sender_0.clone();
|
let mut reporter_with_sender_1 = reporter_with_sender_0.clone();
|
||||||
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
|
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
|
||||||
// tread.
|
// tread.
|
||||||
@ -93,24 +92,36 @@ pub mod crossbeam_test {
|
|||||||
|
|
||||||
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
|
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
|
||||||
let accepted_token = reporter_with_sender_0
|
let accepted_token = reporter_with_sender_0
|
||||||
.acceptance_success(token, &FIXED_STAMP)
|
.acceptance_success(TEST_ID.raw(), &sender_0, token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
|
|
||||||
// Do some start handling here
|
// Do some start handling here
|
||||||
let started_token = reporter_with_sender_0
|
let started_token = reporter_with_sender_0
|
||||||
.start_success(accepted_token, &FIXED_STAMP)
|
.start_success(TEST_ID.raw(), &sender_0, accepted_token, &FIXED_STAMP)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
// Do some step handling here
|
// Do some step handling here
|
||||||
reporter_with_sender_0
|
reporter_with_sender_0
|
||||||
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(0))
|
.step_success(
|
||||||
|
TEST_ID.raw(),
|
||||||
|
&sender_0,
|
||||||
|
&started_token,
|
||||||
|
&FIXED_STAMP,
|
||||||
|
EcssEnumU8::new(0),
|
||||||
|
)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
|
|
||||||
// Finish up
|
// Finish up
|
||||||
reporter_with_sender_0
|
reporter_with_sender_0
|
||||||
.step_success(&started_token, &FIXED_STAMP, EcssEnumU8::new(1))
|
.step_success(
|
||||||
|
TEST_ID.raw(),
|
||||||
|
&sender_0,
|
||||||
|
&started_token,
|
||||||
|
&FIXED_STAMP,
|
||||||
|
EcssEnumU8::new(1),
|
||||||
|
)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
reporter_with_sender_0
|
reporter_with_sender_0
|
||||||
.completion_success(started_token, &FIXED_STAMP)
|
.completion_success(TEST_ID.raw(), &sender_0, started_token, &FIXED_STAMP)
|
||||||
.expect("Completion success failed");
|
.expect("Completion success failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -128,15 +139,15 @@ pub mod crossbeam_test {
|
|||||||
let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
|
||||||
let token = reporter_with_sender_1.add_tc(&tc);
|
let token = reporter_with_sender_1.add_tc(&tc);
|
||||||
let accepted_token = reporter_with_sender_1
|
let accepted_token = reporter_with_sender_1
|
||||||
.acceptance_success(token, &FIXED_STAMP)
|
.acceptance_success(TEST_ID.raw(), &sender_1, token, &FIXED_STAMP)
|
||||||
.expect("Acceptance success failed");
|
.expect("Acceptance success failed");
|
||||||
let started_token = reporter_with_sender_1
|
let started_token = reporter_with_sender_1
|
||||||
.start_success(accepted_token, &FIXED_STAMP)
|
.start_success(TEST_ID.raw(), &sender_1, accepted_token, &FIXED_STAMP)
|
||||||
.expect("Start success failed");
|
.expect("Start success failed");
|
||||||
let fail_code = EcssEnumU16::new(2);
|
let fail_code = EcssEnumU16::new(2);
|
||||||
let params = FailParams::new_no_fail_data(&FIXED_STAMP, &fail_code);
|
let params = FailParams::new_no_fail_data(&FIXED_STAMP, &fail_code);
|
||||||
reporter_with_sender_1
|
reporter_with_sender_1
|
||||||
.completion_failure(started_token, params)
|
.completion_failure(TEST_ID.raw(), &sender_1, started_token, params)
|
||||||
.expect("Completion success failed");
|
.expect("Completion success failed");
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -145,14 +156,14 @@ pub mod crossbeam_test {
|
|||||||
let mut tm_buf: [u8; 1024] = [0; 1024];
|
let mut tm_buf: [u8; 1024] = [0; 1024];
|
||||||
let mut verif_map = HashMap::new();
|
let mut verif_map = HashMap::new();
|
||||||
while packet_counter < PACKETS_SENT {
|
while packet_counter < PACKETS_SENT {
|
||||||
let verif_addr = rx
|
let tm_in_pool = rx
|
||||||
.recv_timeout(Duration::from_millis(50))
|
.recv_timeout(Duration::from_millis(50))
|
||||||
.expect("Packet reception timeout");
|
.expect("Packet reception timeout");
|
||||||
let tm_len;
|
let tm_len;
|
||||||
let shared_tm_store = shared_tm_pool.clone_backing_pool();
|
let shared_tm_store = shared_tm_pool.clone_backing_pool();
|
||||||
{
|
{
|
||||||
let mut rg = shared_tm_store.write().expect("Error locking shared pool");
|
let mut rg = shared_tm_store.write().expect("Error locking shared pool");
|
||||||
let store_guard = rg.read_with_guard(verif_addr);
|
let store_guard = rg.read_with_guard(tm_in_pool.store_addr);
|
||||||
tm_len = store_guard
|
tm_len = store_guard
|
||||||
.read(&mut tm_buf)
|
.read(&mut tm_buf)
|
||||||
.expect("Error reading TM slice");
|
.expect("Error reading TM slice");
|
||||||
|
Loading…
Reference in New Issue
Block a user