This commit is contained in:
parent
7c32b1c905
commit
145b50347d
@ -2,13 +2,14 @@
|
||||
//!
|
||||
//! 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.
|
||||
use core::fmt::Debug;
|
||||
use core::fmt::{Debug, Display, Formatter};
|
||||
use core::time::Duration;
|
||||
#[cfg(feature = "serde")]
|
||||
use serde::{Deserialize, Serialize};
|
||||
use spacepackets::ecss::scheduling::TimeWindowType;
|
||||
use spacepackets::ecss::tc::{GenericPusTcSecondaryHeader, IsPusTelecommand, PusTcReader};
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use spacepackets::time::{CcsdsTimeProvider, TimeReader, UnixTimestamp};
|
||||
use spacepackets::ecss::{PusError, PusPacket};
|
||||
use spacepackets::time::{CcsdsTimeProvider, TimeReader, TimestampError, UnixTimestamp};
|
||||
use spacepackets::CcsdsPacket;
|
||||
#[cfg(feature = "std")]
|
||||
use std::error::Error;
|
||||
@ -136,6 +137,86 @@ impl<TimeProvider: CcsdsTimeProvider + Clone> TimeWindow<TimeProvider> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum ScheduleError {
|
||||
PusError(PusError),
|
||||
/// 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.
|
||||
ReleaseTimeInTimeMargin {
|
||||
current_time: UnixTimestamp,
|
||||
time_margin: Duration,
|
||||
release_time: UnixTimestamp,
|
||||
},
|
||||
/// Nested time-tagged commands are not allowed.
|
||||
NestedScheduledTc,
|
||||
StoreError(StoreError),
|
||||
TcDataEmpty,
|
||||
TimestampError(TimestampError),
|
||||
WrongSubservice,
|
||||
WrongService,
|
||||
}
|
||||
|
||||
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,
|
||||
"Error: time margin too short, current time: {current_time:?}, time margin: {time_margin:?}, release time: {release_time:?}"
|
||||
)
|
||||
}
|
||||
ScheduleError::NestedScheduledTc => {
|
||||
write!(f, "Error: nested scheduling is not allowed")
|
||||
}
|
||||
ScheduleError::StoreError(e) => {
|
||||
write!(f, "Store Error: {e}")
|
||||
}
|
||||
ScheduleError::TcDataEmpty => {
|
||||
write!(f, "Error: empty Tc Data field")
|
||||
}
|
||||
ScheduleError::TimestampError(e) => {
|
||||
write!(f, "Timestamp Error: {e}")
|
||||
}
|
||||
ScheduleError::WrongService => {
|
||||
write!(f, "Error: Service not 11.")
|
||||
}
|
||||
ScheduleError::WrongSubservice => {
|
||||
write!(f, "Error: Subservice not 4.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PusError> for ScheduleError {
|
||||
fn from(e: PusError) -> Self {
|
||||
ScheduleError::PusError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoreError> for ScheduleError {
|
||||
fn from(e: StoreError) -> Self {
|
||||
ScheduleError::StoreError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TimestampError> for ScheduleError {
|
||||
fn from(e: TimestampError) -> Self {
|
||||
ScheduleError::TimestampError(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ScheduleError {}
|
||||
|
||||
pub trait PusSchedulerInterface {
|
||||
type TimeProvider: CcsdsTimeProvider + TimeReader;
|
||||
|
||||
@ -213,13 +294,12 @@ pub mod alloc_mod {
|
||||
use alloc::collections::BTreeMap;
|
||||
use alloc::vec;
|
||||
use alloc::vec::Vec;
|
||||
use core::fmt::{Display, Formatter};
|
||||
use core::time::Duration;
|
||||
use spacepackets::ecss::scheduling::TimeWindowType;
|
||||
use spacepackets::ecss::tc::{PusTc, PusTcReader};
|
||||
use spacepackets::ecss::{PusError, PusPacket};
|
||||
use spacepackets::ecss::PusPacket;
|
||||
use spacepackets::time::cds::DaysLen24Bits;
|
||||
use spacepackets::time::{cds, CcsdsTimeProvider, TimestampError, UnixTimestamp};
|
||||
use spacepackets::time::{cds, CcsdsTimeProvider, UnixTimestamp};
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
use std::time::SystemTimeError;
|
||||
@ -229,78 +309,6 @@ pub mod alloc_mod {
|
||||
WithStoreDeletion(Result<bool, StoreError>),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||
pub enum ScheduleError {
|
||||
PusError(PusError),
|
||||
/// 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.
|
||||
ReleaseTimeInTimeMargin(UnixTimestamp, Duration, UnixTimestamp),
|
||||
/// Nested time-tagged commands are not allowed.
|
||||
NestedScheduledTc,
|
||||
StoreError(StoreError),
|
||||
TcDataEmpty,
|
||||
TimestampError(TimestampError),
|
||||
WrongSubservice,
|
||||
WrongService,
|
||||
}
|
||||
|
||||
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, margin, timestamp) => {
|
||||
write!(
|
||||
f,
|
||||
"Error: time margin too short, current time: {current_time:?}, time margin: {margin:?}, release time: {timestamp:?}"
|
||||
)
|
||||
}
|
||||
ScheduleError::NestedScheduledTc => {
|
||||
write!(f, "Error: nested scheduling is not allowed")
|
||||
}
|
||||
ScheduleError::StoreError(e) => {
|
||||
write!(f, "Store Error: {e}")
|
||||
}
|
||||
ScheduleError::TcDataEmpty => {
|
||||
write!(f, "Error: empty Tc Data field")
|
||||
}
|
||||
ScheduleError::TimestampError(e) => {
|
||||
write!(f, "Timestamp Error: {e}")
|
||||
}
|
||||
ScheduleError::WrongService => {
|
||||
write!(f, "Error: Service not 11.")
|
||||
}
|
||||
ScheduleError::WrongSubservice => {
|
||||
write!(f, "Error: Subservice not 4.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PusError> for ScheduleError {
|
||||
fn from(e: PusError) -> Self {
|
||||
ScheduleError::PusError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StoreError> for ScheduleError {
|
||||
fn from(e: StoreError) -> Self {
|
||||
ScheduleError::StoreError(e)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TimestampError> for ScheduleError {
|
||||
fn from(e: TimestampError) -> Self {
|
||||
ScheduleError::TimestampError(e)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "std")]
|
||||
impl Error for ScheduleError {}
|
||||
|
||||
/// This is the core data structure for scheduling PUS telecommands with [alloc] support.
|
||||
///
|
||||
/// It is assumed that the actual telecommand data is stored in a separate TC pool offering
|
||||
@ -378,11 +386,11 @@ pub mod alloc_mod {
|
||||
info: TcInfo,
|
||||
) -> Result<(), ScheduleError> {
|
||||
if time_stamp < self.current_time + self.time_margin {
|
||||
return Err(ScheduleError::ReleaseTimeInTimeMargin(
|
||||
self.current_time,
|
||||
self.time_margin,
|
||||
time_stamp,
|
||||
));
|
||||
return Err(ScheduleError::ReleaseTimeInTimeMargin {
|
||||
current_time: self.current_time,
|
||||
time_margin: self.time_margin,
|
||||
release_time: time_stamp,
|
||||
});
|
||||
}
|
||||
match self.tc_map.entry(time_stamp) {
|
||||
Entry::Vacant(e) => {
|
||||
@ -672,11 +680,11 @@ pub mod alloc_mod {
|
||||
info: TcInfo,
|
||||
) -> Result<(), ScheduleError> {
|
||||
if time_stamp < self.current_time + self.time_margin {
|
||||
return Err(ScheduleError::ReleaseTimeInTimeMargin(
|
||||
self.current_time,
|
||||
self.time_margin,
|
||||
time_stamp,
|
||||
));
|
||||
return Err(ScheduleError::ReleaseTimeInTimeMargin {
|
||||
current_time: self.current_time,
|
||||
time_margin: self.time_margin,
|
||||
release_time: time_stamp,
|
||||
});
|
||||
}
|
||||
match self.tc_map.entry(time_stamp) {
|
||||
Entry::Vacant(e) => {
|
||||
@ -1324,9 +1332,13 @@ mod tests {
|
||||
assert!(insert_res.is_err());
|
||||
let err = insert_res.unwrap_err();
|
||||
match err {
|
||||
ScheduleError::ReleaseTimeInTimeMargin(curr_time, margin, release_time) => {
|
||||
assert_eq!(curr_time, UnixTimestamp::new_only_seconds(0));
|
||||
assert_eq!(margin, Duration::from_secs(5));
|
||||
ScheduleError::ReleaseTimeInTimeMargin {
|
||||
current_time,
|
||||
time_margin,
|
||||
release_time,
|
||||
} => {
|
||||
assert_eq!(current_time, UnixTimestamp::new_only_seconds(0));
|
||||
assert_eq!(time_margin, Duration::from_secs(5));
|
||||
assert_eq!(release_time, UnixTimestamp::new_only_seconds(4));
|
||||
}
|
||||
_ => panic!("unexepcted error {err}"),
|
||||
|
Loading…
Reference in New Issue
Block a user