Select Git revision
front-controller.php
-
Sonia Zorba authoredSonia Zorba authored
ccsds.py 3.94 KiB
#! /usr/bin/env python3
from bitstring import BitStream
import spiceypy as spice
from datetime import datetime, timedelta
from rich.console import Console
class PacketId:
def __init__(self,data):
pID = BitStream(hex=data).unpack('uint: 3, 2*bin: 1, bits: 11')
self.VersionNum = pID[0]
self.packetType = pID[1]
self.dataFieldHeaderFlag = pID[2]
self.Apid = pID[3].uint
self.Pid = pID[3][0:7].uint
self.Pcat = pID[3][7:].uint
pass
def serialize(self):
return [self.VersionNum, self.packetType, self.dataFieldHeaderFlag,
self.Apid, self.Pid, self.Pcat]
class SeqControl:
def __init__(self,data):
sq = BitStream(hex=data).unpack('bin:2,uint:14')
self.SegmentationFlag = sq[0]
self.SSC = sq[1]
def serialize(self):
return [self.SegmentationFlag, self.SSC]
class SourcePacketHeader:
def __init__(self,data):
# Read the Source Packet Header(48 bits)
# - Packet ID (16 bits)
self.packetId = PacketId(data[0:4])
# - Packet Sequence Control (16 bits)
self.sequeceControl = SeqControl(data[4:8])
"""
- Packet Length (16 bits)
In the packet is stored Packet length is an unsigned word
expressing “Number of octects contained in Packet Data Field” minus 1.
"""
self.packetLength = BitStream(hex=data[8:12]).unpack('uint:16')[0]+1
# Based on BepiColombo SIMBIO-SYS
# ref: BC-SIM-GAF-IC-002 pag. 48
def serialize(self):
return [*self.packetId.serialize(), *self.sequeceControl.serialize(), self.packetLength]
class DataFieldHeader:
def __init__(self,data,missionID,t0):
# Read The Data Field Header (80 bit)
dfhData = BitStream(hex=data).unpack('bin:1,uint:3,bin:4,3*uint:8,uint:1,uint:31,uint:16')
self.pusVersion = dfhData[1]
self.ServiceType = dfhData[3]
self.ServiceSubType = dfhData[4]
self.DestinationId = dfhData[5]
self.Synchronization = dfhData[6]
self.CorseTime = dfhData[7]
self.FineTime = dfhData[8]
self.SCET = "%s.%s" % (self.CorseTime, self.FineTime)
if self.Synchronization == 0:
self.UTCTime = self.scet2UTC(missionID,t0)
else:
self.UTCTime = '1970-01-01T00:00:00.00000Z'
pass
def serialize(self):
return [self.pusVersion, self.ServiceType, self.ServiceSubType,
self.DestinationId, self.SCET, self.UTCTime]
def scet2UTC(self,missionID,t0):
if t0 == None:
et = spice.scs2e(missionID, "{}.{}".format(self.CorseTime, self.FineTime))
ScTime = spice.et2utc(et, 'ISOC', 5)
else:
dateFormat = "%Y-%m-%dT%H:%M:%S.%f"
dt=datetime.strptime(t0,dateFormat)
sc = self.CorseTime + self.FineTime*(2**(-16))
f=dt+timedelta(seconds=sc)
ScTime=f.strftime(dateFormat)
return ScTime+'Z'
class PackeDataField:
def __init__(self,data, missionID,t0):
# Data Field Header
self.DFHeader = DataFieldHeader(data[0:20],missionID,t0)
# Data
self.Data = data[20:]
pass
class CCSDS:
""" Reader for the CCSDS header """
def __init__(self, missionID, data,console:Console=None,t0= None):
if type(missionID) is str:
if missionID.lower() == 'bepicolombo':
missionID=-121
else:
if t0 == None:
print("WARNING: the Mission name is not valid. time converte setted to 1970-01-01 00:00:00")
t0 = "1970-01-01T00:00:00"
# Source Packet Header
self.SPH = SourcePacketHeader(data[0:12])
# Packet Data Field
self.PDF = PackeDataField(data[12:],missionID,t0)
self.APID = self.SPH.packetId.Apid
self.Service=self.PDF.DFHeader.ServiceType
self.subService=self.PDF.DFHeader.ServiceSubType
self.Data=self.PDF.Data