diff --git a/CHANGELOG.md b/CHANGELOG.md index f020c1e..5844963 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,35 @@ list yields a list of all related PRs for each release. # [unreleased] +# [v5.4.3] 2023-08-15 + +## Added + +- PLOC SUPV HK parsing. + +# [v5.4.2] 2023-08-15 + +## Added + +- New NONE entry for PL PCDU submode enum. + +# [v5.4.1] 2023-08-15 + +## Added + +- New event TLE_TOO_OLD + +## Changed + + - PL Subsystem mode ID is int enum now. + +# [v5.4.0] 2023-08-15 + +## Added + +- New enumeration for PL PCDU commanding. +- Some new events + # [v5.3.1] 2023-07-26 ## Changed diff --git a/eive_tmtc/__init__.py b/eive_tmtc/__init__.py index 7215fe2..d701219 100644 --- a/eive_tmtc/__init__.py +++ b/eive_tmtc/__init__.py @@ -1,12 +1,12 @@ -__version__ = "5.3.1" +__version__ = "5.4.3" import logging from pathlib import Path SW_NAME = "eive-tmtc" VERSION_MAJOR = 5 -VERSION_MINOR = 3 -VERSION_REVISION = 1 +VERSION_MINOR = 4 +VERSION_REVISION = 3 EIVE_TMTC_ROOT = Path(__file__).parent PACKAGE_ROOT = EIVE_TMTC_ROOT.parent diff --git a/eive_tmtc/config/returnvalues.csv b/eive_tmtc/config/returnvalues.csv index 1bc9186..065e539 100644 --- a/eive_tmtc/config/returnvalues.csv +++ b/eive_tmtc/config/returnvalues.csv @@ -357,7 +357,6 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x3a02;MQI_Full;No space left for more messages;2;MESSAGE_QUEUE_IF;fsfw/src/fsfw/ipc/MessageQueueIF.h 0x3a03;MQI_NoReplyPartner;Returned if a reply method was called without partner;3;MESSAGE_QUEUE_IF;fsfw/src/fsfw/ipc/MessageQueueIF.h 0x3a04;MQI_DestinationInvalid;Returned if the target destination is invalid.;4;MESSAGE_QUEUE_IF;fsfw/src/fsfw/ipc/MessageQueueIF.h -0x3b00;SPH_ConnBroken;No description;0;SEMAPHORE_IF;fsfw/src/fsfw/osal/common/TcpTmTcServer.h 0x3b01;SPH_SemaphoreTimeout;No description;1;SEMAPHORE_IF;fsfw/src/fsfw/tasks/SemaphoreIF.h 0x3b02;SPH_SemaphoreNotOwned;No description;2;SEMAPHORE_IF;fsfw/src/fsfw/tasks/SemaphoreIF.h 0x3b03;SPH_SemaphoreInvalid;No description;3;SEMAPHORE_IF;fsfw/src/fsfw/tasks/SemaphoreIF.h @@ -373,6 +372,7 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x3e05;HKM_DatasetNotFound;No description;5;HOUSEKEEPING_MANAGER;fsfw/src/fsfw/datapoollocal/LocalDataPoolManager.h 0x3f01;DLEE_StreamTooShort;No description;1;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h 0x3f02;DLEE_DecodingError;No description;2;DLE_ENCODER;fsfw/src/fsfw/globalfunctions/DleEncoder.h +0x4100;PUS9_ConnBroken;No description;0;PUS_SERVICE_9;fsfw/src/fsfw/osal/common/TcpTmTcServer.h 0x4201;PUS11_InvalidTypeTimeWindow;No description;1;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4202;PUS11_InvalidTimeWindow;No description;2;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h 0x4203;PUS11_TimeshiftingNotPossible;No description;3;PUS_SERVICE_11;fsfw/src/fsfw/pus/Service11TelecommandScheduling.h @@ -402,9 +402,9 @@ Full ID (hex); Name; Description; Unique ID; Subsytem Name; File Path 0x4403;UXOS_CommandError;Command execution failed;3;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4404;UXOS_NoCommandLoadedOrPending;;4;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h 0x4406;UXOS_PcloseCallError;No description;6;LINUX_OSAL;fsfw/src/fsfw_hal/linux/CommandExecutor.h -0x4500;HSPI_OpeningFileFailed;No description;0;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h -0x4501;HSPI_FullDuplexTransferFailed;No description;1;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h -0x4502;HSPI_HalfDuplexTransferFailed;No description;2;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h +0x4500;HSPI_HalTimeoutRetval;No description;0;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h +0x4501;HSPI_HalBusyRetval;No description;1;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h +0x4502;HSPI_HalErrorRetval;No description;2;HAL_SPI;fsfw/src/fsfw_hal/stm32h7/spi/spiDefinitions.h 0x4503;HSPI_Timeout;No description;3;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h 0x4504;HSPI_Busy;No description;4;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h 0x4505;HSPI_GenericError;No description;5;HAL_SPI;fsfw/src/fsfw_hal/common/spi/spiCommon.h diff --git a/eive_tmtc/pus_tm/hk_handler.py b/eive_tmtc/pus_tm/hk_handler.py index 73cc578..78c980b 100644 --- a/eive_tmtc/pus_tm/hk_handler.py +++ b/eive_tmtc/pus_tm/hk_handler.py @@ -101,7 +101,9 @@ def handle_regular_hk_print( # noqa C901: Complexity okay here elif objb == obj_ids.IMTQ_HANDLER_ID: return handle_imtq_hk(pw=pw, hk_data=hk_data, set_id=set_id) elif objb == obj_ids.GPS_CONTROLLER: - return handle_gps_data(pw=pw, hk_data=hk_data) + return handle_gps_data( + pw=pw, set_id=set_id, hk_data=hk_data, packet_time=packet_dt + ) elif objb == obj_ids.PCDU_HANDLER_ID: return handle_pcdu_hk(pw=pw, set_id=set_id, hk_data=hk_data) elif objb == obj_ids.BPX_HANDLER_ID: diff --git a/eive_tmtc/tmtc/acs/acs_ctrl.py b/eive_tmtc/tmtc/acs/acs_ctrl.py index a16e5e6..441e898 100644 --- a/eive_tmtc/tmtc/acs/acs_ctrl.py +++ b/eive_tmtc/tmtc/acs/acs_ctrl.py @@ -66,6 +66,7 @@ class ActionId(enum.IntEnum): SOLAR_ARRAY_DEPLOYMENT_SUCCESSFUL = 0 RESET_MEKF = 1 RESTORE_MEKF_NONFINITE_RECOVERY = 2 + UPDATE_TLE = 3 CTRL_STRAT_DICT = { @@ -90,6 +91,13 @@ CTRL_STRAT_DICT = { 31: "PTG_RAW", } +GPS_COURCE_DICT = { + 0: "NONE", + 1: "GPS", + 2: "GPS_EXTRAPOLATED", + 3: "SGP4", +} + class OpCodes: OFF = ["off"] @@ -103,6 +111,7 @@ class OpCodes: SAFE_PTG = ["confirm_deployment"] RESET_MEKF = ["reset_mekf"] RESTORE_MEKF_NONFINITE_RECOVERY = ["restore_mekf_nonfinite_recovery"] + UPDATE_TLE = ["update_tle"] SET_PARAMETER_SCALAR = ["set_scalar_param"] SET_PARAMETER_VECTOR = ["set_vector_param"] SET_PARAMETER_MATRIX = ["set_matrix_param"] @@ -153,6 +162,7 @@ class Info: SAFE_PTG = "Confirm deployment of both solar arrays" RESET_MEKF = "Reset the MEKF" RESTORE_MEKF_NONFINITE_RECOVERY = "Restore MEKF non-finite recovery" + UPDATE_TLE = "Update TLE" SET_PARAMETER_SCALAR = "Set Scalar Parameter" SET_PARAMETER_VECTOR = "Set Vector Parameter" SET_PARAMETER_MATRIX = "Set Matrix Parameter" @@ -220,6 +230,7 @@ def acs_cmd_defs(defs: TmtcDefinitionWrapper): keys=OpCodes.RESTORE_MEKF_NONFINITE_RECOVERY, info=Info.RESTORE_MEKF_NONFINITE_RECOVERY, ) + oce.add(keys=OpCodes.UPDATE_TLE, info=Info.UPDATE_TLE) oce.add(keys=OpCodes.SET_PARAMETER_SCALAR, info=Info.SET_PARAMETER_SCALAR) oce.add(keys=OpCodes.SET_PARAMETER_VECTOR, info=Info.SET_PARAMETER_VECTOR) oce.add(keys=OpCodes.SET_PARAMETER_MATRIX, info=Info.SET_PARAMETER_MATRIX) @@ -308,6 +319,22 @@ def pack_acs_ctrl_command(p: ServiceProviderParams): # noqa C901 q.add_pus_tc( create_action_cmd(ACS_CONTROLLER, ActionId.RESTORE_MEKF_NONFINITE_RECOVERY) ) + elif op_code in OpCodes.UPDATE_TLE: + q.add_log_cmd(f"{Info.UPDATE_TLE}") + while True: + line1 = input("Please input the first line of the TLE: ") + if len(line1) == 69: + break + else: + print("The line does not have the required length of 69 characters") + while True: + line2 = input("Please input the second line of the TLE: ") + if len(line2) == 69: + break + else: + print("The line does not have the required length of 69 characters") + tle = line1.encode() + line2.encode() + q.add_pus_tc(create_action_cmd(ACS_CONTROLLER, ActionId.UPDATE_TLE, tle)) elif op_code in OpCodes.SET_PARAMETER_SCALAR: q.add_log_cmd(f"{Info.SET_PARAMETER_SCALAR}") set_acs_ctrl_param_scalar(q) @@ -985,11 +1012,13 @@ def handle_gyr_data_processed(pw: PrintWrapper, hk_data: bytes): def handle_gps_data_processed(pw: PrintWrapper, hk_data: bytes): pw.dlog("Received GPS Processed Set") + fmt_source = "!B" fmt_scalar = "!d" fmt_vec = "!ddd" + inc_len_source = struct.calcsize(fmt_source) inc_len_scalar = struct.calcsize(fmt_scalar) inc_len_vec = struct.calcsize(fmt_vec) - if len(hk_data) < 2 * inc_len_scalar + 2 * inc_len_vec: + if len(hk_data) < 3 * inc_len_scalar + 2 * inc_len_vec + inc_len_source: pw.dlog("Received HK set too small") return current_idx = 0 @@ -1028,12 +1057,20 @@ def handle_gps_data_processed(pw: PrintWrapper, hk_data: bytes): ) ] current_idx += inc_len_vec + source = struct.unpack( + fmt_source, hk_data[current_idx : current_idx + inc_len_source] + )[0] + current_idx += inc_len_source + if GPS_COURCE_DICT.get(source) is not None: + pw.dlog(f"GPS Source: {GPS_COURCE_DICT[source]}") + else: + pw.dlog(f"'GPS Source (key unknown)': {source}") pw.dlog(f"GPS Latitude: {lat} [deg]") pw.dlog(f"GPS Longitude: {long} [deg]") pw.dlog(f"GPS Altitude: {alt} [m]") pw.dlog(f"GPS Position: {pos} [m]") pw.dlog(f"GPS Velocity: {velo} [m/s]") - FsfwTmTcPrinter.get_validity_buffer(hk_data[current_idx:], num_vars=5) + FsfwTmTcPrinter.get_validity_buffer(hk_data[current_idx:], num_vars=6) def handle_mekf_data(pw: PrintWrapper, hk_data: bytes): diff --git a/eive_tmtc/tmtc/acs/gps.py b/eive_tmtc/tmtc/acs/gps.py index 8fffd13..da90ce1 100644 --- a/eive_tmtc/tmtc/acs/gps.py +++ b/eive_tmtc/tmtc/acs/gps.py @@ -20,37 +20,51 @@ from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter _LOGGER = logging.getLogger(__name__) +class GpsInfo: + MAX_SATELLITES = 30 + + class OpCode: OFF = "off" ON = "on" - REQ_OS_HK = ["hk"] - ENABLE_HK = ["enable_hk"] - DISABLE_HK = ["disable_hk"] + REQ_CORE_HK = ["core_hk_request"] + ENABLE_CORE_HK = ["core_hk_enable"] + DISABLE_CORE_HK = ["core_hk_disable"] + REQ_SKYVIEW_HK = ["skyview_hk_request"] + ENABLE_SKYVIEW_HK = ["skyview_hk_enable"] + DISABLE_SKYVIEW_HK = ["skyview_hk_disable"] RESET_GNSS = ["reset"] class Info: OFF = "Off" ON = "On" - REQ_OS_HK = "Request One-Shot HK" - ENABLE_HK = "Enable HK" - DISABLE_HK = "Disable HK" + REQ_CORE_HK = "Request Core HK" + ENABLE_CORE_HK = "Enable Core HK" + DISABLE_CORE_HK = "Disable Core HK" + REQ_SKYVIEW_HK = "Request Skyview HK" + ENABLE_SKYVIEW_HK = "Enable Skyview HK" + DISABLE_SKYVIEW_HK = "Disable Skyview HK" RESET_GNSS = "Reset GNSS using reset pin" class SetId(enum.IntEnum): - HK = 0 + CORE_HK = 0 + SKYVIEW_HK = 1 @tmtc_definitions_provider def add_gps_cmds(defs: TmtcDefinitionWrapper): oce = OpCodeEntry() - oce.add(keys=OpCode.RESET_GNSS, info=Info.RESET_GNSS) - oce.add(keys=OpCode.REQ_OS_HK, info=Info.REQ_OS_HK) - oce.add(keys=OpCode.ENABLE_HK, info=Info.ENABLE_HK) - oce.add(keys=OpCode.DISABLE_HK, info=Info.DISABLE_HK) oce.add(keys=OpCode.OFF, info=Info.OFF) oce.add(keys=OpCode.ON, info=Info.ON) + oce.add(keys=OpCode.RESET_GNSS, info=Info.RESET_GNSS) + oce.add(keys=OpCode.REQ_CORE_HK, info=Info.REQ_CORE_HK) + oce.add(keys=OpCode.ENABLE_CORE_HK, info=Info.ENABLE_CORE_HK) + oce.add(keys=OpCode.DISABLE_CORE_HK, info=Info.DISABLE_CORE_HK) + oce.add(keys=OpCode.REQ_SKYVIEW_HK, info=Info.REQ_SKYVIEW_HK) + oce.add(keys=OpCode.ENABLE_SKYVIEW_HK, info=Info.ENABLE_SKYVIEW_HK) + oce.add(keys=OpCode.DISABLE_SKYVIEW_HK, info=Info.DISABLE_SKYVIEW_HK) defs.add_service( name=CustomServiceList.GPS_CTRL.value, info="GPS/GNSS Controller", @@ -59,26 +73,43 @@ def add_gps_cmds(defs: TmtcDefinitionWrapper): def pack_gps_command(object_id: bytes, q: DefaultPusQueueHelper, op_code: str): - sid = make_sid(object_id=object_id, set_id=SetId.HK) if op_code in OpCode.RESET_GNSS: # TODO: This needs to be re-implemented _LOGGER.warning("Reset pin handling needs to be re-implemented") - if op_code in OpCode.ENABLE_HK: + if op_code in OpCode.ENABLE_CORE_HK: interval = float(input("Please specify interval in floating point seconds: ")) if interval <= 0: raise ValueError("invalid interval") - q.add_log_cmd(f"GPS: {Info.ENABLE_HK}") + q.add_log_cmd(f"GPS: {Info.ENABLE_CORE_HK}") cmds = create_enable_periodic_hk_command_with_interval( - diag=False, sid=sid, interval_seconds=interval + diag=False, sid=make_sid(object_id=object_id, set_id=SetId.CORE_HK), interval_seconds=interval ) for cmd in cmds: q.add_pus_tc(cmd) - if op_code in OpCode.DISABLE_HK: - q.add_log_cmd(f"gps: {Info.DISABLE_HK}") - q.add_pus_tc(create_disable_periodic_hk_command(diag=False, sid=sid)) - if op_code in OpCode.REQ_OS_HK: - q.add_log_cmd(f"GPS: {Info.REQ_OS_HK}") - q.add_pus_tc(create_request_one_hk_command(sid=sid)) + if op_code in OpCode.DISABLE_CORE_HK: + q.add_log_cmd(f"gps: {Info.DISABLE_CORE_HK}") + q.add_pus_tc(create_disable_periodic_hk_command(diag=False, sid=make_sid(object_id=object_id, + set_id=SetId.CORE_HK))) + if op_code in OpCode.REQ_CORE_HK: + q.add_log_cmd(f"GPS: {Info.REQ_CORE_HK}") + q.add_pus_tc(create_request_one_hk_command(sid=make_sid(object_id=object_id, set_id=SetId.CORE_HK))) + if op_code in OpCode.ENABLE_SKYVIEW_HK: + interval = float(input("Please specify interval in floating point seconds: ")) + if interval <= 0: + raise ValueError("invalid interval") + q.add_log_cmd(f"GPS: {Info.ENABLE_SKYVIEW_HK}") + cmds = create_enable_periodic_hk_command_with_interval( + diag=False, sid=make_sid(object_id=object_id, set_id=SetId.SKYVIEW_HK), interval_seconds=interval + ) + for cmd in cmds: + q.add_pus_tc(cmd) + if op_code in OpCode.DISABLE_SKYVIEW_HK: + q.add_log_cmd(f"gps: {Info.DISABLE_SKYVIEW_HK}") + q.add_pus_tc(create_disable_periodic_hk_command(diag=False, sid=make_sid(object_id=object_id, + set_id=SetId.SKYVIEW_HK))) + if op_code in OpCode.REQ_SKYVIEW_HK: + q.add_log_cmd(f"GPS: {Info.REQ_SKYVIEW_HK}") + q.add_pus_tc(create_request_one_hk_command(sid=make_sid(object_id=object_id, set_id=SetId.SKYVIEW_HK))) if op_code in OpCode.ON: q.add_log_cmd(f"GPS: {Info.ON}") q.add_pus_tc(create_mode_command(object_id, Mode.ON, 0)) @@ -87,8 +118,27 @@ def pack_gps_command(object_id: bytes, q: DefaultPusQueueHelper, op_code: str): q.add_pus_tc(create_mode_command(object_id, Mode.OFF, 0)) -def handle_gps_data(pw: PrintWrapper, hk_data: bytes): - pw.dlog(f"Received GPS data, HK data length {len(hk_data)}") +def handle_gps_data( + pw: PrintWrapper, + set_id: int, + hk_data: bytes, + packet_time: datetime.datetime, +): + pw.ilog(_LOGGER, f"Received GPS CTRL HK with packet time {packet_time}") + match set_id: + case SetId.CORE_HK: + handle_core_data(pw, hk_data) + case SetId.SKYVIEW_HK: + handle_skyview_data(pw, hk_data) + + +def handle_core_data(pw: PrintWrapper, hk_data: bytes): + if len(hk_data) < 4*8+4+2+8: + pw.dlog( + f"GPS Core dataset with size {len(hk_data)} does not have expected size" + f" of {4*8+4+2+8} bytes" + ) + return current_idx = 0 fmt_str = "!ddddBBBHBBBBBI" inc_len = struct.calcsize(fmt_str) @@ -126,3 +176,43 @@ def handle_gps_data(pw: PrintWrapper, hk_data: bytes): FsfwTmTcPrinter.get_validity_buffer( validity_buffer=hk_data[current_idx:], num_vars=14 ) + + +def handle_skyview_data(pw: PrintWrapper, hk_data: bytes): + data_length = 8+GpsInfo.MAX_SATELLITES*(8+3*2+1) + if len(hk_data) < data_length: + pw.dlog( + f"GPS Skyview dataset with size {len(hk_data)} does not have expected size" + f" of {data_length} bytes" + ) + return + current_idx = 0 + fmt_str_unix = "!d" + fmt_str_int16 = "!" + "h" * GpsInfo.MAX_SATELLITES + fmt_str_double = "!" + "d" * GpsInfo.MAX_SATELLITES + fmt_str_uint8 = "!" + "B" * GpsInfo.MAX_SATELLITES + inc_len_unix = struct.calcsize(fmt_str_unix) + inc_len_int16 = struct.calcsize(fmt_str_int16) + inc_len_double = struct.calcsize(fmt_str_double) + inc_len_uint8 = struct.calcsize(fmt_str_uint8) + unix = struct.unpack(fmt_str_unix, hk_data[current_idx: current_idx + inc_len_unix])[0] + current_idx += inc_len_unix + prn_id = struct.unpack(fmt_str_int16, hk_data[current_idx: current_idx + inc_len_int16]) + current_idx += inc_len_int16 + azimuth = struct.unpack(fmt_str_int16, hk_data[current_idx: current_idx + inc_len_int16]) + current_idx += inc_len_int16 + elevation = struct.unpack(fmt_str_int16, hk_data[current_idx: current_idx + inc_len_int16]) + current_idx += inc_len_int16 + signal_to_noise = struct.unpack(fmt_str_double, hk_data[current_idx: current_idx + inc_len_double]) + current_idx += inc_len_double + used = struct.unpack(fmt_str_uint8, hk_data[current_idx: current_idx + inc_len_uint8]) + current_idx += inc_len_uint8 + pw.dlog(f"Skyview Time: {unix} unix-sec") + pw.dlog("{:<8} {:<8} {:<8} {:<8} {:<8}".format('PRN_ID', 'AZ [°]', 'EL [°]', 'S2N [dBW]', 'USED')) + for idx in range(GpsInfo.MAX_SATELLITES): + pw.dlog("{:<8} {:<8} {:<8} {:<8} {:<8}".format(prn_id[idx], azimuth[idx], elevation[idx], signal_to_noise[idx], + used[idx])) + FsfwTmTcPrinter.get_validity_buffer( + validity_buffer=hk_data[current_idx:], num_vars=6 + ) + diff --git a/eive_tmtc/tmtc/payload/ploc_supervisor.py b/eive_tmtc/tmtc/payload/ploc_supervisor.py index b696ecf..18aebab 100644 --- a/eive_tmtc/tmtc/payload/ploc_supervisor.py +++ b/eive_tmtc/tmtc/payload/ploc_supervisor.py @@ -722,10 +722,42 @@ def get_event_buffer_path() -> str: return file +class SocState(enum.IntEnum): + OFF = 0 + BOOTING = 1 + OPERATIONAL = 2 + SHUTDOWN = 3 + + def handle_supv_hk_data(set_id: int, hk_data: bytes, pw: PrintWrapper): current_idx = 0 if set_id == SetIds.HK_REPORT: - pass + fmt_str = "!IIIQIIIIIBBBB" + inc_len = struct.calcsize(fmt_str) + ( + temp_ps, + temp_pl, + temp_sup, + uptime, + cpu_load, + avail_heap, + num_tcs, + num_tms, + soc_state, + nvm_0_1_state, + nvm_3_state, + mission_io_state, + fmc_state, + ) = struct.unpack(fmt_str, hk_data[:inc_len]) + pw.dlog(f"Temp PS {temp_ps} C | Temp PL {temp_pl} C | Temp SUP {temp_sup} C") + pw.dlog(f"Uptime {uptime} | CPU Load {cpu_load} | Avail Heap {avail_heap}") + pw.dlog(f"Number TCs {num_tcs} | Number TMs {num_tms}") + pw.dlog(f"SOC state {SocState(soc_state)}") + pw.dlog(f"NVM 01 State {nvm_0_1_state}") + pw.dlog(f"NVM 3 State {nvm_3_state}") + pw.dlog(f"Mission IO state {mission_io_state}") + pw.dlog(f"FMC state {fmc_state}") + pw.dlog(FsfwTmTcPrinter.get_validity_buffer(hk_data[inc_len:], 13)) elif set_id == SetIds.BOOT_STATUS_REPORT: fmt_str = "!BBIIBBBBBB" inc_len = struct.calcsize(fmt_str) diff --git a/eive_tmtc/tmtc/payload/subsystem.py b/eive_tmtc/tmtc/payload/subsystem.py index 14eaa75..560891d 100644 --- a/eive_tmtc/tmtc/payload/subsystem.py +++ b/eive_tmtc/tmtc/payload/subsystem.py @@ -12,7 +12,7 @@ from tmtccmd.tc.decorator import ServiceProviderParams from tmtccmd.tc.pus_200_fsfw_mode import Subservice as ModeSubservice -class ModeId: +class ModeId(enum.IntEnum): OFF = 0 SUPV_ONLY = 10 MPSOC_STREAM = 11 diff --git a/eive_tmtc/tmtc/power/plpcdu.py b/eive_tmtc/tmtc/power/plpcdu.py index 745d7b4..62517e3 100644 --- a/eive_tmtc/tmtc/power/plpcdu.py +++ b/eive_tmtc/tmtc/power/plpcdu.py @@ -85,6 +85,40 @@ class NormalSubmodesMask(enum.IntEnum): HPA_ON = 5 +class SubmodeForNormalMode(enum.IntEnum): + NONE = 0 + SSR_ON = 1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON + DRO_ON = 1 << NormalSubmodesMask.DRO_ON | ( + 1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON + ) + X8_ON = ( + 1 << NormalSubmodesMask.DRO_ON + | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) + | (1 << NormalSubmodesMask.X8_ON) + ) + TX_ON = ( + 1 << NormalSubmodesMask.DRO_ON + | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) + | (1 << NormalSubmodesMask.X8_ON) + | (1 << NormalSubmodesMask.TX_ON) + ) + MPA_ON = ( + 1 << NormalSubmodesMask.DRO_ON + | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) + | (1 << NormalSubmodesMask.X8_ON) + | (1 << NormalSubmodesMask.TX_ON) + | (1 << NormalSubmodesMask.MPA_ON) + ) + HPA_ON = ( + 1 << NormalSubmodesMask.DRO_ON + | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) + | (1 << NormalSubmodesMask.X8_ON) + | (1 << NormalSubmodesMask.TX_ON) + | (1 << NormalSubmodesMask.MPA_ON) + | (1 << NormalSubmodesMask.HPA_ON) + ) + + class ParamIds(enum.IntEnum): NEG_V_LOWER_BOUND = 0 NEG_V_UPPER_BOUND = 1 @@ -383,41 +417,17 @@ def request_wait_time() -> Optional[float]: def submode_mask_to_submode(on_tgt: NormalSubmodesMask) -> int: if on_tgt == NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON: - return 1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON + return SubmodeForNormalMode.SSR_ON if on_tgt == NormalSubmodesMask.DRO_ON: - return 1 << NormalSubmodesMask.DRO_ON | ( - 1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON - ) + return SubmodeForNormalMode.DRO_ON if on_tgt == NormalSubmodesMask.X8_ON: - return ( - 1 << NormalSubmodesMask.DRO_ON - | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) - | (1 << NormalSubmodesMask.X8_ON) - ) + return SubmodeForNormalMode.X8_ON if on_tgt == NormalSubmodesMask.TX_ON: - return ( - 1 << NormalSubmodesMask.DRO_ON - | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) - | (1 << NormalSubmodesMask.X8_ON) - | (1 << NormalSubmodesMask.TX_ON) - ) + return SubmodeForNormalMode.TX_ON if on_tgt == NormalSubmodesMask.MPA_ON: - return ( - 1 << NormalSubmodesMask.DRO_ON - | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) - | (1 << NormalSubmodesMask.X8_ON) - | (1 << NormalSubmodesMask.TX_ON) - | (1 << NormalSubmodesMask.MPA_ON) - ) + return SubmodeForNormalMode.MPA_ON if on_tgt == NormalSubmodesMask.HPA_ON: - return ( - 1 << NormalSubmodesMask.DRO_ON - | (1 << NormalSubmodesMask.SOLID_STATE_RELAYS_ADC_ON) - | (1 << NormalSubmodesMask.X8_ON) - | (1 << NormalSubmodesMask.TX_ON) - | (1 << NormalSubmodesMask.MPA_ON) - | (1 << NormalSubmodesMask.HPA_ON) - ) + return SubmodeForNormalMode.HPA_ON def pack_wait_time_cmd(q: DefaultPusQueueHelper, param_id: int, print_str: str):