Compare commits

..

5 Commits

Author SHA1 Message Date
e2b49d4573 dependency hell 2025-05-07 13:25:09 +02:00
d96d9b0aff some more fixes, git updates 2025-05-07 13:23:43 +02:00
f7242de683
start fixing examples etc. 2025-05-07 09:56:43 +02:00
240868d1ce
remove some methods 2025-05-06 16:19:36 +02:00
a650773566
tweaks for msp430 2025-05-05 19:18:03 +02:00
18 changed files with 122 additions and 116 deletions

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

@ -29,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, size) = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed"); let pus_tm = PusTmReader::new(&buf, 7).expect("Parsing PUS TM failed");
if pus_tm.service() == 17 && pus_tm.subservice() == 2 { 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

@ -281,9 +281,7 @@ 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) let tm_reader = PusTmReader::new(&tm_packet.packet, 7).expect("failed to create TM reader");
.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

@ -367,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().0; let unexpected_tm = PusTmReader::new(&tm.packet, 7).unwrap();
panic!("unexpected TM packet {unexpected_tm:?}"); panic!("unexpected TM packet {unexpected_tm:?}");
} }
} }
@ -410,7 +410,11 @@ 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.service.service_helper.verif_reporter_mut().add_tc(tc); let token = self
.service
.service_helper
.verif_reporter_mut()
.start_verification(tc);
let accepted_token = self let accepted_token = self
.service .service
.service_helper .service_helper

View File

@ -109,8 +109,8 @@ impl PusTcDistributor {
// 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().0; let pus_tc = pus_tc_result.unwrap();
let init_token = self.verif_reporter.add_tc(&pus_tc); let init_token = self.verif_reporter.start_verification(&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
@ -599,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.add_tc(&PusTcCreator::new( let init = self.verif_reporter.start_verification(&PusTcCreator::new(
sp_header, sp_header,
sec_header_dummy, sec_header_dummy,
&[], &[],
@ -706,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.add_tc(tc); let token = self.verif_reporter.start_verification(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
@ -734,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.0, &tc_reader,
&self.dummy_sender, &self.dummy_sender,
&self.verif_reporter, &self.verif_reporter,
time_stamp, time_stamp,

View File

@ -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

View File

@ -24,6 +24,7 @@ optional = true
[dependencies.satrs-shared] [dependencies.satrs-shared]
version = ">=0.1.3, <=0.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,6 +28,7 @@ features = ["full"]
trybuild = { version = "1", features = ["diff"] } trybuild = { version = "1", features = ["diff"] }
[dev-dependencies.satrs-shared] [dev-dependencies.satrs-shared]
path = "../../satrs-shared"
version = ">=0.1.3, <=0.2" version = ">=0.1.3, <=0.2"
[dev-dependencies.satrs-mib] [dev-dependencies.satrs-mib]

View File

@ -23,6 +23,8 @@ optional = true
[dependencies.spacepackets] [dependencies.spacepackets]
version = ">0.9, <=0.13" version = ">0.9, <=0.13"
git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git"
branch = "msp430-tweak"
default-features = false default-features = false
[features] [features]

View File

@ -13,16 +13,13 @@ 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 = ">=0.1.3, <=0.2" satrs-shared = { version = ">=0.1.3, <=0.2", path = "../satrs-shared" }
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 }
spacepackets = { version = "0.13", default-features = false } spacepackets = { git = "https://egit.irs.uni-stuttgart.de/rust/spacepackets.git", branch = "msp430-tweak", default-features = false }
cobs = { version = "0.3", default-features = false } cobs = { version = "0.4", default-features = false, git = "https://github.com/jamesmunns/cobs.rs.git", branch = "decoding-improvements" }
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 }

View File

@ -150,9 +150,9 @@ impl<
/// ///
/// * `cfg` - Configuration of the server. /// * `cfg` - Configuration of the server.
/// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are /// * `tm_source` - Generic TM source used by the server to pull telemetry packets which are
/// then sent back to the client. /// then sent back to the client.
/// * `tc_receiver` - Any received telecommands which were decoded successfully will be /// * `tc_receiver` - Any received telecommands which were decoded successfully will be
/// forwarded to this TC receiver. /// forwarded to this TC receiver.
pub fn new( pub fn new(
cfg: ServerConfig, cfg: ServerConfig,
tm_source: TmSource, tm_source: TmSource,
@ -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.dst_used, 5); assert_eq!(dec_report.frame_size(), 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.src_used; current_idx += dec_report.parsed_size();
// 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.dst_used, 5); assert_eq!(dec_report.frame_size(), 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.src_used; current_idx += dec_report.parsed_size();
// End sentinel. // End sentinel.
assert_eq!(read_buf[current_idx], 0); assert_eq!(read_buf[current_idx], 0);
break; break;

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

@ -959,15 +959,11 @@ 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()) Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
.map_err(EcssTmtcError::Pus)?
.0)
} }
fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> { fn convert(&self) -> Result<PusTcReader<'_>, PusTcFromMemError> {
Ok(PusTcReader::new(self.tc_slice_raw()) Ok(PusTcReader::new(self.tc_slice_raw()).map_err(EcssTmtcError::Pus)?)
.map_err(EcssTmtcError::Pus)?
.0)
} }
} }
@ -1459,7 +1455,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().0 PusTmReader::new(&self.tm_buf, 7).unwrap()
} }
pub fn check_no_tm_available(&self) -> bool { pub fn check_no_tm_available(&self) -> bool {
@ -1476,7 +1472,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().0; let tm = PusTmReader::new(&tm_raw, 7).unwrap();
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);
@ -1584,9 +1580,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());
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) PusTmReader::new(self.current_tm.as_ref().unwrap(), 7).unwrap()
.unwrap()
.0
} }
pub fn check_no_tm_available(&self) -> bool { pub fn check_no_tm_available(&self) -> bool {
@ -1601,7 +1595,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().0; let tm = PusTmReader::new(next_msg.packet.as_slice(), 7).unwrap();
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.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 { if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
return Err(ScheduleError::NestedScheduledTc); return Err(ScheduleError::NestedScheduledTc);
} }
let req_id = RequestId::from_tc(&check_tc.0); let req_id = RequestId::from_tc(&check_tc);
match pool.add(tc) { 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.0) == 11 && PusPacket::subservice(&check_tc.0) == 4 { if PusPacket::service(&check_tc) == 11 && PusPacket::subservice(&check_tc) == 4 {
return Err(ScheduleError::NestedScheduledTc); return Err(ScheduleError::NestedScheduledTc);
} }
let req_id = RequestId::from_tc(&check_tc.0); let req_id = RequestId::from_tc(&check_tc);
match pool.add(tc) { 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.0, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc, 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.1); assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc, 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.1); assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc, base_ping_tc_simple_ctor(0, &[]));
assert_eq!(scheduler.num_scheduled_telecommands(), 1); 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.1); assert_eq!(read_len, check_tc.total_len());
assert_eq!(check_tc.0, base_ping_tc_simple_ctor(0, &[])); assert_eq!(check_tc, 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().0; let pus_tc_reader = PusTcReader::new(&buf[9..]).unwrap();
assert_eq!(pus_tc_reader, ping_tc); assert_eq!(pus_tc_reader, ping_tc);
} }

View File

@ -310,7 +310,11 @@ mod tests {
impl PusTestHarness for Pus11HandlerWithStoreTester { impl PusTestHarness for Pus11HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> { fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler self.handler
.service_helper .service_helper
.verif_reporter() .verif_reporter()

View File

@ -181,7 +181,11 @@ mod tests {
impl PusTestHarness for Pus17HandlerWithStoreTester { impl PusTestHarness for Pus17HandlerWithStoreTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> { fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler self.handler
.service_helper .service_helper
.verif_reporter() .verif_reporter()
@ -239,7 +243,11 @@ mod tests {
impl PusTestHarness for Pus17HandlerWithVecTester { impl PusTestHarness for Pus17HandlerWithVecTester {
fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> { fn init_verification(&mut self, tc: &PusTcCreator) -> VerificationToken<TcStateAccepted> {
let init_token = self.handler.service_helper.verif_reporter_mut().add_tc(tc); let init_token = self
.handler
.service_helper
.verif_reporter_mut()
.start_verification(tc);
self.handler self.handler
.service_helper .service_helper
.verif_reporter() .verif_reporter()

View File

@ -228,7 +228,7 @@ pub struct VerificationToken<STATE> {
} }
impl<STATE> VerificationToken<STATE> { impl<STATE> VerificationToken<STATE> {
fn new(req_id: RequestId) -> VerificationToken<TcStateNone> { pub fn new(req_id: RequestId) -> VerificationToken<TcStateNone> {
VerificationToken { VerificationToken {
state: PhantomData, state: PhantomData,
request_id: req_id, request_id: req_id,
@ -408,14 +408,10 @@ 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 add_tc( fn start_verification(
&mut self, &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,
@ -482,7 +478,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(Clone)] #[derive(Debug, Clone)]
pub struct VerificationReportCreator { pub struct VerificationReportCreator {
pub dest_id: u16, pub dest_id: u16,
apid: u16, apid: u16,
@ -518,17 +514,8 @@ 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 add_tc( pub fn read_request_id_from_tc(pus_tc: &(impl CcsdsPacket + IsPusTelecommand)) -> RequestId {
&mut self, RequestId::new(pus_tc)
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
self.add_tc_with_req_id(RequestId::new(pus_tc))
}
/// Same as [Self::add_tc] but pass a request ID instead of the direct telecommand.
/// This can be useful if the executing thread does not have full access to the telecommand.
pub fn add_tc_with_req_id(&mut self, req_id: RequestId) -> VerificationToken<TcStateNone> {
VerificationToken::<TcStateNone>::new(req_id)
} }
fn success_verification_no_step<'time, 'src_data>( fn success_verification_no_step<'time, 'src_data>(
@ -962,12 +949,19 @@ 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),
)
}
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,11 +979,16 @@ 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
} }
@ -1351,22 +1350,19 @@ pub mod test_util {
} }
impl VerificationReportingProvider for TestVerificationReporter { impl VerificationReportingProvider for TestVerificationReporter {
fn start_verification(
&self,
pus_tc: &(impl CcsdsPacket + IsPusTelecommand),
) -> VerificationToken<TcStateNone> {
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),
@ -1823,15 +1819,16 @@ pub mod tests {
} }
} }
pub fn init_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>,
@ -2081,8 +2078,8 @@ pub mod tests {
#[test] #[test]
fn test_basic_acceptance_success() { fn test_basic_acceptance_success() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16); let testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 16);
let token = testbench.init(); let token = testbench.init_verification();
testbench testbench
.acceptance_success(token, &EMPTY_STAMP) .acceptance_success(token, &EMPTY_STAMP)
.expect("sending acceptance success failed"); .expect("sending acceptance success failed");
@ -2092,7 +2089,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.init(); let init_token = testbench.init_verification();
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);
@ -2105,7 +2102,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.init(); let init_token = testbench.init_verification();
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);
@ -2118,7 +2115,7 @@ pub mod tests {
#[test] #[test]
fn test_acceptance_fail_data_too_large() { fn test_acceptance_fail_data_too_large() {
let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8); let mut testbench = VerificationReporterTestbench::new(0, create_generic_ping(), 8);
let init_token = testbench.init(); let init_token = testbench.init_verification();
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];
@ -2155,7 +2152,7 @@ pub mod tests {
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.init(); let init_token = testbench.init_verification();
testbench testbench
.acceptance_failure(init_token, fail_params) .acceptance_failure(init_token, fail_params)
.expect("sending acceptance failure failed"); .expect("sending acceptance failure failed");
@ -2173,7 +2170,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.init(); let init_token = testbench.init_verification();
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];
@ -2192,7 +2189,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.init(); let token = testbench.init_verification();
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];
@ -2211,7 +2208,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.init(); let token = testbench.init_verification();
let accepted_token = testbench let accepted_token = testbench
.acceptance_success(token, &EMPTY_STAMP) .acceptance_success(token, &EMPTY_STAMP)
.expect("acceptance failed"); .expect("acceptance failed");
@ -2234,7 +2231,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.init(); let token = testbench.init_verification();
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];
@ -2268,7 +2265,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.init(); let token = testbench.init_verification();
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);
@ -2291,7 +2288,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.init(); let token = testbench.init_verification();
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");
@ -2313,7 +2310,7 @@ pub mod tests {
create_generic_ping(), create_generic_ping(),
SequenceCounterHook::default(), SequenceCounterHook::default(),
); );
let token = testbench.init(); let token = testbench.init_verification();
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");
@ -2331,7 +2328,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.init(); let token = testbench.init_verification();
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");
@ -2358,7 +2355,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.init(); let token = testbench.init_verification();
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

@ -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.0.service(), 5); assert_eq!(tm.service(), 5);
assert_eq!(tm.0.subservice(), 1); assert_eq!(tm.subservice(), 1);
let src_data = tm.0.source_data(); let src_data = tm.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.0.service(), 5); assert_eq!(tm.service(), 5);
assert_eq!(tm.0.subservice(), 2); assert_eq!(tm.subservice(), 2);
let src_data = tm.0.source_data(); let src_data = tm.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 =