Compare commits
3 Commits
move-to-cc
...
ccsds-sche
| Author | SHA1 | Date | |
|---|---|---|---|
| f4aff4780a | |||
| f8628a5279 | |||
|
|
d7b8a8c1d1
|
6
justfile
6
justfile
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -26,9 +26,16 @@ bitbybit = "1.4"
|
|||||||
serde = { version = "1", features = ["derive"] }
|
serde = { version = "1", features = ["derive"] }
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
|
|
||||||
satrs = { path = "../satrs", features = ["test_util"] }
|
[dependencies.satrs]
|
||||||
satrs-minisim = { path = "../satrs-minisim" }
|
path = "../satrs"
|
||||||
satrs-mib = { path = "../satrs-mib" }
|
features = ["test_util"]
|
||||||
|
|
||||||
|
[dependencies.satrs-minisim]
|
||||||
|
path = "../satrs-minisim"
|
||||||
|
|
||||||
|
[dependencies.satrs-mib]
|
||||||
|
version = "0.1.1"
|
||||||
|
path = "../satrs-mib"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["heap_tmtc"]
|
default = ["heap_tmtc"]
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ use interface::{
|
|||||||
};
|
};
|
||||||
use log::info;
|
use log::info;
|
||||||
use logger::setup_logger;
|
use logger::setup_logger;
|
||||||
/*
|
|
||||||
use pus::{
|
use pus::{
|
||||||
action::create_action_service,
|
action::create_action_service,
|
||||||
event::create_event_service,
|
event::create_event_service,
|
||||||
@@ -29,7 +28,6 @@ use pus::{
|
|||||||
test::create_test_service,
|
test::create_test_service,
|
||||||
PusTcDistributor, PusTcMpscRouter,
|
PusTcDistributor, PusTcMpscRouter,
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
use requests::GenericRequestRouter;
|
use requests::GenericRequestRouter;
|
||||||
use satrs::{
|
use satrs::{
|
||||||
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
|
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
|
||||||
@@ -80,7 +78,7 @@ mod events;
|
|||||||
mod hk;
|
mod hk;
|
||||||
mod interface;
|
mod interface;
|
||||||
mod logger;
|
mod logger;
|
||||||
//mod pus;
|
mod pus;
|
||||||
mod requests;
|
mod requests;
|
||||||
mod spi;
|
mod spi;
|
||||||
mod tmtc;
|
mod tmtc;
|
||||||
@@ -179,7 +177,6 @@ fn main() {
|
|||||||
let tc_releaser = TcReleaser::Heap(tc_source_tx.clone());
|
let tc_releaser = TcReleaser::Heap(tc_source_tx.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
let pus_router = PusTcMpscRouter {
|
let pus_router = PusTcMpscRouter {
|
||||||
test_tc_sender: pus_test_tx,
|
test_tc_sender: pus_test_tx,
|
||||||
event_tc_sender: pus_event_tx,
|
event_tc_sender: pus_event_tx,
|
||||||
@@ -236,7 +233,6 @@ fn main() {
|
|||||||
pus_scheduler_service,
|
pus_scheduler_service,
|
||||||
pus_mode_service,
|
pus_mode_service,
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
cfg_if::cfg_if! {
|
cfg_if::cfg_if! {
|
||||||
if #[cfg(not(feature = "heap_tmtc"))] {
|
if #[cfg(not(feature = "heap_tmtc"))] {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ pub fn create_verification_reporter(owner_id: ComponentId, apid: Apid) -> Verifi
|
|||||||
VerificationReporter::new(owner_id, &verif_cfg)
|
VerificationReporter::new(owner_id, &verif_cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
/// Simple router structure which forwards PUS telecommands to dedicated handlers.
|
||||||
pub struct PusTcMpscRouter {
|
pub struct PusTcMpscRouter {
|
||||||
pub test_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
pub test_tc_sender: mpsc::SyncSender<EcssTcAndToken>,
|
||||||
@@ -188,7 +187,6 @@ impl PusTcDistributor {
|
|||||||
Ok(HandlingStatus::HandledOne)
|
Ok(HandlingStatus::HandledOne)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
pub trait TargetedPusService {
|
pub trait TargetedPusService {
|
||||||
const SERVICE_ID: u8;
|
const SERVICE_ID: u8;
|
||||||
@@ -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(
|
||||||
@@ -2,12 +2,8 @@ use satrs::{
|
|||||||
pool::PoolProvider,
|
pool::PoolProvider,
|
||||||
pus::HandlingStatus,
|
pus::HandlingStatus,
|
||||||
tmtc::{PacketAsVec, PacketInPool, SharedPacketPool},
|
tmtc::{PacketAsVec, PacketInPool, SharedPacketPool},
|
||||||
ComponentId,
|
|
||||||
};
|
|
||||||
use std::{
|
|
||||||
collections::HashMap,
|
|
||||||
sync::mpsc::{self, TryRecvError},
|
|
||||||
};
|
};
|
||||||
|
use std::sync::mpsc::{self, TryRecvError};
|
||||||
|
|
||||||
use crate::pus::PusTcDistributor;
|
use crate::pus::PusTcDistributor;
|
||||||
|
|
||||||
@@ -69,24 +65,18 @@ impl TcSourceTaskStatic {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type CcsdsDistributorDyn = HashMap<ComponentId, std::sync::mpsc::SyncSender<PacketAsVec>>;
|
|
||||||
pub type CcsdsDistributorStatic = HashMap<ComponentId, std::sync::mpsc::SyncSender<PacketInPool>>;
|
|
||||||
|
|
||||||
// TC source components where the heap is the backing memory of the received telecommands.
|
// TC source components where the heap is the backing memory of the received telecommands.
|
||||||
pub struct TcSourceTaskDynamic {
|
pub struct TcSourceTaskDynamic {
|
||||||
pub tc_receiver: mpsc::Receiver<PacketAsVec>,
|
pub tc_receiver: mpsc::Receiver<PacketAsVec>,
|
||||||
ccsds_distributor: CcsdsDistributorDyn,
|
pus_distributor: PusTcDistributor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
impl TcSourceTaskDynamic {
|
impl TcSourceTaskDynamic {
|
||||||
pub fn new(
|
pub fn new(tc_receiver: mpsc::Receiver<PacketAsVec>, pus_receiver: PusTcDistributor) -> Self {
|
||||||
tc_receiver: mpsc::Receiver<PacketAsVec>,
|
|
||||||
ccsds_distributor: CcsdsDistributorDyn,
|
|
||||||
) -> Self {
|
|
||||||
Self {
|
Self {
|
||||||
tc_receiver,
|
tc_receiver,
|
||||||
ccsds_distributor,
|
pus_distributor: pus_receiver,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
1
satrs/src/ccsds/mod.rs
Normal file
1
satrs/src/ccsds/mod.rs
Normal file
@@ -0,0 +1 @@
|
|||||||
|
pub mod scheduler;
|
||||||
147
satrs/src/ccsds/scheduler.rs
Normal file
147
satrs/src/ccsds/scheduler.rs
Normal 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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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, &[]);
|
||||||
|
|||||||
@@ -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(
|
||||||
|
|||||||
Reference in New Issue
Block a user