puslib 0.2.5__tar.gz → 0.4.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {puslib-0.2.5/src/puslib.egg-info → puslib-0.4.0}/PKG-INFO +18 -17
- {puslib-0.2.5 → puslib-0.4.0}/README.md +11 -11
- {puslib-0.2.5 → puslib-0.4.0}/setup.cfg +13 -4
- puslib-0.4.0/setup.py +3 -0
- puslib-0.4.0/src/puslib/__init__.py +39 -0
- puslib-0.4.0/src/puslib/crc_ccitt.py +20 -0
- puslib-0.4.0/src/puslib/exceptions.py +13 -0
- puslib-0.4.0/src/puslib/ident.py +45 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/packet.py +254 -116
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/parameter.py +135 -94
- puslib-0.4.0/src/puslib/process.py +163 -0
- puslib-0.4.0/src/puslib/pus_policy.py +106 -0
- puslib-0.4.0/src/puslib/services/__init__.py +14 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/error_codes.py +4 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/param_report.py +35 -14
- puslib-0.4.0/src/puslib/services/pus_001_request_verification.py +137 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/pus_003_housekeeping.py +115 -45
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/pus_005_event_reporting.py +79 -16
- puslib-0.4.0/src/puslib/services/pus_008_function_management.py +73 -0
- puslib-0.4.0/src/puslib/services/pus_017_test.py +41 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/pus_020_parameter_management.py +43 -11
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/services/service.py +33 -12
- puslib-0.4.0/src/puslib/streams/buffer.py +34 -0
- puslib-0.4.0/src/puslib/streams/console.py +10 -0
- puslib-0.4.0/src/puslib/streams/file.py +56 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/streams/stream.py +12 -1
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/time.py +106 -30
- {puslib-0.2.5 → puslib-0.4.0/src/puslib.egg-info}/PKG-INFO +18 -17
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib.egg-info/SOURCES.txt +1 -0
- puslib-0.4.0/tests/test_ident.py +12 -0
- {puslib-0.2.5 → puslib-0.4.0}/tests/test_packet.py +77 -0
- {puslib-0.2.5 → puslib-0.4.0}/tests/test_parameter.py +5 -5
- {puslib-0.2.5 → puslib-0.4.0}/tests/test_policy.py +6 -5
- puslib-0.2.5/setup.py +0 -9
- puslib-0.2.5/src/puslib/__init__.py +0 -82
- puslib-0.2.5/src/puslib/crc_ccitt.py +0 -31
- puslib-0.2.5/src/puslib/exceptions.py +0 -27
- puslib-0.2.5/src/puslib/ident.py +0 -19
- puslib-0.2.5/src/puslib/process.py +0 -73
- puslib-0.2.5/src/puslib/services/__init__.py +0 -14
- puslib-0.2.5/src/puslib/services/pus_001_request_verification.py +0 -85
- puslib-0.2.5/src/puslib/services/pus_008_function_management.py +0 -43
- puslib-0.2.5/src/puslib/services/pus_017_test.py +0 -20
- puslib-0.2.5/src/puslib/streams/buffer.py +0 -23
- puslib-0.2.5/src/puslib/streams/console.py +0 -6
- puslib-0.2.5/src/puslib/streams/file.py +0 -32
- puslib-0.2.5/tests/test_ident.py +0 -12
- {puslib-0.2.5 → puslib-0.4.0}/LICENSE +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/pyproject.toml +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib/streams/__init__.py +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib.egg-info/dependency_links.txt +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib.egg-info/requires.txt +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/src/puslib.egg-info/top_level.txt +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/tests/test_crc.py +0 -0
- {puslib-0.2.5 → puslib-0.4.0}/tests/test_time.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: puslib
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.4.0
|
|
4
4
|
Summary: An implementation of the telemetry and telecommand packet utilization standard (PUS).
|
|
5
5
|
Home-page: https://github.com/pxntus/puslib
|
|
6
6
|
Author: Pontus Nyman
|
|
@@ -14,42 +14,43 @@ Classifier: Natural Language :: English
|
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
19
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
20
17
|
Classifier: Programming Language :: Python :: 3.10
|
|
21
18
|
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
22
22
|
Classifier: Topic :: Communications
|
|
23
23
|
Classifier: Topic :: Scientific/Engineering
|
|
24
|
-
Requires-Python: >=3.
|
|
24
|
+
Requires-Python: >=3.10
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
License-File: LICENSE
|
|
27
27
|
Requires-Dist: bitstring
|
|
28
|
+
Dynamic: license-file
|
|
28
29
|
|
|
29
30
|
# Puslib
|
|
30
31
|
|
|
31
|
-
**Puslib** is a Python
|
|
32
|
+
**Puslib** is a Python library for working with the ECSS Packet Utilization Standard (PUS), a protocol widely used in the space industry.
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
PUS defines an application-level interface between ground and space, covering both segments. It specifies a binary packet format for telecommands and telemetry (based on CCSDS space packets) and a routing mechanism for those packets, as well as a software architecture built around application processes and a set of standard services.
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
|
|
40
|
-
|
|
36
|
+
Puslib covers two main use cases:
|
|
37
|
+
|
|
38
|
+
* **TM/TC packet parsing** — deserialize raw packet streams, inspect packet fields, and extract parameter data for post-processing or analysis.
|
|
39
|
+
* **PUS application stack** — implement a PUS-compliant backend that receives telecommands and emits telemetry, for use in EGSE equipment, simulators, or any system that communicates over TM/TC.
|
|
40
|
+
|
|
41
|
+
The PUS stack is designed from the perspective of the system being monitored and controlled. It receives telecommands and produces telemetry, making it better suited for simulators and EGSE than for mission control systems. It targets ground tooling and test equipment rather than flight software, but don't let the sky be the limit.
|
|
41
42
|
|
|
42
43
|
## Install
|
|
43
44
|
|
|
44
|
-
```
|
|
45
|
+
```shell
|
|
45
46
|
pip install puslib
|
|
46
47
|
```
|
|
47
48
|
|
|
48
|
-
Python 3.
|
|
49
|
+
Python 3.10 or later is required.
|
|
49
50
|
|
|
50
51
|
## Basic Example
|
|
51
52
|
|
|
52
|
-
```
|
|
53
|
+
```python
|
|
53
54
|
from datetime import datetime
|
|
54
55
|
from functools import partial
|
|
55
56
|
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# Puslib
|
|
2
2
|
|
|
3
|
-
**Puslib** is a Python
|
|
3
|
+
**Puslib** is a Python library for working with the ECSS Packet Utilization Standard (PUS), a protocol widely used in the space industry.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
PUS defines an application-level interface between ground and space, covering both segments. It specifies a binary packet format for telecommands and telemetry (based on CCSDS space packets) and a routing mechanism for those packets, as well as a software architecture built around application processes and a set of standard services.
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
Puslib covers two main use cases:
|
|
8
|
+
|
|
9
|
+
* **TM/TC packet parsing** — deserialize raw packet streams, inspect packet fields, and extract parameter data for post-processing or analysis.
|
|
10
|
+
* **PUS application stack** — implement a PUS-compliant backend that receives telecommands and emits telemetry, for use in EGSE equipment, simulators, or any system that communicates over TM/TC.
|
|
11
|
+
|
|
12
|
+
The PUS stack is designed from the perspective of the system being monitored and controlled. It receives telecommands and produces telemetry, making it better suited for simulators and EGSE than for mission control systems. It targets ground tooling and test equipment rather than flight software, but don't let the sky be the limit.
|
|
13
13
|
|
|
14
14
|
## Install
|
|
15
15
|
|
|
16
|
-
```
|
|
16
|
+
```shell
|
|
17
17
|
pip install puslib
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Python 3.
|
|
20
|
+
Python 3.10 or later is required.
|
|
21
21
|
|
|
22
22
|
## Basic Example
|
|
23
23
|
|
|
24
|
-
```
|
|
24
|
+
```python
|
|
25
25
|
from datetime import datetime
|
|
26
26
|
from functools import partial
|
|
27
27
|
|
|
@@ -18,11 +18,11 @@ classifiers =
|
|
|
18
18
|
Operating System :: OS Independent
|
|
19
19
|
Programming Language :: Python :: 3
|
|
20
20
|
Programming Language :: Python :: 3 :: Only
|
|
21
|
-
Programming Language :: Python :: 3.7
|
|
22
|
-
Programming Language :: Python :: 3.8
|
|
23
|
-
Programming Language :: Python :: 3.9
|
|
24
21
|
Programming Language :: Python :: 3.10
|
|
25
22
|
Programming Language :: Python :: 3.11
|
|
23
|
+
Programming Language :: Python :: 3.12
|
|
24
|
+
Programming Language :: Python :: 3.13
|
|
25
|
+
Programming Language :: Python :: 3.14
|
|
26
26
|
Topic :: Communications
|
|
27
27
|
Topic :: Scientific/Engineering
|
|
28
28
|
|
|
@@ -30,7 +30,9 @@ classifiers =
|
|
|
30
30
|
package_dir = = src
|
|
31
31
|
packages = find:
|
|
32
32
|
include_package_data = True
|
|
33
|
-
python_requires = >=3.
|
|
33
|
+
python_requires = >=3.10
|
|
34
|
+
install_requires =
|
|
35
|
+
bitstring
|
|
34
36
|
|
|
35
37
|
[options.packages.find]
|
|
36
38
|
where = src
|
|
@@ -38,6 +40,13 @@ where = src
|
|
|
38
40
|
[tool:pytest]
|
|
39
41
|
testpaths = tests
|
|
40
42
|
|
|
43
|
+
[mypy]
|
|
44
|
+
files = src/puslib
|
|
45
|
+
python_version = 3.10
|
|
46
|
+
warn_return_any = True
|
|
47
|
+
warn_unused_ignores = True
|
|
48
|
+
check_untyped_defs = True
|
|
49
|
+
|
|
41
50
|
[egg_info]
|
|
42
51
|
tag_build =
|
|
43
52
|
tag_date = 0
|
puslib-0.4.0/setup.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from puslib.packet import PusTcPacket, PusTmPacket, AckFlag # noqa: F401
|
|
2
|
+
from puslib.time import CucTime # noqa: F401
|
|
3
|
+
from puslib.pus_policy import PusPolicy
|
|
4
|
+
|
|
5
|
+
__version__ = "0.4.0"
|
|
6
|
+
|
|
7
|
+
_pus_policy = PusPolicy()
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def set_policy(policy):
|
|
11
|
+
"""Set PUS policy to be used.
|
|
12
|
+
|
|
13
|
+
A PUS policy is an object defining various properties of the PUS implementation,
|
|
14
|
+
e.g., various field lengths. This is due to that many parts of the PUS standard
|
|
15
|
+
are mission-specific.
|
|
16
|
+
|
|
17
|
+
The policy is stored as a module-level global and is not thread-safe. This is a
|
|
18
|
+
deliberate design choice: the library assumes a single-threaded execution model
|
|
19
|
+
where the policy is set once at startup and remains unchanged for the lifetime of
|
|
20
|
+
the application. Calling set_policy() from multiple threads, or changing the policy
|
|
21
|
+
while packets are being processed, results in undefined behavior.
|
|
22
|
+
|
|
23
|
+
If per-thread policies are ever required, replace this global with a
|
|
24
|
+
contextvars.ContextVar to give each thread or async task its own policy instance.
|
|
25
|
+
|
|
26
|
+
Arguments:
|
|
27
|
+
policy -- PUS policy
|
|
28
|
+
"""
|
|
29
|
+
global _pus_policy # pylint: disable=global-statement
|
|
30
|
+
_pus_policy = policy
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_policy() -> PusPolicy:
|
|
34
|
+
"""Get the current selected PUS policy.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
PUS policy
|
|
38
|
+
"""
|
|
39
|
+
return _pus_policy
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""CRC-16-CCITT checksum (polynomial 0x1021, preset 0xFFFF)."""
|
|
2
|
+
|
|
3
|
+
import binascii
|
|
4
|
+
|
|
5
|
+
_PRESET = 0xffff
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def calculate(buffer: bytes | bytearray | memoryview) -> int:
|
|
9
|
+
"""Calculate the CRC-16-CCITT checksum on a buffer.
|
|
10
|
+
|
|
11
|
+
Using polynomial 0x1021 (default for crc_hqx) and preset (or initial value)
|
|
12
|
+
0xffff according to ECSS and CCSDS standards.
|
|
13
|
+
|
|
14
|
+
Arguments:
|
|
15
|
+
buffer -- input buffer to calculate checksum for
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
16 bit CRC checksum
|
|
19
|
+
"""
|
|
20
|
+
return binascii.crc_hqx(buffer, _PRESET)
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# flake8: noqa
|
|
2
|
+
|
|
3
|
+
"""All exceptions used by puslib.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class PusException(Exception): ...
|
|
8
|
+
class CrcException(PusException): ...
|
|
9
|
+
class IncompletePacketException(PusException): ...
|
|
10
|
+
class InvalidPacketException(PusException): ...
|
|
11
|
+
class TooSmallBufferException(PusException): ...
|
|
12
|
+
class InvalidTimeFormat(PusException): ...
|
|
13
|
+
class TcPacketRoutingError(PusException): ...
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
from typing import Iterator
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def _seq_count_generator() -> Iterator[int]:
|
|
5
|
+
seq_count = -1
|
|
6
|
+
max_count = 2 ** 14
|
|
7
|
+
while True:
|
|
8
|
+
seq_count = (seq_count + 1) % max_count
|
|
9
|
+
yield seq_count
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class PusIdent:
|
|
13
|
+
"""Represents the identity of A PUS packet.
|
|
14
|
+
|
|
15
|
+
The identity of a PUS packet consists of:
|
|
16
|
+
|
|
17
|
+
- APID (Application ID)
|
|
18
|
+
- packet sequence count
|
|
19
|
+
|
|
20
|
+
The sequence count is per APID and spans [0..16383].
|
|
21
|
+
|
|
22
|
+
The APID-sequence pair, thus, uniquely identifies a PUS packet for the foreseeable future.
|
|
23
|
+
"""
|
|
24
|
+
def __init__(self, apid: int):
|
|
25
|
+
"""Create an identity instance.
|
|
26
|
+
|
|
27
|
+
Arguments:
|
|
28
|
+
apid -- application ID [0..2047]
|
|
29
|
+
"""
|
|
30
|
+
if not 0 <= apid <= 2047:
|
|
31
|
+
raise ValueError("APID must be between 0 and 2047")
|
|
32
|
+
self._apid = apid
|
|
33
|
+
self._seq_count_generator = _seq_count_generator()
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def apid(self) -> int:
|
|
37
|
+
return self._apid
|
|
38
|
+
|
|
39
|
+
def next_seq_count(self) -> int:
|
|
40
|
+
"""Returns next sequence count.
|
|
41
|
+
|
|
42
|
+
Returns:
|
|
43
|
+
sequence count [0..16383]
|
|
44
|
+
"""
|
|
45
|
+
return next(self._seq_count_generator)
|