def readNCTRStmFrameHeader(fd): """creates a NCTRS TM data unit according to the NCTRS_TM_DU_VERSION""" # the function raises an exception when the read fails tmDUtype = getTMdataUnitType() if s_tmDUtype == GRND.NCTRSDU.TM_V0_ERT_FORMAT: tmDuHeaderByteSize = GRND.NCTRSDU.TM_DU_V0_HEADER_BYTE_SIZE elif s_tmDUtype == GRND.NCTRSDU.TM_V1_CDS1_ERT_FORMAT: tmDuHeaderByteSize = GRND.NCTRSDU.TM_DU_V1_CDS1_HEADER_BYTE_SIZE elif s_tmDUtype == GRND.NCTRSDU.TM_V1_CDS2_ERT_FORMAT: tmDuHeaderByteSize = GRND.NCTRSDU.TM_DU_V1_CDS2_HEADER_BYTE_SIZE elif s_tmDUtype == GRND.NCTRSDU.TM_V1_CDS3_ERT_FORMAT: tmDuHeaderByteSize = GRND.NCTRSDU.TM_DU_V1_CDS3_HEADER_BYTE_SIZE else: raise Error("Invalid s_tmDUtype " + str(s_tmDUtype)) # read the TM data unit header if type(fd) == SOCKET_TYPE: tmDuHeader = fd.recv(tmDuHeaderByteSize) else: tmDuHeader = fd.read(tmDuHeaderByteSize) # consistency check tmDuHeaderLen = len(tmDuHeader) if tmDuHeaderLen == 0: if type(fd) == SOCKET_TYPE: raise Error("empty data read") else: # end of file raise Error("") if tmDuHeaderLen != tmDuHeaderByteSize: raise Error("Read of TM DU header failed: invalid size: " + str(tmDuHeaderLen)) return tmDuHeader
def readNCTRSframe(fd): """reads one NCTRS frame from fd, raise execption when there is an error""" # read the TM data unit header try: tmDuHeader = readNCTRStmFrameHeader(fd) except Exception as ex: raise Error(str(ex)) tmDu = createTMdataUnit(tmDuHeader) # consistency check packetSize = tmDu.packetSize remainingSizeExpected = packetSize - len(tmDuHeader) if remainingSizeExpected <= 0: raise Error( "Read of TM DU header failed: invalid packet size field: " + str(remainingSizeExpected)) # read the remaining bytes for the TM data unit try: if type(fd) == SOCKET_TYPE: tmRemaining = fd.recv(remainingSizeExpected) else: tmRemaining = fd.read(remainingSizeExpected) except Exception as ex: raise Error("Read of remaining TM DU failed: " + str(ex)) # consistency check remainingSizeRead = len(tmRemaining) if remainingSizeRead != remainingSizeExpected: raise Error( "Read of remaining TM DU failed: invalid remaining size: " + str(remainingSizeRead)) # TM frame tmDu.append(tmRemaining) return tmDu
def decode(self, du, bitPos): """ decodes the contens from a data unit, returns the new position overloaded from Entity """ paramType = self.getParamType() bitWidth = self.getBitWidth() value = self.value nextBitPos = bitPos + bitWidth # process bit oriented parameter types if paramType == UTIL.DU.BITS: self.value = du.getBits(bitPos, bitWidth) return nextBitPos if paramType == UTIL.DU.SBITS: self.value = du.getSBits(bitPos, bitWidth) return nextBitPos # process byte oriented parameter types if (bitPos % 8) != 0: raise Error("parameter " + self.getParamName() + " position is not byte aligned") if (bitWidth % 8) != 0: raise Error("parameter " + self.getParamName() + " size is not byte aligned") bytePos = bitPos >> 3 byteWidth = bitWidth >> 3 defType = type(self.paramDef) if defType == VariableParamDef: # for variable length parameters: encode the length bytes first lengthBytes = self.paramDef.lengthBytes byteLength = du.getUnsigned(bytePos, lengthBytes) bytePos += lengthBytes byteWidth = byteLength nextBytePos = bytePos + byteWidth nextBitPos = nextBytePos << 3 if paramType == UTIL.DU.BYTES: self.value = du.getBytes(bytePos, byteWidth) return nextBitPos if paramType == UTIL.DU.UNSIGNED: self.value = du.getUnsigned(bytePos, byteWidth) return nextBitPos if paramType == UTIL.DU.SIGNED: self.value = du.getSigned(bytePos, byteWidth) return nextBitPos if paramType == UTIL.DU.FLOAT: self.value = du.getFloat(bytePos, byteWidth) return nextBitPos if paramType == UTIL.DU.TIME: timeFormat = self.paramDef.timeFormat self.value = du.getTime(bytePos, timeFormat) return nextBitPos if paramType == UTIL.DU.STRING: self.value = du.getString(bytePos, byteWidth) return nextBitPos raise Error("unexpected paramType for parameter " + self.getParamName())
def encode(self, du, bitPos): """ encodes the contens into a data unit, returns the new position overloaded from Entity """ paramType = self.getParamType() bitWidth = self.getBitWidth() value = self.value nextBitPos = bitPos + bitWidth # process bit oriented parameter types if paramType == UTIL.DU.BITS: du.setBits(bitPos, bitWidth, value) return nextBitPos if paramType == UTIL.DU.SBITS: du.setSBits(bitPos, bitWidth, value) return nextBitPos # process byte oriented parameter types if (bitPos % 8) != 0: raise Error("parameter " + self.getParamName() + " position is not byte aligned") if (bitWidth % 8) != 0: raise Error("parameter " + self.getParamName() + " size is not byte aligned") bytePos = bitPos >> 3 byteWidth = bitWidth >> 3 defType = type(self.paramDef) if defType == VariableParamDef: # for variable length parameters: encode the length bytes first # for TCs it is also allowed to have no length byte (e.g. CNC protocol) lengthBytes = self.paramDef.lengthBytes if lengthBytes > 0: byteLength = len(value) du.setUnsigned(bytePos, lengthBytes, byteLength) bytePos += lengthBytes byteWidth = byteLength if paramType == UTIL.DU.BYTES: du.setBytes(bytePos, byteWidth, value) return nextBitPos if paramType == UTIL.DU.UNSIGNED: du.setUnsigned(bytePos, byteWidth, value) return nextBitPos if paramType == UTIL.DU.SIGNED: du.setSigned(bytePos, byteWidth, value) return nextBitPos if paramType == UTIL.DU.FLOAT: du.setFloat(bytePos, byteWidth, value) return nextBitPos if paramType == UTIL.DU.TIME: timeFormat = self.paramDef.timeFormat du.setTime(bytePos, timeFormat, value) return nextBitPos if paramType == UTIL.DU.STRING: du.setString(bytePos, byteWidth, value) return nextBitPos raise Error("unexpected paramType for parameter " + self.getParamName())
def getTMframe(self, tmDataPacket): """ creates a Transfer TM frame with embedded TM packet implementation of LINK.IF.TMframeGenerator.getTMframe """ # create the idle packet reservedFrameDataSize = CCSDS.FRAME.TM_FRAME_PRIMARY_HEADER_BYTE_SIZE + \ len(tmDataPacket) + \ CCSDS.FRAME.CLCW_BYTE_SIZE enableSecondaryHeader = (self.frameDefaults.secondaryHeaderFlag == 1) if enableSecondaryHeader: reservedFrameDataSize += CCSDS.FRAME.TM_FRAME_SECONDARY_HEADER_BYTE_SIZE if CCSDS.FRAME.CRC_CHECK: reservedFrameDataSize += 2 remainingFrameDataSize = self.frameDefaults.transferFrameSize - \ reservedFrameDataSize if remainingFrameDataSize < 0: # TM packet does not fit into the frame # ---> an exception must be raisedas long as # TM packet segmentation is not implemeted raise Error("TM packet with SPID " + str(spid) + " does not fit into transfer frame") createIdlePacket = (remainingFrameDataSize != 0) if createIdlePacket: tmIdlePacket = \ SPACE.IF.s_tmPacketGenerator.getIdlePacket(remainingFrameDataSize) # create the transfer frame tmFrame = CCSDS.FRAME.TMframe( enableSecondaryHeader=enableSecondaryHeader) tmFrame.versionNumber = self.frameDefaults.versionNumber tmFrame.spacecraftId = self.frameDefaults.spacecraftId tmFrame.virtualChannelId = self.frameDefaults.virtualChannelId tmFrame.operationalControlField = self.frameDefaults.operationalControlField tmFrame.masterChannelFrameCount = self.masterChannelFrameCount self.masterChannelFrameCount += 1 self.masterChannelFrameCount %= 256 tmFrame.virtualChannelFCountLow = self.virtualChannelFrameCount self.virtualChannelFrameCount += 1 self.virtualChannelFrameCount %= 256 tmFrame.secondaryHeaderFlag = self.frameDefaults.secondaryHeaderFlag tmFrame.synchronisationFlag = self.frameDefaults.synchronisationFlag tmFrame.packetOrderFlag = self.frameDefaults.packetOrderFlag tmFrame.segmentLengthId = self.frameDefaults.segmentLengthId tmFrame.firstHeaderPointer = self.frameDefaults.firstHeaderPointer if enableSecondaryHeader: tmFrame.secondaryHeaderVersionNr = self.frameDefaults.secondaryHeaderVersionNr tmFrame.secondaryHeaderSize = self.frameDefaults.secondaryHeaderSize tmFrame.virtualChannelFCountHigh = self.frameDefaults.virtualChannelFCountHigh tmFrame.append(tmDataPacket.getBufferString()) if createIdlePacket: tmFrame.append(tmIdlePacket.getBufferString()) tmFrame.append(self.clcw.getBufferString()) if CCSDS.FRAME.CRC_CHECK: tmFrame.append("\0" * CCSDS.DU.CRC_BYTE_SIZE) tmFrame.setChecksum() return tmFrame
def addPacketIDrecord(self, apid, serviceType, serviceSubType, pi1, pi2, packetID): """adds a record for packet identification""" # note: this table is also relevant for non-pus packets - in this case the # serviceType and serviceSubType fields must be None key = (apid, serviceType, serviceSubType, pi1, pi2) if key in self.keyFieldIDs: raise Error("key " + str(key) + " is already defined in packet ID map") value = packetID self.packetIDs[key] = value
def fillSlotInTree(self, parentNodeID, slot): """fills a Slot into the tree""" slotName = slot.getSlotName() child = slot.child childType = type(child) if childType == PUS.VP.Param: self.fillParamInTree(parentNodeID, slotName, param=child) elif childType == PUS.VP.List: self.fillListInTree(parentNodeID, slotName, lst=child) else: raise Error("child type " + childType + " not supported")
def createFileHandler(self, socket, handler): """register a file descriptor handler""" # special implementation for faked thread, delegate to parent task global s_parentTask if self.taskType == FAKETHREAD: if s_parentTask: s_parentTask.createFileHandler(socket, handler) else: raise Error("missing parent task for file handler creation") return # normal implementation self.readDictionary[socket] = handler
def __init__(self, slotDef=""): self.slotDef = slotDef # create the slot child depending on the slot child type in the definition childDef = slotDef.childDef childType = type(childDef) if childType == SimpleParamDef or childType == VariableParamDef or \ childType == TimeParamDef: self.child = Param(paramDef=childDef) elif childType == ListDef: self.child = List(listDef=childDef) else: raise Error("child type " + str(childType) + " not supported")
def decode(self, du, bitPos): """ decodes the contens from a data unit, returns the new position overloaded from Entity """ # decode the length lengthValueBitPos = bitPos if (lengthValueBitPos % 8) != 0: raise Error("parameter " + self.getLenParamName() + " position is not byte aligned") lengthValueBitWidth = self.listDef.lenParamDef.bitWidth if (lengthValueBitWidth % 8) != 0: raise Error("parameter " + self.getLenParamName() + " size is not byte aligned") lengthValueBytePos = lengthValueBitPos >> 3 lengthValueByteWidth = lengthValueBitWidth >> 3 lengthValue = du.getUnsigned(lengthValueBytePos, lengthValueByteWidth) bitPos += lengthValueBitWidth # decode the list entries self.setLen(lengthValue) for entry in self.entries: bitPos = entry.decode(du, bitPos) return bitPos
def addKeyFieldRecord(self, apid, serviceType, serviceSubType, pi1bitPos, pi1bitSize, pi2bitPos, pi2bitSize): """adds a record for key field identification""" # note: apid can be None - in this case all packets with the same # serviceType and serviceSubType are matching such an entry # note: this table is also relevant for non-pus packets - in this case the # serviceType and serviceSubType fields must be None # note: pi1bitPos, pi1bitSize and/or pi2bitPos, pi2bitSize can be None - in # this case pi1 and/or pi2 are not used for the packet identification # note: when pi1bitPos, pi1bitSize and/or pi2bitPos, pi2bitSize are None, # then the related enytry for the packet identification must contain # as well None in the pi1 and/or pi2 field key = (apid, serviceType, serviceSubType) value = (pi1bitPos, pi1bitSize, pi2bitPos, pi2bitSize) if key in self.keyFieldIDs: previousValue = self.keyFieldIDs[key] if previousValue != value: raise Error("key " + str(key) + " is already defined in key field ID map") else: self.keyFieldIDs[key] = value
def createTimeHandler(self, ms, handler): """register a time handler""" # special implementation for faked thread, delegate to parent task global s_parentTask if self.taskType == FAKETHREAD: if s_parentTask: s_parentTask.createTimeHandler(ms, handler) else: raise Error("missing parent task for time handler creation") return # normal implementation: create new timer event and order it into # existing ordered timer events timeAbsoluteSec = time.time() timeoutAbsoluteSec = timeAbsoluteSec + (ms / 1000.0) timerEvent = (timeoutAbsoluteSec, handler) i = 0 while i < len(self.timerEvents): nextTimeout = self.timerEvents[i][0] if nextTimeout > timeoutAbsoluteSec: break i += 1 self.timerEvents.insert(i, timerEvent)
def getIdlePacket(self, packetSize): """ creates an idle packet for filling space in a parent container (e.g. a CCSDS TM frame): implementation of SPACE.IF.TMpacketGenerator.getIdlePacket """ # the idle packet is a TM packet without a secondary header (CCSDS) # but with a CRC (if an application expects a CRC) if packetSize < (CCSDS.PACKET.PRIMARY_HEADER_BYTE_SIZE + CCSDS.DU.CRC_BYTE_SIZE): raise Error("no sufficient space for idle packet") applicationProcessId = self.packetDefaults.idlePacketAPID idlePacket = self.getTMpacketHelper(packetSize, applicationProcessId) # re-calculate the sequence counter (maintained per APID) if applicationProcessId in self.sequenceCounters: sequenceCounter = (self.sequenceCounters[applicationProcessId] + 1) % 16384 else: sequenceCounter = 0 idlePacket.sequenceControlCount = sequenceCounter self.sequenceCounters[applicationProcessId] = sequenceCounter # re-calculate the CRC idlePacket.setChecksum() return idlePacket
def getDataFieldHeaderFlag(binaryString, startPos=0): """returns the data field header flag field""" if (len(binaryString) - startPos) < PRIMARY_HEADER_BYTE_SIZE: raise Error("packet header is too small") return ((binaryString[startPos + 0] & 0x08) > 0)
def getApplicationProcessId(binaryString, startPos=0): """returns the application process id field""" if (len(binaryString) - startPos) < PRIMARY_HEADER_BYTE_SIZE: raise Error("packet header is too small") return (((binaryString[startPos + 0] * 256) + binaryString[startPos + 1]) & 0x07FF)
def getPacketLength(binaryString, startPos=0): """returns the packet length field""" if (len(binaryString) - startPos) < PRIMARY_HEADER_BYTE_SIZE: raise Error("packet header is too small") return ((binaryString[startPos + 4] * 256) + binaryString[startPos + 5])
def getTCpacket(self, pktName, tcStruct, reuse=True): """ creates a CCSDS TC packet with optional parameter values: implementation of MC.IF.TCpacketGenerator.getTCpacket """ # fetch the packet definition tcPktDef = SPACE.IF.s_definitions.getTCpktDefByName(pktName) if tcPktDef == None: raise Error("invalid packet name for packet creation: " + pktName) binarySize = tcPktDef.pktSPsize applicationProcessId = tcPktDef.pktAPID if reuse and pktName in self.packetCache: # reuse a packet with the same definition from the cache packet = self.packetCache[pktName] packet.setLen(binarySize) packet.setPacketLength() else: # create the TC packet if tcPktDef.pktHasDFhdr: # PUS packet serviceType = tcPktDef.pktType serviceSubType = tcPktDef.pktSType packet = self.getTCpacketHelper(binarySize, applicationProcessId, serviceType, serviceSubType) else: # CCSDS packet packet = self.getTCpacketHelper(binarySize, applicationProcessId) self.packetCache[pktName] = packet # apply the segmentationFlags packet.segmentationFlags = CCSDS.PACKET.UNSEGMENTED ### apply the encoded tcStruct ### if not tcStruct: # create an empty tcStruct with the correct structure tcStructDef = tcPktDef.tcStructDef if tcStructDef == None: raise Error("invalid packet structure for packet creation: " + pktName) tcStruct = PUS.VP.Struct(tcStructDef) #-- find the correct position for the data structBytePos = CCSDS.PACKET.PRIMARY_HEADER_BYTE_SIZE if tcPktDef.pktHasDFhdr: # PUS packet structBytePos += tcPktDef.pktDFHsize structBitPos = structBytePos << 3 structEndBitPos = structBitPos + tcStruct.getBitWidth() structEndBytePos = (structEndBitPos + 7) >> 3 #-- re-size the packet to exactly fit tcPacketSize = structEndBytePos if tcPktDef.pktCheck: tcPacketSize += CCSDS.DU.CRC_BYTE_SIZE packet.setLen(tcPacketSize) packet.setPacketLength() #-- encode the struct tcStruct.encode(packet, structBitPos) # re-calculate the sequence counter (maintained per APID) if applicationProcessId in self.sequenceCounters: sequenceCounter = (self.sequenceCounters[applicationProcessId] + 1) % 16384 else: sequenceCounter = 0 packet.sequenceControlCount = sequenceCounter self.sequenceCounters[applicationProcessId] = sequenceCounter # re-calculate the CRC if tcPktDef.pktCheck: packet.setChecksum() return packet
def getVersionNumber(binaryString, startPos=0): """returns the version number field""" if (len(binaryString) - startPos) < PRIMARY_HEADER_BYTE_SIZE: raise Error("packet header is too small") return ((binaryString[startPos + 0] & 0xE0) >> 5)
def getTMpacket(self, spid, parameterValues, tmStruct, dataField=None, segmentationFlags=CCSDS.PACKET.UNSEGMENTED, obtUTC=None, reuse=True): """ creates a CCSDS TM packet with optional parameter values: implementation of SPACE.IF.TMpacketGenerator.getTMpacket """ # fetch the packet definition tmPktDef = SUPP.IF.s_definitions.getTMpktDefBySPID(spid) if tmPktDef == None: raise Error("invalid SPID for packet creation: " + str(spid)) binarySize = tmPktDef.pktSPsize applicationProcessId = tmPktDef.pktAPID if reuse and spid in self.packetCache: # reuse a packet with the same definition from the cache packet = self.packetCache[spid] packet.setLen(binarySize) packet.setPacketLength() else: # create the TM packet if tmPktDef.pktHasDFhdr: # PUS packet serviceType = tmPktDef.pktType serviceSubType = tmPktDef.pktSType packet = self.getTMpacketHelper(binarySize, applicationProcessId, serviceType, serviceSubType) # initialise PI1 and PI2 if configured if tmPktDef.pktPI1val != None: pi1BitPos = tmPktDef.pktPI1off * 8 pi1BitWidth = tmPktDef.pktPI1wid pi1Value = tmPktDef.pktPI1val packet.setBits(pi1BitPos, pi1BitWidth, pi1Value) if tmPktDef.pktPI2val != None: pi2BitPos = tmPktDef.pktPI2off * 8 pi2BitWidth = tmPktDef.pktPI2wid pi2Value = tmPktDef.pktPI2val packet.setBits(pi2BitPos, pi2BitWidth, pi2Value) else: # CCSDS packet packet = self.getTMpacketHelper(binarySize, applicationProcessId) self.packetCache[spid] = packet # apply the segmentationFlags packet.segmentationFlags = segmentationFlags # apply the datafield if dataField: dataFieldOffset, dataFieldData = dataField minExpectedPacketSize = dataFieldOffset + len(dataFieldData) if tmPktDef.pktCheck: minExpectedPacketSize += CCSDS.DU.CRC_BYTE_SIZE # re-size the packet if needed if len(packet) < minExpectedPacketSize: binarySize = minExpectedPacketSize packet.setLen(binarySize) packet.setPacketLength() packet.setBytes(dataFieldOffset, len(dataFieldData), dataFieldData) ### apply the encoded tmStruct ### if tmStruct != None: #-- find the correct position for the data structBytePos = CCSDS.PACKET.PRIMARY_HEADER_BYTE_SIZE if tmPktDef.pktHasDFhdr: # PUS packet structBytePos += tmPktDef.pktDFHsize structBitPos = structBytePos << 3 structEndBitPos = structBitPos + tmStruct.getBitWidth() structEndBytePos = (structEndBitPos + 7) >> 3 #-- re-size the packet to exactly fit tmPacketSize = structEndBytePos if tmPktDef.pktCheck: tmPacketSize += CCSDS.DU.CRC_BYTE_SIZE binarySize = max(binarySize, tmPacketSize) packet.setLen(binarySize) packet.setPacketLength() #-- encode the struct tmStruct.encode(packet, structBitPos) # apply the parameters for paramNameValue in parameterValues: paramName, paramValue = paramNameValue # special handling for PUS service 1 parameters for TC acknowledgement if paramName == "PUS_TYPE1_APID": PUS.SERVICES.service1_setTCackAPID(packet, int(paramValue)) continue if paramName == "PUS_TYPE1_SSC": PUS.SERVICES.service1_setTCackSSC(packet, int(paramValue)) continue # search the definition of the parameter (TMparamExtraction) paramExtraction = tmPktDef.getParamExtraction(paramName) if paramExtraction == None: LOG_WARNING( "packet with SPID " + str(spid) + " does not have a parameter " + paramName, "SPACE") else: # apply the parameter value bitPos = paramExtraction.bitPos bitLength = paramExtraction.bitWidth valueType = paramExtraction.valueType if valueType == UTIL.DU.BITS: packet.setBits(bitPos, bitLength, paramValue) elif valueType == UTIL.DU.SBITS: packet.setSBits(bitPos, bitLength, paramValue) else: bytePos = bitPos // 8 byteLength = bitLength // 8 if valueType == UTIL.DU.UNSIGNED: packet.setUnsigned(bytePos, byteLength, paramValue) elif valueType == UTIL.DU.SIGNED: bytePos = bitPos // 8 byteLength = bitLength // 8 packet.setSigned(bytePos, byteLength, paramValue) elif valueType == UTIL.DU.FLOAT: bytePos = bitPos // 8 byteLength = bitLength // 8 packet.setFloat(bytePos, byteLength, paramValue) else: # TIME and other types are passed as string # TODO: use specific encodings bytePos = bitPos // 8 byteLength = bitLength // 8 packet.setString(bytePos, byteLength, paramValue) # re-calculate the time stamp if tmPktDef.pktHasDFhdr and self.packetDefaults.hasTmTT: if obtUTC == None: obtUTC = UTIL.TIME.getActualTime() obtTime = UTIL.TCO.correlateToOBTmissionEpoch(obtUTC) packet.setTimeTag(obtTime) # re-calculate the sequence counter (maintained per APID) if applicationProcessId in self.sequenceCounters: sequenceCounter = (self.sequenceCounters[applicationProcessId] + 1) % 16384 else: sequenceCounter = 0 packet.sequenceControlCount = sequenceCounter self.sequenceCounters[applicationProcessId] = sequenceCounter # re-calculate the CRC if tmPktDef.pktCheck: packet.setChecksum() return packet
def getTMpacket(self, spid, parameterValues=[], dataField=None, segmentationFlags=CCSDS.PACKET.UNSEGMENTED, obtUTC=None, reuse=True): """ creates a CCSDS TM packet with optional parameter values: implementation of SPACE.IF.TMpacketGenerator.getTMpacket """ # fetch the packet definition tmPktDef = SPACE.IF.s_definitions.getTMpktDefBySPID(spid) if tmPktDef == None: raise Error("invalid SPID for packet creation: " + str(spid)) binarySize = tmPktDef.pktSPsize applicationProcessId = tmPktDef.pktAPID if reuse and spid in self.packetCache: # reuse a packet with the same definition from the cache packet = self.packetCache[spid] packet.setLen(binarySize) packet.setPacketLength() else: # create the TM packet if tmPktDef.pktHasDFhdr: # PUS packet serviceType = tmPktDef.pktType serviceSubType = tmPktDef.pktSType packet = self.getTMpacketHelper(binarySize, applicationProcessId, serviceType, serviceSubType) # initialise PI1 and PI2 if configured if tmPktDef.pktPI1val != None: pi1BitPos = tmPktDef.pktPI1off * 8 pi1BitWidth = tmPktDef.pktPI1wid pi1Value = tmPktDef.pktPI1val packet.setBits(pi1BitPos, pi1BitWidth, pi1Value) if tmPktDef.pktPI2val != None: pi2BitPos = tmPktDef.pktPI2off * 8 pi2BitWidth = tmPktDef.pktPI2wid pi2Value = tmPktDef.pktPI2val packet.setBits(pi2BitPos, pi2BitWidth, pi2Value) else: # CCSDS packet packet = self.getTMpacketHelper(binarySize, applicationProcessId) self.packetCache[spid] = packet # apply the segmentationFlags packet.segmentationFlags = segmentationFlags # apply the datafield if dataField: dataFieldOffset, dataFieldData = dataField minExpectedPacketSize = dataFieldOffset + len(dataFieldData) if tmPktDef.pktCheck: minExpectedPacketSize += 2 # re-size the packet if needed if len(packet) < minExpectedPacketSize: packet.setLen(minExpectedPacketSize) packet.setPacketLength() packet.setBytes(dataFieldOffset, len(dataFieldData), dataFieldData) # apply the parameters for paramNameValue in parameterValues: paramName, paramValue = paramNameValue # special handling for PUS service 1 parameters for TC acknowledgement if paramName == "PUS_TYPE1_APID": PUS.SERVICES.service1_setTCackAPID(packet, int(paramValue)) continue if paramName == "PUS_TYPE1_SSC": PUS.SERVICES.service1_setTCackSSC(packet, int(paramValue)) continue # search the definition of the parameter (TMparamExtraction) paramExtraction = tmPktDef.getParamExtraction(paramName) if paramExtraction == None: LOG_WARNING( "packet with SPID " + str(spid) + " does not have a parameter " + paramName, "SPACE") else: # apply the parameter value bitPos = paramExtraction.bitPos bitLength = paramExtraction.bitWidth isInteger = paramExtraction.isInteger if isInteger: packet.setBits(bitPos, bitLength, paramValue) else: bytePos = bitPos / 8 byteLength = bitLength / 8 packet.setString(bytePos, byteLength, paramValue) # re-calculate the time stamp if tmPktDef.pktHasDFhdr and self.hasTmTT: if obtUTC == None: obtUTC = UTIL.TIME.getActualTime() obtTime = UTIL.TCO.correlateToOBTmissionEpoch(obtUTC) packet.setTimeTag(obtTime) # re-calculate the sequence counter (maintained per APID) if applicationProcessId in self.sequenceCounters: sequenceCounter = (self.sequenceCounters[applicationProcessId] + 1) % 16384 else: sequenceCounter = 0 packet.sequenceControlCount = sequenceCounter self.sequenceCounters[applicationProcessId] = sequenceCounter # re-calculate the CRC if tmPktDef.pktCheck: packet.setChecksum() return packet