From 2f3ffec07cf0a883c8e1ef0adc5a89468e475666 Mon Sep 17 00:00:00 2001 From: Anthony Romaniello Date: Mon, 20 Nov 2023 14:50:58 -0500 Subject: [PATCH 01/28] X.Y.Z instead of vX.Y.Z for SigMF extension versions --- scos_actions/metadata/sigmf_builder.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scos_actions/metadata/sigmf_builder.py b/scos_actions/metadata/sigmf_builder.py index 2914096f..7a3bb4a9 100644 --- a/scos_actions/metadata/sigmf_builder.py +++ b/scos_actions/metadata/sigmf_builder.py @@ -13,41 +13,41 @@ # Global info which is ALWAYS true for SCOS-generated recordings GLOBAL_INFO = { - "core:version": "v1.0.0", + "core:version": "1.0.0", "core:extensions": [ { "name": "ntia-algorithm", - "version": "v2.0.1", + "version": "2.0.1", "optional": False, }, { "name": "ntia-core", - "version": "v2.0.0", + "version": "2.0.0", "optional": False, }, { "name": "ntia-diagnostics", - "version": "v1.1.2", + "version": "1.1.2", "optional": True, }, { "name": "ntia-environment", - "version": "v1.0.0", + "version": "1.0.0", "optional": True, }, { "name": "ntia-scos", - "version": "v1.0.0", + "version": "1.0.0", "optional": True, }, { "name": "ntia-sensor", - "version": "v2.0.0", + "version": "2.0.0", "optional": False, }, { "name": "ntia-nasctn-sea", - "version": "v0.6.0", + "version": "0.6.0", "optional": True, }, ], From 0ff93d00d820b0512ca3ff4981aa0290803d0c2b Mon Sep 17 00:00:00 2001 From: Anthony Romaniello Date: Mon, 20 Nov 2023 14:58:18 -0500 Subject: [PATCH 02/28] Remove divisions from example calibration files --- scos_actions/configs/sensor_calibration_example.json | 1 - scos_actions/configs/sigan_calibration_example.json | 1 - 2 files changed, 2 deletions(-) diff --git a/scos_actions/configs/sensor_calibration_example.json b/scos_actions/configs/sensor_calibration_example.json index 57fb6847..669c7445 100644 --- a/scos_actions/configs/sensor_calibration_example.json +++ b/scos_actions/configs/sensor_calibration_example.json @@ -78,7 +78,6 @@ } }, "last_calibration_datetime": "1970-01-01T00:00:00.000000Z", - "calibration_frequency_divisions": [], "calibration_parameters": [ "sample_rate", "frequency", diff --git a/scos_actions/configs/sigan_calibration_example.json b/scos_actions/configs/sigan_calibration_example.json index 57fb6847..669c7445 100644 --- a/scos_actions/configs/sigan_calibration_example.json +++ b/scos_actions/configs/sigan_calibration_example.json @@ -78,7 +78,6 @@ } }, "last_calibration_datetime": "1970-01-01T00:00:00.000000Z", - "calibration_frequency_divisions": [], "calibration_parameters": [ "sample_rate", "frequency", From e7a33812fc33840d9c1f0c1f8171f3816cad4d78 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Wed, 29 Nov 2023 12:34:57 -0700 Subject: [PATCH 03/28] Pull diagnostics from the switches. --- pyproject.toml | 2 +- .../actions/acquire_sea_data_product.py | 51 +++++++------------ 2 files changed, 19 insertions(+), 34 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 32f2b868..1807d767 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ classifiers = [ dependencies = [ "environs>=9.5.0", "django>=3.2.18,<4.0", - "its_preselector @ git+https://github.com/NTIA/Preselector@3.0.2", + "its_preselector @ git+https://github.com/NTIA/Preselector@analog_inputs", "msgspec>=0.16.0,<1.0.0", "numexpr>=2.8.3", "numpy>=1.22.0", diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 5fc636c5..b174c1b4 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -20,6 +20,7 @@ Currently in development. """ +import json import logging import lzma import platform @@ -57,7 +58,9 @@ ntia_sensor, ) from scos_actions.metadata.structs.capture import CaptureSegment +from scos_actions.settings import PRESELECTOR_DIAGNOSTICS from scos_actions.settings import SCOS_SENSOR_GIT_TAG +from scos_actions.settings import SWITCH_DIAGNOSTICS from scos_actions.signal_processing.apd import get_apd from scos_actions.signal_processing.fft import ( get_fft, @@ -122,6 +125,7 @@ FFT_DETECTOR = create_statistical_detector("FftMeanMaxDetector", ["mean", "max"]) PFP_M3_DETECTOR = create_statistical_detector("PfpM3Detector", ["min", "max", "mean"]) + # Expected webswitch configuration: PRESELECTOR_SENSORS = { "temp": 1, # Internal temperature, deg C @@ -704,41 +708,22 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None consecutive points as the action has been running. """ tic = perf_counter() - # Read SPU sensors + switch_diag = {} + # Add status for any switch for switch in switches.values(): - if switch.name == "SPU X410": - spu_diag = switch.get_status() - del spu_diag["name"] - del spu_diag["healthy"] - for sensor in SPU_SENSORS: - try: - value = switch.get_sensor_value(SPU_SENSORS[sensor]) - spu_diag[sensor] = value - except: - logger.warning(f"Unable to read {sensor} from SPU x410") - try: - spu_diag["sigan_internal_temp"] = self.sigan.temperature - except: - logger.warning("Unable to read internal sigan temperature") - # Rename key for use with ** - spu_diag["aux_28v_powered"] = spu_diag.pop("28v_aux_powered") + switch_status = switch.get_status() + del switch_status["name"] + del switch_status["healthy"] + switch_diag.update(switch_status) + try: + switch_diag["sigan_internal_temp"] = self.sigan.temperature + except: + logger.warning("Unable to read internal sigan temperature") # Read preselector sensors - ps_diag = {} - for sensor in PRESELECTOR_SENSORS: - try: - value = preselector.get_sensor_value(PRESELECTOR_SENSORS[sensor]) - ps_diag[sensor] = value - except: - logger.warning(f"Unable to read {sensor} from preselector") - for inpt in PRESELECTOR_DIGITAL_INPUTS: - try: - value = preselector.get_digital_input_value( - PRESELECTOR_DIGITAL_INPUTS[inpt] - ) - ps_diag[inpt] = value - except: - logger.warning(f"Unable to read {inpt} from preselector") + ps_diag = preselector.get_status() + del ps_diag["name"] + del ps_diag["healthy"] # Read computer performance metrics cpu_diag = { # Start with CPU min/max/mean speeds @@ -807,7 +792,7 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None diagnostics = { "datetime": utils.get_datetime_str_now(), "preselector": ntia_diagnostics.Preselector(**ps_diag), - "spu": ntia_diagnostics.SPU(**spu_diag), + "spu": ntia_diagnostics.SPU(**switch_diag), "computer": ntia_diagnostics.Computer(**cpu_diag), "software": ntia_diagnostics.Software(**software_diag), "action_runtime": round(perf_counter() - action_start_tic, 2), From 622d153083a58e932c0abcbf2a5251e29fd515bc Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Wed, 29 Nov 2023 12:57:44 -0700 Subject: [PATCH 04/28] remove old undefined variable import. --- scos_actions/actions/acquire_sea_data_product.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index b174c1b4..080e1714 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -58,9 +58,7 @@ ntia_sensor, ) from scos_actions.metadata.structs.capture import CaptureSegment -from scos_actions.settings import PRESELECTOR_DIAGNOSTICS from scos_actions.settings import SCOS_SENSOR_GIT_TAG -from scos_actions.settings import SWITCH_DIAGNOSTICS from scos_actions.signal_processing.apd import get_apd from scos_actions.signal_processing.fft import ( get_fft, From f93157598616cb31246c5a3edb283241feac6a09 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Wed, 29 Nov 2023 13:45:36 -0700 Subject: [PATCH 05/28] Update allowed sensors and states in Diagnostic metadata. --- .../metadata/structs/ntia_diagnostics.py | 51 +++++++++++++++++-- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index 842d74c3..08481eb2 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -11,21 +11,28 @@ class Preselector(msgspec.Struct, **SIGMF_OBJECT_KWARGS): :param temp: Temperature inside the preselector enclosure, in degrees Celsius. :param noise_diode_temp: Temperature of the noise diode, in degrees Celsius. + :param noise_diode_powered: Boolean indicating if the noise diode is powered. + :param lna_powered: Boolean indicating if the lna is powered. :param lna_temp: Temparature of the low noise amplifier, in degrees Celsius. + :param antenna_path_enabled: Boolean indicating if the antenna path is enabled. + :param noise_diode_path_enabled: Boolean indicating if the noise diode path is enabled. :param humidity: Relative humidity inside the preselector enclosure, as a percentage. :param door_closed: Indicates whether the door of the enclosure is closed. """ temp: Optional[float] = None noise_diode_temp: Optional[float] = None + noise_diode_powered: Optional[bool] = None + lna_powered: Optional[bool] = None lna_temp: Optional[float] = None + antenna_path_enabled: Optional[bool] = None + noise_diode_path_enabled: Optional = None humidity: Optional[float] = None door_closed: Optional[bool] = False class SPU( - msgspec.Struct, rename={"aux_28v_powered": "28v_aux_powered"}, **SIGMF_OBJECT_KWARGS -): + msgspec.Struct, **SIGMF_OBJECT_KWARGS): """ Interface for generating `ntia-diagnostics` `SPU` objects. @@ -33,12 +40,31 @@ class SPU( :param preselector_powered: Indicates if the preselector is powered. :param aux_28v_powered: Indicates if the 28V aux power is on. :param pwr_box_temp: Ambient temperature in power distribution box, - in degrees Celsius. + in degrees Celsius.. :param pwr_box_humidity: Humidity in power distribution box, as a percentage. :param rf_box_temp: Ambient temperature in the RF box (around the signal analyzer), in degrees Celsius. + :param internal_temp: Ambient temperature in the SPU, + in degrees Celsius + :param internal_humidity: Humidity in the SPU. + :param tec_intake_temp: Temperature at the TEC intake. + :param tec_exhaust_temp: Temperature at the TEC exhaust. :param sigan_internal_temp: Internal temperature reported by the signal analyzer. + :param cooling_enabled: Boolean indicating if the cooling is enabled. + :param heat_enabled: Boolean indicating if the heat is enabled. + :param rsa_powered: Boolean indicating if the RSA is powered. + :param nuc_powered: Boolean indicating if NUC is powered. + :param tec_ac_powered: Boolean indicating TEC AC power. + :param ups_power: Boolean indicating UPS power. + :param ups_battery_level: UPS batery level warning. + :param ups_trouble: Indicates trouble with UPS. + :param ups_battery_replace: Boolean indicating if the ups battery needs replacing. + :param door_sensor: Indicates if the door is open. + :param power_5vdc: 5V DC power supplied. + :param power_15vdc: 15V DC power supplied. + :param power_24vdc: 24V DC power supplied. + :param power_28vdc: 28V DC power supplied. """ rf_tray_powered: Optional[bool] = None @@ -47,7 +73,26 @@ class SPU( pwr_box_temp: Optional[float] = None pwr_box_humidity: Optional[float] = None rf_box_temp: Optional[float] = None + internal_temp: Optional[float] = None + internal_humidity: Optional[float] = None + tec_intake_temp: Optional[float] = None + tek_exhaust_temp: Optional[float] = None sigan_internal_temp: Optional[float] = None + cooling_enabled: Optional[bool] = None + heat_enabled: Optional[bool] = None + rsa_powered: Optional[bool] = None + nuc_powered: Optional[bool] = None + tec_ac_powered: Optional[bool] = None + ups_power: Optional[bool] = None + ups_battery_level: Optional[bool] = None + ups_trouble: Optional[bool] = None + ups_battery_replace: Optional[bool] = None + door_sensor: Optional[float] = None + power_5vdc: Optional[float] = None + power_15vdc: Optional[float] = None + power_24vdc: Optional[float] = None + power_28vdc: Optional[float] = None + class SsdSmartData(msgspec.Struct, **SIGMF_OBJECT_KWARGS): From 6b7b2a04572e25333207358b326aeeeac2ac6f73 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 30 Nov 2023 13:43:31 -0700 Subject: [PATCH 06/28] Initial implementation of new spu diagnositcs. --- .../actions/acquire_sea_data_product.py | 75 ++++++++++++-- .../metadata/structs/ntia_diagnostics.py | 98 ++++++++----------- 2 files changed, 112 insertions(+), 61 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 080e1714..54ee6536 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -707,18 +707,22 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None """ tic = perf_counter() switch_diag = {} + all_switch_status = {} # Add status for any switch for switch in switches.values(): switch_status = switch.get_status() del switch_status["name"] del switch_status["healthy"] - switch_diag.update(switch_status) - try: - switch_diag["sigan_internal_temp"] = self.sigan.temperature - except: - logger.warning("Unable to read internal sigan temperature") + all_switch_status.update(switch_status) + + self.set_ups_states(all_switch_status, switch_diag) + self.add_temperature_and_humidity_sensors(all_switch_status, switch_diag) + self.add_power_sensors(all_switch_status, switch_diag) + self.add_power_states(all_switch_status, switch_diag) + if "door_closed" in all_switch_status: + switch_diag["door_closed"] = bool(all_switch_status["door_closed"]) - # Read preselector sensors + #Read preselector sensors ps_diag = preselector.get_status() del ps_diag["name"] del ps_diag["healthy"] @@ -799,6 +803,65 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None # Add diagnostics to SigMF global object self.sigmf_builder.set_diagnostics(ntia_diagnostics.Diagnostics(**diagnostics)) + def set_ups_states(self, all_switch_status: dict, switch_diag: dict): + if "ups_power_state" in all_switch_status: + switch_diag["battery_backup"] = not all_switch_status["ups_power_state"] + if "ups_battery_level" in all_switch_status: + switch_diag["low_battery"] = not all_switch_status["ups_battery_level"] + if "ups_state" in all_switch_status: + switch_diag["ups_healthy"] = not all_switch_status["ups_state"] + if "ups_battery_state" in all_switch_status: + switch_diag["replace_battery"] = not all_switch_status["ups_battery_state"] + + def add_temperature_and_humidity_sensors(self, all_switch_status: dict, switch_diag: dict): + switch_diag["temperature_sensors"] = [] + if "internal_temp" in all_switch_status: + switch_diag["temperature_sensors"].append( + {"name": "internal_temp", "value": all_switch_status["internal_temp"]}) + try: + switch_diag["temperature_sensors"].append({"name": "sigan_internal_temp", "value": self.sigan.temperature}) + except: + logger.warning("Unable to read internal sigan temperature") + if "tec_intake_temp" in all_switch_status: + switch_diag["temperature_sensors"].append({"name": "tec_intake_temp", "value": all_switch_status["tec_intake_temp"]}) + + if "tec_exhaust_temp" in all_switch_status: + switch_diag["temperature_sensors"].append( + {"name": "tec_exhaust_temp", "value": all_switch_status["tec_exhaust_temp"]}) + + if "internal_humidity" in all_switch_status: + switch_diag["humidity_sensors"] = [ + {"name": "internal_humidity", "value": all_switch_status["internal_humidity"]}] + + def add_power_sensors(self, all_switch_status: dict, switch_diag: dict ): + switch_diag["power_sensors"] = [] + if "5vdc_monitor" in all_switch_status: + switch_diag["power_sensors"].append( + {"name": "5v Monitor", "value:": all_switch_status["5vdc_monitor"], "expected_value": 5.0}) + if "15vdc_monitor" in all_switch_status: + switch_diag["power_sensors"].append( + {"name": "15v Monitor", "value:": all_switch_status["15vdc_monitor"], "expected_value": 15.0}) + if "24vdc_monitor" in all_switch_status: + switch_diag["power_sensors"].append( + {"name": "24v Monitor", "value:": all_switch_status["24vdc_monitor"], "expected_value": 24.0}) + if "28vdc_monitor" in all_switch_status: + switch_diag["power_sensors"].append( + {"name": "28v Monitor", "value:": all_switch_status["28vdc_monitor"], "expected_value": 28.0}) + + def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): + if "heating" in all_switch_status: + switch_diag["heating"] = all_switch_status["heating"] + if "cooling" in all_switch_status: + switch_diag["cooling"] all_switch_status["cooling"] + + def add_power_states(self, all_switch_status: dict, switch_diag: dict): + if "sigan_powered" in all_switch_status: + switch_diag["sigan_powered"] = all_switch_status["sigan_powered"] + if "temperature_control_powered" in all_switch_status: + switch_diag["temperature_control_powered"] = all_switch_status["temperature_control_powered"] + if "preselector_powered" in all_switch_status: + switch_diag["preselector_powered"] = all_switch_status["preselector_powered"] + def create_global_sensor_metadata(self): # Add (minimal) ntia-sensor metadata to the sigmf_builder: # sensor ID, serial numbers for preselector, sigan, and computer diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index 08481eb2..ef6af7e9 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -1,4 +1,4 @@ -from typing import Optional +from typing import Optional, List import msgspec @@ -30,69 +30,57 @@ class Preselector(msgspec.Struct, **SIGMF_OBJECT_KWARGS): humidity: Optional[float] = None door_closed: Optional[bool] = False +class DiagnosticSensor(msgspec.Struct, **SIGMF_OBJECT_KWARGS): + """ + Interface for generating `ntia-diagnostics` `DiagnosticSensor` objects. + + :param name: The name of the sensor + :param value: The value provided by the sensor + :param maximum_allowed: The maximum value allowed from the sensor before action should be taken + :param mimimum_allowed: The minimum value allowed from the sensor before action should be taken + :param description: A description of the sensor + """ + name: str + value: float + maximum_allowed: Optional[float] = None + minimum_allowed: Optional[float] = None + expected_value: Optional[float] = None + description: Optional[str] = None class SPU( msgspec.Struct, **SIGMF_OBJECT_KWARGS): """ Interface for generating `ntia-diagnostics` `SPU` objects. - :param rf_tray_powered: Indicates if the RF tray is powered. + :param cooling: Boolean indicating if the cooling is enabled. + :param heating: Boolean indicating if the heat is enabled. :param preselector_powered: Indicates if the preselector is powered. - :param aux_28v_powered: Indicates if the 28V aux power is on. - :param pwr_box_temp: Ambient temperature in power distribution box, - in degrees Celsius.. - :param pwr_box_humidity: Humidity in power distribution box, as a - percentage. - :param rf_box_temp: Ambient temperature in the RF box (around the signal - analyzer), in degrees Celsius. - :param internal_temp: Ambient temperature in the SPU, - in degrees Celsius - :param internal_humidity: Humidity in the SPU. - :param tec_intake_temp: Temperature at the TEC intake. - :param tec_exhaust_temp: Temperature at the TEC exhaust. - :param sigan_internal_temp: Internal temperature reported by the signal analyzer. - :param cooling_enabled: Boolean indicating if the cooling is enabled. - :param heat_enabled: Boolean indicating if the heat is enabled. - :param rsa_powered: Boolean indicating if the RSA is powered. - :param nuc_powered: Boolean indicating if NUC is powered. - :param tec_ac_powered: Boolean indicating TEC AC power. - :param ups_power: Boolean indicating UPS power. - :param ups_battery_level: UPS batery level warning. - :param ups_trouble: Indicates trouble with UPS. - :param ups_battery_replace: Boolean indicating if the ups battery needs replacing. - :param door_sensor: Indicates if the door is open. - :param power_5vdc: 5V DC power supplied. - :param power_15vdc: 15V DC power supplied. - :param power_24vdc: 24V DC power supplied. - :param power_28vdc: 28V DC power supplied. - """ - - rf_tray_powered: Optional[bool] = None + :param sigan_powered: Boolean indicating if the signal analyzer is powered. + :param temperature_control_powered: Boolean indicating TEC AC power. + :param battery_backup: Boolean indicating if it is running on battery backup. + :param low_battery: Boolean indicating if the battery is low. + :param ups_healthy: Indicates trouble with UPS. + :param replace_battery: Boolean indicating if the ups battery needs replacing. + :param temperature_sensors: List of temperature sensor values + :param humidity_sensors: List of humidity sensor values + :param power_sensors: List of power sensor values + :param door_closed: Boolean indicating if the door is closed + """ + cooling: Optional[bool] = None + heating: Optional[bool] = None + sigan_powered: Optional[bool] = None + temperature_control_powered: Optional[bool] = None preselector_powered: Optional[bool] = None - aux_28v_powered: Optional[bool] = None - pwr_box_temp: Optional[float] = None - pwr_box_humidity: Optional[float] = None - rf_box_temp: Optional[float] = None - internal_temp: Optional[float] = None - internal_humidity: Optional[float] = None - tec_intake_temp: Optional[float] = None - tek_exhaust_temp: Optional[float] = None - sigan_internal_temp: Optional[float] = None - cooling_enabled: Optional[bool] = None - heat_enabled: Optional[bool] = None - rsa_powered: Optional[bool] = None - nuc_powered: Optional[bool] = None - tec_ac_powered: Optional[bool] = None - ups_power: Optional[bool] = None - ups_battery_level: Optional[bool] = None - ups_trouble: Optional[bool] = None - ups_battery_replace: Optional[bool] = None - door_sensor: Optional[float] = None - power_5vdc: Optional[float] = None - power_15vdc: Optional[float] = None - power_24vdc: Optional[float] = None - power_28vdc: Optional[float] = None + battery_backup: Optional[bool] = None + low_battery: Optional[bool] = None + ups_healthy: Optional[bool] = None + replace_battery: Optional[bool] = None + + temperature_sensors: Optional[List[DiagnosticSensor]] + humidity_sensors: Optional[List[DiagnosticSensor]] + power_sensors: Optional[List[DiagnosticSensor]] + door_closed: Optional[bool] = None class SsdSmartData(msgspec.Struct, **SIGMF_OBJECT_KWARGS): From d8eff11e6c036fd346fb51006b90d37e73c15f9f Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 30 Nov 2023 13:56:09 -0700 Subject: [PATCH 07/28] typo fix. --- scos_actions/actions/acquire_sea_data_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 54ee6536..2ada163a 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -852,7 +852,7 @@ def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: switch_diag["heating"] = all_switch_status["heating"] if "cooling" in all_switch_status: - switch_diag["cooling"] all_switch_status["cooling"] + switch_diag["cooling"] = all_switch_status["cooling"] def add_power_states(self, all_switch_status: dict, switch_diag: dict): if "sigan_powered" in all_switch_status: From 79827a3f673569747de6aaa4717fcd9329cbdf26 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 30 Nov 2023 14:00:33 -0700 Subject: [PATCH 08/28] set optional fields to None. --- scos_actions/metadata/structs/ntia_diagnostics.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index ef6af7e9..a5927744 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -77,9 +77,9 @@ class SPU( ups_healthy: Optional[bool] = None replace_battery: Optional[bool] = None - temperature_sensors: Optional[List[DiagnosticSensor]] - humidity_sensors: Optional[List[DiagnosticSensor]] - power_sensors: Optional[List[DiagnosticSensor]] + temperature_sensors: Optional[List[DiagnosticSensor]] = None + humidity_sensors: Optional[List[DiagnosticSensor]] = None + power_sensors: Optional[List[DiagnosticSensor]] = None door_closed: Optional[bool] = None From 9e9007fcd9fc6b59f47715981f1d3ad0d3bc2240 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 30 Nov 2023 14:31:51 -0700 Subject: [PATCH 09/28] Update Preselector lib to 3.1.0. --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1807d767..fda627c5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,7 +44,7 @@ classifiers = [ dependencies = [ "environs>=9.5.0", "django>=3.2.18,<4.0", - "its_preselector @ git+https://github.com/NTIA/Preselector@analog_inputs", + "its_preselector @ git+https://github.com/NTIA/Preselector@3.1.0", "msgspec>=0.16.0,<1.0.0", "numexpr>=2.8.3", "numpy>=1.22.0", From 56d0dd4cda117f4f35b2d1e851f3a158035ca56c Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 08:08:39 -0700 Subject: [PATCH 10/28] Change scos_start and scos_uptime to software_start and software_uptime. --- scos_actions/actions/acquire_sea_data_product.py | 4 ++-- scos_actions/metadata/structs/ntia_diagnostics.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 2ada163a..b26ae017 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -762,13 +762,13 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None except: logger.warning("Failed to get CPU overheating status") try: # SCOS start time - cpu_diag["scos_start"] = convert_datetime_to_millisecond_iso_format( + cpu_diag["software_start"] = convert_datetime_to_millisecond_iso_format( start_time ) except: logger.warning("Failed to get SCOS start time") try: # SCOS uptime - cpu_diag["scos_uptime"] = get_days_up() + cpu_diag["software_uptime"] = get_days_up() except: logger.warning("Failed to get SCOS uptime") try: # SSD SMART data diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index a5927744..bcc02baa 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -147,8 +147,8 @@ class Computer(msgspec.Struct, **SIGMF_OBJECT_KWARGS): memory_usage: Optional[float] = None cpu_overheating: Optional[bool] = None cpu_temp: Optional[float] = None - scos_start: Optional[str] = None - scos_uptime: Optional[float] = None + software_start: Optional[str] = None + software_uptime: Optional[float] = None ssd_smart_data: Optional[SsdSmartData] = None From b127b32420e8e7d492c439fb4adba08c95fd2fcd Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 08:47:53 -0700 Subject: [PATCH 11/28] Remove requirement to have SPU-x410 switch. --- scos_actions/actions/acquire_sea_data_product.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index b26ae017..aa8e404c 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -882,9 +882,6 @@ def test_required_components(self): msg = "Acquisition failed: signal analyzer is not available" trigger_api_restart.send(sender=self.__class__) raise RuntimeError(msg) - if "SPU X410" not in [s.name for s in switches.values()]: - msg = "Configuration error: no switch configured with name 'SPU X410'" - raise RuntimeError(msg) if not self.sigan.healthy(): trigger_api_restart.send(sender=self.__class__) return None From 48298e5cae0f58d4b7493842b185a171f7a1d167 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 09:08:51 -0700 Subject: [PATCH 12/28] fix typo in power_sensors metadata. --- scos_actions/actions/acquire_sea_data_product.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index aa8e404c..bd265e21 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -837,16 +837,16 @@ def add_power_sensors(self, all_switch_status: dict, switch_diag: dict ): switch_diag["power_sensors"] = [] if "5vdc_monitor" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "5v Monitor", "value:": all_switch_status["5vdc_monitor"], "expected_value": 5.0}) + {"name": "5v Monitor", "value": all_switch_status["5vdc_monitor"], "expected_value": 5.0}) if "15vdc_monitor" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "15v Monitor", "value:": all_switch_status["15vdc_monitor"], "expected_value": 15.0}) + {"name": "15v Monitor", "value": all_switch_status["15vdc_monitor"], "expected_value": 15.0}) if "24vdc_monitor" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "24v Monitor", "value:": all_switch_status["24vdc_monitor"], "expected_value": 24.0}) + {"name": "24v Monitor", "value": all_switch_status["24vdc_monitor"], "expected_value": 24.0}) if "28vdc_monitor" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "28v Monitor", "value:": all_switch_status["28vdc_monitor"], "expected_value": 28.0}) + {"name": "28v Monitor", "value": all_switch_status["28vdc_monitor"], "expected_value": 28.0}) def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: From 0b1a42dfd7aee12dfe599f9dd2b396ed7a928659 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 10:06:27 -0700 Subject: [PATCH 13/28] change diagnostics to v2.0.0 --- scos_actions/metadata/sigmf_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/metadata/sigmf_builder.py b/scos_actions/metadata/sigmf_builder.py index 2914096f..6759b555 100644 --- a/scos_actions/metadata/sigmf_builder.py +++ b/scos_actions/metadata/sigmf_builder.py @@ -27,7 +27,7 @@ }, { "name": "ntia-diagnostics", - "version": "v1.1.2", + "version": "v2.0.0", "optional": True, }, { From 2364a062a1d45f841724c8b6179410ddb3c5e683 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 10:30:20 -0700 Subject: [PATCH 14/28] Move action_runtime into computer diagnostics. --- scos_actions/actions/acquire_sea_data_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index bd265e21..e2e0d3a7 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -732,6 +732,7 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None "cpu_max_clock": round(max(cpu_speeds), 1), "cpu_min_clock": round(min(cpu_speeds), 1), "cpu_mean_clock": round(np.mean(cpu_speeds), 1), + "action_runtime": round(perf_counter() - action_start_tic, 2), } try: # Computer uptime (days) cpu_diag["cpu_uptime"] = round(get_cpu_uptime_seconds() / (60 * 60 * 24), 2) @@ -797,7 +798,6 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None "spu": ntia_diagnostics.SPU(**switch_diag), "computer": ntia_diagnostics.Computer(**cpu_diag), "software": ntia_diagnostics.Software(**software_diag), - "action_runtime": round(perf_counter() - action_start_tic, 2), } # Add diagnostics to SigMF global object From c947a828208672088396f1b179fcb51cf429a427 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 10:40:34 -0700 Subject: [PATCH 15/28] move action_runtime into computer diagnostics. --- scos_actions/metadata/structs/ntia_diagnostics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index bcc02baa..0c12c6cd 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -143,6 +143,7 @@ class Computer(msgspec.Struct, **SIGMF_OBJECT_KWARGS): cpu_mean_clock: Optional[float] = None cpu_uptime: Optional[float] = None action_cpu_usage: Optional[float] = None + action_runtime: Optional[float] = None system_load_5m: Optional[float] = None memory_usage: Optional[float] = None cpu_overheating: Optional[bool] = None @@ -202,4 +203,4 @@ class Diagnostics(msgspec.Struct, **SIGMF_OBJECT_KWARGS): spu: Optional[SPU] = None computer: Optional[Computer] = None software: Optional[Software] = None - action_runtime: Optional[float] = None + From b0231d01c227650b45521743703398f9d2f859d5 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 11:33:13 -0700 Subject: [PATCH 16/28] Not the value of the door_closed spu sensor because 0 indicates it is closed and 1 indicates it is open. --- scos_actions/actions/acquire_sea_data_product.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index e2e0d3a7..452902e3 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -720,7 +720,7 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None self.add_power_sensors(all_switch_status, switch_diag) self.add_power_states(all_switch_status, switch_diag) if "door_closed" in all_switch_status: - switch_diag["door_closed"] = bool(all_switch_status["door_closed"]) + switch_diag["door_closed"] = not bool(all_switch_status["door_closed"]) #Read preselector sensors ps_diag = preselector.get_status() From 3fcefb32b75665adc1e7fe6327cf257b8ce853f8 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 11:42:49 -0700 Subject: [PATCH 17/28] use door_state in switch config instead of door_closed because it is configured to be 0 for closed and 1 for open. --- scos_actions/actions/acquire_sea_data_product.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 452902e3..1ed18b19 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -719,8 +719,8 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None self.add_temperature_and_humidity_sensors(all_switch_status, switch_diag) self.add_power_sensors(all_switch_status, switch_diag) self.add_power_states(all_switch_status, switch_diag) - if "door_closed" in all_switch_status: - switch_diag["door_closed"] = not bool(all_switch_status["door_closed"]) + if "door_state" in all_switch_status: + switch_diag["door_closed"] = not bool(all_switch_status["door_state"]) #Read preselector sensors ps_diag = preselector.get_status() From 690e1475ff0ca58e7cfdc3052a59a39ae3425142 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 11:51:52 -0700 Subject: [PATCH 18/28] change power sensor names. --- scos_actions/actions/acquire_sea_data_product.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 1ed18b19..27611c19 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -835,18 +835,18 @@ def add_temperature_and_humidity_sensors(self, all_switch_status: dict, switch_d def add_power_sensors(self, all_switch_status: dict, switch_diag: dict ): switch_diag["power_sensors"] = [] - if "5vdc_monitor" in all_switch_status: + if "power_monitor5v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "5v Monitor", "value": all_switch_status["5vdc_monitor"], "expected_value": 5.0}) - if "15vdc_monitor" in all_switch_status: + {"name": "5v Monitor", "value": all_switch_status["power_monitor5v"], "expected_value": 5.0}) + if "power_monitor15v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "15v Monitor", "value": all_switch_status["15vdc_monitor"], "expected_value": 15.0}) - if "24vdc_monitor" in all_switch_status: + {"name": "15v Monitor", "value": all_switch_status["power_monitor15v"], "expected_value": 15.0}) + if "power_monitor24v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "24v Monitor", "value": all_switch_status["24vdc_monitor"], "expected_value": 24.0}) - if "28vdc_monitor" in all_switch_status: + {"name": "24v Monitor", "value": all_switch_status["power_monitor24v"], "expected_value": 24.0}) + if "power_monitor28v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "28v Monitor", "value": all_switch_status["28vdc_monitor"], "expected_value": 28.0}) + {"name": "28v Monitor", "value": all_switch_status["power_monitor28v"], "expected_value": 28.0}) def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: From 7f000a3de0c06db1bdb0084c5a636d25042244cc Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 12:00:26 -0700 Subject: [PATCH 19/28] increment version. --- scos_actions/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/__init__.py b/scos_actions/__init__.py index 9c4b2035..b378fc6c 100644 --- a/scos_actions/__init__.py +++ b/scos_actions/__init__.py @@ -1 +1 @@ -__version__ = "6.4.2" +__version__ = "7.0.0" From 1047ff684377797d108119dfbf5241d6d0d8a4a5 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 13:28:34 -0700 Subject: [PATCH 20/28] Remove unused variables. --- .../actions/acquire_sea_data_product.py | 85 ++++++++++++------- 1 file changed, 56 insertions(+), 29 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index 27611c19..eba78255 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -124,21 +124,6 @@ PFP_M3_DETECTOR = create_statistical_detector("PfpM3Detector", ["min", "max", "mean"]) -# Expected webswitch configuration: -PRESELECTOR_SENSORS = { - "temp": 1, # Internal temperature, deg C - "noise_diode_temp": 2, # Noise diode temperature, deg C - "lna_temp": 3, # LNA temperature, deg C - "humidity": 4, # Internal humidity, percentage -} -PRESELECTOR_DIGITAL_INPUTS = {"door_closed": 1} -SPU_SENSORS = { - "pwr_box_temp": 1, # Power tray temperature, deg C - "rf_box_temp": 2, # RF tray temperature, deg C - "pwr_box_humidity": 3, # Power tray humidity, percentage -} - - @ray.remote class PowerSpectralDensity: """ @@ -722,7 +707,7 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None if "door_state" in all_switch_status: switch_diag["door_closed"] = not bool(all_switch_status["door_state"]) - #Read preselector sensors + # Read preselector sensors ps_diag = preselector.get_status() del ps_diag["name"] del ps_diag["healthy"] @@ -813,40 +798,78 @@ def set_ups_states(self, all_switch_status: dict, switch_diag: dict): if "ups_battery_state" in all_switch_status: switch_diag["replace_battery"] = not all_switch_status["ups_battery_state"] - def add_temperature_and_humidity_sensors(self, all_switch_status: dict, switch_diag: dict): + def add_temperature_and_humidity_sensors( + self, all_switch_status: dict, switch_diag: dict + ): switch_diag["temperature_sensors"] = [] if "internal_temp" in all_switch_status: switch_diag["temperature_sensors"].append( - {"name": "internal_temp", "value": all_switch_status["internal_temp"]}) + {"name": "internal_temp", "value": all_switch_status["internal_temp"]} + ) try: - switch_diag["temperature_sensors"].append({"name": "sigan_internal_temp", "value": self.sigan.temperature}) + switch_diag["temperature_sensors"].append( + {"name": "sigan_internal_temp", "value": self.sigan.temperature} + ) except: logger.warning("Unable to read internal sigan temperature") if "tec_intake_temp" in all_switch_status: - switch_diag["temperature_sensors"].append({"name": "tec_intake_temp", "value": all_switch_status["tec_intake_temp"]}) + switch_diag["temperature_sensors"].append( + { + "name": "tec_intake_temp", + "value": all_switch_status["tec_intake_temp"], + } + ) if "tec_exhaust_temp" in all_switch_status: switch_diag["temperature_sensors"].append( - {"name": "tec_exhaust_temp", "value": all_switch_status["tec_exhaust_temp"]}) + { + "name": "tec_exhaust_temp", + "value": all_switch_status["tec_exhaust_temp"], + } + ) if "internal_humidity" in all_switch_status: switch_diag["humidity_sensors"] = [ - {"name": "internal_humidity", "value": all_switch_status["internal_humidity"]}] + { + "name": "internal_humidity", + "value": all_switch_status["internal_humidity"], + } + ] - def add_power_sensors(self, all_switch_status: dict, switch_diag: dict ): + def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): switch_diag["power_sensors"] = [] if "power_monitor5v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "5v Monitor", "value": all_switch_status["power_monitor5v"], "expected_value": 5.0}) + { + "name": "5v Monitor", + "value": all_switch_status["power_monitor5v"], + "expected_value": 5.0, + } + ) if "power_monitor15v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "15v Monitor", "value": all_switch_status["power_monitor15v"], "expected_value": 15.0}) + { + "name": "15v Monitor", + "value": all_switch_status["power_monitor15v"], + "expected_value": 15.0, + } + ) if "power_monitor24v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "24v Monitor", "value": all_switch_status["power_monitor24v"], "expected_value": 24.0}) + { + "name": "24v Monitor", + "value": all_switch_status["power_monitor24v"], + "expected_value": 24.0, + } + ) if "power_monitor28v" in all_switch_status: switch_diag["power_sensors"].append( - {"name": "28v Monitor", "value": all_switch_status["power_monitor28v"], "expected_value": 28.0}) + { + "name": "28v Monitor", + "value": all_switch_status["power_monitor28v"], + "expected_value": 28.0, + } + ) def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: @@ -858,9 +881,13 @@ def add_power_states(self, all_switch_status: dict, switch_diag: dict): if "sigan_powered" in all_switch_status: switch_diag["sigan_powered"] = all_switch_status["sigan_powered"] if "temperature_control_powered" in all_switch_status: - switch_diag["temperature_control_powered"] = all_switch_status["temperature_control_powered"] + switch_diag["temperature_control_powered"] = all_switch_status[ + "temperature_control_powered" + ] if "preselector_powered" in all_switch_status: - switch_diag["preselector_powered"] = all_switch_status["preselector_powered"] + switch_diag["preselector_powered"] = all_switch_status[ + "preselector_powered" + ] def create_global_sensor_metadata(self): # Add (minimal) ntia-sensor metadata to the sigmf_builder: From 98a6fd8419bf22529d31bc4e989402f8153b0098 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 13:29:14 -0700 Subject: [PATCH 21/28] run pre-commit. --- scos_actions/metadata/structs/ntia_diagnostics.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index 0c12c6cd..a6e5e0e7 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -1,4 +1,4 @@ -from typing import Optional, List +from typing import List, Optional import msgspec @@ -30,6 +30,7 @@ class Preselector(msgspec.Struct, **SIGMF_OBJECT_KWARGS): humidity: Optional[float] = None door_closed: Optional[bool] = False + class DiagnosticSensor(msgspec.Struct, **SIGMF_OBJECT_KWARGS): """ Interface for generating `ntia-diagnostics` `DiagnosticSensor` objects. @@ -40,6 +41,7 @@ class DiagnosticSensor(msgspec.Struct, **SIGMF_OBJECT_KWARGS): :param mimimum_allowed: The minimum value allowed from the sensor before action should be taken :param description: A description of the sensor """ + name: str value: float maximum_allowed: Optional[float] = None @@ -47,8 +49,8 @@ class DiagnosticSensor(msgspec.Struct, **SIGMF_OBJECT_KWARGS): expected_value: Optional[float] = None description: Optional[str] = None -class SPU( - msgspec.Struct, **SIGMF_OBJECT_KWARGS): + +class SPU(msgspec.Struct, **SIGMF_OBJECT_KWARGS): """ Interface for generating `ntia-diagnostics` `SPU` objects. @@ -66,6 +68,7 @@ class SPU( :param power_sensors: List of power sensor values :param door_closed: Boolean indicating if the door is closed """ + cooling: Optional[bool] = None heating: Optional[bool] = None sigan_powered: Optional[bool] = None @@ -203,4 +206,3 @@ class Diagnostics(msgspec.Struct, **SIGMF_OBJECT_KWARGS): spu: Optional[SPU] = None computer: Optional[Computer] = None software: Optional[Software] = None - From 5c4f89ca6b3727d0e0f842739a2c1f4245e0ff85 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 13:52:48 -0700 Subject: [PATCH 22/28] Add log warnings when expected states or sensors are not found in switch status within sea action. --- .../actions/acquire_sea_data_product.py | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index eba78255..e8190253 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -791,12 +791,23 @@ def capture_diagnostics(self, action_start_tic: float, cpu_speeds: list) -> None def set_ups_states(self, all_switch_status: dict, switch_diag: dict): if "ups_power_state" in all_switch_status: switch_diag["battery_backup"] = not all_switch_status["ups_power_state"] + else: + logger.warning("No ups_power_state found in switch status.") + if "ups_battery_level" in all_switch_status: switch_diag["low_battery"] = not all_switch_status["ups_battery_level"] + else: + logger.warning("No ups_battery_level found in switch status.") + if "ups_state" in all_switch_status: switch_diag["ups_healthy"] = not all_switch_status["ups_state"] + else: + logger.warning("No ups_state found in switch status.") + if "ups_battery_state" in all_switch_status: switch_diag["replace_battery"] = not all_switch_status["ups_battery_state"] + else: + logger.warning("No ups_battery_state found in switch status") def add_temperature_and_humidity_sensors( self, all_switch_status: dict, switch_diag: dict @@ -806,12 +817,15 @@ def add_temperature_and_humidity_sensors( switch_diag["temperature_sensors"].append( {"name": "internal_temp", "value": all_switch_status["internal_temp"]} ) + else: + logger.warning("No internal_temp found in switch status.") try: switch_diag["temperature_sensors"].append( {"name": "sigan_internal_temp", "value": self.sigan.temperature} ) except: logger.warning("Unable to read internal sigan temperature") + if "tec_intake_temp" in all_switch_status: switch_diag["temperature_sensors"].append( { @@ -819,6 +833,8 @@ def add_temperature_and_humidity_sensors( "value": all_switch_status["tec_intake_temp"], } ) + else: + logger.warning("No tec_intake_temp found in switch status.") if "tec_exhaust_temp" in all_switch_status: switch_diag["temperature_sensors"].append( @@ -827,6 +843,8 @@ def add_temperature_and_humidity_sensors( "value": all_switch_status["tec_exhaust_temp"], } ) + else: + logger.warning("No tec_exhaust_temp found in switch status.") if "internal_humidity" in all_switch_status: switch_diag["humidity_sensors"] = [ @@ -835,6 +853,8 @@ def add_temperature_and_humidity_sensors( "value": all_switch_status["internal_humidity"], } ] + else: + logger.warning("No internal_humidity found in switch status.") def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): switch_diag["power_sensors"] = [] @@ -846,6 +866,9 @@ def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): "expected_value": 5.0, } ) + else: + logger.warning("No power_monitor5v found in switch status") + if "power_monitor15v" in all_switch_status: switch_diag["power_sensors"].append( { @@ -854,6 +877,9 @@ def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): "expected_value": 15.0, } ) + else: + logger.warning("No power_monitor15v found in switch status.") + if "power_monitor24v" in all_switch_status: switch_diag["power_sensors"].append( { @@ -862,6 +888,9 @@ def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): "expected_value": 24.0, } ) + else: + logger.warning("No power_monitor24v found in switch status") + if "power_monitor28v" in all_switch_status: switch_diag["power_sensors"].append( { @@ -870,24 +899,39 @@ def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): "expected_value": 28.0, } ) + else: + logger.warning("No power_monitor28v found in switch status") def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: switch_diag["heating"] = all_switch_status["heating"] + else: + logger.warning("No heating found in switch status.") + if "cooling" in all_switch_status: switch_diag["cooling"] = all_switch_status["cooling"] + else: + logger.warning("No cooling found in switch status") def add_power_states(self, all_switch_status: dict, switch_diag: dict): if "sigan_powered" in all_switch_status: switch_diag["sigan_powered"] = all_switch_status["sigan_powered"] + else: + logger.warning("No sigan_powered found in switch status.") + if "temperature_control_powered" in all_switch_status: switch_diag["temperature_control_powered"] = all_switch_status[ "temperature_control_powered" ] + else: + logger.warning("No temperature_control_powered found in switch status.") + if "preselector_powered" in all_switch_status: switch_diag["preselector_powered"] = all_switch_status[ "preselector_powered" ] + else: + logger.warning("No preselector_powered found in switch status.") def create_global_sensor_metadata(self): # Add (minimal) ntia-sensor metadata to the sigmf_builder: From 34f00f67e7017376f9c761e93ffc125df28620ec Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Fri, 1 Dec 2023 14:19:05 -0700 Subject: [PATCH 23/28] Corrected type of noise_diode_path_enabled and changed power sensors to use capital V. --- .../actions/acquire_sea_data_product.py | 32 +++++++++---------- .../metadata/structs/ntia_diagnostics.py | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/scos_actions/actions/acquire_sea_data_product.py b/scos_actions/actions/acquire_sea_data_product.py index e8190253..c36caa94 100644 --- a/scos_actions/actions/acquire_sea_data_product.py +++ b/scos_actions/actions/acquire_sea_data_product.py @@ -858,49 +858,49 @@ def add_temperature_and_humidity_sensors( def add_power_sensors(self, all_switch_status: dict, switch_diag: dict): switch_diag["power_sensors"] = [] - if "power_monitor5v" in all_switch_status: + if "power_monitor5V" in all_switch_status: switch_diag["power_sensors"].append( { - "name": "5v Monitor", - "value": all_switch_status["power_monitor5v"], + "name": "5V Monitor", + "value": all_switch_status["power_monitor5V"], "expected_value": 5.0, } ) else: - logger.warning("No power_monitor5v found in switch status") + logger.warning("No power_monitor5V found in switch status") - if "power_monitor15v" in all_switch_status: + if "power_monitor15V" in all_switch_status: switch_diag["power_sensors"].append( { - "name": "15v Monitor", - "value": all_switch_status["power_monitor15v"], + "name": "15V Monitor", + "value": all_switch_status["power_monitor15V"], "expected_value": 15.0, } ) else: - logger.warning("No power_monitor15v found in switch status.") + logger.warning("No power_monitor15V found in switch status.") - if "power_monitor24v" in all_switch_status: + if "power_monitor24V" in all_switch_status: switch_diag["power_sensors"].append( { - "name": "24v Monitor", - "value": all_switch_status["power_monitor24v"], + "name": "24V Monitor", + "value": all_switch_status["power_monitor24V"], "expected_value": 24.0, } ) else: - logger.warning("No power_monitor24v found in switch status") + logger.warning("No power_monitor24V found in switch status") - if "power_monitor28v" in all_switch_status: + if "power_monitor28V" in all_switch_status: switch_diag["power_sensors"].append( { - "name": "28v Monitor", - "value": all_switch_status["power_monitor28v"], + "name": "28V Monitor", + "value": all_switch_status["power_monitor28V"], "expected_value": 28.0, } ) else: - logger.warning("No power_monitor28v found in switch status") + logger.warning("No power_monitor28V found in switch status") def add_heating_cooling(self, all_switch_status: dict, switch_diag: dict): if "heating" in all_switch_status: diff --git a/scos_actions/metadata/structs/ntia_diagnostics.py b/scos_actions/metadata/structs/ntia_diagnostics.py index a6e5e0e7..8c144299 100644 --- a/scos_actions/metadata/structs/ntia_diagnostics.py +++ b/scos_actions/metadata/structs/ntia_diagnostics.py @@ -26,7 +26,7 @@ class Preselector(msgspec.Struct, **SIGMF_OBJECT_KWARGS): lna_powered: Optional[bool] = None lna_temp: Optional[float] = None antenna_path_enabled: Optional[bool] = None - noise_diode_path_enabled: Optional = None + noise_diode_path_enabled: Optional[bool] = None humidity: Optional[float] = None door_closed: Optional[bool] = False From 9588c0bc36987088371bc64cd4f21fe78ef493b6 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Wed, 6 Dec 2023 15:34:27 -0700 Subject: [PATCH 24/28] debug --- scos_actions/actions/acquire_single_freq_fft.py | 1 + scos_actions/actions/acquire_single_freq_tdomain_iq.py | 1 + scos_actions/actions/interfaces/measurement_action.py | 2 ++ 3 files changed, 4 insertions(+) diff --git a/scos_actions/actions/acquire_single_freq_fft.py b/scos_actions/actions/acquire_single_freq_fft.py index a0cd7b6a..aaa37913 100644 --- a/scos_actions/actions/acquire_single_freq_fft.py +++ b/scos_actions/actions/acquire_single_freq_fft.py @@ -188,6 +188,7 @@ def execute(self, schedule_entry: dict, task_id: int) -> dict: # Build capture metadata sigan_settings = self.get_sigan_settings(measurement_result) + logger.debug(f"sigan settings:{sigan_settings}") measurement_result["capture_segment"] = self.create_capture_segment( sample_start=0, start_time=measurement_result["capture_time"], diff --git a/scos_actions/actions/acquire_single_freq_tdomain_iq.py b/scos_actions/actions/acquire_single_freq_tdomain_iq.py index 19aea960..7943dfb7 100644 --- a/scos_actions/actions/acquire_single_freq_tdomain_iq.py +++ b/scos_actions/actions/acquire_single_freq_tdomain_iq.py @@ -96,6 +96,7 @@ def execute(self, schedule_entry: dict, task_id: int) -> dict: ] measurement_result["classification"] = self.classification sigan_settings = self.get_sigan_settings(measurement_result) + logger.debug(f"sigan settings:{sigan_settings}") measurement_result["capture_segment"] = self.create_capture_segment( sample_start=0, start_time=measurement_result["capture_time"], diff --git a/scos_actions/actions/interfaces/measurement_action.py b/scos_actions/actions/interfaces/measurement_action.py index 0dd9587f..8acc224f 100644 --- a/scos_actions/actions/interfaces/measurement_action.py +++ b/scos_actions/actions/interfaces/measurement_action.py @@ -112,6 +112,8 @@ def create_metadata( except KeyError: logger.warning(warning_str.format("calibration_datetime")) try: + cap = measurement_result["capture_segment"] + logger.debug(f"Adding capture:{cap}") self.sigmf_builder.add_capture(measurement_result["capture_segment"]) except KeyError: logger.warning(warning_str.format("capture_segment")) From 245acb7828fdfef41e93a9e2d51eddb9f0bda4e7 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 7 Dec 2023 08:34:44 -0700 Subject: [PATCH 25/28] remove encoder. --- scos_actions/metadata/sigmf_builder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/metadata/sigmf_builder.py b/scos_actions/metadata/sigmf_builder.py index 2a838d82..9ff1bb1e 100644 --- a/scos_actions/metadata/sigmf_builder.py +++ b/scos_actions/metadata/sigmf_builder.py @@ -417,7 +417,7 @@ def set_sensor(self, sensor: Sensor) -> None: self.sigmf_md.set_global_field("ntia-sensor:sensor", sensor) def add_capture(self, capture: CaptureSegment) -> None: - capture_dict = json.loads(msgspec_enc.encode(capture)) + capture_dict = json.loads(capture) sample_start = capture_dict.pop("core:sample_start") self.sigmf_md.add_capture(sample_start, metadata=capture_dict) From 245ddfb71323d95228fc3b459e4ebc4b3928e99a Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 7 Dec 2023 08:59:46 -0700 Subject: [PATCH 26/28] testing --- scos_actions/metadata/sigmf_builder.py | 2 +- scos_actions/metadata/utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scos_actions/metadata/sigmf_builder.py b/scos_actions/metadata/sigmf_builder.py index 9ff1bb1e..2a838d82 100644 --- a/scos_actions/metadata/sigmf_builder.py +++ b/scos_actions/metadata/sigmf_builder.py @@ -417,7 +417,7 @@ def set_sensor(self, sensor: Sensor) -> None: self.sigmf_md.set_global_field("ntia-sensor:sensor", sensor) def add_capture(self, capture: CaptureSegment) -> None: - capture_dict = json.loads(capture) + capture_dict = json.loads(msgspec_enc.encode(capture)) sample_start = capture_dict.pop("core:sample_start") self.sigmf_md.add_capture(sample_start, metadata=capture_dict) diff --git a/scos_actions/metadata/utils.py b/scos_actions/metadata/utils.py index 3a2ea965..ef4fd5e9 100644 --- a/scos_actions/metadata/utils.py +++ b/scos_actions/metadata/utils.py @@ -40,7 +40,7 @@ def _enc_hook(obj: Any) -> Any: # A reusable encoder with custom hook to ensure serialization -msgspec_enc = msgspec.json.Encoder(enc_hook=_enc_hook) +msgspec_enc = msgspec.json.Encoder() # A reusable decoder which outputs a Python dictionary msgspec_dec_dict = msgspec.json.Decoder(type=dict) From 3d0b9ca3e4c3225dd572f16ed1f3613b3bca1690 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 7 Dec 2023 09:53:24 -0700 Subject: [PATCH 27/28] Uset type in encoder and add check and conversion for np.bool_ --- scos_actions/metadata/utils.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/scos_actions/metadata/utils.py b/scos_actions/metadata/utils.py index ef4fd5e9..6253049a 100644 --- a/scos_actions/metadata/utils.py +++ b/scos_actions/metadata/utils.py @@ -33,14 +33,19 @@ def construct_geojson_point( def _enc_hook(obj: Any) -> Any: - if isinstance(obj, np.float64): + #While isinstance is recommended, it was causing a + #Recurrsion error and I don't think we have to worry + #about subytpes here. + if type(obj) == np.float64: return float(obj) + elif type(obj) == np.bool_: + return bool(obj) else: return obj # A reusable encoder with custom hook to ensure serialization -msgspec_enc = msgspec.json.Encoder() +msgspec_enc = msgspec.json.Encoder(enc_hook=_enc_hook) # A reusable decoder which outputs a Python dictionary msgspec_dec_dict = msgspec.json.Decoder(type=dict) From 32d0f9d6c01e0613bbcc151ea709fbaa31b96379 Mon Sep 17 00:00:00 2001 From: Doug Boulware Date: Thu, 7 Dec 2023 11:15:11 -0700 Subject: [PATCH 28/28] increment version to 7.0.1 --- scos_actions/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scos_actions/__init__.py b/scos_actions/__init__.py index b378fc6c..fb16410a 100644 --- a/scos_actions/__init__.py +++ b/scos_actions/__init__.py @@ -1 +1 @@ -__version__ = "7.0.0" +__version__ = "7.0.1"