From bfedd9572e4037d35e12d34af6506c9909ccb6e4 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 21 Feb 2024 15:37:08 +0100 Subject: [PATCH 01/19] as expected, this is hard --- satrs/src/lib.rs | 4 +- satrs/src/mode.rs | 37 ++++-- satrs/src/mode_tree.rs | 261 +++++++++++++++++++++++++++++++++++++++++ satrs/src/queue.rs | 3 + 4 files changed, 295 insertions(+), 10 deletions(-) create mode 100644 satrs/src/mode_tree.rs diff --git a/satrs/src/lib.rs b/satrs/src/lib.rs index c31df8d..ae9122c 100644 --- a/satrs/src/lib.rs +++ b/satrs/src/lib.rs @@ -34,6 +34,7 @@ pub mod events; #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod executable; pub mod hal; +pub mod mode_tree; pub mod objects; pub mod pool; pub mod power; @@ -51,8 +52,7 @@ pub mod params; pub use spacepackets; -/// Generic channel ID type. -pub type ChannelId = u32; +pub use queue::ChannelId; /// Generic target ID type. pub type TargetId = u64; diff --git a/satrs/src/mode.rs b/satrs/src/mode.rs index c5968b4..1346226 100644 --- a/satrs/src/mode.rs +++ b/satrs/src/mode.rs @@ -5,19 +5,22 @@ use spacepackets::ByteConversionError; use crate::TargetId; +pub type Mode = u32; +pub type Submode = u16; + #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct ModeAndSubmode { - mode: u32, - submode: u16, + mode: Mode, + submode: Submode, } impl ModeAndSubmode { - pub const fn new_mode_only(mode: u32) -> Self { + pub const fn new_mode_only(mode: Mode) -> Self { Self { mode, submode: 0 } } - pub const fn new(mode: u32, submode: u16) -> Self { + pub const fn new(mode: Mode, submode: Submode) -> Self { Self { mode, submode } } @@ -33,16 +36,20 @@ impl ModeAndSubmode { }); } Ok(Self { - mode: u32::from_be_bytes(buf[0..4].try_into().unwrap()), - submode: u16::from_be_bytes(buf[4..6].try_into().unwrap()), + mode: Mode::from_be_bytes(buf[0..size_of::()].try_into().unwrap()), + submode: Submode::from_be_bytes( + buf[size_of::()..size_of::() + size_of::()] + .try_into() + .unwrap(), + ), }) } - pub fn mode(&self) -> u32 { + pub fn mode(&self) -> Mode { self.mode } - pub fn submode(&self) -> u16 { + pub fn submode(&self) -> Submode { self.submode } } @@ -87,6 +94,20 @@ pub enum ModeRequest { AnnounceModeRecursive, } +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +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. + ModeReply(ModeAndSubmode), + CantReachMode(ModeAndSubmode), + WrongMode { + expected: ModeAndSubmode, + reached: ModeAndSubmode, + }, +} + #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TargetedModeRequest { diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs new file mode 100644 index 0000000..4eaecf6 --- /dev/null +++ b/satrs/src/mode_tree.rs @@ -0,0 +1,261 @@ +use std::sync::mpsc; + +use alloc::vec::Vec; +use hashbrown::HashMap; + +use crate::{ + mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, + queue::GenericSendError, + ChannelId, +}; + +pub struct ModeRequestWithSenderId { + pub sender_id: ChannelId, + pub request: ModeRequest, +} + +impl ModeRequestWithSenderId { + pub fn new(sender_id: ChannelId, request: ModeRequest) -> Self { + Self { sender_id, request } + } +} + +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum TableEntryType { + /// Target table containing information of the expected children modes for given mode. + Target, + /// Sequence table which contains information about how to reach a target table, including + /// the order of the sequences. + Sequence, +} + +pub struct ModeTableEntry { + /// Name of respective table entry. + pub name: &'static str, + /// Target channel ID. + pub channel_id: ChannelId, + pub mode_submode: ModeAndSubmode, + pub allowed_submode_mask: Option, + pub check_success: bool, +} + +pub struct ModeTableMapValue { + /// Name for a given mode table entry. + pub name: &'static str, + pub entries: Vec, +} + +pub type ModeTable = HashMap; + +#[derive(Debug, Clone)] +pub enum ModeMessagingError { + TargetDoesNotExist(ChannelId), + Send(GenericSendError), +} +impl From for ModeMessagingError { + fn from(value: GenericSendError) -> Self { + Self::Send(value) + } +} + +pub trait ModeReplyHandler { + fn local_channel_id(&self) -> ChannelId; + + fn send_mode_reply( + &mut self, + target_id: ChannelId, + reply: ModeReply, + ) -> Result<(), ModeMessagingError>; +} + +pub struct StandardModeReplyMap { + pub local_id: ChannelId, + pub reply_sender_map: HashMap>, +} + +impl ModeReplyHandler for StandardModeReplyMap { + fn send_mode_reply( + &mut self, + target_channel_id: ChannelId, + reply: ModeReply, + ) -> Result<(), ModeMessagingError> { + if self.reply_sender_map.contains_key(&target_channel_id) { + self.reply_sender_map + .get(&target_channel_id) + .unwrap() + .send(reply) + .map_err(|_| GenericSendError::RxDisconnected)?; + return Ok(()); + } + Err(ModeMessagingError::TargetDoesNotExist(target_channel_id)) + } + + fn local_channel_id(&self) -> ChannelId { + self.local_id + } +} + +pub trait ModeRequestSender { + fn local_channel_id(&self) -> Option; + fn send_mode_request( + &mut self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), ModeMessagingError>; +} + +pub struct StandardModeRequestMap { + pub local_channel_id: ChannelId, + pub request_sender_map: HashMap>, +} + +impl ModeRequestSender for StandardModeRequestMap { + fn send_mode_request( + &mut self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), ModeMessagingError> { + if self.request_sender_map.contains_key(&target_id) { + self.request_sender_map + .get(&target_id) + .unwrap() + .send(ModeRequestWithSenderId { + sender_id: target_id, + request, + }) + .map_err(|_| GenericSendError::RxDisconnected)?; + return Ok(()); + } + Err(ModeMessagingError::TargetDoesNotExist(target_id)) + } + + fn local_channel_id(&self) -> Option { + Some(self.local_channel_id) + } +} + +pub trait ModeProvider { + fn mode_and_submode(&self) -> ModeAndSubmode; +} + +#[derive(Debug, Clone)] +pub enum ModeError { + Messaging(ModeMessagingError), +} + +pub trait ModeRequestHandler: ModeProvider { + fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError>; + + fn announce_mode(&self, recursive: bool); + fn handle_mode_reached(&mut self) -> Result<(), ModeMessagingError>; +} + +#[cfg(test)] +mod tests { + use std::{println, sync::mpsc}; + + use crate::{ + mode::{ModeAndSubmode, ModeReply, ModeRequest}, + mode_tree::ModeRequestSender, + ChannelId, + }; + + use super::{ + ModeMessagingError, ModeProvider, ModeReplyHandler, ModeRequestHandler, + ModeRequestWithSenderId, StandardModeReplyMap, StandardModeRequestMap, + }; + + struct TestDevice { + /// One receiver handle for all mode requests. + pub mode_req_receiver: mpsc::Receiver, + /// This structure contains all handles to send mode replies. + pub mode_reply_sender: StandardModeReplyMap, + pub last_mode_sender: Option, + pub mode_and_submode: ModeAndSubmode, + pub target_mode_and_submode: Option, + } + + struct TestAssembly { + /// One receiver handle for all mode requests. + pub mode_req_receiver: mpsc::Receiver, + /// This structure contains all handles to send mode replies. + pub mode_reply_sender: StandardModeReplyMap, + /// This structure contains all handles to send mode requests to its children. + pub mode_children_map: StandardModeRequestMap, + pub last_mode_sender: Option, + pub mode_and_submode: ModeAndSubmode, + pub target_mode_and_submode: Option, + } + + impl ModeProvider for TestAssembly { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } + } + + impl TestAssembly { + pub fn check_mode_requests(&mut self) { + match self.mode_req_receiver.try_recv() { + Ok(ModeRequestWithSenderId { sender_id, request }) => { + match request { + ModeRequest::SetMode(mode_and_submode) => { + self.start_transition(mode_and_submode).unwrap(); + self.last_mode_sender = Some(sender_id); + } + ModeRequest::ReadMode => { + // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() + self.mode_reply_sender + .send_mode_reply( + sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap() + } + ModeRequest::AnnounceMode => self.announce_mode(false), + ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + } + } + Err(_) => todo!(), + }; + } + } + impl ModeRequestHandler for TestAssembly { + fn start_transition( + &mut self, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), super::ModeError> { + self.target_mode_and_submode = Some(mode_and_submode); + Ok(()) + } + + fn announce_mode(&self, recursive: bool) { + println!( + "Announcing mode (recursively: {}): {:?}", + recursive, self.mode_and_submode + ); + let mut mode_request = ModeRequest::AnnounceMode; + if recursive { + mode_request = ModeRequest::AnnounceModeRecursive; + } + self.mode_children_map + .request_sender_map + .iter() + .for_each(|(_, sender)| { + sender + .send(ModeRequestWithSenderId::new( + self.mode_children_map.local_channel_id().unwrap(), + mode_request, + )) + .expect("sending mode request failed"); + }); + } + + fn handle_mode_reached(&mut self) -> Result<(), ModeMessagingError> { + self.mode_reply_sender.send_mode_reply( + self.last_mode_sender.unwrap(), + ModeReply::ModeReply(self.mode_and_submode), + )?; + Ok(()) + } + } +} diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index 25ff6c6..2d344e0 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -2,6 +2,9 @@ use core::fmt::{Display, Formatter}; #[cfg(feature = "std")] use std::error::Error; +/// Generic channel ID type. +pub type ChannelId = u32; + /// Generic error type for sending something via a message queue. #[derive(Debug, Copy, Clone)] pub enum GenericSendError { -- 2.43.0 From 0bd492038dcb397726ead46f2baefac4c05636da Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 21 Feb 2024 17:47:15 +0100 Subject: [PATCH 02/19] lets just push through with one concrete example and work from there --- satrs/src/mode_tree.rs | 171 +++++++++++++++++++++++++++++++++++++---- satrs/src/pus/mod.rs | 14 ++-- satrs/src/queue.rs | 12 +-- 3 files changed, 171 insertions(+), 26 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 4eaecf6..8ec9910 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -5,7 +5,7 @@ use hashbrown::HashMap; use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, - queue::GenericSendError, + queue::{GenericReceiveError, GenericSendError}, ChannelId, }; @@ -51,6 +51,7 @@ pub type ModeTable = HashMap; pub enum ModeMessagingError { TargetDoesNotExist(ChannelId), Send(GenericSendError), + Receive(GenericReceiveError), } impl From for ModeMessagingError { fn from(value: GenericSendError) -> Self { @@ -58,7 +59,13 @@ impl From for ModeMessagingError { } } -pub trait ModeReplyHandler { +impl From for ModeMessagingError { + fn from(value: GenericReceiveError) -> Self { + Self::Receive(value) + } +} + +pub trait ModeReplySendProvider { fn local_channel_id(&self) -> ChannelId; fn send_mode_reply( @@ -68,12 +75,12 @@ pub trait ModeReplyHandler { ) -> Result<(), ModeMessagingError>; } -pub struct StandardModeReplyMap { +pub struct StandardModeReplySender { pub local_id: ChannelId, pub reply_sender_map: HashMap>, } -impl ModeReplyHandler for StandardModeReplyMap { +impl ModeReplySendProvider for StandardModeReplySender { fn send_mode_reply( &mut self, target_channel_id: ChannelId, @@ -95,7 +102,80 @@ impl ModeReplyHandler for StandardModeReplyMap { } } -pub trait ModeRequestSender { +impl StandardModeReplySender { + pub fn new(local_id: ChannelId) -> Self { + Self { + local_id, + reply_sender_map: HashMap::new(), + } + } + + pub fn add_reply_target( + &mut self, + target_id: ChannelId, + reply_sender: mpsc::Sender, + ) { + self.reply_sender_map.insert(target_id, reply_sender); + } +} + +pub struct ModeReplyTuple { + pub sender_id: ChannelId, + pub reply: ModeReply, +} + +pub trait ModeReplyReceiver { + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; +} + +pub struct StandardModeReplyReceiver { + pub sender_id: ChannelId, + pub receiver: mpsc::Receiver, +} + +#[derive(Default)] +pub struct StandardModeReplyReceiverList { + pub reply_receiver_vec: Vec, +} + +impl StandardModeReplyReceiverList { + pub fn add_reply_receiver( + &mut self, + sender_id: ChannelId, + receiver: mpsc::Receiver, + ) { + self.reply_receiver_vec.push(StandardModeReplyReceiver { + sender_id, + receiver, + }); + } +} + +impl ModeReplyReceiver for StandardModeReplyReceiverList { + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { + for reply_receiver in &self.reply_receiver_vec { + match reply_receiver.receiver.try_recv() { + Ok(reply) => { + return Ok(Some(ModeReplyTuple { + sender_id: reply_receiver.sender_id, + reply, + })) + } + Err(e) => { + if e == mpsc::TryRecvError::Disconnected { + return Err(GenericReceiveError::TxDisconnected(Some( + reply_receiver.sender_id, + )) + .into()); + } + } + } + } + Ok(None) + } +} + +pub trait ModeRequestSendProvider { fn local_channel_id(&self) -> Option; fn send_mode_request( &mut self, @@ -104,12 +184,12 @@ pub trait ModeRequestSender { ) -> Result<(), ModeMessagingError>; } -pub struct StandardModeRequestMap { +pub struct StandardModeRequestSender { pub local_channel_id: ChannelId, pub request_sender_map: HashMap>, } -impl ModeRequestSender for StandardModeRequestMap { +impl ModeRequestSendProvider for StandardModeRequestSender { fn send_mode_request( &mut self, target_id: ChannelId, @@ -134,6 +214,23 @@ impl ModeRequestSender for StandardModeRequestMap { } } +impl StandardModeRequestSender { + pub fn new(local_channel_id: ChannelId) -> Self { + Self { + local_channel_id, + request_sender_map: HashMap::new(), + } + } + + pub fn add_request_target( + &mut self, + target_id: ChannelId, + request_sender: mpsc::Sender, + ) { + self.request_sender_map.insert(target_id, request_sender); + } +} + pub trait ModeProvider { fn mode_and_submode(&self) -> ModeAndSubmode; } @@ -154,22 +251,25 @@ pub trait ModeRequestHandler: ModeProvider { mod tests { use std::{println, sync::mpsc}; + use hashbrown::HashMap; + use crate::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, - mode_tree::ModeRequestSender, + mode_tree::ModeRequestSendProvider, ChannelId, }; use super::{ - ModeMessagingError, ModeProvider, ModeReplyHandler, ModeRequestHandler, - ModeRequestWithSenderId, StandardModeReplyMap, StandardModeRequestMap, + ModeMessagingError, ModeProvider, ModeReplySendProvider, ModeRequestHandler, + ModeRequestWithSenderId, StandardModeReplyReceiverList, StandardModeReplySender, + StandardModeRequestSender, }; struct TestDevice { /// One receiver handle for all mode requests. pub mode_req_receiver: mpsc::Receiver, /// This structure contains all handles to send mode replies. - pub mode_reply_sender: StandardModeReplyMap, + pub mode_reply_sender: StandardModeReplySender, pub last_mode_sender: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, @@ -179,9 +279,10 @@ mod tests { /// One receiver handle for all mode requests. pub mode_req_receiver: mpsc::Receiver, /// This structure contains all handles to send mode replies. - pub mode_reply_sender: StandardModeReplyMap, + pub mode_reply_sender: StandardModeReplySender, /// This structure contains all handles to send mode requests to its children. - pub mode_children_map: StandardModeRequestMap, + pub mode_children_map: StandardModeRequestSender, + pub mode_reply_receiver_list: StandardModeReplyReceiverList, pub last_mode_sender: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, @@ -194,6 +295,10 @@ mod tests { } impl TestAssembly { + pub fn run(&mut self) { + self.check_mode_requests() + } + pub fn check_mode_requests(&mut self) { match self.mode_req_receiver.try_recv() { Ok(ModeRequestWithSenderId { sender_id, request }) => { @@ -219,6 +324,7 @@ mod tests { }; } } + impl ModeRequestHandler for TestAssembly { fn start_transition( &mut self, @@ -258,4 +364,43 @@ mod tests { Ok(()) } } + + pub enum TestChannelId { + Device1 = 1, + Device2 = 2, + Assembly = 3, + } + #[test] + fn basic_test() { + let (dev1_sender, dev1_receiver) = mpsc::channel(); + let (dev2_sender, dev2_receiver) = mpsc::channel(); + let mut mode_reply_sender_dev1 = + StandardModeReplySender::new(TestChannelId::Device1 as u32); + let mut mode_reply_sender_dev2 = + StandardModeReplySender::new(TestChannelId::Device2 as u32); + let mut mode_request_map_assy = + StandardModeRequestSender::new(TestChannelId::Assembly as u32); + let mut mode_reply_map_assy = StandardModeReplySender::new(TestChannelId::Assembly as u32); + + let (dev1_reply_sender, assy_reply_receiver_dev1) = mpsc::channel(); + let (dev2_reply_sender, assy_reply_receiver_dev2) = mpsc::channel(); + mode_reply_sender_dev1.add_reply_target(TestChannelId::Assembly as u32, dev1_reply_sender); + mode_reply_sender_dev2.add_reply_target(TestChannelId::Assembly as u32, dev2_reply_sender); + //mode_reply_map_assy.add_reply_target(target_id, reply_sender) + + let device1 = TestDevice { + mode_req_receiver: dev1_receiver, + mode_reply_sender: mode_reply_sender_dev1, + last_mode_sender: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + }; + let device2 = TestDevice { + mode_req_receiver: dev2_receiver, + mode_reply_sender: mode_reply_sender_dev2, + last_mode_sender: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + }; + } } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 91be068..0d2168c 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -2,7 +2,7 @@ //! //! This module contains structures to make working with the PUS C standard easier. //! The satrs-example application contains various usage examples of these components. -use crate::queue::{GenericRecvError, GenericSendError}; +use crate::queue::{GenericReceiveError, GenericSendError}; use crate::ChannelId; use core::fmt::{Display, Formatter}; #[cfg(feature = "alloc")] @@ -64,7 +64,7 @@ pub enum EcssTmtcError { Pus(PusError), CantSendAddr(StoreAddr), Send(GenericSendError), - Recv(GenericRecvError), + Recv(GenericReceiveError), } impl Display for EcssTmtcError { @@ -110,8 +110,8 @@ impl From for EcssTmtcError { } } -impl From for EcssTmtcError { - fn from(value: GenericRecvError) -> Self { +impl From for EcssTmtcError { + fn from(value: GenericReceiveError) -> Self { Self::Recv(value) } } @@ -367,7 +367,7 @@ pub mod std_mod { use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ EcssChannel, EcssTcAndToken, EcssTcReceiver, EcssTcReceiverCore, EcssTmSender, - EcssTmSenderCore, EcssTmtcError, GenericRecvError, GenericSendError, PusTmWrapper, + EcssTmSenderCore, EcssTmtcError, GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError, }; use crate::tmtc::tm_helper::SharedTmPool; @@ -486,7 +486,7 @@ pub mod std_mod { self.receiver.try_recv().map_err(|e| match e { TryRecvError::Empty => TryRecvTmtcError::Empty, TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) + TryRecvTmtcError::Error(EcssTmtcError::from(GenericReceiveError::TxDisconnected(Some(self.id())))) } }) } @@ -626,7 +626,7 @@ pub mod std_mod { self.receiver.try_recv().map_err(|e| match e { cb::TryRecvError::Empty => TryRecvTmtcError::Empty, cb::TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericRecvError::TxDisconnected)) + TryRecvTmtcError::Error(EcssTmtcError::from(GenericReceiveError::TxDisconnected(Some(self.id())))) } }) } diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index 2d344e0..af73890 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -30,16 +30,16 @@ impl Error for GenericSendError {} /// Generic error type for sending something via a message queue. #[derive(Debug, Copy, Clone)] -pub enum GenericRecvError { +pub enum GenericReceiveError { Empty, - TxDisconnected, + TxDisconnected(Option) } -impl Display for GenericRecvError { +impl Display for GenericReceiveError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { - Self::TxDisconnected => { - write!(f, "tx side has disconnected") + Self::TxDisconnected(channel_id) => { + write!(f, "tx side with id {channel_id:?} has disconnected") } Self::Empty => { write!(f, "nothing to receive") @@ -49,4 +49,4 @@ impl Display for GenericRecvError { } #[cfg(feature = "std")] -impl Error for GenericRecvError {} +impl Error for GenericReceiveError {} -- 2.43.0 From 28523e065f38d0248d7d1754c927336b8e10f4e8 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 21 Feb 2024 19:16:25 +0100 Subject: [PATCH 03/19] slowly starting to understand this --- satrs/src/mode_tree.rs | 330 ++++++++++++++++++++++++++++------------- satrs/src/pus/mod.rs | 12 +- satrs/src/queue.rs | 2 +- 3 files changed, 238 insertions(+), 106 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 8ec9910..8613c17 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -75,12 +75,12 @@ pub trait ModeReplySendProvider { ) -> Result<(), ModeMessagingError>; } -pub struct StandardModeReplySender { +pub struct MpscModeReplyRouter { pub local_id: ChannelId, - pub reply_sender_map: HashMap>, + pub reply_sender_map: HashMap>, } -impl ModeReplySendProvider for StandardModeReplySender { +impl ModeReplySendProvider for MpscModeReplyRouter { fn send_mode_reply( &mut self, target_channel_id: ChannelId, @@ -90,7 +90,10 @@ impl ModeReplySendProvider for StandardModeReplySender { self.reply_sender_map .get(&target_channel_id) .unwrap() - .send(reply) + .send(ModeReplyWithSenderId { + sender_id: self.local_channel_id(), + reply, + }) .map_err(|_| GenericSendError::RxDisconnected)?; return Ok(()); } @@ -102,7 +105,7 @@ impl ModeReplySendProvider for StandardModeReplySender { } } -impl StandardModeReplySender { +impl MpscModeReplyRouter { pub fn new(local_id: ChannelId) -> Self { Self { local_id, @@ -113,61 +116,99 @@ impl StandardModeReplySender { pub fn add_reply_target( &mut self, target_id: ChannelId, - reply_sender: mpsc::Sender, + reply_sender: mpsc::Sender, ) { self.reply_sender_map.insert(target_id, reply_sender); } } -pub struct ModeReplyTuple { +pub struct ModeReplyWithSenderId { pub sender_id: ChannelId, pub reply: ModeReply, } pub trait ModeReplyReceiver { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; } -pub struct StandardModeReplyReceiver { - pub sender_id: ChannelId, - pub receiver: mpsc::Receiver, +pub struct MpscModeReplyReceiver { + local_channel_id: ChannelId, + reply_receiver: mpsc::Receiver, } -#[derive(Default)] -pub struct StandardModeReplyReceiverList { - pub reply_receiver_vec: Vec, -} +impl MpscModeReplyReceiver { + pub fn new( + local_channel_id: ChannelId, + reply_receiver: mpsc::Receiver, + ) -> Self { + Self { + local_channel_id, + reply_receiver, + } + } -impl StandardModeReplyReceiverList { - pub fn add_reply_receiver( - &mut self, - sender_id: ChannelId, - receiver: mpsc::Receiver, - ) { - self.reply_receiver_vec.push(StandardModeReplyReceiver { - sender_id, - receiver, - }); + pub fn local_channel_id(&self) -> ChannelId { + self.local_channel_id } } -impl ModeReplyReceiver for StandardModeReplyReceiverList { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { - for reply_receiver in &self.reply_receiver_vec { - match reply_receiver.receiver.try_recv() { - Ok(reply) => { - return Ok(Some(ModeReplyTuple { - sender_id: reply_receiver.sender_id, - reply, - })) +impl ModeReplyReceiver for MpscModeReplyReceiver { + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { + match self.reply_receiver.try_recv() { + Ok(reply) => { + return Ok(Some(reply)); + } + Err(e) => { + if e == mpsc::TryRecvError::Disconnected { + return Err( + GenericReceiveError::TxDisconnected(Some(self.local_channel_id())).into(), + ); } - Err(e) => { - if e == mpsc::TryRecvError::Disconnected { - return Err(GenericReceiveError::TxDisconnected(Some( - reply_receiver.sender_id, - )) - .into()); - } + } + } + Ok(None) + } +} + +pub trait ModeRequestReceiver { + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; +} + +pub struct MpscModeRequestReceiver { + local_channel_id: ChannelId, + receiver: mpsc::Receiver, +} + +impl MpscModeRequestReceiver { + pub fn new( + local_channel_id: ChannelId, + receiver: mpsc::Receiver, + ) -> Self { + Self { + local_channel_id, + receiver, + } + } + + pub fn local_channel_id(&self) -> ChannelId { + self.local_channel_id + } +} + +impl ModeRequestReceiver for MpscModeRequestReceiver { + fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { + match self.receiver.try_recv() { + Ok(request_and_sender) => { + return Ok(Some(ModeRequestWithSenderId { + sender_id: request_and_sender.sender_id, + request: request_and_sender.request, + })) + } + Err(e) => { + if e == mpsc::TryRecvError::Disconnected { + return Err( + GenericReceiveError::TxDisconnected(Some(self.local_channel_id)).into(), + ); } } } @@ -178,20 +219,20 @@ impl ModeReplyReceiver for StandardModeReplyReceiverList { pub trait ModeRequestSendProvider { fn local_channel_id(&self) -> Option; fn send_mode_request( - &mut self, + &self, target_id: ChannelId, request: ModeRequest, ) -> Result<(), ModeMessagingError>; } -pub struct StandardModeRequestSender { +pub struct MpscModeRequestRouter { pub local_channel_id: ChannelId, pub request_sender_map: HashMap>, } -impl ModeRequestSendProvider for StandardModeRequestSender { +impl ModeRequestSendProvider for MpscModeRequestRouter { fn send_mode_request( - &mut self, + &self, target_id: ChannelId, request: ModeRequest, ) -> Result<(), ModeMessagingError> { @@ -199,10 +240,10 @@ impl ModeRequestSendProvider for StandardModeRequestSender { self.request_sender_map .get(&target_id) .unwrap() - .send(ModeRequestWithSenderId { - sender_id: target_id, + .send(ModeRequestWithSenderId::new( + self.local_channel_id().unwrap(), request, - }) + )) .map_err(|_| GenericSendError::RxDisconnected)?; return Ok(()); } @@ -214,7 +255,7 @@ impl ModeRequestSendProvider for StandardModeRequestSender { } } -impl StandardModeRequestSender { +impl MpscModeRequestRouter { pub fn new(local_channel_id: ChannelId) -> Self { Self { local_channel_id, @@ -251,38 +292,59 @@ pub trait ModeRequestHandler: ModeProvider { mod tests { use std::{println, sync::mpsc}; - use hashbrown::HashMap; - + use super::*; use crate::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, mode_tree::ModeRequestSendProvider, ChannelId, }; - use super::{ - ModeMessagingError, ModeProvider, ModeReplySendProvider, ModeRequestHandler, - ModeRequestWithSenderId, StandardModeReplyReceiverList, StandardModeReplySender, - StandardModeRequestSender, - }; + pub enum TestChannelId { + Device1 = 1, + Device2 = 2, + Assembly = 3, + PusModeService = 4, + } + + struct PusModeService { + // This contains ALL objects which are able to process mode requests. + pub mode_request_recipients: MpscModeRequestRouter, + // This contains all reply receivers for request recipients. + pub mode_reply_receiver_list: MpscModeReplyReceiver, + } + + impl PusModeService { + pub fn send_announce_mode_cmd_to_assy(&self) { + self.mode_request_recipients + .send_mode_request( + TestChannelId::Assembly as u32, + ModeRequest::AnnounceModeRecursive, + ) + .unwrap(); + } + } struct TestDevice { - /// One receiver handle for all mode requests. - pub mode_req_receiver: mpsc::Receiver, - /// This structure contains all handles to send mode replies. - pub mode_reply_sender: StandardModeReplySender, - pub last_mode_sender: Option, + // This object is used to receive all mode requests, for example by the PUS Mode service + // or by the parent assembly. + pub mode_request_receiver: MpscModeRequestReceiver, + // This structure contains all handles to send mode replies back to the senders. + pub mode_reply_router: MpscModeReplyRouter, + // Used to cache the receiver for mode replies. + pub mode_reply_receiver: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, } struct TestAssembly { - /// One receiver handle for all mode requests. - pub mode_req_receiver: mpsc::Receiver, - /// This structure contains all handles to send mode replies. - pub mode_reply_sender: StandardModeReplySender, - /// This structure contains all handles to send mode requests to its children. - pub mode_children_map: StandardModeRequestSender, - pub mode_reply_receiver_list: StandardModeReplyReceiverList, + // This object is used to receive all mode requests, for example by the PUS Mode service + // or by the parent subsystem. + pub mode_request_receiver: MpscModeRequestReceiver, + pub mode_reply_receiver: MpscModeReplyReceiver, + // This structure contains all handles to send mode replies. + pub mode_reply_senders: MpscModeReplyRouter, + // This structure contains all handles to send mode requests to its children. + pub mode_request_senders: MpscModeRequestRouter, pub last_mode_sender: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, @@ -296,11 +358,18 @@ mod tests { impl TestAssembly { pub fn run(&mut self) { - self.check_mode_requests() + // self.check_mode_requests() } - pub fn check_mode_requests(&mut self) { - match self.mode_req_receiver.try_recv() { + /* + pub fn check_mode_requests(&mut self) -> Result<(), ModeMessagingError> { + match self.mode_request_receiver_list.try_recv_mode_reply()? { + Some(request_and_id) => { + match request_and_id { + + } + + } Ok(ModeRequestWithSenderId { sender_id, request }) => { match request { ModeRequest::SetMode(mode_and_submode) => { @@ -322,7 +391,7 @@ mod tests { } Err(_) => todo!(), }; - } + } */ } impl ModeRequestHandler for TestAssembly { @@ -343,13 +412,13 @@ mod tests { if recursive { mode_request = ModeRequest::AnnounceModeRecursive; } - self.mode_children_map + self.mode_request_senders .request_sender_map .iter() .for_each(|(_, sender)| { sender .send(ModeRequestWithSenderId::new( - self.mode_children_map.local_channel_id().unwrap(), + self.mode_request_senders.local_channel_id().unwrap(), mode_request, )) .expect("sending mode request failed"); @@ -357,7 +426,7 @@ mod tests { } fn handle_mode_reached(&mut self) -> Result<(), ModeMessagingError> { - self.mode_reply_sender.send_mode_reply( + self.mode_reply_senders.send_mode_reply( self.last_mode_sender.unwrap(), ModeReply::ModeReply(self.mode_and_submode), )?; @@ -365,42 +434,105 @@ mod tests { } } - pub enum TestChannelId { - Device1 = 1, - Device2 = 2, - Assembly = 3, - } #[test] fn basic_test() { - let (dev1_sender, dev1_receiver) = mpsc::channel(); - let (dev2_sender, dev2_receiver) = mpsc::channel(); - let mut mode_reply_sender_dev1 = - StandardModeReplySender::new(TestChannelId::Device1 as u32); - let mut mode_reply_sender_dev2 = - StandardModeReplySender::new(TestChannelId::Device2 as u32); - let mut mode_request_map_assy = - StandardModeRequestSender::new(TestChannelId::Assembly as u32); - let mut mode_reply_map_assy = StandardModeReplySender::new(TestChannelId::Assembly as u32); + // All request channel handles. + let (request_sender_to_dev1, request_receiver_dev1) = mpsc::channel(); + let (request_sender_to_dev2, request_receiver_dev2) = mpsc::channel(); + let (request_sender_to_assy, request_receiver_assy) = mpsc::channel(); - let (dev1_reply_sender, assy_reply_receiver_dev1) = mpsc::channel(); - let (dev2_reply_sender, assy_reply_receiver_dev2) = mpsc::channel(); - mode_reply_sender_dev1.add_reply_target(TestChannelId::Assembly as u32, dev1_reply_sender); - mode_reply_sender_dev2.add_reply_target(TestChannelId::Assembly as u32, dev2_reply_sender); - //mode_reply_map_assy.add_reply_target(target_id, reply_sender) + // All reply channel handles. + let (reply_sender_to_assy, reply_receiver_assy) = mpsc::channel(); + let (reply_sender_to_pus, reply_receiver_pus) = mpsc::channel(); + + // All request routers. + let mut mode_request_router_assy = + MpscModeRequestRouter::new(TestChannelId::Assembly as u32); + let mut mode_request_router_pus_mode = + MpscModeRequestRouter::new(TestChannelId::PusModeService as u32); + + // All request receivers. + let mode_request_receiver_dev1 = + MpscModeRequestReceiver::new(TestChannelId::Device1 as u32, request_receiver_dev1); + let mode_request_receiver_dev2 = + MpscModeRequestReceiver::new(TestChannelId::Device2 as u32, request_receiver_dev2); + let mode_request_receiver_assy = + MpscModeRequestReceiver::new(TestChannelId::Assembly as u32, request_receiver_assy); + + // All reply senders. + let mut mode_reply_senders_dev1 = MpscModeReplyRouter::new(TestChannelId::Device1 as u32); + let mut mode_reply_senders_dev2 = MpscModeReplyRouter::new(TestChannelId::Device2 as u32); + let mut mode_reply_senders_assy = MpscModeReplyRouter::new(TestChannelId::Assembly as u32); + + // All reply receivers. + let mode_reply_receiver_list_assy = + MpscModeReplyReceiver::new(TestChannelId::Assembly as u32, reply_receiver_assy); + let mode_reply_receiver_pus_service = + MpscModeReplyReceiver::new(TestChannelId::PusModeService as u32, reply_receiver_pus); + + // Set up mode request senders first. + mode_request_router_pus_mode + .add_request_target(TestChannelId::Assembly as u32, request_sender_to_assy); + mode_request_router_pus_mode.add_request_target( + TestChannelId::Device1 as u32, + request_sender_to_dev1.clone(), + ); + mode_request_router_pus_mode.add_request_target( + TestChannelId::Device2 as u32, + request_sender_to_dev2.clone(), + ); + mode_request_router_assy + .add_request_target(TestChannelId::Device1 as u32, request_sender_to_dev1); + mode_request_router_assy + .add_request_target(TestChannelId::Device2 as u32, request_sender_to_dev2); + + // Set up mode reply senders. + mode_reply_senders_dev1 + .add_reply_target(TestChannelId::Assembly as u32, reply_sender_to_assy.clone()); + mode_reply_senders_dev1.add_reply_target( + TestChannelId::PusModeService as u32, + reply_sender_to_pus.clone(), + ); + mode_reply_senders_dev2 + .add_reply_target(TestChannelId::Assembly as u32, reply_sender_to_assy); + mode_reply_senders_dev2.add_reply_target( + TestChannelId::PusModeService as u32, + reply_sender_to_pus.clone(), + ); + mode_reply_senders_assy + .add_reply_target(TestChannelId::PusModeService as u32, reply_sender_to_pus); let device1 = TestDevice { - mode_req_receiver: dev1_receiver, - mode_reply_sender: mode_reply_sender_dev1, - last_mode_sender: None, + mode_request_receiver: mode_request_receiver_dev1, + mode_reply_router: mode_reply_senders_dev1, + mode_reply_receiver: None, mode_and_submode: ModeAndSubmode::new(0, 0), target_mode_and_submode: None, }; let device2 = TestDevice { - mode_req_receiver: dev2_receiver, - mode_reply_sender: mode_reply_sender_dev2, + mode_request_receiver: mode_request_receiver_dev2, + mode_reply_router: mode_reply_senders_dev2, + mode_reply_receiver: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + }; + let assy = TestAssembly { + mode_request_receiver: mode_request_receiver_assy, + mode_reply_senders: mode_reply_senders_assy, + mode_request_senders: mode_request_router_assy, + mode_reply_receiver: mode_reply_receiver_list_assy, last_mode_sender: None, mode_and_submode: ModeAndSubmode::new(0, 0), target_mode_and_submode: None, }; + let pus_service = PusModeService { + mode_request_recipients: mode_request_router_pus_mode, + mode_reply_receiver_list: mode_reply_receiver_pus_service, + }; + + pus_service.send_announce_mode_cmd_to_assy(); + // assy.run(); + // device1.run(); + // device2.run(); } } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 0d2168c..a4ef6a5 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -485,9 +485,9 @@ pub mod std_mod { fn recv_tc(&self) -> Result { self.receiver.try_recv().map_err(|e| match e { TryRecvError::Empty => TryRecvTmtcError::Empty, - TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericReceiveError::TxDisconnected(Some(self.id())))) - } + TryRecvError::Disconnected => TryRecvTmtcError::Error(EcssTmtcError::from( + GenericReceiveError::TxDisconnected(Some(self.id())), + )), }) } } @@ -625,9 +625,9 @@ pub mod std_mod { fn recv_tc(&self) -> Result { self.receiver.try_recv().map_err(|e| match e { cb::TryRecvError::Empty => TryRecvTmtcError::Empty, - cb::TryRecvError::Disconnected => { - TryRecvTmtcError::Error(EcssTmtcError::from(GenericReceiveError::TxDisconnected(Some(self.id())))) - } + cb::TryRecvError::Disconnected => TryRecvTmtcError::Error(EcssTmtcError::from( + GenericReceiveError::TxDisconnected(Some(self.id())), + )), }) } } diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index af73890..dd2e3cd 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -32,7 +32,7 @@ impl Error for GenericSendError {} #[derive(Debug, Copy, Clone)] pub enum GenericReceiveError { Empty, - TxDisconnected(Option) + TxDisconnected(Option), } impl Display for GenericReceiveError { -- 2.43.0 From 69b441cd396b50d302b8c663fb9270185a2f2592 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 15:36:55 +0100 Subject: [PATCH 04/19] introducing more generics --- satrs/src/mode_tree.rs | 720 ++++++++++++++++++++++------------------- satrs/src/queue.rs | 18 ++ satrs/src/request.rs | 246 +++++++++++++- 3 files changed, 648 insertions(+), 336 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 8613c17..80d8b2c 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -5,21 +5,14 @@ use hashbrown::HashMap; use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, - queue::{GenericReceiveError, GenericSendError}, + queue::GenericTargetedMessagingError, + request::{ + MessageWithSenderId, MpscMessageReceiverWithIds, MpscMessageSenderAndReceiver, + MpscMessageSenderMap, MpscMessageSenderWithId, MpscRequestAndReplySenderAndReceiver, + }, ChannelId, }; -pub struct ModeRequestWithSenderId { - pub sender_id: ChannelId, - pub request: ModeRequest, -} - -impl ModeRequestWithSenderId { - pub fn new(sender_id: ChannelId, request: ModeRequest) -> Self { - Self { sender_id, request } - } -} - #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum TableEntryType { /// Target table containing information of the expected children modes for given mode. @@ -47,228 +40,236 @@ pub struct ModeTableMapValue { pub type ModeTable = HashMap; -#[derive(Debug, Clone)] -pub enum ModeMessagingError { - TargetDoesNotExist(ChannelId), - Send(GenericSendError), - Receive(GenericReceiveError), -} -impl From for ModeMessagingError { - fn from(value: GenericSendError) -> Self { - Self::Send(value) - } +pub trait ModeRequestSender { + fn local_channel_id(&self) -> ChannelId; + fn send_mode_request( + &self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError>; } -impl From for ModeMessagingError { - fn from(value: GenericReceiveError) -> Self { - Self::Receive(value) - } -} - -pub trait ModeReplySendProvider { +pub trait ModeReplySender { fn local_channel_id(&self) -> ChannelId; fn send_mode_reply( - &mut self, + &self, target_id: ChannelId, reply: ModeReply, - ) -> Result<(), ModeMessagingError>; -} - -pub struct MpscModeReplyRouter { - pub local_id: ChannelId, - pub reply_sender_map: HashMap>, -} - -impl ModeReplySendProvider for MpscModeReplyRouter { - fn send_mode_reply( - &mut self, - target_channel_id: ChannelId, - reply: ModeReply, - ) -> Result<(), ModeMessagingError> { - if self.reply_sender_map.contains_key(&target_channel_id) { - self.reply_sender_map - .get(&target_channel_id) - .unwrap() - .send(ModeReplyWithSenderId { - sender_id: self.local_channel_id(), - reply, - }) - .map_err(|_| GenericSendError::RxDisconnected)?; - return Ok(()); - } - Err(ModeMessagingError::TargetDoesNotExist(target_channel_id)) - } - - fn local_channel_id(&self) -> ChannelId { - self.local_id - } -} - -impl MpscModeReplyRouter { - pub fn new(local_id: ChannelId) -> Self { - Self { - local_id, - reply_sender_map: HashMap::new(), - } - } - - pub fn add_reply_target( - &mut self, - target_id: ChannelId, - reply_sender: mpsc::Sender, - ) { - self.reply_sender_map.insert(target_id, reply_sender); - } -} - -pub struct ModeReplyWithSenderId { - pub sender_id: ChannelId, - pub reply: ModeReply, -} - -pub trait ModeReplyReceiver { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; -} - -pub struct MpscModeReplyReceiver { - local_channel_id: ChannelId, - reply_receiver: mpsc::Receiver, -} - -impl MpscModeReplyReceiver { - pub fn new( - local_channel_id: ChannelId, - reply_receiver: mpsc::Receiver, - ) -> Self { - Self { - local_channel_id, - reply_receiver, - } - } - - pub fn local_channel_id(&self) -> ChannelId { - self.local_channel_id - } -} - -impl ModeReplyReceiver for MpscModeReplyReceiver { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { - match self.reply_receiver.try_recv() { - Ok(reply) => { - return Ok(Some(reply)); - } - Err(e) => { - if e == mpsc::TryRecvError::Disconnected { - return Err( - GenericReceiveError::TxDisconnected(Some(self.local_channel_id())).into(), - ); - } - } - } - Ok(None) - } + ) -> Result<(), GenericTargetedMessagingError>; } pub trait ModeRequestReceiver { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError>; -} - -pub struct MpscModeRequestReceiver { - local_channel_id: ChannelId, - receiver: mpsc::Receiver, -} - -impl MpscModeRequestReceiver { - pub fn new( - local_channel_id: ChannelId, - receiver: mpsc::Receiver, - ) -> Self { - Self { - local_channel_id, - receiver, - } - } - - pub fn local_channel_id(&self) -> ChannelId { - self.local_channel_id - } -} - -impl ModeRequestReceiver for MpscModeRequestReceiver { - fn try_recv_mode_reply(&self) -> Result, ModeMessagingError> { - match self.receiver.try_recv() { - Ok(request_and_sender) => { - return Ok(Some(ModeRequestWithSenderId { - sender_id: request_and_sender.sender_id, - request: request_and_sender.request, - })) - } - Err(e) => { - if e == mpsc::TryRecvError::Disconnected { - return Err( - GenericReceiveError::TxDisconnected(Some(self.local_channel_id)).into(), - ); - } - } - } - Ok(None) - } -} - -pub trait ModeRequestSendProvider { - fn local_channel_id(&self) -> Option; - fn send_mode_request( + fn try_recv_mode_request( &self, + ) -> Result>, GenericTargetedMessagingError>; +} + +pub trait ModeReplyReceiver { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError>; +} + +impl MpscMessageSenderMap { + pub fn send_mode_request( + &self, + local_id: ChannelId, target_id: ChannelId, request: ModeRequest, - ) -> Result<(), ModeMessagingError>; -} - -pub struct MpscModeRequestRouter { - pub local_channel_id: ChannelId, - pub request_sender_map: HashMap>, -} - -impl ModeRequestSendProvider for MpscModeRequestRouter { - fn send_mode_request( - &self, - target_id: ChannelId, - request: ModeRequest, - ) -> Result<(), ModeMessagingError> { - if self.request_sender_map.contains_key(&target_id) { - self.request_sender_map - .get(&target_id) - .unwrap() - .send(ModeRequestWithSenderId::new( - self.local_channel_id().unwrap(), - request, - )) - .map_err(|_| GenericSendError::RxDisconnected)?; - return Ok(()); - } - Err(ModeMessagingError::TargetDoesNotExist(target_id)) - } - - fn local_channel_id(&self) -> Option { - Some(self.local_channel_id) - } -} - -impl MpscModeRequestRouter { - pub fn new(local_channel_id: ChannelId) -> Self { - Self { - local_channel_id, - request_sender_map: HashMap::new(), - } + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(local_id, target_id, request) } pub fn add_request_target( &mut self, target_id: ChannelId, - request_sender: mpsc::Sender, + request_sender: mpsc::Sender>, ) { - self.request_sender_map.insert(target_id, request_sender); + self.add_message_target(target_id, request_sender) + } +} + +impl MpscMessageSenderMap { + pub fn send_mode_reply( + &self, + local_id: ChannelId, + target_id: ChannelId, + request: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(local_id, target_id, request) + } + + pub fn add_reply_target( + &mut self, + target_id: ChannelId, + request_sender: mpsc::Sender>, + ) { + self.add_message_target(target_id, request_sender) + } +} + +impl ModeReplySender for MpscMessageSenderWithId { + fn send_mode_reply( + &self, + target_channel_id: ChannelId, + reply: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(target_channel_id, reply) + } + + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id + } +} + +impl ModeRequestSender for MpscMessageSenderWithId { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id + } + + fn send_mode_request( + &self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.send_message(target_id, request) + } +} + +impl ModeReplyReceiver for MpscMessageReceiverWithIds { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.try_recv_message() + } +} +impl ModeRequestReceiver for MpscMessageReceiverWithIds { + fn try_recv_mode_request( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.try_recv_message() + } +} + +impl ModeRequestSender for MpscMessageSenderAndReceiver { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_request( + &self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.message_sender_map + .send_mode_request(self.local_channel_id(), target_id, request) + } +} + +impl ModeReplySender for MpscMessageSenderAndReceiver { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_reply( + &self, + target_id: ChannelId, + request: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.message_sender_map + .send_mode_reply(self.local_channel_id(), target_id, request) + } +} + +impl ModeReplyReceiver for MpscMessageSenderAndReceiver { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.message_receiver + .try_recv_message(self.local_channel_id_generic()) + } +} +impl ModeRequestReceiver for MpscMessageSenderAndReceiver { + fn try_recv_mode_request( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.message_receiver + .try_recv_message(self.local_channel_id_generic()) + } +} + +pub type MpscModeRequestHandlerConnector = MpscMessageSenderAndReceiver; +pub type MpscModeRequestorConnector = MpscMessageSenderAndReceiver; +pub type MpscModeConnector = MpscRequestAndReplySenderAndReceiver; + +impl MpscRequestAndReplySenderAndReceiver { + pub fn add_request_target( + &mut self, + target_id: ChannelId, + request_sender: mpsc::Sender>, + ) { + self.request_sender_map + .add_message_target(target_id, request_sender) + } +} + +impl MpscRequestAndReplySenderAndReceiver { + pub fn add_reply_target( + &mut self, + target_id: ChannelId, + reply_sender: mpsc::Sender>, + ) { + self.reply_sender_map + .add_message_target(target_id, reply_sender) + } +} + +impl ModeRequestSender for MpscRequestAndReplySenderAndReceiver { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_request( + &self, + target_id: ChannelId, + request: ModeRequest, + ) -> Result<(), GenericTargetedMessagingError> { + self.request_sender_map + .send_mode_request(self.local_channel_id(), target_id, request) + } +} + +impl ModeReplySender for MpscRequestAndReplySenderAndReceiver { + fn local_channel_id(&self) -> ChannelId { + self.local_channel_id_generic() + } + + fn send_mode_reply( + &self, + target_id: ChannelId, + request: ModeReply, + ) -> Result<(), GenericTargetedMessagingError> { + self.reply_sender_map + .send_mode_reply(self.local_channel_id(), target_id, request) + } +} + +impl ModeReplyReceiver for MpscRequestAndReplySenderAndReceiver { + fn try_recv_mode_reply( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.reply_receiver + .try_recv_message(self.local_channel_id_generic()) + } +} + +impl ModeRequestReceiver for MpscRequestAndReplySenderAndReceiver { + fn try_recv_mode_request( + &self, + ) -> Result>, GenericTargetedMessagingError> { + self.request_receiver + .try_recv_message(self.local_channel_id_generic()) } } @@ -278,24 +279,32 @@ pub trait ModeProvider { #[derive(Debug, Clone)] pub enum ModeError { - Messaging(ModeMessagingError), + Messaging(GenericTargetedMessagingError), +} + +impl From for ModeError { + fn from(value: GenericTargetedMessagingError) -> Self { + Self::Messaging(value) + } } pub trait ModeRequestHandler: ModeProvider { fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError>; fn announce_mode(&self, recursive: bool); - fn handle_mode_reached(&mut self) -> Result<(), ModeMessagingError>; + fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>; } #[cfg(test)] mod tests { use std::{println, sync::mpsc}; + use alloc::string::{String, ToString}; + use super::*; use crate::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, - mode_tree::ModeRequestSendProvider, + mode_tree::ModeRequestSender, ChannelId, }; @@ -307,15 +316,12 @@ mod tests { } struct PusModeService { - // This contains ALL objects which are able to process mode requests. - pub mode_request_recipients: MpscModeRequestRouter, - // This contains all reply receivers for request recipients. - pub mode_reply_receiver_list: MpscModeReplyReceiver, + pub mode_node: MpscModeRequestorConnector, } impl PusModeService { pub fn send_announce_mode_cmd_to_assy(&self) { - self.mode_request_recipients + self.mode_node .send_mode_request( TestChannelId::Assembly as u32, ModeRequest::AnnounceModeRecursive, @@ -325,27 +331,70 @@ mod tests { } struct TestDevice { - // This object is used to receive all mode requests, for example by the PUS Mode service - // or by the parent assembly. - pub mode_request_receiver: MpscModeRequestReceiver, - // This structure contains all handles to send mode replies back to the senders. - pub mode_reply_router: MpscModeReplyRouter, - // Used to cache the receiver for mode replies. - pub mode_reply_receiver: Option, + pub name: String, + pub mode_node: MpscModeRequestHandlerConnector, pub mode_and_submode: ModeAndSubmode, - pub target_mode_and_submode: Option, + pub mode_req_commander: Option, + } + + impl TestDevice { + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { + match request_and_id.message { + ModeRequest::SetMode(mode_and_submode) => { + self.start_transition(mode_and_submode).unwrap(); + self.mode_req_commander = Some(request_and_id.sender_id); + } + ModeRequest::ReadMode => self + .mode_node + .send_mode_reply( + request_and_id.sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap(), + ModeRequest::AnnounceMode => self.announce_mode(false), + ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + } + } + Ok(()) + } + } + + impl ModeProvider for TestDevice { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } + } + impl ModeRequestHandler for TestDevice { + fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { + self.mode_and_submode = mode_and_submode; + self.handle_mode_reached()?; + Ok(()) + } + + fn announce_mode(&self, _recursive: bool) { + println!( + "{}: announcing mode: {:?}", + self.name, self.mode_and_submode + ); + } + + fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + self.mode_node.send_mode_reply( + self.mode_req_commander.unwrap(), + ModeReply::ModeReply(self.mode_and_submode), + )?; + Ok(()) + } } struct TestAssembly { - // This object is used to receive all mode requests, for example by the PUS Mode service - // or by the parent subsystem. - pub mode_request_receiver: MpscModeRequestReceiver, - pub mode_reply_receiver: MpscModeReplyReceiver, - // This structure contains all handles to send mode replies. - pub mode_reply_senders: MpscModeReplyRouter, - // This structure contains all handles to send mode requests to its children. - pub mode_request_senders: MpscModeRequestRouter, - pub last_mode_sender: Option, + pub mode_node: MpscModeConnector, + pub mode_req_commander: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, } @@ -358,40 +407,53 @@ mod tests { impl TestAssembly { pub fn run(&mut self) { - // self.check_mode_requests() + self.check_mode_requests().expect("mode messaging error"); + self.check_mode_replies().expect("mode messaging error"); } - /* - pub fn check_mode_requests(&mut self) -> Result<(), ModeMessagingError> { - match self.mode_request_receiver_list.try_recv_mode_reply()? { - Some(request_and_id) => { - match request_and_id { - + pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { + match request_and_id.message { + ModeRequest::SetMode(mode_and_submode) => { + self.start_transition(mode_and_submode).unwrap(); + self.mode_req_commander = Some(request_and_id.sender_id); } - + ModeRequest::ReadMode => { + // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() + self.mode_node + .send_mode_reply( + request_and_id.sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap() + } + ModeRequest::AnnounceMode => self.announce_mode(false), + ModeRequest::AnnounceModeRecursive => self.announce_mode(true), } - Ok(ModeRequestWithSenderId { sender_id, request }) => { - match request { - ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(mode_and_submode).unwrap(); - self.last_mode_sender = Some(sender_id); - } - ModeRequest::ReadMode => { - // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() - self.mode_reply_sender - .send_mode_reply( - sender_id, - ModeReply::ModeReply(self.mode_and_submode), - ) - .unwrap() - } - ModeRequest::AnnounceMode => self.announce_mode(false), - ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + } + Ok(()) + } + pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { + match reply_and_id.message { + ModeReply::ModeInfo(_) => todo!(), + ModeReply::ModeReply(reply) => { + println!( + "TestAssembly: Received mode reply from {:?}, reached: {:?}", + reply_and_id.sender_id, reply + ); + } + ModeReply::CantReachMode(_) => todo!(), + ModeReply::WrongMode { expected, reached } => { + println!( + "TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}", + reply_and_id.sender_id, reached, expected + ); } } - Err(_) => todo!(), - }; - } */ + } + Ok(()) + } } impl ModeRequestHandler for TestAssembly { @@ -405,29 +467,30 @@ mod tests { fn announce_mode(&self, recursive: bool) { println!( - "Announcing mode (recursively: {}): {:?}", + "TestAssembly: Announcing mode (recursively: {}): {:?}", recursive, self.mode_and_submode ); let mut mode_request = ModeRequest::AnnounceMode; if recursive { mode_request = ModeRequest::AnnounceModeRecursive; } - self.mode_request_senders + self.mode_node .request_sender_map + .0 .iter() .for_each(|(_, sender)| { sender - .send(ModeRequestWithSenderId::new( - self.mode_request_senders.local_channel_id().unwrap(), + .send(MessageWithSenderId::new( + self.mode_node.local_channel_id_generic(), mode_request, )) .expect("sending mode request failed"); }); } - fn handle_mode_reached(&mut self) -> Result<(), ModeMessagingError> { - self.mode_reply_senders.send_mode_reply( - self.last_mode_sender.unwrap(), + fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + self.mode_node.send_mode_reply( + self.mode_req_commander.unwrap(), ModeReply::ModeReply(self.mode_and_submode), )?; Ok(()) @@ -445,94 +508,81 @@ mod tests { let (reply_sender_to_assy, reply_receiver_assy) = mpsc::channel(); let (reply_sender_to_pus, reply_receiver_pus) = mpsc::channel(); - // All request routers. - let mut mode_request_router_assy = - MpscModeRequestRouter::new(TestChannelId::Assembly as u32); - let mut mode_request_router_pus_mode = - MpscModeRequestRouter::new(TestChannelId::PusModeService as u32); + // Mode requestors and handlers. + let mut mode_node_assy = MpscModeConnector::new( + TestChannelId::Assembly as u32, + request_receiver_assy, + reply_receiver_assy, + ); + // Mode requestors only. + let mut mode_node_pus = MpscModeRequestorConnector::new( + TestChannelId::PusModeService as u32, + reply_receiver_pus, + ); - // All request receivers. - let mode_request_receiver_dev1 = - MpscModeRequestReceiver::new(TestChannelId::Device1 as u32, request_receiver_dev1); - let mode_request_receiver_dev2 = - MpscModeRequestReceiver::new(TestChannelId::Device2 as u32, request_receiver_dev2); - let mode_request_receiver_assy = - MpscModeRequestReceiver::new(TestChannelId::Assembly as u32, request_receiver_assy); - - // All reply senders. - let mut mode_reply_senders_dev1 = MpscModeReplyRouter::new(TestChannelId::Device1 as u32); - let mut mode_reply_senders_dev2 = MpscModeReplyRouter::new(TestChannelId::Device2 as u32); - let mut mode_reply_senders_assy = MpscModeReplyRouter::new(TestChannelId::Assembly as u32); - - // All reply receivers. - let mode_reply_receiver_list_assy = - MpscModeReplyReceiver::new(TestChannelId::Assembly as u32, reply_receiver_assy); - let mode_reply_receiver_pus_service = - MpscModeReplyReceiver::new(TestChannelId::PusModeService as u32, reply_receiver_pus); + // Request handlers only. + let mut mode_node_dev1 = MpscModeRequestHandlerConnector::new( + TestChannelId::Device1 as u32, + request_receiver_dev1, + ); + let mut mode_node_dev2 = MpscModeRequestHandlerConnector::new( + TestChannelId::Device2 as u32, + request_receiver_dev2, + ); // Set up mode request senders first. - mode_request_router_pus_mode - .add_request_target(TestChannelId::Assembly as u32, request_sender_to_assy); - mode_request_router_pus_mode.add_request_target( + mode_node_pus.add_message_target(TestChannelId::Assembly as u32, request_sender_to_assy); + mode_node_pus.add_message_target( TestChannelId::Device1 as u32, request_sender_to_dev1.clone(), ); - mode_request_router_pus_mode.add_request_target( + mode_node_pus.add_message_target( TestChannelId::Device2 as u32, request_sender_to_dev2.clone(), ); - mode_request_router_assy - .add_request_target(TestChannelId::Device1 as u32, request_sender_to_dev1); - mode_request_router_assy - .add_request_target(TestChannelId::Device2 as u32, request_sender_to_dev2); + mode_node_assy.add_request_target(TestChannelId::Device1 as u32, request_sender_to_dev1); + mode_node_assy.add_request_target(TestChannelId::Device2 as u32, request_sender_to_dev2); // Set up mode reply senders. - mode_reply_senders_dev1 - .add_reply_target(TestChannelId::Assembly as u32, reply_sender_to_assy.clone()); - mode_reply_senders_dev1.add_reply_target( + mode_node_dev1 + .add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy.clone()); + mode_node_dev1.add_message_target( TestChannelId::PusModeService as u32, reply_sender_to_pus.clone(), ); - mode_reply_senders_dev2 - .add_reply_target(TestChannelId::Assembly as u32, reply_sender_to_assy); - mode_reply_senders_dev2.add_reply_target( + mode_node_dev2.add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy); + mode_node_dev2.add_message_target( TestChannelId::PusModeService as u32, reply_sender_to_pus.clone(), ); - mode_reply_senders_assy - .add_reply_target(TestChannelId::PusModeService as u32, reply_sender_to_pus); + mode_node_assy.add_reply_target(TestChannelId::PusModeService as u32, reply_sender_to_pus); - let device1 = TestDevice { - mode_request_receiver: mode_request_receiver_dev1, - mode_reply_router: mode_reply_senders_dev1, - mode_reply_receiver: None, + let mut device1 = TestDevice { + name: "Test Device 1".to_string(), + mode_node: mode_node_dev1, + mode_req_commander: None, mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, }; - let device2 = TestDevice { - mode_request_receiver: mode_request_receiver_dev2, - mode_reply_router: mode_reply_senders_dev2, - mode_reply_receiver: None, + let mut device2 = TestDevice { + name: "Test Device 2".to_string(), + mode_node: mode_node_dev2, + mode_req_commander: None, mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, }; - let assy = TestAssembly { - mode_request_receiver: mode_request_receiver_assy, - mode_reply_senders: mode_reply_senders_assy, - mode_request_senders: mode_request_router_assy, - mode_reply_receiver: mode_reply_receiver_list_assy, - last_mode_sender: None, + let mut assy = TestAssembly { + mode_node: mode_node_assy, + mode_req_commander: None, mode_and_submode: ModeAndSubmode::new(0, 0), target_mode_and_submode: None, }; let pus_service = PusModeService { - mode_request_recipients: mode_request_router_pus_mode, - mode_reply_receiver_list: mode_reply_receiver_pus_service, + mode_node: mode_node_pus, }; pus_service.send_announce_mode_cmd_to_assy(); - // assy.run(); - // device1.run(); - // device2.run(); + assy.run(); + device1.run(); + device2.run(); + assy.run(); } } diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index dd2e3cd..88741a2 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -50,3 +50,21 @@ impl Display for GenericReceiveError { #[cfg(feature = "std")] impl Error for GenericReceiveError {} + +#[derive(Debug, Clone)] +pub enum GenericTargetedMessagingError { + TargetDoesNotExist(ChannelId), + Send(GenericSendError), + Receive(GenericReceiveError), +} +impl From for GenericTargetedMessagingError { + fn from(value: GenericSendError) -> Self { + Self::Send(value) + } +} + +impl From for GenericTargetedMessagingError { + fn from(value: GenericReceiveError) -> Self { + Self::Receive(value) + } +} diff --git a/satrs/src/request.rs b/satrs/src/request.rs index 24ca497..572a232 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -2,12 +2,16 @@ use core::fmt; #[cfg(feature = "std")] use std::error::Error; +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +pub use std_mod::*; + use spacepackets::{ ecss::{tc::IsPusTelecommand, PusPacket}, ByteConversionError, CcsdsPacket, }; -use crate::TargetId; +use crate::{ChannelId, TargetId}; pub type Apid = u16; @@ -108,3 +112,243 @@ impl fmt::Display for TargetAndApidId { write!(f, "{}, {}", self.apid, self.target) } } + +pub struct MessageWithSenderId { + pub sender_id: ChannelId, + pub message: MESSAGE, +} + +impl MessageWithSenderId { + pub fn new(sender_id: ChannelId, message: MESSAGE) -> Self { + Self { sender_id, message } + } +} + +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] +mod std_mod { + use std::sync::mpsc; + + use hashbrown::HashMap; + + use crate::{ + queue::{GenericReceiveError, GenericSendError, GenericTargetedMessagingError}, + ChannelId, + }; + + use super::MessageWithSenderId; + + pub trait TargetedMessageSendProvider { + type Message; + fn send_message( + &self, + local_channel_id: ChannelId, + target_channel_id: ChannelId, + message: Self::Message, + ) -> Result<(), GenericTargetedMessagingError>; + } + + pub struct MpscMessageSenderMap>( + pub HashMap, + ); + + impl Default for MpscMessageSenderMap { + fn default() -> Self { + Self(Default::default()) + } + } + + impl MpscMessageSenderMap { + pub fn send_message( + &self, + local_channel_id: ChannelId, + target_channel_id: ChannelId, + message: Message, + ) -> Result<(), GenericTargetedMessagingError> { + if self.0.contains_key(&target_channel_id) { + self.0 + .get(&target_channel_id) + .unwrap() + .send(MessageWithSenderId::new(local_channel_id, message)) + .map_err(|_| GenericSendError::RxDisconnected)?; + return Ok(()); + } + Err(GenericTargetedMessagingError::TargetDoesNotExist( + target_channel_id, + )) + } + + pub fn add_message_target( + &mut self, + target_id: ChannelId, + message_sender: mpsc::Sender>, + ) { + self.0.insert(target_id, message_sender); + } + } + + pub struct MpscMessageSenderWithId { + pub local_channel_id: ChannelId, + pub message_sender_map: MpscMessageSenderMap, + } + + impl MpscMessageSenderWithId { + pub fn new(local_channel_id: ChannelId) -> Self { + Self { + local_channel_id, + message_sender_map: Default::default(), + } + } + + pub fn send_message( + &self, + target_channel_id: ChannelId, + message: MESSAGE, + ) -> Result<(), GenericTargetedMessagingError> { + self.message_sender_map + .send_message(self.local_channel_id, target_channel_id, message) + } + + pub fn add_message_target( + &mut self, + target_id: ChannelId, + message_sender: mpsc::Sender>, + ) { + self.message_sender_map + .add_message_target(target_id, message_sender) + } + } + + pub struct MpscMessageWithSenderReceiver( + pub mpsc::Receiver>, + ); + + impl From>> + for MpscMessageWithSenderReceiver + { + fn from(value: mpsc::Receiver>) -> Self { + Self(value) + } + } + + impl MpscMessageWithSenderReceiver { + pub fn try_recv_message( + &self, + local_id: ChannelId, + ) -> Result>, GenericTargetedMessagingError> { + match self.0.try_recv() { + Ok(reply) => { + return Ok(Some(reply)); + } + Err(e) => { + if e == mpsc::TryRecvError::Disconnected { + return Err(GenericReceiveError::TxDisconnected(Some(local_id)).into()); + } + } + } + Ok(None) + } + } + + pub struct MpscMessageReceiverWithIds { + local_channel_id: ChannelId, + reply_receiver: MpscMessageWithSenderReceiver, + } + + impl MpscMessageReceiverWithIds { + pub fn new( + local_channel_id: ChannelId, + reply_receiver: MpscMessageWithSenderReceiver, + ) -> Self { + Self { + local_channel_id, + reply_receiver, + } + } + + pub fn local_channel_id(&self) -> ChannelId { + self.local_channel_id + } + + pub fn try_recv_message( + &self, + ) -> Result>, GenericTargetedMessagingError> { + match self.reply_receiver.0.try_recv() { + Ok(reply) => { + return Ok(Some(reply)); + } + Err(e) => { + if e == mpsc::TryRecvError::Disconnected { + return Err(GenericReceiveError::TxDisconnected(Some( + self.local_channel_id(), + )) + .into()); + } + } + } + Ok(None) + } + } + + pub struct MpscMessageSenderAndReceiver { + pub local_channel_id: ChannelId, + pub message_sender_map: MpscMessageSenderMap, + pub message_receiver: MpscMessageWithSenderReceiver, + } + + impl MpscMessageSenderAndReceiver { + pub fn new( + local_channel_id: ChannelId, + message_receiver: mpsc::Receiver>, + ) -> Self { + Self { + local_channel_id, + message_sender_map: Default::default(), + message_receiver: MpscMessageWithSenderReceiver::from(message_receiver), + } + } + + pub fn add_message_target( + &mut self, + target_id: ChannelId, + message_sender: mpsc::Sender>, + ) { + self.message_sender_map + .add_message_target(target_id, message_sender) + } + + pub fn local_channel_id_generic(&self) -> ChannelId { + self.local_channel_id + } + } + + pub struct MpscRequestAndReplySenderAndReceiver { + pub local_channel_id: ChannelId, + // These 2 are a functional group. + pub request_sender_map: MpscMessageSenderMap, + pub reply_receiver: MpscMessageWithSenderReceiver, + // These 2 are a functional group. + pub request_receiver: MpscMessageWithSenderReceiver, + pub reply_sender_map: MpscMessageSenderMap, + } + + impl MpscRequestAndReplySenderAndReceiver { + pub fn new( + local_channel_id: ChannelId, + request_receiver: mpsc::Receiver>, + reply_receiver: mpsc::Receiver>, + ) -> Self { + Self { + local_channel_id, + request_receiver: request_receiver.into(), + reply_receiver: reply_receiver.into(), + request_sender_map: Default::default(), + reply_sender_map: Default::default(), + } + } + + pub fn local_channel_id_generic(&self) -> ChannelId { + self.local_channel_id + } + } +} -- 2.43.0 From 7967b955532d338df9279f589db7a89dc4f0fef7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 15:51:51 +0100 Subject: [PATCH 05/19] this is not easy --- satrs/src/request.rs | 28 +++++++++------------------- 1 file changed, 9 insertions(+), 19 deletions(-) diff --git a/satrs/src/request.rs b/satrs/src/request.rs index 572a232..4ef482c 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -138,32 +138,22 @@ mod std_mod { use super::MessageWithSenderId; - pub trait TargetedMessageSendProvider { - type Message; - fn send_message( - &self, - local_channel_id: ChannelId, - target_channel_id: ChannelId, - message: Self::Message, - ) -> Result<(), GenericTargetedMessagingError>; - } - - pub struct MpscMessageSenderMap>( - pub HashMap, + pub struct MpscMessageSenderMap( + pub HashMap>>, ); - impl Default for MpscMessageSenderMap { + impl Default for MpscMessageSenderMap { fn default() -> Self { Self(Default::default()) } } - impl MpscMessageSenderMap { + impl MpscMessageSenderMap { pub fn send_message( &self, local_channel_id: ChannelId, target_channel_id: ChannelId, - message: Message, + message: MESSAGE, ) -> Result<(), GenericTargetedMessagingError> { if self.0.contains_key(&target_channel_id) { self.0 @@ -181,18 +171,18 @@ mod std_mod { pub fn add_message_target( &mut self, target_id: ChannelId, - message_sender: mpsc::Sender>, + message_sender: mpsc::Sender>, ) { self.0.insert(target_id, message_sender); } } - pub struct MpscMessageSenderWithId { + pub struct MpscMessageSenderWithId { pub local_channel_id: ChannelId, - pub message_sender_map: MpscMessageSenderMap, + pub message_sender_map: MpscMessageSenderMap, } - impl MpscMessageSenderWithId { + impl MpscMessageSenderWithId { pub fn new(local_channel_id: ChannelId) -> Self { Self { local_channel_id, -- 2.43.0 From e7c0d33ccb0104f8ddc3f5b172931042f1027eef Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 17:19:32 +0100 Subject: [PATCH 06/19] that was hard --- satrs/src/mode_tree.rs | 136 ++++++++++++++++-------- satrs/src/request.rs | 231 +++++++++++++++++++++++------------------ 2 files changed, 227 insertions(+), 140 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 80d8b2c..e088981 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -7,8 +7,9 @@ use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, queue::GenericTargetedMessagingError, request::{ - MessageWithSenderId, MpscMessageReceiverWithIds, MpscMessageSenderAndReceiver, - MpscMessageSenderMap, MpscMessageSenderWithId, MpscRequestAndReplySenderAndReceiver, + MessageReceiver, MessageReceiverWithId, MessageSender, MessageSenderAndReceiver, + MessageSenderMap, MessageSenderMapWithId, MessageWithSenderId, + RequestAndReplySenderAndReceiver, }, ChannelId, }; @@ -71,7 +72,7 @@ pub trait ModeReplyReceiver { ) -> Result>, GenericTargetedMessagingError>; } -impl MpscMessageSenderMap { +impl> MessageSenderMap { pub fn send_mode_request( &self, local_id: ChannelId, @@ -81,16 +82,12 @@ impl MpscMessageSenderMap { self.send_message(local_id, target_id, request) } - pub fn add_request_target( - &mut self, - target_id: ChannelId, - request_sender: mpsc::Sender>, - ) { + pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) { self.add_message_target(target_id, request_sender) } } -impl MpscMessageSenderMap { +impl> MessageSenderMap { pub fn send_mode_reply( &self, local_id: ChannelId, @@ -100,16 +97,12 @@ impl MpscMessageSenderMap { self.send_message(local_id, target_id, request) } - pub fn add_reply_target( - &mut self, - target_id: ChannelId, - request_sender: mpsc::Sender>, - ) { + pub fn add_reply_target(&mut self, target_id: ChannelId, request_sender: S) { self.add_message_target(target_id, request_sender) } } -impl ModeReplySender for MpscMessageSenderWithId { +impl> ModeReplySender for MessageSenderMapWithId { fn send_mode_reply( &self, target_channel_id: ChannelId, @@ -123,7 +116,7 @@ impl ModeReplySender for MpscMessageSenderWithId { } } -impl ModeRequestSender for MpscMessageSenderWithId { +impl> ModeRequestSender for MessageSenderMapWithId { fn local_channel_id(&self) -> ChannelId { self.local_channel_id } @@ -137,14 +130,16 @@ impl ModeRequestSender for MpscMessageSenderWithId { } } -impl ModeReplyReceiver for MpscMessageReceiverWithIds { +impl> ModeReplyReceiver for MessageReceiverWithId { fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } } -impl ModeRequestReceiver for MpscMessageReceiverWithIds { +impl> ModeRequestReceiver + for MessageReceiverWithId +{ fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -152,7 +147,9 @@ impl ModeRequestReceiver for MpscMessageReceiverWithIds { } } -impl ModeRequestSender for MpscMessageSenderAndReceiver { +impl, R: MessageReceiver> ModeRequestSender + for MessageSenderAndReceiver +{ fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } @@ -167,7 +164,9 @@ impl ModeRequestSender for MpscMessageSenderAndReceiver } } -impl ModeReplySender for MpscMessageSenderAndReceiver { +impl, R: MessageReceiver> ModeReplySender + for MessageSenderAndReceiver +{ fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } @@ -182,7 +181,9 @@ impl ModeReplySender for MpscMessageSenderAndReceiver { } } -impl ModeReplyReceiver for MpscMessageSenderAndReceiver { +impl, R: MessageReceiver> ModeReplyReceiver + for MessageSenderAndReceiver +{ fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -190,7 +191,9 @@ impl ModeReplyReceiver for MpscMessageSenderAndReceiver { .try_recv_message(self.local_channel_id_generic()) } } -impl ModeRequestReceiver for MpscMessageSenderAndReceiver { +impl, R: MessageReceiver> ModeRequestReceiver + for MessageSenderAndReceiver +{ fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -199,33 +202,63 @@ impl ModeRequestReceiver for MpscMessageSenderAndReceiver { } } -pub type MpscModeRequestHandlerConnector = MpscMessageSenderAndReceiver; -pub type MpscModeRequestorConnector = MpscMessageSenderAndReceiver; -pub type MpscModeConnector = MpscRequestAndReplySenderAndReceiver; +pub type ModeRequestHandlerConnector = MessageSenderAndReceiver; +pub type MpscModeRequestHandlerConnector = ModeRequestHandlerConnector< + mpsc::Sender>, + mpsc::Receiver>, +>; -impl MpscRequestAndReplySenderAndReceiver { - pub fn add_request_target( - &mut self, - target_id: ChannelId, - request_sender: mpsc::Sender>, - ) { +pub type ModeRequestorConnector = MessageSenderAndReceiver; +pub type MpscModeRequestorConnector = ModeRequestorConnector< + mpsc::Sender>, + mpsc::Receiver>, +>; + +pub type ModeConnector = + RequestAndReplySenderAndReceiver; +pub type MpscModeConnector = ModeConnector< + mpsc::Sender>, + mpsc::Receiver>, + mpsc::Sender>, + mpsc::Receiver>, +>; + +impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > RequestAndReplySenderAndReceiver +{ + pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S0) { self.request_sender_map .add_message_target(target_id, request_sender) } } -impl MpscRequestAndReplySenderAndReceiver { - pub fn add_reply_target( - &mut self, - target_id: ChannelId, - reply_sender: mpsc::Sender>, - ) { +impl< + REQUEST, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > RequestAndReplySenderAndReceiver +{ + pub fn add_reply_target(&mut self, target_id: ChannelId, reply_sender: S1) { self.reply_sender_map .add_message_target(target_id, reply_sender) } } -impl ModeRequestSender for MpscRequestAndReplySenderAndReceiver { +impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeRequestSender for RequestAndReplySenderAndReceiver +{ fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } @@ -240,7 +273,14 @@ impl ModeRequestSender for MpscRequestAndReplySenderAndReceiver ModeReplySender for MpscRequestAndReplySenderAndReceiver { +impl< + REQUEST, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeReplySender for RequestAndReplySenderAndReceiver +{ fn local_channel_id(&self) -> ChannelId { self.local_channel_id_generic() } @@ -255,7 +295,14 @@ impl ModeReplySender for MpscRequestAndReplySenderAndReceiver ModeReplyReceiver for MpscRequestAndReplySenderAndReceiver { +impl< + REQUEST, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeReplyReceiver for RequestAndReplySenderAndReceiver +{ fn try_recv_mode_reply( &self, ) -> Result>, GenericTargetedMessagingError> { @@ -264,7 +311,14 @@ impl ModeReplyReceiver for MpscRequestAndReplySenderAndReceiver ModeRequestReceiver for MpscRequestAndReplySenderAndReceiver { +impl< + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > ModeRequestReceiver for RequestAndReplySenderAndReceiver +{ fn try_recv_mode_request( &self, ) -> Result>, GenericTargetedMessagingError> { diff --git a/satrs/src/request.rs b/satrs/src/request.rs index 4ef482c..2cb174c 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -11,7 +11,7 @@ use spacepackets::{ ByteConversionError, CcsdsPacket, }; -use crate::{ChannelId, TargetId}; +use crate::{queue::GenericTargetedMessagingError, ChannelId, TargetId}; pub type Apid = u16; @@ -113,20 +113,31 @@ impl fmt::Display for TargetAndApidId { } } -pub struct MessageWithSenderId { +pub struct MessageWithSenderId { pub sender_id: ChannelId, - pub message: MESSAGE, + pub message: MSG, } -impl MessageWithSenderId { - pub fn new(sender_id: ChannelId, message: MESSAGE) -> Self { +impl MessageWithSenderId { + pub fn new(sender_id: ChannelId, message: MSG) -> Self { Self { sender_id, message } } } +/// Generic trait for objects which can send targeted messages. +pub trait MessageSender: Send { + fn send(&self, message: MessageWithSenderId) -> Result<(), GenericTargetedMessagingError>; +} + +// Generic trait for objects which can receive targeted messages. +pub trait MessageReceiver { + fn try_recv(&self) -> Result>, GenericTargetedMessagingError>; +} + #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] mod std_mod { + use core::marker::PhantomData; use std::sync::mpsc; use hashbrown::HashMap; @@ -136,24 +147,59 @@ mod std_mod { ChannelId, }; - use super::MessageWithSenderId; + use super::{MessageReceiver, MessageSender, MessageWithSenderId}; - pub struct MpscMessageSenderMap( - pub HashMap>>, - ); - - impl Default for MpscMessageSenderMap { - fn default() -> Self { - Self(Default::default()) + impl MessageSender for mpsc::Sender> { + fn send( + &self, + message: MessageWithSenderId, + ) -> Result<(), GenericTargetedMessagingError> { + self.send(message) + .map_err(|_| GenericSendError::RxDisconnected)?; + Ok(()) + } + } + impl MessageSender for mpsc::SyncSender> { + fn send( + &self, + message: MessageWithSenderId, + ) -> Result<(), GenericTargetedMessagingError> { + if let Err(e) = self.try_send(message) { + match e { + mpsc::TrySendError::Full(_) => { + return Err(GenericSendError::QueueFull(None).into()); + } + mpsc::TrySendError::Disconnected(_) => todo!(), + } + } + Ok(()) } } - impl MpscMessageSenderMap { + pub struct MessageSenderMap>( + pub HashMap, + PhantomData, + ); + + pub type MpscSenderMap = MessageReceiverWithId>; + pub type MpscBoundedSenderMap = MessageReceiverWithId>; + + impl> Default for MessageSenderMap { + fn default() -> Self { + Self(Default::default(), PhantomData) + } + } + + impl> MessageSenderMap { + pub fn add_message_target(&mut self, target_id: ChannelId, message_sender: S) { + self.0.insert(target_id, message_sender); + } + pub fn send_message( &self, local_channel_id: ChannelId, target_channel_id: ChannelId, - message: MESSAGE, + message: MSG, ) -> Result<(), GenericTargetedMessagingError> { if self.0.contains_key(&target_channel_id) { self.0 @@ -167,22 +213,14 @@ mod std_mod { target_channel_id, )) } - - pub fn add_message_target( - &mut self, - target_id: ChannelId, - message_sender: mpsc::Sender>, - ) { - self.0.insert(target_id, message_sender); - } } - pub struct MpscMessageSenderWithId { + pub struct MessageSenderMapWithId> { pub local_channel_id: ChannelId, - pub message_sender_map: MpscMessageSenderMap, + pub message_sender_map: MessageSenderMap, } - impl MpscMessageSenderWithId { + impl> MessageSenderMapWithId { pub fn new(local_channel_id: ChannelId) -> Self { Self { local_channel_id, @@ -193,62 +231,62 @@ mod std_mod { pub fn send_message( &self, target_channel_id: ChannelId, - message: MESSAGE, + message: MSG, ) -> Result<(), GenericTargetedMessagingError> { self.message_sender_map .send_message(self.local_channel_id, target_channel_id, message) } - pub fn add_message_target( - &mut self, - target_id: ChannelId, - message_sender: mpsc::Sender>, - ) { + pub fn add_message_target(&mut self, target_id: ChannelId, message_sender: S) { self.message_sender_map .add_message_target(target_id, message_sender) } } - pub struct MpscMessageWithSenderReceiver( - pub mpsc::Receiver>, - ); - - impl From>> - for MpscMessageWithSenderReceiver - { - fn from(value: mpsc::Receiver>) -> Self { - Self(value) + impl MessageReceiver for mpsc::Receiver> { + fn try_recv( + &self, + ) -> Result>, GenericTargetedMessagingError> { + match self.try_recv() { + Ok(msg) => Ok(Some(msg)), + Err(e) => match e { + mpsc::TryRecvError::Empty => Ok(None), + mpsc::TryRecvError::Disconnected => { + Err(GenericReceiveError::TxDisconnected(None).into()) + } + }, + } } } - impl MpscMessageWithSenderReceiver { + pub struct MessageWithSenderIdReceiver>(pub R, PhantomData); + + impl> From for MessageWithSenderIdReceiver { + fn from(receiver: R) -> Self { + MessageWithSenderIdReceiver(receiver, PhantomData) + } + } + + impl> MessageWithSenderIdReceiver { pub fn try_recv_message( &self, - local_id: ChannelId, - ) -> Result>, GenericTargetedMessagingError> { - match self.0.try_recv() { - Ok(reply) => { - return Ok(Some(reply)); - } - Err(e) => { - if e == mpsc::TryRecvError::Disconnected { - return Err(GenericReceiveError::TxDisconnected(Some(local_id)).into()); - } - } - } - Ok(None) + _local_id: ChannelId, + ) -> Result>, GenericTargetedMessagingError> { + self.0.try_recv() } } - pub struct MpscMessageReceiverWithIds { + pub struct MessageReceiverWithId> { local_channel_id: ChannelId, - reply_receiver: MpscMessageWithSenderReceiver, + reply_receiver: MessageWithSenderIdReceiver, } - impl MpscMessageReceiverWithIds { + pub type MpscMessageReceiverWithId = MessageReceiverWithId>; + + impl> MessageReceiverWithId { pub fn new( local_channel_id: ChannelId, - reply_receiver: MpscMessageWithSenderReceiver, + reply_receiver: MessageWithSenderIdReceiver, ) -> Self { Self { local_channel_id, @@ -259,50 +297,34 @@ mod std_mod { pub fn local_channel_id(&self) -> ChannelId { self.local_channel_id } + } + impl> MessageReceiverWithId { pub fn try_recv_message( &self, - ) -> Result>, GenericTargetedMessagingError> { - match self.reply_receiver.0.try_recv() { - Ok(reply) => { - return Ok(Some(reply)); - } - Err(e) => { - if e == mpsc::TryRecvError::Disconnected { - return Err(GenericReceiveError::TxDisconnected(Some( - self.local_channel_id(), - )) - .into()); - } - } - } - Ok(None) + ) -> Result>, GenericTargetedMessagingError> { + self.reply_receiver.0.try_recv() } } - pub struct MpscMessageSenderAndReceiver { + pub struct MessageSenderAndReceiver, R: MessageReceiver> { pub local_channel_id: ChannelId, - pub message_sender_map: MpscMessageSenderMap, - pub message_receiver: MpscMessageWithSenderReceiver, + pub message_sender_map: MessageSenderMap, + pub message_receiver: MessageWithSenderIdReceiver, } - impl MpscMessageSenderAndReceiver { - pub fn new( - local_channel_id: ChannelId, - message_receiver: mpsc::Receiver>, - ) -> Self { + impl, R: MessageReceiver> + MessageSenderAndReceiver + { + pub fn new(local_channel_id: ChannelId, message_receiver: R) -> Self { Self { local_channel_id, message_sender_map: Default::default(), - message_receiver: MpscMessageWithSenderReceiver::from(message_receiver), + message_receiver: MessageWithSenderIdReceiver::from(message_receiver), } } - pub fn add_message_target( - &mut self, - target_id: ChannelId, - message_sender: mpsc::Sender>, - ) { + pub fn add_message_target(&mut self, target_id: ChannelId, message_sender: S) { self.message_sender_map .add_message_target(target_id, message_sender) } @@ -312,22 +334,33 @@ mod std_mod { } } - pub struct MpscRequestAndReplySenderAndReceiver { + pub struct RequestAndReplySenderAndReceiver< + REQUEST, + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > { pub local_channel_id: ChannelId, // These 2 are a functional group. - pub request_sender_map: MpscMessageSenderMap, - pub reply_receiver: MpscMessageWithSenderReceiver, + pub request_sender_map: MessageSenderMap, + pub reply_receiver: MessageWithSenderIdReceiver, // These 2 are a functional group. - pub request_receiver: MpscMessageWithSenderReceiver, - pub reply_sender_map: MpscMessageSenderMap, + pub request_receiver: MessageWithSenderIdReceiver, + pub reply_sender_map: MessageSenderMap, } - impl MpscRequestAndReplySenderAndReceiver { - pub fn new( - local_channel_id: ChannelId, - request_receiver: mpsc::Receiver>, - reply_receiver: mpsc::Receiver>, - ) -> Self { + impl< + REQUEST, + REPLY, + S0: MessageSender, + R0: MessageReceiver, + S1: MessageSender, + R1: MessageReceiver, + > RequestAndReplySenderAndReceiver + { + pub fn new(local_channel_id: ChannelId, request_receiver: R1, reply_receiver: R0) -> Self { Self { local_channel_id, request_receiver: request_receiver.into(), -- 2.43.0 From 508561d7916cd319e816c532a1f963c2602785c0 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 17:31:10 +0100 Subject: [PATCH 07/19] sync channel now works as well --- satrs/src/mode_tree.rs | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index e088981..1fb4c6f 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -137,6 +137,7 @@ impl> ModeReplyReceiver for MessageReceiverWithId< self.try_recv_message() } } + impl> ModeRequestReceiver for MessageReceiverWithId { @@ -207,12 +208,20 @@ pub type MpscModeRequestHandlerConnector = ModeRequestHandlerConnector< mpsc::Sender>, mpsc::Receiver>, >; +pub type MpscBoundedModeRequestHandlerConnector = ModeRequestHandlerConnector< + mpsc::SyncSender>, + mpsc::Receiver>, +>; pub type ModeRequestorConnector = MessageSenderAndReceiver; pub type MpscModeRequestorConnector = ModeRequestorConnector< mpsc::Sender>, mpsc::Receiver>, >; +pub type MpscBoundedModeRequestorConnector = ModeRequestorConnector< + mpsc::SyncSender>, + mpsc::Receiver>, +>; pub type ModeConnector = RequestAndReplySenderAndReceiver; @@ -222,6 +231,12 @@ pub type MpscModeConnector = ModeConnector< mpsc::Sender>, mpsc::Receiver>, >; +pub type MpscBoundedModeConnector = ModeConnector< + mpsc::SyncSender>, + mpsc::Receiver>, + mpsc::SyncSender>, + mpsc::Receiver>, +>; impl< REPLY, @@ -370,7 +385,7 @@ mod tests { } struct PusModeService { - pub mode_node: MpscModeRequestorConnector, + pub mode_node: MpscBoundedModeRequestorConnector, } impl PusModeService { @@ -386,7 +401,7 @@ mod tests { struct TestDevice { pub name: String, - pub mode_node: MpscModeRequestHandlerConnector, + pub mode_node: MpscBoundedModeRequestHandlerConnector, pub mode_and_submode: ModeAndSubmode, pub mode_req_commander: Option, } @@ -447,7 +462,7 @@ mod tests { } struct TestAssembly { - pub mode_node: MpscModeConnector, + pub mode_node: MpscBoundedModeConnector, pub mode_req_commander: Option, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, @@ -554,32 +569,32 @@ mod tests { #[test] fn basic_test() { // All request channel handles. - let (request_sender_to_dev1, request_receiver_dev1) = mpsc::channel(); - let (request_sender_to_dev2, request_receiver_dev2) = mpsc::channel(); - let (request_sender_to_assy, request_receiver_assy) = mpsc::channel(); + let (request_sender_to_dev1, request_receiver_dev1) = mpsc::sync_channel(10); + let (request_sender_to_dev2, request_receiver_dev2) = mpsc::sync_channel(10); + let (request_sender_to_assy, request_receiver_assy) = mpsc::sync_channel(10); // All reply channel handles. - let (reply_sender_to_assy, reply_receiver_assy) = mpsc::channel(); - let (reply_sender_to_pus, reply_receiver_pus) = mpsc::channel(); + let (reply_sender_to_assy, reply_receiver_assy) = mpsc::sync_channel(10); + let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); // Mode requestors and handlers. - let mut mode_node_assy = MpscModeConnector::new( + let mut mode_node_assy = MpscBoundedModeConnector::new( TestChannelId::Assembly as u32, request_receiver_assy, reply_receiver_assy, ); // Mode requestors only. - let mut mode_node_pus = MpscModeRequestorConnector::new( + let mut mode_node_pus = MpscBoundedModeRequestorConnector::new( TestChannelId::PusModeService as u32, reply_receiver_pus, ); // Request handlers only. - let mut mode_node_dev1 = MpscModeRequestHandlerConnector::new( + let mut mode_node_dev1 = MpscBoundedModeRequestHandlerConnector::new( TestChannelId::Device1 as u32, request_receiver_dev1, ); - let mut mode_node_dev2 = MpscModeRequestHandlerConnector::new( + let mut mode_node_dev2 = MpscBoundedModeRequestHandlerConnector::new( TestChannelId::Device2 as u32, request_receiver_dev2, ); -- 2.43.0 From f28509548857a37928b7a35b298a6e7aebbc4504 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 17:37:18 +0100 Subject: [PATCH 08/19] move test code to dedicated integration test module --- satrs/src/mode_tree.rs | 288 --------------------------------------- satrs/tests/mode_tree.rs | 288 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 288 insertions(+), 288 deletions(-) create mode 100644 satrs/tests/mode_tree.rs diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 1fb4c6f..1c1bfa6 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -366,292 +366,4 @@ pub trait ModeRequestHandler: ModeProvider { #[cfg(test)] mod tests { - use std::{println, sync::mpsc}; - - use alloc::string::{String, ToString}; - - use super::*; - use crate::{ - mode::{ModeAndSubmode, ModeReply, ModeRequest}, - mode_tree::ModeRequestSender, - ChannelId, - }; - - pub enum TestChannelId { - Device1 = 1, - Device2 = 2, - Assembly = 3, - PusModeService = 4, - } - - struct PusModeService { - pub mode_node: MpscBoundedModeRequestorConnector, - } - - impl PusModeService { - pub fn send_announce_mode_cmd_to_assy(&self) { - self.mode_node - .send_mode_request( - TestChannelId::Assembly as u32, - ModeRequest::AnnounceModeRecursive, - ) - .unwrap(); - } - } - - struct TestDevice { - pub name: String, - pub mode_node: MpscBoundedModeRequestHandlerConnector, - pub mode_and_submode: ModeAndSubmode, - pub mode_req_commander: Option, - } - - impl TestDevice { - pub fn run(&mut self) { - self.check_mode_requests().expect("mode messaging error"); - } - - pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { - if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { - match request_and_id.message { - ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(mode_and_submode).unwrap(); - self.mode_req_commander = Some(request_and_id.sender_id); - } - ModeRequest::ReadMode => self - .mode_node - .send_mode_reply( - request_and_id.sender_id, - ModeReply::ModeReply(self.mode_and_submode), - ) - .unwrap(), - ModeRequest::AnnounceMode => self.announce_mode(false), - ModeRequest::AnnounceModeRecursive => self.announce_mode(true), - } - } - Ok(()) - } - } - - impl ModeProvider for TestDevice { - fn mode_and_submode(&self) -> ModeAndSubmode { - self.mode_and_submode - } - } - impl ModeRequestHandler for TestDevice { - fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { - self.mode_and_submode = mode_and_submode; - self.handle_mode_reached()?; - Ok(()) - } - - fn announce_mode(&self, _recursive: bool) { - println!( - "{}: announcing mode: {:?}", - self.name, self.mode_and_submode - ); - } - - fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { - self.mode_node.send_mode_reply( - self.mode_req_commander.unwrap(), - ModeReply::ModeReply(self.mode_and_submode), - )?; - Ok(()) - } - } - - struct TestAssembly { - pub mode_node: MpscBoundedModeConnector, - pub mode_req_commander: Option, - pub mode_and_submode: ModeAndSubmode, - pub target_mode_and_submode: Option, - } - - impl ModeProvider for TestAssembly { - fn mode_and_submode(&self) -> ModeAndSubmode { - self.mode_and_submode - } - } - - impl TestAssembly { - pub fn run(&mut self) { - self.check_mode_requests().expect("mode messaging error"); - self.check_mode_replies().expect("mode messaging error"); - } - - pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { - if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { - match request_and_id.message { - ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(mode_and_submode).unwrap(); - self.mode_req_commander = Some(request_and_id.sender_id); - } - ModeRequest::ReadMode => { - // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() - self.mode_node - .send_mode_reply( - request_and_id.sender_id, - ModeReply::ModeReply(self.mode_and_submode), - ) - .unwrap() - } - ModeRequest::AnnounceMode => self.announce_mode(false), - ModeRequest::AnnounceModeRecursive => self.announce_mode(true), - } - } - Ok(()) - } - pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { - if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { - match reply_and_id.message { - ModeReply::ModeInfo(_) => todo!(), - ModeReply::ModeReply(reply) => { - println!( - "TestAssembly: Received mode reply from {:?}, reached: {:?}", - reply_and_id.sender_id, reply - ); - } - ModeReply::CantReachMode(_) => todo!(), - ModeReply::WrongMode { expected, reached } => { - println!( - "TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}", - reply_and_id.sender_id, reached, expected - ); - } - } - } - Ok(()) - } - } - - impl ModeRequestHandler for TestAssembly { - fn start_transition( - &mut self, - mode_and_submode: ModeAndSubmode, - ) -> Result<(), super::ModeError> { - self.target_mode_and_submode = Some(mode_and_submode); - Ok(()) - } - - fn announce_mode(&self, recursive: bool) { - println!( - "TestAssembly: Announcing mode (recursively: {}): {:?}", - recursive, self.mode_and_submode - ); - let mut mode_request = ModeRequest::AnnounceMode; - if recursive { - mode_request = ModeRequest::AnnounceModeRecursive; - } - self.mode_node - .request_sender_map - .0 - .iter() - .for_each(|(_, sender)| { - sender - .send(MessageWithSenderId::new( - self.mode_node.local_channel_id_generic(), - mode_request, - )) - .expect("sending mode request failed"); - }); - } - - fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { - self.mode_node.send_mode_reply( - self.mode_req_commander.unwrap(), - ModeReply::ModeReply(self.mode_and_submode), - )?; - Ok(()) - } - } - - #[test] - fn basic_test() { - // All request channel handles. - let (request_sender_to_dev1, request_receiver_dev1) = mpsc::sync_channel(10); - let (request_sender_to_dev2, request_receiver_dev2) = mpsc::sync_channel(10); - let (request_sender_to_assy, request_receiver_assy) = mpsc::sync_channel(10); - - // All reply channel handles. - let (reply_sender_to_assy, reply_receiver_assy) = mpsc::sync_channel(10); - let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); - - // Mode requestors and handlers. - let mut mode_node_assy = MpscBoundedModeConnector::new( - TestChannelId::Assembly as u32, - request_receiver_assy, - reply_receiver_assy, - ); - // Mode requestors only. - let mut mode_node_pus = MpscBoundedModeRequestorConnector::new( - TestChannelId::PusModeService as u32, - reply_receiver_pus, - ); - - // Request handlers only. - let mut mode_node_dev1 = MpscBoundedModeRequestHandlerConnector::new( - TestChannelId::Device1 as u32, - request_receiver_dev1, - ); - let mut mode_node_dev2 = MpscBoundedModeRequestHandlerConnector::new( - TestChannelId::Device2 as u32, - request_receiver_dev2, - ); - - // Set up mode request senders first. - mode_node_pus.add_message_target(TestChannelId::Assembly as u32, request_sender_to_assy); - mode_node_pus.add_message_target( - TestChannelId::Device1 as u32, - request_sender_to_dev1.clone(), - ); - mode_node_pus.add_message_target( - TestChannelId::Device2 as u32, - request_sender_to_dev2.clone(), - ); - mode_node_assy.add_request_target(TestChannelId::Device1 as u32, request_sender_to_dev1); - mode_node_assy.add_request_target(TestChannelId::Device2 as u32, request_sender_to_dev2); - - // Set up mode reply senders. - mode_node_dev1 - .add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy.clone()); - mode_node_dev1.add_message_target( - TestChannelId::PusModeService as u32, - reply_sender_to_pus.clone(), - ); - mode_node_dev2.add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy); - mode_node_dev2.add_message_target( - TestChannelId::PusModeService as u32, - reply_sender_to_pus.clone(), - ); - mode_node_assy.add_reply_target(TestChannelId::PusModeService as u32, reply_sender_to_pus); - - let mut device1 = TestDevice { - name: "Test Device 1".to_string(), - mode_node: mode_node_dev1, - mode_req_commander: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - }; - let mut device2 = TestDevice { - name: "Test Device 2".to_string(), - mode_node: mode_node_dev2, - mode_req_commander: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - }; - let mut assy = TestAssembly { - mode_node: mode_node_assy, - mode_req_commander: None, - mode_and_submode: ModeAndSubmode::new(0, 0), - target_mode_and_submode: None, - }; - let pus_service = PusModeService { - mode_node: mode_node_pus, - }; - - pus_service.send_announce_mode_cmd_to_assy(); - assy.run(); - device1.run(); - device2.run(); - assy.run(); - } } diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs new file mode 100644 index 0000000..d0c986f --- /dev/null +++ b/satrs/tests/mode_tree.rs @@ -0,0 +1,288 @@ +use std::{println, sync::mpsc}; + +use satrs::mode_tree::ModeRequestSender; +use satrs::{ + mode::{ModeAndSubmode, ModeReply, ModeRequest}, + mode_tree::{ + ModeError, ModeProvider, ModeReplyReceiver, ModeReplySender, ModeRequestHandler, + ModeRequestReceiver, MpscBoundedModeConnector, MpscBoundedModeRequestHandlerConnector, + MpscBoundedModeRequestorConnector, + }, + queue::GenericTargetedMessagingError, + request::MessageWithSenderId, + ChannelId, +}; +use std::string::{String, ToString}; + +pub enum TestChannelId { + Device1 = 1, + Device2 = 2, + Assembly = 3, + PusModeService = 4, +} + +struct PusModeService { + pub mode_node: MpscBoundedModeRequestorConnector, +} + +impl PusModeService { + pub fn send_announce_mode_cmd_to_assy(&self) { + self.mode_node + .send_mode_request( + TestChannelId::Assembly as u32, + ModeRequest::AnnounceModeRecursive, + ) + .unwrap(); + } +} + +struct TestDevice { + pub name: String, + pub mode_node: MpscBoundedModeRequestHandlerConnector, + pub mode_and_submode: ModeAndSubmode, + pub mode_req_commander: Option, +} + +impl TestDevice { + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { + match request_and_id.message { + ModeRequest::SetMode(mode_and_submode) => { + self.start_transition(mode_and_submode).unwrap(); + self.mode_req_commander = Some(request_and_id.sender_id); + } + ModeRequest::ReadMode => self + .mode_node + .send_mode_reply( + request_and_id.sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap(), + ModeRequest::AnnounceMode => self.announce_mode(false), + ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + } + } + Ok(()) + } +} + +impl ModeProvider for TestDevice { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} +impl ModeRequestHandler for TestDevice { + fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { + self.mode_and_submode = mode_and_submode; + self.handle_mode_reached()?; + Ok(()) + } + + fn announce_mode(&self, _recursive: bool) { + println!( + "{}: announcing mode: {:?}", + self.name, self.mode_and_submode + ); + } + + fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + self.mode_node.send_mode_reply( + self.mode_req_commander.unwrap(), + ModeReply::ModeReply(self.mode_and_submode), + )?; + Ok(()) + } +} + +struct TestAssembly { + pub mode_node: MpscBoundedModeConnector, + pub mode_req_commander: Option, + pub mode_and_submode: ModeAndSubmode, + pub target_mode_and_submode: Option, +} + +impl ModeProvider for TestAssembly { + fn mode_and_submode(&self) -> ModeAndSubmode { + self.mode_and_submode + } +} + +impl TestAssembly { + pub fn run(&mut self) { + self.check_mode_requests().expect("mode messaging error"); + self.check_mode_replies().expect("mode messaging error"); + } + + pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { + match request_and_id.message { + ModeRequest::SetMode(mode_and_submode) => { + self.start_transition(mode_and_submode).unwrap(); + self.mode_req_commander = Some(request_and_id.sender_id); + } + ModeRequest::ReadMode => { + // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() + self.mode_node + .send_mode_reply( + request_and_id.sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap() + } + ModeRequest::AnnounceMode => self.announce_mode(false), + ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + } + } + Ok(()) + } + pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { + if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { + match reply_and_id.message { + ModeReply::ModeInfo(_) => todo!(), + ModeReply::ModeReply(reply) => { + println!( + "TestAssembly: Received mode reply from {:?}, reached: {:?}", + reply_and_id.sender_id, reply + ); + } + ModeReply::CantReachMode(_) => todo!(), + ModeReply::WrongMode { expected, reached } => { + println!( + "TestAssembly: Wrong mode reply from {:?}, reached {:?}, expected {:?}", + reply_and_id.sender_id, reached, expected + ); + } + } + } + Ok(()) + } +} + +impl ModeRequestHandler for TestAssembly { + fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { + self.target_mode_and_submode = Some(mode_and_submode); + Ok(()) + } + + fn announce_mode(&self, recursive: bool) { + println!( + "TestAssembly: Announcing mode (recursively: {}): {:?}", + recursive, self.mode_and_submode + ); + let mut mode_request = ModeRequest::AnnounceMode; + if recursive { + mode_request = ModeRequest::AnnounceModeRecursive; + } + self.mode_node + .request_sender_map + .0 + .iter() + .for_each(|(_, sender)| { + sender + .send(MessageWithSenderId::new( + self.mode_node.local_channel_id_generic(), + mode_request, + )) + .expect("sending mode request failed"); + }); + } + + fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + self.mode_node.send_mode_reply( + self.mode_req_commander.unwrap(), + ModeReply::ModeReply(self.mode_and_submode), + )?; + Ok(()) + } +} + +fn main() { + // All request channel handles. + let (request_sender_to_dev1, request_receiver_dev1) = mpsc::sync_channel(10); + let (request_sender_to_dev2, request_receiver_dev2) = mpsc::sync_channel(10); + let (request_sender_to_assy, request_receiver_assy) = mpsc::sync_channel(10); + + // All reply channel handles. + let (reply_sender_to_assy, reply_receiver_assy) = mpsc::sync_channel(10); + let (reply_sender_to_pus, reply_receiver_pus) = mpsc::sync_channel(10); + + // Mode requestors and handlers. + let mut mode_node_assy = MpscBoundedModeConnector::new( + TestChannelId::Assembly as u32, + request_receiver_assy, + reply_receiver_assy, + ); + // Mode requestors only. + let mut mode_node_pus = MpscBoundedModeRequestorConnector::new( + TestChannelId::PusModeService as u32, + reply_receiver_pus, + ); + + // Request handlers only. + let mut mode_node_dev1 = MpscBoundedModeRequestHandlerConnector::new( + TestChannelId::Device1 as u32, + request_receiver_dev1, + ); + let mut mode_node_dev2 = MpscBoundedModeRequestHandlerConnector::new( + TestChannelId::Device2 as u32, + request_receiver_dev2, + ); + + // Set up mode request senders first. + mode_node_pus.add_message_target(TestChannelId::Assembly as u32, request_sender_to_assy); + mode_node_pus.add_message_target( + TestChannelId::Device1 as u32, + request_sender_to_dev1.clone(), + ); + mode_node_pus.add_message_target( + TestChannelId::Device2 as u32, + request_sender_to_dev2.clone(), + ); + mode_node_assy.add_request_target(TestChannelId::Device1 as u32, request_sender_to_dev1); + mode_node_assy.add_request_target(TestChannelId::Device2 as u32, request_sender_to_dev2); + + // Set up mode reply senders. + mode_node_dev1.add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy.clone()); + mode_node_dev1.add_message_target( + TestChannelId::PusModeService as u32, + reply_sender_to_pus.clone(), + ); + mode_node_dev2.add_message_target(TestChannelId::Assembly as u32, reply_sender_to_assy); + mode_node_dev2.add_message_target( + TestChannelId::PusModeService as u32, + reply_sender_to_pus.clone(), + ); + mode_node_assy.add_reply_target(TestChannelId::PusModeService as u32, reply_sender_to_pus); + + let mut device1 = TestDevice { + name: "Test Device 1".to_string(), + mode_node: mode_node_dev1, + mode_req_commander: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + }; + let mut device2 = TestDevice { + name: "Test Device 2".to_string(), + mode_node: mode_node_dev2, + mode_req_commander: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + }; + let mut assy = TestAssembly { + mode_node: mode_node_assy, + mode_req_commander: None, + mode_and_submode: ModeAndSubmode::new(0, 0), + target_mode_and_submode: None, + }; + let pus_service = PusModeService { + mode_node: mode_node_pus, + }; + + pus_service.send_announce_mode_cmd_to_assy(); + assy.run(); + device1.run(); + device2.run(); + assy.run(); +} -- 2.43.0 From 0331b04619a5f3af3b4a83dbce0e0a72a0042f93 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 22 Feb 2024 17:45:49 +0100 Subject: [PATCH 09/19] this is okay for now --- satrs/tests/mode_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index d0c986f..d7e6092 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -125,7 +125,6 @@ impl TestAssembly { self.mode_req_commander = Some(request_and_id.sender_id); } ModeRequest::ReadMode => { - // self.handle_read_mode_request(0, self.mode_and_submode, &mut self.mode_reply_sender).unwrap() self.mode_node .send_mode_reply( request_and_id.sender_id, @@ -139,6 +138,7 @@ impl TestAssembly { } Ok(()) } + pub fn check_mode_replies(&mut self) -> Result<(), GenericTargetedMessagingError> { if let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? { match reply_and_id.message { -- 2.43.0 From f088807652d0f5db7e4c3912c0cfda18a4ffe527 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 23 Feb 2024 13:59:15 +0100 Subject: [PATCH 10/19] cargo fmt --- satrs/src/mode_tree.rs | 3 +-- satrs/tests/mode_tree.rs | 15 +++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 1c1bfa6..8bfb137 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -365,5 +365,4 @@ pub trait ModeRequestHandler: ModeProvider { } #[cfg(test)] -mod tests { -} +mod tests {} diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index d7e6092..3c8680f 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -124,14 +124,13 @@ impl TestAssembly { self.start_transition(mode_and_submode).unwrap(); self.mode_req_commander = Some(request_and_id.sender_id); } - ModeRequest::ReadMode => { - self.mode_node - .send_mode_reply( - request_and_id.sender_id, - ModeReply::ModeReply(self.mode_and_submode), - ) - .unwrap() - } + ModeRequest::ReadMode => self + .mode_node + .send_mode_reply( + request_and_id.sender_id, + ModeReply::ModeReply(self.mode_and_submode), + ) + .unwrap(), ModeRequest::AnnounceMode => self.announce_mode(false), ModeRequest::AnnounceModeRecursive => self.announce_mode(true), } -- 2.43.0 From fdcf1146ec1bdf732603b7e28214faf52c17a0a9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 23 Feb 2024 14:38:22 +0100 Subject: [PATCH 11/19] fix CI --- satrs/src/lib.rs | 2 ++ satrs/src/mode_tree.rs | 1 - 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/satrs/src/lib.rs b/satrs/src/lib.rs index 996b9e5..b3374f9 100644 --- a/satrs/src/lib.rs +++ b/satrs/src/lib.rs @@ -32,6 +32,8 @@ pub mod events; #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod executable; pub mod hal; +#[cfg(feature = "std")] +#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod mode_tree; pub mod objects; pub mod pool; diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 8bfb137..dca114a 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -1,5 +1,4 @@ use std::sync::mpsc; - use alloc::vec::Vec; use hashbrown::HashMap; -- 2.43.0 From 07cd37066733661468189692f788455d8f145aeb Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Fri, 23 Feb 2024 17:45:32 +0100 Subject: [PATCH 12/19] cargo fmt --- satrs/src/mode_tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index dca114a..62e622d 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -1,6 +1,6 @@ -use std::sync::mpsc; use alloc::vec::Vec; use hashbrown::HashMap; +use std::sync::mpsc; use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, -- 2.43.0 From f5acdaeffca2ed730b0434fe8f79006375418b10 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 26 Feb 2024 17:14:02 +0100 Subject: [PATCH 13/19] this is just REALLY annoying.. --- satrs/src/action.rs | 20 ++++++++++++--- satrs/src/params.rs | 36 +++++++++++++++++++++++++++ satrs/src/pus/action.rs | 54 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 101 insertions(+), 9 deletions(-) diff --git a/satrs/src/action.rs b/satrs/src/action.rs index 7caeaa6..b35a48d 100644 --- a/satrs/src/action.rs +++ b/satrs/src/action.rs @@ -1,4 +1,8 @@ -use crate::{pool::StoreAddr, TargetId}; +use crate::{ + params::{Params, ParamsHeapless}, + pool::StoreAddr, + TargetId, +}; pub type ActionId = u32; @@ -43,21 +47,29 @@ impl TargetedActionRequest { /// A reply to an action request. #[non_exhaustive] -#[derive(Clone, Eq, PartialEq, Debug)] +#[derive(Clone, Debug)] pub enum ActionReply { - CompletionFailed(ActionId), + CompletionFailed { + id: ActionId, + reason: Params, + }, StepFailed { id: ActionId, step: u32, + reason: Params, }, Completed(ActionId), #[cfg(feature = "alloc")] CompletedStringId(alloc::string::String), #[cfg(feature = "alloc")] - CompletionFailedStringId(alloc::string::String), + CompletionFailedStringId { + id: alloc::string::String, + reason: Params, + }, #[cfg(feature = "alloc")] StepFailedStringId { id: alloc::string::String, step: u32, + reason: Params, }, } diff --git a/satrs/src/params.rs b/satrs/src/params.rs index 1279015..90d7028 100644 --- a/satrs/src/params.rs +++ b/satrs/src/params.rs @@ -618,6 +618,42 @@ impl From<&str> for Params { } } +/// Please note while [WritableToBeBytes] is implemented for [Params], the default implementation +/// will not be able to process store parameters. +impl WritableToBeBytes for Params { + fn raw_len(&self) -> usize { + match self { + Params::Heapless(p) => match p { + ParamsHeapless::Raw(raw) => raw.raw_len(), + ParamsHeapless::EcssEnum(enumeration) => enumeration.raw_len(), + }, + Params::Store(_) => 0, + Params::Vec(vec) => vec.len(), + Params::String(string) => string.len(), + } + } + + fn write_to_be_bytes(&self, buf: &mut [u8]) -> Result { + match self { + Params::Heapless(p) => match p { + ParamsHeapless::Raw(raw) => raw.write_to_be_bytes(buf), + ParamsHeapless::EcssEnum(enumeration) => enumeration.write_to_be_bytes(buf), + }, + Params::Store(_) => Ok(0), + Params::Vec(vec) => { + // TODO: size checks. + buf[0..vec.len()].copy_from_slice(vec); + Ok(vec.len()) + } + Params::String(string) => { + // TODO: size checks + buf[0..string.len()].copy_from_slice(string.as_bytes()); + Ok(string.len()) + } + } + } +} + #[cfg(test)] mod tests { use super::*; diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 2ee4815..8d43d9c 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -1,4 +1,7 @@ -use crate::{action::ActionRequest, TargetId}; +use crate::{ + action::{ActionId, ActionReply, ActionRequest}, + TargetId, +}; use super::verification::{TcStateAccepted, VerificationToken}; @@ -61,10 +64,17 @@ pub mod alloc_mod { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { - use crate::pus::{ - get_current_cds_short_timestamp, verification::VerificationReportingProvider, - EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, - PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, + use hashbrown::HashMap; + + use crate::{ + params::WritableToBeBytes, + pus::{ + get_current_cds_short_timestamp, + verification::{FailParams, TcStateStarted, VerificationReportingProvider}, + EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, + PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, + PusServiceHelper, + }, }; use super::*; @@ -175,6 +185,40 @@ pub mod std_mod { Ok(PusPacketHandlerResult::RequestHandled) } } + pub struct PusService8ReplyHandler { + active_requests: HashMap, + verification_reporter: VerificationReporter, + fail_data_buf: alloc::vec::Vec, + } + + impl + PusService8ReplyHandler + { + pub fn add_routed_request(&mut self, target_id: TargetId, action_id: ActionId) { + self.active_requests.insert(target_id, action_id); + } + pub fn handle_action_reply( + &mut self, + reply: ActionReply, + token: VerificationToken, + time_stamp: &[u8], + ) { + match reply { + ActionReply::CompletionFailed { id, reason } => { + reason.write_to_be_bytes(self.fail_data_buf.as_mut_slice()); + self.verification_reporter.completion_failure( + token, + FailParams::new(time_stamp, failure_code, failure_data), + ); + } + ActionReply::StepFailed { id, step, reason } => {} + ActionReply::Completed(id) => {} + ActionReply::CompletedStringId(id) => {} + ActionReply::CompletionFailedStringId { id, reason } => {} + ActionReply::StepFailedStringId { id, step, reason } => {} + } + } + } } #[cfg(test)] -- 2.43.0 From a47bec7ffec6e67e23add3889cf15e45ff8858e9 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 27 Feb 2024 13:59:54 +0100 Subject: [PATCH 14/19] PUS specific action reply --- satrs/src/action.rs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/satrs/src/action.rs b/satrs/src/action.rs index 7caeaa6..5e13356 100644 --- a/satrs/src/action.rs +++ b/satrs/src/action.rs @@ -1,3 +1,6 @@ +use satrs_shared::res_code::ResultU16; +use spacepackets::util::UnsignedByteField; + use crate::{pool::StoreAddr, TargetId}; pub type ActionId = u32; @@ -41,23 +44,18 @@ impl TargetedActionRequest { } } -/// A reply to an action request. +/// A reply to an action request specific to PUS. #[non_exhaustive] #[derive(Clone, Eq, PartialEq, Debug)] -pub enum ActionReply { - CompletionFailed(ActionId), +pub enum ActionReplyPus { + CompletionFailed { + action_id: ActionId, + error_code: ResultU16, + }, StepFailed { id: ActionId, - step: u32, + error_code: ResultU16, + step: UnsignedByteField, }, Completed(ActionId), - #[cfg(feature = "alloc")] - CompletedStringId(alloc::string::String), - #[cfg(feature = "alloc")] - CompletionFailedStringId(alloc::string::String), - #[cfg(feature = "alloc")] - StepFailedStringId { - id: alloc::string::String, - step: u32, - }, } -- 2.43.0 From 656229a542407464df286e4fc08323dcf1067b15 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 27 Feb 2024 14:33:14 +0100 Subject: [PATCH 15/19] continue the pain --- satrs/src/action.rs | 6 +- satrs/src/pus/action.rs | 114 +++++++++++++++++++++++++++++------- satrs/src/pus/mod.rs | 52 ++++++++-------- satrs/src/queue.rs | 6 +- satrs/src/tmtc/tm_helper.rs | 6 +- 5 files changed, 128 insertions(+), 56 deletions(-) diff --git a/satrs/src/action.rs b/satrs/src/action.rs index b35a48d..c51a99a 100644 --- a/satrs/src/action.rs +++ b/satrs/src/action.rs @@ -1,8 +1,4 @@ -use crate::{ - params::{Params, ParamsHeapless}, - pool::StoreAddr, - TargetId, -}; +use crate::{params::Params, pool::StoreAddr, TargetId}; pub type ActionId = u32; diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 8d43d9c..4696eed 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -1,10 +1,14 @@ use crate::{ - action::{ActionId, ActionReply, ActionRequest}, + action::{ActionId, ActionRequest}, + params::Params, TargetId, }; use super::verification::{TcStateAccepted, VerificationToken}; +use satrs_shared::res_code::ResultU16; +use spacepackets::ecss::EcssEnumU16; + #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub use std_mod::*; @@ -13,6 +17,24 @@ pub use std_mod::*; #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub use alloc_mod::*; +/// A reply to an action request, but tailored to the PUS standard verification process. +#[non_exhaustive] +#[derive(Clone, Debug)] +pub enum ActionReplyPus { + CompletionFailed { + id: ActionId, + error_code: ResultU16, + params: Params, + }, + StepFailed { + id: ActionId, + error_code: ResultU16, + step: EcssEnumU16, + params: Params, + }, + Completed(ActionId), +} + /// This trait is an abstraction for the routing of PUS service 8 action requests to a dedicated /// recipient using the generic [TargetId]. pub trait PusActionRequestRouter { @@ -65,15 +87,19 @@ pub mod alloc_mod { #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { use hashbrown::HashMap; + use spacepackets::ByteConversionError; use crate::{ params::WritableToBeBytes, pus::{ get_current_cds_short_timestamp, - verification::{FailParams, TcStateStarted, VerificationReportingProvider}, - EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, GenericRoutingError, - PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, - PusServiceHelper, + verification::{ + FailParams, FailParamsWithStep, RequestId, TcStateStarted, + VerificationReportingProvider, + }, + EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, + GenericRoutingError, PusPacketHandlerResult, PusPacketHandlingError, + PusRoutingErrorHandler, PusServiceHelper, }, }; @@ -185,8 +211,15 @@ pub mod std_mod { Ok(PusPacketHandlerResult::RequestHandled) } } + + #[derive(Debug, Clone, PartialEq, Eq)] + pub struct ActiveRequest { + action_id: ActionId, + target_id: TargetId, + } + pub struct PusService8ReplyHandler { - active_requests: HashMap, + active_requests: HashMap, verification_reporter: VerificationReporter, fail_data_buf: alloc::vec::Vec, } @@ -194,29 +227,68 @@ pub mod std_mod { impl PusService8ReplyHandler { - pub fn add_routed_request(&mut self, target_id: TargetId, action_id: ActionId) { - self.active_requests.insert(target_id, action_id); + pub fn add_routed_request( + &mut self, + request_id: RequestId, + target_id: TargetId, + action_id: ActionId, + ) { + self.active_requests.insert( + request_id, + ActiveRequest { + target_id, + action_id, + }, + ); } + pub fn handle_action_reply( &mut self, - reply: ActionReply, + reply: ActionReplyPus, token: VerificationToken, time_stamp: &[u8], - ) { + ) -> Result<(), EcssTmtcError> { match reply { - ActionReply::CompletionFailed { id, reason } => { - reason.write_to_be_bytes(self.fail_data_buf.as_mut_slice()); - self.verification_reporter.completion_failure( - token, - FailParams::new(time_stamp, failure_code, failure_data), - ); + ActionReplyPus::CompletionFailed { + id: _, + error_code, + params, + } => { + params.write_to_be_bytes(&mut self.fail_data_buf)?; + self.verification_reporter + .completion_failure( + token, + FailParams::new(time_stamp, &error_code, &self.fail_data_buf), + ) + .map_err(|e| e.0)?; + } + ActionReplyPus::StepFailed { + id: _, + error_code, + step, + params, + } => { + params.write_to_be_bytes(&mut self.fail_data_buf)?; + self.verification_reporter + .step_failure( + token, + FailParamsWithStep::new( + time_stamp, + &step, + &error_code, + &self.fail_data_buf, + ), + ) + .expect("step failure"); + } + ActionReplyPus::Completed(id) => { + self.active_requests.remove(&id); + self.verification_reporter + .completion_success(token, time_stamp) + .expect("completion success"); } - ActionReply::StepFailed { id, step, reason } => {} - ActionReply::Completed(id) => {} - ActionReply::CompletedStringId(id) => {} - ActionReply::CompletionFailedStringId { id, reason } => {} - ActionReply::StepFailedStringId { id, step, reason } => {} } + Ok(()) } } } diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index ba0ff1d..1f62c36 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -4,7 +4,7 @@ //! The satrs-example application contains various usage examples of these components. use crate::pool::{StoreAddr, StoreError}; use crate::pus::verification::{TcStateAccepted, TcStateToken, VerificationToken}; -use crate::queue::{GenericRecvError, GenericSendError}; +use crate::queue::{GenericReceiveError, GenericSendError}; use crate::ChannelId; use core::fmt::{Display, Formatter}; #[cfg(feature = "alloc")] @@ -59,26 +59,26 @@ impl<'tm> From> for PusTmWrapper<'tm> { #[derive(Debug, Clone)] pub enum EcssTmtcError { - StoreLock, Store(StoreError), + ByteConversion(ByteConversionError), Pus(PusError), CantSendAddr(StoreAddr), CantSendDirectTm, Send(GenericSendError), - Recv(GenericRecvError), + Receive(GenericReceiveError), } impl Display for EcssTmtcError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { - EcssTmtcError::StoreLock => { - write!(f, "store lock error") - } EcssTmtcError::Store(store) => { - write!(f, "store error: {store}") + write!(f, "ecss tmtc error: {store}") } - EcssTmtcError::Pus(pus_e) => { - write!(f, "PUS error: {pus_e}") + EcssTmtcError::ByteConversion(e) => { + write!(f, "ecss tmtc error: {e}") + } + EcssTmtcError::Pus(e) => { + write!(f, "ecss tmtc error: {e}") } EcssTmtcError::CantSendAddr(addr) => { write!(f, "can not send address {addr}") @@ -86,11 +86,11 @@ impl Display for EcssTmtcError { EcssTmtcError::CantSendDirectTm => { write!(f, "can not send TM directly") } - EcssTmtcError::Send(send_e) => { - write!(f, "send error {send_e}") + EcssTmtcError::Send(e) => { + write!(f, "ecss tmtc error: {e}") } - EcssTmtcError::Recv(recv_e) => { - write!(f, "recv error {recv_e}") + EcssTmtcError::Receive(e) => { + write!(f, "ecss tmtc error {e}") } } } @@ -114,9 +114,9 @@ impl From for EcssTmtcError { } } -impl From for EcssTmtcError { - fn from(value: GenericRecvError) -> Self { - Self::Recv(value) +impl From for EcssTmtcError { + fn from(value: GenericReceiveError) -> Self { + Self::Receive(value) } } @@ -125,9 +125,10 @@ impl Error for EcssTmtcError { fn source(&self) -> Option<&(dyn Error + 'static)> { match self { EcssTmtcError::Store(e) => Some(e), + EcssTmtcError::ByteConversion(e) => Some(e), EcssTmtcError::Pus(e) => Some(e), EcssTmtcError::Send(e) => Some(e), - EcssTmtcError::Recv(e) => Some(e), + EcssTmtcError::Receive(e) => Some(e), _ => None, } } @@ -368,11 +369,13 @@ mod alloc_mod { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { - use crate::pool::{PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr}; + use crate::pool::{ + PoolProvider, PoolProviderWithGuards, SharedStaticMemoryPool, StoreAddr, StoreError, + }; use crate::pus::verification::{TcStateAccepted, VerificationToken}; use crate::pus::{ EcssChannel, EcssTcAndToken, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, - GenericRecvError, GenericSendError, PusTmWrapper, TryRecvTmtcError, + GenericReceiveError, GenericSendError, PusTmWrapper, TryRecvTmtcError, }; use crate::tmtc::tm_helper::SharedTmPool; use crate::{ChannelId, TargetId}; @@ -564,7 +567,7 @@ pub mod std_mod { self.receiver.try_recv().map_err(|e| match e { TryRecvError::Empty => TryRecvTmtcError::Empty, TryRecvError::Disconnected => { - TryRecvTmtcError::Tmtc(EcssTmtcError::from(GenericRecvError::TxDisconnected)) + TryRecvTmtcError::Tmtc(EcssTmtcError::from(GenericReceiveError::TxDisconnected)) } }) } @@ -659,7 +662,7 @@ pub mod std_mod { self.receiver.try_recv().map_err(|e| match e { cb::TryRecvError::Empty => TryRecvTmtcError::Empty, cb::TryRecvError::Disconnected => TryRecvTmtcError::Tmtc(EcssTmtcError::from( - GenericRecvError::TxDisconnected, + GenericReceiveError::TxDisconnected, )), }) } @@ -805,10 +808,9 @@ pub mod std_mod { pub fn copy_tc_to_buf(&mut self, addr: StoreAddr) -> Result<(), PusPacketHandlingError> { // Keep locked section as short as possible. - let mut tc_pool = self - .shared_tc_store - .write() - .map_err(|_| PusPacketHandlingError::EcssTmtc(EcssTmtcError::StoreLock))?; + let mut tc_pool = self.shared_tc_store.write().map_err(|_| { + PusPacketHandlingError::EcssTmtc(EcssTmtcError::Store(StoreError::LockError)) + })?; let tc_size = tc_pool .len_of_data(&addr) .map_err(|e| PusPacketHandlingError::EcssTmtc(EcssTmtcError::Store(e)))?; diff --git a/satrs/src/queue.rs b/satrs/src/queue.rs index 5ba4bdc..a80f44f 100644 --- a/satrs/src/queue.rs +++ b/satrs/src/queue.rs @@ -29,12 +29,12 @@ impl Error for GenericSendError {} /// Generic error type for sending something via a message queue. #[derive(Debug, Copy, Clone)] -pub enum GenericRecvError { +pub enum GenericReceiveError { Empty, TxDisconnected, } -impl Display for GenericRecvError { +impl Display for GenericReceiveError { fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { Self::TxDisconnected => { @@ -48,7 +48,7 @@ impl Display for GenericRecvError { } #[cfg(feature = "std")] -impl Error for GenericRecvError {} +impl Error for GenericReceiveError {} #[cfg(feature = "std")] impl From> for GenericSendError { diff --git a/satrs/src/tmtc/tm_helper.rs b/satrs/src/tmtc/tm_helper.rs index 192d574..9de359b 100644 --- a/satrs/src/tmtc/tm_helper.rs +++ b/satrs/src/tmtc/tm_helper.rs @@ -8,7 +8,9 @@ pub use std_mod::*; #[cfg(feature = "std")] pub mod std_mod { - use crate::pool::{PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StoreAddr}; + use crate::pool::{ + PoolProvider, SharedStaticMemoryPool, StaticMemoryPool, StoreAddr, StoreError, + }; use crate::pus::EcssTmtcError; use spacepackets::ecss::tm::PusTmCreator; use spacepackets::ecss::WritablePusPacket; @@ -34,7 +36,7 @@ pub mod std_mod { } pub fn add_pus_tm(&self, pus_tm: &PusTmCreator) -> Result { - let mut pg = self.0.write().map_err(|_| EcssTmtcError::StoreLock)?; + let mut pg = self.0.write().map_err(|_| StoreError::LockError)?; let addr = pg.free_element(pus_tm.len_written(), |buf| { pus_tm .write_to_bytes(buf) -- 2.43.0 From a7e614dfb3513175855f8c95084b595527f6ccbf Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 27 Feb 2024 16:27:36 +0100 Subject: [PATCH 16/19] it's some sort of reply handler --- satrs/src/pus/action.rs | 64 ++++++++++++++++++++++++++++++++--------- satrs/src/pus/mod.rs | 6 ++++ 2 files changed, 57 insertions(+), 13 deletions(-) diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 4696eed..95c200c 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -86,9 +86,6 @@ pub mod alloc_mod { #[cfg(feature = "std")] #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] pub mod std_mod { - use hashbrown::HashMap; - use spacepackets::ByteConversionError; - use crate::{ params::WritableToBeBytes, pus::{ @@ -102,6 +99,9 @@ pub mod std_mod { PusRoutingErrorHandler, PusServiceHelper, }, }; + use hashbrown::HashMap; + use spacepackets::time::UnixTimestamp; + use std::time::SystemTimeError; use super::*; @@ -214,14 +214,16 @@ pub mod std_mod { #[derive(Debug, Clone, PartialEq, Eq)] pub struct ActiveRequest { - action_id: ActionId, - target_id: TargetId, + token: VerificationToken, + start_time: UnixTimestamp, + timeout_seconds: u32, } pub struct PusService8ReplyHandler { active_requests: HashMap, verification_reporter: VerificationReporter, fail_data_buf: alloc::vec::Vec, + current_time: UnixTimestamp, } impl @@ -230,18 +232,52 @@ pub mod std_mod { pub fn add_routed_request( &mut self, request_id: RequestId, - target_id: TargetId, - action_id: ActionId, + token: VerificationToken, + timeout_seconds: u32, ) { self.active_requests.insert( request_id, ActiveRequest { - target_id, - action_id, + token, + start_time: self.current_time, + timeout_seconds, }, ); } + #[cfg(feature = "std")] + #[cfg_attr(doc_cfg, doc(cfg(feature = "std")))] + pub fn update_time_from_now(&mut self) -> Result<(), SystemTimeError> { + self.current_time = UnixTimestamp::from_now()?; + Ok(()) + } + + pub fn check_for_timeouts(&mut self, time_stamp: &[u8]) -> Result<(), EcssTmtcError> { + for (_req_id, active_req) in self.active_requests.iter() { + // TODO: Simplified until spacepackets update. + let diff = + (self.current_time.unix_seconds - active_req.start_time.unix_seconds) as u32; + if diff > active_req.timeout_seconds { + self.handle_timeout(active_req, time_stamp); + } + } + Ok(()) + } + + pub fn handle_timeout(&self, active_request: &ActiveRequest, time_stamp: &[u8]) { + self.verification_reporter + .completion_failure( + active_request.token, + FailParams::new( + time_stamp, + // WTF, what failure code? + &ResultU16::new(0, 0), + &[], + ), + ) + .unwrap(); + } + pub fn handle_action_reply( &mut self, reply: ActionReplyPus, @@ -254,6 +290,7 @@ pub mod std_mod { error_code, params, } => { + self.active_requests.remove(&token.req_id()); params.write_to_be_bytes(&mut self.fail_data_buf)?; self.verification_reporter .completion_failure( @@ -268,6 +305,7 @@ pub mod std_mod { step, params, } => { + self.active_requests.remove(&token.req_id()); params.write_to_be_bytes(&mut self.fail_data_buf)?; self.verification_reporter .step_failure( @@ -279,13 +317,13 @@ pub mod std_mod { &self.fail_data_buf, ), ) - .expect("step failure"); + .map_err(|e| e.0)?; } - ActionReplyPus::Completed(id) => { - self.active_requests.remove(&id); + ActionReplyPus::Completed(_id) => { + self.active_requests.remove(&token.req_id()); self.verification_reporter .completion_success(token, time_stamp) - .expect("completion success"); + .map_err(|e| e.0)?; } } Ok(()) diff --git a/satrs/src/pus/mod.rs b/satrs/src/pus/mod.rs index 43f8462..77a948c 100644 --- a/satrs/src/pus/mod.rs +++ b/satrs/src/pus/mod.rs @@ -114,6 +114,12 @@ impl From for EcssTmtcError { } } +impl From for EcssTmtcError { + fn from(value: ByteConversionError) -> Self { + Self::ByteConversion(value) + } +} + impl From for EcssTmtcError { fn from(value: GenericReceiveError) -> Self { Self::Receive(value) -- 2.43.0 From 9f82c57a951f1710cc1b04d514617f1df69435b2 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 27 Feb 2024 16:52:14 +0100 Subject: [PATCH 17/19] actually need to do something with the IDs --- satrs/src/pus/action.rs | 57 ++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 20 deletions(-) diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index 95c200c..ad81f9c 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -4,7 +4,7 @@ use crate::{ TargetId, }; -use super::verification::{TcStateAccepted, VerificationToken}; +use super::verification::{RequestId, TcStateAccepted, VerificationToken}; use satrs_shared::res_code::ResultU16; use spacepackets::ecss::EcssEnumU16; @@ -17,22 +17,36 @@ pub use std_mod::*; #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))] pub use alloc_mod::*; +#[derive(Clone, Debug)] +pub struct ActionRequestWithId { + pub req_id: RequestId, + pub request: ActionRequest, +} + +#[derive(Clone, Debug)] +pub struct ActionReplyPusWithIds { + pub action_id: ActionId, + pub req_id: RequestId, + pub reply: ActionReplyPus, +} + /// A reply to an action request, but tailored to the PUS standard verification process. #[non_exhaustive] #[derive(Clone, Debug)] pub enum ActionReplyPus { + Completed, + StepSuccess { + step: EcssEnumU16, + }, CompletionFailed { - id: ActionId, error_code: ResultU16, params: Params, }, StepFailed { - id: ActionId, error_code: ResultU16, step: EcssEnumU16, params: Params, }, - Completed(ActionId), } /// This trait is an abstraction for the routing of PUS service 8 action requests to a dedicated @@ -280,36 +294,34 @@ pub mod std_mod { pub fn handle_action_reply( &mut self, - reply: ActionReplyPus, - token: VerificationToken, + action_reply_with_ids: ActionReplyPusWithIds, time_stamp: &[u8], ) -> Result<(), EcssTmtcError> { - match reply { - ActionReplyPus::CompletionFailed { - id: _, - error_code, - params, - } => { - self.active_requests.remove(&token.req_id()); + let active_req = self.active_requests.get(&action_reply_with_ids.req_id); + if active_req.is_none() { + // TODO: This is an unexpected reply. We need to deal with this somehow. + } + let active_req = active_req.unwrap(); + match action_reply_with_ids.reply { + ActionReplyPus::CompletionFailed { error_code, params } => { params.write_to_be_bytes(&mut self.fail_data_buf)?; self.verification_reporter .completion_failure( - token, + active_req.token, FailParams::new(time_stamp, &error_code, &self.fail_data_buf), ) .map_err(|e| e.0)?; + self.active_requests.remove(&action_reply_with_ids.req_id); } ActionReplyPus::StepFailed { - id: _, error_code, step, params, } => { - self.active_requests.remove(&token.req_id()); params.write_to_be_bytes(&mut self.fail_data_buf)?; self.verification_reporter .step_failure( - token, + active_req.token, FailParamsWithStep::new( time_stamp, &step, @@ -318,12 +330,17 @@ pub mod std_mod { ), ) .map_err(|e| e.0)?; + self.active_requests.remove(&action_reply_with_ids.req_id); } - ActionReplyPus::Completed(_id) => { - self.active_requests.remove(&token.req_id()); + ActionReplyPus::Completed => { self.verification_reporter - .completion_success(token, time_stamp) + .completion_success(active_req.token, time_stamp) .map_err(|e| e.0)?; + self.active_requests.remove(&action_reply_with_ids.req_id); + } + ActionReplyPus::StepSuccess { step } => { + self.verification_reporter + .step_success(&active_req.token, time_stamp, step)?; } } Ok(()) -- 2.43.0 From dca573e8a9c74d4d55be5141958fbee269a41d1d Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Feb 2024 11:05:22 +0100 Subject: [PATCH 18/19] use generic request ID type --- satrs/src/pus/action.rs | 26 +++++++++++++++----------- satrs/src/pus/verification.rs | 16 ++++++++++++++++ satrs/src/request.rs | 5 +++++ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/satrs/src/pus/action.rs b/satrs/src/pus/action.rs index ad81f9c..1526843 100644 --- a/satrs/src/pus/action.rs +++ b/satrs/src/pus/action.rs @@ -1,10 +1,11 @@ use crate::{ action::{ActionId, ActionRequest}, params::Params, + request::RequestId, TargetId, }; -use super::verification::{RequestId, TcStateAccepted, VerificationToken}; +use super::verification::{TcStateAccepted, VerificationToken}; use satrs_shared::res_code::ResultU16; use spacepackets::ecss::EcssEnumU16; @@ -19,14 +20,14 @@ pub use alloc_mod::*; #[derive(Clone, Debug)] pub struct ActionRequestWithId { - pub req_id: RequestId, + pub request_id: RequestId, pub request: ActionRequest, } #[derive(Clone, Debug)] pub struct ActionReplyPusWithIds { + pub request_id: RequestId, pub action_id: ActionId, - pub req_id: RequestId, pub reply: ActionReplyPus, } @@ -105,13 +106,13 @@ pub mod std_mod { pus::{ get_current_cds_short_timestamp, verification::{ - FailParams, FailParamsWithStep, RequestId, TcStateStarted, - VerificationReportingProvider, + self, FailParams, FailParamsWithStep, TcStateStarted, VerificationReportingProvider, }, EcssTcInMemConverter, EcssTcReceiverCore, EcssTmSenderCore, EcssTmtcError, GenericRoutingError, PusPacketHandlerResult, PusPacketHandlingError, PusRoutingErrorHandler, PusServiceHelper, }, + request::RequestId, }; use hashbrown::HashMap; use spacepackets::time::UnixTimestamp; @@ -245,12 +246,12 @@ pub mod std_mod { { pub fn add_routed_request( &mut self, - request_id: RequestId, + request_id: verification::RequestId, token: VerificationToken, timeout_seconds: u32, ) { self.active_requests.insert( - request_id, + request_id.into(), ActiveRequest { token, start_time: self.current_time, @@ -297,7 +298,7 @@ pub mod std_mod { action_reply_with_ids: ActionReplyPusWithIds, time_stamp: &[u8], ) -> Result<(), EcssTmtcError> { - let active_req = self.active_requests.get(&action_reply_with_ids.req_id); + let active_req = self.active_requests.get(&action_reply_with_ids.request_id); if active_req.is_none() { // TODO: This is an unexpected reply. We need to deal with this somehow. } @@ -311,7 +312,8 @@ pub mod std_mod { FailParams::new(time_stamp, &error_code, &self.fail_data_buf), ) .map_err(|e| e.0)?; - self.active_requests.remove(&action_reply_with_ids.req_id); + self.active_requests + .remove(&action_reply_with_ids.request_id); } ActionReplyPus::StepFailed { error_code, @@ -330,13 +332,15 @@ pub mod std_mod { ), ) .map_err(|e| e.0)?; - self.active_requests.remove(&action_reply_with_ids.req_id); + self.active_requests + .remove(&action_reply_with_ids.request_id); } ActionReplyPus::Completed => { self.verification_reporter .completion_success(active_req.token, time_stamp) .map_err(|e| e.0)?; - self.active_requests.remove(&action_reply_with_ids.req_id); + self.active_requests + .remove(&action_reply_with_ids.request_id); } ActionReplyPus::StepSuccess { step } => { self.verification_reporter diff --git a/satrs/src/pus/verification.rs b/satrs/src/pus/verification.rs index 89ce9b9..2c05482 100644 --- a/satrs/src/pus/verification.rs +++ b/satrs/src/pus/verification.rs @@ -173,6 +173,22 @@ impl RequestId { } } +impl From for RequestId { + fn from(value: u32) -> Self { + Self { + version_number: ((value >> 29) & 0b111) as u8, + packet_id: PacketId::from(((value >> 16) & 0xffff) as u16), + psc: PacketSequenceCtrl::from((value & 0xffff) as u16), + } + } +} + +impl From for u32 { + fn from(value: RequestId) -> Self { + value.raw() + } +} + /// If a verification operation fails, the passed token will be returned as well. This allows /// re-trying the operation at a later point. #[derive(Debug, Clone)] diff --git a/satrs/src/request.rs b/satrs/src/request.rs index 0ca9d03..d552446 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -13,6 +13,11 @@ use spacepackets::{ use crate::{queue::GenericTargetedMessagingError, ChannelId, TargetId}; +/// Generic request ID type. Requests can be associated with an ID to have a unique identifier +/// for them. This can be useful for tasks like tracking their progress. +pub type RequestId = u32; + +/// CCSDS APID type definition. Please note that the APID is a 14 bit value. pub type Apid = u16; #[derive(Debug, Clone, PartialEq, Eq)] -- 2.43.0 From 0647abc9c67561ffae65968e3d815e71b0871175 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Wed, 28 Feb 2024 11:29:08 +0100 Subject: [PATCH 19/19] added new RequestId --- satrs/src/mode_tree.rs | 113 +++++++++++++++++++++++++-------------- satrs/src/request.rs | 57 +++++++++++--------- satrs/tests/mode_tree.rs | 89 ++++++++++++++++++++---------- 3 files changed, 165 insertions(+), 94 deletions(-) diff --git a/satrs/src/mode_tree.rs b/satrs/src/mode_tree.rs index 62e622d..3da5c26 100644 --- a/satrs/src/mode_tree.rs +++ b/satrs/src/mode_tree.rs @@ -6,9 +6,9 @@ use crate::{ mode::{Mode, ModeAndSubmode, ModeReply, ModeRequest, Submode}, queue::GenericTargetedMessagingError, request::{ - MessageReceiver, MessageReceiverWithId, MessageSender, MessageSenderAndReceiver, - MessageSenderMap, MessageSenderMapWithId, MessageWithSenderId, - RequestAndReplySenderAndReceiver, + GenericMessage, MessageReceiver, MessageReceiverWithId, MessageSender, + MessageSenderAndReceiver, MessageSenderMap, MessageSenderMapWithId, + RequestAndReplySenderAndReceiver, RequestId, }, ChannelId, }; @@ -44,6 +44,7 @@ pub trait ModeRequestSender { fn local_channel_id(&self) -> ChannelId; fn send_mode_request( &self, + request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError>; @@ -54,6 +55,7 @@ pub trait ModeReplySender { fn send_mode_reply( &self, + request_id: RequestId, target_id: ChannelId, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError>; @@ -62,23 +64,24 @@ pub trait ModeReplySender { pub trait ModeRequestReceiver { fn try_recv_mode_request( &self, - ) -> Result>, GenericTargetedMessagingError>; + ) -> Result>, GenericTargetedMessagingError>; } pub trait ModeReplyReceiver { fn try_recv_mode_reply( &self, - ) -> Result>, GenericTargetedMessagingError>; + ) -> Result>, GenericTargetedMessagingError>; } impl> MessageSenderMap { pub fn send_mode_request( &self, + request_id: RequestId, local_id: ChannelId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(local_id, target_id, request) + self.send_message(request_id, local_id, target_id, request) } pub fn add_request_target(&mut self, target_id: ChannelId, request_sender: S) { @@ -89,11 +92,12 @@ impl> MessageSenderMap { impl> MessageSenderMap { pub fn send_mode_reply( &self, + request_id: RequestId, local_id: ChannelId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(local_id, target_id, request) + self.send_message(request_id, local_id, target_id, request) } pub fn add_reply_target(&mut self, target_id: ChannelId, request_sender: S) { @@ -104,10 +108,11 @@ impl> MessageSenderMap { impl> ModeReplySender for MessageSenderMapWithId { fn send_mode_reply( &self, + request_id: RequestId, target_channel_id: ChannelId, reply: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(target_channel_id, reply) + self.send_message(request_id, target_channel_id, reply) } fn local_channel_id(&self) -> ChannelId { @@ -122,17 +127,18 @@ impl> ModeRequestSender for MessageSenderMapWithId fn send_mode_request( &self, + request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.send_message(target_id, request) + self.send_message(request_id, target_id, request) } } impl> ModeReplyReceiver for MessageReceiverWithId { fn try_recv_mode_reply( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } } @@ -142,7 +148,7 @@ impl> ModeRequestReceiver { fn try_recv_mode_request( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.try_recv_message() } } @@ -156,11 +162,16 @@ impl, R: MessageReceiver> ModeRequestS fn send_mode_request( &self, + request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map - .send_mode_request(self.local_channel_id(), target_id, request) + self.message_sender_map.send_mode_request( + request_id, + self.local_channel_id(), + target_id, + request, + ) } } @@ -173,11 +184,16 @@ impl, R: MessageReceiver> ModeReplySende fn send_mode_reply( &self, + request_id: RequestId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map - .send_mode_reply(self.local_channel_id(), target_id, request) + self.message_sender_map.send_mode_reply( + request_id, + self.local_channel_id(), + target_id, + request, + ) } } @@ -186,7 +202,7 @@ impl, R: MessageReceiver> ModeReplyReceiver { fn try_recv_mode_reply( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.message_receiver .try_recv_message(self.local_channel_id_generic()) } @@ -196,7 +212,7 @@ impl, R: MessageReceiver> ModeRequestRecei { fn try_recv_mode_request( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.message_receiver .try_recv_message(self.local_channel_id_generic()) } @@ -204,37 +220,37 @@ impl, R: MessageReceiver> ModeRequestRecei pub type ModeRequestHandlerConnector = MessageSenderAndReceiver; pub type MpscModeRequestHandlerConnector = ModeRequestHandlerConnector< - mpsc::Sender>, - mpsc::Receiver>, + mpsc::Sender>, + mpsc::Receiver>, >; pub type MpscBoundedModeRequestHandlerConnector = ModeRequestHandlerConnector< - mpsc::SyncSender>, - mpsc::Receiver>, + mpsc::SyncSender>, + mpsc::Receiver>, >; pub type ModeRequestorConnector = MessageSenderAndReceiver; pub type MpscModeRequestorConnector = ModeRequestorConnector< - mpsc::Sender>, - mpsc::Receiver>, + mpsc::Sender>, + mpsc::Receiver>, >; pub type MpscBoundedModeRequestorConnector = ModeRequestorConnector< - mpsc::SyncSender>, - mpsc::Receiver>, + mpsc::SyncSender>, + mpsc::Receiver>, >; pub type ModeConnector = RequestAndReplySenderAndReceiver; pub type MpscModeConnector = ModeConnector< - mpsc::Sender>, - mpsc::Receiver>, - mpsc::Sender>, - mpsc::Receiver>, + mpsc::Sender>, + mpsc::Receiver>, + mpsc::Sender>, + mpsc::Receiver>, >; pub type MpscBoundedModeConnector = ModeConnector< - mpsc::SyncSender>, - mpsc::Receiver>, - mpsc::SyncSender>, - mpsc::Receiver>, + mpsc::SyncSender>, + mpsc::Receiver>, + mpsc::SyncSender>, + mpsc::Receiver>, >; impl< @@ -279,11 +295,16 @@ impl< fn send_mode_request( &self, + request_id: RequestId, target_id: ChannelId, request: ModeRequest, ) -> Result<(), GenericTargetedMessagingError> { - self.request_sender_map - .send_mode_request(self.local_channel_id(), target_id, request) + self.request_sender_map.send_mode_request( + request_id, + self.local_channel_id(), + target_id, + request, + ) } } @@ -301,11 +322,16 @@ impl< fn send_mode_reply( &self, + request_id: RequestId, target_id: ChannelId, request: ModeReply, ) -> Result<(), GenericTargetedMessagingError> { - self.reply_sender_map - .send_mode_reply(self.local_channel_id(), target_id, request) + self.reply_sender_map.send_mode_reply( + request_id, + self.local_channel_id(), + target_id, + request, + ) } } @@ -319,7 +345,7 @@ impl< { fn try_recv_mode_reply( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.reply_receiver .try_recv_message(self.local_channel_id_generic()) } @@ -335,7 +361,7 @@ impl< { fn try_recv_mode_request( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.request_receiver .try_recv_message(self.local_channel_id_generic()) } @@ -357,9 +383,14 @@ impl From for ModeError { } pub trait ModeRequestHandler: ModeProvider { - fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError>; + fn start_transition( + &mut self, + request_id: RequestId, + sender_id: ChannelId, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), ModeError>; - fn announce_mode(&self, recursive: bool); + fn announce_mode(&self, request_id: RequestId, sender_id: ChannelId, recursive: bool); fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError>; } diff --git a/satrs/src/request.rs b/satrs/src/request.rs index d552446..438cc25 100644 --- a/satrs/src/request.rs +++ b/satrs/src/request.rs @@ -118,25 +118,32 @@ impl fmt::Display for TargetAndApidId { } } -pub struct MessageWithSenderId { +/// Generic message type which is associated with a sender using a [ChannelId] and associated +/// with a request using a [RequestId]. +pub struct GenericMessage { pub sender_id: ChannelId, + pub request_id: RequestId, pub message: MSG, } -impl MessageWithSenderId { - pub fn new(sender_id: ChannelId, message: MSG) -> Self { - Self { sender_id, message } +impl GenericMessage { + pub fn new(request_id: RequestId, sender_id: ChannelId, message: MSG) -> Self { + Self { + request_id, + sender_id, + message, + } } } /// Generic trait for objects which can send targeted messages. pub trait MessageSender: Send { - fn send(&self, message: MessageWithSenderId) -> Result<(), GenericTargetedMessagingError>; + fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError>; } // Generic trait for objects which can receive targeted messages. pub trait MessageReceiver { - fn try_recv(&self) -> Result>, GenericTargetedMessagingError>; + fn try_recv(&self) -> Result>, GenericTargetedMessagingError>; } #[cfg(feature = "std")] @@ -152,23 +159,17 @@ mod std_mod { ChannelId, }; - use super::{MessageReceiver, MessageSender, MessageWithSenderId}; + use super::{GenericMessage, MessageReceiver, MessageSender, RequestId}; - impl MessageSender for mpsc::Sender> { - fn send( - &self, - message: MessageWithSenderId, - ) -> Result<(), GenericTargetedMessagingError> { + impl MessageSender for mpsc::Sender> { + fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError> { self.send(message) .map_err(|_| GenericSendError::RxDisconnected)?; Ok(()) } } - impl MessageSender for mpsc::SyncSender> { - fn send( - &self, - message: MessageWithSenderId, - ) -> Result<(), GenericTargetedMessagingError> { + impl MessageSender for mpsc::SyncSender> { + fn send(&self, message: GenericMessage) -> Result<(), GenericTargetedMessagingError> { if let Err(e) = self.try_send(message) { match e { mpsc::TrySendError::Full(_) => { @@ -202,6 +203,7 @@ mod std_mod { pub fn send_message( &self, + request_id: RequestId, local_channel_id: ChannelId, target_channel_id: ChannelId, message: MSG, @@ -210,7 +212,7 @@ mod std_mod { self.0 .get(&target_channel_id) .unwrap() - .send(MessageWithSenderId::new(local_channel_id, message)) + .send(GenericMessage::new(request_id, local_channel_id, message)) .map_err(|_| GenericSendError::RxDisconnected)?; return Ok(()); } @@ -233,11 +235,16 @@ mod std_mod { pub fn send_message( &self, + request_id: RequestId, target_channel_id: ChannelId, message: MSG, ) -> Result<(), GenericTargetedMessagingError> { - self.message_sender_map - .send_message(self.local_channel_id, target_channel_id, message) + 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: ChannelId, message_sender: S) { @@ -246,10 +253,8 @@ mod std_mod { } } - impl MessageReceiver for mpsc::Receiver> { - fn try_recv( - &self, - ) -> Result>, GenericTargetedMessagingError> { + impl MessageReceiver for mpsc::Receiver> { + fn try_recv(&self) -> Result>, GenericTargetedMessagingError> { match self.try_recv() { Ok(msg) => Ok(Some(msg)), Err(e) => match e { @@ -274,7 +279,7 @@ mod std_mod { pub fn try_recv_message( &self, _local_id: ChannelId, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.0.try_recv() } } @@ -305,7 +310,7 @@ mod std_mod { impl> MessageReceiverWithId { pub fn try_recv_message( &self, - ) -> Result>, GenericTargetedMessagingError> { + ) -> Result>, GenericTargetedMessagingError> { self.reply_receiver.0.try_recv() } } diff --git a/satrs/tests/mode_tree.rs b/satrs/tests/mode_tree.rs index 3c8680f..a66b774 100644 --- a/satrs/tests/mode_tree.rs +++ b/satrs/tests/mode_tree.rs @@ -1,6 +1,8 @@ +use core::cell::Cell; use std::{println, sync::mpsc}; use satrs::mode_tree::ModeRequestSender; +use satrs::request::RequestId; use satrs::{ mode::{ModeAndSubmode, ModeReply, ModeRequest}, mode_tree::{ @@ -9,7 +11,7 @@ use satrs::{ MpscBoundedModeRequestorConnector, }, queue::GenericTargetedMessagingError, - request::MessageWithSenderId, + request::GenericMessage, ChannelId, }; use std::string::{String, ToString}; @@ -22,6 +24,7 @@ pub enum TestChannelId { } struct PusModeService { + pub request_id_counter: Cell, pub mode_node: MpscBoundedModeRequestorConnector, } @@ -29,10 +32,13 @@ impl PusModeService { pub fn send_announce_mode_cmd_to_assy(&self) { self.mode_node .send_mode_request( + self.request_id_counter.get(), TestChannelId::Assembly as u32, ModeRequest::AnnounceModeRecursive, ) .unwrap(); + self.request_id_counter + .replace(self.request_id_counter.get() + 1); } } @@ -40,7 +46,7 @@ struct TestDevice { pub name: String, pub mode_node: MpscBoundedModeRequestHandlerConnector, pub mode_and_submode: ModeAndSubmode, - pub mode_req_commander: Option, + pub mode_requestor_info: Option<(RequestId, ChannelId)>, } impl TestDevice { @@ -49,21 +55,27 @@ impl TestDevice { } pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { - if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { - match request_and_id.message { + if let Some(request) = self.mode_node.try_recv_mode_request()? { + match request.message { ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(mode_and_submode).unwrap(); - self.mode_req_commander = Some(request_and_id.sender_id); + self.start_transition(request.request_id, request.sender_id, mode_and_submode) + .unwrap(); + self.mode_requestor_info = Some((request.request_id, request.sender_id)); } ModeRequest::ReadMode => self .mode_node .send_mode_reply( - request_and_id.sender_id, + request.request_id, + request.sender_id, ModeReply::ModeReply(self.mode_and_submode), ) .unwrap(), - ModeRequest::AnnounceMode => self.announce_mode(false), - ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + ModeRequest::AnnounceMode => { + self.announce_mode(request.request_id, request.sender_id, false) + } + ModeRequest::AnnounceModeRecursive => { + self.announce_mode(request.request_id, request.sender_id, true) + } } } Ok(()) @@ -76,13 +88,18 @@ impl ModeProvider for TestDevice { } } impl ModeRequestHandler for TestDevice { - fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { + fn start_transition( + &mut self, + _request_id: RequestId, + _sender_id: ChannelId, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), ModeError> { self.mode_and_submode = mode_and_submode; self.handle_mode_reached()?; Ok(()) } - fn announce_mode(&self, _recursive: bool) { + fn announce_mode(&self, _request_id: RequestId, _sender_id: ChannelId, _recursive: bool) { println!( "{}: announcing mode: {:?}", self.name, self.mode_and_submode @@ -90,8 +107,10 @@ impl ModeRequestHandler for TestDevice { } fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + let (req_id, sender_id) = self.mode_requestor_info.unwrap(); self.mode_node.send_mode_reply( - self.mode_req_commander.unwrap(), + req_id, + sender_id, ModeReply::ModeReply(self.mode_and_submode), )?; Ok(()) @@ -100,7 +119,7 @@ impl ModeRequestHandler for TestDevice { struct TestAssembly { pub mode_node: MpscBoundedModeConnector, - pub mode_req_commander: Option, + pub mode_requestor_info: Option<(RequestId, ChannelId)>, pub mode_and_submode: ModeAndSubmode, pub target_mode_and_submode: Option, } @@ -118,21 +137,26 @@ impl TestAssembly { } pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> { - if let Some(request_and_id) = self.mode_node.try_recv_mode_request()? { - match request_and_id.message { + if let Some(request) = self.mode_node.try_recv_mode_request()? { + match request.message { ModeRequest::SetMode(mode_and_submode) => { - self.start_transition(mode_and_submode).unwrap(); - self.mode_req_commander = Some(request_and_id.sender_id); + self.start_transition(request.request_id, request.sender_id, mode_and_submode) + .unwrap(); } ModeRequest::ReadMode => self .mode_node .send_mode_reply( - request_and_id.sender_id, + request.request_id, + request.sender_id, ModeReply::ModeReply(self.mode_and_submode), ) .unwrap(), - ModeRequest::AnnounceMode => self.announce_mode(false), - ModeRequest::AnnounceModeRecursive => self.announce_mode(true), + ModeRequest::AnnounceMode => { + self.announce_mode(request.request_id, request.sender_id, false) + } + ModeRequest::AnnounceModeRecursive => { + self.announce_mode(request.request_id, request.sender_id, true) + } } } Ok(()) @@ -162,16 +186,23 @@ impl TestAssembly { } impl ModeRequestHandler for TestAssembly { - fn start_transition(&mut self, mode_and_submode: ModeAndSubmode) -> Result<(), ModeError> { + fn start_transition( + &mut self, + request_id: RequestId, + sender_id: ChannelId, + mode_and_submode: ModeAndSubmode, + ) -> Result<(), ModeError> { + self.mode_requestor_info = Some((request_id, sender_id)); self.target_mode_and_submode = Some(mode_and_submode); Ok(()) } - fn announce_mode(&self, recursive: bool) { + fn announce_mode(&self, request_id: RequestId, _sender_id: ChannelId, recursive: bool) { println!( "TestAssembly: Announcing mode (recursively: {}): {:?}", recursive, self.mode_and_submode ); + // self.mode_requestor_info = Some((request_id, sender_id)); let mut mode_request = ModeRequest::AnnounceMode; if recursive { mode_request = ModeRequest::AnnounceModeRecursive; @@ -182,7 +213,8 @@ impl ModeRequestHandler for TestAssembly { .iter() .for_each(|(_, sender)| { sender - .send(MessageWithSenderId::new( + .send(GenericMessage::new( + request_id, self.mode_node.local_channel_id_generic(), mode_request, )) @@ -191,8 +223,10 @@ impl ModeRequestHandler for TestAssembly { } fn handle_mode_reached(&mut self) -> Result<(), GenericTargetedMessagingError> { + let (req_id, sender_id) = self.mode_requestor_info.unwrap(); self.mode_node.send_mode_reply( - self.mode_req_commander.unwrap(), + req_id, + sender_id, ModeReply::ModeReply(self.mode_and_submode), )?; Ok(()) @@ -260,22 +294,23 @@ fn main() { let mut device1 = TestDevice { name: "Test Device 1".to_string(), mode_node: mode_node_dev1, - mode_req_commander: None, + mode_requestor_info: None, mode_and_submode: ModeAndSubmode::new(0, 0), }; let mut device2 = TestDevice { name: "Test Device 2".to_string(), mode_node: mode_node_dev2, - mode_req_commander: None, + mode_requestor_info: None, mode_and_submode: ModeAndSubmode::new(0, 0), }; let mut assy = TestAssembly { mode_node: mode_node_assy, - mode_req_commander: None, + mode_requestor_info: None, mode_and_submode: ModeAndSubmode::new(0, 0), target_mode_and_submode: None, }; let pus_service = PusModeService { + request_id_counter: Cell::new(0), mode_node: mode_node_pus, }; -- 2.43.0