Compare commits

..

2 Commits

Author SHA1 Message Date
b1c7be0b38 reduce number of generics 2025-02-07 16:30:37 +01:00
29c045551b Mode Tree Feature Update 2025-02-07 16:21:50 +01:00
64 changed files with 494 additions and 764 deletions

View File

@@ -1,7 +1,7 @@
<p align="center"> <img src="misc/satrs-logo-v2.png" width="40%"> </p> <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 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://robamu.github.io/sat-rs/book/) [![sat-rs book](https://img.shields.io/badge/sat--rs-book-darkgreen?style=flat)](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/book/)
[![Crates.io](https://img.shields.io/crates/v/satrs)](https://crates.io/crates/satrs) [![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) [![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 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 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 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://robamu.github.io/sat-rs/book/) link to the [more high-level sat-rs book](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/)
at the [IRS software projects website](https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/). 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 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 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. 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): * [`satrs-minisim`](https://egit.irs.uni-stuttgart.de/rust/sat-rs/src/branch/main/satrs-minisim):
Mini-Simulator based on [nexosim](https://github.com/asynchronics/nexosim) which Mini-Simulator based on [asynchronix](https://github.com/asynchronics/asynchronix) which
simulates some physical devices for the `satrs-example` application device handlers. 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): * [`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. Components to build a mission information base from the on-board software directly.
@@ -61,8 +61,6 @@ Each project has its own `CHANGELOG.md`.
packet protocol implementations. This repository is re-exported in the packet protocol implementations. This repository is re-exported in the
[`satrs`](https://egit.irs.uni-stuttgart.de/rust/satrs/src/branch/main/satrs) [`satrs`](https://egit.irs.uni-stuttgart.de/rust/satrs/src/branch/main/satrs)
crate. crate.
* [`cfdp`](https://egit.irs.uni-stuttgart.de/rust/cfdp): CCSDS File Delivery Protocol
(CFDP) high-level library components.
# Flight Heritage # Flight Heritage

View File

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

View File

@@ -1,34 +0,0 @@
[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

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

View File

@@ -18,7 +18,7 @@ csv = "1"
num_enum = "0.7" num_enum = "0.7"
thiserror = "2" thiserror = "2"
lazy_static = "1" lazy_static = "1"
strum = { version = "0.27", features = ["derive"] } strum = { version = "0.26", features = ["derive"] }
derive-new = "0.7" derive-new = "0.7"
cfg-if = "1" cfg-if = "1"
serde = { version = "1", features = ["derive"] } serde = { version = "1", features = ["derive"] }

View File

@@ -39,10 +39,7 @@ class EventU32:
class AcsId(enum.IntEnum): class AcsId(enum.IntEnum):
SUBSYSTEM = 1 MGM_0 = 0
MGM_ASSEMBLY = 2
MGM_0 = 3
MGM_1 = 4
class AcsHkIds(enum.IntEnum): class AcsHkIds(enum.IntEnum):

View File

@@ -1 +0,0 @@
// TODO: Write the assembly

View File

@@ -1 +0,0 @@
// TODO: Write dummy controller

View File

@@ -2,7 +2,6 @@ use derive_new::new;
use satrs::hk::{HkRequest, HkRequestVariant}; use satrs::hk::{HkRequest, HkRequestVariant};
use satrs::mode_tree::{ModeChild, ModeNode}; use satrs::mode_tree::{ModeChild, ModeNode};
use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender}; use satrs::power::{PowerSwitchInfo, PowerSwitcherCommandSender};
use satrs_example::ids::generic_pus::PUS_MODE;
use satrs_example::{DeviceMode, TimestampHelper}; use satrs_example::{DeviceMode, TimestampHelper};
use satrs_minisim::acs::lis3mdl::{ use satrs_minisim::acs::lis3mdl::{
MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR, MgmLis3MdlReply, MgmLis3RawValues, FIELD_LSB_PER_GAUSS_4_SENS, GAUSS_TO_MICROTESLA_FACTOR,
@@ -21,7 +20,7 @@ use satrs::mode::{
}; };
use satrs::pus::{EcssTmSender, PusTmVariant}; use satrs::pus::{EcssTmSender, PusTmVariant};
use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId}; use satrs::request::{GenericMessage, MessageMetadata, UniqueApidTargetId};
use satrs_example::config::components::NO_SENDER; use satrs_example::config::components::{NO_SENDER, PUS_MODE_SERVICE};
use crate::hk::PusHkHelper; use crate::hk::PusHkHelper;
use crate::pus::hk::{HkReply, HkReplyVariant}; use crate::pus::hk::{HkReply, HkReplyVariant};
@@ -83,7 +82,7 @@ impl SpiInterface for SpiSimInterface {
.sim_request_tx .sim_request_tx
.send(SimRequest::new_with_epoch_time(mgm_sensor_request)) .send(SimRequest::new_with_epoch_time(mgm_sensor_request))
{ {
log::error!("failed to send MGM LIS3 request: {e}"); log::error!("failed to send MGM LIS3 request: {}", e);
} }
match self.sim_reply_rx.recv_timeout(Duration::from_millis(50)) { match self.sim_reply_rx.recv_timeout(Duration::from_millis(50)) {
Ok(sim_reply) => { Ok(sim_reply) => {
@@ -97,7 +96,7 @@ impl SpiInterface for SpiSimInterface {
.copy_from_slice(&sim_reply_lis3.raw.z.to_le_bytes()); .copy_from_slice(&sim_reply_lis3.raw.z.to_le_bytes());
} }
Err(e) => { Err(e) => {
log::warn!("MGM LIS3 SIM reply timeout: {e}"); log::warn!("MGM LIS3 SIM reply timeout: {}", e);
} }
} }
Ok(()) Ok(())
@@ -417,7 +416,7 @@ impl<
if requestor.sender_id() == NO_SENDER { if requestor.sender_id() == NO_SENDER {
return Ok(()); return Ok(());
} }
if requestor.sender_id() != PUS_MODE.id() { if requestor.sender_id() != PUS_MODE_SERVICE.id() {
log::warn!( log::warn!(
"can not send back mode reply to sender {:x}", "can not send back mode reply to sender {:x}",
requestor.sender_id() requestor.sender_id()
@@ -434,7 +433,7 @@ impl<
requestor: MessageMetadata, requestor: MessageMetadata,
reply: ModeReply, reply: ModeReply,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
if requestor.sender_id() != PUS_MODE.id() { if requestor.sender_id() != PUS_MODE_SERVICE.id() {
log::warn!( log::warn!(
"can not send back mode reply to sender {}", "can not send back mode reply to sender {}",
requestor.sender_id() requestor.sender_id()
@@ -492,7 +491,7 @@ mod tests {
tmtc::PacketAsVec, tmtc::PacketAsVec,
ComponentId, ComponentId,
}; };
use satrs_example::ids::{acs::ASSEMBLY, Apid}; use satrs_example::config::components::{Apid, MGM_ASSEMBLY};
use satrs_minisim::acs::lis3mdl::MgmLis3RawValues; use satrs_minisim::acs::lis3mdl::MgmLis3RawValues;
use crate::{eps::TestSwitchHelper, pus::hk::HkReply, requests::CompositeRequest}; use crate::{eps::TestSwitchHelper, pus::hk::HkReply, requests::CompositeRequest};
@@ -538,7 +537,7 @@ mod tests {
impl ModeNode for MgmAssemblyMock { impl ModeNode for MgmAssemblyMock {
fn id(&self) -> satrs::ComponentId { fn id(&self) -> satrs::ComponentId {
PUS_MODE.into() PUS_MODE_SERVICE.into()
} }
} }
@@ -557,7 +556,7 @@ mod tests {
impl ModeNode for PusMock { impl ModeNode for PusMock {
fn id(&self) -> satrs::ComponentId { fn id(&self) -> satrs::ComponentId {
PUS_MODE.into() PUS_MODE_SERVICE.into()
} }
} }
@@ -592,8 +591,8 @@ mod tests {
TestSpiInterface::default(), TestSpiInterface::default(),
shared_mgm_set, shared_mgm_set,
); );
handler.add_mode_parent(PUS_MODE.into(), reply_tx_to_pus); handler.add_mode_parent(PUS_MODE_SERVICE.into(), reply_tx_to_pus);
handler.add_mode_parent(ASSEMBLY.into(), reply_tx_to_parent); handler.add_mode_parent(MGM_ASSEMBLY.into(), reply_tx_to_parent);
Self { Self {
mode_request_tx: request_tx, mode_request_tx: request_tx,
mode_reply_rx_to_pus: reply_rx_to_pus, mode_reply_rx_to_pus: reply_rx_to_pus,
@@ -631,7 +630,7 @@ mod tests {
testbench testbench
.mode_request_tx .mode_request_tx
.send(GenericMessage::new( .send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE.id()), MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
ModeRequest::SetMode { ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0), mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false, forced: false,
@@ -692,7 +691,7 @@ mod tests {
testbench testbench
.mode_request_tx .mode_request_tx
.send(GenericMessage::new( .send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE.id()), MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
ModeRequest::SetMode { ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0), mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false, forced: false,

View File

@@ -1,4 +1 @@
pub mod assembly;
pub mod ctrl;
pub mod mgm; pub mod mgm;
pub mod subsystem;

View File

@@ -1 +0,0 @@
// TODO: Write subsystem

View File

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

View File

@@ -43,14 +43,14 @@ pub const TEST_EVENT: EventU32TypedSev<SeverityInfo> = EventU32TypedSev::<Severi
lazy_static! { lazy_static! {
pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = { pub static ref PACKET_ID_VALIDATOR: HashSet<PacketId> = {
let mut set = HashSet::new(); let mut set = HashSet::new();
for id in crate::ids::Apid::iter() { for id in components::Apid::iter() {
set.insert(PacketId::new(PacketType::Tc, true, id as u16)); set.insert(PacketId::new(PacketType::Tc, true, id as u16));
} }
set set
}; };
pub static ref APID_VALIDATOR: HashSet<u16> = { pub static ref APID_VALIDATOR: HashSet<u16> = {
let mut set = HashSet::new(); let mut set = HashSet::new();
for id in crate::ids::Apid::iter() { for id in components::Apid::iter() {
set.insert(id as u16); set.insert(id as u16);
} }
set set
@@ -122,8 +122,74 @@ pub mod mode_err {
} }
pub mod components { pub mod components {
use satrs::ComponentId; use satrs::{request::UniqueApidTargetId, ComponentId};
use strum::EnumIter;
#[derive(Copy, Clone, PartialEq, Eq, EnumIter)]
pub enum Apid {
Sched = 1,
GenericPus = 2,
Acs = 3,
Cfdp = 4,
Tmtc = 5,
Eps = 6,
}
// 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,
}
#[derive(Copy, Clone, PartialEq, Eq)]
pub enum AcsId {
Mgm0 = 0,
Assembly = 1,
}
#[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 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 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 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 const NO_SENDER: ComponentId = ComponentId::MAX;
} }

View File

@@ -20,8 +20,7 @@ use satrs::{
spacepackets::ByteConversionError, spacepackets::ByteConversionError,
}; };
use satrs_example::{ use satrs_example::{
config::components::NO_SENDER, config::components::{NO_SENDER, PCDU_HANDLER, PUS_MODE_SERVICE},
ids::{eps::PCDU, generic_pus::PUS_MODE},
DeviceMode, TimestampHelper, DeviceMode, TimestampHelper,
}; };
use satrs_minisim::{ use satrs_minisim::{
@@ -36,7 +35,6 @@ use crate::{
hk::PusHkHelper, hk::PusHkHelper,
pus::hk::{HkReply, HkReplyVariant}, pus::hk::{HkReply, HkReplyVariant},
requests::CompositeRequest, requests::CompositeRequest,
tmtc::sender::TmTcSender,
}; };
pub trait SerialInterface { pub trait SerialInterface {
@@ -205,14 +203,14 @@ pub type SharedSwitchSet = Arc<Mutex<SwitchSet>>;
/// Example PCDU device handler. /// Example PCDU device handler.
#[derive(new)] #[derive(new)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub struct PcduHandler<ComInterface: SerialInterface> { pub struct PcduHandler<ComInterface: SerialInterface, TmSender: EcssTmSender> {
id: UniqueApidTargetId, id: UniqueApidTargetId,
dev_str: &'static str, dev_str: &'static str,
mode_node: ModeRequestHandlerMpscBounded, mode_node: ModeRequestHandlerMpscBounded,
composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>, composite_request_rx: mpsc::Receiver<GenericMessage<CompositeRequest>>,
hk_reply_tx: mpsc::SyncSender<GenericMessage<HkReply>>, hk_reply_tx: mpsc::SyncSender<GenericMessage<HkReply>>,
switch_request_rx: mpsc::Receiver<GenericMessage<SwitchRequest>>, switch_request_rx: mpsc::Receiver<GenericMessage<SwitchRequest>>,
tm_sender: TmTcSender, tm_sender: TmSender,
pub com_interface: ComInterface, pub com_interface: ComInterface,
shared_switch_map: Arc<Mutex<SwitchSet>>, shared_switch_map: Arc<Mutex<SwitchSet>>,
#[new(value = "PusHkHelper::new(id)")] #[new(value = "PusHkHelper::new(id)")]
@@ -225,7 +223,7 @@ pub struct PcduHandler<ComInterface: SerialInterface> {
tm_buf: [u8; 256], tm_buf: [u8; 256],
} }
impl<ComInterface: SerialInterface> PcduHandler<ComInterface> { impl<ComInterface: SerialInterface, TmSender: EcssTmSender> PcduHandler<ComInterface, TmSender> {
pub fn periodic_operation(&mut self, op_code: OpCode) { pub fn periodic_operation(&mut self, op_code: OpCode) {
match op_code { match op_code {
OpCode::RegularOp => { OpCode::RegularOp => {
@@ -401,18 +399,22 @@ impl<ComInterface: SerialInterface> PcduHandler<ComInterface> {
} }
} }
}) { }) {
log::warn!("receiving PCDU replies failed: {e:?}"); log::warn!("receiving PCDU replies failed: {:?}", e);
} }
} }
} }
impl<ComInterface: SerialInterface> ModeProvider for PcduHandler<ComInterface> { impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeProvider
for PcduHandler<ComInterface, TmSender>
{
fn mode_and_submode(&self) -> ModeAndSubmode { fn mode_and_submode(&self) -> ModeAndSubmode {
self.mode_and_submode self.mode_and_submode
} }
} }
impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterface> { impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeRequestHandler
for PcduHandler<ComInterface, TmSender>
{
type Error = ModeError; type Error = ModeError;
fn start_transition( fn start_transition(
&mut self, &mut self,
@@ -450,7 +452,7 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
if requestor.sender_id() == NO_SENDER { if requestor.sender_id() == NO_SENDER {
return Ok(()); return Ok(());
} }
if requestor.sender_id() != PUS_MODE.id() { if requestor.sender_id() != PUS_MODE_SERVICE.id() {
log::warn!( log::warn!(
"can not send back mode reply to sender {}", "can not send back mode reply to sender {}",
requestor.sender_id() requestor.sender_id()
@@ -467,7 +469,7 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
requestor: MessageMetadata, requestor: MessageMetadata,
reply: ModeReply, reply: ModeReply,
) -> Result<(), Self::Error> { ) -> Result<(), Self::Error> {
if requestor.sender_id() != PUS_MODE.id() { if requestor.sender_id() != PUS_MODE_SERVICE.id() {
log::warn!( log::warn!(
"can not send back mode reply to sender {}", "can not send back mode reply to sender {}",
requestor.sender_id() requestor.sender_id()
@@ -488,13 +490,17 @@ impl<ComInterface: SerialInterface> ModeRequestHandler for PcduHandler<ComInterf
} }
} }
impl<ComInterface: SerialInterface> ModeNode for PcduHandler<ComInterface> { impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeNode
for PcduHandler<ComInterface, TmSender>
{
fn id(&self) -> satrs::ComponentId { fn id(&self) -> satrs::ComponentId {
PCDU.into() PCDU_HANDLER.into()
} }
} }
impl<ComInterface: SerialInterface> ModeChild for PcduHandler<ComInterface> { impl<ComInterface: SerialInterface, TmSender: EcssTmSender> ModeChild
for PcduHandler<ComInterface, TmSender>
{
type Sender = mpsc::SyncSender<GenericMessage<ModeReply>>; type Sender = mpsc::SyncSender<GenericMessage<ModeReply>>;
fn add_mode_parent(&mut self, id: satrs::ComponentId, reply_sender: Self::Sender) { fn add_mode_parent(&mut self, id: satrs::ComponentId, reply_sender: Self::Sender) {
@@ -509,7 +515,7 @@ mod tests {
use satrs::{ use satrs::{
mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec, mode::ModeRequest, power::SwitchStateBinary, request::GenericMessage, tmtc::PacketAsVec,
}; };
use satrs_example::ids::{self, Apid}; use satrs_example::config::components::{Apid, EPS_SUBSYSTEM, MGM_HANDLER_0, PCDU_HANDLER};
use satrs_minisim::eps::SwitchMapBinary; use satrs_minisim::eps::SwitchMapBinary;
use super::*; use super::*;
@@ -557,7 +563,7 @@ mod tests {
pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>, pub hk_reply_rx: mpsc::Receiver<GenericMessage<HkReply>>,
pub tm_rx: mpsc::Receiver<PacketAsVec>, pub tm_rx: mpsc::Receiver<PacketAsVec>,
pub switch_request_tx: mpsc::Sender<GenericMessage<SwitchRequest>>, pub switch_request_tx: mpsc::Sender<GenericMessage<SwitchRequest>>,
pub handler: PcduHandler<SerialInterfaceTest>, pub handler: PcduHandler<SerialInterfaceTest, mpsc::Sender<PacketAsVec>>,
} }
impl PcduTestbench { impl PcduTestbench {
@@ -565,10 +571,11 @@ mod tests {
let (mode_request_tx, mode_request_rx) = mpsc::sync_channel(5); 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_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_reply_tx_to_parent, mode_reply_rx_to_parent) = mpsc::sync_channel(5);
let mode_node = ModeRequestHandlerMpscBounded::new(PCDU.into(), mode_request_rx); let mode_node =
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), mode_request_rx);
let (composite_request_tx, composite_request_rx) = mpsc::channel(); let (composite_request_tx, composite_request_rx) = mpsc::channel();
let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10); let (hk_reply_tx, hk_reply_rx) = mpsc::sync_channel(10);
let (tm_tx, tm_rx) = mpsc::sync_channel::<PacketAsVec>(5); let (tm_tx, tm_rx) = mpsc::channel::<PacketAsVec>();
let (switch_request_tx, switch_reqest_rx) = mpsc::channel(); let (switch_request_tx, switch_reqest_rx) = mpsc::channel();
let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default())); let shared_switch_map = Arc::new(Mutex::new(SwitchSet::default()));
let mut handler = PcduHandler::new( let mut handler = PcduHandler::new(
@@ -578,12 +585,12 @@ mod tests {
composite_request_rx, composite_request_rx,
hk_reply_tx, hk_reply_tx,
switch_reqest_rx, switch_reqest_rx,
TmTcSender::Heap(tm_tx.clone()), tm_tx,
SerialInterfaceTest::default(), SerialInterfaceTest::default(),
shared_switch_map, shared_switch_map,
); );
handler.add_mode_parent(ids::eps::SUBSYSTEM.into(), mode_reply_tx_to_parent); handler.add_mode_parent(EPS_SUBSYSTEM.into(), mode_reply_tx_to_parent);
handler.add_mode_parent(PUS_MODE.into(), mode_reply_tx_to_pus); handler.add_mode_parent(PUS_MODE_SERVICE.into(), mode_reply_tx_to_pus);
Self { Self {
mode_request_tx, mode_request_tx,
mode_reply_rx_to_pus, mode_reply_rx_to_pus,
@@ -678,7 +685,7 @@ mod tests {
testbench testbench
.mode_request_tx .mode_request_tx
.send(GenericMessage::new( .send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE.id()), MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
ModeRequest::SetMode { ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0), mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false, forced: false,
@@ -713,7 +720,7 @@ mod tests {
testbench testbench
.mode_request_tx .mode_request_tx
.send(GenericMessage::new( .send(GenericMessage::new(
MessageMetadata::new(0, PUS_MODE.id()), MessageMetadata::new(0, PUS_MODE_SERVICE.id()),
ModeRequest::SetMode { ModeRequest::SetMode {
mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0), mode_and_submode: ModeAndSubmode::new(DeviceMode::Normal as u32, 0),
forced: false, forced: false,
@@ -723,7 +730,7 @@ mod tests {
testbench testbench
.switch_request_tx .switch_request_tx
.send(GenericMessage::new( .send(GenericMessage::new(
MessageMetadata::new(0, ids::acs::MGM0.id()), MessageMetadata::new(0, MGM_HANDLER_0.id()),
SwitchRequest::new(0, SwitchStateBinary::On), SwitchRequest::new(0, SwitchStateBinary::On),
)) ))
.expect("failed to send switch request"); .expect("failed to send switch request");

View File

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

View File

@@ -1,94 +0,0 @@
//! 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,
Assembly = 2,
Mgm0 = 3,
Mgm1 = 4,
}
pub const SUBSYSTEM: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Subsystem as u32);
pub const ASSEMBLY: super::UniqueApidTargetId =
super::UniqueApidTargetId::new(super::Apid::Acs as u16, Id::Assembly 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

@@ -24,7 +24,7 @@ pub fn create_sim_client(sim_request_rx: mpsc::Receiver<SimRequest>) -> Option<S
return Some(sim_client); return Some(sim_client);
} }
Err(e) => { Err(e) => {
log::warn!("sim client creation error: {e}"); log::warn!("sim client creation error: {}", e);
} }
} }
None None
@@ -116,7 +116,7 @@ impl SimClientUdp {
.udp_client .udp_client
.send_to(request_json.as_bytes(), self.simulator_addr) .send_to(request_json.as_bytes(), self.simulator_addr)
{ {
log::error!("error sending data to UDP SIM server: {e}"); log::error!("error sending data to UDP SIM server: {}", e);
break; break;
} else { } else {
no_sim_requests_handled = false; no_sim_requests_handled = false;
@@ -151,7 +151,7 @@ impl SimClientUdp {
} }
} }
Err(e) => { Err(e) => {
log::warn!("failed to deserialize SIM reply: {e}"); log::warn!("failed to deserialize SIM reply: {}", e);
} }
} }
} }
@@ -161,7 +161,7 @@ impl SimClientUdp {
{ {
break; break;
} }
log::error!("error receiving data from UDP SIM server: {e}"); log::error!("error receiving data from UDP SIM server: {}", e);
break; break;
} }
} }

View File

@@ -31,7 +31,7 @@ impl SpacePacketValidator for SimplePacketValidator {
if self.valid_ids.contains(&sp_header.packet_id()) { if self.valid_ids.contains(&sp_header.packet_id()) {
return SpValidity::Valid; return SpValidity::Valid;
} }
log::warn!("ignoring space packet with header {sp_header:?}"); log::warn!("ignoring space packet with header {:?}", sp_header);
// We could perform a CRC check.. but lets keep this simple and assume that TCP ensures // We could perform a CRC check.. but lets keep this simple and assume that TCP ensures
// data integrity. // data integrity.
SpValidity::Skip SpValidity::Skip

View File

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

View File

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

View File

@@ -39,16 +39,11 @@ use satrs::{
}; };
use satrs_example::{ use satrs_example::{
config::{ config::{
components::NO_SENDER, components::{MGM_HANDLER_0, NO_SENDER, PCDU_HANDLER, TCP_SERVER, UDP_SERVER},
pool::create_sched_tc_pool, pool::create_sched_tc_pool,
tasks::{FREQ_MS_AOCS, FREQ_MS_PUS_STACK, FREQ_MS_UDP_TMTC, SIM_CLIENT_IDLE_DELAY_MS}, 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, OBSW_SERVER_ADDR, PACKET_ID_VALIDATOR, SERVER_PORT,
}, },
ids::{
acs::*,
eps::*,
tmtc::{TCP_SERVER, UDP_SERVER},
},
DeviceMode, DeviceMode,
}; };
use tmtc::sender::TmTcSender; use tmtc::sender::TmTcSender;
@@ -112,29 +107,23 @@ fn main() {
} }
let (sim_request_tx, sim_request_rx) = mpsc::channel(); let (sim_request_tx, sim_request_rx) = mpsc::channel();
let (mgm_0_sim_reply_tx, mgm_0_sim_reply_rx) = mpsc::channel(); let (mgm_sim_reply_tx, mgm_sim_reply_rx) = mpsc::channel();
let (mgm_1_sim_reply_tx, mgm_1_sim_reply_rx) = mpsc::channel();
let (pcdu_sim_reply_tx, pcdu_sim_reply_rx) = mpsc::channel(); let (pcdu_sim_reply_tx, pcdu_sim_reply_rx) = mpsc::channel();
let mut opt_sim_client = create_sim_client(sim_request_rx); let mut opt_sim_client = create_sim_client(sim_request_rx);
let (mgm_0_handler_composite_tx, mgm_0_handler_composite_rx) = mpsc::sync_channel(10); let (mgm_handler_composite_tx, mgm_handler_composite_rx) = mpsc::sync_channel(10);
let (mgm_1_handler_composite_tx, mgm_1_handler_composite_rx) = mpsc::sync_channel(10);
let (pcdu_handler_composite_tx, pcdu_handler_composite_rx) = mpsc::sync_channel(30); let (pcdu_handler_composite_tx, pcdu_handler_composite_rx) = mpsc::sync_channel(30);
let (mgm_0_handler_mode_tx, mgm_0_handler_mode_rx) = mpsc::sync_channel(5); let (mgm_handler_mode_tx, mgm_handler_mode_rx) = mpsc::sync_channel(5);
let (mgm_1_handler_mode_tx, mgm_1_handler_mode_rx) = mpsc::sync_channel(5);
let (pcdu_handler_mode_tx, pcdu_handler_mode_rx) = mpsc::sync_channel(5); let (pcdu_handler_mode_tx, pcdu_handler_mode_rx) = mpsc::sync_channel(5);
// Some request are targetable. This map is used to retrieve sender handles based on a target ID. // Some request are targetable. This map is used to retrieve sender handles based on a target ID.
let mut request_map = GenericRequestRouter::default(); let mut request_map = GenericRequestRouter::default();
request_map request_map
.composite_router_map .composite_router_map
.insert(MGM0.id(), mgm_0_handler_composite_tx); .insert(MGM_HANDLER_0.id(), mgm_handler_composite_tx);
request_map request_map
.composite_router_map .composite_router_map
.insert(MGM1.id(), mgm_1_handler_composite_tx); .insert(PCDU_HANDLER.id(), pcdu_handler_composite_tx);
request_map
.composite_router_map
.insert(PCDU.id(), pcdu_handler_composite_tx);
// This helper structure is used by all telecommand providers which need to send telecommands // This helper structure is used by all telecommand providers which need to send telecommands
// to the TC source. // to the TC source.
@@ -303,65 +292,34 @@ fn main() {
let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20); let (switch_request_tx, switch_request_rx) = mpsc::sync_channel(20);
let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone()); let switch_helper = PowerSwitchHelper::new(switch_request_tx, shared_switch_set.clone());
let shared_mgm_0_set = Arc::default(); let shared_mgm_set = Arc::default();
let shared_mgm_1_set = Arc::default(); let mgm_mode_node =
let mgm_0_mode_node = ModeRequestHandlerMpscBounded::new(MGM0.into(), mgm_0_handler_mode_rx); ModeRequestHandlerMpscBounded::new(MGM_HANDLER_0.into(), mgm_handler_mode_rx);
let mgm_1_mode_node = ModeRequestHandlerMpscBounded::new(MGM1.into(), mgm_1_handler_mode_rx); let mgm_spi_interface = if let Some(sim_client) = opt_sim_client.as_mut() {
let (mgm_0_spi_interface, mgm_1_spi_interface) = sim_client.add_reply_recipient(satrs_minisim::SimComponent::MgmLis3Mdl, mgm_sim_reply_tx);
if let Some(sim_client) = opt_sim_client.as_mut() {
sim_client
.add_reply_recipient(satrs_minisim::SimComponent::Mgm0Lis3Mdl, mgm_0_sim_reply_tx);
sim_client
.add_reply_recipient(satrs_minisim::SimComponent::Mgm1Lis3Mdl, mgm_1_sim_reply_tx);
(
SpiSimInterfaceWrapper::Sim(SpiSimInterface { SpiSimInterfaceWrapper::Sim(SpiSimInterface {
sim_request_tx: sim_request_tx.clone(), sim_request_tx: sim_request_tx.clone(),
sim_reply_rx: mgm_0_sim_reply_rx, sim_reply_rx: mgm_sim_reply_rx,
}), })
SpiSimInterfaceWrapper::Sim(SpiSimInterface {
sim_request_tx: sim_request_tx.clone(),
sim_reply_rx: mgm_1_sim_reply_rx,
}),
)
} else { } else {
( SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default())
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default()),
SpiSimInterfaceWrapper::Dummy(SpiDummyInterface::default()),
)
}; };
let mut mgm_0_handler = MgmHandlerLis3Mdl::new( let mut mgm_handler = MgmHandlerLis3Mdl::new(
MGM0, MGM_HANDLER_0,
"MGM_0", "MGM_0",
mgm_0_mode_node, mgm_mode_node,
mgm_0_handler_composite_rx, mgm_handler_composite_rx,
pus_hk_reply_tx.clone(), pus_hk_reply_tx.clone(),
switch_helper.clone(), switch_helper.clone(),
tm_sender.clone(), tm_sender,
mgm_0_spi_interface, mgm_spi_interface,
shared_mgm_0_set, shared_mgm_set,
); );
let mut mgm_1_handler = MgmHandlerLis3Mdl::new( // Connect PUS service to device handler.
MGM1,
"MGM_1",
mgm_1_mode_node,
mgm_1_handler_composite_rx,
pus_hk_reply_tx.clone(),
switch_helper.clone(),
tm_sender.clone(),
mgm_1_spi_interface,
shared_mgm_1_set,
);
// Connect PUS service to device handlers.
connect_mode_nodes( connect_mode_nodes(
&mut pus_stack.mode_srv, &mut pus_stack.mode_srv,
mgm_0_handler_mode_tx, mgm_handler_mode_tx,
&mut mgm_0_handler, &mut mgm_handler,
pus_mode_reply_tx.clone(),
);
connect_mode_nodes(
&mut pus_stack.mode_srv,
mgm_1_handler_mode_tx,
&mut mgm_1_handler,
pus_mode_reply_tx.clone(), pus_mode_reply_tx.clone(),
); );
@@ -374,15 +332,16 @@ fn main() {
} else { } else {
SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default()) SerialSimInterfaceWrapper::Dummy(SerialInterfaceDummy::default())
}; };
let pcdu_mode_node = ModeRequestHandlerMpscBounded::new(PCDU.into(), pcdu_handler_mode_rx); let pcdu_mode_node =
ModeRequestHandlerMpscBounded::new(PCDU_HANDLER.into(), pcdu_handler_mode_rx);
let mut pcdu_handler = PcduHandler::new( let mut pcdu_handler = PcduHandler::new(
PCDU, PCDU_HANDLER,
"PCDU", "PCDU",
pcdu_mode_node, pcdu_mode_node,
pcdu_handler_composite_rx, pcdu_handler_composite_rx,
pus_hk_reply_tx, pus_hk_reply_tx,
switch_request_rx, switch_request_rx,
tm_sender.clone(), tm_sink_tx,
pcdu_serial_interface, pcdu_serial_interface,
shared_switch_set, shared_switch_set,
); );
@@ -455,8 +414,7 @@ fn main() {
let jh_aocs = thread::Builder::new() let jh_aocs = thread::Builder::new()
.name("sat-rs aocs".to_string()) .name("sat-rs aocs".to_string())
.spawn(move || loop { .spawn(move || loop {
mgm_0_handler.periodic_operation(); mgm_handler.periodic_operation();
mgm_1_handler.periodic_operation();
thread::sleep(Duration::from_millis(FREQ_MS_AOCS)); thread::sleep(Duration::from_millis(FREQ_MS_AOCS));
}) })
.unwrap(); .unwrap();

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -11,8 +11,8 @@ use satrs::pus::{
}; };
use satrs::spacepackets::ecss::tc::PusTcReader; use satrs::spacepackets::ecss::tc::PusTcReader;
use satrs::spacepackets::ecss::{PusPacket, PusServiceId}; use satrs::spacepackets::ecss::{PusPacket, PusServiceId};
use satrs_example::config::components::PUS_TEST_SERVICE;
use satrs_example::config::{tmtc_err, TEST_EVENT}; use satrs_example::config::{tmtc_err, TEST_EVENT};
use satrs_example::ids::generic_pus::PUS_TEST;
use std::sync::mpsc; use std::sync::mpsc;
use super::{DirectPusService, HandlingStatus}; use super::{DirectPusService, HandlingStatus};
@@ -24,10 +24,10 @@ pub fn create_test_service(
pus_test_rx: mpsc::Receiver<EcssTcAndToken>, pus_test_rx: mpsc::Receiver<EcssTcAndToken>,
) -> TestCustomServiceWrapper { ) -> TestCustomServiceWrapper {
let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new( let pus17_handler = PusService17TestHandler::new(PusServiceHelper::new(
PUS_TEST.id(), PUS_TEST_SERVICE.id(),
pus_test_rx, pus_test_rx,
tm_sender, tm_sender,
create_verification_reporter(PUS_TEST.id(), PUS_TEST.apid), create_verification_reporter(PUS_TEST_SERVICE.id(), PUS_TEST_SERVICE.apid),
tc_in_mem_converter, tc_in_mem_converter,
)); ));
TestCustomServiceWrapper { TestCustomServiceWrapper {
@@ -90,7 +90,7 @@ impl DirectPusService for TestCustomServiceWrapper {
); );
} }
DirectPusPacketHandlerResult::CustomSubservice(subservice, token) => { DirectPusPacketHandlerResult::CustomSubservice(subservice, token) => {
let tc = PusTcReader::new( let (tc, _) = PusTcReader::new(
self.handler self.handler
.service_helper .service_helper
.tc_in_mem_converter .tc_in_mem_converter
@@ -100,7 +100,7 @@ impl DirectPusService for TestCustomServiceWrapper {
if subservice == 128 { if subservice == 128 {
info!("generating test event"); info!("generating test event");
self.event_tx self.event_tx
.send(EventMessage::new(PUS_TEST.id(), TEST_EVENT.into())) .send(EventMessage::new(PUS_TEST_SERVICE.id(), TEST_EVENT.into()))
.expect("Sending test event failed"); .expect("Sending test event failed");
match self.handler.service_helper.verif_reporter().start_success( match self.handler.service_helper.verif_reporter().start_success(
self.handler.service_helper.tm_sender(), 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::tc::PusTcReader;
use satrs::spacepackets::ecss::PusPacket; use satrs::spacepackets::ecss::PusPacket;
use satrs::ComponentId; use satrs::ComponentId;
use satrs_example::config::components::PUS_ROUTING_SERVICE;
use satrs_example::config::tmtc_err; use satrs_example::config::tmtc_err;
use satrs_example::ids;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
#[non_exhaustive] #[non_exhaustive]
@@ -37,7 +37,7 @@ pub struct GenericRequestRouter {
impl Default for GenericRequestRouter { impl Default for GenericRequestRouter {
fn default() -> Self { fn default() -> Self {
Self { Self {
id: ids::generic_pus::PUS_ROUTING.raw(), id: PUS_ROUTING_SERVICE.raw(),
composite_router_map: Default::default(), composite_router_map: Default::default(),
mode_router_map: Default::default(), mode_router_map: Default::default(),
} }

View File

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

View File

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

View File

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

View File

@@ -11,7 +11,7 @@ serde_json = "1"
log = "0.4" log = "0.4"
thiserror = "2" thiserror = "2"
fern = "0.7" fern = "0.7"
strum = { version = "0.27", features = ["derive"] } strum = { version = "0.26", features = ["derive"] }
num_enum = "0.7" num_enum = "0.7"
humantime = "2" humantime = "2"
tai-time = { version = "0.3", features = ["serde"] } tai-time = { version = "0.3", features = ["serde"] }

View File

@@ -203,7 +203,7 @@ pub mod tests {
let sim_reply = sim_testbench.try_receive_next_reply(); let sim_reply = sim_testbench.try_receive_next_reply();
assert!(sim_reply.is_some()); assert!(sim_reply.is_some());
let sim_reply = sim_reply.unwrap(); let sim_reply = sim_reply.unwrap();
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl); assert_eq!(sim_reply.component(), SimComponent::MgmLis3Mdl);
let reply = MgmLis3MdlReply::from_sim_message(&sim_reply) let reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
.expect("failed to deserialize MGM sensor values"); .expect("failed to deserialize MGM sensor values");
assert_eq!(reply.common.switch_state, SwitchStateBinary::Off); assert_eq!(reply.common.switch_state, SwitchStateBinary::Off);
@@ -226,7 +226,7 @@ pub mod tests {
let mut sim_reply_res = sim_testbench.try_receive_next_reply(); let mut sim_reply_res = sim_testbench.try_receive_next_reply();
assert!(sim_reply_res.is_some()); assert!(sim_reply_res.is_some());
let mut sim_reply = sim_reply_res.unwrap(); let mut sim_reply = sim_reply_res.unwrap();
assert_eq!(sim_reply.component(), SimComponent::Mgm0Lis3Mdl); assert_eq!(sim_reply.component(), SimComponent::MgmLis3Mdl);
let first_reply = MgmLis3MdlReply::from_sim_message(&sim_reply) let first_reply = MgmLis3MdlReply::from_sim_message(&sim_reply)
.expect("failed to deserialize MGM sensor values"); .expect("failed to deserialize MGM sensor values");
sim_testbench.step_until(Duration::from_millis(50)).unwrap(); sim_testbench.step_until(Duration::from_millis(50)).unwrap();

View File

@@ -24,8 +24,7 @@ const PCDU_REQ_WIRETAPPING: bool = false;
const MGT_REQ_WIRETAPPING: bool = false; const MGT_REQ_WIRETAPPING: bool = false;
pub struct ModelAddrWrapper { pub struct ModelAddrWrapper {
mgm_0_addr: Address<MagnetometerModel<MgmLis3MdlReply>>, mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
mgm_1_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pcdu_addr: Address<PcduModel>, pcdu_addr: Address<PcduModel>,
mgt_addr: Address<MagnetorquerModel>, mgt_addr: Address<MagnetorquerModel>,
} }
@@ -43,14 +42,12 @@ pub struct SimController {
impl ModelAddrWrapper { impl ModelAddrWrapper {
pub fn new( pub fn new(
mgm_0_addr: Address<MagnetometerModel<MgmLis3MdlReply>>, mgm_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
mgm_1_addr: Address<MagnetometerModel<MgmLis3MdlReply>>,
pcdu_addr: Address<PcduModel>, pcdu_addr: Address<PcduModel>,
mgt_addr: Address<MagnetorquerModel>, mgt_addr: Address<MagnetorquerModel>,
) -> Self { ) -> Self {
Self { Self {
mgm_0_addr, mgm_addr,
mgm_1_addr,
pcdu_addr, pcdu_addr,
mgt_addr, mgt_addr,
} }
@@ -99,8 +96,7 @@ impl SimController {
} }
if let Err(e) = match request.component() { if let Err(e) = match request.component() {
SimComponent::SimCtrl => self.handle_ctrl_request(&request), SimComponent::SimCtrl => self.handle_ctrl_request(&request),
SimComponent::Mgm0Lis3Mdl => self.handle_mgm_request(0, &request), SimComponent::MgmLis3Mdl => self.handle_mgm_request(&request),
SimComponent::Mgm1Lis3Mdl => self.handle_mgm_request(1, &request),
SimComponent::Mgt => self.handle_mgt_request(&request), SimComponent::Mgt => self.handle_mgt_request(&request),
SimComponent::Pcdu => self.handle_pcdu_request(&request), SimComponent::Pcdu => self.handle_pcdu_request(&request),
} { } {
@@ -120,7 +116,7 @@ impl SimController {
fn handle_ctrl_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> { fn handle_ctrl_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> {
let sim_ctrl_request = SimCtrlRequest::from_sim_message(request)?; let sim_ctrl_request = SimCtrlRequest::from_sim_message(request)?;
if SIM_CTRL_REQ_WIRETAPPING { if SIM_CTRL_REQ_WIRETAPPING {
log::info!("received sim ctrl request: {sim_ctrl_request:?}"); log::info!("received sim ctrl request: {:?}", sim_ctrl_request);
} }
match sim_ctrl_request { match sim_ctrl_request {
SimCtrlRequest::Ping => { SimCtrlRequest::Ping => {
@@ -132,25 +128,19 @@ impl SimController {
Ok(()) Ok(())
} }
fn handle_mgm_request( fn handle_mgm_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> {
&mut self,
mgm_idx: usize,
request: &SimRequest,
) -> Result<(), SimRequestError> {
let mgm_request = MgmRequestLis3Mdl::from_sim_message(request)?; let mgm_request = MgmRequestLis3Mdl::from_sim_message(request)?;
if MGM_REQ_WIRETAPPING { if MGM_REQ_WIRETAPPING {
log::info!("received MGM request: {mgm_request:?}"); log::info!("received MGM request: {:?}", mgm_request);
} }
match mgm_request { match mgm_request {
MgmRequestLis3Mdl::RequestSensorData => { MgmRequestLis3Mdl::RequestSensorData => {
let addr = match mgm_idx {
0 => &self.addr_wrapper.mgm_0_addr,
1 => &self.addr_wrapper.mgm_1_addr,
_ => panic!("invalid mgm index"),
};
self.simulation self.simulation
.process_event(MagnetometerModel::send_sensor_values, (), addr) .process_event(
MagnetometerModel::send_sensor_values,
(),
&self.addr_wrapper.mgm_addr,
)
.expect("event execution error for mgm"); .expect("event execution error for mgm");
} }
} }
@@ -160,7 +150,7 @@ impl SimController {
fn handle_pcdu_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> { fn handle_pcdu_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> {
let pcdu_request = PcduRequest::from_sim_message(request)?; let pcdu_request = PcduRequest::from_sim_message(request)?;
if PCDU_REQ_WIRETAPPING { if PCDU_REQ_WIRETAPPING {
log::info!("received PCDU request: {pcdu_request:?}"); log::info!("received PCDU request: {:?}", pcdu_request);
} }
match pcdu_request { match pcdu_request {
PcduRequest::RequestSwitchInfo => { PcduRequest::RequestSwitchInfo => {
@@ -188,7 +178,7 @@ impl SimController {
fn handle_mgt_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> { fn handle_mgt_request(&mut self, request: &SimRequest) -> Result<(), SimRequestError> {
let mgt_request = MgtRequest::from_sim_message(request)?; let mgt_request = MgtRequest::from_sim_message(request)?;
if MGT_REQ_WIRETAPPING { if MGT_REQ_WIRETAPPING {
log::info!("received MGT request: {mgt_request:?}"); log::info!("received MGT request: {:?}", mgt_request);
} }
match mgt_request { match mgt_request {
MgtRequest::ApplyTorque { duration, dipole } => self MgtRequest::ApplyTorque { duration, dipole } => self

View File

@@ -14,8 +14,7 @@ pub const SWITCH_INFO_DELAY_MS: u64 = 10;
pub struct PcduModel { pub struct PcduModel {
pub switcher_map: SwitchMapBinaryWrapper, pub switcher_map: SwitchMapBinaryWrapper,
pub mgm_0_switch: Output<SwitchStateBinary>, pub mgm_switch: Output<SwitchStateBinary>,
pub mgm_1_switch: Output<SwitchStateBinary>,
pub mgt_switch: Output<SwitchStateBinary>, pub mgt_switch: Output<SwitchStateBinary>,
pub reply_sender: mpsc::Sender<SimReply>, pub reply_sender: mpsc::Sender<SimReply>,
} }
@@ -24,8 +23,7 @@ impl PcduModel {
pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self { pub fn new(reply_sender: mpsc::Sender<SimReply>) -> Self {
Self { Self {
switcher_map: Default::default(), switcher_map: Default::default(),
mgm_0_switch: Output::new(), mgm_switch: Output::new(),
mgm_1_switch: Output::new(),
mgt_switch: Output::new(), mgt_switch: Output::new(),
reply_sender, reply_sender,
} }
@@ -57,7 +55,7 @@ impl PcduModel {
*val = switch_and_target_state.1; *val = switch_and_target_state.1;
match switch_and_target_state.0 { match switch_and_target_state.0 {
PcduSwitch::Mgm => { PcduSwitch::Mgm => {
self.mgm_0_switch.send(switch_and_target_state.1).await; self.mgm_switch.send(switch_and_target_state.1).await;
} }
PcduSwitch::Mgt => { PcduSwitch::Mgt => {
self.mgt_switch.send(switch_and_target_state.1).await; self.mgt_switch.send(switch_and_target_state.1).await;

View File

@@ -5,8 +5,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)] #[derive(Debug, Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Hash)]
pub enum SimComponent { pub enum SimComponent {
SimCtrl, SimCtrl,
Mgm0Lis3Mdl, MgmLis3Mdl,
Mgm1Lis3Mdl,
Mgt, Mgt,
Pcdu, Pcdu,
} }
@@ -278,7 +277,7 @@ pub mod acs {
} }
impl SerializableSimMsgPayload<SimRequest> for MgmRequestLis3Mdl { impl SerializableSimMsgPayload<SimRequest> for MgmRequestLis3Mdl {
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl; const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
} }
// Normally, small magnetometers generate their output as a signed 16 bit raw format or something // Normally, small magnetometers generate their output as a signed 16 bit raw format or something
@@ -369,7 +368,7 @@ pub mod acs {
} }
impl SerializableSimMsgPayload<SimReply> for MgmLis3MdlReply { impl SerializableSimMsgPayload<SimReply> for MgmLis3MdlReply {
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl; const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
} }
impl MgmReplyProvider for MgmLis3MdlReply { impl MgmReplyProvider for MgmLis3MdlReply {
@@ -419,7 +418,7 @@ pub mod acs {
} }
impl SerializableSimMsgPayload<SimReply> for MgtReply { impl SerializableSimMsgPayload<SimReply> for MgtReply {
const TARGET: SimComponent = SimComponent::Mgm0Lis3Mdl; const TARGET: SimComponent = SimComponent::MgmLis3Mdl;
} }
} }

View File

@@ -31,15 +31,11 @@ fn create_sim_controller(
request_receiver: mpsc::Receiver<SimRequest>, request_receiver: mpsc::Receiver<SimRequest>,
) -> SimController { ) -> SimController {
// Instantiate models and their mailboxes. // Instantiate models and their mailboxes.
let mgm_0_model = let mgm_model =
MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone());
let mgm_1_model =
MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone()); MagnetometerModel::new_for_lis3mdl(Duration::from_millis(50), reply_sender.clone());
let mgm_0_mailbox = Mailbox::new(); let mgm_mailbox = Mailbox::new();
let mgm_0_addr = mgm_0_mailbox.address(); let mgm_addr = mgm_mailbox.address();
let mgm_1_mailbox = Mailbox::new();
let mgm_1_addr = mgm_1_mailbox.address();
let pcdu_mailbox = Mailbox::new(); let pcdu_mailbox = Mailbox::new();
let pcdu_addr = pcdu_mailbox.address(); let pcdu_addr = pcdu_mailbox.address();
let mgt_mailbox = Mailbox::new(); let mgt_mailbox = Mailbox::new();
@@ -47,11 +43,8 @@ fn create_sim_controller(
let mut pcdu_model = PcduModel::new(reply_sender.clone()); let mut pcdu_model = PcduModel::new(reply_sender.clone());
pcdu_model pcdu_model
.mgm_0_switch .mgm_switch
.connect(MagnetometerModel::switch_device, &mgm_0_addr); .connect(MagnetometerModel::switch_device, &mgm_addr);
pcdu_model
.mgm_1_switch
.connect(MagnetometerModel::switch_device, &mgm_1_addr);
let mut mgt_model = MagnetorquerModel::new(reply_sender.clone()); let mut mgt_model = MagnetorquerModel::new(reply_sender.clone());
// Input connections. // Input connections.
@@ -59,14 +52,9 @@ fn create_sim_controller(
.mgt_switch .mgt_switch
.connect(MagnetorquerModel::switch_device, &mgt_addr); .connect(MagnetorquerModel::switch_device, &mgt_addr);
// Output connections. // Output connections.
mgt_model.gen_magnetic_field.connect( mgt_model
MagnetometerModel::apply_external_magnetic_field, .gen_magnetic_field
&mgm_0_addr, .connect(MagnetometerModel::apply_external_magnetic_field, &mgm_addr);
);
mgt_model.gen_magnetic_field.connect(
MagnetometerModel::apply_external_magnetic_field,
&mgm_1_addr,
);
// Instantiate the simulator // Instantiate the simulator
let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now()); let sys_clock = SystemClock::from_system_time(start_time, SystemTime::now());
@@ -75,10 +63,9 @@ fn create_sim_controller(
} else { } else {
SimInit::new() SimInit::new()
}; };
let addrs = ModelAddrWrapper::new(mgm_0_addr, mgm_1_addr, pcdu_addr, mgt_addr); let addrs = ModelAddrWrapper::new(mgm_addr, pcdu_addr, mgt_addr);
let (simulation, scheduler) = sim_init let (simulation, scheduler) = sim_init
.add_model(mgm_0_model, mgm_0_mailbox, "MGM 0 model") .add_model(mgm_model, mgm_mailbox, "MGM model")
.add_model(mgm_1_model, mgm_1_mailbox, "MGM 1 model")
.add_model(pcdu_model, pcdu_mailbox, "PCDU model") .add_model(pcdu_model, pcdu_mailbox, "PCDU model")
.add_model(mgt_model, mgt_mailbox, "MGT model") .add_model(mgt_model, mgt_mailbox, "MGT model")
.init(start_time) .init(start_time)
@@ -130,7 +117,7 @@ fn main() {
let mut udp_server = let mut udp_server =
SimUdpServer::new(SIM_CTRL_PORT, request_sender, reply_receiver, 200, None) SimUdpServer::new(SIM_CTRL_PORT, request_sender, reply_receiver, 200, None)
.expect("could not create UDP request server"); .expect("could not create UDP request server");
log::info!("starting UDP server on port {SIM_CTRL_PORT}"); log::info!("starting UDP server on port {}", SIM_CTRL_PORT);
// This thread manages the simulator UDP server. // This thread manages the simulator UDP server.
let udp_tc_thread = thread::spawn(move || { let udp_tc_thread = thread::spawn(move || {
udp_server.run(); udp_server.run();

View File

@@ -8,14 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v0.2.3] 2025-07-22
`spacepackets` range v0.14 to v0.15
# [v0.2.2] 2025-05-10
- Bump to `spacepackests` v0.14
# [v0.2.1] 2024-11-15 # [v0.2.1] 2024-11-15
Increased allowed spacepackets to v0.13 Increased allowed spacepackets to v0.13
@@ -49,7 +41,3 @@ Allow `spacepackets` range starting with v0.10 and v0.11.
# [v0.1.0] 2024-02-12 # [v0.1.0] 2024-02-12
Initial release. Initial release.
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.3...HEAD
[v0.2.3]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-shared-v0.2.1...satrs-shared-v0.2.3
[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] [package]
name = "satrs-shared" name = "satrs-shared"
description = "Components shared by multiple sat-rs crates" description = "Components shared by multiple sat-rs crates"
version = "0.2.3" version = "0.2.1"
edition = "2021" edition = "2021"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"] authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/" homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
@@ -11,7 +11,6 @@ license = "Apache-2.0"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
spacepackets = { version = ">=0.14, <=0.15", default-features = false }
[dependencies.serde] [dependencies.serde]
version = "1" version = "1"
@@ -19,9 +18,12 @@ default-features = false
optional = true optional = true
[dependencies.defmt] [dependencies.defmt]
version = "1" version = "0.3"
optional = true optional = true
[dependencies.spacepackets]
version = ">0.9, <=0.13"
default-features = false
[features] [features]
serde = ["dep:serde", "spacepackets/serde"] serde = ["dep:serde", "spacepackets/serde"]

View File

@@ -8,18 +8,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [unreleased] # [unreleased]
# [v0.3.0-alpha.2] 2025-07-22
`satrs-shared` update
# [v0.3.0-alpha.1] 2025-07-22
`spacepackets` range v0.14 to v0.15
# [v0.3.0-alpha.0] 2025-02-18
`spacepackets` v0.13
## Changed ## Changed
- Renamed `StaticPoolConfig::new` to `StaticPoolConfig::new_from_subpool_cfg_tuples`. The new - Renamed `StaticPoolConfig::new` to `StaticPoolConfig::new_from_subpool_cfg_tuples`. The new
@@ -206,8 +194,3 @@ docs-rs hotfix
# [v0.1.0] 2024-02-12 # [v0.1.0] 2024-02-12
Initial release. Initial release.
[unreleased]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-v0.3.0-alpha.2...HEAD
[v0.3.0-alpha.2]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-v0.3.0-alpha.1...satrs-v0.3.0-alpha.2
[v0.3.0-alpha.1]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-v0.3.0-alpha.0...satrs-v0.3.0-alpha.1
[v0.3.0-alpha.0]: https://egit.irs.uni-stuttgart.de/rust/sat-rs/compare/satrs-v0.2.1...satrs-v0.3.0-alpha.0

View File

@@ -1,11 +1,11 @@
[package] [package]
name = "satrs" name = "satrs"
version = "0.3.0-alpha.2" version = "0.2.1"
edition = "2021" edition = "2021"
rust-version = "1.82.0" rust-version = "1.82.0"
authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"] authors = ["Robin Mueller <muellerr@irs.uni-stuttgart.de>"]
description = "A library collection to build software for remote systems" description = "A framework to build software for remote systems"
homepage = "https://github.com/us-irs/sat-rs" homepage = "https://absatsw.irs.uni-stuttgart.de/projects/sat-rs/"
repository = "https://egit.irs.uni-stuttgart.de/rust/sat-rs" repository = "https://egit.irs.uni-stuttgart.de/rust/sat-rs"
license = "Apache-2.0" license = "Apache-2.0"
keywords = ["no-std", "space", "aerospace"] keywords = ["no-std", "space", "aerospace"]
@@ -13,14 +13,16 @@ keywords = ["no-std", "space", "aerospace"]
categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-support", "embedded"] categories = ["aerospace", "aerospace::space-protocols", "no-std", "hardware-support", "embedded"]
[dependencies] [dependencies]
satrs-shared = { version = "0.2", path = "../satrs-shared" } satrs-shared = ">=0.1.3, <=0.2"
spacepackets = { version = ">=0.14, <=0.15", default-features = false }
delegate = ">0.7, <=0.13" delegate = ">0.7, <=0.13"
paste = "1" paste = "1"
derive-new = ">=0.6, <=0.7" derive-new = ">=0.6, <=0.7"
smallvec = "1"
crc = "3"
num_enum = { version = ">0.5, <=0.7", default-features = false } num_enum = { version = ">0.5, <=0.7", default-features = false }
cobs = { version = "0.4", 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 }
thiserror = { version = "2", default-features = false } thiserror = { version = "2", default-features = false }
hashbrown = { version = ">=0.14, <=0.15", optional = true } hashbrown = { version = ">=0.14, <=0.15", optional = true }
@@ -31,9 +33,9 @@ downcast-rs = { version = "2", default-features = false, optional = true }
bus = { version = "2.2", optional = true } bus = { version = "2.2", optional = true }
crossbeam-channel = { version = "0.5", default-features = false, optional = true } crossbeam-channel = { version = "0.5", default-features = false, optional = true }
serde = { version = "1", default-features = false, optional = true } serde = { version = "1", default-features = false, optional = true }
socket2 = { version = "0.6", features = ["all"], optional = true } socket2 = { version = "0.5", features = ["all"], optional = true }
mio = { version = "1", features = ["os-poll", "net"], optional = true } mio = { version = "1", features = ["os-poll", "net"], optional = true }
defmt = { version = "1", optional = true } defmt = { version = "0.3", optional = true }
[dev-dependencies] [dev-dependencies]
serde = "1" serde = "1"

View File

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

View File

@@ -90,8 +90,8 @@ pub fn parse_buffer_for_ccsds_space_packets<SendError>(
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use spacepackets::{ use spacepackets::{
ecss::tc::PusTcCreator, CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType, ecss::{tc::PusTcCreator, WritablePusPacket},
SequenceFlags, SpHeader, CcsdsPacket, PacketId, PacketSequenceCtrl, PacketType, SequenceFlags, SpHeader,
}; };
use crate::{encoding::tests::TcCacher, ComponentId}; use crate::{encoding::tests::TcCacher, ComponentId};

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!(encode_packet_with_cobs(&INVERTED_PACKET, &mut encoding_buf, &mut current_idx));
/// assert_eq!(encoding_buf[0], 0); /// assert_eq!(encoding_buf[0], 0);
/// let dec_report = decode_in_place_report(&mut encoding_buf[1..]).expect("decoding failed"); /// let dec_report = decode_in_place_report(&mut encoding_buf[1..]).expect("decoding failed");
/// assert_eq!(encoding_buf[1 + dec_report.parsed_size()], 0); /// assert_eq!(encoding_buf[1 + dec_report.src_used], 0);
/// assert_eq!(dec_report.frame_size(), 5); /// assert_eq!(dec_report.dst_used, 5);
/// assert_eq!(current_idx, 16); /// assert_eq!(current_idx, 16);
/// ``` /// ```
pub fn encode_packet_with_cobs( pub fn encode_packet_with_cobs(

View File

@@ -377,13 +377,13 @@ mod tests {
current_idx += 1; current_idx += 1;
let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..]) let mut dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed"); .expect("COBS decoding failed");
assert_eq!(dec_report.frame_size(), 5); assert_eq!(dec_report.dst_used, 5);
// Skip first sentinel byte. // Skip first sentinel byte.
assert_eq!( assert_eq!(
&read_buf[current_idx..current_idx + INVERTED_PACKET.len()], &read_buf[current_idx..current_idx + INVERTED_PACKET.len()],
&INVERTED_PACKET &INVERTED_PACKET
); );
current_idx += dec_report.parsed_size(); current_idx += dec_report.src_used;
// End sentinel. // End sentinel.
assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte"); assert_eq!(read_buf[current_idx], 0, "invalid sentinel end byte");
current_idx += 1; current_idx += 1;
@@ -393,13 +393,13 @@ mod tests {
current_idx += 1; current_idx += 1;
dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..]) dec_report = cobs::decode_in_place_report(&mut read_buf[current_idx..])
.expect("COBS decoding failed"); .expect("COBS decoding failed");
assert_eq!(dec_report.frame_size(), 5); assert_eq!(dec_report.dst_used, 5);
// Skip first sentinel byte. // Skip first sentinel byte.
assert_eq!( assert_eq!(
&read_buf[current_idx..current_idx + SIMPLE_PACKET.len()], &read_buf[current_idx..current_idx + SIMPLE_PACKET.len()],
&SIMPLE_PACKET &SIMPLE_PACKET
); );
current_idx += dec_report.parsed_size(); current_idx += dec_report.src_used;
// End sentinel. // End sentinel.
assert_eq!(read_buf[current_idx], 0); assert_eq!(read_buf[current_idx], 0);
break; break;

View File

@@ -129,6 +129,7 @@ mod tests {
use crate::ComponentId; use crate::ComponentId;
use core::cell::RefCell; use core::cell::RefCell;
use spacepackets::ecss::tc::PusTcCreator; use spacepackets::ecss::tc::PusTcCreator;
use spacepackets::ecss::WritablePusPacket;
use spacepackets::SpHeader; use spacepackets::SpHeader;
use std::collections::VecDeque; use std::collections::VecDeque;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket}; use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};

View File

@@ -409,7 +409,7 @@ mod tests {
assert!(res.event_was_enabled); assert!(res.event_was_enabled);
assert!(res.params_were_propagated); assert!(res.params_were_propagated);
let event_tm = event_rx.try_recv().expect("no event received"); 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.service(), 5);
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8); assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
assert_eq!(tm.user_data().len(), 4 + param_data.len()); assert_eq!(tm.user_data().len(), 4 + param_data.len());
@@ -437,7 +437,7 @@ mod tests {
assert!(res.event_was_enabled); assert!(res.event_was_enabled);
assert!(res.params_were_propagated); assert!(res.params_were_propagated);
let event_tm = event_rx.try_recv().expect("no event received"); 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.service(), 5);
assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8); assert_eq!(tm.subservice(), Subservice::TmInfoReport as u8);
assert_eq!(tm.user_data().len(), 4 + param_data.len()); assert_eq!(tm.user_data().len(), 4 + param_data.len());

View File

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

View File

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

View File

@@ -292,10 +292,10 @@ pub trait PusSchedulerProvider {
pool: &mut (impl PoolProvider + ?Sized), pool: &mut (impl PoolProvider + ?Sized),
) -> Result<TcInfo, ScheduleError> { ) -> Result<TcInfo, ScheduleError> {
let check_tc = PusTcReader::new(tc)?; let check_tc = PusTcReader::new(tc)?;
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 { if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
return Err(ScheduleError::NestedScheduledTc); return Err(ScheduleError::NestedScheduledTc);
} }
let req_id = RequestId::from_tc(&check_tc); let req_id = RequestId::from_tc(&check_tc.0);
match pool.add(tc) { match pool.add(tc) {
Ok(addr) => { Ok(addr) => {
@@ -480,10 +480,10 @@ pub mod alloc_mod {
pool: &mut (impl PoolProvider + ?Sized), pool: &mut (impl PoolProvider + ?Sized),
) -> Result<TcInfo, ScheduleError> { ) -> Result<TcInfo, ScheduleError> {
let check_tc = PusTcReader::new(tc)?; let check_tc = PusTcReader::new(tc)?;
if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 { if PusPacket::service(&check_tc.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 {
return Err(ScheduleError::NestedScheduledTc); return Err(ScheduleError::NestedScheduledTc);
} }
let req_id = RequestId::from_tc(&check_tc); let req_id = RequestId::from_tc(&check_tc.0);
match pool.add(tc) { match pool.add(tc) {
Ok(addr) => { Ok(addr) => {
@@ -1313,7 +1313,7 @@ mod tests {
let mut read_buf: [u8; 64] = [0; 64]; let mut read_buf: [u8; 64] = [0; 64];
pool.read(&tc_info_0.addr(), &mut read_buf).unwrap(); pool.read(&tc_info_0.addr(), &mut read_buf).unwrap();
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data"); let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1); 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 read_len = pool.read(&addr_vec[0], &mut read_buf).unwrap();
let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data"); let check_tc = PusTcReader::new(&read_buf).expect("incorrect Pus tc raw data");
assert_eq!(read_len, check_tc.total_len()); assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
} }
#[test] #[test]
@@ -1362,8 +1362,8 @@ mod tests {
let read_len = pool.read(&info.addr, &mut buf).unwrap(); let read_len = pool.read(&info.addr, &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data"); let check_tc = PusTcReader::new(&buf).expect("incorrect Pus tc raw data");
assert_eq!(read_len, check_tc.total_len()); assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1); 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 read_len = pool.read(&addr_vec[0], &mut buf).unwrap();
let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data"); let check_tc = PusTcReader::new(&buf).expect("incorrect PUS tc raw data");
assert_eq!(read_len, check_tc.total_len()); assert_eq!(read_len, check_tc.1);
assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[]));
} }
#[test] #[test]
@@ -2031,7 +2031,7 @@ mod tests {
assert_eq!(n, 1); assert_eq!(n, 1);
let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap(); let time_reader = cds::CdsTime::from_bytes_with_u16_days(&buf[2..2 + 7]).unwrap();
assert_eq!(time_reader, time_writer); assert_eq!(time_reader, time_writer);
let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap(); let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap().0;
assert_eq!(pus_tc_reader, ping_tc); assert_eq!(pus_tc_reader, ping_tc);
} }

View File

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

View File

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

View File

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

View File

@@ -121,10 +121,10 @@ impl SequenceExecutionHelper {
/// example by checking [mode replies][ModeReply] received by the children components, and /// example by checking [mode replies][ModeReply] received by the children components, and
/// then calling [Self::confirm_sequence_done] to advance to the sequence or complete the /// then calling [Self::confirm_sequence_done] to advance to the sequence or complete the
/// sequence. /// sequence.
/// * [ModeCommandingResult::Done] - The sequence is done. The user can load a new /// * [ModeCommandingResult::CommandingDone] - The sequence is done. The user can load a new
/// sequence now without overwriting the last one. The sequence executor is in /// sequence now without overwriting the last one. The sequence executor is in
/// [SequenceExecutionHelperState::Idle] again. /// [SequenceExecutionHelperState::Idle] again.
/// * [ModeCommandingResult::StepDone] - The sequence has advanced one step. The user /// * [ModeCommandingResult::CommandingStepDone] - The sequence has advanced one step. The user
/// can now call [Self::run] again to immediately execute the next step in the sequence. /// can now call [Self::run] again to immediately execute the next step in the sequence.
/// ///
/// Generally, periodic execution of the [Self::run] method should be performed while /// Generally, periodic execution of the [Self::run] method should be performed while
@@ -597,7 +597,7 @@ impl SubsystemCommandingHelper {
} }
fn update_internal_req_id(&mut self) { 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.current_sequence_index().unwrap() as u32;
self.seq_exec_helper.set_request_id(new_internal_req_id); self.seq_exec_helper.set_request_id(new_internal_req_id);
self.active_internal_request_id = Some(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) => { Ok(event_tm) => {
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7) let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
.expect("Deserializing TM failed"); .expect("Deserializing TM failed");
assert_eq!(tm.service(), 5); assert_eq!(tm.0.service(), 5);
assert_eq!(tm.subservice(), 1); assert_eq!(tm.0.subservice(), 1);
let src_data = tm.source_data(); let src_data = tm.0.source_data();
assert!(!src_data.is_empty()); assert!(!src_data.is_empty());
assert_eq!(src_data.len(), 4); assert_eq!(src_data.len(), 4);
let event = let event =
@@ -137,9 +137,9 @@ fn test_threaded_usage() {
Ok(event_tm) => { Ok(event_tm) => {
let tm = PusTmReader::new(event_tm.packet.as_slice(), 7) let tm = PusTmReader::new(event_tm.packet.as_slice(), 7)
.expect("Deserializing TM failed"); .expect("Deserializing TM failed");
assert_eq!(tm.service(), 5); assert_eq!(tm.0.service(), 5);
assert_eq!(tm.subservice(), 2); assert_eq!(tm.0.subservice(), 2);
let src_data = tm.source_data(); let src_data = tm.0.source_data();
assert!(!src_data.is_empty()); assert!(!src_data.is_empty());
assert_eq!(src_data.len(), 12); assert_eq!(src_data.len(), 12);
let event = let event =

View File

@@ -46,8 +46,8 @@ pub mod crossbeam_test {
let sender = let sender =
PacketSenderWithSharedPool::new_with_shared_packet_pool(tx.clone(), &shared_tm_pool); PacketSenderWithSharedPool::new_with_shared_packet_pool(tx.clone(), &shared_tm_pool);
let sender_1 = sender.clone(); let sender_1 = sender.clone();
let reporter_with_sender_0 = VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &cfg); let mut reporter_with_sender_0 = VerificationReporter::new(TEST_COMPONENT_ID_0.id(), &cfg);
let reporter_with_sender_1 = reporter_with_sender_0.clone(); let mut reporter_with_sender_1 = reporter_with_sender_0.clone();
// For test purposes, we retrieve the request ID from the TCs and pass them to the receiver // For test purposes, we retrieve the request ID from the TCs and pass them to the receiver
// tread. // tread.
let req_id_0; let req_id_0;
@@ -89,9 +89,9 @@ pub mod crossbeam_test {
let pg = tc_guard.read_with_guard(tc_addr); let pg = tc_guard.read_with_guard(tc_addr);
tc_len = pg.read(&mut tc_buf).unwrap(); 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.start_verification_with_req_id(req_id_0); let token = reporter_with_sender_0.add_tc_with_req_id(req_id_0);
let accepted_token = reporter_with_sender_0 let accepted_token = reporter_with_sender_0
.acceptance_success(&sender, token, &FIXED_STAMP) .acceptance_success(&sender, token, &FIXED_STAMP)
.expect("Acceptance success failed"); .expect("Acceptance success failed");
@@ -125,8 +125,8 @@ pub mod crossbeam_test {
let pg = tc_guard.read_with_guard(tc_addr); let pg = tc_guard.read_with_guard(tc_addr);
tc_len = pg.read(&mut tc_buf).unwrap(); 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_1.start_verification(&tc); let token = reporter_with_sender_1.add_tc(&tc);
let accepted_token = reporter_with_sender_1 let accepted_token = reporter_with_sender_1
.acceptance_success(&sender_1, token, &FIXED_STAMP) .acceptance_success(&sender_1, token, &FIXED_STAMP)
.expect("Acceptance success failed"); .expect("Acceptance success failed");
@@ -156,7 +156,7 @@ pub mod crossbeam_test {
.read(&mut tm_buf) .read(&mut tm_buf)
.expect("Error reading TM slice"); .expect("Error reading TM slice");
} }
let pus_tm = let (pus_tm, _) =
PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM"); PusTmReader::new(&tm_buf[0..tm_len], 7).expect("Error reading verification TM");
let req_id = let req_id =
RequestId::from_bytes(&pus_tm.source_data()[0..RequestId::SIZE_AS_BYTES]) RequestId::from_bytes(&pus_tm.source_data()[0..RequestId::SIZE_AS_BYTES])