Merge branch 'introduce_tm_db' into bump-tmtccmd
All checks were successful
EIVE/-/pipeline/pr-main This commit looks good
All checks were successful
EIVE/-/pipeline/pr-main This commit looks good
This commit is contained in:
commit
507c3e3ff3
4
.gitignore
vendored
4
.gitignore
vendored
@ -28,3 +28,7 @@ log
|
|||||||
/.installed.cfg
|
/.installed.cfg
|
||||||
/*.egg
|
/*.egg
|
||||||
/MANIFEST
|
/MANIFEST
|
||||||
|
|
||||||
|
# Telemetry database.
|
||||||
|
/tm.db
|
||||||
|
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
from .definitions import * # noqa
|
@ -11,6 +11,10 @@ from spacepackets.ccsds import PacketId
|
|||||||
from spacepackets.util import UnsignedByteField
|
from spacepackets.util import UnsignedByteField
|
||||||
|
|
||||||
|
|
||||||
|
TM_DB_PATH = "tm.db"
|
||||||
|
# Separate DB or not? Not sure..
|
||||||
|
# RAW_TM_PATH = "raw_tm.db"
|
||||||
|
|
||||||
PUS_APID = 0x65
|
PUS_APID = 0x65
|
||||||
CFDP_APID = 0x66
|
CFDP_APID = 0x66
|
||||||
PUS_PACKET_ID = PacketId(PacketType.TM, True, PUS_APID)
|
PUS_PACKET_ID = PacketId(PacketType.TM, True, PUS_APID)
|
||||||
|
21
eive_tmtc/pus_tm/hk.py
Normal file
21
eive_tmtc/pus_tm/hk.py
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
import uuid
|
||||||
|
import dataclasses
|
||||||
|
import datetime
|
||||||
|
import sqlite3
|
||||||
|
from tmtccmd.pus.tm.s3_fsfw_hk import Service3FsfwTm
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class HkTmInfo:
|
||||||
|
packet_uuid: uuid.UUID
|
||||||
|
hk_packet: Service3FsfwTm
|
||||||
|
db_con: sqlite3.Connection
|
||||||
|
hk_data: bytes
|
||||||
|
|
||||||
|
@property
|
||||||
|
def packet_datetime(self) -> datetime.datetime:
|
||||||
|
return self.hk_packet.pus_tm.time_provider.as_datetime()
|
||||||
|
|
||||||
|
@property
|
||||||
|
def set_id(self) -> int:
|
||||||
|
return self.hk_packet.set_id
|
@ -1,7 +1,10 @@
|
|||||||
"""HK Handling for EIVE OBSW"""
|
"""HK Handling for EIVE OBSW"""
|
||||||
import dataclasses
|
import dataclasses
|
||||||
import logging
|
import logging
|
||||||
from typing import List
|
import sqlite3
|
||||||
|
from typing import List, cast
|
||||||
|
from uuid import UUID
|
||||||
|
from eive_tmtc.pus_tm.hk import HkTmInfo
|
||||||
|
|
||||||
from eive_tmtc.tmtc.acs.acs_ctrl import handle_acs_ctrl_hk_data
|
from eive_tmtc.tmtc.acs.acs_ctrl import handle_acs_ctrl_hk_data
|
||||||
from eive_tmtc.tmtc.internal_err_reporter import handle_ier_hk_data
|
from eive_tmtc.tmtc.internal_err_reporter import handle_ier_hk_data
|
||||||
@ -16,9 +19,7 @@ from eive_tmtc.tmtc.acs.reaction_wheels import handle_rw_hk_data
|
|||||||
from eive_tmtc.tmtc.com.syrlinks_handler import handle_syrlinks_hk_data
|
from eive_tmtc.tmtc.com.syrlinks_handler import handle_syrlinks_hk_data
|
||||||
from eive_tmtc.tmtc.tcs import handle_thermal_controller_hk_data
|
from eive_tmtc.tmtc.tcs import handle_thermal_controller_hk_data
|
||||||
from eive_tmtc.tmtc.tcs.tmp1075 import handle_tmp_1075_hk_data
|
from eive_tmtc.tmtc.tcs.tmp1075 import handle_tmp_1075_hk_data
|
||||||
from spacepackets.ecss import PusTelemetry
|
|
||||||
from tmtccmd.pus.tm.s3_fsfw_hk import (
|
from tmtccmd.pus.tm.s3_fsfw_hk import (
|
||||||
Service3Base,
|
|
||||||
HkContentType,
|
HkContentType,
|
||||||
Service3FsfwTm,
|
Service3FsfwTm,
|
||||||
)
|
)
|
||||||
@ -56,13 +57,15 @@ class HkFilter:
|
|||||||
|
|
||||||
def handle_hk_packet(
|
def handle_hk_packet(
|
||||||
raw_tm: bytes,
|
raw_tm: bytes,
|
||||||
|
packet_uuid: UUID,
|
||||||
obj_id_dict: ObjectIdDictT,
|
obj_id_dict: ObjectIdDictT,
|
||||||
printer: FsfwTmTcPrinter,
|
printer: FsfwTmTcPrinter,
|
||||||
hk_filter: HkFilter,
|
hk_filter: HkFilter,
|
||||||
hk_level: int,
|
hk_level: int,
|
||||||
|
db_con: sqlite3.Connection,
|
||||||
):
|
):
|
||||||
tm_packet = Service3FsfwTm.unpack(raw_telemetry=raw_tm, custom_hk_handling=False)
|
tm_packet = Service3FsfwTm.unpack(raw_telemetry=raw_tm, custom_hk_handling=False)
|
||||||
named_obj_id = obj_id_dict.get(tm_packet.object_id.as_bytes)
|
named_obj_id = cast(ObjectIdU32, obj_id_dict.get(tm_packet.object_id.as_bytes))
|
||||||
if named_obj_id is None:
|
if named_obj_id is None:
|
||||||
named_obj_id = tm_packet.object_id
|
named_obj_id = tm_packet.object_id
|
||||||
if tm_packet.subservice == 25 or tm_packet.subservice == 26:
|
if tm_packet.subservice == 25 or tm_packet.subservice == 26:
|
||||||
@ -73,8 +76,9 @@ def handle_hk_packet(
|
|||||||
printer=printer,
|
printer=printer,
|
||||||
object_id=named_obj_id,
|
object_id=named_obj_id,
|
||||||
hk_packet=tm_packet,
|
hk_packet=tm_packet,
|
||||||
tm=tm_packet.pus_tm,
|
tm_packet=tm_packet.pus_tm,
|
||||||
hk_data=hk_data,
|
hk_data=hk_data,
|
||||||
|
db=db_con,
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
try:
|
try:
|
||||||
@ -85,10 +89,11 @@ def handle_hk_packet(
|
|||||||
if hk_level >= 1:
|
if hk_level >= 1:
|
||||||
handle_regular_hk_print(
|
handle_regular_hk_print(
|
||||||
printer=printer,
|
printer=printer,
|
||||||
|
packet_uuid=packet_uuid,
|
||||||
object_id=named_obj_id,
|
object_id=named_obj_id,
|
||||||
hk_packet=tm_packet,
|
hk_packet=tm_packet,
|
||||||
tm=tm_packet.pus_tm,
|
|
||||||
hk_data=hk_data,
|
hk_data=hk_data,
|
||||||
|
db=db_con,
|
||||||
)
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
@ -99,26 +104,37 @@ def handle_hk_packet(
|
|||||||
|
|
||||||
|
|
||||||
def handle_regular_hk_print( # noqa C901: Complexity okay here
|
def handle_regular_hk_print( # noqa C901: Complexity okay here
|
||||||
printer: FsfwTmTcPrinter,
|
hk_packet: Service3FsfwTm,
|
||||||
object_id: ObjectIdU32,
|
packet_uuid: UUID,
|
||||||
hk_packet: Service3Base,
|
|
||||||
tm: PusTelemetry,
|
|
||||||
hk_data: bytes,
|
hk_data: bytes,
|
||||||
|
db: sqlite3.Connection,
|
||||||
|
object_id: ObjectIdU32,
|
||||||
|
printer: FsfwTmTcPrinter,
|
||||||
):
|
):
|
||||||
objb = object_id.as_bytes
|
objb = object_id.as_bytes
|
||||||
set_id = hk_packet.set_id
|
set_id = hk_packet.set_id
|
||||||
packet_dt = tm.time_provider.as_date_time()
|
hk_info = HkTmInfo(
|
||||||
|
packet_uuid=packet_uuid, hk_packet=hk_packet, db_con=db, hk_data=hk_data
|
||||||
|
)
|
||||||
|
assert hk_packet.pus_tm.time_provider is not None
|
||||||
|
packet_dt = hk_packet.pus_tm.time_provider.as_date_time()
|
||||||
pw = PrintWrapper(printer.file_logger)
|
pw = PrintWrapper(printer.file_logger)
|
||||||
"""This function is called when a Service 3 Housekeeping packet is received."""
|
"""This function is called when a Service 3 Housekeeping packet is received."""
|
||||||
if objb in [obj_ids.RW1_ID, obj_ids.RW2_ID, obj_ids.RW3_ID, obj_ids.RW4_ID]:
|
if objb in [obj_ids.RW1_ID, obj_ids.RW2_ID, obj_ids.RW3_ID, obj_ids.RW4_ID]:
|
||||||
return handle_rw_hk_data(pw, object_id, set_id, hk_data)
|
return handle_rw_hk_data(pw, object_id, set_id, hk_data)
|
||||||
elif objb == obj_ids.SYRLINKS_HANDLER_ID:
|
elif objb == obj_ids.SYRLINKS_HANDLER_ID:
|
||||||
return handle_syrlinks_hk_data(pw=pw, hk_data=hk_data, set_id=set_id)
|
return handle_syrlinks_hk_data(
|
||||||
|
hk_info=hk_info,
|
||||||
|
pw=pw,
|
||||||
|
)
|
||||||
elif objb == obj_ids.IMTQ_HANDLER_ID:
|
elif objb == obj_ids.IMTQ_HANDLER_ID:
|
||||||
return handle_imtq_hk(pw=pw, hk_data=hk_data, set_id=set_id)
|
return handle_imtq_hk(pw=pw, hk_data=hk_data, set_id=set_id)
|
||||||
elif objb == obj_ids.GPS_CONTROLLER:
|
elif objb == obj_ids.GPS_CONTROLLER:
|
||||||
return handle_gps_data(
|
return handle_gps_data(
|
||||||
pw=pw, set_id=set_id, hk_data=hk_data, packet_time=packet_dt
|
pw=pw,
|
||||||
|
set_id=set_id,
|
||||||
|
hk_data=hk_data,
|
||||||
|
packet_time=packet_dt,
|
||||||
)
|
)
|
||||||
elif objb == obj_ids.PCDU_HANDLER_ID:
|
elif objb == obj_ids.PCDU_HANDLER_ID:
|
||||||
return handle_pcdu_hk(pw=pw, set_id=set_id, hk_data=hk_data)
|
return handle_pcdu_hk(pw=pw, set_id=set_id, hk_data=hk_data)
|
||||||
@ -127,9 +143,21 @@ def handle_regular_hk_print( # noqa C901: Complexity okay here
|
|||||||
elif objb == obj_ids.CORE_CONTROLLER_ID:
|
elif objb == obj_ids.CORE_CONTROLLER_ID:
|
||||||
return handle_core_hk_data(pw=pw, hk_data=hk_data, set_id=set_id)
|
return handle_core_hk_data(pw=pw, hk_data=hk_data, set_id=set_id)
|
||||||
elif objb == obj_ids.PDU_1_HANDLER_ID:
|
elif objb == obj_ids.PDU_1_HANDLER_ID:
|
||||||
return handle_pdu_data(pw=pw, pdu_idx=1, set_id=set_id, hk_data=hk_data)
|
return handle_pdu_data(
|
||||||
|
hk_info=hk_info,
|
||||||
|
pw=pw,
|
||||||
|
pdu_idx=1,
|
||||||
|
set_id=set_id,
|
||||||
|
hk_data=hk_data,
|
||||||
|
)
|
||||||
elif objb == obj_ids.PDU_2_HANDLER_ID:
|
elif objb == obj_ids.PDU_2_HANDLER_ID:
|
||||||
return handle_pdu_data(pw=pw, pdu_idx=2, set_id=set_id, hk_data=hk_data)
|
return handle_pdu_data(
|
||||||
|
hk_info=hk_info,
|
||||||
|
pw=pw,
|
||||||
|
pdu_idx=2,
|
||||||
|
set_id=set_id,
|
||||||
|
hk_data=hk_data,
|
||||||
|
)
|
||||||
elif objb == obj_ids.PLOC_MPSOC_ID:
|
elif objb == obj_ids.PLOC_MPSOC_ID:
|
||||||
return handle_ploc_mpsoc_hk_data(pw=pw, hk_data=hk_data, set_id=set_id)
|
return handle_ploc_mpsoc_hk_data(pw=pw, hk_data=hk_data, set_id=set_id)
|
||||||
elif objb == obj_ids.ACU_HANDLER_ID:
|
elif objb == obj_ids.ACU_HANDLER_ID:
|
||||||
|
@ -1,126 +0,0 @@
|
|||||||
"""Core EIVE TM handler module
|
|
||||||
"""
|
|
||||||
import logging
|
|
||||||
|
|
||||||
from spacepackets.ccsds.time import CdsShortTimestamp
|
|
||||||
from spacepackets.ecss import PusTelemetry
|
|
||||||
from spacepackets.ecss.pus_17_test import Service17Tm
|
|
||||||
from spacepackets.util import PrintFormats
|
|
||||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
|
||||||
from tmtccmd.logging.pus import RawTmtcTimedLogWrapper
|
|
||||||
from tmtccmd.pus import VerificationWrapper
|
|
||||||
from tmtccmd.pus.s20_fsfw_param import Service20FsfwTm, Service20ParamDumpWrapper
|
|
||||||
from tmtccmd.pus.s20_fsfw_param_defs import CustomSubservice as ParamSubservice
|
|
||||||
from tmtccmd.pus.s200_fsfw_mode import Service200FsfwTm
|
|
||||||
from tmtccmd.pus.s200_fsfw_mode import Subservice as ModeSubservice
|
|
||||||
|
|
||||||
from eive_tmtc.config.object_ids import get_object_ids
|
|
||||||
|
|
||||||
from .action_reply_handler import handle_action_reply
|
|
||||||
from .defs import PrintWrapper
|
|
||||||
from .event_handler import handle_event_packet
|
|
||||||
from .hk_handler import HkFilter, handle_hk_packet
|
|
||||||
from .verification_handler import generic_retval_printout, handle_service_1_fsfw_packet
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def pus_factory_hook( # noqa C901 : Complexity okay here
|
|
||||||
packet: bytes,
|
|
||||||
verif_wrapper: VerificationWrapper,
|
|
||||||
printer: FsfwTmTcPrinter,
|
|
||||||
raw_logger: RawTmtcTimedLogWrapper,
|
|
||||||
hk_level: int,
|
|
||||||
hk_filter: HkFilter,
|
|
||||||
):
|
|
||||||
if len(packet) < 8:
|
|
||||||
_LOGGER.warning("Detected packet shorter than 8 bytes!")
|
|
||||||
return
|
|
||||||
try:
|
|
||||||
tm_packet = PusTelemetry.unpack(packet, CdsShortTimestamp.empty())
|
|
||||||
# _LOGGER.info(f"Sequence count: {tm_packet.seq_count}")
|
|
||||||
except ValueError as value_error:
|
|
||||||
_LOGGER.warning(f"{value_error}")
|
|
||||||
_LOGGER.warning("Could not generate PUS TM object from raw data")
|
|
||||||
_LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}")
|
|
||||||
return
|
|
||||||
service = tm_packet.service
|
|
||||||
obj_id_dict = get_object_ids()
|
|
||||||
pw = PrintWrapper(printer.file_logger)
|
|
||||||
dedicated_handler = True
|
|
||||||
if service == 1:
|
|
||||||
handle_service_1_fsfw_packet(wrapper=verif_wrapper, raw_tm=packet)
|
|
||||||
elif service == 3:
|
|
||||||
handle_hk_packet(
|
|
||||||
printer=printer,
|
|
||||||
raw_tm=packet,
|
|
||||||
obj_id_dict=obj_id_dict,
|
|
||||||
hk_level=hk_level,
|
|
||||||
hk_filter=hk_filter,
|
|
||||||
)
|
|
||||||
elif service == 5:
|
|
||||||
handle_event_packet(raw_tm=packet, pw=pw)
|
|
||||||
elif service == 8:
|
|
||||||
handle_action_reply(raw_tm=packet, printer=printer, obj_id_dict=obj_id_dict)
|
|
||||||
elif service == 17:
|
|
||||||
tm_packet = Service17Tm.unpack(
|
|
||||||
data=packet, time_reader=CdsShortTimestamp.empty()
|
|
||||||
)
|
|
||||||
if tm_packet.subservice == 2:
|
|
||||||
verif_wrapper.dlog("Received Ping Reply TM[17,2]")
|
|
||||||
dedicated_handler = True
|
|
||||||
elif service == 20:
|
|
||||||
param_packet = Service20FsfwTm.unpack(
|
|
||||||
raw_telemetry=packet, time_reader=CdsShortTimestamp.empty()
|
|
||||||
)
|
|
||||||
if tm_packet.subservice == ParamSubservice.TM_DUMP_REPLY:
|
|
||||||
param_wrapper = Service20ParamDumpWrapper(param_tm=param_packet)
|
|
||||||
try:
|
|
||||||
param = param_wrapper.get_param()
|
|
||||||
obj = obj_id_dict.get(param_wrapper.param_tm.object_id)
|
|
||||||
pw.dlog(f"Received parameter dump TM from {obj}")
|
|
||||||
pw.dlog(f"Parameter: {param}")
|
|
||||||
if param.rows == 1 and param.columns == 1:
|
|
||||||
try:
|
|
||||||
scalar_param = param.parse_scalar_param()
|
|
||||||
if isinstance(scalar_param, int):
|
|
||||||
pw.dlog(f"Scalar integer parameter: {scalar_param}")
|
|
||||||
elif isinstance(scalar_param, float):
|
|
||||||
pw.dlog(f"Scalar floating point parameter: {scalar_param}")
|
|
||||||
except ValueError as e:
|
|
||||||
pw.dlog(f"received {e} trying to parse scalar parameter")
|
|
||||||
else:
|
|
||||||
# TODO: Could improve display further by actually displaying a matrix as a
|
|
||||||
# matrix using row and column information
|
|
||||||
pw.dlog(
|
|
||||||
"Received vector or matrix data:"
|
|
||||||
f" {param.param_raw.hex(sep=',')}"
|
|
||||||
)
|
|
||||||
except ValueError as e:
|
|
||||||
pw.dlog(f"received {e} when trying to parse parameters")
|
|
||||||
except NotImplementedError as e:
|
|
||||||
pw.dlog(f"received {e} when trying to parse parameters")
|
|
||||||
else:
|
|
||||||
pw.dlog(f"unknown subservice {tm_packet.subservice} for parameter service")
|
|
||||||
elif service == 200:
|
|
||||||
tm_packet = Service200FsfwTm.unpack(
|
|
||||||
raw_telemetry=packet, time_reader=CdsShortTimestamp.empty()
|
|
||||||
)
|
|
||||||
if tm_packet.subservice == ModeSubservice.TM_CANT_REACH_MODE:
|
|
||||||
obj_id = tm_packet.object_id
|
|
||||||
obj_id_obj = obj_id_dict.get(obj_id)
|
|
||||||
retval = tm_packet.return_value
|
|
||||||
string_list = generic_retval_printout(retval)
|
|
||||||
pw.dlog(f"Received Mode Reply from {obj_id_obj}: Can't reach mode.")
|
|
||||||
for string in string_list:
|
|
||||||
pw.dlog(f"Reason: {string}")
|
|
||||||
dedicated_handler = True
|
|
||||||
else:
|
|
||||||
dedicated_handler = False
|
|
||||||
else:
|
|
||||||
_LOGGER.info(f"The service {service} is not implemented in Telemetry Factory")
|
|
||||||
tm_packet.print_source_data(PrintFormats.HEX)
|
|
||||||
dedicated_handler = True
|
|
||||||
if not dedicated_handler and tm_packet is not None:
|
|
||||||
printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet)
|
|
||||||
raw_logger.log_tm(tm_packet)
|
|
206
eive_tmtc/pus_tm/pus_handler.py
Normal file
206
eive_tmtc/pus_tm/pus_handler.py
Normal file
@ -0,0 +1,206 @@
|
|||||||
|
"""Core EIVE TM handler module
|
||||||
|
"""
|
||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
|
import uuid
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from spacepackets.ccsds.time import CdsShortTimestamp
|
||||||
|
from spacepackets.ecss import PusTelemetry
|
||||||
|
from spacepackets.ecss.pus_17_test import Service17Tm
|
||||||
|
from spacepackets.util import PrintFormats
|
||||||
|
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||||
|
from tmtccmd.logging.pus import RawTmtcTimedLogWrapper
|
||||||
|
from tmtccmd.pus import VerificationWrapper
|
||||||
|
from tmtccmd.pus.s20_fsfw_param import Service20FsfwTm, Service20ParamDumpWrapper
|
||||||
|
from tmtccmd.pus.s20_fsfw_param_defs import CustomSubservice as ParamSubservice
|
||||||
|
from tmtccmd.pus.s200_fsfw_mode import Service200FsfwTm
|
||||||
|
from tmtccmd.pus.s200_fsfw_mode import Subservice as ModeSubservice
|
||||||
|
from tmtccmd.tmtc import GenericApidHandlerBase, SpecificApidHandlerBase
|
||||||
|
from eive_tmtc.config.definitions import TM_DB_PATH, PUS_APID
|
||||||
|
|
||||||
|
from eive_tmtc.config.object_ids import get_object_ids
|
||||||
|
|
||||||
|
from .action_reply_handler import handle_action_reply
|
||||||
|
from .defs import PrintWrapper
|
||||||
|
from .event_handler import handle_event_packet
|
||||||
|
from .hk_handler import HkFilter, handle_hk_packet
|
||||||
|
from .verification_handler import generic_retval_printout, handle_service_1_fsfw_packet
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class PusHandler(SpecificApidHandlerBase):
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
wrapper: VerificationWrapper,
|
||||||
|
printer: FsfwTmTcPrinter,
|
||||||
|
raw_logger: RawTmtcTimedLogWrapper,
|
||||||
|
hk_level: int,
|
||||||
|
):
|
||||||
|
super().__init__(PUS_APID, None)
|
||||||
|
self.printer = printer
|
||||||
|
self.verif_wrapper = wrapper
|
||||||
|
self.raw_logger = raw_logger
|
||||||
|
self.hk_level = hk_level
|
||||||
|
self.these_objs_hk_only = []
|
||||||
|
self.hk_filter = HkFilter(object_ids=self.these_objs_hk_only, set_ids=[])
|
||||||
|
self.obj_id_dict = get_object_ids()
|
||||||
|
self.pw = PrintWrapper(printer.file_logger)
|
||||||
|
|
||||||
|
def handle_tm(self, packet: bytes, _user_args: Any):
|
||||||
|
self.pus_handler(
|
||||||
|
packet,
|
||||||
|
)
|
||||||
|
|
||||||
|
def pus_handler( # noqa C901 : Complexity okay here
|
||||||
|
self,
|
||||||
|
packet: bytes,
|
||||||
|
):
|
||||||
|
packet_uuid = uuid.uuid4()
|
||||||
|
if len(packet) < 8:
|
||||||
|
_LOGGER.warning("Detected packet shorter than 8 bytes!")
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
tm_packet = PusTelemetry.unpack(packet, CdsShortTimestamp.empty())
|
||||||
|
# _LOGGER.info(f"Sequence count: {tm_packet.seq_count}")
|
||||||
|
except ValueError as value_error:
|
||||||
|
_LOGGER.warning(f"{value_error}")
|
||||||
|
_LOGGER.warning("Could not generate PUS TM object from raw data")
|
||||||
|
_LOGGER.warning(f"Raw Packet: [{packet.hex(sep=',')}], REPR: {packet!r}")
|
||||||
|
return
|
||||||
|
db_con = sqlite3.connect(TM_DB_PATH)
|
||||||
|
self._store_packet_in_db(db_con, packet, tm_packet, packet_uuid)
|
||||||
|
service = tm_packet.service
|
||||||
|
dedicated_handler = True
|
||||||
|
if service == 1:
|
||||||
|
handle_service_1_fsfw_packet(wrapper=self.verif_wrapper, raw_tm=packet)
|
||||||
|
elif service == 3:
|
||||||
|
handle_hk_packet(
|
||||||
|
db_con=db_con,
|
||||||
|
packet_uuid=packet_uuid,
|
||||||
|
printer=self.printer,
|
||||||
|
raw_tm=packet,
|
||||||
|
obj_id_dict=self.obj_id_dict,
|
||||||
|
hk_level=self.hk_level,
|
||||||
|
hk_filter=self.hk_filter,
|
||||||
|
)
|
||||||
|
elif service == 5:
|
||||||
|
handle_event_packet(raw_tm=packet, pw=self.pw)
|
||||||
|
elif service == 8:
|
||||||
|
handle_action_reply(
|
||||||
|
raw_tm=packet, printer=self.printer, obj_id_dict=self.obj_id_dict
|
||||||
|
)
|
||||||
|
elif service == 17:
|
||||||
|
pus17_tm = Service17Tm.unpack(
|
||||||
|
data=packet, time_reader=CdsShortTimestamp.empty()
|
||||||
|
)
|
||||||
|
if pus17_tm.subservice == 2:
|
||||||
|
self.verif_wrapper.dlog("Received Ping Reply TM[17,2]")
|
||||||
|
dedicated_handler = True
|
||||||
|
elif service == 20:
|
||||||
|
self._handle_param_packet(packet, tm_packet)
|
||||||
|
elif service == 200:
|
||||||
|
dedicated_handler = self._handle_mode_packet(packet, tm_packet)
|
||||||
|
else:
|
||||||
|
_LOGGER.info(
|
||||||
|
f"The service {service} is not implemented in Telemetry Factory"
|
||||||
|
)
|
||||||
|
tm_packet.print_source_data(PrintFormats.HEX)
|
||||||
|
dedicated_handler = True
|
||||||
|
if not dedicated_handler and tm_packet is not None:
|
||||||
|
self.printer.handle_long_tm_print(packet_if=tm_packet, info_if=tm_packet)
|
||||||
|
self.raw_logger.log_tm(tm_packet)
|
||||||
|
|
||||||
|
def _store_packet_in_db(
|
||||||
|
self,
|
||||||
|
db_con: sqlite3.Connection,
|
||||||
|
packet: bytes,
|
||||||
|
tm_packet: PusTelemetry,
|
||||||
|
packet_uuid: uuid.UUID,
|
||||||
|
):
|
||||||
|
cursor = db_con.cursor()
|
||||||
|
assert tm_packet.time_provider is not None
|
||||||
|
cursor.execute(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS pus_tm(
|
||||||
|
packet_uuid TEXT PRIMARY KEY,
|
||||||
|
generation_time TEXT,
|
||||||
|
service NUM,
|
||||||
|
subservice NUM,
|
||||||
|
data_len NUM,
|
||||||
|
raw_data BLOB
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
cursor.execute(
|
||||||
|
"INSERT INTO pus_tm VALUES(?, ?, ?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
str(packet_uuid),
|
||||||
|
tm_packet.time_provider.as_datetime(),
|
||||||
|
tm_packet.service,
|
||||||
|
tm_packet.subservice,
|
||||||
|
len(packet),
|
||||||
|
packet,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
db_con.commit()
|
||||||
|
|
||||||
|
def _handle_param_packet(self, raw_data: bytes, tm_packet: PusTelemetry):
|
||||||
|
param_packet = Service20FsfwTm.unpack(
|
||||||
|
raw_telemetry=raw_data, time_reader=CdsShortTimestamp.empty()
|
||||||
|
)
|
||||||
|
if tm_packet.subservice == ParamSubservice.TM_DUMP_REPLY:
|
||||||
|
param_wrapper = Service20ParamDumpWrapper(param_tm=param_packet)
|
||||||
|
try:
|
||||||
|
param = param_wrapper.get_param()
|
||||||
|
obj = self.obj_id_dict.get(param_wrapper.param_tm.object_id)
|
||||||
|
self.pw.dlog(f"Received parameter dump TM from {obj}")
|
||||||
|
self.pw.dlog(f"Parameter: {param}")
|
||||||
|
if param.rows == 1 and param.columns == 1:
|
||||||
|
try:
|
||||||
|
scalar_param = param.parse_scalar_param()
|
||||||
|
if isinstance(scalar_param, int):
|
||||||
|
self.pw.dlog(f"Scalar integer parameter: {scalar_param}")
|
||||||
|
elif isinstance(scalar_param, float):
|
||||||
|
self.pw.dlog(
|
||||||
|
f"Scalar floating point parameter: {scalar_param}"
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
self.pw.dlog(f"received {e} trying to parse scalar parameter")
|
||||||
|
else:
|
||||||
|
# TODO: Could improve display further by actually displaying a matrix as a
|
||||||
|
# matrix using row and column information
|
||||||
|
self.pw.dlog(
|
||||||
|
"Received vector or matrix data:"
|
||||||
|
f" {param.param_raw.hex(sep=',')}"
|
||||||
|
)
|
||||||
|
except ValueError as e:
|
||||||
|
self.pw.dlog(f"received {e} when trying to parse parameters")
|
||||||
|
except NotImplementedError as e:
|
||||||
|
self.pw.dlog(f"received {e} when trying to parse parameters")
|
||||||
|
else:
|
||||||
|
self.pw.dlog(
|
||||||
|
f"unknown subservice {tm_packet.subservice} for parameter service"
|
||||||
|
)
|
||||||
|
|
||||||
|
def _handle_mode_packet(self, raw_data: bytes, _: PusTelemetry) -> bool:
|
||||||
|
tm_packet = Service200FsfwTm.unpack(
|
||||||
|
raw_telemetry=raw_data, time_reader=CdsShortTimestamp.empty()
|
||||||
|
)
|
||||||
|
if tm_packet.subservice == ModeSubservice.TM_CANT_REACH_MODE:
|
||||||
|
obj_id = tm_packet.object_id
|
||||||
|
obj_id_obj = self.obj_id_dict.get(obj_id)
|
||||||
|
retval = tm_packet.return_value
|
||||||
|
string_list = generic_retval_printout(retval)
|
||||||
|
self.pw.dlog(f"Received Mode Reply from {obj_id_obj}: Can't reach mode.")
|
||||||
|
for string in string_list:
|
||||||
|
self.pw.dlog(f"Reason: {string}")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
class UnknownApidHandler(GenericApidHandlerBase):
|
||||||
|
def handle_tm(self, apid: int, packet: bytes, _user_args: Any):
|
||||||
|
_LOGGER.warning(
|
||||||
|
f"Packet with unknown APID {apid} detected: {packet.hex(sep=',')}"
|
||||||
|
)
|
@ -8,32 +8,32 @@
|
|||||||
import enum
|
import enum
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
|
|
||||||
from tmtccmd.config import CmdTreeNode
|
|
||||||
|
|
||||||
from eive_tmtc.pus_tm.defs import PrintWrapper
|
|
||||||
from eive_tmtc.tmtc.com.defs import Mode as ComMode
|
|
||||||
from eive_tmtc.config.definitions import CustomServiceList
|
|
||||||
from tmtccmd.config.tmtc import (
|
|
||||||
tmtc_definitions_provider,
|
|
||||||
TmtcDefinitionWrapper,
|
|
||||||
OpCodeEntry,
|
|
||||||
)
|
|
||||||
from tmtccmd.tmtc import DefaultPusQueueHelper
|
|
||||||
from tmtccmd.pus.tc.s3_fsfw_hk import (
|
|
||||||
make_sid,
|
|
||||||
create_request_one_diag_command,
|
|
||||||
create_request_one_hk_command,
|
|
||||||
create_enable_periodic_hk_command_with_interval_with_diag,
|
|
||||||
create_disable_periodic_hk_command_with_diag,
|
|
||||||
)
|
|
||||||
from spacepackets.ecss.tc import PusTelecommand
|
|
||||||
from tmtccmd.pus.s200_fsfw_mode import Mode, create_mode_command
|
|
||||||
from eive_tmtc.config.object_ids import SYRLINKS_HANDLER_ID
|
|
||||||
import struct
|
import struct
|
||||||
|
|
||||||
from tmtccmd.util import ObjectIdU32
|
from spacepackets.ecss.tc import PusTelecommand
|
||||||
|
from tmtccmd.config.tmtc import (
|
||||||
|
CmdTreeNode,
|
||||||
|
OpCodeEntry,
|
||||||
|
TmtcDefinitionWrapper,
|
||||||
|
tmtc_definitions_provider,
|
||||||
|
)
|
||||||
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
from tmtccmd.fsfw.tmtc_printer import FsfwTmTcPrinter
|
||||||
|
from tmtccmd.pus.s200_fsfw_mode import Mode, create_mode_command
|
||||||
|
from tmtccmd.pus.tc.s3_fsfw_hk import (
|
||||||
|
create_disable_periodic_hk_command_with_diag,
|
||||||
|
create_enable_periodic_hk_command_with_interval_with_diag,
|
||||||
|
create_request_one_diag_command,
|
||||||
|
create_request_one_hk_command,
|
||||||
|
make_sid,
|
||||||
|
)
|
||||||
|
from tmtccmd.tmtc import DefaultPusQueueHelper
|
||||||
|
from tmtccmd.util import ObjectIdU32
|
||||||
|
|
||||||
|
from eive_tmtc.config.definitions import CustomServiceList
|
||||||
|
from eive_tmtc.config.object_ids import SYRLINKS_HANDLER_ID
|
||||||
|
from eive_tmtc.pus_tm.defs import PrintWrapper
|
||||||
|
from eive_tmtc.pus_tm.hk import HkTmInfo
|
||||||
|
from eive_tmtc.tmtc.com.defs import Mode as ComMode
|
||||||
|
|
||||||
|
|
||||||
class SetId(enum.IntEnum):
|
class SetId(enum.IntEnum):
|
||||||
@ -273,18 +273,24 @@ def pack_syrlinks_command( # noqa C901: Complexity okay here.
|
|||||||
q.add_pus_tc(PusTelecommand(service=8, subservice=128, app_data=command))
|
q.add_pus_tc(PusTelecommand(service=8, subservice=128, app_data=command))
|
||||||
|
|
||||||
|
|
||||||
def handle_syrlinks_hk_data(pw: PrintWrapper, set_id: int, hk_data: bytes):
|
def handle_syrlinks_hk_data(
|
||||||
if set_id == SetId.RX_REGISTERS_DATASET:
|
hk_info: HkTmInfo,
|
||||||
return handle_syrlinks_rx_registers_dataset(pw, hk_data)
|
pw: PrintWrapper,
|
||||||
elif set_id == SetId.TX_REGISTERS_DATASET:
|
):
|
||||||
return handle_syrlinks_tx_registers_dataset(pw, hk_data)
|
if hk_info.set_id == SetId.RX_REGISTERS_DATASET:
|
||||||
elif set_id == SetId.TEMPERATURE_SET_ID:
|
return handle_syrlinks_rx_registers_dataset(hk_info, pw)
|
||||||
return handle_syrlinks_temp_dataset(pw, hk_data)
|
elif hk_info.set_id == SetId.TX_REGISTERS_DATASET:
|
||||||
|
return handle_syrlinks_tx_registers_dataset(hk_info, pw)
|
||||||
|
elif hk_info.set_id == SetId.TEMPERATURE_SET_ID:
|
||||||
|
return handle_syrlinks_temp_dataset(hk_info, pw)
|
||||||
else:
|
else:
|
||||||
pw.dlog(f"Service 3 TM: Syrlinks handler reply with unknown set ID {set_id}")
|
pw.dlog(
|
||||||
|
f"Service 3 TM: Syrlinks handler reply with unknown set ID {hk_info.set_id}"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def handle_syrlinks_temp_dataset(pw: PrintWrapper, hk_data: bytes):
|
def handle_syrlinks_temp_dataset(hk_info: HkTmInfo, pw: PrintWrapper):
|
||||||
|
hk_data = hk_info.hk_data
|
||||||
if len(hk_data) < 8:
|
if len(hk_data) < 8:
|
||||||
raise ValueError("expected at least 8 bytes of HK data")
|
raise ValueError("expected at least 8 bytes of HK data")
|
||||||
temp_power_amplifier = struct.unpack("!f", hk_data[0:4])[0]
|
temp_power_amplifier = struct.unpack("!f", hk_data[0:4])[0]
|
||||||
@ -294,7 +300,11 @@ def handle_syrlinks_temp_dataset(pw: PrintWrapper, hk_data: bytes):
|
|||||||
pw.dlog(FsfwTmTcPrinter.get_validity_buffer(hk_data[8:], 2))
|
pw.dlog(FsfwTmTcPrinter.get_validity_buffer(hk_data[8:], 2))
|
||||||
|
|
||||||
|
|
||||||
def handle_syrlinks_rx_registers_dataset(pw: PrintWrapper, hk_data: bytes):
|
def handle_syrlinks_rx_registers_dataset(
|
||||||
|
hk_info: HkTmInfo,
|
||||||
|
pw: PrintWrapper,
|
||||||
|
):
|
||||||
|
hk_data = hk_info.hk_data
|
||||||
header_list = [
|
header_list = [
|
||||||
"RX Status",
|
"RX Status",
|
||||||
"RX Sensitivity",
|
"RX Sensitivity",
|
||||||
@ -357,14 +367,44 @@ def handle_syrlinks_rx_registers_dataset(pw: PrintWrapper, hk_data: bytes):
|
|||||||
pw.dlog(
|
pw.dlog(
|
||||||
FsfwTmTcPrinter.get_validity_buffer(validity_buffer=validity_buffer, num_vars=8)
|
FsfwTmTcPrinter.get_validity_buffer(validity_buffer=validity_buffer, num_vars=8)
|
||||||
)
|
)
|
||||||
pw.dlog(f"Carrier Detect: {carrier_detect}")
|
print(f"Carrier Detect: {carrier_detect}")
|
||||||
pw.dlog(f"Carrier Lock: {carrier_lock}")
|
print(f"Carrier Lock: {carrier_lock}")
|
||||||
pw.dlog(f"Data Lock (data clock recovery loop lock status): {data_lock}")
|
print(f"Data Lock (data clock recovery loop lock status): {data_lock}")
|
||||||
pw.dlog(f"Data Valid (valid if TEB < 10e-5): {data_valid}")
|
print(f"Data Valid (valid if TEB < 10e-5): {data_valid}")
|
||||||
pw.dlog(f"Data Lock (data clock recovery loop lock status): {data_lock}")
|
print(f"Data Lock (data clock recovery loop lock status): {data_lock}")
|
||||||
pw.dlog(f"RX AGC Inhibit: {rx_agc_inhibit}")
|
print(f"RX AGC Inhibit: {rx_agc_inhibit}")
|
||||||
pw.dlog(f"RX AGC: {rx_agc}")
|
print(f"RX AGC: {rx_agc}")
|
||||||
pw.dlog(f"Eb / E0RX [dB]: {eb_to_n0}")
|
print(f"Eb / E0RX [dB]: {eb_to_n0}")
|
||||||
|
cursor = hk_info.db_con.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS syrlinks_rx_regs(
|
||||||
|
packet_uuid TEXT PRIMARY KEY,
|
||||||
|
generation_time TEXT,
|
||||||
|
carrier_detect NUM,
|
||||||
|
carrier_lock NUM,
|
||||||
|
data_lock NUM,
|
||||||
|
data_valid NUM,
|
||||||
|
rx_agc_inhibit NUM,
|
||||||
|
rx_agc NUM,
|
||||||
|
eb_to_e0_rx NUM
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
cursor.execute(
|
||||||
|
"INSERT INTO syrlinks_rx_regs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
str(hk_info.packet_uuid),
|
||||||
|
hk_info.hk_packet.pus_tm.time_provider.as_datetime(), # type: ignore
|
||||||
|
carrier_detect,
|
||||||
|
carrier_lock,
|
||||||
|
data_lock,
|
||||||
|
data_valid,
|
||||||
|
rx_agc_inhibit,
|
||||||
|
rx_agc,
|
||||||
|
eb_to_n0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
hk_info.db_con.commit()
|
||||||
|
|
||||||
|
|
||||||
class TxConv(enum.IntEnum):
|
class TxConv(enum.IntEnum):
|
||||||
@ -390,11 +430,11 @@ WAVEFORM_STRINGS = ["OFF", "CW", "QPSK", "0QPSK", "PCM/PM", "PSK/PM", "BPSK"]
|
|||||||
|
|
||||||
|
|
||||||
def handle_syrlinks_tx_registers_dataset(
|
def handle_syrlinks_tx_registers_dataset(
|
||||||
|
hk_info: HkTmInfo,
|
||||||
pw: PrintWrapper,
|
pw: PrintWrapper,
|
||||||
hk_data: bytes,
|
|
||||||
):
|
):
|
||||||
header_list = ["TX Status Raw", "TX Waveform", "TX AGC value"]
|
header_list = ["TX Status Raw", "TX Waveform", "TX AGC value"]
|
||||||
tx_status = hk_data[0]
|
tx_status = hk_info.hk_data[0]
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
tx_conv = TxConv(tx_status & 0b111)
|
tx_conv = TxConv(tx_status & 0b111)
|
||||||
@ -412,9 +452,10 @@ def handle_syrlinks_tx_registers_dataset(
|
|||||||
logging.getLogger(__name__).warning(
|
logging.getLogger(__name__).warning(
|
||||||
f"invalid TX conf set {(tx_status >> 2) & 0b11}"
|
f"invalid TX conf set {(tx_status >> 2) & 0b11}"
|
||||||
)
|
)
|
||||||
tx_conf_set = -1
|
# Hack to make DB insertion work.
|
||||||
|
tx_conf_set = TxCfgSet.START_WITH_CURRENT_CFG
|
||||||
tx_clock_detect = (tx_status >> 4) & 0b1
|
tx_clock_detect = (tx_status >> 4) & 0b1
|
||||||
tx_waveform = hk_data[1]
|
tx_waveform = hk_info.hk_data[1]
|
||||||
waveform = tx_waveform & 0b1111
|
waveform = tx_waveform & 0b1111
|
||||||
try:
|
try:
|
||||||
waveform_str = WAVEFORM_STRINGS[waveform]
|
waveform_str = WAVEFORM_STRINGS[waveform]
|
||||||
@ -422,11 +463,11 @@ def handle_syrlinks_tx_registers_dataset(
|
|||||||
logging.getLogger(__name__).warning(f"Unknown waveform value {waveform}")
|
logging.getLogger(__name__).warning(f"Unknown waveform value {waveform}")
|
||||||
waveform_str = "Unknown"
|
waveform_str = "Unknown"
|
||||||
pcm_mode = (tx_waveform >> 4) & 0b1
|
pcm_mode = (tx_waveform >> 4) & 0b1
|
||||||
tx_agc_value = struct.unpack("!H", hk_data[2:4])[0]
|
tx_agc_value = struct.unpack("!H", hk_info.hk_data[2:4])[0]
|
||||||
tx_agc_inhibit = (tx_agc_value >> 15) & 0b1
|
tx_agc_inhibit = (tx_agc_value >> 15) & 0b1
|
||||||
tx_agc = tx_agc_value & 0xFFF
|
tx_agc = tx_agc_value & 0xFFF
|
||||||
content_list = [tx_status, tx_waveform, tx_agc_value]
|
content_list = [tx_status, tx_waveform, tx_agc_value]
|
||||||
validity_buffer = hk_data[4:]
|
validity_buffer = hk_info.hk_data[4:]
|
||||||
for header, content in zip(header_list, content_list):
|
for header, content in zip(header_list, content_list):
|
||||||
pw.dlog(f"{header}: {content}")
|
pw.dlog(f"{header}: {content}")
|
||||||
pw.dlog(
|
pw.dlog(
|
||||||
@ -434,10 +475,46 @@ def handle_syrlinks_tx_registers_dataset(
|
|||||||
)
|
)
|
||||||
# pw.dlog(f"TX CONV: {tx_conv!r}")
|
# pw.dlog(f"TX CONV: {tx_conv!r}")
|
||||||
# pw.dlog(f"TX DIFF (differential encoder enable): {tx_diff_encoder_enable}")
|
# pw.dlog(f"TX DIFF (differential encoder enable): {tx_diff_encoder_enable}")
|
||||||
pw.dlog(f"TX Status: {tx_status_status!r}")
|
print(f"TX Status: {tx_status_status!r}")
|
||||||
pw.dlog(f"TX Config Set: {tx_conf_set!r}")
|
print(f"TX Config Set: {tx_conf_set!r}")
|
||||||
pw.dlog(f"TX Clock Detect: {tx_clock_detect}")
|
print(f"TX Clock Detect: {tx_clock_detect}")
|
||||||
pw.dlog(f"Waveform: {waveform_str}")
|
print(f"Waveform: {waveform_str}")
|
||||||
pw.dlog(f"PCM Mode: {pcm_mode}")
|
print(f"PCM Mode: {pcm_mode}")
|
||||||
pw.dlog(f"TX AGC Inhibit: {tx_agc_inhibit}")
|
print(f"TX AGC Inhibit: {tx_agc_inhibit}")
|
||||||
pw.dlog(f"TX AGC: {tx_agc}")
|
print(f"TX AGC: {tx_agc}")
|
||||||
|
cursor = hk_info.db_con.cursor()
|
||||||
|
cursor.execute(
|
||||||
|
"""
|
||||||
|
CREATE TABLE IF NOT EXISTS syrlinks_tx_regs(
|
||||||
|
packet_uuid TEXT PRIMARY KEY,
|
||||||
|
generation_time TEXT,
|
||||||
|
tx_status NUM,
|
||||||
|
tx_status_str TEXT,
|
||||||
|
tx_cfg_set NUM,
|
||||||
|
tx_cfg_set_str TEXT,
|
||||||
|
tx_clock_detect NUM,
|
||||||
|
waveform NUM,
|
||||||
|
waveform_str TEXT,
|
||||||
|
pcm_mode NUM,
|
||||||
|
tx_agc_inhibut NUM,
|
||||||
|
tx_agc NUM
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
cursor.execute(
|
||||||
|
"INSERT INTO syrlinks_tx_regs VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
str(hk_info.packet_uuid),
|
||||||
|
hk_info.hk_packet.pus_tm.time_provider.as_datetime(), # type: ignore
|
||||||
|
tx_status_status,
|
||||||
|
tx_status_status.name,
|
||||||
|
tx_conf_set,
|
||||||
|
tx_conf_set.name,
|
||||||
|
tx_clock_detect,
|
||||||
|
waveform,
|
||||||
|
waveform_str,
|
||||||
|
pcm_mode,
|
||||||
|
tx_agc_inhibit,
|
||||||
|
tx_agc,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
hk_info.db_con.commit()
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
|
import dataclasses
|
||||||
import struct
|
import struct
|
||||||
|
import logging
|
||||||
|
import sqlite3
|
||||||
from typing import List, Tuple
|
from typing import List, Tuple
|
||||||
|
from eive_tmtc.pus_tm.hk import HkTmInfo
|
||||||
|
|
||||||
from eive_tmtc.tmtc.power.acu import acu_config_table_handler
|
from eive_tmtc.tmtc.power.acu import acu_config_table_handler
|
||||||
from eive_tmtc.tmtc.power.common_power import (
|
from eive_tmtc.tmtc.power.common_power import (
|
||||||
@ -19,6 +23,8 @@ from eive_tmtc.config.object_ids import (
|
|||||||
ACU_HANDLER_ID,
|
ACU_HANDLER_ID,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
P60_INDEX_LIST = [
|
P60_INDEX_LIST = [
|
||||||
"ACU VCC",
|
"ACU VCC",
|
||||||
"PDU1 VCC",
|
"PDU1 VCC",
|
||||||
@ -146,7 +152,25 @@ class DevicesInfoParser:
|
|||||||
return "Unknown Type"
|
return "Unknown Type"
|
||||||
|
|
||||||
|
|
||||||
def handle_pdu_data(pw: PrintWrapper, pdu_idx: int, set_id: int, hk_data: bytes):
|
@dataclasses.dataclass
|
||||||
|
class PduData:
|
||||||
|
boot_count: int
|
||||||
|
batt_mode: int
|
||||||
|
temperature: float
|
||||||
|
vcc: int
|
||||||
|
vbat: int
|
||||||
|
out_enables: List[bool]
|
||||||
|
voltages: List[int]
|
||||||
|
currents: List[int]
|
||||||
|
|
||||||
|
|
||||||
|
def handle_pdu_data(
|
||||||
|
hk_data: bytes,
|
||||||
|
hk_info: HkTmInfo,
|
||||||
|
pw: PrintWrapper,
|
||||||
|
pdu_idx: int,
|
||||||
|
set_id: int,
|
||||||
|
):
|
||||||
current_idx = 0
|
current_idx = 0
|
||||||
priv_idx = pdu_idx - 1
|
priv_idx = pdu_idx - 1
|
||||||
if set_id == SetId.AUX or set_id == SetId.AUX:
|
if set_id == SetId.AUX or set_id == SetId.AUX:
|
||||||
@ -219,7 +243,86 @@ def handle_pdu_data(pw: PrintWrapper, pdu_idx: int, set_id: int, hk_data: bytes)
|
|||||||
f"Boot Count {boot_count} | Battery Mode {batt_mode} | "
|
f"Boot Count {boot_count} | Battery Mode {batt_mode} | "
|
||||||
f"Temperature {temperature} | VCC {vcc} | VBAT {vbat}"
|
f"Temperature {temperature} | VCC {vcc} | VBAT {vbat}"
|
||||||
)
|
)
|
||||||
pw.dlog(info)
|
try:
|
||||||
|
handle_pdu_db_insertion(
|
||||||
|
hk_info,
|
||||||
|
pdu_idx,
|
||||||
|
PduData(
|
||||||
|
boot_count,
|
||||||
|
batt_mode,
|
||||||
|
temperature,
|
||||||
|
vcc,
|
||||||
|
vbat,
|
||||||
|
output_enb_list,
|
||||||
|
voltage_list,
|
||||||
|
current_list,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
_LOGGER.warning(f"SQLite error {e}")
|
||||||
|
_LOGGER.info(info)
|
||||||
|
|
||||||
|
|
||||||
|
def handle_pdu_db_insertion(
|
||||||
|
hk_info: HkTmInfo,
|
||||||
|
pdu_idx: int,
|
||||||
|
pdu_data: PduData,
|
||||||
|
):
|
||||||
|
cursor = hk_info.db_con.cursor()
|
||||||
|
if pdu_idx == 1:
|
||||||
|
tbl_base_name = "pdu1"
|
||||||
|
channel_list = PDU1_CHANNELS_NAMES
|
||||||
|
else:
|
||||||
|
tbl_base_name = "pdu2"
|
||||||
|
channel_list = PDU2_CHANNELS_NAMES
|
||||||
|
cursor.execute(
|
||||||
|
f"""
|
||||||
|
CREATE TABLE IF NOT EXISTS {tbl_base_name}(
|
||||||
|
packet_uuid TEXT PRIMARY KEY,
|
||||||
|
generation_time TEXT,
|
||||||
|
boot_count NUM,
|
||||||
|
bat_mode NUM,
|
||||||
|
temp REAL,
|
||||||
|
vcc NUM,
|
||||||
|
vbat NUM
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
cursor.execute(
|
||||||
|
f"INSERT INTO {tbl_base_name} VALUES(?, ?, ?, ?, ?, ?, ?)",
|
||||||
|
(
|
||||||
|
str(hk_info.packet_uuid),
|
||||||
|
hk_info.packet_datetime,
|
||||||
|
pdu_data.boot_count,
|
||||||
|
pdu_data.batt_mode,
|
||||||
|
pdu_data.temperature,
|
||||||
|
pdu_data.vcc,
|
||||||
|
pdu_data.vbat,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
for idx, name in enumerate(channel_list):
|
||||||
|
words = name.split()
|
||||||
|
camel_case_name = "_".join(word.lower() for word in words)
|
||||||
|
tbl_name = f"{tbl_base_name}_{camel_case_name}"
|
||||||
|
cursor.execute(
|
||||||
|
f"""
|
||||||
|
CREATE TABLE IF NOT EXISTS {tbl_name}(
|
||||||
|
packet_uuid TEXT PRIMARY KEY,
|
||||||
|
generation_time TEXT,
|
||||||
|
out_enable NUM,
|
||||||
|
voltage NUM,
|
||||||
|
current NUM
|
||||||
|
)"""
|
||||||
|
)
|
||||||
|
value_tuple = (
|
||||||
|
str(hk_info.packet_uuid),
|
||||||
|
hk_info.packet_datetime,
|
||||||
|
pdu_data.out_enables[idx],
|
||||||
|
pdu_data.voltages[idx],
|
||||||
|
pdu_data.currents[idx],
|
||||||
|
)
|
||||||
|
cursor.execute(f"INSERT INTO {tbl_name} VALUES(?, ?, ?, ?, ?)", value_tuple)
|
||||||
|
hk_info.db_con.commit()
|
||||||
|
|
||||||
|
|
||||||
def handle_p60_hk_data(pw: PrintWrapper, set_id: int, hk_data: bytes):
|
def handle_p60_hk_data(pw: PrintWrapper, set_id: int, hk_data: bytes):
|
||||||
|
43
tmtcc.py
43
tmtcc.py
@ -15,7 +15,6 @@ from spacepackets.ecss import PusVerificator
|
|||||||
from spacepackets.version import get_version as get_sp_version
|
from spacepackets.version import get_version as get_sp_version
|
||||||
from tmtccmd import BackendBase
|
from tmtccmd import BackendBase
|
||||||
from tmtccmd.cfdp.handler import RemoteEntityCfgTable
|
from tmtccmd.cfdp.handler import RemoteEntityCfgTable
|
||||||
from eive_tmtc.cfdp.handler import CfdpInCcsdsHandler
|
|
||||||
from tmtccmd.cfdp.mib import (
|
from tmtccmd.cfdp.mib import (
|
||||||
IndicationCfg,
|
IndicationCfg,
|
||||||
LocalEntityCfg,
|
LocalEntityCfg,
|
||||||
@ -41,11 +40,13 @@ from tmtccmd.logging.pus import (
|
|||||||
TimedLogWhen,
|
TimedLogWhen,
|
||||||
)
|
)
|
||||||
from tmtccmd.pus import VerificationWrapper
|
from tmtccmd.pus import VerificationWrapper
|
||||||
from tmtccmd.tmtc import CcsdsTmHandler, GenericApidHandlerBase, SpecificApidHandlerBase
|
from tmtccmd.tmtc import CcsdsTmHandler
|
||||||
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
|
from tmtccmd.util import FileSeqCountProvider, PusFileSeqCountProvider
|
||||||
|
|
||||||
from eive_tmtc import APP_LOGGER
|
from eive_tmtc import APP_LOGGER
|
||||||
|
from eive_tmtc.pus_tm.pus_handler import PusHandler, UnknownApidHandler
|
||||||
from eive_tmtc.cfdp.fault_handler import EiveCfdpFaultHandler
|
from eive_tmtc.cfdp.fault_handler import EiveCfdpFaultHandler
|
||||||
|
from eive_tmtc.cfdp.handler import CfdpInCcsdsHandler
|
||||||
from eive_tmtc.cfdp.tm import CfdpInCcsdsWrapper
|
from eive_tmtc.cfdp.tm import CfdpInCcsdsWrapper
|
||||||
from eive_tmtc.cfdp.user import EiveCfdpUser, EiveCheckTimerProvider
|
from eive_tmtc.cfdp.user import EiveCfdpUser, EiveCheckTimerProvider
|
||||||
from eive_tmtc.config.definitions import (
|
from eive_tmtc.config.definitions import (
|
||||||
@ -56,8 +57,6 @@ from eive_tmtc.config.definitions import (
|
|||||||
)
|
)
|
||||||
from eive_tmtc.config.hook import EiveHookObject
|
from eive_tmtc.config.hook import EiveHookObject
|
||||||
from eive_tmtc.pus_tc.tc_handler import TcHandler
|
from eive_tmtc.pus_tc.tc_handler import TcHandler
|
||||||
from eive_tmtc.pus_tm.hk_handler import HkFilter
|
|
||||||
from eive_tmtc.pus_tm.pus_demux import pus_factory_hook
|
|
||||||
|
|
||||||
_LOGGER = APP_LOGGER
|
_LOGGER = APP_LOGGER
|
||||||
_LOG_LEVEL = logging.INFO
|
_LOG_LEVEL = logging.INFO
|
||||||
@ -67,42 +66,6 @@ ROTATING_TIMED_LOGGER_INTERVAL_WHEN = TimedLogWhen.PER_MINUTE
|
|||||||
ROTATING_TIMED_LOGGER_INTERVAL = 30
|
ROTATING_TIMED_LOGGER_INTERVAL = 30
|
||||||
|
|
||||||
|
|
||||||
class PusHandler(SpecificApidHandlerBase):
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
wrapper: VerificationWrapper,
|
|
||||||
printer: FsfwTmTcPrinter,
|
|
||||||
raw_logger: RawTmtcTimedLogWrapper,
|
|
||||||
hk_level: int,
|
|
||||||
):
|
|
||||||
super().__init__(PUS_APID, None)
|
|
||||||
self.printer = printer
|
|
||||||
self.verif_wrapper = wrapper
|
|
||||||
self.raw_logger = raw_logger
|
|
||||||
self.hk_level = hk_level
|
|
||||||
self.these_objs_hk_only = []
|
|
||||||
self.hk_filter = HkFilter(object_ids=self.these_objs_hk_only, set_ids=[])
|
|
||||||
|
|
||||||
def handle_tm(self, packet: bytes, _user_args: any):
|
|
||||||
# with open("tc.bin", "wb") as of:
|
|
||||||
# of.write(packet)
|
|
||||||
pus_factory_hook(
|
|
||||||
packet,
|
|
||||||
self.verif_wrapper,
|
|
||||||
self.printer,
|
|
||||||
self.raw_logger,
|
|
||||||
self.hk_level,
|
|
||||||
self.hk_filter,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UnknownApidHandler(GenericApidHandlerBase):
|
|
||||||
def handle_tm(self, apid: int, packet: bytes, _user_args: any):
|
|
||||||
_LOGGER.warning(
|
|
||||||
f"Packet with unknown APID {apid} detected: {packet.hex(sep=',')}"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class CustomCcsdsTmHandler(CcsdsTmHandler):
|
class CustomCcsdsTmHandler(CcsdsTmHandler):
|
||||||
def user_hook(self, apid: int, packet: bytes):
|
def user_hook(self, apid: int, packet: bytes):
|
||||||
_LOGGER.debug(f"Received packet {packet.hex(sep=',')} with APID {apid}")
|
_LOGGER.debug(f"Received packet {packet.hex(sep=',')} with APID {apid}")
|
||||||
|
Loading…
Reference in New Issue
Block a user