Compare commits

...

3 Commits

Author SHA1 Message Date
f4aff4780a continue CCSDS scheduler 2025-11-17 11:34:27 +01:00
f8628a5279 Merge remote-tracking branch 'origin/main' into ccsds-scheduler 2025-11-17 11:26:11 +01:00
Robin Mueller
d7b8a8c1d1 start new CCSDS scheduler 2025-10-20 12:06:18 +02:00
8 changed files with 257 additions and 184 deletions

View File

@@ -14,12 +14,12 @@ test:
embedded: embedded:
cargo check -p satrs --target=thumbv7em-none-eabihf --no-default-features cargo check -p satrs --target=thumbv7em-none-eabihf --no-default-features
fmt:
cargo fmt --all
check-fmt: check-fmt:
cargo fmt --all -- --check cargo fmt --all -- --check
fmt:
cargo fmt --all
clippy: clippy:
cargo clippy -- -D warnings cargo clippy -- -D warnings

View File

@@ -5,7 +5,7 @@ use crate::pus::create_verification_reporter;
use crate::tmtc::sender::TmTcSender; use crate::tmtc::sender::TmTcSender;
use log::info; use log::info;
use satrs::pool::{PoolProvider, StaticMemoryPool}; use satrs::pool::{PoolProvider, StaticMemoryPool};
use satrs::pus::scheduler::{PusScheduler, TcInfo}; use satrs::pus::scheduler::{PusSchedulerAlloc, TcInfo};
use satrs::pus::scheduler_srv::PusSchedServiceHandler; use satrs::pus::scheduler_srv::PusSchedServiceHandler;
use satrs::pus::verification::VerificationReporter; use satrs::pus::verification::VerificationReporter;
use satrs::pus::{ use satrs::pus::{
@@ -86,7 +86,7 @@ pub struct SchedulingServiceWrapper {
TmTcSender, TmTcSender,
EcssTcCacher, EcssTcCacher,
VerificationReporter, VerificationReporter,
PusScheduler, PusSchedulerAlloc,
>, >,
pub sched_tc_pool: StaticMemoryPool, pub sched_tc_pool: StaticMemoryPool,
pub releaser_buf: [u8; 4096], pub releaser_buf: [u8; 4096],
@@ -179,7 +179,7 @@ pub fn create_scheduler_service(
pus_sched_rx: mpsc::Receiver<EcssTcAndToken>, pus_sched_rx: mpsc::Receiver<EcssTcAndToken>,
sched_tc_pool: StaticMemoryPool, sched_tc_pool: StaticMemoryPool,
) -> SchedulingServiceWrapper { ) -> SchedulingServiceWrapper {
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) let scheduler = PusSchedulerAlloc::new_with_current_init_time(Duration::from_secs(5))
.expect("Creating PUS Scheduler failed"); .expect("Creating PUS Scheduler failed");
let pus_11_handler = PusSchedServiceHandler::new( let pus_11_handler = PusSchedServiceHandler::new(
PusServiceHelper::new( PusServiceHelper::new(

1
satrs/src/ccsds/mod.rs Normal file
View File

@@ -0,0 +1 @@
pub mod scheduler;

View File

@@ -0,0 +1,147 @@
use core::{hash::Hash, time::Duration};
#[cfg(feature = "alloc")]
pub use alloc_mod::*;
use spacepackets::{
ByteConversionError, CcsdsPacketIdAndPsc,
time::{TimestampError, UnixTime},
};
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum ScheduleError {
/// The release time is within the time-margin added on top of the current time.
/// The first parameter is the current time, the second one the time margin, and the third one
/// the release time.
#[error("release time in margin")]
ReleaseTimeInTimeMargin {
current_time: UnixTime,
time_margin: Duration,
release_time: UnixTime,
},
/// Nested time-tagged commands are not allowed.
#[error("nested scheduled tc")]
NestedScheduledTc,
#[error("tc data empty")]
TcDataEmpty,
#[error("scheduler is full")]
Full,
#[error("timestamp error: {0}")]
TimestampError(#[from] TimestampError),
#[error("wrong subservice number {0}")]
WrongSubservice(u8),
#[error("wrong service number {0}")]
WrongService(u8),
#[error("byte conversion error: {0}")]
ByteConversionError(#[from] ByteConversionError),
}
#[derive(Debug, PartialEq, Eq, Clone)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct CcsdsSchedulePacketId {
pub base: CcsdsPacketIdAndPsc,
pub crc16: Option<u16>,
}
impl Hash for CcsdsSchedulePacketId {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
self.base.hash(state);
self.crc16.hash(state);
}
}
#[cfg(feature = "alloc")]
pub mod alloc_mod {
use core::time::Duration;
#[cfg(feature = "std")]
use std::time::SystemTimeError;
use spacepackets::{CcsdsPacketIdAndPsc, CcsdsPacketReader, time::UnixTime};
use crate::ccsds::scheduler::CcsdsSchedulePacketId;
pub struct CcsdsScheduler {
tc_map: alloc::collections::BTreeMap<
UnixTime,
alloc::vec::Vec<(CcsdsSchedulePacketId, alloc::vec::Vec<u8>)>,
>,
packet_limit: usize,
pub(crate) current_time: UnixTime,
time_margin: Duration,
enabled: bool,
}
impl CcsdsScheduler {
pub fn new(current_time: UnixTime, packet_limit: usize, time_margin: Duration) -> Self {
Self {
tc_map: alloc::collections::BTreeMap::new(),
packet_limit,
current_time,
time_margin,
enabled: true,
}
}
/// Like [Self::new], but sets the `init_current_time` parameter to the current system time.
#[cfg(feature = "std")]
pub fn new_with_current_init_time(
packet_limit: usize,
time_margin: Duration,
) -> Result<Self, SystemTimeError> {
Ok(Self::new(UnixTime::now()?, packet_limit, time_margin))
}
pub fn num_of_entries(&self) -> usize {
self.tc_map
.values()
.map(|v| v.iter().map(|(_, v)| v.len()).sum::<usize>())
.sum()
}
#[inline]
pub fn enable(&mut self) {
self.enabled = true;
}
#[inline]
pub fn disable(&mut self) {
self.enabled = false;
}
#[inline]
pub fn update_time(&mut self, current_time: UnixTime) {
self.current_time = current_time;
}
#[inline]
pub fn current_time(&self) -> &UnixTime {
&self.current_time
}
pub fn insert_telecommand_with_reader(
&mut self,
reader: &CcsdsPacketReader,
release_time: UnixTime,
) -> Result<(), super::ScheduleError> {
if self.num_of_entries() + 1 >= self.packet_limit {
return Err(super::ScheduleError::Full);
}
let base_id = CcsdsPacketIdAndPsc::new_from_ccsds_packet(reader);
Ok(())
}
// TODO: Implementation
pub fn insert_telecommand(
&mut self,
packet_id: CcsdsSchedulePacketId,
raw_packet: &[u8],
release_time: UnixTime,
) -> Result<(), super::ScheduleError> {
if self.num_of_entries() + 1 >= self.packet_limit {
return Err(super::ScheduleError::Full);
}
Ok(())
}
}
}

View File

@@ -23,6 +23,7 @@ extern crate downcast_rs;
extern crate std; extern crate std;
pub mod action; pub mod action;
pub mod ccsds;
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
pub mod dev_mgmt; pub mod dev_mgmt;
pub mod encoding; pub mod encoding;

View File

@@ -155,73 +155,34 @@ impl Display for StoreIdError {
#[cfg(feature = "std")] #[cfg(feature = "std")]
impl Error for StoreIdError {} impl Error for StoreIdError {}
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "defmt", derive(defmt::Format))] #[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum PoolError { pub enum PoolError {
/// Requested data block is too large /// Requested data block is too large
#[error("data to store with size {0} is too large")]
DataTooLarge(usize), DataTooLarge(usize),
/// The store is full. Contains the index of the full subpool /// The store is full. Contains the index of the full subpool
#[error("store does not have any capacity")]
StoreFull(u16), StoreFull(u16),
/// The store can not hold any data. /// The store can not hold any data.
#[error("store does not have any capacity")]
NoCapacity, NoCapacity,
/// Store ID is invalid. This also includes partial errors where only the subpool is invalid /// Store ID is invalid. This also includes partial errors where only the subpool is invalid
#[error("invalid store ID: {0}, address: {1:?}")]
InvalidStoreId(StoreIdError, Option<PoolAddr>), InvalidStoreId(StoreIdError, Option<PoolAddr>),
/// Valid subpool and packet index, but no data is stored at the given address /// Valid subpool and packet index, but no data is stored at the given address
#[error("no data exists at address {0:?}")]
DataDoesNotExist(PoolAddr), DataDoesNotExist(PoolAddr),
ByteConversionError(spacepackets::ByteConversionError), #[error("byte conversion error: {0}")]
ByteConversion(#[from] spacepackets::ByteConversionError),
#[error("lock error")]
LockError, LockError,
/// Internal or configuration errors /// Internal or configuration errors
#[error("lock error")]
InternalError(u32), InternalError(u32),
} }
impl Display for PoolError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
PoolError::DataTooLarge(size) => {
write!(f, "data to store with size {size} is too large")
}
PoolError::NoCapacity => {
write!(f, "store does not have any capacity")
}
PoolError::StoreFull(u16) => {
write!(f, "store is too full. index for full subpool: {u16}")
}
PoolError::InvalidStoreId(id_e, addr) => {
write!(f, "invalid store ID: {id_e}, address: {addr:?}")
}
PoolError::DataDoesNotExist(addr) => {
write!(f, "no data exists at address {addr:?}")
}
PoolError::InternalError(e) => {
write!(f, "internal error: {e}")
}
PoolError::ByteConversionError(e) => {
write!(f, "store error: {e}")
}
PoolError::LockError => {
write!(f, "lock error")
}
}
}
}
impl From<ByteConversionError> for PoolError {
fn from(value: ByteConversionError) -> Self {
Self::ByteConversionError(value)
}
}
#[cfg(feature = "std")]
impl Error for PoolError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
if let PoolError::InvalidStoreId(e, _) = self {
return Some(e);
}
None
}
}
/// Generic trait for pool providers which provide memory pools for variable sized packet data. /// Generic trait for pool providers which provide memory pools for variable sized packet data.
/// ///
/// It specifies a basic API to [Self::add], [Self::modify], [Self::read] and [Self::delete] data /// It specifies a basic API to [Self::add], [Self::modify], [Self::read] and [Self::delete] data

View File

@@ -3,7 +3,7 @@
//! The core data structure of this module is the [PusScheduler]. This structure can be used //! The core data structure of this module is the [PusScheduler]. This structure can be used
//! to perform the scheduling of telecommands like specified in the ECSS standard. //! to perform the scheduling of telecommands like specified in the ECSS standard.
use arbitrary_int::{u11, u14}; use arbitrary_int::{u11, u14};
use core::fmt::{Debug, Display, Formatter}; use core::fmt::Debug;
use core::time::Duration; use core::time::Duration;
#[cfg(feature = "serde")] #[cfg(feature = "serde")]
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -12,8 +12,6 @@ use spacepackets::ecss::tc::{GenericPusTcSecondaryHeader, IsPusTelecommand, PusT
use spacepackets::ecss::{PusError, PusPacket, WritablePusPacket}; use spacepackets::ecss::{PusError, PusPacket, WritablePusPacket};
use spacepackets::time::{CcsdsTimeProvider, TimeReader, TimeWriter, TimestampError, UnixTime}; use spacepackets::time::{CcsdsTimeProvider, TimeReader, TimeWriter, TimestampError, UnixTime};
use spacepackets::{ByteConversionError, CcsdsPacket}; use spacepackets::{ByteConversionError, CcsdsPacket};
#[cfg(feature = "std")]
use std::error::Error;
use crate::pool::{PoolError, PoolProvider}; use crate::pool::{PoolError, PoolProvider};
#[cfg(feature = "alloc")] #[cfg(feature = "alloc")]
@@ -144,107 +142,39 @@ impl<TimeProvider: CcsdsTimeProvider + Clone> TimeWindow<TimeProvider> {
} }
} }
#[derive(Debug, Clone, PartialEq, Eq)] #[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ScheduleError { pub enum ScheduleError {
PusError(PusError), #[error("pus error: {0}")]
PusError(#[from] PusError),
/// The release time is within the time-margin added on top of the current time. /// The release time is within the time-margin added on top of the current time.
/// The first parameter is the current time, the second one the time margin, and the third one /// The first parameter is the current time, the second one the time margin, and the third one
/// the release time. /// the release time.
#[error("release time in margin")]
ReleaseTimeInTimeMargin { ReleaseTimeInTimeMargin {
current_time: UnixTime, current_time: UnixTime,
time_margin: Duration, time_margin: Duration,
release_time: UnixTime, release_time: UnixTime,
}, },
/// Nested time-tagged commands are not allowed. /// Nested time-tagged commands are not allowed.
#[error("nested scheduled tc")]
NestedScheduledTc, NestedScheduledTc,
StoreError(PoolError), #[error("store error")]
Pool(#[from] PoolError),
#[error("tc data empty")]
TcDataEmpty, TcDataEmpty,
TimestampError(TimestampError), #[error("timestamp error: {0}")]
TimestampError(#[from] TimestampError),
#[error("wrong subservice number {0}")]
WrongSubservice(u8), WrongSubservice(u8),
#[error("wrong service number {0}")]
WrongService(u8), WrongService(u8),
ByteConversionError(ByteConversionError), #[error("byte conversion error: {0}")]
} ByteConversionError(#[from] ByteConversionError),
impl Display for ScheduleError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
ScheduleError::PusError(e) => {
write!(f, "Pus Error: {e}")
}
ScheduleError::ReleaseTimeInTimeMargin {
current_time,
time_margin,
release_time,
} => {
write!(
f,
"time margin too short, current time: {current_time:?}, time margin: {time_margin:?}, release time: {release_time:?}"
)
}
ScheduleError::NestedScheduledTc => {
write!(f, "nested scheduling is not allowed")
}
ScheduleError::StoreError(e) => {
write!(f, "pus scheduling: {e}")
}
ScheduleError::TcDataEmpty => {
write!(f, "empty TC data field")
}
ScheduleError::TimestampError(e) => {
write!(f, "pus scheduling: {e}")
}
ScheduleError::WrongService(srv) => {
write!(f, "pus scheduling: wrong service number {srv}")
}
ScheduleError::WrongSubservice(subsrv) => {
write!(f, "pus scheduling: wrong subservice number {subsrv}")
}
ScheduleError::ByteConversionError(e) => {
write!(f, "pus scheduling: {e}")
}
}
}
}
impl From<PusError> for ScheduleError {
fn from(e: PusError) -> Self {
Self::PusError(e)
}
}
impl From<PoolError> for ScheduleError {
fn from(e: PoolError) -> Self {
Self::StoreError(e)
}
}
impl From<TimestampError> for ScheduleError {
fn from(e: TimestampError) -> Self {
Self::TimestampError(e)
}
}
impl From<ByteConversionError> for ScheduleError {
fn from(e: ByteConversionError) -> Self {
Self::ByteConversionError(e)
}
}
#[cfg(feature = "std")]
impl Error for ScheduleError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
match self {
ScheduleError::PusError(e) => Some(e),
ScheduleError::StoreError(e) => Some(e),
ScheduleError::TimestampError(e) => Some(e),
ScheduleError::ByteConversionError(e) => Some(e),
_ => None,
}
}
} }
/// Generic trait for scheduler objects which are able to schedule ECSS PUS C packets. /// Generic trait for scheduler objects which are able to schedule ECSS PUS C packets.
pub trait PusSchedulerProvider { pub trait PusScheduler {
type TimeProvider: CcsdsTimeProvider + TimeReader; type TimeProvider: CcsdsTimeProvider + TimeReader;
fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), PoolError>; fn reset(&mut self, store: &mut (impl PoolProvider + ?Sized)) -> Result<(), PoolError>;
@@ -405,7 +335,7 @@ pub mod alloc_mod {
/// ///
/// Currently, sub-schedules and groups are not supported. /// Currently, sub-schedules and groups are not supported.
#[derive(Debug)] #[derive(Debug)]
pub struct PusScheduler { pub struct PusSchedulerAlloc {
// TODO: Use MonotonicTime from tai-time crate instead of UnixTime and cache leap seconds. // TODO: Use MonotonicTime from tai-time crate instead of UnixTime and cache leap seconds.
// TODO: Introduce optional limit of commands stored in the TC map. If a limit is set, // TODO: Introduce optional limit of commands stored in the TC map. If a limit is set,
// there will be a check for each insertion whether the map is full, making the memory // there will be a check for each insertion whether the map is full, making the memory
@@ -415,7 +345,8 @@ pub mod alloc_mod {
time_margin: Duration, time_margin: Duration,
enabled: bool, enabled: bool,
} }
impl PusScheduler {
impl PusSchedulerAlloc {
/// Create a new PUS scheduler. /// Create a new PUS scheduler.
/// ///
/// # Arguments /// # Arguments
@@ -427,7 +358,7 @@ pub mod alloc_mod {
/// * `tc_buf_size` - Buffer for temporary storage of telecommand packets. This buffer /// * `tc_buf_size` - Buffer for temporary storage of telecommand packets. This buffer
/// should be large enough to accomodate the largest expected TC packets. /// should be large enough to accomodate the largest expected TC packets.
pub fn new(init_current_time: UnixTime, time_margin: Duration) -> Self { pub fn new(init_current_time: UnixTime, time_margin: Duration) -> Self {
PusScheduler { PusSchedulerAlloc {
tc_map: Default::default(), tc_map: Default::default(),
current_time: init_current_time, current_time: init_current_time,
time_margin, time_margin,
@@ -449,10 +380,12 @@ pub mod alloc_mod {
num_entries num_entries
} }
#[inline]
pub fn update_time(&mut self, current_time: UnixTime) { pub fn update_time(&mut self, current_time: UnixTime) {
self.current_time = current_time; self.current_time = current_time;
} }
#[inline]
pub fn current_time(&self) -> &UnixTime { pub fn current_time(&self) -> &UnixTime {
&self.current_time &self.current_time
} }
@@ -798,7 +731,7 @@ pub mod alloc_mod {
} }
} }
impl PusSchedulerProvider for PusScheduler { impl PusScheduler for PusSchedulerAlloc {
type TimeProvider = cds::CdsTime; type TimeProvider = cds::CdsTime;
/// This will disable the scheduler and clear the schedule as specified in 6.11.4.4. /// This will disable the scheduler and clear the schedule as specified in 6.11.4.4.
@@ -982,7 +915,8 @@ mod tests {
#[test] #[test]
fn test_enable_api() { fn test_enable_api() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
assert!(scheduler.is_enabled()); assert!(scheduler.is_enabled());
scheduler.disable(); scheduler.disable();
assert!(!scheduler.is_enabled()); assert!(!scheduler.is_enabled());
@@ -996,7 +930,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::new(0), &[]);
@@ -1038,7 +973,8 @@ mod tests {
#[test] #[test]
fn insert_multi_with_same_time() { fn insert_multi_with_same_time() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
scheduler scheduler
.insert_unwrapped_and_stored_tc( .insert_unwrapped_and_stored_tc(
@@ -1097,7 +1033,8 @@ mod tests {
#[test] #[test]
fn test_time_update() { fn test_time_update() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let time = UnixTime::new(1, 2_000_000); let time = UnixTime::new(1, 2_000_000);
scheduler.update_time(time); scheduler.update_time(time);
assert_eq!(scheduler.current_time(), &time); assert_eq!(scheduler.current_time(), &time);
@@ -1151,7 +1088,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
@@ -1219,7 +1157,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
@@ -1279,7 +1218,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
scheduler.disable(); scheduler.disable();
@@ -1344,7 +1284,8 @@ mod tests {
#[test] #[test]
fn insert_unwrapped_tc() { fn insert_unwrapped_tc() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
@@ -1394,7 +1335,8 @@ mod tests {
#[test] #[test]
fn insert_wrapped_tc() { fn insert_wrapped_tc() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
@@ -1446,7 +1388,8 @@ mod tests {
#[test] #[test]
fn insert_wrong_service() { fn insert_wrong_service() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
@@ -1471,7 +1414,8 @@ mod tests {
#[test] #[test]
fn insert_wrong_subservice() { fn insert_wrong_subservice() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
@@ -1496,7 +1440,8 @@ mod tests {
#[test] #[test]
fn insert_wrapped_tc_faulty_app_data() { fn insert_wrapped_tc_faulty_app_data() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
@@ -1513,7 +1458,8 @@ mod tests {
#[test] #[test]
fn insert_doubly_wrapped_time_tagged_cmd() { fn insert_doubly_wrapped_time_tagged_cmd() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
@@ -1531,7 +1477,7 @@ mod tests {
#[test] #[test]
fn test_ctor_from_current() { fn test_ctor_from_current() {
let scheduler = PusScheduler::new_with_current_init_time(Duration::from_secs(5)) let scheduler = PusSchedulerAlloc::new_with_current_init_time(Duration::from_secs(5))
.expect("creation from current time failed"); .expect("creation from current time failed");
let current_time = scheduler.current_time; let current_time = scheduler.current_time;
assert!(current_time.as_secs() > 0); assert!(current_time.as_secs() > 0);
@@ -1539,7 +1485,8 @@ mod tests {
#[test] #[test]
fn test_update_from_current() { fn test_update_from_current() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
assert_eq!(scheduler.current_time.as_secs(), 0); assert_eq!(scheduler.current_time.as_secs(), 0);
scheduler scheduler
.update_time_from_now() .update_time_from_now()
@@ -1549,7 +1496,8 @@ mod tests {
#[test] #[test]
fn release_time_within_time_margin() { fn release_time_within_time_margin() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
@@ -1582,7 +1530,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
scheduler scheduler
@@ -1619,7 +1568,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
scheduler scheduler
@@ -1645,7 +1595,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
scheduler scheduler
@@ -1666,7 +1617,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
scheduler scheduler
@@ -1687,7 +1639,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);
scheduler scheduler
@@ -1729,7 +1682,8 @@ mod tests {
#[test] #[test]
fn insert_full_store_test() { fn insert_full_store_test() {
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples( let mut pool = StaticMemoryPool::new(StaticPoolConfig::new_from_subpool_cfg_tuples(
vec![(1, 64)], vec![(1, 64)],
@@ -1745,7 +1699,7 @@ mod tests {
assert!(insert_res.is_err()); assert!(insert_res.is_err());
let err = insert_res.unwrap_err(); let err = insert_res.unwrap_err();
match err { match err {
ScheduleError::StoreError(e) => match e { ScheduleError::Pool(e) => match e {
PoolError::StoreFull(_) => {} PoolError::StoreFull(_) => {}
_ => panic!("unexpected store error {e}"), _ => panic!("unexpected store error {e}"),
}, },
@@ -1755,7 +1709,7 @@ mod tests {
fn insert_command_with_release_time( fn insert_command_with_release_time(
pool: &mut StaticMemoryPool, pool: &mut StaticMemoryPool,
scheduler: &mut PusScheduler, scheduler: &mut PusSchedulerAlloc,
seq_count: u14, seq_count: u14,
release_secs: u64, release_secs: u64,
) -> TcInfo { ) -> TcInfo {
@@ -1774,7 +1728,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2); assert_eq!(scheduler.num_scheduled_telecommands(), 2);
@@ -1806,7 +1761,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150); let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150);
@@ -1841,7 +1797,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); let tc_info_0 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150);
@@ -1876,7 +1833,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); let _ = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); let tc_info_1 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150); let tc_info_2 = insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 150);
@@ -1917,7 +1875,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
assert_eq!(scheduler.num_scheduled_telecommands(), 2); assert_eq!(scheduler.num_scheduled_telecommands(), 2);
@@ -1946,7 +1905,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let cmd_0_to_delete = let cmd_0_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 100);
@@ -1973,7 +1933,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let cmd_0_to_delete = let cmd_0_to_delete =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let cmd_1_to_delete = let cmd_1_to_delete =
@@ -2001,7 +1962,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let cmd_out_of_range_0 = let cmd_out_of_range_0 =
insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50); insert_command_with_release_time(&mut pool, &mut scheduler, u14::ZERO, 50);
let cmd_0_to_delete = let cmd_0_to_delete =
@@ -2039,7 +2001,8 @@ mod tests {
vec![(10, 32), (5, 64)], vec![(10, 32), (5, 64)],
false, false,
)); ));
let mut scheduler = PusScheduler::new(UnixTime::new_only_secs(0), Duration::from_secs(5)); let mut scheduler =
PusSchedulerAlloc::new(UnixTime::new_only_secs(0), Duration::from_secs(5));
let mut buf: [u8; 32] = [0; 32]; let mut buf: [u8; 32] = [0; 32];
let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]); let tc_info_0 = ping_tc_to_store(&mut pool, &mut buf, u14::ZERO, &[]);

View File

@@ -1,4 +1,4 @@
use super::scheduler::PusSchedulerProvider; use super::scheduler::PusScheduler;
use super::verification::{VerificationReporter, VerificationReportingProvider}; use super::verification::{VerificationReporter, VerificationReportingProvider};
use super::{ use super::{
CacheAndReadRawEcssTc, DirectPusPacketHandlerResult, EcssTcInSharedPoolCacher, EcssTcReceiver, CacheAndReadRawEcssTc, DirectPusPacketHandlerResult, EcssTcInSharedPoolCacher, EcssTcReceiver,
@@ -26,11 +26,11 @@ pub struct PusSchedServiceHandler<
TmSender: EcssTmSender, TmSender: EcssTmSender,
TcInMemConverter: CacheAndReadRawEcssTc, TcInMemConverter: CacheAndReadRawEcssTc,
VerificationReporter: VerificationReportingProvider, VerificationReporter: VerificationReportingProvider,
PusScheduler: PusSchedulerProvider, PusSchedulerInstance: PusScheduler,
> { > {
pub service_helper: pub service_helper:
PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>, PusServiceHelper<TcReceiver, TmSender, TcInMemConverter, VerificationReporter>,
scheduler: PusScheduler, scheduler: PusSchedulerInstance,
} }
impl< impl<
@@ -38,7 +38,7 @@ impl<
TmSender: EcssTmSender, TmSender: EcssTmSender,
TcInMemConverter: CacheAndReadRawEcssTc, TcInMemConverter: CacheAndReadRawEcssTc,
VerificationReporter: VerificationReportingProvider, VerificationReporter: VerificationReportingProvider,
Scheduler: PusSchedulerProvider, Scheduler: PusScheduler,
> PusSchedServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter, Scheduler> > PusSchedServiceHandler<TcReceiver, TmSender, TcInMemConverter, VerificationReporter, Scheduler>
{ {
pub fn new( pub fn new(
@@ -254,7 +254,7 @@ mod tests {
use crate::pus::{DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError}; use crate::pus::{DirectPusPacketHandlerResult, MpscTcReceiver, PusPacketHandlingError};
use crate::pus::{ use crate::pus::{
EcssTcInSharedPoolCacher, EcssTcInSharedPoolCacher,
scheduler::{self, PusSchedulerProvider, TcInfo}, scheduler::{self, PusScheduler, TcInfo},
tests::PusServiceHandlerWithSharedStoreCommon, tests::PusServiceHandlerWithSharedStoreCommon,
verification::{RequestId, TcStateAccepted, VerificationToken}, verification::{RequestId, TcStateAccepted, VerificationToken},
}; };
@@ -349,7 +349,7 @@ mod tests {
inserted_tcs: VecDeque<TcInfo>, inserted_tcs: VecDeque<TcInfo>,
} }
impl PusSchedulerProvider for TestScheduler { impl PusScheduler for TestScheduler {
type TimeProvider = cds::CdsTime; type TimeProvider = cds::CdsTime;
fn reset( fn reset(