diff --git a/deps/spacepackets b/deps/spacepackets index 66fa442..84f1af2 160000 --- a/deps/spacepackets +++ b/deps/spacepackets @@ -1 +1 @@ -Subproject commit 66fa442c837f00ce16412d5b730b9f5d7f375a16 +Subproject commit 84f1af27d4b15dde47b9944e0e533dff6fd8b1a4 diff --git a/tmtcc.py b/tmtcc.py index c7d3206..de0e789 100755 --- a/tmtcc.py +++ b/tmtcc.py @@ -4,13 +4,30 @@ import sys import time import traceback from pathlib import Path +from typing import cast from spacepackets import SpacePacketHeader, SpacePacket -from spacepackets.cfdp import ConditionCode, ChecksumType, TransmissionMode +from spacepackets.cfdp import ( + ConditionCode, + ChecksumType, + TransmissionMode, + PduHolder, + DirectiveType, +) from tmtccmd.cfdp import CfdpUserBase, TransactionId +from tmtccmd.cfdp.defs import CfdpRequestType from tmtccmd.cfdp.handler import CfdpInCcsdsHandler -from tmtccmd.cfdp.mib import DefaultFaultHandlerBase, LocalEntityCfg, IndicationCfg, RemoteEntityCfg -from tmtccmd.cfdp.user import TransactionFinishedParams, MetadataRecvParams, FileSegmentRecvdParams +from tmtccmd.cfdp.mib import ( + DefaultFaultHandlerBase, + LocalEntityCfg, + IndicationCfg, + RemoteEntityCfg, +) +from tmtccmd.cfdp.user import ( + TransactionFinishedParams, + MetadataRecvParams, + FileSegmentRecvdParams, +) from tmtccmd.tc.handler import SendCbParams try: @@ -54,11 +71,23 @@ from tmtccmd.tc import ( TcQueueEntryType, DefaultPusQueueHelper, ) -from tmtccmd.config import default_json_path, SetupWrapper, params_to_procedure_conversion -from tmtccmd.config.args import SetupParams, PreArgsParsingWrapper, \ - ProcedureParamsWrapper +from tmtccmd.config import ( + default_json_path, + SetupWrapper, + params_to_procedure_conversion, +) +from tmtccmd.config.args import ( + SetupParams, + PreArgsParsingWrapper, + ProcedureParamsWrapper, +) from config import __version__ -from config.definitions import PUS_APID, CFDP_APID, CFDP_LOCAL_ENTITY_ID, CFDP_REMOTE_ENTITY_ID +from config.definitions import ( + PUS_APID, + CFDP_APID, + CFDP_LOCAL_ENTITY_ID, + CFDP_REMOTE_ENTITY_ID, +) from config.hook import EiveHookObject from pus_tm.factory_hook import pus_factory_hook from pus_tc.procedure_packer import handle_default_procedure @@ -164,28 +193,35 @@ class TcHandler(TcHandlerBase): def __init__( self, seq_count_provider: FileSeqCountProvider, + cfdp_in_ccsds_wrapper: CfdpInCcsdsWrapper, pus_verificator: PusVerificator, file_logger: logging.Logger, raw_logger: RawTmtcTimedLogWrapper, gui: bool, ): super().__init__() + self.cfdp_handler_started = False + self.cfdp_dest_id = CFDP_REMOTE_ENTITY_ID self.seq_count_provider = seq_count_provider self.pus_verificator = pus_verificator self.file_logger = file_logger self.raw_logger = raw_logger self.gui = gui + self.cfdp_done = False self.queue_helper = DefaultPusQueueHelper( queue_wrapper=None, pus_apid=PUS_APID, seq_cnt_provider=seq_count_provider, pus_verificator=pus_verificator, ) + self.cfdp_in_ccsds_wrapper = cfdp_in_ccsds_wrapper def feed_cb(self, info: ProcedureWrapper, wrapper: FeedWrapper): self.queue_helper.queue_wrapper = wrapper.queue_wrapper if info.proc_type == TcProcedureType.DEFAULT: handle_default_procedure(self, info.to_def_procedure(), self.queue_helper) + elif info.proc_type == TcProcedureType.CFDP: + self.handle_cfdp_procedure(info) def send_cb(self, send_params: SendCbParams): entry_helper = send_params.entry @@ -206,17 +242,63 @@ class TcHandler(TcHandlerBase): f"{get_current_time_string(True)}: {tc_info_string}" ) send_params.com_if.send(raw_tc) + elif entry_helper.entry_type == TcQueueEntryType.CCSDS_TC: + cfdp_packet_in_ccsds = entry_helper.to_space_packet_entry() + send_params.com_if.send(cfdp_packet_in_ccsds.space_packet.pack()) elif entry_helper.entry_type == TcQueueEntryType.LOG: log_entry = entry_helper.to_log_entry() LOGGER.info(log_entry.log_str) self.file_logger.info(log_entry.log_str) + def handle_cfdp_procedure(self, info: ProcedureWrapper): + cfdp_procedure = info.to_cfdp_procedure() + if cfdp_procedure.cfdp_request_type == CfdpRequestType.PUT: + if ( + not self.cfdp_in_ccsds_wrapper.handler.put_request_pending() + and not self.cfdp_handler_started + ): + put_req = cfdp_procedure.request_wrapper.to_put_request() + put_req.cfg.destination_id = self.cfdp_dest_id + LOGGER.info( + f"CFDP: Starting file put request with parameters:\n{put_req}" + ) + self.cfdp_in_ccsds_wrapper.handler.cfdp_handler.put_request(put_req) + self.cfdp_handler_started = True + + for source_pair, dest_pair in self.cfdp_in_ccsds_wrapper.handler: + pdu, sp = source_pair + pdu = cast(PduHolder, pdu) + if pdu.is_file_directive: + if pdu.pdu_directive_type == DirectiveType.METADATA_PDU: + metadata = pdu.to_metadata_pdu() + self.queue_helper.add_log_cmd( + f"CFDP Source: Sending Metadata PDU for file with size " + f"{metadata.file_size}" + ) + elif pdu.pdu_directive_type == DirectiveType.EOF_PDU: + self.queue_helper.add_log_cmd( + f"CFDP Source: Sending EOF PDU" + ) + else: + fd_pdu = pdu.to_file_data_pdu() + self.queue_helper.add_log_cmd( + f"CFDP Source: Sending File Data PDU for segment at offset " + f"{fd_pdu.offset} with length {len(fd_pdu.file_data)}" + ) + self.queue_helper.add_ccsds_tc(sp) + self.cfdp_in_ccsds_wrapper.handler.confirm_source_packet_sent() + self.cfdp_in_ccsds_wrapper.handler.source_handler.state_machine() + def queue_finished_cb(self, info: ProcedureWrapper): - if info is not None and info.proc_type == TcQueueEntryType.PUS_TC: - def_proc = info.to_def_procedure() - LOGGER.info( - f"Finished queue for service {def_proc.service} and op code {def_proc.op_code}" - ) + if info is not None: + if info.proc_type == TcQueueEntryType.PUS_TC: + def_proc = info.to_def_procedure() + LOGGER.info( + f"Finished queue for service {def_proc.service} and op code {def_proc.op_code}" + ) + elif info.proc_type == TcProcedureType.CFDP: + LOGGER.info(f"Finished CFDP queue") + self.cfdp_done = True def setup_params() -> SetupWrapper: @@ -238,9 +320,7 @@ def setup_params() -> SetupWrapper: post_arg_parsing_wrapper.set_params_without_prompts(params, proc_param_wrapper) params.apid = PUS_APID setup_wrapper = SetupWrapper( - hook_obj=hook_obj, - setup_params=params, - proc_param_wrapper=proc_param_wrapper + hook_obj=hook_obj, setup_params=params, proc_param_wrapper=proc_param_wrapper ) return setup_wrapper @@ -298,6 +378,7 @@ def setup_tmtc_handlers( file_logger=printer.file_logger, raw_logger=raw_logger, gui=gui, + cfdp_in_ccsds_wrapper=cfdp_in_ccsds_wrapper, ) return ccsds_handler, tc_handler @@ -309,8 +390,10 @@ def setup_backend( ) -> BackendBase: init_proc = params_to_procedure_conversion(setup_wrapper.proc_param_wrapper) tmtc_backend = tmtccmd.create_default_tmtc_backend( - setup_wrapper=setup_wrapper, tm_handler=ccsds_handler, tc_handler=tc_handler, - init_procedure=init_proc + setup_wrapper=setup_wrapper, + tm_handler=ccsds_handler, + tc_handler=tc_handler, + init_procedure=init_proc, ) tmtccmd.start(tmtc_backend=tmtc_backend, hook_obj=setup_wrapper.hook_obj) return tmtc_backend