Skip to content

Commit 719d90f

Browse files
authored
Merge pull request #77 from us-irs/update-spacepackets
Update spacepackets
2 parents bcbb918 + a750a92 commit 719d90f

21 files changed

+325
-292
lines changed

CHANGELOG.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,27 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
88

99
# [unreleased]
1010

11+
# [v0.24.0] 2024-04-23
12+
13+
## Removed
14+
15+
- Global configuration module for TC and TM APID was removed.
16+
17+
## Changed
18+
19+
- ECSS PUS telemetry time handling is now more generic and low level: Constructors expect
20+
a simple `bytes` type while unpackers/readers expect the length of the timestamp. A helper
21+
constant for the offset of the timestamp is exposed which can help with determining the
22+
length of the timestamp.
23+
- `CdsShortTimestamp.from_now` renamed to `now`.
24+
- The ECSS TMTC APID field must not be set explicitely in the class constructors.
25+
26+
## Added
27+
28+
- `spacepackets.ecss.tm.PUS_TM_TIMESTAMP_OFFSET` constant which can be used as a look-ahead to
29+
determine the timestamp length from a raw PUS TM packet.
30+
- `spacepackets.ccsds.CCSDS_HEADER_LEN` constant.
31+
1132
# [v0.23.1] 2024-04-22
1233

1334
## Added

docs/api/ecss.rst

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ ECSS Package
66
:undoc-members:
77
:show-inheritance:
88

9+
.. automodule:: spacepackets.ecss.defs
10+
:members:
11+
:undoc-members:
12+
:show-inheritance:
13+
914
ECSS PUS Telecommand Module
10-
--------------------------------
15+
----------------------------
1116

1217
:ref:`api/ecss_tc:ECSS Telecommand Module`
1318

@@ -16,17 +21,6 @@ ECSS PUS Telemetry Module
1621

1722
:ref:`api/ecss_tm:ECSS Telemetry Module`
1823

19-
ECSS Configuration Submodule
20-
----------------------------------
21-
22-
This module can be used to configure common default values so these don't have to be specified
23-
each time anymore when creating ECSS packets
24-
25-
.. automodule:: spacepackets.ecss.conf
26-
:members:
27-
:undoc-members:
28-
:show-inheritance:
29-
3024
ECSS Fields Submodule
3125
----------------------------------
3226

docs/examples.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ PUS ping telemetry reply without a timestamp.
1616
cmd_as_bytes = ping_cmd.pack()
1717
print(f"Ping telecommand [17,1] (hex): [{cmd_as_bytes.hex(sep=',')}]")
1818

19-
ping_reply = PusTm(service=17, subservice=2, apid=0x01, time_provider=None)
19+
ping_reply = PusTm(service=17, subservice=2, apid=0x01, timestamp=bytes())
2020
tm_as_bytes = ping_reply.pack()
2121
print(f"Ping reply [17,2] (hex): [{tm_as_bytes.hex(sep=',')}]")
2222

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
66
name = "spacepackets"
77
description = "Various CCSDS and ECSS packet implementations"
88
readme = "README.md"
9-
version = "0.23.1"
9+
version = "0.24.0"
1010
requires-python = ">=3.8"
1111
license = {text = "Apache-2.0"}
1212
authors = [

spacepackets/ccsds/spacepacket.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010

1111
from spacepackets.exceptions import BytesTooShortError
1212

13-
SPACE_PACKET_HEADER_SIZE: Final = 6
14-
SEQ_FLAG_MASK = 0xC000
15-
APID_MASK = 0x7FF
16-
PACKET_ID_MASK = 0x1FFF
13+
CCSDS_HEADER_LEN: Final[int] = 6
14+
SPACE_PACKET_HEADER_SIZE: Final[int] = CCSDS_HEADER_LEN
15+
SEQ_FLAG_MASK: Final[int] = 0xC000
16+
APID_MASK: Final[int] = 0x7FF
17+
PACKET_ID_MASK: Final[int] = 0x1FFF
18+
MAX_SEQ_COUNT: Final[int] = pow(2, 14) - 1
19+
MAX_APID: Final[int] = pow(2, 11) - 1
1720

1821

1922
class PacketType(enum.IntEnum):
@@ -34,7 +37,7 @@ class PacketSeqCtrl:
3437
"""
3538

3639
def __init__(self, seq_flags: SequenceFlags, seq_count: int):
37-
if seq_count > pow(2, 14) - 1 or seq_count < 0:
40+
if seq_count > MAX_SEQ_COUNT or seq_count < 0:
3841
raise ValueError(
3942
f"Sequence count larger than allowed {pow(2, 14) - 1} or negative"
4043
)
@@ -205,7 +208,7 @@ def __init__(
205208
:param data_len: Contains a length count C that equals one fewer than the length of the
206209
packet data field. Should not be larger than 65535 bytes
207210
:param ccsds_version:
208-
:param sec_header_flag: Secondary header flag, 1 or True by default
211+
:param sec_header_flag: Secondary header flag, or False by default.
209212
:param seq_flags:
210213
:raises ValueError: On invalid parameters
211214
"""
@@ -299,7 +302,7 @@ def seq_flags(self, value):
299302

300303
@property
301304
def header_len(self) -> int:
302-
return SPACE_PACKET_HEADER_SIZE
305+
return CCSDS_HEADER_LEN
303306

304307
@apid.setter
305308
def apid(self, apid):
@@ -311,7 +314,7 @@ def packet_len(self) -> int:
311314
312315
:return: Size of the TM packet based on the space packet header data length field.
313316
"""
314-
return SPACE_PACKET_HEADER_SIZE + self.data_len + 1
317+
return CCSDS_HEADER_LEN + self.data_len + 1
315318

316319
@classmethod
317320
def unpack(cls, data: bytes) -> SpacePacketHeader:
@@ -500,7 +503,7 @@ def parse_space_packets(
500503
# Packet ID detected
501504
while True:
502505
# Can't even parse CCSDS header. Wait for more data to arrive.
503-
if current_idx + SPACE_PACKET_HEADER_SIZE >= len(concatenated_packets):
506+
if current_idx + CCSDS_HEADER_LEN >= len(concatenated_packets):
504507
break
505508
current_packet_id = (
506509
struct.unpack("!H", concatenated_packets[current_idx : current_idx + 2])[0]

spacepackets/ccsds/time/cds.py

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ def _calculate_unix_seconds(self):
8484

8585
def _calculate_date_time(self):
8686
if self._unix_seconds < 0:
87-
self._date_time = datetime.datetime(
87+
self._datetime = datetime.datetime(
8888
1970, 1, 1, tzinfo=datetime.timezone.utc
8989
) + datetime.timedelta(seconds=self._unix_seconds)
9090
else:
91-
self._date_time = datetime.datetime.fromtimestamp(
91+
self._datetime = datetime.datetime.fromtimestamp(
9292
self._unix_seconds, tz=datetime.timezone.utc
9393
)
9494

@@ -108,7 +108,7 @@ def ccsds_days(self) -> int:
108108
def ms_of_day(self) -> int:
109109
return self._ms_of_day
110110

111-
def pack(self) -> bytearray:
111+
def pack(self) -> bytes:
112112
cds_packet = bytearray()
113113
cds_packet.extend(self.__p_field)
114114
cds_packet.extend(struct.pack("!H", self._ccsds_days))
@@ -169,12 +169,14 @@ def __repr__(self):
169169
)
170170

171171
def __str__(self):
172-
return f"Date {self._date_time!r} with representation {self!r}"
172+
return f"Date {self._datetime!r} with representation {self!r}"
173173

174-
def __eq__(self, other: CdsShortTimestamp):
175-
return (self.ccsds_days == other.ccsds_days) and (
176-
self.ms_of_day == other.ms_of_day
177-
)
174+
def __eq__(self, other: object):
175+
if isinstance(other, CdsShortTimestamp):
176+
return (self.ccsds_days == other.ccsds_days) and (
177+
self.ms_of_day == other.ms_of_day
178+
)
179+
return False
178180

179181
def __add__(self, timedelta: datetime.timedelta):
180182
"""Allows adding timedelta to the CDS timestamp provider.
@@ -200,23 +202,33 @@ def __add__(self, timedelta: datetime.timedelta):
200202
return self
201203

202204
@classmethod
203-
def from_now(cls) -> CdsShortTimestamp:
205+
def now(cls) -> CdsShortTimestamp:
204206
"""Returns a seven byte CDS short timestamp with the current time."""
205207
return cls.from_date_time(datetime.datetime.now(tz=datetime.timezone.utc))
206208

209+
@classmethod
210+
@deprecation.deprecated(
211+
deprecated_in="0.24.0",
212+
current_version=get_version(),
213+
details="use now instead",
214+
)
215+
def from_now(cls) -> CdsShortTimestamp:
216+
"""Returns a seven byte CDS short timestamp with the current time."""
217+
return cls.now()
218+
207219
@classmethod
208220
@deprecation.deprecated(
209221
deprecated_in="0.14.0rc1",
210222
current_version=get_version(),
211223
details="use from_now instead",
212224
)
213225
def from_current_time(cls) -> CdsShortTimestamp:
214-
return cls.from_now()
226+
return cls.now()
215227

216228
@classmethod
217-
def from_date_time(cls, dt: datetime.datetime) -> CdsShortTimestamp:
229+
def from_datetime(cls, dt: datetime.datetime) -> CdsShortTimestamp:
218230
instance = cls.empty(False)
219-
instance._date_time = dt
231+
instance._datetime = dt
220232
instance._unix_seconds = dt.timestamp()
221233
full_unix_secs = int(math.floor(instance._unix_seconds))
222234
subsec_millis = int((instance._unix_seconds - full_unix_secs) * 1000)
@@ -226,6 +238,15 @@ def from_date_time(cls, dt: datetime.datetime) -> CdsShortTimestamp:
226238
instance._ccsds_days = convert_unix_days_to_ccsds_days(unix_days)
227239
return instance
228240

241+
@classmethod
242+
@deprecation.deprecated(
243+
deprecated_in="0.24.0",
244+
current_version=get_version(),
245+
details="use from_datetime instead",
246+
)
247+
def from_date_time(cls, dt: datetime.datetime) -> CdsShortTimestamp:
248+
return cls.from_datetime(dt)
249+
229250
@staticmethod
230251
def ms_of_today(seconds_since_epoch: Optional[float] = None):
231252
if seconds_since_epoch is None:
@@ -238,5 +259,13 @@ def ms_of_today(seconds_since_epoch: Optional[float] = None):
238259
def as_unix_seconds(self) -> float:
239260
return self._unix_seconds
240261

262+
def as_datetime(self) -> datetime.datetime:
263+
return self._datetime
264+
265+
@deprecation.deprecated(
266+
deprecated_in="0.24.0",
267+
current_version=get_version(),
268+
details="use as_datetime instead",
269+
)
241270
def as_date_time(self) -> datetime.datetime:
242-
return self._date_time
271+
return self.as_datetime()

spacepackets/ccsds/time/common.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ def len(self) -> int:
7272
return self.len_packed
7373

7474
@abstractmethod
75-
def pack(self) -> bytearray:
75+
def pack(self) -> bytes:
7676
pass
7777

7878
@abstractmethod

spacepackets/ecss/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from crcmod.predefined import mkPredefinedCrcFun
22

3-
from .tc import PusVersion, PusTelecommand, PusTc, PusTcDataFieldHeader
3+
from .tc import PusTc, PusTelecommand, PusTcDataFieldHeader
44
from .tm import PusTm, PusTelemetry, PusTmSecondaryHeader
55
from .fields import (
66
PacketFieldEnum,
@@ -13,7 +13,7 @@
1313
PfcSigned,
1414
PfcUnsigned,
1515
)
16-
from .defs import PusService
16+
from .defs import PusService, PusVersion
1717
from .req_id import RequestId
1818
from .pus_verificator import PusVerificator
1919

spacepackets/ecss/conf.py

Lines changed: 0 additions & 46 deletions
This file was deleted.

spacepackets/ecss/defs.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
import enum
22

33

4+
class PusVersion(enum.IntEnum):
5+
# ESA PSS-07-101. Not supported by this package!
6+
ESA_PUS = 0
7+
# ECSS-E-70-41A
8+
PUS_A = 1
9+
# ECSS-E-ST-70-41C
10+
PUS_C = 2
11+
12+
413
class PusService(enum.IntEnum):
514
S1_VERIFICATION = 1
615
S2_RAW_CMD = 2

0 commit comments

Comments
 (0)