Compare commits
56 Commits
Author | SHA1 | Date | |
---|---|---|---|
d23cc6834a | |||
33cff5e2d2
|
|||
acbcbbe98f
|
|||
c3b0470aa6
|
|||
e56f8732be | |||
af5e81158c
|
|||
d285b1caec | |||
1f49f0c70d
|
|||
b1fbad39e3 | |||
de57b9da5b | |||
f02230804d | |||
8ddcc37c74 | |||
b50c75c13c | |||
36799ef51d
|
|||
772ef5b323
|
|||
2f8bed4581
|
|||
72def77d40
|
|||
bc1a1774a6 | |||
4b08f5dd5b
|
|||
b0562ea9c7
|
|||
f76cd94535
|
|||
8a1e5b7b99
|
|||
0e208629b0
|
|||
403657110b
|
|||
23f21b40eb | |||
a6b3ccb4cc
|
|||
d7b494a950
|
|||
73bc043538
|
|||
02e7e809de
|
|||
d6f6aff139 | |||
d39a49bd4c | |||
f42318bc57 | |||
fd3a799019 | |||
1664e6adb5 | |||
8042f3607d
|
|||
59278447fd | |||
b58977fd65 | |||
beae6b3f05 | |||
12c60ac310 | |||
1acbb8bb43 | |||
051e9e6ffb | |||
6d88746ec3 | |||
5571a6852e | |||
1ddb93410e | |||
b0b186ac1f | |||
f95331742b | |||
c91ad9e08b | |||
fcabaa5b09 | |||
bf9ab7edf7 | |||
957d756d1e | |||
4b054b7628 | |||
9001a28545
|
|||
6b2fbc6917 | |||
ab770a0057 | |||
0cbf28f25c
|
|||
0a05873f4e |
35
CHANGELOG.md
35
CHANGELOG.md
@ -10,6 +10,41 @@ list yields a list of all related PRs for each release.
|
||||
|
||||
# [unreleased]
|
||||
|
||||
# [v5.5.0] 2023-09-12
|
||||
|
||||
- Version is not specfied dynamically anymore and can be updated in `pyproject.toml`
|
||||
- New events and returnvalues
|
||||
- Bump `tmtccmd` to v6.0.0rc0
|
||||
|
||||
# [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
|
||||
|
@ -1,13 +1,6 @@
|
||||
__version__ = "5.3.1"
|
||||
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
SW_NAME = "eive-tmtc"
|
||||
VERSION_MAJOR = 5
|
||||
VERSION_MINOR = 3
|
||||
VERSION_REVISION = 1
|
||||
|
||||
EIVE_TMTC_ROOT = Path(__file__).parent
|
||||
PACKAGE_ROOT = EIVE_TMTC_ROOT.parent
|
||||
|
||||
|
@ -94,6 +94,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
11205;0x2bc5;MEKF_AUTOMATIC_RESET;INFO;MEKF performed an automatic reset after detection of nonfinite values.;mission/acs/defs.h
|
||||
11206;0x2bc6;MEKF_INVALID_MODE_VIOLATION;HIGH;MEKF was not able to compute a solution during any pointing ACS mode for a prolonged time.;mission/acs/defs.h
|
||||
11207;0x2bc7;SAFE_MODE_CONTROLLER_FAILURE;HIGH;The ACS safe mode controller was not able to compute a solution and has failed. P1: Missing information about magnetic field, P2: Missing information about rotational rate;mission/acs/defs.h
|
||||
11208;0x2bc8;TLE_TOO_OLD;INFO;The TLE for the SGP4 Propagator has become too old.;mission/acs/defs.h
|
||||
11300;0x2c24;SWITCH_CMD_SENT;INFO;Indicates that a FSFW object requested setting a switch P1: 1 if on was requested, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11301;0x2c25;SWITCH_HAS_CHANGED;INFO;Indicated that a switch state has changed P1: New switch state, 1 for on, 0 for off | P2: Switch Index;mission/power/defs.h
|
||||
11302;0x2c26;SWITCHING_Q7S_DENIED;MEDIUM;No description;mission/power/defs.h
|
||||
@ -161,6 +162,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
12412;0x307c;PDEC_RESET_FAILED;HIGH;Failed to pull PDEC reset to low;linux/ipcore/pdec.h
|
||||
12413;0x307d;OPEN_IRQ_FILE_FAILED;HIGH;Failed to open the IRQ uio file;linux/ipcore/pdec.h
|
||||
12414;0x307e;PDEC_INIT_FAILED;HIGH;PDEC initialization failed. This might also be due to the persistent confiuration never becoming available, for example due to SD card issues.;linux/ipcore/pdec.h
|
||||
12415;0x307f;PDEC_CONFIG_CORRUPTED;HIGH;The PDEC configuration area has been corrupted P1: The first configuration word P2: The second configuration word;linux/ipcore/pdec.h
|
||||
12500;0x30d4;IMAGE_UPLOAD_FAILED;LOW;Image upload failed;linux/acs/StrComHandler.h
|
||||
12501;0x30d5;IMAGE_DOWNLOAD_FAILED;LOW;Image download failed;linux/acs/StrComHandler.h
|
||||
12502;0x30d6;IMAGE_UPLOAD_SUCCESSFUL;LOW;Uploading image to star tracker was successfulop;linux/acs/StrComHandler.h
|
||||
@ -255,6 +257,7 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
13800;0x35e8;MISSING_PACKET;LOW;No description;mission/payload/scexHelpers.h
|
||||
13801;0x35e9;EXPERIMENT_TIMEDOUT;LOW;No description;mission/payload/scexHelpers.h
|
||||
13802;0x35ea;MULTI_PACKET_COMMAND_DONE;INFO;No description;mission/payload/scexHelpers.h
|
||||
13803;0x35eb;FS_UNUSABLE;LOW;No description;mission/payload/scexHelpers.h
|
||||
13901;0x364d;SET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13902;0x364e;GET_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
13903;0x364f;INSERT_CONFIGFILEVALUE_FAILED;MEDIUM;No description;mission/utility/GlobalConfigHandler.h
|
||||
@ -300,3 +303,5 @@ Event ID (dec); Event ID (hex); Name; Severity; Description; File Path
|
||||
14312;0x37e8;DUMP_MISC_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14313;0x37e9;DUMP_HK_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14314;0x37ea;DUMP_CFDP_CANCELLED;LOW;P1: Number of dumped packets. P2: Total dumped bytes.;mission/persistentTmStoreDefs.h
|
||||
14500;0x38a4;TEMPERATURE_ALL_ONES_START;MEDIUM;Detected invalid values, starting invalid message counting;mission/acs/SusHandler.h
|
||||
14501;0x38a5;TEMPERATURE_ALL_ONES_RECOVERY;INFO;Detected valid values again, resetting invalid message counter. P1: Invalid message counter.;mission/acs/SusHandler.h
|
||||
|
|
@ -60,3 +60,4 @@
|
||||
142;COM_SUBSYSTEM
|
||||
143;PERSISTENT_TM_STORE
|
||||
144;SYRLINKS_COM
|
||||
145;SUS_HANDLER
|
||||
|
|
@ -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:
|
||||
|
@ -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):
|
||||
|
@ -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",
|
||||
@ -58,27 +72,64 @@ 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)
|
||||
def pack_gps_command( # noqa: C901
|
||||
object_id: bytes, q: DefaultPusQueueHelper, op_code: str
|
||||
): # noqa: C901:
|
||||
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 +138,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 +196,65 @@ 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
|
||||
)
|
||||
|
@ -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)
|
||||
|
@ -17,17 +17,17 @@ USE_SCEX_CONF_FILE = True
|
||||
|
||||
|
||||
class OpCode:
|
||||
PING = ["0", "ping"]
|
||||
ION_CMD = ["1", "ion"]
|
||||
TEMP_CMD = ["2", "temp"]
|
||||
EXP_STATUS_CMD = ["3", "expstatus"]
|
||||
PING = "ping"
|
||||
ION_CMD = "ion"
|
||||
TEMP_CMD = "temp"
|
||||
EXP_STATUS_CMD = "expstatus"
|
||||
|
||||
ONE_CELLS_CMD = ["4", "onecell"]
|
||||
ALL_CELLS_CMD = ["5", "allcells"]
|
||||
FRAM = ["6", "fram"]
|
||||
ONE_CELLS_CMD = "onecell"
|
||||
ALL_CELLS_CMD = "allcells"
|
||||
FRAM = "fram"
|
||||
|
||||
SWITCH_ON = ["7", "on"]
|
||||
SWITCH_OFF = ["8", "off"]
|
||||
SWITCH_ON = "on"
|
||||
SWITCH_OFF = "off"
|
||||
|
||||
|
||||
class ActionId(enum.IntEnum):
|
||||
@ -78,7 +78,7 @@ def add_scex_cmds(defs: TmtcDefinitionWrapper):
|
||||
def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
op_code = p.op_code
|
||||
q = p.queue_helper
|
||||
if op_code in OpCode.SWITCH_ON:
|
||||
if op_code == OpCode.SWITCH_ON:
|
||||
q.add_log_cmd(Info.SWITCH_ON)
|
||||
q.add_pus_tc(
|
||||
PusTelecommand(
|
||||
@ -87,7 +87,7 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
app_data=pack_mode_data(SCEX_HANDLER_ID, Mode.ON, 0),
|
||||
)
|
||||
)
|
||||
if op_code in OpCode.SWITCH_OFF:
|
||||
if op_code == OpCode.SWITCH_OFF:
|
||||
q.add_log_cmd(Info.SWITCH_OFF)
|
||||
q.add_pus_tc(
|
||||
PusTelecommand(
|
||||
@ -96,20 +96,20 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
app_data=pack_mode_data(SCEX_HANDLER_ID, Mode.OFF, 0),
|
||||
)
|
||||
)
|
||||
if op_code in OpCode.PING:
|
||||
if op_code == OpCode.PING:
|
||||
q.add_log_cmd(Info.PING)
|
||||
app_data = bytes([0])
|
||||
q.add_pus_tc(create_action_cmd(SCEX_HANDLER_ID, ActionId.PING, app_data))
|
||||
if op_code in OpCode.ION_CMD:
|
||||
if op_code == OpCode.ION_CMD:
|
||||
q.add_log_cmd(Info.ION_CMD)
|
||||
app_data = bytes([0])
|
||||
q.add_pus_tc(create_action_cmd(SCEX_HANDLER_ID, ActionId.ION_CMD, app_data))
|
||||
if op_code in OpCode.TEMP_CMD:
|
||||
if op_code == OpCode.TEMP_CMD:
|
||||
q.add_log_cmd(Info.TEMP_CMD)
|
||||
app_data = bytes([0])
|
||||
q.add_pus_tc(create_action_cmd(SCEX_HANDLER_ID, ActionId.TEMP_CMD, app_data))
|
||||
|
||||
if op_code in OpCode.EXP_STATUS_CMD:
|
||||
if op_code == OpCode.EXP_STATUS_CMD:
|
||||
q.add_log_cmd(Info.EXP_STATUS_CMD)
|
||||
app_data = bytes([0])
|
||||
q.add_pus_tc(
|
||||
@ -117,7 +117,7 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
)
|
||||
|
||||
# one cell
|
||||
if op_code in OpCode.ONE_CELLS_CMD:
|
||||
if op_code == OpCode.ONE_CELLS_CMD:
|
||||
q.add_log_cmd(Info.ONE_CELLS_CMD)
|
||||
app_data = bytearray([0])
|
||||
|
||||
@ -165,7 +165,7 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
create_action_cmd(SCEX_HANDLER_ID, ActionId.ONE_CELLS_CMD, app_data)
|
||||
)
|
||||
|
||||
if op_code in OpCode.ALL_CELLS_CMD:
|
||||
if op_code == OpCode.ALL_CELLS_CMD:
|
||||
q.add_log_cmd(Info.ALL_CELLS_CMD)
|
||||
app_data = bytearray([0])
|
||||
|
||||
@ -197,7 +197,7 @@ def pack_scex_cmds(p: ServiceProviderParams): # noqa C901
|
||||
create_action_cmd(SCEX_HANDLER_ID, ActionId.ALL_CELLS_CMD, app_data)
|
||||
)
|
||||
|
||||
if op_code in OpCode.FRAM:
|
||||
if op_code == OpCode.FRAM:
|
||||
q.add_log_cmd(Info.FRAM)
|
||||
app_data = bytes([0])
|
||||
q.add_pus_tc(create_action_cmd(SCEX_HANDLER_ID, ActionId.FRAM, app_data))
|
||||
|
@ -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
|
||||
|
@ -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):
|
||||
|
@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
||||
name = "eive-tmtc"
|
||||
description = "TMTC Commander EIVE"
|
||||
readme = "README.md"
|
||||
dynamic = ["version"]
|
||||
version = "5.5.0"
|
||||
requires-python = ">=3.10"
|
||||
license = {text = "Apache-2.0"}
|
||||
authors = [
|
||||
@ -29,9 +29,8 @@ classifiers = [
|
||||
"Topic :: Scientific/Engineering"
|
||||
]
|
||||
dependencies = [
|
||||
"tmtccmd ~= 5.0",
|
||||
"tmtccmd == 6.0.0rc0",
|
||||
"python-dateutil ~= 2.8",
|
||||
# "tmtccmd @ git+https://github.com/robamu-org/tmtccmd@1b110d321ef85#egg=tmtccmd"
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
@ -40,9 +39,6 @@ dependencies = [
|
||||
[tool.setuptools]
|
||||
include-package-data = true
|
||||
|
||||
[tool.setuptools.dynamic]
|
||||
version = {attr = "eive_tmtc.__version__"}
|
||||
|
||||
# Auto-Discovery is problematic for some reason, so use custom-discovery
|
||||
[tool.setuptools.packages]
|
||||
find = {}
|
||||
|
@ -3,7 +3,7 @@ Checklist for new releases
|
||||
|
||||
# Pre-Release
|
||||
|
||||
1. Bump version inside the `eive_tmtc/__init__.py` file.
|
||||
1. Bump version inside the `pyproject.toml` file.
|
||||
2. Update `CHANGELOG.md`: Convert `unreleased` section into version section
|
||||
with date and new `unreleased`section.
|
||||
3. Run auto-formatter with `black .`
|
||||
|
33
tmtcc.py
33
tmtcc.py
@ -2,10 +2,11 @@
|
||||
import logging
|
||||
import sys
|
||||
import time
|
||||
import traceback
|
||||
from pathlib import Path
|
||||
from typing import cast
|
||||
|
||||
from spacepackets.ecss import PusVerificator
|
||||
from spacepackets.version import get_version as get_sp_version
|
||||
from spacepackets.ccsds import SPACE_PACKET_HEADER_SIZE
|
||||
from spacepackets.cfdp import (
|
||||
ConditionCode,
|
||||
@ -16,6 +17,8 @@ from spacepackets.cfdp import (
|
||||
PduFactory,
|
||||
PduType,
|
||||
)
|
||||
|
||||
import tmtccmd
|
||||
from tmtccmd.logging import add_colorlog_console_logger
|
||||
from tmtccmd.cfdp import CfdpUserBase, TransactionId
|
||||
from tmtccmd.cfdp.defs import CfdpRequestType
|
||||
@ -32,28 +35,6 @@ from tmtccmd.cfdp.user import (
|
||||
FileSegmentRecvdParams,
|
||||
)
|
||||
from tmtccmd.tc.handler import SendCbParams
|
||||
|
||||
try:
|
||||
import spacepackets
|
||||
except ImportError as error:
|
||||
print(error)
|
||||
print("Python spacepackets module could not be imported")
|
||||
print(
|
||||
'Install with "cd spacepackets && python3 -m pip intall -e ." for interative installation'
|
||||
)
|
||||
sys.exit(1)
|
||||
|
||||
try:
|
||||
import tmtccmd
|
||||
except ImportError:
|
||||
run_tmtc_commander = None
|
||||
initialize_tmtc_commander = None
|
||||
tb = traceback.format_exc()
|
||||
print(tb)
|
||||
print("Python tmtccmd submodule could not be imported")
|
||||
sys.exit(1)
|
||||
|
||||
from spacepackets.ecss import PusVerificator
|
||||
from tmtccmd import TcHandlerBase, BackendBase
|
||||
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
|
||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||
@ -86,7 +67,7 @@ from tmtccmd.config.args import (
|
||||
ProcedureParamsWrapper,
|
||||
)
|
||||
from eive_tmtc import APP_LOGGER
|
||||
from eive_tmtc import __version__
|
||||
from importlib.metadata import version
|
||||
from eive_tmtc.config.definitions import (
|
||||
PUS_APID,
|
||||
CFDP_APID,
|
||||
@ -449,8 +430,8 @@ def setup_backend(
|
||||
|
||||
|
||||
def main(): # noqa C901: Complexity okay here.
|
||||
print(f"-- eive tmtc v{__version__} --")
|
||||
print(f"-- spacepackets v{spacepackets.__version__} --")
|
||||
print(f"-- eive tmtc v{version('eive-tmtc')} --")
|
||||
print(f"-- spacepackets v{get_sp_version()} --")
|
||||
add_colorlog_console_logger(_LOGGER)
|
||||
# TODO: -V CLI argument to enable this?
|
||||
_LOGGER.setLevel(_LOG_LEVEL)
|
||||
|
Reference in New Issue
Block a user