diff --git a/common.py b/common.py index 6b5cc46..2bb4b59 100644 --- a/common.py +++ b/common.py @@ -11,17 +11,27 @@ from spacepackets.cfdp import ( GenericPduPacket, PduHolder, PduFactory, + ChecksumTypes, + ConditionCode, ) from tmtccmd.cfdp import ( RemoteEntityCfgTable, RemoteEntityCfg, LocalEntityCfg, CfdpUserBase, + IndicationCfg, + TransactionId, ) from spacepackets.util import UnsignedByteField from tmtccmd.cfdp.defs import CfdpRequestType, CfdpStates from tmtccmd.cfdp.handler import SourceHandler, DestHandler +from tmtccmd.cfdp.mib import DefaultFaultHandlerBase from tmtccmd.cfdp.request import PutRequest, PutRequestCfg +from tmtccmd.cfdp.user import ( + FileSegmentRecvdParams, + MetadataRecvParams, + TransactionFinishedParams, +) from tmtccmd.logging import get_current_time_string from tmtccmd.pus.pus_11_tc_sched import Subservices as Pus11Subservices from tmtccmd.tc.queue import DefaultPusQueueHelper @@ -51,7 +61,12 @@ from common_tmtc.pus_tc.service_20_parameters import pack_service20_commands_int from common_tmtc.pus_tc.service_2_raw_cmd import pack_service_2_commands_into from common_tmtc.pus_tc.service_3_housekeeping import pack_service_3_commands_into from common_tmtc.pus_tc.service_8_func_cmd import pack_service_8_commands_into -from examples.tmtcc import EXAMPLE_PUS_APID, EXAMPLE_CFDP_APID +from examples.tmtcc import ( + EXAMPLE_PUS_APID, + EXAMPLE_CFDP_APID, + CFDP_LOCAL_ENTITY_ID, + CFDP_REMOTE_ENTITY_ID, +) from tmtccmd import TcHandlerBase, get_console_logger, TmTcCfgHookBase, BackendBase from tmtccmd.pus import VerificationWrapper from tmtccmd.tc import ( @@ -71,15 +86,56 @@ from common_tmtc.pus_tm.factory_hook import pus_factory_hook LOGGER = get_console_logger() +class ExampleCfdpUser(CfdpUserBase): + def transaction_indication(self, transaction_id: TransactionId): + pass + + def eof_sent_indication(self, transaction_id: TransactionId): + pass + + def transaction_finished_indication(self, params: TransactionFinishedParams): + pass + + def metadata_recv_indication(self, params: MetadataRecvParams): + pass + + def file_segment_recv_indication(self, params: FileSegmentRecvdParams): + pass + + def report_indication(self, transaction_id: TransactionId, status_report: any): + pass + + def suspended_indication( + self, transaction_id: TransactionId, cond_code: ConditionCode + ): + pass + + def resumed_indication(self, transaction_id: TransactionId, progress: int): + pass + + def fault_indication( + self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int + ): + pass + + def abandoned_indication( + self, transaction_id: TransactionId, cond_code: ConditionCode, progress: int + ): + pass + + def eof_recv_indication(self, transaction_id: TransactionId): + pass + + class CfdpCcsdsWrapper(SpecificApidHandlerBase): def __init__( self, cfg: LocalEntityCfg, user: CfdpUserBase, - cfdp_seq_cnt_provider: ProvidesSeqCount, - remote_cfg: Sequence[RemoteEntityCfg], - ccsds_seq_cnt_provider: ProvidesSeqCount, + remote_cfgs: Sequence[RemoteEntityCfg], ccsds_apid: int, + cfdp_seq_cnt_provider: ProvidesSeqCount, + ccsds_seq_cnt_provider: ProvidesSeqCount, ): """Wrapper helper type used to wrap PDU packets into CCSDS packets and to extract PDU packets from CCSDS packets. @@ -89,7 +145,6 @@ class CfdpCcsdsWrapper(SpecificApidHandlerBase): virtual filestore implementation. :param cfdp_seq_cnt_provider: Every CFDP file transfer has a transaction sequence number. This provider is used to retrieve that sequence number. - :param remote_cfg: :param ccsds_seq_cnt_provider: Each CFDP PDU is wrapped into a CCSDS space packet, and each space packet has a dedicated sequence count. This provider is used to retrieve the sequence count. @@ -98,7 +153,7 @@ class CfdpCcsdsWrapper(SpecificApidHandlerBase): CFDP packets. """ super().__init__(EXAMPLE_CFDP_APID, None) - self.handler = CfdpHandler(cfg, user, cfdp_seq_cnt_provider, remote_cfg) + self.handler = CfdpHandler(cfg, user, cfdp_seq_cnt_provider, remote_cfgs) self.ccsds_seq_cnt_provider = ccsds_seq_cnt_provider self.ccsds_apid = ccsds_apid @@ -138,18 +193,15 @@ class CfdpHandler: cfg: LocalEntityCfg, user: CfdpUserBase, seq_cnt_provider: ProvidesSeqCount, - remote_cfg: Sequence[RemoteEntityCfg], + remote_cfgs: Sequence[RemoteEntityCfg], ): self.dest_id = UnsignedByteField(EXAMPLE_PUS_APID, 2) self.remote_cfg_table = RemoteEntityCfgTable() - self.remote_cfg_table.add_configs(remote_cfg) + self.remote_cfg_table.add_configs(remote_cfgs) self.dest_handler = DestHandler(cfg, user, self.remote_cfg_table) self.source_handler = SourceHandler(cfg, seq_cnt_provider, user) - def put_request( - self, - request: PutRequest - ): + def put_request(self, request: PutRequest): if self.remote_cfg_table.get_cfg(request.cfg.destination_id): raise ValueError( f"No remote CFDP config found for entity ID {request.cfg.destination_id}" @@ -284,7 +336,18 @@ class TcHandler(TcHandlerBase): 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(): - put_req = cfdp_procedure.request_wrapper.to_put_request() + # put_req = cfdp_procedure.request_wrapper.to_put_request() + with open("/tmp/hello.txt") as of: + of.write("Hello first CFDP file") + # TODO: Replace hardcoded put request if the request works + put_request_cfg = PutRequestCfg( + destination_id=self.cfdp_in_ccsds_wrapper.handler.dest_id, + source_file=Path("/tmp/hello.txt"), + dest_file="/tmp/hello-created-by-dest.txt", + closure_requested=False, + trans_mode=TransmissionModes.UNACKNOWLEDGED, + ) + put_req = PutRequest(put_request_cfg) LOGGER.info(f"Starting put request {put_req}") # TODO: Only start put request if there isn't one pending yet. The source handler # state can probably be used for this. @@ -345,10 +408,40 @@ def setup_params(hook_obj: TmTcCfgHookBase) -> SetupWrapper: def setup_tmtc_handlers( verif_wrapper: VerificationWrapper, printer: FsfwTmTcPrinter, - cfdp_handler: CfdpCcsdsWrapper, raw_logger: RawTmtcTimedLogWrapper, ) -> (CcsdsTmHandler, TcHandler): + fh_base = DefaultFaultHandlerBase() + cfdp_cfg = LocalEntityCfg( + local_entity_id=CFDP_LOCAL_ENTITY_ID, + indication_cfg=IndicationCfg(), + default_fault_handlers=fh_base, + ) + remote_cfg = RemoteEntityCfg( + closure_requested=False, + entity_id=CFDP_REMOTE_ENTITY_ID, + max_file_segment_len=1024, + check_limit=None, + crc_on_transmission=False, + crc_type=ChecksumTypes.CRC_32, + default_transmission_mode=TransmissionModes.UNACKNOWLEDGED, + ) + cfdp_seq_count_provider = FileSeqCountProvider( + max_bit_width=16, file_name=Path("cfdp_transaction_cnt.txt") + ) + cfdp_ccsds_seq_count_provider = PusFileSeqCountProvider( + file_name=Path("cfdp_ccsds_seqcnt.txt") + ) + cfdp_user = ExampleCfdpUser() + cfdp_in_ccsds_handler = CfdpCcsdsWrapper( + cfg=cfdp_cfg, + remote_cfgs=[remote_cfg], + ccsds_apid=EXAMPLE_CFDP_APID, + ccsds_seq_cnt_provider=cfdp_ccsds_seq_count_provider, + cfdp_seq_cnt_provider=cfdp_seq_count_provider, + user=cfdp_user, + ) + pus_handler = PusHandler( printer=printer, raw_logger=raw_logger, wrapper=verif_wrapper ) @@ -358,8 +451,10 @@ def setup_tmtc_handlers( file_logger=printer.file_logger, raw_logger=raw_logger, pus_verificator=verif_wrapper.pus_verificator, - seq_count_provider=PusFileSeqCountProvider(), - cfdp_in_ccsds_wrapper=cfdp_handler, + seq_count_provider=PusFileSeqCountProvider( + file_name=Path("pus_ccsds_seqcnt.txt") + ), + cfdp_in_ccsds_wrapper=cfdp_in_ccsds_handler, ) return ccsds_handler, tc_handler