Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generic packet #140

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions docs/source/benchmarking.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,11 @@ Progress: [====================]100% [Elapsed: 0:00:00.264275, Parsed 511200 byt
## Parsing Individual Values Benchmarking

In addition to the benchmarks discussed above, we also benchmarked the low level operations that make up most
of the parsing work. The parser relies on two fundamental methods: `read_as_int(nbits)` and `read_as_bytes(nbits)`,
each of which is capable of reading an arbitrary number of bits from a byte string. That is, the binary data being
parsed need not be byte aligned or even an integer number of bytes.
of the parsing work. The parser relies on two fundamental methods: `_read_from_binary_as_int(nbits)` and
`_read_from_binary_as_bytes(nbits)`, each of which is capable of reading an arbitrary number of bits from a bytes object.
That is, the binary data being parsed need not be byte aligned or even an integer number of bytes. These are not intended
to be used by external users, but are included in the benchmarks because they are fundamental to how fast we can
parse items from binary data.

```
-------------------------------------------------------------------------------------------------------- benchmark: 5 tests --------------------------------------------------------------------------------------------------------
Expand Down
10 changes: 5 additions & 5 deletions docs/source/changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@ Release notes for the `space_packet_parser` library
- Add support for creating a packet definition from Python objects and serializing it as XML.
- BUGFIX: Fix kbps calculation in packet generator for showing progress.
- Add support for string and float encoded enumerated lookup parameters.
- Add properties to extract the CCSDS Header items from the ``RawPacketData`` object directly.
e.g. ``RawPacketData.apid``
- Add properties to extract the CCSDS Header items from the ``CCSDSPacketBytes`` object directly.
e.g. ``CCSDSPacketBytes.apid``
- Add a ``create_ccsds_packet`` function that can create a CCSDS Packet
with the given header items and data. This is useful for creating
mock packets in testing and experimentation for creating debugging
streams as needed.
- Add a ``ccsds_packet_generator()`` function that iterates through raw
- Add a ``ccsds_generator()`` function that iterates through raw
bytes and yields individual CCSDS packets.
- Add continuation packet support to the XTCE parsing and packet generation.
- Add continuation packet support to the ccsds packet generation.
This adds logic to concatenate packet data fields together across successive
packets (if there was too much data to fit in a single CCSDS packet or it
was logically better to split by other teams).
- Add warnings if packets are out of sequence within a given apid.
- Add ability to remove secondary header bytes from subsequent packets.
``definition.packet_generator(data, combine_segmented_packets=True, secondary_header_bytes=4)``
``ccsds_generator(data, combine_segmented_packets=True, secondary_header_bytes=4)``
- Add a command line interface (spp) to enable quick and easy access to
some common tasks and utilities.
- Add function to directly create an `xarray.DataSet` from a packet file and XTCE definition.
Expand Down
50 changes: 46 additions & 4 deletions docs/source/users.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,58 @@ conda install -c lasp space_packet_parser
```

## Basic Usage
Usage with XTCE packet definition:

The typical workflow for parsing packets is to

1. Load a packet definition

Packet definitions are the XTCE configuration documents that describe how to parse
and extract binary chunks of data into Python variables.

```python
definition = spp.load_xtce("/path/to/xtce_definition.xml")
```

2. Iterate over binary data

You can load binary data from a file all at once, or continually read from a socket stream.
To parse individual packets, you can iterate over that binary data to yield individual
binary packet chunks one at a time. There is a built-in generator for CCSDS packets.
Other binary packet generators can be used as well if your packets follow a different
protocol from CCSDS.

```python
for binary_packet in spp.ccsds_packet_generator("/path/to/packet_file.ccsds"):
# Print out each packet's header
print(binary_packet)
```

3. Parse the binary packet data into a dictionary of parsed items

With a definition (1) and a stream of individual packets (2), one can
then parse the contents of that binary data into Python objects. The packet
definition defines a lookup structure based on ``Parameter`` names,
which are returned as a python dictionary of `{ParameterName: value}` items.

```python
packet = definition.parse_bytes(binary_packet)
# All items within the packet
print(packet)
# An individual item
print(packet["my_uint3_param"])
```

Putting this all together in an example script:

```python
from pathlib import Path
import space_packet_parser as spp

packet_file = Path('my_packets.pkts')
xtce_document = Path('my_xtce_document.xml')
packet_definition = spp.load_xtce(xtce_document)
packets = list(packet_definition.packet_generator(packet_file.open('rb')))
with open("my_packets.pkts", "rb") as packet_file:
packet_generator = spp.ccsds_packet_generator(packet_file.open('rb'))
packets = [packet_definition.parse_bytes(ccsds_packet) for ccsds_packet in packet_generator]

# You can introspect the packet definition to learn about what was parsed
# Look up a type (includes unit and encoding info)
Expand All @@ -45,7 +87,7 @@ We aim to provide examples of usage patterns. Please see the `examples` director
a specific example you want to see demonstrated, please open a GitHub Issue or Discussion for support.

## Packet Objects
The object returned from the `packet_generator` is a `CCSDSPacket` (unless you're yielding parsing
The object returned from the `packet_generator` is a `Packet` (unless you're yielding parsing
exceptions for debugging). This object subclasses a python dictionary and behaves as a dictionary. To retrieve
a parameter value from the yielded packet, you can iterate over its `items()` or you can access individual parameters
by name.
Expand Down
8 changes: 8 additions & 0 deletions space_packet_parser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
from pathlib import Path
from typing import Union

from space_packet_parser.ccsds import ccsds_generator
from space_packet_parser.common import Packet
from space_packet_parser.xtce.definitions import XtcePacketDefinition

__all__ = [
"ccsds_generator",
"Packet",
"XtcePacketDefinition",
"load_xml",
]

def load_xtce(filename: Union[str, Path]) -> XtcePacketDefinition:
"""Create an XtcePacketDefinition object from an XTCE XML file
Expand Down
Loading