27 Commits

Author SHA1 Message Date
6a4417c954 added and scheduled MGM assembly 2025-05-19 16:18:31 +02:00
f600ee499a Merge pull request 'add first generator' (#234) from generators into main
Reviewed-on: #234
2025-05-19 15:23:37 +02:00
3f28f60c59 add first generator 2025-05-19 15:21:51 +02:00
44b1f2b037 Merge pull request 'possible fix for clippy warning' (#233) from possible-fix-for-clippy-warning into main
Reviewed-on: #233
2025-05-19 15:15:24 +02:00
4b22958b34 possible fix for clippy warning 2025-05-19 15:14:59 +02:00
a711c6acd9 Merge pull request 'bump spacepackets' (#232) from bump-spacepackets into main
Reviewed-on: #232
2025-05-19 14:19:00 +02:00
99a954a1f5 some tweaks 2025-05-19 14:18:26 +02:00
4a4fd7ac2c use git deps 2025-05-16 19:49:43 +02:00
9bf08849a2 annoying 2025-05-16 19:43:45 +02:00
b8f7fefe26 Merge pull request 'should fix tests' (#231) from test-fix into main
Reviewed-on: #231
2025-05-10 16:31:14 +02:00
a501832698 should fix tests 2025-05-10 16:30:37 +02:00
c7284d3f1c Merge pull request 'minor wording improvements' (#230) from some-wording-improvements into main
Reviewed-on: #230
2025-05-10 16:27:37 +02:00
18263d4568 Merge branch 'main' into some-wording-improvements 2025-05-10 16:27:29 +02:00
95519c1363 minor wording improvements 2025-05-10 16:27:04 +02:00
2ec32717d0 Merge pull request 'use released dependencies' (#229) from use-relesed-dependencies into main
Reviewed-on: #229
2025-05-10 16:24:37 +02:00
bfdd777685 use released dependencies 2025-05-10 16:24:06 +02:00
b54c2b7863 Merge pull request 'spacepackets update' (#227) from spacepackets-update into main
Reviewed-on: #227
2025-05-10 16:19:07 +02:00
19f3355283 Merge pull request 'update SIM suite name' (#228) from update-sim-suite-name into main
Reviewed-on: #228
2025-05-10 16:18:16 +02:00
4aeb28d2f1 update SIM suite name 2025-05-10 16:14:48 +02:00
ddc4544456 spacepackets update, clippy fixes 2025-05-10 16:13:45 +02:00
9ab36c0362 Merge pull request 'update docs' (#226) from update-docs into main
Reviewed-on: #226
2025-05-06 16:21:17 +02:00
b95769c177 Merge branch 'main' into update-docs 2025-05-06 16:21:10 +02:00
bb20533ae1 Merge pull request 'remove token API for verification creator core' (#224) from simplify-verification-reporter-core into main
Reviewed-on: #224
2025-05-05 19:03:34 +02:00
27cacd0f43 remove token API for verification creator core 2025-05-05 19:02:37 +02:00
bd6488e87b update docs 2025-04-01 20:58:18 +02:00
52ec0d44aa Merge pull request 'bump README links' (#223) from update-readme-links into main
Reviewed-on: #223
2025-04-01 15:15:14 +02:00
4fa9f8d685 bump README links 2025-04-01 15:05:28 +02:00
49 changed files with 784 additions and 424 deletions

View File

@ -1,7 +1,7 @@
<p align="center"> <img src="misc/satrs-logo-v2.png" width="40%"> </p>
[![sat-rs website](https://img.shields.io/badge/sat--rs-website-darkgreen?style=flat)](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
[![sat-rs book](https://img.shields.io/badge/sat--rs-book-darkgreen?style=flat)](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/book/)
[![sat-rs book](https://img.shields.io/badge/sat--rs-book-darkgreen?style=flat)](https://robamu.github.io/sat-rs/book/)
[![Crates.io](https://img.shields.io/crates/v/satrs)](https://crates.io/crates/satrs)
[![docs.rs](https://img.shields.io/docsrs/satrs)](https://docs.rs/satrs)
@ -11,7 +11,7 @@ sat-rs
This is the repository of the sat-rs library. Its primary goal is to provide re-usable components
to write on-board software for remote systems like rovers or satellites. It is specifically written
for the special requirements for these systems. You can find an overview of the project and the
link to the [more high-level sat-rs book](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
link to the [more high-level sat-rs book](https://robamu.github.io/sat-rs/book/)
at the [IRS software projects website](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/).
This is early-stage software. Important features are missing. New releases
@ -38,7 +38,7 @@ This project currently contains following crates:
Example of a simple example on-board software using various sat-rs components which can be run
on a host computer or on any system with a standard runtime like a Raspberry Pi.
* [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim):
Mini-Simulator based on [asynchronix](https://github.com/asynchronics/asynchronix) which
Mini-Simulator based on [nexosim](https://github.com/asynchronics/nexosim) which
simulates some physical devices for the `satrs-example` application device handlers.
* [`satrs-mib`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-mib):
Components to build a mission information base from the on-board software directly.

View File

@ -0,0 +1,8 @@
[package]
name = "satrs-gen"
version = "0.1.0"
edition = "2024"
[dependencies]
toml = "0.8"
heck = "0.5"

View File

@ -0,0 +1,34 @@
[apid]
Sched = 1
GenericPus = 2
Acs = 3
Cfdp = 4
Tmtc = 5
Eps = 6
[ids]
[ids.Eps]
Pcdu = 0
Subsystem = 1
[ids.Tmtc]
UdpServer = 0
TcpServer = 1
[ids.GenericPus]
PusEventManagement = 0
PusRouting = 1
PusTest = 2
PusAction = 3
PusMode = 4
PusHk = 5
[ids.Sched]
PusSched = 0
[ids.Acs]
Subsystem = 1
Assembly = 2
Mgm0 = 3
Mgm1 = 4

View File

@ -0,0 +1,91 @@
use heck::{ToShoutySnakeCase, ToSnakeCase};
use std::{
collections::BTreeMap,
fs::{self, File},
io::{self, Write},
};
use toml::{Value, map::Map};
fn main() -> io::Result<()> {
// Read the configuration file
let config_str = fs::read_to_string("components.toml").expect("Unable to read file");
let config: Value = toml::from_str(&config_str).expect("Unable to parse TOML");
let mut output = File::create("../satrs-example/src/ids.rs")?;
generate_rust_code(&config, &mut output);
Ok(())
}
fn sort_enum_table(table_map: &Map<String, Value>) -> BTreeMap<u64, &str> {
// Collect entries into a BTreeMap to sort them by key
let mut sorted_entries: BTreeMap<u64, &str> = BTreeMap::new();
for (key, value) in table_map {
if let Some(value) = value.as_integer() {
if !(0..=0x7FF).contains(&value) {
panic!("Invalid APID value: {}", value);
}
sorted_entries.insert(value as u64, key);
}
}
sorted_entries
}
fn generate_rust_code(config: &Value, writer: &mut impl Write) {
writeln!(
writer,
"//! This is an auto-generated configuration module."
)
.unwrap();
writeln!(writer, "use satrs::request::UniqueApidTargetId;").unwrap();
writeln!(writer).unwrap();
// Generate the main module
writeln!(
writer,
"#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::EnumIter)]"
)
.unwrap();
writeln!(writer, "pub enum Apid {{").unwrap();
// Generate constants for the main module
if let Some(apid_table) = config.get("apid").and_then(Value::as_table) {
let sorted_entries = sort_enum_table(apid_table);
// Write the sorted entries to the writer
for (value, key) in sorted_entries {
writeln!(writer, " {} = {},", key, value).unwrap();
}
}
writeln!(writer, "}}").unwrap();
// Generate ID tables.
if let Some(id_tables) = config.get("ids").and_then(Value::as_table) {
for (mod_name, table) in id_tables {
let mod_name_as_snake = mod_name.to_snake_case();
writeln!(writer).unwrap();
writeln!(writer, "pub mod {} {{", mod_name_as_snake).unwrap();
let sorted_entries = sort_enum_table(table.as_table().unwrap());
writeln!(writer, " #[derive(Debug, Copy, Clone, PartialEq, Eq)]").unwrap();
writeln!(writer, " pub enum Id {{").unwrap();
// Write the sorted entries to the writer
for (value, key) in &sorted_entries {
writeln!(writer, " {} = {},", key, value).unwrap();
}
writeln!(writer, " }}").unwrap();
writeln!(writer).unwrap();
for (_value, key) in sorted_entries {
let key_shouting = key.to_shouty_snake_case();
writeln!(
writer,
" pub const {}: super::UniqueApidTargetId = super::UniqueApidTargetId::new(super::Apid::{} as u16, Id::{} as u32);",
key_shouting, mod_name, key
).unwrap();
}
writeln!(writer, "}}").unwrap();
}
}
}

View File

@ -3,20 +3,20 @@
Software for space systems oftentimes has different requirements than the software for host
systems or servers. Currently, most space systems are considered embedded systems.
For these systems, the computation power and the available heap are the most important resources
which are constrained. This might make completeley heap based memory management schemes which
For these systems, the computation power and the available heap are important resources
which are also constrained. This might make completeley heap based memory management schemes which
are oftentimes used on host and server based systems unfeasable. Still, completely forbidding
heap allocations might make software development unnecessarilly difficult, especially in a
time where the OBSW might be running on Linux based systems with hundreds of MBs of RAM.
A useful pattern used commonly in space systems is to limit heap allocations to program
A useful pattern commonly used in space systems is to limit heap allocations to program
initialization time and avoid frequent run-time allocations. This prevents issues like
running out of memory (something even Rust can not protect from) or heap fragmentation on systems
without a MMU.
# Using pre-allocated pool structures
A huge candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all
A candidate for heap allocations is the TMTC and handling. TC, TMs and IPC data are all
candidates where the data size might vary greatly. The regular solution for host systems
might be to send around this data as a `Vec<u8>` until it is dropped. `sat-rs` provides
another solution to avoid run-time allocations by offering pre-allocated static

View File

@ -1 +1,175 @@
// TODO: Write the assembly
//
use std::sync::mpsc;
use satrs::{
dev_mgmt::{DevManagerCommandingHelper, DevManagerHelperResult, TransparentDevManagerHook},
mode::{
ModeAndSubmode, ModeError, ModeProvider, ModeReply, ModeReplyReceiver as _,
ModeReplySender as _, ModeRequest, ModeRequestHandler, ModeRequestReceiver as _,
ModeRequestorAndHandlerMpscBounded, UNKNOWN_MODE,
},
mode_tree::{ModeChild, ModeNode, ModeParent},
queue::GenericTargetedMessagingError,
request::{GenericMessage, MessageMetadata},
ComponentId,
};
use satrs_example::{ids, DeviceMode};
pub type RequestSenderType = mpsc::SyncSender<GenericMessage<ModeRequest>>;
pub type ReplySenderType = mpsc::SyncSender<GenericMessage<ModeReply>>;
// TODO: Needs to perform same functions as the integration test assembly, but also needs
// to track mode changes and health changes of children.
pub struct MgmAssembly {
pub mode_node: ModeRequestorAndHandlerMpscBounded,
pub mode_requestor_info: Option<MessageMetadata>,
pub mode_and_submode: ModeAndSubmode,
pub commanding_helper: DevManagerCommandingHelper<TransparentDevManagerHook>,
}
impl MgmAssembly {
pub fn new(mode_node: ModeRequestorAndHandlerMpscBounded) -> Self {
Self {
mode_node,
mode_requestor_info: None,
mode_and_submode: UNKNOWN_MODE,
commanding_helper: DevManagerCommandingHelper::new(TransparentDevManagerHook::default()),
}
}
pub const fn id() -> ComponentId {
ids::acs::MGM_ASSEMBLY.raw()
}
pub fn periodic_operation(&mut self) {
self.check_mode_requests().expect("mode messaging error");
self.check_mode_replies().expect("mode messaging error");
// TODO: perform target keeping, check whether children are in correct mode.
}
pub fn check_mode_requests(&mut self) -> Result<(), GenericTargetedMessagingError> {
while let Some(request) = self.mode_node.try_recv_mode_request()? {
self.handle_mode_request(request).unwrap();
}
Ok(())
}
pub fn check_mode_replies(&mut self) -> Result<(), ModeError> {
while let Some(reply_and_id) = self.mode_node.try_recv_mode_reply()? {
match self.commanding_helper.handle_mode_reply(&reply_and_id) {
Ok(result) => {
if let DevManagerHelperResult::ModeCommandingDone(context) = result {
// Complete the mode command.
self.mode_and_submode = context.target_mode;
self.handle_mode_reached(self.mode_requestor_info)?;
}
}
Err(err) => match err {
satrs::dev_mgmt::DevManagerHelperError::ChildNotInStore => todo!(),
},
}
}
Ok(())
}
}
impl ModeNode for MgmAssembly {
fn id(&self) -> ComponentId {
Self::id()
}
}
impl ModeParent for MgmAssembly {
type Sender = RequestSenderType;
fn add_mode_child(&mut self, id: ComponentId, request_sender: RequestSenderType) {
self.mode_node.add_request_target(id, request_sender);
self.commanding_helper.add_mode_child(id, UNKNOWN_MODE);
}
}
impl ModeChild for MgmAssembly {
type Sender = ReplySenderType;
fn add_mode_parent(&mut self, id: ComponentId, reply_sender: ReplySenderType) {
self.mode_node.add_reply_target(id, reply_sender);
}
}
impl ModeProvider for MgmAssembly {
fn mode_and_submode(&self) -> ModeAndSubmode {
self.mode_and_submode
}
}
impl ModeRequestHandler for MgmAssembly {
type Error = ModeError;
fn start_transition(
&mut self,
requestor: MessageMetadata,
mode_and_submode: ModeAndSubmode,
forced: bool,
) -> Result<(), Self::Error> {
// Always accept forced commands and commands to mode OFF.
if self.commanding_helper.target_mode().is_some()
&& !forced
&& mode_and_submode.mode() != DeviceMode::Off as u32
{
return Err(ModeError::Busy);
}
self.mode_requestor_info = Some(requestor);
self.commanding_helper.send_mode_cmd_to_all_children(
requestor.request_id(),
mode_and_submode,
forced,
&self.mode_node,
)?;
Ok(())
}
fn announce_mode(&self, requestor_info: Option<MessageMetadata>, recursive: bool) {
println!(
"TestAssembly: Announcing mode (recursively: {}): {:?}",
recursive, self.mode_and_submode
);
let request_id = requestor_info.map_or(0, |info| info.request_id());
self.commanding_helper
.send_announce_mode_cmd_to_children(request_id, &self.mode_node, recursive)
.expect("sending mode request failed");
// TODO: Send announce event.
log::info!(
"MGM assembly announcing mode: {:?}",
self.mode_and_submode()
);
}
fn handle_mode_reached(
&mut self,
mode_requestor: Option<MessageMetadata>,
) -> Result<(), Self::Error> {
if let Some(requestor) = mode_requestor {
self.send_mode_reply(requestor, ModeReply::ModeReply(self.mode_and_submode))?;
}
self.announce_mode(mode_requestor, false);
Ok(())
}
fn handle_mode_info(
&mut self,
requestor_info: MessageMetadata,
info: ModeAndSubmode,
) -> Result<(), Self::Error> {
// TODO: Perform mode keeping.
Ok(())
}
fn send_mode_reply(
&self,
requestor: MessageMetadata,
reply: ModeReply,
) -> Result<(), Self::Error> {
self.mode_node.send_mode_reply(requestor, reply)?;
Ok(())
}
}

View File

@ -2,7 +2,7 @@ use derive_new::new;
use satrs::hk::{HkRequest, HkRequestVariant};
use satrs::mode_tree::{ModeChild, ModeNode};
use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender};
use satrs_example::config::pus::PUS_MODE_SERVICE;
use satrs_example::ids::generic_pus::PUS_MODE;
use satrs_example::{DeviceMode, TimestampHelper};
use satrs_minisim::acs::lis3mdl::{
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
@ -400,6 +400,7 @@ impl<
}
fn announce_mode(&self, _requestor_info: Option<MessageMetadata>, _recursive: bool) {
// TODO: Event
log::info!(
"{} announcing mode: {:?}",
self.dev_str,
@ -417,7 +418,7 @@ impl<
if requestor.sender_id() == NO_SENDER {
return Ok(());
}
if requestor.sender_id() != PUS_MODE_SERVICE.id() {
if requestor.sender_id() != PUS_MODE.id() {
log::warn!(
"can not send back mode reply to sender {:x}",
requestor.sender_id()
@ -434,7 +435,7 @@ impl<
requestor: MessageMetadata,
reply: ModeReply,
) -> Result<(), Self::Error> {
if requestor.sender_id() != PUS_MODE_SERVICE.id() {
if requestor.sender_id() != PUS_MODE.id() {
log::warn!(
"can not send back mode reply to sender {}",
requestor.sender_id()
@ -492,7 +493,7 @@ mod tests {
tmtc::PacketAsVec,
ComponentId,
};
use satrs_example::config::{acs::MGM_ASSEMBLY, components::Apid};
use satrs_example::ids::{acs::MGM_ASSEMBLY, Apid};
use satrs_minisim::acs::lis3mdl::MgmLis3RawValues;
use crate::{eps::TestSwitchHelper, pus::hk::HkReply, requests::CompositeRequest};
@ -538,7 +539,7 @@ mod tests {
impl ModeNode for MgmAssemblyMock {
fn id(&self) -> satrs::ComponentId {
PUS_MODE_SERVICE.into()
PUS_MODE.into()
}
}
@ -557,7 +558,7 @@ mod tests {
impl ModeNode for PusMock {
fn id(&self) -> satrs::ComponentId {
PUS_MODE_SERVICE.into()
PUS_MODE.into()
}
}
@ -592,7 +593,7 @@ mod tests {
TestSpiInterface::default(),
shared_mgm_set,
);
handler.add_mode_parent(PUS_MODE_SERVICE.into(), reply_tx_to_pus);
handler.add_mode_parent(PUS_MODE.into(), reply_tx_to_pus);
handler.add_mode_parent(MGM_ASSEMBLY.into(), reply_tx_to_parent);
Self {
mode_request_tx: request_tx,
@ -631,7 +632,7 @@ mod tests {
testbench
.mode_request_tx
.send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
MessageMetadata::new(0, PUS_MODE.id()),
ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false,
@ -692,7 +693,7 @@ mod tests {
testbench
.mode_request_tx
.send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
MessageMetadata::new(0, PUS_MODE.id()),
ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false,

View File

@ -1,10 +1,7 @@
use satrs::pus::verification::RequestId;
use satrs::spacepackets::ecss::tc::PusTcCreator;
use satrs::spacepackets::ecss::tm::PusTmReader;
use satrs::{
spacepackets::ecss::{PusPacket, WritablePusPacket},
spacepackets::SpHeader,
};
use satrs::{spacepackets::ecss::PusPacket, spacepackets::SpHeader};
use satrs_example::config::{OBSW_SERVER_ADDR, SERVER_PORT};
use std::net::{IpAddr, SocketAddr, UdpSocket};
use std::time::Duration;
@ -29,7 +26,7 @@ fn main() {
let res = client.recv(&mut buf);
match res {
Ok(_len) => {
let (pus_tm, size) = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed");
let pus_tm = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed");
if pus_tm.service() == 17 && pus_tm.subservice() == 2 {
println!("Received PUS Ping Reply TM[17,2]")
} else if pus_tm.service() == 1 {

View File

@ -43,14 +43,14 @@ pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<Severi
lazy_static! {
pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = {
let mut set = HashSet::new();
for id in components::Apid::iter() {
for id in crate::ids::Apid::iter() {
set.insert(PacketId::new(PacketType::Tc, true, id as u16));
}
set
};
pub static ref APID_VALIDATOR: HashSet<u16> = {
let mut set = HashSet::new();
for id in components::Apid::iter() {
for id in crate::ids::Apid::iter() {
set.insert(id as u16);
}
set
@ -122,92 +122,11 @@ pub mod mode_err {
}
pub mod components {
use satrs::{request::UniqueApidTargetId, ComponentId};
use strum::EnumIter;
use satrs::ComponentId;
#[derive(Copy, Clone, PartialEq, Eq, EnumIter)]
pub enum Apid {
Sched = 1,
GenericPus = 2,
Acs = 3,
Cfdp = 4,
Tmtc = 5,
Eps = 6,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum EpsId {
Pcdu = 0,
Subsystem = 1,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum TmtcId {
UdpServer = 0,
TcpServer = 1,
}
pub const EPS_SUBSYSTEM: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Eps as u16, EpsId::Subsystem as u32);
pub const PCDU_HANDLER: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Eps as u16, EpsId::Pcdu as u32);
pub const UDP_SERVER: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::UdpServer as u32);
pub const TCP_SERVER: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Tmtc as u16, TmtcId::TcpServer as u32);
pub const NO_SENDER: ComponentId = ComponentId::MAX;
}
pub mod pus {
use super::components::Apid;
use satrs::request::UniqueApidTargetId;
// Component IDs for components with the PUS APID.
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum PusId {
PusEventManagement = 0,
PusRouting = 1,
PusTest = 2,
PusAction = 3,
PusMode = 4,
PusHk = 5,
}
pub const PUS_ACTION_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusAction as u32);
pub const PUS_EVENT_MANAGEMENT: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, 0);
pub const PUS_ROUTING_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusRouting as u32);
pub const PUS_TEST_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusTest as u32);
pub const PUS_MODE_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusMode as u32);
pub const PUS_HK_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::GenericPus as u16, PusId::PusHk as u32);
pub const PUS_SCHED_SERVICE: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Sched as u16, 0);
}
pub mod acs {
use super::components::Apid;
use satrs::request::UniqueApidTargetId;
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AcsId {
Subsystem = 1,
Assembly = 2,
Mgm0 = 3,
Mgm1 = 4,
}
pub const MGM_ASSEMBLY: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Assembly as u32);
pub const MGM_HANDLER_0: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
pub const MGM_HANDLER_1: UniqueApidTargetId =
UniqueApidTargetId::new(Apid::Acs as u16, AcsId::Mgm0 as u32);
}
pub mod pool {
use super::*;
pub fn create_static_pools() -> (StaticMemoryPool, StaticMemoryPool) {

View File

@ -20,10 +20,8 @@ use satrs::{
spacepackets::ByteConversionError,
};
use satrs_example::{
config::{
components::{NO_SENDER, PCDU_HANDLER},
pus::PUS_MODE_SERVICE,
},
config::components::NO_SENDER,
ids::{eps::PCDU, generic_pus::PUS_MODE},
DeviceMode, TimestampHelper,
};
use satrs_minisim::{
@ -452,7 +450,7 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
if requestor.sender_id() == NO_SENDER {
return Ok(());
}
if requestor.sender_id() != PUS_MODE_SERVICE.id() {
if requestor.sender_id() != PUS_MODE.id() {
log::warn!(
"can not send back mode reply to sender {}",
requestor.sender_id()
@ -469,7 +467,7 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
requestor: MessageMetadata,
reply: ModeReply,
) -> Result<(), Self::Error> {
if requestor.sender_id() != PUS_MODE_SERVICE.id() {
if requestor.sender_id() != PUS_MODE.id() {
log::warn!(
"can not send back mode reply to sender {}",
requestor.sender_id()
@ -492,7 +490,7 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
impl<ComInterface: SerialInterface> ModeNode for PcduHandler<ComInterface> {
fn id(&self) -> satrs::ComponentId {
PCDU_HANDLER.into()
PCDU.into()
}
}
@ -511,10 +509,7 @@ mod tests {
use satrs::{
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
};
use satrs_example::config::{
acs::MGM_HANDLER_0,
components::{Apid, EPS_SUBSYSTEM, PCDU_HANDLER},
};
use satrs_example::ids::{self, Apid};
use satrs_minisim::eps::SwitchMapBinary;
use super::*;
@ -570,8 +565,7 @@ mod tests {
let (mode_request_tx, mode_request_rx) = mpsc::sync_channel(5);
let (mode_reply_tx_to_pus, mode_reply_rx_to_pus) = mpsc::sync_channel(5);
let (mode_reply_tx_to_parent, mode_reply_rx_to_parent) = mpsc::sync_channel(5);
let mode_node =
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), mode_request_rx);
let mode_node = ModeRequestHandlerMpscBounded::new(PCDU.into(), mode_request_rx);
let (composite_request_tx, composite_request_rx) = mpsc::channel();
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
let (tm_tx, tm_rx) = mpsc::sync_channel::<PacketAsVec>(5);
@ -588,8 +582,8 @@ mod tests {
SerialInterfaceTest::default(),
shared_switch_map,
);
handler.add_mode_parent(EPS_SUBSYSTEM.into(), mode_reply_tx_to_parent);
handler.add_mode_parent(PUS_MODE_SERVICE.into(), mode_reply_tx_to_pus);
handler.add_mode_parent(ids::eps::SUBSYSTEM.into(), mode_reply_tx_to_parent);
handler.add_mode_parent(PUS_MODE.into(), mode_reply_tx_to_pus);
Self {
mode_request_tx,
mode_reply_rx_to_pus,
@ -684,7 +678,7 @@ mod tests {
testbench
.mode_request_tx
.send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
MessageMetadata::new(0, PUS_MODE.id()),
ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false,
@ -719,7 +713,7 @@ mod tests {
testbench
.mode_request_tx
.send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
MessageMetadata::new(0, PUS_MODE.id()),
ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false,
@ -729,7 +723,7 @@ mod tests {
testbench
.switch_request_tx
.send(GenericMessage::new(
MessageMetadata::new(0, MGM_HANDLER_0.id()),
MessageMetadata::new(0, ids::acs::MGM0.id()),
SwitchRequest::new(0, SwitchStateBinary::On),
))
.expect("failed to send switch request");

View File

@ -16,7 +16,7 @@ use satrs::{
},
spacepackets::time::cds::CdsTime,
};
use satrs_example::config::pus::PUS_EVENT_MANAGEMENT;
use satrs_example::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use crate::update_time;
@ -281,9 +281,7 @@ mod tests {
.try_recv()
.expect("failed to receive TM packet");
assert_eq!(tm_packet.sender_id, PUS_EVENT_MANAGEMENT.id());
let tm_reader = PusTmReader::new(&tm_packet.packet, 7)
.expect("failed to create TM reader")
.0;
let tm_reader = PusTmReader::new(&tm_packet.packet, 7).expect("failed to create TM reader");
assert_eq!(tm_reader.apid(), TEST_CREATOR_ID.apid);
assert_eq!(tm_reader.user_data().len(), 4);
let event_read_back = EventU32::from_be_bytes(tm_reader.user_data().try_into().unwrap());

94
satrs-example/src/ids.rs Normal file
View File

@ -0,0 +1,94 @@
//! This is an auto-generated configuration module.
use satrs::request::UniqueApidTargetId;
#[derive(Debug, Copy, Clone, PartialEq, Eq, strum::EnumIter)]
pub enum Apid {
Sched = 1,
GenericPus = 2,
Acs = 3,
Cfdp = 4,
Tmtc = 5,
Eps = 6,
}
pub mod acs {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Id {
Subsystem = 1,
MgmAssembly = 2,
Mgm0 = 3,
Mgm1 = 4,
}
pub const SUBSYSTEM: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Subsystem as u32);
pub const MGM_ASSEMBLY: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::MgmAssembly as u32);
pub const MGM0: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Mgm0 as u32);
pub const MGM1: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Mgm1 as u32);
}
pub mod eps {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Id {
Pcdu = 0,
Subsystem = 1,
}
pub const PCDU: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Eps as u16, Id::Pcdu as u32);
pub const SUBSYSTEM: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Eps as u16, Id::Subsystem as u32);
}
pub mod generic_pus {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Id {
PusEventManagement = 0,
PusRouting = 1,
PusTest = 2,
PusAction = 3,
PusMode = 4,
PusHk = 5,
}
pub const PUS_EVENT_MANAGEMENT: super::UniqueApidTargetId = super::UniqueApidTargetId::new(
super::Apid::GenericPus as u16,
Id::PusEventManagement as u32,
);
pub const PUS_ROUTING: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusRouting as u32);
pub const PUS_TEST: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusTest as u32);
pub const PUS_ACTION: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusAction as u32);
pub const PUS_MODE: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusMode as u32);
pub const PUS_HK: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::GenericPus as u16, Id::PusHk as u32);
}
pub mod sched {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Id {
PusSched = 0,
}
pub const PUS_SCHED: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Sched as u16, Id::PusSched as u32);
}
pub mod tmtc {
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum Id {
UdpServer = 0,
TcpServer = 1,
}
pub const UDP_SERVER: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Tmtc as u16, Id::UdpServer as u32);
pub const TCP_SERVER: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Tmtc as u16, Id::TcpServer as u32);
}

View File

@ -119,7 +119,8 @@ mod tests {
},
ComponentId,
};
use satrs_example::config::{components, OBSW_SERVER_ADDR};
use satrs_example::config::OBSW_SERVER_ADDR;
use satrs_example::ids;
use crate::tmtc::sender::{MockSender, TmTcSender};
@ -175,7 +176,7 @@ mod tests {
udp_tc_server,
tm_handler,
};
let sph = SpHeader::new_for_unseg_tc(components::Apid::GenericPus as u16, 0, 0);
let sph = SpHeader::new_for_unseg_tc(ids::Apid::GenericPus as u16, 0, 0);
let ping_tc = PusTcCreator::new_simple(sph, 17, 1, &[], true)
.to_vec()
.unwrap();

View File

@ -1,6 +1,7 @@
use satrs::spacepackets::time::{cds::CdsTime, TimeWriter};
pub mod config;
pub mod ids;
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum DeviceMode {

View File

@ -5,7 +5,10 @@ use std::{
time::Duration,
};
use acs::mgm::{MgmHandlerLis3Mdl, SpiDummyInterface, SpiSimInterface, SpiSimInterfaceWrapper};
use acs::{
assembly::MgmAssembly,
mgm::{MgmHandlerLis3Mdl, SpiDummyInterface, SpiSimInterface, SpiSimInterfaceWrapper},
};
use eps::{
pcdu::{PcduHandler, SerialInterfaceDummy, SerialInterfaceToSim, SerialSimInterfaceWrapper},
PowerSwitchHelper,
@ -31,7 +34,10 @@ use pus::{
use requests::GenericRequestRouter;
use satrs::{
hal::std::{tcp_server::ServerConfig, udp_server::UdpTcServer},
mode::{Mode, ModeAndSubmode, ModeRequest, ModeRequestHandlerMpscBounded},
mode::{
Mode, ModeAndSubmode, ModeRequest, ModeRequestHandlerMpscBounded,
ModeRequestorAndHandlerMpscBounded,
},
mode_tree::connect_mode_nodes,
pus::{event_man::EventRequestWithToken, EcssTcInMemConverter, HandlingStatus},
request::{GenericMessage, MessageMetadata},
@ -39,12 +45,16 @@ use satrs::{
};
use satrs_example::{
config::{
acs::{MGM_HANDLER_0, MGM_HANDLER_1},
components::{NO_SENDER, PCDU_HANDLER, TCP_SERVER, UDP_SERVER},
components::NO_SENDER,
pool::create_sched_tc_pool,
tasks::{FREQ_MS_AOCS, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS},
OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
},
ids::{
acs::*,
eps::*,
tmtc::{TCP_SERVER, UDP_SERVER},
},
DeviceMode,
};
use tmtc::sender::TmTcSender;
@ -124,13 +134,13 @@ fn main() {
let mut request_map = GenericRequestRouter::default();
request_map
.composite_router_map
.insert(MGM_HANDLER_0.id(), mgm_0_handler_composite_tx);
.insert(MGM0.id(), mgm_0_handler_composite_tx);
request_map
.composite_router_map
.insert(MGM_HANDLER_0.id(), mgm_1_handler_composite_tx);
.insert(MGM1.id(), mgm_1_handler_composite_tx);
request_map
.composite_router_map
.insert(PCDU_HANDLER.id(), pcdu_handler_composite_tx);
.insert(PCDU.id(), pcdu_handler_composite_tx);
// This helper structure is used by all telecommand providers which need to send telecommands
// to the TC source.
@ -299,12 +309,19 @@ fn main() {
let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20);
let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone());
let (mgm_assy_mode_req_tx, mgm_assy_mode_req_rx) = mpsc::sync_channel(20);
let (mgm_assy_mode_reply_tx, mgm_assy_mode_reply_rx) = mpsc::sync_channel(20);
let mgm_assembly_mode_node = ModeRequestorAndHandlerMpscBounded::new(
MgmAssembly::id(),
mgm_assy_mode_req_rx,
mgm_assy_mode_reply_rx,
);
let mut mgm_assembly = MgmAssembly::new(mgm_assembly_mode_node);
let shared_mgm_0_set = Arc::default();
let shared_mgm_1_set = Arc::default();
let mgm_0_mode_node =
ModeRequestHandlerMpscBounded::new(MGM_HANDLER_0.into(), mgm_0_handler_mode_rx);
let mgm_1_mode_node =
ModeRequestHandlerMpscBounded::new(MGM_HANDLER_1.into(), mgm_1_handler_mode_rx);
let mgm_0_mode_node = ModeRequestHandlerMpscBounded::new(MGM0.into(), mgm_0_handler_mode_rx);
let mgm_1_mode_node = ModeRequestHandlerMpscBounded::new(MGM1.into(), mgm_1_handler_mode_rx);
let (mgm_0_spi_interface, mgm_1_spi_interface) =
if let Some(sim_client) = opt_sim_client.as_mut() {
sim_client
@ -328,7 +345,7 @@ fn main() {
)
};
let mut mgm_0_handler = MgmHandlerLis3Mdl::new(
MGM_HANDLER_0,
MGM0,
"MGM_0",
mgm_0_mode_node,
mgm_0_handler_composite_rx,
@ -339,7 +356,7 @@ fn main() {
shared_mgm_0_set,
);
let mut mgm_1_handler = MgmHandlerLis3Mdl::new(
MGM_HANDLER_1,
MGM1,
"MGM_1",
mgm_1_mode_node,
mgm_1_handler_composite_rx,
@ -362,6 +379,19 @@ fn main() {
&mut mgm_1_handler,
pus_mode_reply_tx.clone(),
);
// Connect assembly to device handlers.
connect_mode_nodes(
&mut mgm_assembly,
mgm_assy_mode_req_tx.clone(),
&mut mgm_1_handler,
mgm_assy_mode_reply_tx.clone(),
);
connect_mode_nodes(
&mut mgm_assembly,
mgm_assy_mode_req_tx,
&mut mgm_1_handler,
mgm_assy_mode_reply_tx,
);
let pcdu_serial_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
sim_client.add_reply_recipient(satrs_minisim::SimComponent::Pcdu, pcdu_sim_reply_tx);
@ -372,10 +402,9 @@ fn main() {
} else {
SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default())
};
let pcdu_mode_node =
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), pcdu_handler_mode_rx);
let pcdu_mode_node = ModeRequestHandlerMpscBounded::new(PCDU.into(), pcdu_handler_mode_rx);
let mut pcdu_handler = PcduHandler::new(
PCDU_HANDLER,
PCDU,
"PCDU",
pcdu_mode_node,
pcdu_handler_composite_rx,
@ -454,6 +483,7 @@ fn main() {
let jh_aocs = thread::Builder::new()
.name("sat-rs aocs".to_string())
.spawn(move || loop {
mgm_assembly.periodic_operation();
mgm_0_handler.periodic_operation();
mgm_1_handler.periodic_operation();
thread::sleep(Duration::from_millis(FREQ_MS_AOCS));

View File

@ -16,8 +16,9 @@ use satrs::pus::{
use satrs::request::{GenericMessage, UniqueApidTargetId};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{EcssEnumU16, PusPacket, PusServiceId};
use satrs_example::config::pus::PUS_ACTION_SERVICE;
use satrs_example::config::tmtc_err;
use satrs_example::ids;
use satrs_example::ids::generic_pus::PUS_ACTION;
use std::sync::mpsc;
use std::time::Duration;
@ -214,10 +215,10 @@ pub fn create_action_service(
) -> ActionServiceWrapper {
let action_request_handler = PusTargetedRequestService::new(
PusServiceHelper::new(
PUS_ACTION_SERVICE.id(),
ids::generic_pus::PUS_ACTION.id(),
pus_action_rx,
tm_sender,
create_verification_reporter(PUS_ACTION_SERVICE.id(), PUS_ACTION_SERVICE.apid),
create_verification_reporter(PUS_ACTION.id(), PUS_ACTION.apid),
tc_in_mem_converter,
),
ActionRequestConverter::default(),
@ -367,7 +368,7 @@ mod tests {
if let Err(mpsc::TryRecvError::Empty) = packet {
} else {
let tm = packet.unwrap();
let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap().0;
let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap();
panic!("unexpected TM packet {unexpected_tm:?}");
}
}
@ -410,7 +411,11 @@ mod tests {
pub fn add_tc(&mut self, tc: &PusTcCreator) {
self.request_id = Some(verification::RequestId::new(tc).into());
let token = self.service.service_helper.verif_reporter_mut().add_tc(tc);
let token = self
.service
.service_helper
.verif_reporter_mut()
.start_verification(tc);
let accepted_token = self
.service
.service_helper

View File

@ -10,7 +10,7 @@ use satrs::pus::{
PartialPusHandlingError, PusServiceHelper,
};
use satrs::spacepackets::ecss::PusServiceId;
use satrs_example::config::pus::PUS_EVENT_MANAGEMENT;
use satrs_example::ids::generic_pus::PUS_EVENT_MANAGEMENT;
use super::{DirectPusService, HandlingStatus};

View File

@ -13,8 +13,8 @@ use satrs::request::{GenericMessage, UniqueApidTargetId};
use satrs::res_code::ResultU16;
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{hk, PusPacket, PusServiceId};
use satrs_example::config::pus::PUS_HK_SERVICE;
use satrs_example::config::{hk_err, tmtc_err};
use satrs_example::ids::generic_pus::PUS_HK;
use std::sync::mpsc;
use std::time::Duration;
@ -249,10 +249,10 @@ pub fn create_hk_service(
) -> HkServiceWrapper {
let pus_3_handler = PusTargetedRequestService::new(
PusServiceHelper::new(
PUS_HK_SERVICE.id(),
PUS_HK.id(),
pus_hk_rx,
tm_sender,
create_verification_reporter(PUS_HK_SERVICE.id(), PUS_HK_SERVICE.apid),
create_verification_reporter(PUS_HK.id(), PUS_HK.apid),
tc_in_mem_converter,
),
HkRequestConverter::default(),

View File

@ -18,8 +18,8 @@ use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
use satrs::tmtc::{PacketAsVec, PacketInPool};
use satrs::ComponentId;
use satrs_example::config::pus::PUS_ROUTING_SERVICE;
use satrs_example::config::{tmtc_err, CustomPusServiceId};
use satrs_example::ids::generic_pus::PUS_ROUTING;
use satrs_example::TimestampHelper;
use std::fmt::Debug;
use std::sync::mpsc;
@ -62,12 +62,9 @@ pub struct PusTcDistributor {
impl PusTcDistributor {
pub fn new(tm_sender: TmTcSender, pus_router: PusTcMpscRouter) -> Self {
Self {
id: PUS_ROUTING_SERVICE.raw(),
id: PUS_ROUTING.raw(),
tm_sender,
verif_reporter: create_verification_reporter(
PUS_ROUTING_SERVICE.id(),
PUS_ROUTING_SERVICE.apid,
),
verif_reporter: create_verification_reporter(PUS_ROUTING.id(), PUS_ROUTING.apid),
pus_router,
stamp_helper: TimestampHelper::default(),
}
@ -109,8 +106,8 @@ impl PusTcDistributor {
// TODO: Shouldn't this be an error?
return Ok(HandlingStatus::HandledOne);
}
let pus_tc = pus_tc_result.unwrap().0;
let init_token = self.verif_reporter.add_tc(&pus_tc);
let pus_tc = pus_tc_result.unwrap();
let init_token = self.verif_reporter.start_verification(&pus_tc);
self.stamp_helper.update_from_now();
let accepted_token = self
.verif_reporter
@ -599,7 +596,7 @@ pub(crate) mod tests {
) -> (verification::RequestId, ActivePusRequestStd) {
let sp_header = SpHeader::new_from_apid(apid);
let sec_header_dummy = PusTcSecondaryHeader::new_simple(0, 0);
let init = self.verif_reporter.add_tc(&PusTcCreator::new(
let init = self.verif_reporter.start_verification(&PusTcCreator::new(
sp_header,
sec_header_dummy,
&[],
@ -706,7 +703,7 @@ pub(crate) mod tests {
}
pub fn add_tc(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let token = self.verif_reporter.add_tc(tc);
let token = self.verif_reporter.start_verification(tc);
self.current_request_id = Some(verification::RequestId::new(tc));
self.current_packet = Some(tc.to_vec().unwrap());
self.verif_reporter
@ -734,7 +731,7 @@ pub(crate) mod tests {
let tc_reader = PusTcReader::new(&current_packet).unwrap();
let (active_info, request) = self.converter.convert(
token,
&tc_reader.0,
&tc_reader,
&self.dummy_sender,
&self.verif_reporter,
time_stamp,

View File

@ -1,6 +1,6 @@
use derive_new::new;
use satrs::mode_tree::{ModeNode, ModeParent};
use satrs_example::config::pus::PUS_MODE_SERVICE;
use satrs_example::ids;
use std::sync::mpsc;
use std::time::Duration;
@ -217,15 +217,18 @@ pub fn create_mode_service(
) -> ModeServiceWrapper {
let mode_request_handler = PusTargetedRequestService::new(
PusServiceHelper::new(
PUS_MODE_SERVICE.id(),
ids::generic_pus::PUS_MODE.id(),
pus_action_rx,
tm_sender,
create_verification_reporter(PUS_MODE_SERVICE.id(), PUS_MODE_SERVICE.apid),
create_verification_reporter(
ids::generic_pus::PUS_MODE.id(),
ids::generic_pus::PUS_MODE.apid,
),
tc_in_mem_converter,
),
ModeRequestConverter::default(),
DefaultActiveRequestMap::default(),
ModeReplyHandler::new(PUS_MODE_SERVICE.id()),
ModeReplyHandler::new(ids::generic_pus::PUS_MODE.id()),
mode_router,
reply_receiver,
);

View File

@ -15,7 +15,7 @@ use satrs::pus::{
use satrs::spacepackets::ecss::PusServiceId;
use satrs::tmtc::{PacketAsVec, PacketInPool, PacketSenderWithSharedPool};
use satrs::ComponentId;
use satrs_example::config::pus::PUS_SCHED_SERVICE;
use satrs_example::ids::sched::PUS_SCHED;
use super::{DirectPusService, HandlingStatus};
@ -183,10 +183,10 @@ pub fn create_scheduler_service(
.expect("Creating PUS Scheduler failed");
let pus_11_handler = PusSchedServiceHandler::new(
PusServiceHelper::new(
PUS_SCHED_SERVICE.id(),
PUS_SCHED.id(),
pus_sched_rx,
tm_sender,
create_verification_reporter(PUS_SCHED_SERVICE.id(), PUS_SCHED_SERVICE.apid),
create_verification_reporter(PUS_SCHED.id(), PUS_SCHED.apid),
tc_in_mem_converter,
),
scheduler,

View File

@ -11,8 +11,8 @@ use satrs::pus::{
};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
use satrs_example::config::pus::PUS_TEST_SERVICE;
use satrs_example::config::{tmtc_err, TEST_EVENT};
use satrs_example::ids::generic_pus::PUS_TEST;
use std::sync::mpsc;
use super::{DirectPusService, HandlingStatus};
@ -24,10 +24,10 @@ pub fn create_test_service(
pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
) -> TestCustomServiceWrapper {
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
PUS_TEST_SERVICE.id(),
PUS_TEST.id(),
pus_test_rx,
tm_sender,
create_verification_reporter(PUS_TEST_SERVICE.id(), PUS_TEST_SERVICE.apid),
create_verification_reporter(PUS_TEST.id(), PUS_TEST.apid),
tc_in_mem_converter,
));
TestCustomServiceWrapper {
@ -90,7 +90,7 @@ impl DirectPusService for TestCustomServiceWrapper {
);
}
DirectPusPacketHandlerResult::CustomSubservice(subservice, token) => {
let (tc, _) = PusTcReader::new(
let tc = PusTcReader::new(
self.handler
.service_helper
.tc_in_mem_converter
@ -100,7 +100,7 @@ impl DirectPusService for TestCustomServiceWrapper {
if subservice == 128 {
info!("generating test event");
self.event_tx
.send(EventMessage::new(PUS_TEST_SERVICE.id(), TEST_EVENT.into()))
.send(EventMessage::new(PUS_TEST.id(), TEST_EVENT.into()))
.expect("Sending test event failed");
match self.handler.service_helper.verif_reporter().start_success(
self.handler.service_helper.tm_sender(),

View File

@ -14,8 +14,8 @@ use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::PusPacket;
use satrs::ComponentId;
use satrs_example::config::pus::PUS_ROUTING_SERVICE;
use satrs_example::config::tmtc_err;
use satrs_example::ids;
#[derive(Clone, Debug)]
#[non_exhaustive]
@ -37,7 +37,7 @@ pub struct GenericRequestRouter {
impl Default for GenericRequestRouter {
fn default() -> Self {
Self {
id: PUS_ROUTING_SERVICE.raw(),
id: ids::generic_pus::PUS_ROUTING.raw(),
composite_router_map: Default::default(),
mode_router_map: Default::default(),
}

View File

@ -11,7 +11,9 @@ use crate::pus::PusTcDistributor;
pub struct TcSourceTaskStatic {
shared_tc_pool: SharedPacketPool,
tc_receiver: mpsc::Receiver<PacketInPool>,
tc_buf: [u8; 4096],
/// We allocate this buffer from the heap to avoid a clippy warning on large enum variant
/// differences.
tc_buf: Box<[u8; 4096]>,
pus_distributor: PusTcDistributor,
}
@ -25,7 +27,7 @@ impl TcSourceTaskStatic {
Self {
shared_tc_pool,
tc_receiver,
tc_buf: [0; 4096],
tc_buf: Box::new([0; 4096]),
pus_distributor: pus_receiver,
}
}
@ -44,11 +46,11 @@ impl TcSourceTaskStatic {
.0
.read()
.expect("locking tc pool failed");
pool.read(&packet_in_pool.store_addr, &mut self.tc_buf)
pool.read(&packet_in_pool.store_addr, self.tc_buf.as_mut_slice())
.expect("reading pool failed");
drop(pool);
self.pus_distributor
.handle_tc_packet_in_store(packet_in_pool, &self.tc_buf)
.handle_tc_packet_in_store(packet_in_pool, self.tc_buf.as_slice())
.ok();
HandlingStatus::HandledOne
}

View File

@ -23,7 +23,8 @@ version = "1"
optional = true
[dependencies.satrs-shared]
version = ">=0.1.3, <=0.2"
version = "0.2.2"
path = "../satrs-shared"
features = ["serde"]
[dependencies.satrs-mib-codegen]

View File

@ -28,7 +28,8 @@ features = ["full"]
trybuild = { version = "1", features = ["diff"] }
[dev-dependencies.satrs-shared]
version = ">=0.1.3, <=0.2"
version = "0.2.2"
path = "../../satrs-shared"
[dev-dependencies.satrs-mib]
path = ".."

View File

@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased]
# [v0.2.2] 2025-05-10
- Bump to `spacepackests` v0.14
# [v0.2.1] 2024-11-15
Increased allowed spacepackets to v0.13
@ -41,3 +45,6 @@ Allow `spacepackets` range starting with v0.10 and v0.11.
# [v0.1.0] 2024-02-12
Initial release.
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.2...HEAD
[v0.2.2]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.1...satrs-shared-v0.2.2

View File

@ -1,7 +1,7 @@
[package]
name = "satrs-shared"
description = "Components shared by multiple sat-rs crates"
version = "0.2.1"
version = "0.2.2"
edition = "2021"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
@ -11,6 +11,7 @@ license = "Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
spacepackets = { version = ">=0.14, <=0.15", git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", default-features = false }
[dependencies.serde]
version = "1"
@ -18,12 +19,9 @@ default-features = false
optional = true
[dependencies.defmt]
version = "0.3"
version = "1"
optional = true
[dependencies.spacepackets]
version = ">0.9, <=0.13"
default-features = false
[features]
serde = ["dep:serde", "spacepackets/serde"]

View File

@ -4,8 +4,8 @@ version = "0.3.0-alpha.0"
edition = "2021"
rust-version = "1.82.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
description = "A framework to build software for remote systems"
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
description = "A library collection to build software for remote systems"
homepage = "https://github.com/us-irs/sat-rs"
repository = "https://egit.irs.uni-stuttgart.de/rust/sat-rs"
license = "Apache-2.0"
keywords = ["no-std", "space", "aerospace"]
@ -13,16 +13,14 @@ keywords = ["no-std", "space", "aerospace"]
categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-support", "embedded"]
[dependencies]
satrs-shared = ">=0.1.3, <=0.2"
satrs-shared = { version = "0.2.2", path = "../satrs-shared" }
spacepackets = { version = ">=0.14, <=0.15", git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", default-features = false }
delegate = ">0.7, <=0.13"
paste = "1"
derive-new = ">=0.6, <=0.7"
smallvec = "1"
crc = "3"
num_enum = { version = ">0.5, <=0.7", default-features = false }
spacepackets = { version = "0.13", default-features = false }
cobs = { version = "0.3", default-features = false }
num-traits = { version = "0.2", default-features = false }
cobs = { version = "0.4", default-features = false, git = "https://github.com/jamesmunns/cobs.rs.git", branch = "main" }
thiserror = { version = "2", default-features = false }
hashbrown = { version = ">=0.14, <=0.15", optional = true }

View File

@ -4,5 +4,5 @@
sat-rs
======
This crate contains the primary components of the sat-rs framework.
This crate contains the primary components of the sat-rs library collection.
You can find more information on the [homepage](https://egit.irs.uni-stuttgart.de/rust/sat-rs).

View File

@ -24,8 +24,8 @@ use cobs::{decode_in_place, encode, max_encoding_length};
/// assert!(encode_packet_with_cobs(&INVERTED_PACKET, &mut encoding_buf, &mut current_idx));
/// assert_eq!(encoding_buf[0], 0);
/// let dec_report = decode_in_place_report(&mut encoding_buf[1..]).expect("decoding failed");
/// assert_eq!(encoding_buf[1 + dec_report.src_used], 0);
/// assert_eq!(dec_report.dst_used, 5);
/// assert_eq!(encoding_buf[1 + dec_report.parsed_size()], 0);
/// assert_eq!(dec_report.frame_size(), 5);
/// assert_eq!(current_idx, 16);
/// ```
pub fn encode_packet_with_cobs(

View File

@ -162,7 +162,7 @@ pub trait SenderMapProvider<
/// * `ListenerMap`: [ListenerMapProvider] which maps listener keys to channel IDs.
/// * `EventSender`: [EventSendProvider] contained within the sender map which sends the events.
/// * `Event`: The event type. This type must implement the [GenericEvent]. Currently only [EventU32]
/// and [EventU16] are supported.
/// and [EventU16] are supported.
/// * `ParamProvider`: Auxiliary data which is sent with the event to provide optional context
/// information
pub struct EventManager<

View File

@ -312,11 +312,11 @@ impl EventU32 {
/// # Parameter
///
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
/// be stored inside the uppermost 2 bits of the raw event ID
/// be stored inside the uppermost 2 bits of the raw event ID
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
/// next 14 bits after the severity. Therefore, the size is limited by dec 16383 hex 0x3FFF.
/// * `unique_id`: Each event has a unique 16 bit ID occupying the last 16 bits of the
/// raw event ID
/// raw event ID
pub fn new_checked(
severity: Severity,
group_id: <Self as GenericEvent>::GroupId,
@ -486,11 +486,11 @@ impl EventU16 {
/// # Parameter
///
/// * `severity`: Each event has a [severity][Severity]. The raw value of the severity will
/// be stored inside the uppermost 2 bits of the raw event ID
/// be stored inside the uppermost 2 bits of the raw event ID
/// * `group_id`: Related events can be grouped using a group ID. The group ID will occupy the
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F.
/// next 6 bits after the severity. Therefore, the size is limited by dec 63 hex 0x3F.
/// * `unique_id`: Each event has a unique 8 bit ID occupying the last 8 bits of the
/// raw event ID
/// raw event ID
pub fn new_checked(
severity: Severity,
group_id: <Self as GenericEvent>::GroupId,

View File

@ -39,9 +39,9 @@ pub trait ExecutableWithType: Executable {
///
/// * `executable`: Executable task
/// * `task_freq`: Optional frequency of task. Required for periodic and fixed cycle tasks.
/// If [None] is passed, no sleeping will be performed.
/// If [None] is passed, no sleeping will be performed.
/// * `op_code`: Operation code which is passed to the executable task
/// [operation call][Executable::periodic_op]
/// [operation call][Executable::periodic_op]
/// * `termination`: Optional termination handler which can cancel threads with a broadcast
pub fn exec_sched_single<
T: ExecutableWithType<Error = E> + Send + 'static + ?Sized,

View File

@ -150,9 +150,9 @@ impl<
///
/// * `cfg` - Configuration of the server.
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
/// then sent back to the client.
/// then sent back to the client.
/// * `tc_receiver` - Any received telecommands which were decoded successfully will be
/// forwarded to this TC receiver.
/// forwarded to this TC receiver.
pub fn new(
cfg: ServerConfig,
tm_source: TmSource,
@ -377,13 +377,13 @@ mod tests {
current_idx += 1;
let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed");
assert_eq!(dec_report.dst_used, 5);
assert_eq!(dec_report.frame_size(), 5);
// Skip first sentinel byte.
assert_eq!(
&read_buf[current_idx..current_idx + INVERTED_PACKET.len()],
&INVERTED_PACKET
);
current_idx += dec_report.src_used;
current_idx += dec_report.parsed_size();
// End sentinel.
assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte");
current_idx += 1;
@ -393,13 +393,13 @@ mod tests {
current_idx += 1;
dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed");
assert_eq!(dec_report.dst_used, 5);
assert_eq!(dec_report.frame_size(), 5);
// Skip first sentinel byte.
assert_eq!(
&read_buf[current_idx..current_idx + SIMPLE_PACKET.len()],
&SIMPLE_PACKET
);
current_idx += dec_report.src_used;
current_idx += dec_report.parsed_size();
// End sentinel.
assert_eq!(read_buf[current_idx], 0);
break;

View File

@ -25,22 +25,22 @@ pub use crate::hal::std::tcp_spacepackets_server::{SpacepacketsTmSender, TcpSpac
///
/// * `addr` - Address of the TCP server.
/// * `inner_loop_delay` - If a client connects for a longer period, but no TC is received or
/// no TM needs to be sent, the TCP server will delay for the specified amount of time
/// to reduce CPU load.
/// no TM needs to be sent, the TCP server will delay for the specified amount of time
/// to reduce CPU load.
/// * `tm_buffer_size` - Size of the TM buffer used to read TM from the [PacketSource] and
/// encoding of that data. This buffer should at large enough to hold the maximum expected
/// TM size read from the packet source.
/// encoding of that data. This buffer should at large enough to hold the maximum expected
/// TM size read from the packet source.
/// * `tc_buffer_size` - Size of the TC buffer used to read encoded telecommands sent from
/// the client. It is recommended to make this buffer larger to allow reading multiple
/// consecutive packets as well, for example by using common buffer sizes like 4096 or 8192
/// byte. The buffer should at the very least be large enough to hold the maximum expected
/// telecommand size.
/// the client. It is recommended to make this buffer larger to allow reading multiple
/// consecutive packets as well, for example by using common buffer sizes like 4096 or 8192
/// byte. The buffer should at the very least be large enough to hold the maximum expected
/// telecommand size.
/// * `reuse_addr` - Can be used to set the `SO_REUSEADDR` option on the raw socket. This is
/// especially useful if the address and port are static for the server. Set to false by
/// default.
/// especially useful if the address and port are static for the server. Set to false by
/// default.
/// * `reuse_port` - Can be used to set the `SO_REUSEPORT` option on the raw socket. This is
/// especially useful if the address and port are static for the server. Set to false by
/// default.
/// especially useful if the address and port are static for the server. Set to false by
/// default.
#[derive(Debug, Copy, Clone)]
pub struct ServerConfig {
pub id: ComponentId,
@ -211,12 +211,12 @@ impl<
///
/// * `cfg` - Configuration of the server.
/// * `tc_parser` - Parser which extracts telecommands from the raw bytestream received from
/// the client.
/// the client.
/// * `tm_sender` - Sends back telemetry to the client using the specified TM source.
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
/// then sent back to the client.
/// then sent back to the client.
/// * `tc_sender` - Any received telecommand which was decoded successfully will be forwarded
/// using this TC sender.
/// using this TC sender.
/// * `stop_signal` - Can be used to stop the server even if a connection is ongoing.
pub fn new(
cfg: ServerConfig,

View File

@ -120,15 +120,15 @@ impl<
///
/// * `cfg` - Configuration of the server.
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
/// then sent back to the client.
/// then sent back to the client.
/// * `tc_sender` - Any received telecommands which were decoded successfully will be
/// forwarded using this [PacketSenderRaw].
/// forwarded using this [PacketSenderRaw].
/// * `validator` - Used to determine the space packets relevant for further processing and
/// to detect broken space packets.
/// to detect broken space packets.
/// * `handled_connection_hook` - Called to notify the user about a succesfully handled
/// connection.
/// connection.
/// * `stop_signal` - Can be used to shut down the TCP server even for longer running
/// connections.
/// connections.
pub fn new(
cfg: ServerConfig,
tm_source: TmSource,

View File

@ -770,11 +770,11 @@ mod alloc_mod {
/// # Parameters
///
/// * `cfg` - Vector of tuples which represent a subpool. The first entry in the tuple specifies
/// the number of memory blocks in the subpool, the second entry the size of the blocks
/// the number of memory blocks in the subpool, the second entry the size of the blocks
/// * `spill_to_higher_subpools` - Specifies whether data will be spilled to higher subpools
/// if the next fitting subpool is full. This is useful to ensure the pool remains useful
/// for all data sizes as long as possible. However, an undesirable side-effect might be
/// the chocking of larger subpools by underdimensioned smaller subpools.
/// if the next fitting subpool is full. This is useful to ensure the pool remains useful
/// for all data sizes as long as possible. However, an undesirable side-effect might be
/// the chocking of larger subpools by underdimensioned smaller subpools.
#[derive(Debug, Clone)]
pub struct StaticPoolConfig {
cfg: Vec<SubpoolConfig>,

View File

@ -409,7 +409,7 @@ mod tests {
assert!(res.event_was_enabled);
assert!(res.params_were_propagated);
let event_tm = event_rx.try_recv().expect("no event received");
let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
let tm = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
assert_eq!(tm.service(), 5);
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
assert_eq!(tm.user_data().len(), 4 + param_data.len());
@ -437,7 +437,7 @@ mod tests {
assert!(res.event_was_enabled);
assert!(res.params_were_propagated);
let event_tm = event_rx.try_recv().expect("no event received");
let (tm, _) = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
let tm = PusTmReader::new(&event_tm.packet, 7).expect("reading TM failed");
assert_eq!(tm.service(), 5);
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
assert_eq!(tm.user_data().len(), 4 + param_data.len());

View File

@ -199,8 +199,12 @@ mod tests {
}
impl PusTestHarness for Pus5HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler
.service_helper
.verif_reporter()
@ -245,7 +249,7 @@ mod tests {
.write_to_be_bytes(&mut app_data)
.expect("writing test event failed");
let ping_tc = PusTcCreator::new(sp_header, sec_header, &app_data, true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
test_harness.handle_one_tc().unwrap();
@ -306,7 +310,7 @@ mod tests {
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sec_header = PusTcSecondaryHeader::new_simple(5, 200);
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_ok());
@ -326,7 +330,7 @@ mod tests {
let sec_header =
PusTcSecondaryHeader::new_simple(5, Subservice::TcEnableEventGeneration as u8);
let ping_tc = PusTcCreator::new(sp_header, sec_header, &[0, 1, 2], true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_err());

View File

@ -959,15 +959,11 @@ pub mod std_mod {
possible_packet: &TcInMemory,
) -> Result<PusTcReader<'_>, PusTcFromMemError> {
self.cache(possible_packet)?;
Ok(PusTcReader::new(self.tc_slice_raw())
.map_err(EcssTmtcError::Pus)?
.0)
Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
}
fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> {
Ok(PusTcReader::new(self.tc_slice_raw())
.map_err(EcssTmtcError::Pus)?
.0)
Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
}
}
@ -1279,7 +1275,7 @@ pub mod test_util {
UniqueApidTargetId::new(TEST_APID, TEST_UNIQUE_ID_1);
pub trait PusTestHarness {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted>;
fn send_tc(&self, token: &VerificationToken<TcStateAccepted>, tc: &PusTcCreator);
fn read_next_tm(&mut self) -> PusTmReader<'_>;
fn check_no_tm_available(&self) -> bool;
@ -1459,7 +1455,7 @@ pub mod tests {
let tm_pool = self.tm_pool.0.read().unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
self.tm_buf[0..tm_raw.len()].copy_from_slice(&tm_raw);
PusTmReader::new(&self.tm_buf, 7).unwrap().0
PusTmReader::new(&self.tm_buf, 7).unwrap()
}
pub fn check_no_tm_available(&self) -> bool {
@ -1476,7 +1472,7 @@ pub mod tests {
let tm_in_pool = next_msg.unwrap();
let tm_pool = self.tm_pool.0.read().unwrap();
let tm_raw = tm_pool.read_as_vec(&tm_in_pool.store_addr).unwrap();
let tm = PusTmReader::new(&tm_raw, 7).unwrap().0;
let tm = PusTmReader::new(&tm_raw, 7).unwrap();
assert_eq!(PusPacket::service(&tm), 1);
assert_eq!(PusPacket::subservice(&tm), subservice);
assert_eq!(tm.apid(), TEST_APID);
@ -1584,9 +1580,7 @@ pub mod tests {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
self.current_tm = Some(next_msg.unwrap().packet);
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7)
.unwrap()
.0
PusTmReader::new(self.current_tm.as_ref().unwrap(), 7).unwrap()
}
pub fn check_no_tm_available(&self) -> bool {
@ -1601,7 +1595,7 @@ pub mod tests {
let next_msg = self.tm_receiver.try_recv();
assert!(next_msg.is_ok());
let next_msg = next_msg.unwrap();
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap().0;
let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap();
assert_eq!(PusPacket::service(&tm), 1);
assert_eq!(PusPacket::subservice(&tm), subservice);
assert_eq!(tm.apid(), TEST_APID);

View File

@ -292,10 +292,10 @@ pub trait PusSchedulerProvider {
pool: &mut (impl PoolProvider + ?Sized),
) -> Result<TcInfo, ScheduleError> {
let check_tc = PusTcReader::new(tc)?;
if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
return Err(ScheduleError::NestedScheduledTc);
}
let req_id = RequestId::from_tc(&check_tc.0);
let req_id = RequestId::from_tc(&check_tc);
match pool.add(tc) {
Ok(addr) => {
@ -411,10 +411,10 @@ pub mod alloc_mod {
///
/// * `init_current_time` - The time to initialize the scheduler with.
/// * `time_margin` - This time margin is used when inserting new telecommands into the
/// schedule. If the release time of a new telecommand is earlier than the time margin
/// added to the current time, it will not be inserted into the schedule.
/// schedule. If the release time of a new telecommand is earlier than the time margin
/// added to the current time, it will not be inserted into the schedule.
/// * `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 {
PusScheduler {
tc_map: Default::default(),
@ -480,10 +480,10 @@ pub mod alloc_mod {
pool: &mut (impl PoolProvider + ?Sized),
) -> Result<TcInfo, ScheduleError> {
let check_tc = PusTcReader::new(tc)?;
if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
return Err(ScheduleError::NestedScheduledTc);
}
let req_id = RequestId::from_tc(&check_tc.0);
let req_id = RequestId::from_tc(&check_tc);
match pool.add(tc) {
Ok(addr) => {
@ -683,10 +683,10 @@ pub mod alloc_mod {
/// # Arguments
///
/// * `releaser` - Closure where the first argument is whether the scheduler is enabled and
/// the second argument is the telecommand information also containing the store
/// address. This closure should return whether the command should be deleted. Please
/// note that returning false might lead to memory leaks if the TC is not cleared from
/// the store in some other way.
/// the second argument is the telecommand information also containing the store
/// address. This closure should return whether the command should be deleted. Please
/// note that returning false might lead to memory leaks if the TC is not cleared from
/// the store in some other way.
/// * `tc_store` - The holding store of the telecommands.
/// * `tc_buf` - Buffer to hold each telecommand being released.
pub fn release_telecommands_with_buffer<R: FnMut(bool, &TcInfo, &[u8]) -> bool>(
@ -1313,7 +1313,7 @@ mod tests {
let mut read_buf: [u8; 64] = [0; 64];
pool.read(&tc_info_0.addr(), &mut read_buf).unwrap();
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
@ -1335,8 +1335,8 @@ mod tests {
let read_len = pool.read(&addr_vec[0], &mut read_buf).unwrap();
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
}
#[test]
@ -1362,8 +1362,8 @@ mod tests {
let read_len = pool.read(&info.addr, &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data");
assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1);
@ -1387,8 +1387,8 @@ mod tests {
let read_len = pool.read(&addr_vec[0], &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data");
assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
}
#[test]
@ -2031,7 +2031,7 @@ mod tests {
assert_eq!(n, 1);
let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap();
assert_eq!(time_reader, time_writer);
let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap().0;
let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap();
assert_eq!(pus_tc_reader, ping_tc);
}

View File

@ -309,8 +309,12 @@ mod tests {
}
impl PusTestHarness for Pus11HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler
.service_helper
.verif_reporter()
@ -383,7 +387,7 @@ mod tests {
let reply_header = SpHeader::new_for_unseg_tm(TEST_APID, 0, 0);
let tc_header = PusTcSecondaryHeader::new_simple(11, subservice as u8);
let enable_scheduling = PusTcCreator::new(reply_header, tc_header, &[0; 7], true);
let token = test_harness.init_verification(&enable_scheduling);
let token = test_harness.start_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);
let request_id = token.request_id();
@ -445,7 +449,7 @@ mod tests {
&sched_app_data[..written_len],
true,
);
let token = test_harness.init_verification(&enable_scheduling);
let token = test_harness.start_verification(&enable_scheduling);
test_harness.send_tc(&token, &enable_scheduling);
let request_id = token.request_id();

View File

@ -180,8 +180,12 @@ mod tests {
}
impl PusTestHarness for Pus17HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler
.service_helper
.verif_reporter()
@ -238,8 +242,12 @@ mod tests {
}
impl PusTestHarness for Pus17HandlerWithVecTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc);
fn start_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler
.service_helper
.verif_reporter()
@ -279,7 +287,7 @@ mod tests {
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sec_header = PusTcSecondaryHeader::new_simple(17, 1);
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let request_id = token.request_id();
let result = test_harness.handle_one_tc();
@ -334,7 +342,7 @@ mod tests {
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sec_header = PusTcSecondaryHeader::new_simple(3, 1);
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_err());
@ -355,7 +363,7 @@ mod tests {
let sp_header = SpHeader::new_for_unseg_tc(TEST_APID, 0, 0);
let sec_header = PusTcSecondaryHeader::new_simple(17, 200);
let ping_tc = PusTcCreator::new_no_app_data(sp_header, sec_header, true);
let token = test_harness.init_verification(&ping_tc);
let token = test_harness.start_verification(&ping_tc);
test_harness.send_tc(&token, &ping_tc);
let result = test_harness.handle_one_tc();
assert!(result.is_ok());

View File

@ -47,7 +47,7 @@
//! tc_header,
//! true
//! );
//! let init_token = reporter.add_tc(&pus_tc_0);
//! let init_token = reporter.start_verification(&pus_tc_0);
//!
//! // Complete success sequence for a telecommand
//! let accepted_token = reporter.acceptance_success(&sender, init_token, &EMPTY_STAMP).unwrap();
@ -65,8 +65,7 @@
//! let store_guard = rg.read_with_guard(tm_in_store.store_addr);
//! tm_len = store_guard.read(&mut tm_buf).expect("Error reading TM slice");
//! }
//! let (pus_tm, _) = PusTmReader::new(&tm_buf[0..tm_len], 7)
//! .expect("Error reading verification TM");
//! let pus_tm = PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
//! if packet_idx == 0 {
//! assert_eq!(pus_tm.subservice(), 1);
//! } else if packet_idx == 1 {
@ -228,7 +227,7 @@ pub struct VerificationToken<STATE> {
}
impl<STATE> VerificationToken<STATE> {
fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
pub fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
VerificationToken {
state: PhantomData,
request_id: req_id,
@ -408,14 +407,10 @@ pub trait VerificationReportingProvider {
fn set_apid(&mut self, apid: Apid);
fn apid(&self) -> Apid;
fn add_tc(
&mut self,
fn start_verification(
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
self.add_tc_with_req_id(RequestId::new(pus_tc))
}
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
) -> VerificationToken<TcStateNone>;
fn acceptance_success(
&self,
@ -482,7 +477,7 @@ pub trait VerificationReportingProvider {
/// the buffer passed to the API exposes by this struct will be used to serialize the source data.
/// This buffer may not be re-used to serialize the whole telemetry because that would overwrite
/// the source data itself.
#[derive(Clone)]
#[derive(Debug, Clone)]
pub struct VerificationReportCreator {
pub dest_id: u16,
apid: u16,
@ -518,24 +513,15 @@ impl VerificationReportCreator {
/// Initialize verification handling by passing a TC reference. This returns a token required
/// to call the acceptance functions
pub fn add_tc(
&mut self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
self.add_tc_with_req_id(RequestId::new(pus_tc))
pub fn read_request_id_from_tc(pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> RequestId {
RequestId::new(pus_tc)
}
/// Same as [Self::add_tc] but pass a request ID instead of the direct telecommand.
/// This can be useful if the executing thread does not have full access to the telecommand.
pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(req_id)
}
fn success_verification_no_step<'time, 'src_data, State: Copy>(
fn success_verification_no_step<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: u8,
token: VerificationToken<State>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
time_stamp: &'time [u8],
@ -545,7 +531,7 @@ impl VerificationReportCreator {
subservice,
seq_count,
msg_count,
&token.request_id(),
request_id,
time_stamp,
None::<&dyn EcssEnumeration>,
)?;
@ -554,11 +540,11 @@ impl VerificationReportCreator {
// Internal helper function, too many arguments is acceptable for this case.
#[allow(clippy::too_many_arguments)]
fn failure_verification_no_step<'time, 'src_data, State: Copy>(
fn failure_verification_no_step<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
subservice: u8,
token: VerificationToken<State>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
step: Option<&(impl EcssEnumeration + ?Sized)>,
@ -569,7 +555,7 @@ impl VerificationReportCreator {
subservice,
seq_count,
msg_count,
&token.request_id(),
request_id,
step,
params,
)?;
@ -580,39 +566,27 @@ impl VerificationReportCreator {
pub fn acceptance_success<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcStateNone>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
time_stamp: &'time [u8],
) -> Result<
(
PusTmCreator<'time, 'src_data>,
VerificationToken<TcStateAccepted>,
),
ByteConversionError,
> {
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
let tm_creator = self.success_verification_no_step(
src_data_buf,
Subservice::TmAcceptanceSuccess.into(),
token,
request_id,
seq_count,
msg_count,
time_stamp,
)?;
Ok((
tm_creator,
VerificationToken {
state: PhantomData,
request_id: token.request_id(),
},
))
Ok(tm_creator)
}
/// Package a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard.
pub fn acceptance_failure<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcStateNone>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
params: FailParams<'time, '_>,
@ -620,7 +594,7 @@ impl VerificationReportCreator {
self.failure_verification_no_step(
src_data_buf,
Subservice::TmAcceptanceFailure.into(),
token,
request_id,
seq_count,
msg_count,
None::<&dyn EcssEnumeration>,
@ -634,32 +608,20 @@ impl VerificationReportCreator {
pub fn start_success<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcStateAccepted>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
time_stamp: &'time [u8],
) -> Result<
(
PusTmCreator<'time, 'src_data>,
VerificationToken<TcStateStarted>,
),
ByteConversionError,
> {
) -> Result<PusTmCreator<'time, 'src_data>, ByteConversionError> {
let tm_creator = self.success_verification_no_step(
src_data_buf,
Subservice::TmStartSuccess.into(),
token,
request_id,
seq_count,
msg_count,
time_stamp,
)?;
Ok((
tm_creator,
VerificationToken {
state: PhantomData,
request_id: token.request_id(),
},
))
Ok(tm_creator)
}
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
@ -669,7 +631,7 @@ impl VerificationReportCreator {
pub fn start_failure<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcStateAccepted>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
params: FailParams<'time, '_>,
@ -677,7 +639,7 @@ impl VerificationReportCreator {
self.failure_verification_no_step(
src_data_buf,
Subservice::TmStartFailure.into(),
token,
request_id,
seq_count,
msg_count,
None::<&dyn EcssEnumeration>,
@ -691,7 +653,7 @@ impl VerificationReportCreator {
pub fn step_success<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: &VerificationToken<TcStateStarted>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
time_stamp: &'time [u8],
@ -702,7 +664,7 @@ impl VerificationReportCreator {
Subservice::TmStepSuccess.into(),
seq_count,
msg_count,
&token.request_id(),
request_id,
time_stamp,
Some(&step),
)
@ -735,10 +697,10 @@ impl VerificationReportCreator {
///
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
/// token because verification handling is done.
pub fn completion_success<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>(
pub fn completion_success<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcState>,
request_id: &RequestId,
seq_counter: u16,
msg_counter: u16,
time_stamp: &'time [u8],
@ -746,7 +708,7 @@ impl VerificationReportCreator {
self.success_verification_no_step(
src_data_buf,
Subservice::TmCompletionSuccess.into(),
token,
request_id,
seq_counter,
msg_counter,
time_stamp,
@ -757,10 +719,10 @@ impl VerificationReportCreator {
///
/// Requires a token previously acquired by calling [Self::start_success]. It consumes the
/// token because verification handling is done.
pub fn completion_failure<'time, 'src_data, TcState: WasAtLeastAccepted + Copy>(
pub fn completion_failure<'time, 'src_data>(
&self,
src_data_buf: &'src_data mut [u8],
token: VerificationToken<TcState>,
request_id: &RequestId,
seq_count: u16,
msg_count: u16,
params: FailParams<'time, '_>,
@ -768,7 +730,7 @@ impl VerificationReportCreator {
self.failure_verification_no_step(
src_data_buf,
Subservice::TmCompletionFailure.into(),
token,
request_id,
seq_count,
msg_count,
None::<&dyn EcssEnumeration>,
@ -986,12 +948,26 @@ pub mod alloc_mod {
}
}
pub fn start_verification(
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(
VerificationReportCreator::read_request_id_from_tc(pus_tc),
)
}
pub fn start_verification_with_req_id(
&self,
request_id: RequestId,
) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(request_id)
}
delegate!(
to self.reporter_creator {
pub fn set_apid(&mut self, apid: u16) -> bool;
pub fn apid(&self) -> u16;
pub fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
pub fn dest_id(&self) -> u16;
pub fn set_dest_id(&mut self, dest_id: u16);
}
@ -1009,11 +985,16 @@ pub mod alloc_mod {
to self.reporter_creator {
fn set_apid(&mut self, apid: Apid);
fn apid(&self) -> Apid;
fn add_tc(&mut self, pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> VerificationToken<TcStateNone>;
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone>;
}
);
fn start_verification(
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(RequestId::new(pus_tc))
}
fn owner_id(&self) -> ComponentId {
self.owner_id
}
@ -1026,13 +1007,19 @@ pub mod alloc_mod {
time_stamp: &[u8],
) -> Result<VerificationToken<TcStateAccepted>, EcssTmtcError> {
let mut source_data_buf = self.source_data_buf.borrow_mut();
let (mut tm_creator, token) = self
let mut tm_creator = self
.reporter_creator
.acceptance_success(source_data_buf.as_mut_slice(), token, 0, 0, time_stamp)
.acceptance_success(
source_data_buf.as_mut_slice(),
&token.request_id(),
0,
0,
time_stamp,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
Ok(token)
Ok(VerificationToken::new_accepted_state(token.request_id()))
}
/// Package and send a PUS TM\[1, 2\] packet, see 8.1.2.2 of the PUS standard
@ -1045,7 +1032,7 @@ pub mod alloc_mod {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.reporter_creator
.acceptance_failure(buf.as_mut_slice(), token, 0, 0, params)
.acceptance_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@ -1062,13 +1049,13 @@ pub mod alloc_mod {
time_stamp: &[u8],
) -> Result<VerificationToken<TcStateStarted>, EcssTmtcError> {
let mut buf = self.source_data_buf.borrow_mut();
let (mut tm_creator, started_token) = self
let mut tm_creator = self
.reporter_creator
.start_success(buf.as_mut_slice(), token, 0, 0, time_stamp)
.start_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
Ok(started_token)
Ok(VerificationToken::new_started_state(token.request_id()))
}
/// Package and send a PUS TM\[1, 4\] packet, see 8.1.2.4 of the PUS standard.
@ -1084,7 +1071,7 @@ pub mod alloc_mod {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.reporter_creator
.start_failure(buf.as_mut_slice(), token, 0, 0, params)
.start_failure(buf.as_mut_slice(), &token.request_id(), 0, 0, params)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@ -1104,7 +1091,14 @@ pub mod alloc_mod {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.reporter_creator
.step_success(buf.as_mut_slice(), token, 0, 0, time_stamp, step)
.step_success(
buf.as_mut_slice(),
&token.request_id(),
0,
0,
time_stamp,
step,
)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@ -1145,7 +1139,7 @@ pub mod alloc_mod {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.reporter_creator
.completion_success(buf.as_mut_slice(), token, 0, 0, time_stamp)
.completion_success(buf.as_mut_slice(), &token.request_id(), 0, 0, time_stamp)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id, PusTmVariant::Direct(tm_creator))?;
@ -1165,7 +1159,7 @@ pub mod alloc_mod {
let mut buf = self.source_data_buf.borrow_mut();
let mut tm_creator = self
.reporter_creator
.completion_failure(buf.as_mut_slice(), token, 0, 00, params)
.completion_failure(buf.as_mut_slice(), &token.request_id(), 0, 00, params)
.map_err(PusError::ByteConversion)?;
self.tm_hook.modify_tm(&mut tm_creator);
sender.send_tm(self.owner_id(), PusTmVariant::Direct(tm_creator))?;
@ -1362,22 +1356,23 @@ pub mod test_util {
}
impl VerificationReportingProvider for TestVerificationReporter {
fn start_verification(
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
let request_id = RequestId::new(pus_tc);
self.report_queue
.borrow_mut()
.push_back((request_id, VerificationReportInfo::Added));
VerificationToken::<TcStateNone>::new(RequestId::new(pus_tc))
}
fn set_apid(&mut self, _apid: Apid) {}
fn apid(&self) -> Apid {
0
}
fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
self.report_queue
.borrow_mut()
.push_back((req_id, VerificationReportInfo::Added));
VerificationToken {
state: PhantomData,
request_id: req_id,
}
}
fn acceptance_success(
&self,
_sender: &(impl EcssTmSender + ?Sized),
@ -1834,15 +1829,16 @@ pub mod tests {
}
}
pub fn start_verification(&self) -> VerificationToken<TcStateNone> {
let tc_reader = PusTcReader::new(&self.tc).unwrap();
self.reporter.start_verification(&tc_reader)
}
#[allow(dead_code)]
fn set_dest_id(&mut self, dest_id: u16) {
self.reporter.set_dest_id(dest_id);
}
fn init(&mut self) -> VerificationToken<TcStateNone> {
self.reporter.add_tc(&PusTcReader::new(&self.tc).unwrap().0)
}
fn acceptance_success(
&self,
token: VerificationToken<TcStateNone>,
@ -1920,7 +1916,7 @@ pub mod tests {
additional_data: None,
};
let mut service_queue = self.sender.service_queue.borrow_mut();
assert!(service_queue.len() >= 1);
assert!(!service_queue.is_empty());
let info = service_queue.pop_front().unwrap();
assert_eq!(info, cmp_info);
}
@ -2092,8 +2088,8 @@ pub mod tests {
#[test]
fn test_basic_acceptance_success() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init();
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.start_verification();
testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("sending acceptance success failed");
@ -2103,7 +2099,7 @@ pub mod tests {
#[test]
fn test_basic_acceptance_failure() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let init_token = testbench.init();
let init_token = testbench.start_verification();
let timestamp = [1, 2, 3, 4, 5, 6, 7];
let fail_code = EcssEnumU16::new(2);
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
@ -2116,7 +2112,7 @@ pub mod tests {
#[test]
fn test_basic_acceptance_failure_with_helper() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let init_token = testbench.init();
let init_token = testbench.start_verification();
let timestamp = [1, 2, 3, 4, 5, 6, 7];
let fail_code = EcssEnumU16::new(2);
let fail_params = FailParams::new_no_fail_data(timestamp.as_slice(), &fail_code);
@ -2128,8 +2124,8 @@ pub mod tests {
#[test]
fn test_acceptance_fail_data_too_large() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8);
let init_token = testbench.init();
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8);
let init_token = testbench.start_verification();
let stamp_buf = [1, 2, 3, 4, 5, 6, 7];
let fail_code = EcssEnumU16::new(2);
let fail_data: [u8; 16] = [0; 16];
@ -2160,13 +2156,13 @@ pub mod tests {
#[test]
fn test_basic_acceptance_failure_with_fail_data() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let fail_code = EcssEnumU8::new(10);
let fail_data = EcssEnumU32::new(12);
let mut fail_data_raw = [0; 4];
fail_data.write_to_be_bytes(&mut fail_data_raw).unwrap();
let fail_params = FailParams::new(&EMPTY_STAMP, &fail_code, fail_data_raw.as_slice());
let init_token = testbench.init();
let init_token = testbench.start_verification();
testbench
.acceptance_failure(init_token, fail_params)
.expect("sending acceptance failure failed");
@ -2184,7 +2180,7 @@ pub mod tests {
#[test]
fn test_start_failure() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let init_token = testbench.init();
let init_token = testbench.start_verification();
let fail_code = EcssEnumU8::new(22);
let fail_data: i32 = -12;
let mut fail_data_raw = [0; 4];
@ -2203,7 +2199,7 @@ pub mod tests {
#[test]
fn test_start_failure_with_helper() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init();
let token = testbench.start_verification();
let fail_code = EcssEnumU8::new(22);
let fail_data: i32 = -12;
let mut fail_data_raw = [0; 4];
@ -2222,7 +2218,7 @@ pub mod tests {
#[test]
fn test_steps_success() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init();
let token = testbench.start_verification();
let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("acceptance failed");
@ -2245,7 +2241,7 @@ pub mod tests {
#[test]
fn test_step_failure() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init();
let token = testbench.start_verification();
let fail_code = EcssEnumU32::new(0x1020);
let fail_data: f32 = -22.3232;
let mut fail_data_raw = [0; 4];
@ -2279,7 +2275,7 @@ pub mod tests {
#[test]
fn test_completion_failure() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init();
let token = testbench.start_verification();
let fail_code = EcssEnumU32::new(0x1020);
let fail_params = FailParams::new_no_fail_data(&EMPTY_STAMP, &fail_code);
@ -2302,7 +2298,7 @@ pub mod tests {
fn test_complete_success_sequence() {
let mut testbench =
VerificationReporterTestbench::new(TEST_COMPONENT_ID_0.id(), create_generic_ping(), 16);
let token = testbench.init();
let token = testbench.start_verification();
let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("Sending acceptance success failed");
@ -2324,7 +2320,7 @@ pub mod tests {
create_generic_ping(),
SequenceCounterHook::default(),
);
let token = testbench.init();
let token = testbench.start_verification();
let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("Sending acceptance success failed");
@ -2342,7 +2338,7 @@ pub mod tests {
#[test]
fn test_completion_failure_helper_string_param() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
let token = testbench.init();
let token = testbench.start_verification();
let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("Sending acceptance success failed");
@ -2369,7 +2365,7 @@ pub mod tests {
#[test]
fn test_step_failure_helper_string_param() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 32);
let token = testbench.init();
let token = testbench.start_verification();
let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP)
.expect("Sending acceptance success failed");

View File

@ -39,7 +39,7 @@ impl UniqueApidTargetId {
}
}
pub fn raw(&self) -> ComponentId {
pub const fn raw(&self) -> ComponentId {
((self.apid as u64) << 32) | (self.unique_id as u64)
}

View File

@ -136,7 +136,7 @@ impl SequenceExecutionHelper {
/// with [Self::load]
/// * `sender` - The sender to send mode requests to the components
/// * `children_mode_store` - The mode store vector to keep track of the mode states of
/// children components
/// children components
pub fn run(
&mut self,
table: &SequenceModeTables,
@ -597,7 +597,7 @@ impl SubsystemCommandingHelper {
}
fn update_internal_req_id(&mut self) {
let new_internal_req_id = self.request_id().unwrap() << 8
let new_internal_req_id = (self.request_id().unwrap() << 8)
| self.seq_exec_helper.current_sequence_index().unwrap() as u32;
self.seq_exec_helper.set_request_id(new_internal_req_id);
self.active_internal_request_id = Some(new_internal_req_id);

View File

@ -107,9 +107,9 @@ fn test_threaded_usage() {
Ok(event_tm) => {
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
.expect("Deserializing TM failed");
assert_eq!(tm.0.service(), 5);
assert_eq!(tm.0.subservice(), 1);
let src_data = tm.0.source_data();
assert_eq!(tm.service(), 5);
assert_eq!(tm.subservice(), 1);
let src_data = tm.source_data();
assert!(!src_data.is_empty());
assert_eq!(src_data.len(), 4);
let event =
@ -137,9 +137,9 @@ fn test_threaded_usage() {
Ok(event_tm) => {
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
.expect("Deserializing TM failed");
assert_eq!(tm.0.service(), 5);
assert_eq!(tm.0.subservice(), 2);
let src_data = tm.0.source_data();
assert_eq!(tm.service(), 5);
assert_eq!(tm.subservice(), 2);
let src_data = tm.source_data();
assert!(!src_data.is_empty());
assert_eq!(src_data.len(), 12);
let event =

View File

@ -89,9 +89,9 @@ pub mod crossbeam_test {
let pg = tc_guard.read_with_guard(tc_addr);
tc_len = pg.read(&mut tc_buf).unwrap();
}
let (_tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
let _tc = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
let token = reporter_with_sender_0.start_verification_with_req_id(req_id_0);
let accepted_token = reporter_with_sender_0
.acceptance_success(&sender, token, &FIXED_STAMP)
.expect("Acceptance success failed");
@ -125,8 +125,8 @@ pub mod crossbeam_test {
let pg = tc_guard.read_with_guard(tc_addr);
tc_len = pg.read(&mut tc_buf).unwrap();
}
let (tc, _) = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
let token = reporter_with_sender_1.add_tc(&tc);
let tc = PusTcReader::new(&tc_buf[0..tc_len]).unwrap();
let token = reporter_with_sender_1.start_verification(&tc);
let accepted_token = reporter_with_sender_1
.acceptance_success(&sender_1, token, &FIXED_STAMP)
.expect("Acceptance success failed");
@ -156,7 +156,7 @@ pub mod crossbeam_test {
.read(&mut tm_buf)
.expect("Error reading TM slice");
}
let (pus_tm, _) =
let pus_tm =
PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
let req_id =
RequestId::from_bytes(&pus_tm.source_data()[0..RequestId::SIZE_AS_BYTES])