From 9cea8c9b08c3fb3e17c2527c0f78b57027e1e33f Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 15 Oct 2024 16:17:02 +0200 Subject: [PATCH] update CCSDS Spacepackets API and docs --- README.md | 3 +- spacepackets/ccsds/spacepacket.py | 99 +++++++++++++++++++++++++++---- 2 files changed, 88 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 849c881..7998c11 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,8 @@ coverage run -m pytest # Documentation -The documentation is built with Sphinx +The documentation is built with Sphinx and new documentation should be written using the +[NumPy format](https://www.sphinx-doc.org/en/master/usage/extensions/example_numpy.html#example-numpy). Install the required dependencies first: diff --git a/spacepackets/ccsds/spacepacket.py b/spacepackets/ccsds/spacepacket.py index 809d5d1..ccfcbe7 100644 --- a/spacepackets/ccsds/spacepacket.py +++ b/spacepackets/ccsds/spacepacket.py @@ -172,8 +172,7 @@ def pack(self) -> bytearray: class SpacePacketHeader(AbstractSpacePacket): - """This class encapsulates the space packet header. - Packet reference: Blue Book CCSDS 133.0-B-2""" + """This class encapsulates the space packet header. Packet reference: Blue Book CCSDS 133.0-B-2""" def __init__( self, @@ -187,6 +186,10 @@ def __init__( ): """Create a space packet header with the given field parameters. + The data length field can also be set from the total packet length by using the + :py:meth:`set_data_len_from_packet_len` method after construction of the space packet + header object. + >>> sph = SpacePacketHeader(packet_type=PacketType.TC, apid=0x42, seq_count=0, data_len=12) >>> hex(sph.apid) '0x42' @@ -201,17 +204,28 @@ def __init__( >>> sph.packet_seq_control PacketSeqCtrl(seq_flags=, seq_count=0) - :param packet_type: 0 for Telemetery, 1 for Telecommands - :param apid: Application Process ID, should not be larger - than 11 bits, deciaml 2074 or hex 0x7ff - :param seq_count: Source sequence counter, should not be larger than 0x3fff or - decimal 16383 - :param data_len: Contains a length count C that equals one fewer than the length of the - packet data field. Should not be larger than 65535 bytes - :param ccsds_version: - :param sec_header_flag: Secondary header flag, or False by default. - :param seq_flags: - :raises ValueError: On invalid parameters + Parameters + ----------- + packet_type: PacketType + 0 for Telemetery, 1 for Telecommands + apid: int + Application Process ID, should not be larger than 11 bits, deciaml 2074 or hex 0x7ff + seq_count: int + Source sequence counter, should not be larger than 0x3fff or decimal 16383 + data_len: int + Contains a length count C that equals one fewer than the length of the packet data + field. Should not be larger than 65535 bytes + sec_header_flag: bool + Secondary header flag, or False by default. + seq_flags: + Sequence flags, defaults to unsegmented. + ccsds_version: int + Version of the CCSDS packet. Defaults to 0b000 + + Raises + -------- + ValueError: + On invalid parameters """ if data_len > pow(2, 16) - 1 or data_len < 0: raise ValueError( @@ -225,6 +239,52 @@ def __init__( self._psc = PacketSeqCtrl(seq_flags=seq_flags, seq_count=seq_count) self.data_len = data_len + @classmethod + def tc( + cls, + apid: int, + seq_count: int, + data_len: int, + sec_header_flag: bool = False, + seq_flags: SequenceFlags = SequenceFlags.UNSEGMENTED, + ccsds_version: int = 0b000, + ): + """Create a space packet header with the given field parameters for a telecommand packet. + Calls the default constructor with the packet type set to telecommand. + """ + cls( + packet_type=PacketType.TC, + apid=apid, + seq_count=seq_count, + data_len=data_len, + sec_header_flag=sec_header_flag, + seq_flags=seq_flags, + ccsds_version=ccsds_version, + ) + + @classmethod + def tm( + cls, + apid: int, + seq_count: int, + data_len: int, + sec_header_flag: bool = False, + seq_flags: SequenceFlags = SequenceFlags.UNSEGMENTED, + ccsds_version: int = 0b000, + ): + """Create a space packet header with the given field parameters for a telemetry packet. + Calls the default constructor with the packet type set to telemetry. + """ + cls( + packet_type=PacketType.TM, + apid=apid, + seq_count=seq_count, + data_len=data_len, + sec_header_flag=sec_header_flag, + seq_flags=seq_flags, + ccsds_version=ccsds_version, + ) + @classmethod def from_composite_fields( cls, @@ -289,6 +349,19 @@ def sec_header_flag(self, value): def seq_count(self): return self._psc.seq_count + def set_data_len_from_packet_len(self, packet_len: int): + """Sets the data length field from the given total packet length. The total packet length + must be at least 7 bytes. + + Raises + ------- + ValueError: + The passed packet length is smaller than the minimum expected 7 bytes. + """ + if packet_len < CCSDS_HEADER_LEN + 1: + raise ValueError("specified total packet length too short") + self.data_len = packet_len - CCSDS_HEADER_LEN - 1 + @seq_count.setter def seq_count(self, seq_cnt): self._psc.seq_count = seq_cnt