Merge pull request 'add support for closure handling' (#119) from mueller/cfdp-closure-requested into main

Reviewed-on: #119
This commit is contained in:
Robin Müller 2022-10-21 15:26:37 +02:00
commit c13f4a8575
5 changed files with 42 additions and 13 deletions

View File

@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager"> <component name="ProjectRunConfigurationManager">
<configuration default="false" name="CFDP Test File Small" type="PythonConfigurationType" factoryName="Python" folderName="CFDP"> <configuration default="false" name="CFDP Test File Small No Closure" type="PythonConfigurationType" factoryName="Python" folderName="CFDP">
<module name="tmtc" /> <module name="tmtc" />
<option name="INTERPRETER_OPTIONS" value="" /> <option name="INTERPRETER_OPTIONS" value="" />
<option name="PARENT_ENVS" value="true" /> <option name="PARENT_ENVS" value="true" />
@ -13,7 +13,7 @@
<option name="ADD_SOURCE_ROOTS" value="true" /> <option name="ADD_SOURCE_ROOTS" value="true" />
<EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" /> <EXTENSION ID="PythonCoverageRunConfigurationExtension" runner="coverage.py" />
<option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtcc.py" /> <option name="SCRIPT_NAME" value="$PROJECT_DIR$/tmtcc.py" />
<option name="PARAMETERS" value="cfdp filetest/cfdp_test.txt /tmp/cfdp_test.txt -d 0.2" /> <option name="PARAMETERS" value="cfdp filetest/cfdp_test.txt /tmp/cfdp_test.txt --no-closure -d 0.2" />
<option name="SHOW_COMMAND_LINE" value="false" /> <option name="SHOW_COMMAND_LINE" value="false" />
<option name="EMULATE_TERMINAL" value="false" /> <option name="EMULATE_TERMINAL" value="false" />
<option name="MODULE_MODE" value="false" /> <option name="MODULE_MODE" value="false" />

View File

@ -6,11 +6,18 @@
import enum import enum
from spacepackets import PacketType
from spacepackets.ccsds import PacketId
from spacepackets.util import UnsignedByteField from spacepackets.util import UnsignedByteField
PUS_APID = 0x65 PUS_APID = 0x65
SPACE_PACKET_IDS = (0x08 << 8 | PUS_APID,)
CFDP_APID = 0x66 CFDP_APID = 0x66
PUS_PACKET_ID = PacketId(PacketType.TM, True, PUS_APID)
CFDP_PACKET_ID = PacketId(PacketType.TM, False, CFDP_APID)
SPACE_PACKET_IDS = (
PUS_PACKET_ID.raw(),
CFDP_PACKET_ID.raw(),
)
CFDP_LOCAL_ENTITY_ID = UnsignedByteField(byte_len=2, val=1) CFDP_LOCAL_ENTITY_ID = UnsignedByteField(byte_len=2, val=1)
CFDP_REMOTE_ENTITY_ID = UnsignedByteField(byte_len=2, val=CFDP_APID) CFDP_REMOTE_ENTITY_ID = UnsignedByteField(byte_len=2, val=CFDP_APID)

2
deps/tmtccmd vendored

@ -1 +1 @@
Subproject commit 229a2b5032b0c1becd93fe37f34ddc93a6b425c4 Subproject commit f3c9501891b582f5b4c61aec5eb939d05a2e24d2

View File

@ -20,8 +20,13 @@ from pus_tm.devs.gps import handle_gps_data
from pus_tm.devs.gyros import handle_gyros_hk_data from pus_tm.devs.gyros import handle_gyros_hk_data
from tmtc.power.tm import handle_pdu_data, handle_p60_hk_data, handle_acu_hk_data from tmtc.power.tm import handle_pdu_data, handle_p60_hk_data, handle_acu_hk_data
from pus_tm.devs.syrlinks import handle_syrlinks_hk_data from pus_tm.devs.syrlinks import handle_syrlinks_hk_data
from tmtc.acs.imtq import ImtqSetIds, handle_self_test_data, handle_eng_set, \ from tmtc.acs.imtq import (
handle_calibrated_mtm_measurement, handle_raw_mtm_measurement ImtqSetIds,
handle_self_test_data,
handle_eng_set,
handle_calibrated_mtm_measurement,
handle_raw_mtm_measurement,
)
from pus_tm.defs import FsfwTmTcPrinter from pus_tm.defs import FsfwTmTcPrinter
from pus_tm.system.core import handle_core_hk_data from pus_tm.system.core import handle_core_hk_data
from pus_tm.devs.mgms import handle_mgm_hk_data from pus_tm.devs.mgms import handle_mgm_hk_data

View File

@ -7,12 +7,15 @@ from pathlib import Path
from typing import cast from typing import cast
from spacepackets import SpacePacketHeader, SpacePacket from spacepackets import SpacePacketHeader, SpacePacket
from spacepackets.ccsds import SPACE_PACKET_HEADER_SIZE
from spacepackets.cfdp import ( from spacepackets.cfdp import (
ConditionCode, ConditionCode,
ChecksumType, ChecksumType,
TransmissionMode, TransmissionMode,
PduHolder, PduHolder,
DirectiveType, DirectiveType,
PduFactory,
PduType,
) )
from tmtccmd.cfdp import CfdpUserBase, TransactionId from tmtccmd.cfdp import CfdpUserBase, TransactionId
from tmtccmd.cfdp.defs import CfdpRequestType from tmtccmd.cfdp.defs import CfdpRequestType
@ -182,11 +185,20 @@ class CfdpInCcsdsWrapper(SpecificApidHandlerBase):
self.handler = cfdp_in_ccsds_handler self.handler = cfdp_in_ccsds_handler
def handle_tm(self, packet: bytes, _user_args: any): def handle_tm(self, packet: bytes, _user_args: any):
ccsds_header_raw = packet[0:6] # Ignore the space packet header. Its only purpose is to use the same protocol and
sp_header = SpacePacketHeader.unpack(ccsds_header_raw) # have a seaprate APID for space packets. If this function is called, the APID is correct.
pdu = packet[6:] pdu = packet[SPACE_PACKET_HEADER_SIZE:]
sp = SpacePacket(sp_header, sec_header=None, user_data=pdu) pdu_base = PduFactory.from_raw(pdu)
self.handler.pass_packet(sp) if pdu_base.pdu_type == PduType.FILE_DATA:
LOGGER.info("Received File Data PDU TM")
else:
if pdu_base.directive_type == DirectiveType.FINISHED_PDU:
LOGGER.info(f"Received Finished PDU TM")
else:
LOGGER.info(
f"Received File Directive PDU with type {pdu_base.directive_type!r} TM"
)
self.handler.pass_pdu_packet(pdu_base)
class TcHandler(TcHandlerBase): class TcHandler(TcHandlerBase):
@ -207,7 +219,6 @@ class TcHandler(TcHandlerBase):
self.file_logger = file_logger self.file_logger = file_logger
self.raw_logger = raw_logger self.raw_logger = raw_logger
self.gui = gui self.gui = gui
self.cfdp_done = False
self.queue_helper = DefaultPusQueueHelper( self.queue_helper = DefaultPusQueueHelper(
queue_wrapper=None, queue_wrapper=None,
pus_apid=PUS_APID, pus_apid=PUS_APID,
@ -216,6 +227,9 @@ class TcHandler(TcHandlerBase):
) )
self.cfdp_in_ccsds_wrapper = cfdp_in_ccsds_wrapper self.cfdp_in_ccsds_wrapper = cfdp_in_ccsds_wrapper
def cfdp_done(self) -> bool:
return not self.cfdp_in_ccsds_wrapper.handler.put_request_pending()
def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper): def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper):
self.queue_helper.queue_wrapper = wrapper.queue_wrapper self.queue_helper.queue_wrapper = wrapper.queue_wrapper
if info.proc_type == TcProcedureType.DEFAULT: if info.proc_type == TcProcedureType.DEFAULT:
@ -298,7 +312,6 @@ class TcHandler(TcHandlerBase):
) )
elif info.proc_type == TcProcedureType.CFDP: elif info.proc_type == TcProcedureType.CFDP:
LOGGER.info(f"Finished CFDP queue") LOGGER.info(f"Finished CFDP queue")
self.cfdp_done = True
def setup_params() -> SetupWrapper: def setup_params() -> SetupWrapper:
@ -423,12 +436,16 @@ def main():
try: try:
while True: while True:
state = tmtc_backend.periodic_op(None) state = tmtc_backend.periodic_op(None)
tc_handler.cfdp_in_ccsds_wrapper.handler.fsm()
if state.request == BackendRequest.TERMINATION_NO_ERROR: if state.request == BackendRequest.TERMINATION_NO_ERROR:
sys.exit(0) sys.exit(0)
elif state.request == BackendRequest.DELAY_IDLE: elif state.request == BackendRequest.DELAY_IDLE:
LOGGER.info("TMTC Client in IDLE mode") LOGGER.info("TMTC Client in IDLE mode")
time.sleep(3.0) time.sleep(3.0)
elif state.request == BackendRequest.DELAY_LISTENER: elif state.request == BackendRequest.DELAY_LISTENER:
if tc_handler.cfdp_done():
LOGGER.info("CFDP transaction done, closing client")
sys.exit(0)
time.sleep(0.5) time.sleep(0.5)
elif state.request == BackendRequest.DELAY_CUSTOM: elif state.request == BackendRequest.DELAY_CUSTOM:
if state.next_delay.total_seconds() < 0.5: if state.next_delay.total_seconds() < 0.5: