Merge pull request 'Improvements to Loop Mode and HK Parsing' (#73) from mohr/looooop into develop

Reviewed-on: #73
This commit is contained in:
Robin Müller 2022-05-18 22:29:43 +02:00
commit 480e0f07e0
13 changed files with 268 additions and 62 deletions

View File

@ -47,3 +47,4 @@ class CustomServiceList(enum.Enum):
SUS_ASS = "sus-ass"
TCS_ASS = "tcs-ass"
TIME = "time"
CONTROLLERS = "controllers"

View File

@ -27,6 +27,7 @@ ACU_HANDLER_ID = bytes([0x44, 0x25, 0x00, 0x03])
BPX_HANDLER_ID = bytes([0x44, 0x26, 0x00, 0x00])
# Thermal Object IDs
THERMAL_CONTROLLER_ID = bytes([0x43, 0x40, 0x00, 0x01])
HEATER_ID = bytes([0x44, 0x41, 0x00, 0xA4])
TMP_1075_1_HANDLER_ID = bytes([0x44, 0x42, 0x00, 0x04])
TMP_1075_2_HANDLER_ID = bytes([0x44, 0x42, 0x00, 0x05])

View File

@ -949,6 +949,7 @@ def add_ploc_supv_cmds(cmd_dict: ServiceOpCodeDictT):
def add_system_cmds(cmd_dict: ServiceOpCodeDictT):
from pus_tc.system.acs import AcsOpCodes, SusOpCodes
import pus_tc.system.tcs as tcs
import pus_tc.system.controllers as controllers
default_opts = generate_op_code_options(
enter_listener_mode=False, custom_timeout=8.0
@ -1054,3 +1055,23 @@ def add_system_cmds(cmd_dict: ServiceOpCodeDictT):
info="TCS Board Assembly",
op_code_entry=op_code_dict,
)
op_code_dict = dict()
add_op_code_entry(
op_code_dict=op_code_dict,
keys=controllers.OpCodes.THERMAL_CONTROLLER,
info=controllers.Info.THERMAL_CONTROLLER,
options=default_opts,
)
add_op_code_entry(
op_code_dict=op_code_dict,
keys=controllers.OpCodes.CORE_CONTROLLER,
info=controllers.Info.CORE_CONTROLLER,
options=default_opts,
)
add_service_op_code_entry(
srv_op_code_dict=cmd_dict,
name=CustomServiceList.CONTROLLERS.value,
info="Controllers",
op_code_entry=op_code_dict,
)

View File

@ -3,8 +3,7 @@ from tmtccmd.tc.definitions import TcQueueT
from tmtccmd.tc.pus_200_fsfw_modes import Modes
from config.object_ids import ACS_BOARD_ASS_ID, SUS_BOARD_ASS_ID
from .common import command_assembly
from .common import command_mode
class AcsOpCodes:
ACS_ASS_A_SIDE = ["0", "acs-a"]
@ -31,7 +30,7 @@ class DualSideSubmodes(enum.IntEnum):
def pack_acs_command(tc_queue: TcQueueT, op_code: str):
if op_code in AcsOpCodes.ACS_ASS_A_SIDE:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.A_SIDE,
@ -39,7 +38,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching to ACS board assembly A side",
)
if op_code in AcsOpCodes.ACS_ASS_B_SIDE:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.B_SIDE,
@ -47,7 +46,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching to ACS board assembly B side",
)
if op_code in AcsOpCodes.ACS_ASS_DUAL_MODE:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.DUAL_SIDE,
@ -55,7 +54,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching to ACS board assembly dual mode",
)
if op_code in AcsOpCodes.ACS_ASS_A_ON:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.ON,
submode=DualSideSubmodes.A_SIDE,
@ -63,7 +62,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching ACS board assembly A side on",
)
if op_code in AcsOpCodes.ACS_ASS_B_ON:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.ON,
submode=DualSideSubmodes.B_SIDE,
@ -71,7 +70,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching ACS board assembly B side on",
)
if op_code in AcsOpCodes.ACS_ASS_DUAL_ON:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.ON,
submode=DualSideSubmodes.B_SIDE,
@ -79,7 +78,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
info="Switching ACS board assembly dual side on",
)
if op_code in AcsOpCodes.ACS_ASS_OFF:
command_assembly(
command_mode(
object_id=ACS_BOARD_ASS_ID,
mode=Modes.OFF,
submode=0,
@ -90,7 +89,7 @@ def pack_acs_command(tc_queue: TcQueueT, op_code: str):
def pack_sus_cmds(tc_queue: TcQueueT, op_code: str):
if op_code in SusOpCodes.SUS_ASS_NOM_SIDE:
command_assembly(
command_mode(
object_id=SUS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.A_SIDE,
@ -98,7 +97,7 @@ def pack_sus_cmds(tc_queue: TcQueueT, op_code: str):
info="Switching to SUS board to nominal side",
)
if op_code in SusOpCodes.SUS_ASS_RED_SIDE:
command_assembly(
command_mode(
object_id=SUS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.B_SIDE,
@ -106,7 +105,7 @@ def pack_sus_cmds(tc_queue: TcQueueT, op_code: str):
info="Switching to SUS board to redundant side",
)
if op_code in SusOpCodes.SUS_ASS_OFF:
command_assembly(
command_mode(
object_id=SUS_BOARD_ASS_ID,
mode=Modes.OFF,
submode=0,
@ -114,7 +113,7 @@ def pack_sus_cmds(tc_queue: TcQueueT, op_code: str):
info="Switching SUS board off",
)
if op_code in SusOpCodes.SUS_ASS_DUAL_MODE:
command_assembly(
command_mode(
object_id=SUS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=DualSideSubmodes.DUAL_SIDE,

View File

@ -3,7 +3,7 @@ from spacepackets.ecss.tc import PusTelecommand
from tmtccmd.tc.pus_200_fsfw_modes import pack_mode_data, Modes, Subservices
def command_assembly(
def command_mode(
object_id: bytes, mode: Modes, submode: int, tc_queue: TcQueueT, info: str
):
tc_queue.appendleft((QueueCommands.PRINT, info))

View File

@ -0,0 +1,44 @@
from ast import Pass
from tmtccmd.tc.definitions import TcQueueT
from .common import command_mode
import config.object_ids as obj_ids
class OpCodes:
THERMAL_CONTROLLER = [obj_ids.THERMAL_CONTROLLER_ID.hex(), "thermal_controller"]
CORE_CONTROLLER = [obj_ids.CORE_CONTROLLER_ID.hex(), "core_controller"]
class Info:
THERMAL_CONTROLLER = "Thermal controller"
CORE_CONTROLLER = "ACS controller"
def pack_controller_commands(tc_queue: TcQueueT, op_code: str):
mode = int(input("Specify mode: (OFF = 0; ON = 1; NORMAL = 2) [2] ") or "2")
print(mode)
if mode < 0 or mode > 2:
print("Invalid Mode, defaulting to OFF")
mode = 0
submode = int(input("Specify submode [0]: ") or "0")
command_mode(
object_id=get_object_from_op_code(op_code),
mode=mode,
submode=submode,
tc_queue=tc_queue,
info=op_code + " to " + str(mode) + "," + str(submode),
)
def get_object_from_op_code(op_code: str):
try:
return bytes.fromhex(op_code)
except:
pass
if op_code in OpCodes.THERMAL_CONTROLLER:
return obj_ids.THERMAL_CONTROLLER_ID
if op_code in OpCodes.CORE_CONTROLLER:
return obj_ids.CORE_CONTROLLER_ID

View File

@ -1,7 +1,7 @@
from tmtccmd.tc.definitions import TcQueueT, QueueCommands
from tmtccmd.tc.pus_200_fsfw_modes import Modes
from .common import command_assembly
from .common import command_mode
from config.object_ids import TCS_BOARD_ASS_ID
@ -17,7 +17,7 @@ class Info:
def pack_tcs_sys_commands(tc_queue: TcQueueT, op_code: str):
if op_code in OpCodes.TCS_BOARD_ASS_NORMAL:
command_assembly(
command_mode(
object_id=TCS_BOARD_ASS_ID,
mode=Modes.NORMAL,
submode=0,
@ -25,7 +25,7 @@ def pack_tcs_sys_commands(tc_queue: TcQueueT, op_code: str):
info=Info.TCS_BOARD_ASS_NORMAL,
)
if op_code in OpCodes.TCS_BOARD_ASS_OFF:
command_assembly(
command_mode(
object_id=TCS_BOARD_ASS_ID,
mode=Modes.OFF,
submode=0,

View File

@ -40,6 +40,7 @@ from pus_tc.system.acs import pack_acs_command, pack_sus_cmds
from pus_tc.devs.plpcdu import pack_pl_pcdu_commands
from pus_tc.devs.str_img_helper import pack_str_img_helper_command
from pus_tc.system.tcs import pack_tcs_sys_commands
from pus_tc.system.controllers import pack_controller_commands
from config.definitions import CustomServiceList
from config.object_ids import (
P60_DOCK_HANDLER,
@ -234,6 +235,8 @@ def pack_service_queue_user(
return pack_rw_ass_cmds(
tc_queue=service_queue, object_id=RW_ASSEMBLY, op_code=op_code
)
if service == CustomServiceList.CONTROLLERS.value:
return pack_controller_commands(tc_queue=service_queue, op_code=op_code)
LOGGER.warning("Invalid Service !")

View File

@ -33,6 +33,7 @@ def ccsds_tm_handler(apid: int, raw_tm_packet: bytes, _user_args: any) -> None:
pus_factory_hook(raw_tm_packet=raw_tm_packet)
def pus_factory_hook(raw_tm_packet: bytes):
if len(raw_tm_packet) < 8:
LOGGER.warning("Detected packet shorter than 8 bytes!")

View File

@ -3,6 +3,8 @@ import struct
import os
import datetime
from tmtccmd.config.definitions import HkReplyUnpacked
from tmtccmd.tm.pus_3_fsfw_hk import (
Service3Base,
@ -20,8 +22,14 @@ import config.object_ids as obj_ids
from pus_tm.devs.reaction_wheels import handle_rw_hk_data
from pus_tm.defs import FsfwTmTcPrinter, log_to_both
from pus_tm.tm_tcp_server import TmTcpServer
LOGGER = get_console_logger()
TM_TCP_SERVER = TmTcpServer.getInstance()
def handle_hk_packet(
raw_tm: bytes,
@ -34,6 +42,9 @@ def handle_hk_packet(
named_obj_id = tm_packet.object_id
if tm_packet.subservice == 25 or tm_packet.subservice == 26:
hk_data = tm_packet.tm_data[8:]
TM_TCP_SERVER.report_raw_hk_data(object_id=named_obj_id,
set_id=tm_packet.set_id,
hk_data=hk_data)
printer.generic_hk_tm_print(
content_type=HkContentType.HK,
object_id=named_obj_id,
@ -49,7 +60,6 @@ def handle_hk_packet(
if tm_packet.subservice == 10 or tm_packet.subservice == 12:
LOGGER.warning("HK definitions printout not implemented yet")
def handle_regular_hk_print(
printer: FsfwTmTcPrinter,
object_id: ObjectId,
@ -97,12 +107,13 @@ def handle_regular_hk_print(
handle_p60_hk_data(printer=printer, set_id=set_id, hk_data=hk_data)
if objb == obj_ids.PL_PCDU_ID:
log_to_both(printer, "Received PL PCDU HK data")
if objb == obj_ids.THERMAL_CONTROLLER_ID:
handle_thermal_controller_hk_data( object_id=object_id, printer=printer, set_id=set_id, hk_data=hk_data)
else:
LOGGER.info("Service 3 TM: Parsing for this SID has not been implemented.")
return HkReplyUnpacked()
def handle_syrlinks_rx_registers_dataset(printer: FsfwTmTcPrinter, hk_data: bytes):
def handle_syrlinks_rx_registers_dataset( printer: FsfwTmTcPrinter, hk_data: bytes):
reply = HkReplyUnpacked()
header_list = [
"RX Status",
@ -137,7 +148,6 @@ def handle_syrlinks_rx_registers_dataset(printer: FsfwTmTcPrinter, hk_data: byte
log_to_both(printer, str(content_list))
printer.print_validity_buffer(validity_buffer=validity_buffer, num_vars=8)
def handle_syrlinks_tx_registers_dataset(
printer: FsfwTmTcPrinter,
hk_data: bytes,
@ -153,7 +163,6 @@ def handle_syrlinks_tx_registers_dataset(
log_to_both(printer, str(content_list))
printer.print_validity_buffer(validity_buffer=validity_buffer, num_vars=3)
def handle_self_test_data(printer: FsfwTmTcPrinter, hk_data: bytes):
header_list = [
"Init Err",
@ -258,7 +267,7 @@ def handle_self_test_data(printer: FsfwTmTcPrinter, hk_data: bytes):
init_coil_z_temperature,
err,
raw_mag_x,
init_raw_mag_y,
raw_mag_y,
raw_mag_z,
cal_mag_x,
cal_mag_y,
@ -288,6 +297,34 @@ def handle_self_test_data(printer: FsfwTmTcPrinter, hk_data: bytes):
log_to_both(printer, str(content_list))
printer.print_validity_buffer(validity_buffer=validity_buffer, num_vars=num_of_vars)
def handle_thermal_controller_hk_data(object_id: ObjectId, printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
if set_id == 0:
LOGGER.info("Received Sensor Temperature data")
# get all the floats
tm_data = struct.unpack("!ffffffffffffffff", hk_data[:16 * 4])
parsed_data = {}
# put them into an list with their names
parsed_data = []
parsed_data.append({"SENSOR_PLOC_HEATSPREADER": tm_data[0]})
parsed_data.append({"SENSOR_PLOC_MISSIONBOARD": tm_data[1]})
parsed_data.append({"SENSOR_4K_CAMERA": tm_data[2]})
parsed_data.append({"SENSOR_DAC_HEATSPREADER": tm_data[3]})
parsed_data.append({"SENSOR_STARTRACKER": tm_data[4]})
parsed_data.append({"SENSOR_RW1": tm_data[5]})
parsed_data.append({"SENSOR_DRO": tm_data[6]})
parsed_data.append({"SENSOR_SCEX": tm_data[7]})
parsed_data.append({"SENSOR_X8": tm_data[8]})
parsed_data.append({"SENSOR_HPA": tm_data[9]})
parsed_data.append({"SENSOR_TX_MODUL": tm_data[10]})
parsed_data.append({"SENSOR_MPA": tm_data[11]})
parsed_data.append({"SENSOR_ACU": tm_data[12]})
parsed_data.append({"SENSOR_PLPCDU_HEATSPREADER": tm_data[13]})
parsed_data.append({"SENSOR_TCS_BOARD": tm_data[14]})
parsed_data.append({"SENSOR_MAGNETTORQUER": tm_data[15]})
TM_TCP_SERVER.report_parsed_hk_data(object_id, set_id, parsed_data)
def handle_gps_data(printer: FsfwTmTcPrinter, hk_data: bytes):
LOGGER.info(f"Received GPS data, HK data length {len(hk_data)}")
@ -342,7 +379,6 @@ def handle_gps_data(printer: FsfwTmTcPrinter, hk_data: bytes):
log_to_both(printer, str(content_list))
printer.print_validity_buffer(validity_buffer=validity_buffer, num_vars=10)
def handle_bpx_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
if set_id == BpxSetIds.GET_HK_SET:
fmt_str = "!HHHHhhhhIB"
@ -402,13 +438,12 @@ def handle_bpx_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
log_to_both(printer, str(content_list))
printer.print_validity_buffer(validity_buffer=validity_buffer, num_vars=10)
def handle_core_hk_data(printer: FsfwTmTcPrinter, hk_data: bytes):
fmt_str = "!fffH"
inc_len = struct.calcsize(fmt_str)
(temperature, ps_voltage, pl_voltage, tx_agc_value) = struct.unpack(
fmt_str, hk_data[0 : 0 + inc_len]
fmt_str, hk_data[0: 0 + inc_len]
)
printout = (
f"Chip Temperature [°C] {temperature} | PS Voltage [mV] {ps_voltage} | "
@ -417,7 +452,6 @@ def handle_core_hk_data(printer: FsfwTmTcPrinter, hk_data: bytes):
log_to_both(printer, printout)
printer.print_validity_buffer(validity_buffer=hk_data[inc_len:], num_vars=4)
P60_INDEX_LIST = [
"ACU VCC",
"PDU1 VCC",
@ -462,7 +496,6 @@ PDU2_CHANNELS_NAMES = [
PDU_CHANNEL_NAMES = [PDU1_CHANNELS_NAMES, PDU2_CHANNELS_NAMES]
class WdtInfo:
def __init__(self):
self.wdt_reboots_list = []
@ -474,7 +507,7 @@ class WdtInfo:
for idx in range(len(self.wdt_reboots_list)):
log_to_both(
printer,
f"{WDT_LIST[idx].ljust(5)} | "
f"{TmHandler.WDT_LIST[idx].ljust(5)} | "
f"{self.wdt_reboots_list[idx]:010} | {self.time_pings_left_list[idx]:010}",
)
@ -484,13 +517,13 @@ class WdtInfo:
self.time_pings_left_list = []
for idx in range(5):
self.wdt_reboots_list.append(
struct.unpack("!I", wdt_data[priv_idx : priv_idx + 4])[0]
struct.unpack("!I", wdt_data[priv_idx: priv_idx + 4])[0]
)
priv_idx += 4
current_idx += 4
for idx in range(3):
self.time_pings_left_list.append(
struct.unpack("!I", wdt_data[priv_idx : priv_idx + 4])[0]
struct.unpack("!I", wdt_data[priv_idx: priv_idx + 4])[0]
)
priv_idx += 4
current_idx += 4
@ -500,7 +533,6 @@ class WdtInfo:
priv_idx += 1
return current_idx
def handle_pdu_data(
printer: FsfwTmTcPrinter, pdu_idx: int, set_id: int, hk_data: bytes
):
@ -518,7 +550,7 @@ def handle_pdu_data(
boot_cause,
uptime,
reset_cause,
) = struct.unpack(fmt_str, hk_data[current_idx : current_idx + inc_len])
) = struct.unpack(fmt_str, hk_data[current_idx: current_idx + inc_len])
log_to_both(printer, f"VCC {vcc} mV | VBAT {vbat} mV")
log_to_both(
printer, f"Converter Enables [{conv_enb_0},{conv_enb_1},{conv_enb_2}]"
@ -530,21 +562,21 @@ def handle_pdu_data(
current_idx += inc_len
latchup_list = []
log_to_both(printer, "Latchups")
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
latchup_list.append(
struct.unpack("!H", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!H", hk_data[current_idx: current_idx + 2])[0]
)
content_line = (
f"{PDU_CHANNEL_NAMES[priv_idx][idx].ljust(24)} | {latchup_list[idx]}"
f"{TmHandler.PDU_CHANNEL_NAMES[priv_idx][idx].ljust(24)} | {latchup_list[idx]}"
)
log_to_both(printer, content_line)
current_idx += 2
device_types = []
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
device_types.append(hk_data[current_idx])
current_idx += 1
device_statuses = []
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
device_statuses.append(hk_data[current_idx])
current_idx += 1
wdt = WdtInfo()
@ -553,35 +585,35 @@ def handle_pdu_data(
if set_id == SetIds.PDU_1_CORE or set_id == SetIds.PDU_2_CORE:
log_to_both(printer, f"Received PDU HK from PDU {pdu_idx}")
current_list = []
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
current_list.append(
struct.unpack("!h", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!h", hk_data[current_idx: current_idx + 2])[0]
)
current_idx += 2
voltage_list = []
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
voltage_list.append(
struct.unpack("!H", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!H", hk_data[current_idx: current_idx + 2])[0]
)
current_idx += 2
output_enb_list = []
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
output_enb_list.append(hk_data[current_idx])
current_idx += 1
header_str = f"{'Name'.ljust(24)} | OutEnb | U [mV] | I [mA]"
print(header_str)
printer.file_logger.info(header_str)
for idx in range(len(PDU1_CHANNELS_NAMES)):
for idx in range(len(TmHandler.PDU1_CHANNELS_NAMES)):
out_enb = f"{output_enb_list[idx]}".ljust(6)
content_line = (
f"{PDU_CHANNEL_NAMES[priv_idx][idx].ljust(24)} | {out_enb} | "
f"{TmHandler.PDU_CHANNEL_NAMES[priv_idx][idx].ljust(24)} | {out_enb} | "
f"{voltage_list[idx]:05} | {current_list[idx]:04}"
)
log_to_both(printer, content_line)
fmt_str = "!IBh"
inc_len = struct.calcsize(fmt_str)
(boot_count, batt_mode, temperature) = struct.unpack(
fmt_str, hk_data[current_idx : current_idx + inc_len]
fmt_str, hk_data[current_idx: current_idx + inc_len]
)
info = (
f"Boot Count {boot_count} | Battery Mode {batt_mode} | "
@ -589,7 +621,6 @@ def handle_pdu_data(
)
log_to_both(printer, info)
def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
if set_id == SetIds.P60_CORE:
log_to_both(printer, "Received P60 Core HK. Voltages in mV, currents in mA")
@ -597,13 +628,13 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
current_list = []
for idx in range(13):
current_list.append(
struct.unpack("!h", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!h", hk_data[current_idx: current_idx + 2])[0]
)
current_idx += 2
voltage_list = []
for idx in range(13):
voltage_list.append(
struct.unpack("!H", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!H", hk_data[current_idx: current_idx + 2])[0]
)
current_idx += 2
out_enb_list = []
@ -616,7 +647,7 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
for idx in range(13):
out_enb = f"{out_enb_list[idx]}".ljust(6)
content_line = (
f"{P60_INDEX_LIST[idx].ljust(24)} | {out_enb} | "
f"{TmHandler.P60_INDEX_LIST[idx].ljust(24)} | {out_enb} | "
f"{voltage_list[idx]:05} | {current_list[idx]:04}"
)
log_to_both(printer, content_line)
@ -629,7 +660,7 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
batt_voltage,
temp_0,
temp_1,
) = struct.unpack(fmt_str, hk_data[current_idx : current_idx + inc_len])
) = struct.unpack(fmt_str, hk_data[current_idx: current_idx + inc_len])
current_idx += inc_len
batt_info = (
f"Batt: Mode {batt_mode} | Boot Count {boot_count} | "
@ -646,9 +677,9 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
log_to_both(printer, "P60 Dock Latchups")
for idx in range(0, 13):
latchup_list.append(
struct.unpack("!H", hk_data[current_idx : current_idx + 2])[0]
struct.unpack("!H", hk_data[current_idx: current_idx + 2])[0]
)
content_line = f"{P60_INDEX_LIST[idx].ljust(24)} | {latchup_list[idx]}"
content_line = f"{TmHandler.P60_INDEX_LIST[idx].ljust(24)} | {latchup_list[idx]}"
log_to_both(printer, content_line)
current_idx += 2
fmt_str = "!IIHBBHHhhB"
@ -664,7 +695,7 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
batt_temp_0,
batt_temp_1,
dearm_status,
) = struct.unpack(fmt_str, hk_data[current_idx : current_idx + inc_len])
) = struct.unpack(fmt_str, hk_data[current_idx: current_idx + inc_len])
current_idx += inc_len
wdt = WdtInfo()
current_idx = wdt.parse(wdt_data=hk_data[current_idx:], current_idx=current_idx)
@ -675,7 +706,7 @@ def handle_p60_hk_data(printer: FsfwTmTcPrinter, set_id: int, hk_data: bytes):
batt_discharge_current,
ant6_depl,
ar6_depl,
) = struct.unpack(fmt_str, hk_data[current_idx : current_idx + inc_len])
) = struct.unpack(fmt_str, hk_data[current_idx: current_idx + inc_len])
current_idx += inc_len
device_types = []
device_statuses = []

102
pus_tm/tm_tcp_server.py Normal file
View File

@ -0,0 +1,102 @@
import socket
from typing import Optional
import json
import base64
from tmtccmd.logging import get_console_logger
from tmtccmd.utility.obj_id import ObjectId
from dle_encoder import DleEncoder
# TODO add to configuration parameters
SERVER_HOST = ""
SERVER_PORT = 7305
LOGGER = get_console_logger()
class TmTcpServer:
_Instance = None
def __init__(
self):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.bind((SERVER_HOST, SERVER_PORT))
# for now, only accept one connection
self.server_socket.listen(0)
self.server_socket.setblocking(False)
self.client_connection: Optional[socket.socket] = None
self.dle_encoder = DleEncoder()
def __del__(self):
try:
self.close()
except:
LOGGER.warning("Could not close sockets!")
def close(self):
self.server_socket.close()
if self.client_connection != None:
self.client_connection.close()
def getInstance():
if TmTcpServer._Instance == None:
TmTcpServer._Instance = TmTcpServer()
return TmTcpServer._Instance
def _send_dictionary_over_socket(self, dictionary):
# keep listeners current
if self.client_connection == None:
# no running connection, see if a client wants to connect
try:
(self.client_connection, _) = self.server_socket.accept()
self.client_connection.setblocking(False)
except:
# no client waiting
return
data_json_bytes = json.dumps(dictionary).encode()
# dle encode the bytes
# adding a newline because someone might want to look at it in a console
data_json_bytes = self.dle_encoder.encode(data_json_bytes + b'\n')
try:
sent_length = self.client_connection.send(data_json_bytes)
except:
self.client_connection = None
return
if sent_length == 0:
self.client_connection.close()
self.client_connection = None
def report_raw_hk_data(self, object_id: ObjectId,
set_id: int,
hk_data: bytes):
data_dict = {}
data_dict["type"] = "TM"
data_dict["tmType"] = "Raw HK"
data_dict["objectId"] = object_id.as_string
data_dict["setId"] = set_id
data_dict["rawData"] = base64.b64encode(hk_data).decode()
self._send_dictionary_over_socket(data_dict)
def report_parsed_hk_data(self, object_id: ObjectId,
set_id: int,
data_dictionary):
data_dict = {}
data_dict["type"] = "TM"
data_dict["tmType"] = "Parsed HK"
data_dict["objectId"] = object_id.as_string
data_dict["setId"] = set_id
data_dict["content"] = data_dictionary
self._send_dictionary_over_socket(data_dict)

@ -1 +1 @@
Subproject commit e81e6dbd594c1cdf51cd355a724cbd267d9dee38
Subproject commit 862fdf23bc4a90ced47ee1c811de4237e3508536

View File

@ -1,5 +1,6 @@
#!/usr/bin/env python3
"""EIVE TMTC Commander"""
from distutils.log import debug
import sys
import traceback
@ -11,6 +12,7 @@ try:
create_default_args_parser,
add_default_tmtccmd_args,
parse_default_input_arguments,
handle_unspecified_args,
)
from tmtccmd.ccsds.handler import CcsdsTmHandler, ApidHandler
from tmtccmd.logging import get_console_logger
@ -62,7 +64,7 @@ def main():
tmtc_backend.set_mode(CoreModeList.CONTINUOUS_MODE)
get_console_logger().info("Disabling console logger for continuous operation")
get_console_logger().disabled = True
get_console_logger().setLevel("ERROR")
tmtccmd.init_and_start_daemons(tmtc_backend=tmtc_backend)
tmtccmd.performOperation(tmtc_backend=tmtc_backend)
@ -71,11 +73,12 @@ def main():
sys.argv = sys.argv[:1]
while True:
args = parse_default_input_arguments(arg_parser, hook_obj)
setup_args = SetupArgs(
hook_obj=hook_obj, use_gui=False, apid=PUS_APID, cli_args=args
)
tmtccmd.setup(setup_args=setup_args)
args.service = None
args.op_code = None
handle_unspecified_args(args, hook_obj.get_service_op_code_dictionary())
tmtc_backend.set_service(args.service)
tmtc_backend.set_opcode(args.op_code)
tmtc_backend.set_mode(CoreModeList.CONTINUOUS_MODE)
tmtccmd.performOperation(tmtc_backend=tmtc_backend)