space-packet-parser 5.0.1__tar.gz → 6.0.0.dev1__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.
- {space_packet_parser-5.0.1 → space_packet_parser-6.0.0.dev1}/CITATION.cff +5 -2
- space_packet_parser-6.0.0.dev1/PKG-INFO +97 -0
- space_packet_parser-6.0.0.dev1/README.md +47 -0
- space_packet_parser-6.0.0.dev1/pyproject.toml +153 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/__init__.py +20 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/cli.py +189 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/common.py +249 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/definitions.py +17 -0
- {space_packet_parser-5.0.1 → space_packet_parser-6.0.0.dev1}/space_packet_parser/exceptions.py +14 -1
- space_packet_parser-6.0.0.dev1/space_packet_parser/packets.py +465 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/xarr.py +215 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/xtce/__init__.py +21 -0
- {space_packet_parser-5.0.1/space_packet_parser → space_packet_parser-6.0.0.dev1/space_packet_parser/xtce}/calibrators.py +223 -58
- {space_packet_parser-5.0.1/space_packet_parser → space_packet_parser-6.0.0.dev1/space_packet_parser/xtce}/comparisons.py +228 -84
- space_packet_parser-6.0.0.dev1/space_packet_parser/xtce/containers.py +299 -0
- space_packet_parser-6.0.0.dev1/space_packet_parser/xtce/definitions.py +559 -0
- {space_packet_parser-5.0.1/space_packet_parser → space_packet_parser-6.0.0.dev1/space_packet_parser/xtce}/encodings.py +327 -146
- space_packet_parser-5.0.1/space_packet_parser/parameters.py → space_packet_parser-6.0.0.dev1/space_packet_parser/xtce/parameter_types.py +251 -109
- space_packet_parser-6.0.0.dev1/space_packet_parser/xtce/parameters.py +117 -0
- space_packet_parser-5.0.1/PKG-INFO +0 -52
- space_packet_parser-5.0.1/README.md +0 -29
- space_packet_parser-5.0.1/pyproject.toml +0 -63
- space_packet_parser-5.0.1/space_packet_parser/__init__.py +0 -0
- space_packet_parser-5.0.1/space_packet_parser/definitions.py +0 -653
- space_packet_parser-5.0.1/space_packet_parser/packets.py +0 -247
- {space_packet_parser-5.0.1 → space_packet_parser-6.0.0.dev1}/LICENSE.txt +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
cff-version: 1.2.0
|
|
2
2
|
title: 'space_packet_parser'
|
|
3
3
|
type: software
|
|
4
|
-
version: '
|
|
4
|
+
version: '6.0.0dev1'
|
|
5
5
|
description: A CCSDS telemetry packet decoding library based on the XTCE packet format description standard.
|
|
6
6
|
license: BSD-3-Clause
|
|
7
7
|
abstract: The Space Packet Parser Python library is a generalized, configurable packet decoding library for CCSDS telemetry
|
|
@@ -29,5 +29,8 @@ maintainers:
|
|
|
29
29
|
- email: gavin.medley@lasp.colorado.edu
|
|
30
30
|
name: Gavin Medley
|
|
31
31
|
orcid: "0000-0002-3520-9715"
|
|
32
|
-
|
|
32
|
+
- email: greg.lucas@lasp.colorado.edu
|
|
33
|
+
name: Greg Lucas
|
|
34
|
+
orcid: "0000-0003-1331-1863"
|
|
35
|
+
repository-code: "https://github.com/lasp/space_packet_parser"
|
|
33
36
|
url: "https://space-packet-parser.readthedocs.io"
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: space_packet_parser
|
|
3
|
+
Version: 6.0.0.dev1
|
|
4
|
+
Summary: A CCSDS telemetry packet decoding library based on the XTCE packet format description standard.
|
|
5
|
+
License: BSD-3-Clause
|
|
6
|
+
Keywords: ccsds,xtce,space data systems,space packet protocol,packet parsing,lasp,university of colorado,data processing,data extraction,data manipulation,data transformation,data encoding,data decoding,packet inspection,binary data,python
|
|
7
|
+
Author: Gavin Medley
|
|
8
|
+
Author-email: gavin.medley@lasp.colorado.edu
|
|
9
|
+
Maintainer: Gavin Medley
|
|
10
|
+
Maintainer-email: gavin.medley@lasp.colorado.edu
|
|
11
|
+
Requires-Python: >=3.9
|
|
12
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
13
|
+
Classifier: Intended Audience :: Science/Research
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Topic :: Scientific/Engineering
|
|
16
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Operating System :: OS Independent
|
|
19
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
20
|
+
Provides-Extra: docs
|
|
21
|
+
Provides-Extra: examples
|
|
22
|
+
Provides-Extra: test
|
|
23
|
+
Provides-Extra: xarray
|
|
24
|
+
Requires-Dist: click (>=8.0)
|
|
25
|
+
Requires-Dist: lxml (>=4.8.0)
|
|
26
|
+
Requires-Dist: matplotlib (>=3.4) ; extra == "examples"
|
|
27
|
+
Requires-Dist: myst-parser ; extra == "docs"
|
|
28
|
+
Requires-Dist: numpy (>=2.0.0) ; extra == "xarray"
|
|
29
|
+
Requires-Dist: numpy ; extra == "test"
|
|
30
|
+
Requires-Dist: pre-commit ; extra == "test"
|
|
31
|
+
Requires-Dist: pytest ; extra == "test"
|
|
32
|
+
Requires-Dist: pytest-benchmark ; extra == "test"
|
|
33
|
+
Requires-Dist: pytest-cov ; extra == "test"
|
|
34
|
+
Requires-Dist: pytest-randomly ; extra == "test"
|
|
35
|
+
Requires-Dist: pyyaml ; extra == "docs"
|
|
36
|
+
Requires-Dist: pyyaml ; extra == "test"
|
|
37
|
+
Requires-Dist: rich (>=13.0)
|
|
38
|
+
Requires-Dist: ruff ; extra == "test"
|
|
39
|
+
Requires-Dist: sphinx ; extra == "docs"
|
|
40
|
+
Requires-Dist: sphinx-autoapi ; extra == "docs"
|
|
41
|
+
Requires-Dist: sphinx-rtd-theme ; extra == "docs"
|
|
42
|
+
Requires-Dist: tomli ; extra == "test"
|
|
43
|
+
Requires-Dist: xarray (>2024.0.0) ; extra == "xarray"
|
|
44
|
+
Requires-Dist: xarray ; extra == "test"
|
|
45
|
+
Project-URL: Documentation, https://space-packet-parser.readthedocs.io
|
|
46
|
+
Project-URL: Homepage, https://github.com/lasp/space_packet_parser
|
|
47
|
+
Project-URL: Repository, https://github.com/lasp/space_packet_parser
|
|
48
|
+
Description-Content-Type: text/markdown
|
|
49
|
+
|
|
50
|
+
# Space Packet Parser
|
|
51
|
+
|
|
52
|
+
[](https://anaconda.org/lasp/space_packet_parser)
|
|
53
|
+
[](https://pypi.org/project/space-packet-parser/)
|
|
54
|
+
[](https://doi.org/10.5281/zenodo.7735001)
|
|
55
|
+
|
|
56
|
+
[](https://github.com/lasp/space_packet_parser/actions/workflows/tests.yml)
|
|
57
|
+
[](https://codecov.io/gh/lasp/space_packet_parser)
|
|
58
|
+
|
|
59
|
+
**Documentation:** [https://space-packet-parser.readthedocs.io/en/latest/](https://space-packet-parser.readthedocs.io/en/latest/)
|
|
60
|
+
|
|
61
|
+
| **Stable ReadTheDocs Build** | [](https://app.readthedocs.org/projects/space-packet-parser/builds/?version__slug=stable) |
|
|
62
|
+
|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
63
|
+
| **Latest ReadTheDocs Build** | [](https://app.readthedocs.org/projects/space-packet-parser/builds/?version__slug=latest) |
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
Space Packet Parser is a package for decoding CCSDS telemetry packets according to an XTCE packet structure definition.
|
|
67
|
+
It is based on the UML model of the XTCE spec and aims to support all but the most esoteric elements of the
|
|
68
|
+
XTCE telemetry packet specification.
|
|
69
|
+
|
|
70
|
+
Resources:
|
|
71
|
+
- [XTCE (Green Book - Informational Report)](https://public.ccsds.org/Pubs/660x2g2.pdf)
|
|
72
|
+
- [XTCE Element Description (Green Book - Informational Report)](https://public.ccsds.org/Pubs/660x1g2.pdf)
|
|
73
|
+
- [XTCE (Blue Book - Recommended Standard)](https://public.ccsds.org/Pubs/660x0b2.pdf)
|
|
74
|
+
|
|
75
|
+
## Installation
|
|
76
|
+
From PyPI
|
|
77
|
+
```bash
|
|
78
|
+
pip install space_packet_parser
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
From Anaconda (distributed on the `lasp` channel):
|
|
82
|
+
```bash
|
|
83
|
+
conda install -c lasp space_packet_parser
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Proud Member of the Python in Heliophysics Community (PyHC)
|
|
87
|
+
|
|
88
|
+
[<img src="https://heliopython.org/img/PyHC%20header%20logo%20500x500.png" alt="PyHC" height="70"/>](https://heliopython.org)
|
|
89
|
+
|
|
90
|
+
## Missions using Space Packet Parser
|
|
91
|
+
|
|
92
|
+
[<img src="https://imap.princeton.edu/sites/g/files/toruqf7171/files/imap-mark-hor-multicolor-dark.png" alt="IMAP" height="70"/>](https://imap.princeton.edu/)
|
|
93
|
+
[<img src="https://clarreo-pathfinder.larc.nasa.gov/wp-content/uploads/sites/133/2019/08/clarreo_pathfinder_mission_patch_design_v4_decal_1_24_17.png" alt="CLARREO" height="140"/>](https://clarreo-pathfinder.larc.nasa.gov/)
|
|
94
|
+
[<img src="https://lasp.colorado.edu/libera/files/2021/02/Libera-Logo-HiRes.png" alt="Libera" height="70"/>](https://lasp.colorado.edu/libera/)
|
|
95
|
+
[<img src="https://lasp.colorado.edu/ctim/files/2023/01/CTIM_LOGO_350x100_centered_transparent.png" alt="CTIM-FD" height="70"/>](https://lasp.colorado.edu/ctim/)
|
|
96
|
+
[<img src="https://mms.gsfc.nasa.gov/images/promotional_materials/mms_decal_rgb_4in_trabk_72dpi.png" alt="MMS-FEEPS" height="140"/>](https://lasp.colorado.edu/mms/sdc/public/)
|
|
97
|
+
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
# Space Packet Parser
|
|
2
|
+
|
|
3
|
+
[](https://anaconda.org/lasp/space_packet_parser)
|
|
4
|
+
[](https://pypi.org/project/space-packet-parser/)
|
|
5
|
+
[](https://doi.org/10.5281/zenodo.7735001)
|
|
6
|
+
|
|
7
|
+
[](https://github.com/lasp/space_packet_parser/actions/workflows/tests.yml)
|
|
8
|
+
[](https://codecov.io/gh/lasp/space_packet_parser)
|
|
9
|
+
|
|
10
|
+
**Documentation:** [https://space-packet-parser.readthedocs.io/en/latest/](https://space-packet-parser.readthedocs.io/en/latest/)
|
|
11
|
+
|
|
12
|
+
| **Stable ReadTheDocs Build** | [](https://app.readthedocs.org/projects/space-packet-parser/builds/?version__slug=stable) |
|
|
13
|
+
|------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|
14
|
+
| **Latest ReadTheDocs Build** | [](https://app.readthedocs.org/projects/space-packet-parser/builds/?version__slug=latest) |
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
Space Packet Parser is a package for decoding CCSDS telemetry packets according to an XTCE packet structure definition.
|
|
18
|
+
It is based on the UML model of the XTCE spec and aims to support all but the most esoteric elements of the
|
|
19
|
+
XTCE telemetry packet specification.
|
|
20
|
+
|
|
21
|
+
Resources:
|
|
22
|
+
- [XTCE (Green Book - Informational Report)](https://public.ccsds.org/Pubs/660x2g2.pdf)
|
|
23
|
+
- [XTCE Element Description (Green Book - Informational Report)](https://public.ccsds.org/Pubs/660x1g2.pdf)
|
|
24
|
+
- [XTCE (Blue Book - Recommended Standard)](https://public.ccsds.org/Pubs/660x0b2.pdf)
|
|
25
|
+
|
|
26
|
+
## Installation
|
|
27
|
+
From PyPI
|
|
28
|
+
```bash
|
|
29
|
+
pip install space_packet_parser
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
From Anaconda (distributed on the `lasp` channel):
|
|
33
|
+
```bash
|
|
34
|
+
conda install -c lasp space_packet_parser
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
## Proud Member of the Python in Heliophysics Community (PyHC)
|
|
38
|
+
|
|
39
|
+
[<img src="https://heliopython.org/img/PyHC%20header%20logo%20500x500.png" alt="PyHC" height="70"/>](https://heliopython.org)
|
|
40
|
+
|
|
41
|
+
## Missions using Space Packet Parser
|
|
42
|
+
|
|
43
|
+
[<img src="https://imap.princeton.edu/sites/g/files/toruqf7171/files/imap-mark-hor-multicolor-dark.png" alt="IMAP" height="70"/>](https://imap.princeton.edu/)
|
|
44
|
+
[<img src="https://clarreo-pathfinder.larc.nasa.gov/wp-content/uploads/sites/133/2019/08/clarreo_pathfinder_mission_patch_design_v4_decal_1_24_17.png" alt="CLARREO" height="140"/>](https://clarreo-pathfinder.larc.nasa.gov/)
|
|
45
|
+
[<img src="https://lasp.colorado.edu/libera/files/2021/02/Libera-Logo-HiRes.png" alt="Libera" height="70"/>](https://lasp.colorado.edu/libera/)
|
|
46
|
+
[<img src="https://lasp.colorado.edu/ctim/files/2023/01/CTIM_LOGO_350x100_centered_transparent.png" alt="CTIM-FD" height="70"/>](https://lasp.colorado.edu/ctim/)
|
|
47
|
+
[<img src="https://mms.gsfc.nasa.gov/images/promotional_materials/mms_decal_rgb_4in_trabk_72dpi.png" alt="MMS-FEEPS" height="140"/>](https://lasp.colorado.edu/mms/sdc/public/)
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "space_packet_parser"
|
|
3
|
+
version = "6.0.0dev1"
|
|
4
|
+
description = "A CCSDS telemetry packet decoding library based on the XTCE packet format description standard."
|
|
5
|
+
license = { text = "BSD-3-Clause" }
|
|
6
|
+
readme = "README.md"
|
|
7
|
+
requires-python = ">=3.9"
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "Gavin Medley", email = "gavin.medley@lasp.colorado.edu" },
|
|
10
|
+
{ name = "Greg Lucas", email = "greg.lucas@lasp.colorado.edu" },
|
|
11
|
+
{ name = "Michael Chambliss", email = "michael.chambliss@lasp.colorado.edu" }
|
|
12
|
+
]
|
|
13
|
+
maintainers = [
|
|
14
|
+
{ name = "Gavin Medley", email = "gavin.medley@lasp.colorado.edu" },
|
|
15
|
+
{ name = "Greg Lucas", email = "greg.lucas@lasp.colorado.edu" }
|
|
16
|
+
]
|
|
17
|
+
keywords = [
|
|
18
|
+
"ccsds",
|
|
19
|
+
"xtce",
|
|
20
|
+
"space data systems",
|
|
21
|
+
"space packet protocol",
|
|
22
|
+
"packet parsing",
|
|
23
|
+
"lasp",
|
|
24
|
+
"university of colorado",
|
|
25
|
+
"data processing",
|
|
26
|
+
"data extraction",
|
|
27
|
+
"data manipulation",
|
|
28
|
+
"data transformation",
|
|
29
|
+
"data encoding",
|
|
30
|
+
"data decoding",
|
|
31
|
+
"packet inspection",
|
|
32
|
+
"binary data",
|
|
33
|
+
"python"
|
|
34
|
+
]
|
|
35
|
+
classifiers = [
|
|
36
|
+
"Development Status :: 5 - Production/Stable",
|
|
37
|
+
"Intended Audience :: Science/Research",
|
|
38
|
+
"Intended Audience :: Developers",
|
|
39
|
+
"Topic :: Scientific/Engineering",
|
|
40
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
41
|
+
"Programming Language :: Python :: 3",
|
|
42
|
+
"Operating System :: OS Independent",
|
|
43
|
+
"License :: OSI Approved :: BSD License"
|
|
44
|
+
]
|
|
45
|
+
# These are the dependencies used for metadata when building the project
|
|
46
|
+
dependencies = [
|
|
47
|
+
"lxml>=4.8.0",
|
|
48
|
+
"click>=8.0",
|
|
49
|
+
"rich>=13.0"
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[project.urls]
|
|
53
|
+
repository = "https://github.com/lasp/space_packet_parser"
|
|
54
|
+
homepage = "https://github.com/lasp/space_packet_parser"
|
|
55
|
+
documentation = "https://space-packet-parser.readthedocs.io"
|
|
56
|
+
|
|
57
|
+
[project.scripts]
|
|
58
|
+
spp = "space_packet_parser.cli:spp"
|
|
59
|
+
|
|
60
|
+
# These are the project extras used for metadata when building the project
|
|
61
|
+
[project.optional-dependencies]
|
|
62
|
+
xarray = [
|
|
63
|
+
"xarray>2024.0.0",
|
|
64
|
+
"numpy>=2.0.0"
|
|
65
|
+
]
|
|
66
|
+
examples = [
|
|
67
|
+
"matplotlib>=3.4"
|
|
68
|
+
]
|
|
69
|
+
test = [
|
|
70
|
+
"pre-commit",
|
|
71
|
+
"pytest",
|
|
72
|
+
"pytest-benchmark",
|
|
73
|
+
"pytest-randomly",
|
|
74
|
+
"pytest-cov",
|
|
75
|
+
"pyyaml", # needed by check_metadata.py
|
|
76
|
+
"ruff",
|
|
77
|
+
"tomli", # for support of python<3.11 toml parsing in check_metadata.py
|
|
78
|
+
"xarray", # for testing extra
|
|
79
|
+
"numpy" # for testing extra
|
|
80
|
+
]
|
|
81
|
+
docs = [
|
|
82
|
+
"pyyaml",
|
|
83
|
+
"sphinx",
|
|
84
|
+
"myst-parser",
|
|
85
|
+
"sphinx-autoapi",
|
|
86
|
+
"sphinx-rtd-theme"
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
[tool.poetry]
|
|
90
|
+
packages = [
|
|
91
|
+
{ include = "space_packet_parser" }
|
|
92
|
+
]
|
|
93
|
+
include = [
|
|
94
|
+
"LICENSE.txt",
|
|
95
|
+
"CITATION.cff"
|
|
96
|
+
]
|
|
97
|
+
|
|
98
|
+
[tool.poetry.group.xarray.dependencies]
|
|
99
|
+
xarray = ">2024.0.0"
|
|
100
|
+
numpy = ">=2.0.0"
|
|
101
|
+
|
|
102
|
+
[tool.poetry.group.examples.dependencies]
|
|
103
|
+
matplotlib = ">=3.4"
|
|
104
|
+
|
|
105
|
+
[tool.poetry.group.test.dependencies]
|
|
106
|
+
pre-commit = "*"
|
|
107
|
+
pytest = "*"
|
|
108
|
+
pytest-benchmark = "*"
|
|
109
|
+
pytest-randomly = "*"
|
|
110
|
+
pytest-cov = "*"
|
|
111
|
+
pyyaml = "*"
|
|
112
|
+
ruff = "*"
|
|
113
|
+
tomli = "*"
|
|
114
|
+
|
|
115
|
+
[tool.poetry.group.docs.dependencies]
|
|
116
|
+
pyyaml = "*"
|
|
117
|
+
sphinx = "*"
|
|
118
|
+
myst-parser = "*"
|
|
119
|
+
sphinx-autoapi = "*"
|
|
120
|
+
sphinx-rtd-theme = "*"
|
|
121
|
+
|
|
122
|
+
[build-system]
|
|
123
|
+
requires = ["poetry-core>=2.0.1"]
|
|
124
|
+
build-backend = "poetry.core.masonry.api"
|
|
125
|
+
|
|
126
|
+
[tool.pytest.ini_options]
|
|
127
|
+
filterwarnings = [
|
|
128
|
+
"error",
|
|
129
|
+
"ignore:You are encoding a BooleanParameterType:UserWarning"
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
# Note: Ruff uses the "nearest" configuration file at runtime so configurations may be overridden
|
|
133
|
+
# e.g. see ruff.toml in the tests directory
|
|
134
|
+
[tool.ruff]
|
|
135
|
+
line-length = 120
|
|
136
|
+
extend-include = [
|
|
137
|
+
"space_packet_parser/**/*.py",
|
|
138
|
+
"examples/**/*.py",
|
|
139
|
+
"tests/**/*.py"
|
|
140
|
+
]
|
|
141
|
+
extend-exclude = []
|
|
142
|
+
|
|
143
|
+
[tool.ruff.lint]
|
|
144
|
+
select = [
|
|
145
|
+
"E", # pycodestyle errors
|
|
146
|
+
"W", # pycodestyle warnings
|
|
147
|
+
"F", # pyflakes
|
|
148
|
+
"I", # isort import sorting
|
|
149
|
+
"S", # flake8-bandit security
|
|
150
|
+
"PT", # flake8-pytest-style
|
|
151
|
+
"UP" # pyupgrade syntax upgrader
|
|
152
|
+
]
|
|
153
|
+
per-file-ignores = { "tests/*" = ["S"] }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""Space Packet Parser"""
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
from typing import Union
|
|
4
|
+
|
|
5
|
+
from space_packet_parser.xtce.definitions import XtcePacketDefinition
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def load_xml(filename: Union[str, Path]) -> XtcePacketDefinition:
|
|
9
|
+
"""Create an XtcePacketDefinition object from an XTCE XML file
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
filename : Union[str, Path]
|
|
14
|
+
XTCE XML file
|
|
15
|
+
|
|
16
|
+
Returns
|
|
17
|
+
-------
|
|
18
|
+
: definitions.XtcePacketDefinition
|
|
19
|
+
"""
|
|
20
|
+
return XtcePacketDefinition.from_xtce(filename)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
|
|
3
|
+
"""Command line interface to the Space Packet Parsing library.
|
|
4
|
+
|
|
5
|
+
This module serves as a command line utility to inspect and process packet data.
|
|
6
|
+
|
|
7
|
+
Use
|
|
8
|
+
---
|
|
9
|
+
spp <command> [<args>]
|
|
10
|
+
spp --help
|
|
11
|
+
spp --describe <packet_file>
|
|
12
|
+
"""
|
|
13
|
+
import logging
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Optional
|
|
16
|
+
|
|
17
|
+
import click
|
|
18
|
+
from rich import pretty
|
|
19
|
+
from rich.console import Console
|
|
20
|
+
from rich.logging import RichHandler
|
|
21
|
+
from rich.panel import Panel
|
|
22
|
+
from rich.table import Table
|
|
23
|
+
from rich.tree import Tree
|
|
24
|
+
|
|
25
|
+
from space_packet_parser.packets import ccsds_generator
|
|
26
|
+
from space_packet_parser.xtce.definitions import DEFAULT_ROOT_CONTAINER, XtcePacketDefinition
|
|
27
|
+
|
|
28
|
+
# Initialize a console instance for rich output
|
|
29
|
+
console = Console()
|
|
30
|
+
|
|
31
|
+
# Maximum number of rows to display
|
|
32
|
+
MAX_ROWS = 10
|
|
33
|
+
HEAD_ROWS = 5
|
|
34
|
+
# Standard names for header field values when inspecting packets without an XTCE definition
|
|
35
|
+
DISPLAY_HEADER_FIELDS = ("VER", "TYPE", "SHFLG", "APID", "SEQFLG", "SEQCNT", "PKTLEN")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
@click.group(context_settings={'show_default': True})
|
|
39
|
+
@click.version_option(message="Space Packet Parser CLI (%(prog)s) v%(version)s")
|
|
40
|
+
@click.option("-v", "--verbose", is_flag=True, help="Enable verbose output (DEBUG logging)")
|
|
41
|
+
@click.option("-q", "--quiet", is_flag=True, help="Disable logging output entirely")
|
|
42
|
+
@click.option("--log-level", default="INFO", help="Log level, e.g. WARNING, INFO, DEBUG. Ignored if -q or -v is set.")
|
|
43
|
+
def spp(verbose, quiet, log_level):
|
|
44
|
+
"""Command line utility for working with CCSDS packets."""
|
|
45
|
+
# Set logging level
|
|
46
|
+
loglevel = logging.getLevelNamesMapping()[log_level]
|
|
47
|
+
if verbose:
|
|
48
|
+
loglevel = logging.DEBUG
|
|
49
|
+
elif quiet:
|
|
50
|
+
loglevel = logging.CRITICAL
|
|
51
|
+
|
|
52
|
+
# Configure logging with RichHandler for colorized output
|
|
53
|
+
logging.basicConfig(
|
|
54
|
+
level=loglevel,
|
|
55
|
+
format="%(message)s",
|
|
56
|
+
datefmt="[%X]",
|
|
57
|
+
handlers=[RichHandler(console=console, rich_tracebacks=True)]
|
|
58
|
+
)
|
|
59
|
+
logging.getLogger("rich").setLevel(loglevel)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@spp.command()
|
|
63
|
+
@click.argument("file_path", type=click.Path(exists=True, path_type=Path))
|
|
64
|
+
@click.option("--sequence-containers", is_flag=True, help="Display sequence containers")
|
|
65
|
+
@click.option("--parameters", is_flag=True, help="Display parameters")
|
|
66
|
+
@click.option("--parameter-types", is_flag=True, help="Display parameter types")
|
|
67
|
+
@click.option("--root-container", default=DEFAULT_ROOT_CONTAINER,
|
|
68
|
+
help=f"Name of root SequenceContainer element. Default is {DEFAULT_ROOT_CONTAINER}.")
|
|
69
|
+
def describe_xtce(
|
|
70
|
+
file_path: Path,
|
|
71
|
+
sequence_containers: bool,
|
|
72
|
+
parameters: bool,
|
|
73
|
+
parameter_types: bool,
|
|
74
|
+
root_container: str
|
|
75
|
+
) -> None:
|
|
76
|
+
"""Describe the contents and structure of an XTCE packet definition file."""
|
|
77
|
+
logging.debug(f"Describing XTCE file: {file_path}")
|
|
78
|
+
definition = XtcePacketDefinition.from_xtce(file_path, root_container_name=root_container)
|
|
79
|
+
tree = Tree(definition.root_container_name)
|
|
80
|
+
|
|
81
|
+
# Recursively add nodes based on the inheritors of each container
|
|
82
|
+
def add_nodes(tree_node, parent_key):
|
|
83
|
+
children = definition.containers[parent_key].inheritors
|
|
84
|
+
for child_key in children:
|
|
85
|
+
# Create a new child node (name + comparisons used to distinguish between containers)
|
|
86
|
+
child_node = tree_node.add(
|
|
87
|
+
f"{child_key} {definition.containers[child_key].restriction_criteria}")
|
|
88
|
+
# Recursively add any children of this child
|
|
89
|
+
add_nodes(child_node, child_key)
|
|
90
|
+
|
|
91
|
+
add_nodes(tree, definition.root_container_name)
|
|
92
|
+
|
|
93
|
+
console.print(Panel(tree, title="XTCE Container Layout", border_style="cyan", expand=False))
|
|
94
|
+
if sequence_containers:
|
|
95
|
+
console.print(Panel(pretty.Pretty(definition.containers),
|
|
96
|
+
title=f"Sequence Containers ({len(definition.containers)})",
|
|
97
|
+
border_style="blue", expand=False))
|
|
98
|
+
if parameters:
|
|
99
|
+
console.print(Panel(pretty.Pretty(definition.parameters),
|
|
100
|
+
title=f"Parameters ({len(definition.parameters)})",
|
|
101
|
+
border_style="green", expand=False))
|
|
102
|
+
if parameter_types:
|
|
103
|
+
console.print(Panel(pretty.Pretty(definition.parameter_types),
|
|
104
|
+
title=f"Parameter Types ({len(definition.parameter_types)})",
|
|
105
|
+
border_style="magenta", expand=False))
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@spp.command()
|
|
109
|
+
@click.argument("file_path", type=click.Path(exists=True, path_type=Path))
|
|
110
|
+
# TODO: Allow multiple file paths, ordered
|
|
111
|
+
# TODO: Allow filtering by header values
|
|
112
|
+
def describe_packets(file_path: Path) -> None:
|
|
113
|
+
"""Describe the header contents of a packet file, no packet definition required."""
|
|
114
|
+
logging.debug(f"Describing packet file: {file_path}")
|
|
115
|
+
with open(file_path, "rb") as f:
|
|
116
|
+
packets = list(ccsds_generator(f))
|
|
117
|
+
|
|
118
|
+
npackets = len(packets)
|
|
119
|
+
if npackets == 0:
|
|
120
|
+
console.print(f"No packets found in {file_path}")
|
|
121
|
+
return
|
|
122
|
+
|
|
123
|
+
# Create table for packet data display
|
|
124
|
+
table = Table(title=f"[bold magenta]{file_path}: {npackets} packets[/bold magenta]",
|
|
125
|
+
show_header=True,
|
|
126
|
+
header_style="bold magenta")
|
|
127
|
+
|
|
128
|
+
# Add columns for header fields only
|
|
129
|
+
for key in DISPLAY_HEADER_FIELDS:
|
|
130
|
+
table.add_column(key)
|
|
131
|
+
|
|
132
|
+
# Determine rows to display (head and tail with ellipsis if necessary)
|
|
133
|
+
if npackets > MAX_ROWS:
|
|
134
|
+
packets_to_show = packets[:HEAD_ROWS] + packets[-HEAD_ROWS:]
|
|
135
|
+
else:
|
|
136
|
+
packets_to_show = packets
|
|
137
|
+
|
|
138
|
+
# Add rows to the table
|
|
139
|
+
for packet in packets_to_show[:HEAD_ROWS]:
|
|
140
|
+
table.add_row(*[str(value) for value in packet.header_values])
|
|
141
|
+
|
|
142
|
+
# Add ellipsis if there are more packets
|
|
143
|
+
if npackets > MAX_ROWS:
|
|
144
|
+
table.add_row(*["..." for _ in packets[0].header_values])
|
|
145
|
+
|
|
146
|
+
for packet in packets_to_show[-HEAD_ROWS:]:
|
|
147
|
+
table.add_row(*[str(value) for value in packet.header_values])
|
|
148
|
+
|
|
149
|
+
# Print the table
|
|
150
|
+
console.print(table, overflow="ellipsis")
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
@spp.command()
|
|
154
|
+
@click.argument("packet_file", type=click.Path(exists=True, path_type=Path))
|
|
155
|
+
@click.argument("definition_file", type=click.Path(exists=True, path_type=Path))
|
|
156
|
+
@click.option("--packet", type=int, default=None, help="Display the packet at the given index (0-indexed)")
|
|
157
|
+
@click.option("--max-items", type=int, default=20, help="Maximum number of items to display")
|
|
158
|
+
@click.option("--max-string", type=int, default=40, help="Maximum length of string data")
|
|
159
|
+
@click.option("--skip-header-bytes", type=int, default=0, help="Number of bytes to skip before each packet")
|
|
160
|
+
def parse(
|
|
161
|
+
packet_file: Path,
|
|
162
|
+
definition_file: Path,
|
|
163
|
+
packet: Optional[int],
|
|
164
|
+
max_items: int,
|
|
165
|
+
max_string: int,
|
|
166
|
+
skip_header_bytes: int
|
|
167
|
+
) -> None:
|
|
168
|
+
"""Parse a packet file using the provided XTCE definition."""
|
|
169
|
+
logging.debug(f"Parsing packet file: {packet_file}")
|
|
170
|
+
logging.debug(f"Using packet definition file: {definition_file}")
|
|
171
|
+
|
|
172
|
+
with open(packet_file, "rb") as f:
|
|
173
|
+
packets = list(
|
|
174
|
+
XtcePacketDefinition.from_xtce(
|
|
175
|
+
definition_file
|
|
176
|
+
).packet_generator(
|
|
177
|
+
f,
|
|
178
|
+
skip_header_bytes=skip_header_bytes
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
if packet is not None:
|
|
183
|
+
if packet > len(packets):
|
|
184
|
+
console.print(f"Packet index {packet} out of range with only {len(packets)} packets in the file")
|
|
185
|
+
return
|
|
186
|
+
packets = packets[packet]
|
|
187
|
+
# Limit the number of packets and variables printed
|
|
188
|
+
# also limit the length of strings (binary data can be long)
|
|
189
|
+
pretty.pprint(packets, indent_guides=False, max_length=max_items, max_string=max_string)
|