CCSDS library

We created at IRAP a python library to parse CCSDS TM files.

This tools is able to parse a sequence of CCSDS TM/TC packets, from binary or hexadecimal file.

Installation notes

This library needs a python 3.6.x or greater.

Spice kernels

It uses also another library, to handle Spice Kernels files to provide correct timetags from CCSDS coarse_time and fine_time fields.

This tool depends on an external library, spiceypy that can be installed using:

pip instal spiceypy

MIB database

The CCSDS library needs also an access to Solar orbiter MIB database, to extract some useful informations.

This MIB database can be downloaded from MSSL or SOC website.

The various MIB database versions have to be installed in a directory, corresponding to MIB_DIR shell environmment variable.

export MIB_DIR=/DATA/SOLAR/MIB

And we need also to create a Linux logical link to the latest MIB available version

$ cd $MIB_DIR
$ ln -s MIB__20210330M08921PFMS001_SOL latest

CCSDS packet attributes

For each packet TM/TC packet, we can have access to the following attributes

packet_type

Packet type (O: TC, 1: TM)

pid

Identifier (95..99) for SWA instruments

categ

Category of packets

apid

APID = 16 PID + categ

seq

Sequence counter (for each apid)

service_type

PUS service type

sub_service

PUS sub type

coarse

coarse time (integer seconds)

fine

fine time (integer x 1/512s)

dt

timetag (python datetime) computed with SpiceKernels correction

size

Size in bytes of paylod

data

payload byte array

length

CCSDS length field

raw

byte array (including CCSDS headers)

sid

Packet identifier (214 for PAS calibration)

spid

Packet identifier in MID database

descr

Packet description extracted from MIB

tc_name

ZIAxxxx

tc_descr

TC description from MIB

CCSDS file reader

This function allows to parse a binary or hexadecimal CCSDS file, as a sequence of TM/TC packets.

A first example, to parse the whole file, selecting TC_ACK TM packet (service_type = 1) and display default packet attributes

from CCSDS import CCSDS_reader

filename = "20210424_000000_20210425_000000.swa-batch-tm.bin"

for packet in CCSDS_reader (filename):

        if packet.service_type == 1:
                print (packet)

Produces the following output

APID( 99, 1) TM(  1,  1) # 1359 Size =     4 2021-04-24T05:27:30.701   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  1) # 1359 Size =     4 2021-04-24T05:27:30.701   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  7) # 1360 Size =     4 2021-04-24T05:27:33.951   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  7) # 1360 Size =     4 2021-04-24T05:27:33.951   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  1) # 1361 Size =     4 2021-04-24T05:27:34.094   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  1) # 1361 Size =     4 2021-04-24T05:27:34.094   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  7) # 1362 Size =     4 2021-04-24T05:27:34.244   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  7) # 1362 Size =     4 2021-04-24T05:27:34.244   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  1) # 1363 Size =     4 2021-04-24T05:27:34.244   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  1) # 1363 Size =     4 2021-04-24T05:27:34.244   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  7) # 1364 Size =     4 2021-04-24T05:27:34.368   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  7) # 1364 Size =     4 2021-04-24T05:27:34.368   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  1) # 1365 Size =     4 2021-04-24T12:00:00.777   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  7) # 1366 Size =     4 2021-04-24T12:00:00.777   SWA_TM_CMD_EXE
APID( 99, 1) TM(  1,  1) # 1367 Size =     4 2021-04-24T12:00:10.786   SWA_TM_CMD_ACP
APID( 99, 1) TM(  1,  7) # 1368 Size =     4 2021-04-24T12:07:25.028   SWA_TM_CMD_EXE

We can modify the default behaviour, replacing the default output with:

        if packet.service_type == 1:
                print (packet.raw.hex())

Will display the whole TM packet, packet.raw, but converted to hexadecimal with the hex() function.

0e31c54f000d1001016e28166883c0a11dfccfcf
0e31c54f000d1001016e28166883c0a11dfccfcf
0e31c550000d1001076e2816688700991dfccfcf
0e31c550000d1001076e2816688700991dfccfcf
0e31c551000d100101fe2816688725611dfcc000
0e31c551000d100101fe2816688725611dfcc000
0e31c552000d100107fe281668874b981dfcc000
0e31c552000d100107fe281668874b981dfcc000
0e31c553000d100101fe281668874ba41dfcc000
0e31c553000d100101fe281668874ba41dfcc000
0e31c554000d100107fe281668876b641dfcc000
0e31c554000d100107fe281668876b641dfcc000
0e31c555000d1001016e2816c481c9e61dfccfd0
0e31c556000d1001076e2816c481ca071dfccfd0
0e31c557000d1001016e2816c48bcc4e1dfccfd1
0e31c558000d1001076e2816c63e0a2f1dfccfd1

We can also produce a binary output file, from a CCSDS hexadecimal file and select only SWA_EVENTS.

input_file = "20210424_000000_20210425_000000.swa-batch-tm.hex"

output_file = "20210424.event.bin"

with open (output_file, "wb") as output:

        for packet in CCSDS_reader (input_file):

                if packet.service_type == 5:
                        output.write (packet.raw)

TM data filtering

It is possible to filter TM/TC data using dedicated filtering functions.

Filtering SWA EVENTS packet

def     event_filter (packet):
        return packet.service_type == 5 and packet.sub_service in [1,2,3,4]

Filtering TC acknowledgements

def     ack_filter (packet):
        return packet.service_type == 1 and packet.sub_service in [7,8]

Filtering PAS calibration data

def     calib_filter (packet):
        return packet.apid == 1532 and packet.sid == 214

A more complex example:

  • the following function start to convert a string parameter to a internal python datetime.date

  • then compute start and stop variables (python datetime objects) to cover from 00:00 to 24:00

  • then creates a filtering function that embed these start/stop time interval to filter TM packets

  • finally, return the filtering function

def     make_daily_filter (str):
        """
        Return a function that filters daily TM packets
        """
        day = str_to_date (str)
        start = datetime.datetime (day.year, day.month, day.day, 0, 0, 0)
        stop  = start + datetime.timedelta (days = 1)

        def     filter (packet):
                return start <= packet.dt < stop

        return filter

Then we can use these filtering functions to select the corresponding packets.

from CCSDS import CCSDS_reader

filename = "20210424_000000_20210425_000000.swa-batch-tm.bin"

# choose one from
my_filter = event_filter
my_filter = ack_filer
my_filter = make_daily_filter ("2021-04-24")

for packet in filter (my_filter, CCSDS_reader (filename)):

        print (packet)

Merge/select data from several input files

It should be possible to merge several input files, applying some filter, to produce an unique output file.

One example of use is to merge various CCSDS TM file, corresponding to daily files downloaded from EDDS server with storage_time parameter.

We can run every day a new request to EDDS to download all SWA data with storage_time in range 00:00/24:00.

That will create daily files with all SWA packets dumped during this period.

Then, we can merge all these files and filter CCSDS packet using their timetag (corresponding to CCSDS packet generation_time), in a given daily range.

So we can reconstruct a daily generation_time TM file.

def     merge_TM (input_files):
        """
        Produce a sequence of TM packet from a list of CCSDS input files
        """
        for filename in input_files:

                for packet in CCDS_reader(filename):

                        yield packet

def     produce_TM_file (str_date, input_files):
        """
        Produce daily TM file from a list of input files
        """
        my_filter = make_daily_filter (str_date)

        output_file = "%s.generation_time.bin" % str_date

        with open (output_file, "wb") as output:

                for packet in filter (my_filter, merge_TM (input_files)):

                        output.write (packet.raw)

        print ("Generation", output_file)


if __name__ == "__main__":

        from sys import argv

        day = argv [1]

        input_files = argv [2:]


        produce_TM_file (day, input_files)

Example of use:

$ python produce_TM.py 2021-04-08 20210408.storage_time.bin 20210409.storage_time.bin 20210410.storage_time.bin 20210411.storage_time.bin ...