diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d67710..17613f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). # [unreleased] -# [v0.17.0] 2025-10-29 +# [v0.17.0] 2025-10-31 ## Changed @@ -18,6 +18,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/). value getter. - Renamed `CcsdsPrimaryHeader::from_composite_fields` to `CcsdsPrimaryHeader::new_from_composite_fields` +- Renamed `PusPacket::service` to `PusPacket::service_type_id` and `PusPacket::subservice` to + `PusPacket::message_subtype_id`. Also added `PusPacket::message_type_id`. Performed the same + change for the ECSS PUS C secondary header traits. ## Added diff --git a/src/ecss/mod.rs b/src/ecss/mod.rs index 95dd2c9..4db5043 100644 --- a/src/ecss/mod.rs +++ b/src/ecss/mod.rs @@ -203,17 +203,45 @@ pub enum PusError { ByteConversion(#[from] ByteConversionError), } +/// Message type ID field. +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "defmt", derive(defmt::Format))] +pub struct MessageTypeId { + pub type_id: u8, + pub subtype_id: u8, +} + +impl MessageTypeId { + /// Generic constructor. + pub const fn new(type_id: u8, subtype_id: u8) -> Self { + Self { + type_id, + subtype_id, + } + } +} + /// Generic trait to describe common attributes for both PUS Telecommands (TC) and PUS Telemetry /// (TM) packets. All PUS packets are also a special type of [CcsdsPacket]s. pub trait PusPacket: CcsdsPacket { /// PUS version. fn pus_version(&self) -> Result; - /// Service ID. - fn service(&self) -> u8; + /// Message type ID. + fn message_type_id(&self) -> MessageTypeId; - /// Subservice ID. - fn subservice(&self) -> u8; + /// Service type ID. + #[inline] + fn service_type_id(&self) -> u8 { + self.message_type_id().type_id + } + + /// Message subtype ID. + #[inline] + fn message_subtype_id(&self) -> u8 { + self.message_type_id().subtype_id + } /// User data field. fn user_data(&self) -> &[u8]; diff --git a/src/ecss/tc.rs b/src/ecss/tc.rs index 81dcd7f..a3809ab 100644 --- a/src/ecss/tc.rs +++ b/src/ecss/tc.rs @@ -5,18 +5,18 @@ //! //! ```rust //! use spacepackets::SpHeader; -//! use spacepackets::ecss::tc::{PusTcCreator, PusTcReader, PusTcSecondaryHeader, CreatorConfig}; +//! use spacepackets::ecss::tc::{MessageTypeId, PusTcCreator, PusTcReader, PusTcSecondaryHeader, CreatorConfig}; //! use arbitrary_int::u11; //! //! // Create a ping telecommand with no user application data //! let pus_tc = PusTcCreator::new_no_app_data( //! SpHeader::new_from_apid(u11::new(0x02)), -//! PusTcSecondaryHeader::new_simple(17, 1), +//! PusTcSecondaryHeader::new_simple(MessageTypeId::new(17, 1)), //! CreatorConfig::default() //! ); //! println!("{:?}", pus_tc); -//! assert_eq!(pus_tc.service(), 17); -//! assert_eq!(pus_tc.subservice(), 1); +//! assert_eq!(pus_tc.service_type_id(), 17); +//! assert_eq!(pus_tc.message_subtype_id(), 1); //! assert_eq!(pus_tc.apid().value(), 0x02); //! //! // Serialize TC into a raw buffer @@ -29,25 +29,25 @@ //! //! // Deserialize from the raw byte representation //! let pus_tc_deserialized = PusTcReader::new(&test_buf).expect("Deserialization failed"); -//! assert_eq!(pus_tc.service(), 17); -//! assert_eq!(pus_tc.subservice(), 1); +//! assert_eq!(pus_tc.service_type_id(), 17); +//! assert_eq!(pus_tc.message_subtype_id(), 1); //! assert_eq!(pus_tc.apid().value(), 0x02); //! //! // Alternative builder API //! let pus_tc_by_builder = PusTcCreator::builder() -//! .with_service(17) -//! .with_subservice(1) +//! .with_service_type_id(17) +//! .with_message_subtype_id(1) //! .with_apid(u11::new(0x02)) //! .build(); //! assert_eq!(pus_tc_by_builder, pus_tc); //! ``` use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE}; -pub use crate::ecss::CreatorConfig; use crate::ecss::{ crc_from_raw_data, sp_header_impls, user_data_from_raw, verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion, WritablePusPacket, }; +pub use crate::ecss::{CreatorConfig, MessageTypeId}; use crate::{ByteConversionError, CcsdsPacket, PacketType, SequenceFlags, CCSDS_HEADER_LEN}; use crate::{PacketId, PacketSequenceControl, SpHeader}; use arbitrary_int::{u11, u14, u3, u4}; @@ -100,16 +100,29 @@ impl AckFlags { } pub trait GenericPusTcSecondaryHeader { + /// PUS version. fn pus_version(&self) -> Result; + /// Acknowledgement flags. fn ack_flags(&self) -> AckFlags; - fn service(&self) -> u8; - fn subservice(&self) -> u8; + /// Message type ID. + fn message_type_id(&self) -> MessageTypeId; + /// Source ID. fn source_id(&self) -> u16; + + #[inline] + fn service_type_id(&self) -> u8 { + self.message_type_id().type_id + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.message_type_id().subtype_id + } } pub mod zc { use crate::ecss::tc::{AckFlags, GenericPusTcSecondaryHeader}; - use crate::ecss::{PusError, PusVersion}; + use crate::ecss::{MessageTypeId, PusError, PusVersion}; use arbitrary_int::traits::Integer; use arbitrary_int::u4; use zerocopy::{FromBytes, Immutable, IntoBytes, NetworkEndian, Unaligned, U16}; @@ -118,8 +131,8 @@ pub mod zc { #[repr(C)] pub struct PusTcSecondaryHeader { version_ack: u8, - service: u8, - subservice: u8, + service_type_id: u8, + message_subtype_id: u8, source_id: U16, } @@ -131,8 +144,8 @@ pub mod zc { } Ok(PusTcSecondaryHeader { version_ack: ((value.version as u8) << 4) | value.ack_flags.raw_value().as_u8(), - service: value.service, - subservice: value.subservice, + service_type_id: value.service_type_id(), + message_subtype_id: value.message_subtype_id(), source_id: U16::from(value.source_id), }) } @@ -150,13 +163,22 @@ pub mod zc { } #[inline] - fn service(&self) -> u8 { - self.service + /// Message type ID. + fn message_type_id(&self) -> MessageTypeId { + MessageTypeId { + type_id: self.service_type_id, + subtype_id: self.message_subtype_id, + } } #[inline] - fn subservice(&self) -> u8 { - self.subservice + fn service_type_id(&self) -> u8 { + self.service_type_id + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.message_subtype_id } #[inline] @@ -170,8 +192,7 @@ pub mod zc { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "defmt", derive(defmt::Format))] pub struct PusTcSecondaryHeader { - pub service: u8, - pub subservice: u8, + pub message_type_id: MessageTypeId, pub source_id: u16, pub ack_flags: AckFlags, pub version: PusVersion, @@ -189,13 +210,8 @@ impl GenericPusTcSecondaryHeader for PusTcSecondaryHeader { } #[inline] - fn service(&self) -> u8 { - self.service - } - - #[inline] - fn subservice(&self) -> u8 { - self.subservice + fn message_type_id(&self) -> MessageTypeId { + self.message_type_id } #[inline] @@ -209,8 +225,7 @@ impl TryFrom for PusTcSecondaryHeader { fn try_from(value: zc::PusTcSecondaryHeader) -> Result { Ok(PusTcSecondaryHeader { - service: value.service(), - subservice: value.subservice(), + message_type_id: value.message_type_id(), source_id: value.source_id(), ack_flags: value.ack_flags(), version: PUS_VERSION, @@ -222,10 +237,9 @@ impl PusTcSecondaryHeader { pub const HEADER_LEN: usize = PUC_TC_SECONDARY_HEADER_LEN; #[inline] - pub fn new_simple(service: u8, subservice: u8) -> Self { + pub fn new_simple(message_type_id: MessageTypeId) -> Self { PusTcSecondaryHeader { - service, - subservice, + message_type_id, ack_flags: ACK_ALL, source_id: 0, version: PusVersion::PusC, @@ -233,10 +247,9 @@ impl PusTcSecondaryHeader { } #[inline] - pub fn new(service: u8, subservice: u8, ack_flags: AckFlags, source_id: u16) -> Self { + pub fn new(message_type_id: MessageTypeId, ack_flags: AckFlags, source_id: u16) -> Self { PusTcSecondaryHeader { - service, - subservice, + message_type_id, ack_flags, source_id, version: PusVersion::PusC, @@ -299,14 +312,13 @@ impl<'app_data> PusTcCreator<'app_data> { #[inline] pub fn new_simple( sph: SpHeader, - service: u8, - subservice: u8, + message_type_id: MessageTypeId, app_data: &'app_data [u8], packet_config: CreatorConfig, ) -> Self { Self::new( sph, - PusTcSecondaryHeader::new(service, subservice, ACK_ALL, 0), + PusTcSecondaryHeader::new(message_type_id, ACK_ALL, 0), app_data, packet_config, ) @@ -336,13 +348,13 @@ impl<'app_data> PusTcCreator<'app_data> { } #[inline] - pub fn service(&self) -> u8 { - self.sec_header.service + pub fn service_type_id(&self) -> u8 { + self.sec_header.service_type_id() } #[inline] - pub fn subservice(&self) -> u8 { - self.sec_header.subservice + pub fn message_subtype_id(&self) -> u8 { + self.sec_header.message_subtype_id() } #[inline] @@ -513,9 +525,11 @@ impl PusPacket for PusTcCreator<'_> { #[inline] fn pus_version(&self) -> Result; #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + #[inline] + fn message_subtype_id(&self) -> u8; }); #[inline] @@ -541,9 +555,11 @@ impl GenericPusTcSecondaryHeader for PusTcCreator<'_> { #[inline] fn pus_version(&self) -> Result; #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + #[inline] + fn message_subtype_id(&self) -> u8; #[inline] fn source_id(&self) -> u16; #[inline] @@ -734,7 +750,7 @@ impl PusTcBuilder<'_> { PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0)), 0, ), - sec_header: PusTcSecondaryHeader::new(0, 0, ACK_ALL, 0), + sec_header: PusTcSecondaryHeader::new(MessageTypeId::new(0, 0), ACK_ALL, 0), app_data: &[], has_checksum: true, } @@ -760,14 +776,20 @@ impl PusTcBuilder<'_> { } #[inline] - pub fn with_service(mut self, service: u8) -> Self { - self.sec_header.service = service; + pub fn with_message_type_id(mut self, message_type: MessageTypeId) -> Self { + self.sec_header.message_type_id = message_type; self } #[inline] - pub fn with_subservice(mut self, service: u8) -> Self { - self.sec_header.subservice = service; + pub fn with_service_type_id(mut self, service: u8) -> Self { + self.sec_header.message_type_id.type_id = service; + self + } + + #[inline] + pub fn with_message_subtype_id(mut self, subtype_id: u8) -> Self { + self.sec_header.message_type_id.subtype_id = subtype_id; self } @@ -974,9 +996,11 @@ impl PusPacket for PusTcReader<'_> { #[inline] fn pus_version(&self) -> Result; #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + #[inline] + fn message_subtype_id(&self) -> u8; }); fn has_checksum(&self) -> bool { @@ -999,9 +1023,11 @@ impl GenericPusTcSecondaryHeader for PusTcReader<'_> { #[inline] fn pus_version(&self) -> Result; #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + #[inline] + fn message_subtype_id(&self) -> u8; #[inline] fn source_id(&self) -> u16; #[inline] @@ -1042,13 +1068,13 @@ mod tests { fn base_ping_tc_full_ctor() -> PusTcCreator<'static> { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); - let tc_header = PusTcSecondaryHeader::new_simple(17, 1); + let tc_header = PusTcSecondaryHeader::new_simple(MessageTypeId::new(17, 1)); PusTcCreator::new_no_app_data(sph, tc_header, CreatorConfig::default()) } fn base_ping_tc_full_ctor_no_checksum() -> PusTcCreator<'static> { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); - let tc_header = PusTcSecondaryHeader::new_simple(17, 1); + let tc_header = PusTcSecondaryHeader::new_simple(MessageTypeId::new(17, 1)); PusTcCreator::new_no_app_data( sph, tc_header, @@ -1061,21 +1087,26 @@ mod tests { fn base_ping_tc_simple_ctor() -> PusTcCreator<'static> { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); - PusTcCreator::new_simple(sph, 17, 1, &[], CreatorConfig::default()) + PusTcCreator::new_simple( + sph, + MessageTypeId::new(17, 1), + &[], + CreatorConfig::default(), + ) } fn base_ping_tc_with_builder(alt_api: bool) -> PusTcCreator<'static> { if alt_api { return PusTcCreator::builder() - .with_service(17) - .with_subservice(1) + .with_service_type_id(17) + .with_message_subtype_id(1) .with_apid(u11::new(0x02)) .with_sequence_count(u14::new(0x34)) .build(); } PusTcBuilder::new() - .with_service(17) - .with_subservice(1) + .with_service_type_id(17) + .with_message_subtype_id(1) .with_apid(u11::new(0x02)) .with_sequence_count(u14::new(0x34)) .build() @@ -1085,8 +1116,7 @@ mod tests { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); PusTcCreator::new_simple( sph, - 17, - 1, + MessageTypeId::new(17, 1), &[], CreatorConfig { set_ccsds_len: true, @@ -1102,8 +1132,7 @@ mod tests { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); PusTcCreator::new_simple( sph, - 17, - 1, + MessageTypeId::new(17, 1), app_data, CreatorConfig { set_ccsds_len: true, @@ -1234,7 +1263,7 @@ mod tests { #[test] fn test_deserialization_alt_ctor() { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); - let tc_header = PusTcSecondaryHeader::new_simple(17, 1); + let tc_header = PusTcSecondaryHeader::new_simple(MessageTypeId::new(17, 1)); let mut test_buf: [u8; 32] = [0; 32]; let mut pus_tc = PusTcCreatorWithReservedAppData::new(&mut test_buf, sph, tc_header, 0, true).unwrap(); @@ -1289,8 +1318,7 @@ mod tests { let sph = SpHeader::new_for_unseg_tc(u11::new(0x02), u14::new(0x34), 0); let mut tc = PusTcCreator::new_simple( sph, - 17, - 1, + MessageTypeId::new(17, 1), &[], CreatorConfig { set_ccsds_len: false, @@ -1517,10 +1545,10 @@ mod tests { } fn verify_test_tc_generic(tc: &(impl PusPacket + GenericPusTcSecondaryHeader)) { - assert_eq!(PusPacket::service(tc), 17); - assert_eq!(GenericPusTcSecondaryHeader::service(tc), 17); - assert_eq!(PusPacket::subservice(tc), 1); - assert_eq!(GenericPusTcSecondaryHeader::subservice(tc), 1); + assert_eq!(PusPacket::service_type_id(tc), 17); + assert_eq!(GenericPusTcSecondaryHeader::service_type_id(tc), 17); + assert_eq!(PusPacket::message_subtype_id(tc), 1); + assert_eq!(GenericPusTcSecondaryHeader::message_subtype_id(tc), 1); assert!(tc.sec_header_flag()); assert_eq!(PusPacket::pus_version(tc).unwrap(), PusC); assert_eq!(tc.seq_count().value(), 0x34); @@ -1650,8 +1678,8 @@ mod tests { SequenceFlags::Unsegmented, u14::new(0x34), )) - .with_service(17) - .with_subservice(1) + .with_service_type_id(17) + .with_message_subtype_id(1) .with_ack_flags(AckFlags::new_with_raw_value(u4::new(0b1010))) .with_source_id(0x2f2f) .with_checksum(false) @@ -1660,7 +1688,7 @@ mod tests { assert_eq!(tc.sequence_flags(), SequenceFlags::Unsegmented); assert_eq!(tc.apid().value(), 0x02); assert_eq!(tc.packet_type(), PacketType::Tc); - assert_eq!(tc.service(), 17); - assert_eq!(tc.subservice(), 1); + assert_eq!(tc.service_type_id(), 17); + assert_eq!(tc.message_subtype_id(), 1); } } diff --git a/src/ecss/tc_pus_a.rs b/src/ecss/tc_pus_a.rs index bf6f6fc..c1f5a8b 100644 --- a/src/ecss/tc_pus_a.rs +++ b/src/ecss/tc_pus_a.rs @@ -15,8 +15,8 @@ //! true //! ); //! println!("{:?}", pus_tc); -//! assert_eq!(pus_tc.service(), 17); -//! assert_eq!(pus_tc.subservice(), 1); +//! assert_eq!(pus_tc.service_type_id(), 17); +//! assert_eq!(pus_tc.message_subtype_id(), 1); //! assert_eq!(pus_tc.apid().value(), 0x02); //! //! // Serialize TC into a raw buffer @@ -29,15 +29,15 @@ //! //! // Deserialize from the raw byte representation. No source ID, 0 spare bytes. //! let pus_tc_deserialized = PusTcReader::new(&test_buf, None, 0).expect("Deserialization failed"); -//! assert_eq!(pus_tc.service(), 17); -//! assert_eq!(pus_tc.subservice(), 1); +//! assert_eq!(pus_tc.service_type_id(), 17); +//! assert_eq!(pus_tc.message_subtype_id(), 1); //! assert_eq!(pus_tc.apid().value(), 0x02); //! ``` use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE}; use crate::ecss::tc::{AckFlags, ACK_ALL}; use crate::ecss::{ crc_from_raw_data, sp_header_impls, user_data_from_raw, - verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion, + verify_crc16_ccitt_false_from_raw_to_pus_error, MessageTypeId, PusError, PusPacket, PusVersion, WritablePusPacket, }; use crate::util::{UnsignedByteField, UnsignedEnum}; @@ -499,11 +499,23 @@ impl PusPacket for PusTcCreator<'_> { delegate!(to self.sec_header { #[inline] fn pus_version(&self) -> Result; - #[inline] - fn service(&self) -> u8; - #[inline] - fn subservice(&self) -> u8; }); + #[inline] + fn message_type_id(&self) -> MessageTypeId { + MessageTypeId { + type_id: self.service_type_id(), + subtype_id: self.message_subtype_id(), + } + } + #[inline] + fn service_type_id(&self) -> u8 { + self.sec_header.service + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.sec_header.subservice + } #[inline] fn user_data(&self) -> &[u8] { @@ -793,14 +805,28 @@ impl CcsdsPacket for PusTcReader<'_> { impl PusPacket for PusTcReader<'_> { delegate!(to self.sec_header { - #[inline] - fn service(&self) -> u8; - #[inline] - fn subservice(&self) -> u8; #[inline] fn pus_version(&self) -> Result; }); + #[inline] + fn message_type_id(&self) -> MessageTypeId { + MessageTypeId { + type_id: self.service_type_id(), + subtype_id: self.message_subtype_id(), + } + } + + #[inline] + fn service_type_id(&self) -> u8 { + self.sec_header.service + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.sec_header.subservice + } + #[inline] fn has_checksum(&self) -> bool { true @@ -1229,9 +1255,9 @@ mod tests { } fn verify_test_tc_generic(tc: &(impl PusPacket + GenericPusTcSecondaryHeader)) { - assert_eq!(PusPacket::service(tc), 17); + assert_eq!(PusPacket::service_type_id(tc), 17); assert_eq!(GenericPusTcSecondaryHeader::service(tc), 17); - assert_eq!(PusPacket::subservice(tc), 1); + assert_eq!(PusPacket::message_subtype_id(tc), 1); assert_eq!(GenericPusTcSecondaryHeader::subservice(tc), 1); assert!(tc.sec_header_flag()); assert_eq!(PusPacket::pus_version(tc).unwrap(), PusVersion::PusA); diff --git a/src/ecss/tm.rs b/src/ecss/tm.rs index e887ad5..78dff85 100644 --- a/src/ecss/tm.rs +++ b/src/ecss/tm.rs @@ -6,7 +6,7 @@ //! ```rust //! use spacepackets::time::cds::CdsTime; //! use spacepackets::SpHeader; -//! use spacepackets::ecss::tm::{PusTmCreator, PusTmReader, PusTmSecondaryHeader, CreatorConfig}; +//! use spacepackets::ecss::tm::{MessageTypeId, PusTmCreator, PusTmReader, PusTmSecondaryHeader, CreatorConfig}; //! use arbitrary_int::u11; //! //! let mut time_buf: [u8; 7] = [0; 7]; @@ -17,12 +17,12 @@ //! // Create a ping telemetry with no user source data //! let ping_tm = PusTmCreator::new_no_source_data( //! SpHeader::new_from_apid(u11::new(0x02)), -//! PusTmSecondaryHeader::new_simple(17, 2, &time_buf), +//! PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), &time_buf), //! CreatorConfig::default() //! ); //! println!("{:?}", ping_tm); -//! assert_eq!(ping_tm.service(), 17); -//! assert_eq!(ping_tm.subservice(), 2); +//! assert_eq!(ping_tm.service_type_id(), 17); +//! assert_eq!(ping_tm.message_subtype_id(), 2); //! assert_eq!(ping_tm.apid().value(), 0x02); //! //! // Serialize TM into a raw buffer @@ -36,27 +36,27 @@ //! // Deserialize from the raw byte representation //! let ping_tm_reader = PusTmReader::new(&test_buf, 7).expect("Deserialization failed"); //! assert_eq!(written_size, ping_tm_reader.packet_len()); -//! assert_eq!(ping_tm_reader.service(), 17); -//! assert_eq!(ping_tm_reader.subservice(), 2); +//! assert_eq!(ping_tm_reader.service_type_id(), 17); +//! assert_eq!(ping_tm_reader.message_subtype_id(), 2); //! assert_eq!(ping_tm_reader.apid().value(), 0x02); //! assert_eq!(ping_tm_reader.timestamp(), &time_buf); //! //! // Alternative builder API //! let pus_tm_by_builder = PusTmCreator::builder() -//! .with_service(17) -//! .with_subservice(2) +//! .with_service_type_id(17) +//! .with_message_subtype_id(2) //! .with_apid(u11::new(0x02)) //! .with_timestamp(&time_buf) //! .build(); //! assert_eq!(pus_tm_by_builder, ping_tm); //! ``` use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE}; -pub use crate::ecss::CreatorConfig; use crate::ecss::{ calc_pus_crc16, crc_from_raw_data, sp_header_impls, user_data_from_raw, verify_crc16_ccitt_false_from_raw_to_pus_error, PusError, PusPacket, PusVersion, WritablePusPacket, }; +pub use crate::ecss::{CreatorConfig, MessageTypeId}; use crate::{ ByteConversionError, CcsdsPacket, PacketId, PacketSequenceControl, PacketType, SequenceFlags, SpHeader, CCSDS_HEADER_LEN, MAX_APID, @@ -85,17 +85,34 @@ pub const PUS_TM_MIN_SEC_HEADER_LEN: usize = 7; pub const PUS_TM_MIN_LEN_WITHOUT_SOURCE_DATA: usize = CCSDS_HEADER_LEN + PUS_TM_MIN_SEC_HEADER_LEN; pub trait GenericPusTmSecondaryHeader { + /// PUS version. fn pus_version(&self) -> Result; + /// Spacecraft time reference status. fn sc_time_ref_status(&self) -> u4; - fn service(&self) -> u8; - fn subservice(&self) -> u8; - fn msg_counter(&self) -> u16; + /// Message type ID. + fn message_type_id(&self) -> MessageTypeId; + /// Message counter for the message type. + fn msg_type_counter(&self) -> u16; + + /// Destination ID. fn dest_id(&self) -> u16; + + /// Service type ID. + #[inline] + fn service_type_id(&self) -> u8 { + self.message_type_id().type_id + } + + /// Message subtype ID. + #[inline] + fn message_subtype_id(&self) -> u8 { + self.message_type_id().subtype_id + } } pub mod zc { use super::GenericPusTmSecondaryHeader; - use crate::ecss::{PusError, PusVersion}; + use crate::ecss::{MessageTypeId, PusError, PusVersion}; use arbitrary_int::{traits::Integer as _, u4}; use zerocopy::{FromBytes, Immutable, IntoBytes, NetworkEndian, Unaligned, U16}; @@ -103,8 +120,8 @@ pub mod zc { #[repr(C)] pub struct PusTmSecHeaderWithoutTimestamp { pus_version_and_sc_time_ref_status: u8, - service: u8, - subservice: u8, + service_type_id: u8, + message_subtype_id: u8, msg_counter: U16, dest_id: U16, } @@ -125,8 +142,8 @@ pub mod zc { Ok(PusTmSecHeaderWithoutTimestamp { pus_version_and_sc_time_ref_status: ((header.pus_version as u8) << 4) | header.sc_time_ref_status.as_u8(), - service: header.service, - subservice: header.subservice, + service_type_id: header.service_type_id(), + message_subtype_id: header.message_subtype_id(), msg_counter: U16::from(header.msg_counter), dest_id: U16::from(header.dest_id), }) @@ -146,18 +163,27 @@ pub mod zc { u4::new(self.pus_version_and_sc_time_ref_status & 0b1111) } + /// Message type ID. #[inline] - fn service(&self) -> u8 { - self.service + fn message_type_id(&self) -> MessageTypeId { + MessageTypeId { + type_id: self.service_type_id, + subtype_id: self.message_subtype_id, + } } #[inline] - fn subservice(&self) -> u8 { - self.subservice + fn service_type_id(&self) -> u8 { + self.service_type_id } #[inline] - fn msg_counter(&self) -> u16 { + fn message_subtype_id(&self) -> u8 { + self.message_subtype_id + } + + #[inline] + fn msg_type_counter(&self) -> u16 { self.msg_counter.get() } @@ -174,8 +200,7 @@ pub mod zc { pub struct PusTmSecondaryHeader<'stamp> { pus_version: PusVersion, pub sc_time_ref_status: u4, - pub service: u8, - pub subservice: u8, + pub message_type_id: MessageTypeId, pub msg_counter: u16, pub dest_id: u16, pub timestamp: &'stamp [u8], @@ -183,20 +208,19 @@ pub struct PusTmSecondaryHeader<'stamp> { impl<'stamp> PusTmSecondaryHeader<'stamp> { #[inline] - pub fn new_simple(service: u8, subservice: u8, timestamp: &'stamp [u8]) -> Self { - Self::new(service, subservice, 0, 0, timestamp) + pub fn new_simple(message_type_id: MessageTypeId, timestamp: &'stamp [u8]) -> Self { + Self::new(message_type_id, 0, 0, timestamp) } /// Like [Self::new_simple] but without a timestamp. #[inline] - pub fn new_simple_no_timestamp(service: u8, subservice: u8) -> Self { - Self::new(service, subservice, 0, 0, &[]) + pub fn new_simple_no_timestamp(message_type_id: MessageTypeId) -> Self { + Self::new(message_type_id, 0, 0, &[]) } #[inline] pub fn new( - service: u8, - subservice: u8, + message_type_id: MessageTypeId, msg_counter: u16, dest_id: u16, timestamp: &'stamp [u8], @@ -204,8 +228,7 @@ impl<'stamp> PusTmSecondaryHeader<'stamp> { PusTmSecondaryHeader { pus_version: PusVersion::PusC, sc_time_ref_status: u4::new(0), - service, - subservice, + message_type_id, msg_counter, dest_id, timestamp, @@ -225,17 +248,12 @@ impl GenericPusTmSecondaryHeader for PusTmSecondaryHeader<'_> { } #[inline] - fn service(&self) -> u8 { - self.service + fn message_type_id(&self) -> MessageTypeId { + self.message_type_id } #[inline] - fn subservice(&self) -> u8 { - self.subservice - } - - #[inline] - fn msg_counter(&self) -> u16 { + fn msg_type_counter(&self) -> u16 { self.msg_counter } @@ -257,9 +275,8 @@ impl<'slice> TryFrom> for PusTmSecondaryHeader<'slice Ok(PusTmSecondaryHeader { pus_version: version.unwrap(), sc_time_ref_status: sec_header.zc_header.sc_time_ref_status(), - service: sec_header.zc_header.service(), - subservice: sec_header.zc_header.subservice(), - msg_counter: sec_header.zc_header.msg_counter(), + message_type_id: sec_header.zc_header.message_type_id(), + msg_counter: sec_header.zc_header.msg_type_counter(), dest_id: sec_header.zc_header.dest_id(), timestamp: sec_header.timestamp, }) @@ -329,8 +346,7 @@ impl<'time, 'src_data> PusTmCreator<'time, 'src_data> { #[inline] pub fn new_simple( sp_header: SpHeader, - service: u8, - subservice: u8, + message_type_id: MessageTypeId, time_provider: &impl TimeWriter, stamp_buf: &'time mut [u8], source_data: &'src_data [u8], @@ -338,7 +354,7 @@ impl<'time, 'src_data> PusTmCreator<'time, 'src_data> { ) -> Result { let stamp_size = time_provider.write_to_bytes(stamp_buf)?; let sec_header = - PusTmSecondaryHeader::new_simple(service, subservice, &stamp_buf[0..stamp_size]); + PusTmSecondaryHeader::new_simple(message_type_id, &stamp_buf[0..stamp_size]); Ok(Self::new(sp_header, sec_header, source_data, packet_config)) } @@ -371,13 +387,13 @@ impl<'time, 'src_data> PusTmCreator<'time, 'src_data> { } #[inline] - pub fn service(&self) -> u8 { - self.sec_header.service + pub fn service_type_id(&self) -> u8 { + self.sec_header.service_type_id() } #[inline] - pub fn subservice(&self) -> u8 { - self.sec_header.subservice + pub fn message_subtype_id(&self) -> u8 { + self.sec_header.message_subtype_id() } #[inline] @@ -567,9 +583,7 @@ impl PusPacket for PusTmCreator<'_, '_> { delegate!(to self.sec_header { #[inline] - fn service(&self) -> u8; - #[inline] - fn subservice(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; }); #[inline] @@ -590,14 +604,21 @@ impl GenericPusTmSecondaryHeader for PusTmCreator<'_, '_> { delegate!(to self.sec_header { #[inline] fn pus_version(&self) -> Result; + /// Message type ID. + fn message_type_id(&self) -> MessageTypeId; + + /// Service type ID. #[inline] - fn service(&self) -> u8; + fn service_type_id(&self) -> u8; + + /// Message subtype ID. #[inline] - fn subservice(&self) -> u8; + fn message_subtype_id(&self) -> u8; + #[inline] fn dest_id(&self) -> u16; #[inline] - fn msg_counter(&self) -> u16; + fn msg_type_counter(&self) -> u16; #[inline] fn sc_time_ref_status(&self) -> u4; }); @@ -627,7 +648,15 @@ impl PusTmBuilder<'_, '_> { PacketSequenceControl::new(SequenceFlags::Unsegmented, u14::new(0)), 0, ), - sec_header: PusTmSecondaryHeader::new(0, 0, 0, 0, &[]), + sec_header: PusTmSecondaryHeader::new( + MessageTypeId { + type_id: 0, + subtype_id: 0, + }, + 0, + 0, + &[], + ), source_data: &[], has_checksum: true, } @@ -659,14 +688,20 @@ impl PusTmBuilder<'_, '_> { } #[inline] - pub fn with_service(mut self, service: u8) -> Self { - self.sec_header.service = service; + pub fn with_message_type_id(mut self, message_type_id: MessageTypeId) -> Self { + self.sec_header.message_type_id = message_type_id; self } #[inline] - pub fn with_subservice(mut self, service: u8) -> Self { - self.sec_header.subservice = service; + pub fn with_service_type_id(mut self, type_id: u8) -> Self { + self.sec_header.message_type_id.type_id = type_id; + self + } + + #[inline] + pub fn with_message_subtype_id(mut self, subtype_id: u8) -> Self { + self.sec_header.message_type_id.subtype_id = subtype_id; self } @@ -1040,13 +1075,13 @@ impl<'raw_data> PusTmReader<'raw_data> { } #[inline] - pub fn service(&self) -> u8 { - self.sec_header.service + pub fn service_type_id(&self) -> u8 { + self.sec_header.service_type_id() } #[inline] - pub fn subservice(&self) -> u8 { - self.sec_header.subservice + pub fn message_subtype_id(&self) -> u8 { + self.sec_header.message_subtype_id() } #[inline] @@ -1102,10 +1137,15 @@ impl PusPacket for PusTmReader<'_> { delegate!(to self.sec_header { #[inline] fn pus_version(&self) -> Result; + #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; + #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + + #[inline] + fn message_subtype_id(&self) -> u8; }); #[inline] @@ -1129,13 +1169,15 @@ impl GenericPusTmSecondaryHeader for PusTmReader<'_> { #[inline] fn pus_version(&self) -> Result; #[inline] - fn service(&self) -> u8; + fn message_type_id(&self) -> MessageTypeId; #[inline] - fn subservice(&self) -> u8; + fn service_type_id(&self) -> u8; + #[inline] + fn message_subtype_id(&self) -> u8; #[inline] fn dest_id(&self) -> u16; #[inline] - fn msg_counter(&self) -> u16; + fn msg_type_counter(&self) -> u16; #[inline] fn sc_time_ref_status(&self) -> u4; }); @@ -1257,6 +1299,24 @@ impl<'raw> PusTmZeroCopyWriter<'raw> { self.raw_tm[slice_len - 2..].copy_from_slice(&crc16.to_be_bytes()); } } + + #[inline] + fn service_type_id(&self) -> u8 { + self.raw_tm[7] + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.raw_tm[8] + } + + #[inline] + fn message_type_id(&self) -> MessageTypeId { + MessageTypeId { + type_id: self.service_type_id(), + subtype_id: self.message_subtype_id(), + } + } } impl CcsdsPacket for PusTmZeroCopyWriter<'_> { @@ -1287,19 +1347,24 @@ impl PusPacket for PusTmZeroCopyWriter<'_> { self.sec_header_without_timestamp().pus_version() } - #[inline] - fn service(&self) -> u8 { - self.raw_tm[7] - } - #[inline] fn has_checksum(&self) -> bool { self.has_checksum } #[inline] - fn subservice(&self) -> u8 { - self.raw_tm[8] + fn service_type_id(&self) -> u8 { + self.service_type_id() + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.message_subtype_id() + } + + #[inline] + fn message_type_id(&self) -> MessageTypeId { + self.message_type_id() } #[inline] @@ -1334,20 +1399,25 @@ impl GenericPusTmSecondaryHeader for PusTmZeroCopyWriter<'_> { #[inline] fn sc_time_ref_status(&self) -> u4; #[inline] - fn msg_counter(&self) -> u16; + fn msg_type_counter(&self) -> u16; #[inline] fn dest_id(&self) -> u16; } } #[inline] - fn service(&self) -> u8 { - PusPacket::service(self) + fn service_type_id(&self) -> u8 { + self.service_type_id() } #[inline] - fn subservice(&self) -> u8 { - PusPacket::subservice(self) + fn message_subtype_id(&self) -> u8 { + self.message_subtype_id() + } + + #[inline] + fn message_type_id(&self) -> MessageTypeId { + self.message_type_id() } } @@ -1367,7 +1437,7 @@ mod tests { fn base_ping_reply_full_ctor<'a, 'b>(timestamp: &'a [u8]) -> PusTmCreator<'a, 'b> { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); PusTmCreator::new_no_source_data(sph, tm_header, CreatorConfig::default()) } @@ -1379,23 +1449,23 @@ mod tests { return PusTmCreator::builder() .with_apid(u11::new(0x123)) .with_sequence_count(u14::new(0x234)) - .with_service(17) - .with_subservice(2) + .with_service_type_id(17) + .with_message_subtype_id(2) .with_timestamp(timestamp) .build(); } PusTmBuilder::new() .with_apid(u11::new(0x123)) .with_sequence_count(u14::new(0x234)) - .with_service(17) - .with_subservice(2) + .with_service_type_id(17) + .with_message_subtype_id(2) .with_timestamp(timestamp) .build() } fn base_ping_reply_full_ctor_no_checksum<'a, 'b>(timestamp: &'a [u8]) -> PusTmCreator<'a, 'b> { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); PusTmCreator::new_no_source_data( sph, tm_header, @@ -1407,13 +1477,13 @@ mod tests { } fn ping_reply_with_data<'a, 'b>(timestamp: &'a [u8]) -> PusTmCreator<'a, 'b> { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); PusTmCreator::new(sph, tm_header, DUMMY_DATA, CreatorConfig::default()) } fn base_hk_reply<'a, 'b>(timestamp: &'a [u8], src_data: &'b [u8]) -> PusTmCreator<'a, 'b> { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tc_header = PusTmSecondaryHeader::new_simple(3, 5, timestamp); + let tc_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(3, 5), timestamp); PusTmCreator::new(sph, tc_header, src_data, CreatorConfig::default()) } @@ -1422,7 +1492,7 @@ mod tests { src_data: &'b [u8], ) -> PusTmCreator<'a, 'b> { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tc_header = PusTmSecondaryHeader::new_simple(3, 5, timestamp); + let tc_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(3, 5), timestamp); PusTmCreator::new( sph, tc_header, @@ -1459,8 +1529,7 @@ mod tests { let mut stamp_buf: [u8; 8] = [0; 8]; let pus_tm = PusTmCreator::new_simple( sph, - 17, - 2, + MessageTypeId::new(17, 2), &time_provider, &mut stamp_buf, &[], @@ -1486,7 +1555,7 @@ mod tests { fn test_serialization_no_source_data_alt_ctor() { let timestamp = dummy_timestamp(); let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); let mut buf: [u8; 32] = [0; 32]; let mut pus_tm = PusTmCreatorWithReservedSourceData::new(&mut buf, sph, tm_header, 0, true).unwrap(); @@ -1502,7 +1571,7 @@ mod tests { fn test_serialization_no_source_data_alt_ctor_no_checksum_verification() { let timestamp = dummy_timestamp(); let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); let mut buf: [u8; 32] = [0; 32]; let mut pus_tm = PusTmCreatorWithReservedSourceData::new(&mut buf, sph, tm_header, 0, true).unwrap(); @@ -1520,7 +1589,7 @@ mod tests { fn test_serialization_no_source_data_alt_ctor_no_checksum() { let timestamp = dummy_timestamp(); let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tm_header = PusTmSecondaryHeader::new_simple(17, 2, timestamp); + let tm_header = PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), timestamp); let mut buf: [u8; 32] = [0; 32]; let mut pus_tm = PusTmCreatorWithReservedSourceData::new(&mut buf, sph, tm_header, 0, false).unwrap(); @@ -1596,7 +1665,8 @@ mod tests { let src_data = &[1, 2, 3]; let mut buf: [u8; 32] = [0; 32]; let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tc_header = PusTmSecondaryHeader::new_simple(3, 5, dummy_timestamp()); + let tc_header = + PusTmSecondaryHeader::new_simple(MessageTypeId::new(3, 5), dummy_timestamp()); let mut hk_reply_unwritten = PusTmCreatorWithReservedSourceData::new(&mut buf, sph, tc_header, 3, true).unwrap(); assert_eq!(hk_reply_unwritten.source_data_len(), 3); @@ -1616,7 +1686,8 @@ mod tests { let src_data = &[1, 2, 3]; let mut buf: [u8; 32] = [0; 32]; let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tc_header = PusTmSecondaryHeader::new_simple(3, 5, dummy_timestamp()); + let tc_header = + PusTmSecondaryHeader::new_simple(MessageTypeId::new(3, 5), dummy_timestamp()); let mut hk_reply_unwritten = PusTmCreatorWithReservedSourceData::new(&mut buf, sph, tc_header, 3, true).unwrap(); assert_eq!(hk_reply_unwritten.source_data_len(), 3); @@ -1640,7 +1711,7 @@ mod tests { pus_tm.set_msg_counter(0x1f1f); assert_eq!(pus_tm.sc_time_ref_status().value(), 0b1010); assert_eq!(pus_tm.dest_id(), 0x7fff); - assert_eq!(pus_tm.msg_counter(), 0x1f1f); + assert_eq!(pus_tm.msg_type_counter(), 0x1f1f); pus_tm.set_apid(u11::new(0x7ff)); assert_eq!(pus_tm.apid().value(), 0x7ff); } @@ -1772,7 +1843,8 @@ mod tests { #[test] fn test_manual_field_update() { let sph = SpHeader::new_for_unseg_tm(u11::new(0x123), u14::new(0x234), 0); - let tc_header = PusTmSecondaryHeader::new_simple(17, 2, dummy_timestamp()); + let tc_header = + PusTmSecondaryHeader::new_simple(MessageTypeId::new(17, 2), dummy_timestamp()); let mut tm = PusTmCreator::new_no_source_data( sph, tc_header, @@ -1928,10 +2000,10 @@ mod tests { exp_full_len: usize, ) { assert!(tm.is_tm()); - assert_eq!(PusPacket::service(tm), 17); - assert_eq!(GenericPusTmSecondaryHeader::service(tm), 17); - assert_eq!(PusPacket::subservice(tm), 2); - assert_eq!(GenericPusTmSecondaryHeader::subservice(tm), 2); + assert_eq!(PusPacket::service_type_id(tm), 17); + assert_eq!(GenericPusTmSecondaryHeader::service_type_id(tm), 17); + assert_eq!(PusPacket::message_subtype_id(tm), 2); + assert_eq!(GenericPusTmSecondaryHeader::message_subtype_id(tm), 2); assert!(tm.sec_header_flag()); if has_user_data { assert!(!tm.user_data().is_empty()); @@ -1946,7 +2018,7 @@ mod tests { ); assert_eq!(tm.data_len(), exp_full_len as u16 - 7); assert_eq!(tm.dest_id(), 0x0000); - assert_eq!(tm.msg_counter(), 0x0000); + assert_eq!(tm.msg_type_counter(), 0x0000); assert_eq!(tm.sc_time_ref_status().value(), 0b0000); } @@ -1984,7 +2056,7 @@ mod tests { // This performs all necessary checks, including the CRC check. let tm_read_back = PusTmReader::new(&buf, 7).expect("Re-creating PUS TM failed"); assert_eq!(tm_read_back.packet_len(), tm_size); - assert_eq!(tm_read_back.msg_counter(), 100); + assert_eq!(tm_read_back.msg_type_counter(), 100); assert_eq!(tm_read_back.dest_id(), 55); assert_eq!(tm_read_back.seq_count(), MAX_SEQ_COUNT); assert_eq!(tm_read_back.apid(), MAX_APID); @@ -2003,8 +2075,8 @@ mod tests { writer.set_msg_count(100); writer.set_seq_count(MAX_SEQ_COUNT); writer.set_apid(MAX_APID); - assert_eq!(PusPacket::service(&writer), 17); - assert_eq!(PusPacket::subservice(&writer), 2); + assert_eq!(PusPacket::service_type_id(&writer), 17); + assert_eq!(PusPacket::message_subtype_id(&writer), 2); assert_eq!(writer.apid(), MAX_APID); assert_eq!(writer.seq_count(), MAX_SEQ_COUNT); } @@ -2023,12 +2095,15 @@ mod tests { writer.set_msg_count(100); writer.set_seq_count(MAX_SEQ_COUNT); writer.set_apid(MAX_APID); - assert_eq!(PusPacket::service(&writer), 17); - assert_eq!(PusPacket::subservice(&writer), 2); + assert_eq!(PusPacket::service_type_id(&writer), 17); + assert_eq!(PusPacket::message_subtype_id(&writer), 2); assert_eq!(writer.dest_id(), 55); - assert_eq!(writer.msg_counter(), 100); + assert_eq!(writer.msg_type_counter(), 100); assert_eq!(writer.sec_header_without_timestamp().dest_id(), 55); - assert_eq!(writer.sec_header_without_timestamp().msg_counter(), 100); + assert_eq!( + writer.sec_header_without_timestamp().msg_type_counter(), + 100 + ); assert_eq!(writer.user_data(), DUMMY_DATA); // Need to check crc16 before finish, because finish will update the CRC. let crc16 = writer.checksum(); @@ -2039,7 +2114,7 @@ mod tests { #[test] fn test_sec_header_without_stamp() { - let sec_header = PusTmSecondaryHeader::new_simple_no_timestamp(17, 1); + let sec_header = PusTmSecondaryHeader::new_simple_no_timestamp(MessageTypeId::new(17, 1)); assert_eq!(sec_header.timestamp, &[]); } @@ -2105,8 +2180,7 @@ mod tests { let mut stamp_buf: [u8; 8] = [0; 8]; let pus_tm = PusTmCreator::new_simple( sph, - 17, - 2, + MessageTypeId::new(17, 2), &time_provider, &mut stamp_buf, &[], @@ -2127,8 +2201,7 @@ mod tests { let mut stamp_buf: [u8; 8] = [0; 8]; let pus_tm = PusTmCreator::new_simple( sph, - 17, - 2, + MessageTypeId::new(17, 2), &time_provider, &mut stamp_buf, &[], @@ -2166,8 +2239,8 @@ mod tests { SequenceFlags::Unsegmented, u14::new(0x34), )) - .with_service(17) - .with_subservice(2) + .with_service_type_id(17) + .with_message_subtype_id(2) .with_dest_id(0x2f2f) .with_checksum(false) .build(); @@ -2175,7 +2248,7 @@ mod tests { assert_eq!(tm.sequence_flags(), SequenceFlags::Unsegmented); assert_eq!(tm.apid().value(), 0x02); assert_eq!(tm.packet_type(), PacketType::Tm); - assert_eq!(tm.service(), 17); - assert_eq!(tm.subservice(), 2); + assert_eq!(tm.service_type_id(), 17); + assert_eq!(tm.message_subtype_id(), 2); } } diff --git a/src/ecss/tm_pus_a.rs b/src/ecss/tm_pus_a.rs index 7f1367e..0e43de1 100644 --- a/src/ecss/tm_pus_a.rs +++ b/src/ecss/tm_pus_a.rs @@ -27,8 +27,8 @@ //! true //! ); //! println!("{:?}", ping_tm); -//! assert_eq!(ping_tm.service(), 17); -//! assert_eq!(ping_tm.subservice(), 2); +//! assert_eq!(ping_tm.service_type_id(), 17); +//! assert_eq!(ping_tm.message_subtype_id(), 2); //! assert_eq!(ping_tm.apid().value(), 0x02); //! //! // Serialize TM into a raw buffer @@ -42,16 +42,16 @@ //! // Deserialize from the raw byte representation //! let ping_tm_reader = PusTmReader::new(&test_buf, &SecondaryHeaderParameters::new_minimal(7)).expect("deserialization failed"); //! assert_eq!(written_size, ping_tm_reader.packet_len()); -//! assert_eq!(ping_tm_reader.service(), 17); -//! assert_eq!(ping_tm_reader.subservice(), 2); +//! assert_eq!(ping_tm_reader.service_type_id(), 17); +//! assert_eq!(ping_tm_reader.message_subtype_id(), 2); //! assert_eq!(ping_tm_reader.apid().value(), 0x02); //! assert_eq!(ping_tm_reader.timestamp(), &time_buf); //! ``` use crate::crc::{CRC_CCITT_FALSE, CRC_CCITT_FALSE_NO_TABLE}; use crate::ecss::{ calc_pus_crc16, crc_from_raw_data, sp_header_impls, user_data_from_raw, - verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, PusError, PusPacket, PusVersion, - WritablePusPacket, + verify_crc16_ccitt_false_from_raw_to_pus_error, CrcType, MessageTypeId, PusError, PusPacket, + PusVersion, WritablePusPacket, }; use crate::util::{UnsignedByteField, UnsignedEnum}; use crate::{ @@ -559,12 +559,22 @@ impl PusPacket for PusTmCreator<'_, '_> { Ok(self.sec_header.pus_version) } - delegate!(to self.sec_header { - #[inline] - fn service(&self) -> u8; - #[inline] - fn subservice(&self) -> u8; - }); + #[inline] + fn message_type_id(&self) -> super::MessageTypeId { + super::MessageTypeId { + type_id: self.sec_header.service, + subtype_id: self.sec_header.subservice, + } + } + + #[inline] + fn service_type_id(&self) -> u8 { + self.sec_header.service + } + #[inline] + fn message_subtype_id(&self) -> u8 { + self.sec_header.subservice + } #[inline] fn user_data(&self) -> &[u8] { @@ -867,12 +877,23 @@ impl PusPacket for PusTmReader<'_> { Ok(self.sec_header.pus_version) } - delegate!(to self.sec_header { - #[inline] - fn service(&self) -> u8; - #[inline] - fn subservice(&self) -> u8; - }); + #[inline] + fn message_type_id(&self) -> super::MessageTypeId { + MessageTypeId { + type_id: self.sec_header.service, + subtype_id: self.sec_header.subservice, + } + } + + #[inline] + fn service_type_id(&self) -> u8 { + self.sec_header.service + } + + #[inline] + fn message_subtype_id(&self) -> u8 { + self.sec_header.subservice + } #[inline] fn user_data(&self) -> &[u8] { @@ -1117,12 +1138,20 @@ impl PusPacket for PusTmZeroCopyWriter<'_> { } #[inline] - fn service(&self) -> u8 { + fn message_type_id(&self) -> super::MessageTypeId { + MessageTypeId { + type_id: self.service_type_id(), + subtype_id: self.message_subtype_id(), + } + } + + #[inline] + fn service_type_id(&self) -> u8 { self.raw_tm[7] } #[inline] - fn subservice(&self) -> u8 { + fn message_subtype_id(&self) -> u8 { self.raw_tm[8] } @@ -1774,9 +1803,9 @@ mod tests { msg_counter: Option, ) { assert!(tm.is_tm()); - assert_eq!(PusPacket::service(tm), 17); + assert_eq!(PusPacket::service_type_id(tm), 17); assert_eq!(GenericPusTmSecondaryHeader::service(tm), 17); - assert_eq!(PusPacket::subservice(tm), 2); + assert_eq!(PusPacket::message_subtype_id(tm), 2); assert_eq!(GenericPusTmSecondaryHeader::subservice(tm), 2); assert!(tm.sec_header_flag()); if has_user_data { @@ -1859,8 +1888,8 @@ mod tests { writer .set_destination_id(UnsignedByteFieldU16::new(0xf1f1).into()) .unwrap(); - assert_eq!(PusPacket::service(&writer), 17); - assert_eq!(PusPacket::subservice(&writer), 2); + assert_eq!(PusPacket::service_type_id(&writer), 17); + assert_eq!(PusPacket::message_subtype_id(&writer), 2); assert_eq!( writer.dest_id().unwrap().unwrap(), UnsignedByteFieldU16::new(0xf1f1).into() @@ -1881,8 +1910,8 @@ mod tests { .expect("Creating zero copy writer failed"); writer.set_seq_count(MAX_SEQ_COUNT); writer.set_apid(MAX_APID); - assert_eq!(PusPacket::service(&writer), 17); - assert_eq!(PusPacket::subservice(&writer), 2); + assert_eq!(PusPacket::service_type_id(&writer), 17); + assert_eq!(PusPacket::message_subtype_id(&writer), 2); assert!(writer.dest_id().unwrap().is_none()); assert!(writer.msg_counter().is_none()); if let Err(err) = writer.set_destination_id(UnsignedByteFieldU16::new(0xf1f1).into()) {