diff --git a/CHANGELOG.md b/CHANGELOG.md index af74f87c..2128a01d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,14 @@ list yields a list of all related PRs for each release. username appended at the end is created as a side-product now PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/248 +### Heater + +- Adds `HealthIF` to heaters. Heaters are own system object with queues now which allows to set them faulty. +- SW will attempt to shut down heaters which are on but marked faulty +- Some simplifications for `HeaterHandler`, use `std::vector` instead of `std::unordered_map` for primary container. Using the heater indexes 0 to 7 allows to use natural array indexing +- Some additional input sanity checks in `executeAction` + PR: https://egit.irs.uni-stuttgart.de/eive/eive-obsw/pulls/236 + ## Changed - Build unittest as default side product of hosted builds diff --git a/bsp_q7s/core/InitMission.cpp b/bsp_q7s/core/InitMission.cpp index 8b7a2723..6c69fd87 100644 --- a/bsp_q7s/core/InitMission.cpp +++ b/bsp_q7s/core/InitMission.cpp @@ -36,8 +36,16 @@ ObjectManagerIF* objectManager = nullptr; void initmission::initMission() { sif::info << "Building global objects.." << std::endl; - /* Instantiate global object manager and also create all objects */ - ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr); + try { + /* Instantiate global object manager and also create all objects */ + ObjectManager::instance()->setObjectFactoryFunction(ObjectFactory::produce, nullptr); + } catch (const std::invalid_argument& e) { + sif::error << "initmission::initMission: Object Construction failed with an " + "invalid argument: " + << e.what(); + std::exit(1); + } + sif::info << "Initializing all objects.." << std::endl; ObjectManager::instance()->initialize(); @@ -427,6 +435,10 @@ void initmission::createPusTasks(TaskFactory& factory, if (result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_200", objects::PUS_SERVICE_200_MODE_MGMT); } + result = pusMedPrio->addComponent(objects::PUS_SERVICE_201_HEALTH); + if (result != HasReturnvaluesIF::RETURN_OK) { + initmission::printAddObjectError("PUS_201", objects::PUS_SERVICE_201_HEALTH); + } result = pusMedPrio->addComponent(objects::PUS_SERVICE_20_PARAMETERS); if (result != HasReturnvaluesIF::RETURN_OK) { initmission::printAddObjectError("PUS_20", objects::PUS_SERVICE_20_PARAMETERS); diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 7cad3e68..490b5251 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -482,7 +482,8 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI #endif /* OBSW_ADD_ACS_HANDLERS == 1 */ } -void ObjectFactory::createHeaterComponents() { +void ObjectFactory::createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, + HealthTableIF* healthTable) { using namespace gpio; GpioCookie* heaterGpiosCookie = new GpioCookie; GpiodRegularByLineName* gpio = nullptr; @@ -523,8 +524,21 @@ void ObjectFactory::createHeaterComponents() { Levels::LOW); heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpio); - new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, - objects::PCDU_HANDLER, pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); + gpioIF->addGpios(heaterGpiosCookie); + + HeaterHelper helper({{ + {new HealthDevice(objects::HEATER_0_PLOC_PROC_BRD, MessageQueueIF::NO_QUEUE), + gpioIds::HEATER_0}, + {new HealthDevice(objects::HEATER_1_PCDU_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_1}, + {new HealthDevice(objects::HEATER_2_ACS_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_2}, + {new HealthDevice(objects::HEATER_3_OBC_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_3}, + {new HealthDevice(objects::HEATER_4_CAMERA, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_4}, + {new HealthDevice(objects::HEATER_5_STR, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_5}, + {new HealthDevice(objects::HEATER_6_DRO, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_6}, + {new HealthDevice(objects::HEATER_7_HPA, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_7}, + }}); + new HeaterHandler(objects::HEATER_HANDLER, gpioIF, helper, pwrSwitcher, + pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); } void ObjectFactory::createSolarArrayDeploymentComponents() { diff --git a/bsp_q7s/core/ObjectFactory.h b/bsp_q7s/core/ObjectFactory.h index e2349f9b..e6a68cf2 100644 --- a/bsp_q7s/core/ObjectFactory.h +++ b/bsp_q7s/core/ObjectFactory.h @@ -10,7 +10,9 @@ class UartComIF; class SpiComIF; class I2cComIF; class PowerSwitchIF; +class HealthTableIF; class AcsBoardAssembly; +class GpioIF; namespace ObjectFactory { @@ -27,7 +29,7 @@ void createTmpComponents(); void createRadSensorComponent(LinuxLibgpioIF* gpioComIF); void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF, PowerSwitchIF* pwrSwitcher); -void createHeaterComponents(); +void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable); void createImtqComponents(PowerSwitchIF* pwrSwitcher); void createBpxBatteryComponent(); void createStrComponents(PowerSwitchIF* pwrSwitcher); diff --git a/bsp_q7s/fmObjectFactory.cpp b/bsp_q7s/fmObjectFactory.cpp index 06c41e49..00e7bbd9 100644 --- a/bsp_q7s/fmObjectFactory.cpp +++ b/bsp_q7s/fmObjectFactory.cpp @@ -11,7 +11,8 @@ void ObjectFactory::produce(void* args) { ObjectFactory::setStatics(); - ObjectFactory::produceGenericObjects(); + HealthTableIF* healthTable = nullptr; + ObjectFactory::produceGenericObjects(&healthTable); LinuxLibgpioIF* gpioComIF = nullptr; UartComIF* uartComIF = nullptr; @@ -31,7 +32,7 @@ void ObjectFactory::produce(void* args) { #if OBSW_ADD_ACS_BOARD == 1 createAcsBoardComponents(gpioComIF, uartComIF, pwrSwitcher); #endif - createHeaterComponents(); + createHeaterComponents(gpioComIF, pwrSwitcher, healthTable); createSolarArrayDeploymentComponents(); createPlPcduComponents(gpioComIF, spiMainComIF, pwrSwitcher); #if OBSW_ADD_SYRLINKS == 1 diff --git a/common/config/commonClassIds.h b/common/config/commonClassIds.h index d95ff67d..dc440c4d 100644 --- a/common/config/commonClassIds.h +++ b/common/config/commonClassIds.h @@ -6,35 +6,35 @@ namespace CLASS_ID { enum commonClassIds: uint8_t { - COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT, - PCDU_HANDLER, //PCDU - HEATER_HANDLER, //HEATER - SYRLINKS_HANDLER, //SYRLINKS - IMTQ_HANDLER, //IMTQ - RW_HANDLER, //RWHA - STR_HANDLER, //STRH - DWLPWRON_CMD, //DWLPWRON - MPSOC_TM, //MPTM - PLOC_SUPERVISOR_HANDLER, //PLSV - PLOC_SUPV_HELPER, //PLSPVhLP - SUS_HANDLER, //SUSS - CCSDS_IP_CORE_BRIDGE, //IPCI - PTME, //PTME - PLOC_UPDATER, //PLUD - STR_HELPER, //STRHLP - GOM_SPACE_HANDLER, //GOMS - PLOC_MEMORY_DUMPER, //PLMEMDUMP - PDEC_HANDLER, //PDEC - CCSDS_HANDLER, //CCSDS - RATE_SETTER, //RS - ARCSEC_JSON_BASE, //JSONBASE - NVM_PARAM_BASE, //NVMB - FILE_SYSTEM_HELPER, //FSHLP - PLOC_MPSOC_HELPER, // PLMPHLP - SA_DEPL_HANDLER, //SADPL - MPSOC_RETURN_VALUES_IF, //MPSOCRTVIF - SUPV_RETURN_VALUES_IF, //SPVRTVIF - COMMON_CLASS_ID_END // [EXPORT] : [END] + COMMON_CLASS_ID_START = FW_CLASS_ID_COUNT, + PCDU_HANDLER, //PCDU + HEATER_HANDLER, //HEATER + SYRLINKS_HANDLER, //SYRLINKS + IMTQ_HANDLER, //IMTQ + RW_HANDLER, //RWHA + STR_HANDLER, //STRH + DWLPWRON_CMD, //DWLPWRON + MPSOC_TM, //MPTM + PLOC_SUPERVISOR_HANDLER, //PLSV + PLOC_SUPV_HELPER, //PLSPVhLP + SUS_HANDLER, //SUSS + CCSDS_IP_CORE_BRIDGE, //IPCI + PTME, //PTME + PLOC_UPDATER, //PLUD + STR_HELPER, //STRHLP + GOM_SPACE_HANDLER, //GOMS + PLOC_MEMORY_DUMPER, //PLMEMDUMP + PDEC_HANDLER, //PDEC + CCSDS_HANDLER, //CCSDS + RATE_SETTER, //RS + ARCSEC_JSON_BASE, //JSONBASE + NVM_PARAM_BASE, //NVMB + FILE_SYSTEM_HELPER, //FSHLP + PLOC_MPSOC_HELPER, // PLMPHLP + SA_DEPL_HANDLER, //SADPL + MPSOC_RETURN_VALUES_IF, //MPSOCRTVIF + SUPV_RETURN_VALUES_IF, //SPVRTVIF + COMMON_CLASS_ID_END // [EXPORT] : [END] }; } diff --git a/common/config/commonObjects.h b/common/config/commonObjects.h index 567d5988..bacd5b9b 100644 --- a/common/config/commonObjects.h +++ b/common/config/commonObjects.h @@ -22,13 +22,6 @@ enum commonObjects: uint32_t { CORE_CONTROLLER = 0x43000003, /* 0x44 ('D') for device handlers */ - P60DOCK_HANDLER = 0x44250000, - PDU1_HANDLER = 0x44250001, - PDU2_HANDLER = 0x44250002, - ACU_HANDLER = 0x44250003, - BPX_BATT_HANDLER = 0x44260000, - TMP1075_HANDLER_1 = 0x44420004, - TMP1075_HANDLER_2 = 0x44420005, MGM_0_LIS3_HANDLER = 0x44120006, MGM_1_RM3100_HANDLER = 0x44120107, MGM_2_LIS3_HANDLER = 0x44120208, @@ -37,12 +30,35 @@ enum commonObjects: uint32_t { GYRO_1_L3G_HANDLER = 0x44120111, GYRO_2_ADIS_HANDLER = 0x44120212, GYRO_3_L3G_HANDLER = 0x44120313, - PLPCDU_HANDLER = 0x44300000, + RW1 = 0x44120047, + RW2 = 0x44120148, + RW3 = 0x44120249, + RW4 = 0x44120350, + STAR_TRACKER = 0x44130001, + GPS_CONTROLLER = 0x44130045, IMTQ_HANDLER = 0x44140014, + TMP1075_HANDLER_1 = 0x44420004, + TMP1075_HANDLER_2 = 0x44420005, + PCDU_HANDLER = 0x442000A1, + P60DOCK_HANDLER = 0x44250000, + PDU1_HANDLER = 0x44250001, + PDU2_HANDLER = 0x44250002, + ACU_HANDLER = 0x44250003, + BPX_BATT_HANDLER = 0x44260000, + PLPCDU_HANDLER = 0x44300000, + RAD_SENSOR = 0x443200A5, + PLOC_UPDATER = 0x44330000, + PLOC_MEMORY_DUMPER = 0x44330001, + STR_HELPER = 0x44330002, + PLOC_MPSOC_HELPER = 0x44330003, + AXI_PTME_CONFIG = 0x44330004, + PTME_CONFIG = 0x44330005, PLOC_MPSOC_HANDLER = 0x44330015, PLOC_SUPERVISOR_HANDLER = 0x44330016, PLOC_SUPERVISOR_HELPER = 0x44330017, + SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2, + HEATER_HANDLER = 0x444100A4, /** * Not yet specified which pt1000 will measure which device/location in the satellite. @@ -89,20 +105,17 @@ enum commonObjects: uint32_t { SUS_5_N_LOC_XFYMZB_PT_ZB = 0x44120037, SUS_11_R_LOC_XBYMZB_PT_ZB = 0x44120043, - GPS_CONTROLLER = 0x44130045, + SYRLINKS_HK_HANDLER = 0x445300A3, - RW1 = 0x44120047, - RW2 = 0x44120148, - RW3 = 0x44120249, - RW4 = 0x44120350, - - STAR_TRACKER = 0x44130001, - - PLOC_MEMORY_DUMPER = 0x44330001, - STR_HELPER = 0x44330002, - PLOC_MPSOC_HELPER = 0x44330003, - AXI_PTME_CONFIG = 44330004, - PTME_CONFIG = 44330005, + // 0x60 for other stuff + HEATER_0_PLOC_PROC_BRD = 0x60000000, + HEATER_1_PCDU_BRD = 0x60000001, + HEATER_2_ACS_BRD = 0x60000002, + HEATER_3_OBC_BRD = 0x60000003, + HEATER_4_CAMERA = 0x60000004, + HEATER_5_STR = 0x60000005, + HEATER_6_DRO = 0x60000006, + HEATER_7_HPA = 0x60000007, // 0x73 ('s') for assemblies and system/subsystem components ACS_BOARD_ASS = 0x73000001, diff --git a/common/config/devices/heaterSwitcherList.h b/common/config/devices/heaterSwitcherList.h index 014e795c..256e5c88 100644 --- a/common/config/devices/heaterSwitcherList.h +++ b/common/config/devices/heaterSwitcherList.h @@ -3,16 +3,16 @@ #include -namespace heaterSwitches { - enum switcherList: uint8_t { - HEATER_0, - HEATER_1, - HEATER_2, - HEATER_3, - HEATER_4, - HEATER_5, - HEATER_6, - HEATER_7, +namespace heater { + enum Switchers: uint8_t { + HEATER_0_OBC_BRD, + HEATER_1_PLOC_PROC_BRD, + HEATER_2_ACS_BRD, + HEATER_3_PCDU_PDU, + HEATER_4_CAMERA, + HEATER_5_STR, + HEATER_6_DRO, + HEATER_7_HPA, NUMBER_OF_SWITCHES }; } diff --git a/generators/bsp_q7s_events.csv b/generators/bsp_q7s_events.csv index 4570c0e0..34326f6b 100644 --- a/generators/bsp_q7s_events.csv +++ b/generators/bsp_q7s_events.csv @@ -83,9 +83,12 @@ 11303;0x2c27;FDIR_REACTION_IGNORED;MEDIUM;;mission/devices/devicedefinitions/powerDefinitions.h 11400;0x2c88;GPIO_PULL_HIGH_FAILED;LOW;;mission/devices/HeaterHandler.h 11401;0x2c89;GPIO_PULL_LOW_FAILED;LOW;;mission/devices/HeaterHandler.h -11402;0x2c8a;SWITCH_ALREADY_ON;LOW;;mission/devices/HeaterHandler.h -11403;0x2c8b;SWITCH_ALREADY_OFF;LOW;;mission/devices/HeaterHandler.h -11404;0x2c8c;MAIN_SWITCH_TIMEOUT;LOW;;mission/devices/HeaterHandler.h +11402;0x2c8a;HEATER_WENT_ON;INFO;;mission/devices/HeaterHandler.h +11403;0x2c8b;HEATER_WENT_OFF;INFO;;mission/devices/HeaterHandler.h +11404;0x2c8c;SWITCH_ALREADY_ON;LOW;;mission/devices/HeaterHandler.h +11405;0x2c8d;SWITCH_ALREADY_OFF;LOW;;mission/devices/HeaterHandler.h +11406;0x2c8e;MAIN_SWITCH_TIMEOUT;MEDIUM;;mission/devices/HeaterHandler.h +11407;0x2c8f;FAULTY_HEATER_WAS_ON;LOW;;mission/devices/HeaterHandler.h 11500;0x2cec;MAIN_SWITCH_ON_TIMEOUT;LOW;;mission/devices/SolarArrayDeploymentHandler.h 11501;0x2ced;MAIN_SWITCH_OFF_TIMEOUT;LOW;;mission/devices/SolarArrayDeploymentHandler.h 11502;0x2cee;DEPLOYMENT_FAILED;HIGH;;mission/devices/SolarArrayDeploymentHandler.h diff --git a/generators/bsp_q7s_objects.csv b/generators/bsp_q7s_objects.csv index 22fed880..f9380ece 100644 --- a/generators/bsp_q7s_objects.csv +++ b/generators/bsp_q7s_objects.csv @@ -37,9 +37,12 @@ 0x44260000;BPX_BATT_HANDLER 0x44300000;PLPCDU_HANDLER 0x443200A5;RAD_SENSOR +0x44330000;PLOC_UPDATER 0x44330001;PLOC_MEMORY_DUMPER 0x44330002;STR_HELPER 0x44330003;PLOC_MPSOC_HELPER +0x44330004;AXI_PTME_CONFIG +0x44330005;PTME_CONFIG 0x44330015;PLOC_MPSOC_HANDLER 0x44330016;PLOC_SUPERVISOR_HANDLER 0x44330017;PLOC_SUPERVISOR_HELPER @@ -109,6 +112,14 @@ 0x5400CAFE;DUMMY_INTERFACE 0x54123456;LIBGPIOD_TEST 0x54694269;TEST_TASK +0x60000000;HEATER_0_PLOC_PROC_BRD +0x60000001;HEATER_1_PCDU_BRD +0x60000002;HEATER_2_ACS_BRD +0x60000003;HEATER_3_OBC_BRD +0x60000004;HEATER_4_CAMERA +0x60000005;HEATER_5_STR +0x60000006;HEATER_6_DRO +0x60000007;HEATER_7_HPA 0x73000001;ACS_BOARD_ASS 0x73000002;SUS_BOARD_ASS 0x73000003;TCS_BOARD_ASS diff --git a/generators/bsp_q7s_returnvalues.csv b/generators/bsp_q7s_returnvalues.csv index a1b8e422..faf6dd65 100644 --- a/generators/bsp_q7s_returnvalues.csv +++ b/generators/bsp_q7s_returnvalues.csv @@ -389,6 +389,7 @@ 0x2e03; ASC_BufferTooSmall;;0x3;fsfw/src/fsfw/globalfunctions/AsciiConverter.h;ASCII_CONVERTER 0x1701; HHI_ObjectNotHealthy;;1;fsfw/src/fsfw/health/HasHealthIF.h;HAS_HEALTH_IF 0x1702; HHI_InvalidHealthState;;2;fsfw/src/fsfw/health/HasHealthIF.h;HAS_HEALTH_IF +0x1703; HHI_IsExternallyControlled;;3;fsfw/src/fsfw/health/HasHealthIF.h;HAS_HEALTH_IF 0x3101; CF_ObjectHasNoFunctions;;1;fsfw/src/fsfw/action/CommandsActionsIF.h;COMMANDS_ACTIONS_IF 0x3102; CF_AlreadyCommanding;;2;fsfw/src/fsfw/action/CommandsActionsIF.h;COMMANDS_ACTIONS_IF 0x3201; HF_IsBusy;;1;fsfw/src/fsfw/action/HasActionsIF.h;HAS_ACTIONS_IF diff --git a/generators/events/translateEvents.cpp b/generators/events/translateEvents.cpp index 2cb071ea..08283d78 100644 --- a/generators/events/translateEvents.cpp +++ b/generators/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 200 translations. + * @brief Auto-generated event translation file. Contains 203 translations. * @details - * Generated on: 2022-05-11 17:58:22 + * Generated on: 2022-05-12 20:45:27 */ #include "translateEvents.h" @@ -90,9 +90,12 @@ const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; const char *FDIR_REACTION_IGNORED_STRING = "FDIR_REACTION_IGNORED"; const char *GPIO_PULL_HIGH_FAILED_STRING = "GPIO_PULL_HIGH_FAILED"; const char *GPIO_PULL_LOW_FAILED_STRING = "GPIO_PULL_LOW_FAILED"; +const char *HEATER_WENT_ON_STRING = "HEATER_WENT_ON"; +const char *HEATER_WENT_OFF_STRING = "HEATER_WENT_OFF"; const char *SWITCH_ALREADY_ON_STRING = "SWITCH_ALREADY_ON"; const char *SWITCH_ALREADY_OFF_STRING = "SWITCH_ALREADY_OFF"; const char *MAIN_SWITCH_TIMEOUT_STRING = "MAIN_SWITCH_TIMEOUT"; +const char *FAULTY_HEATER_WAS_ON_STRING = "FAULTY_HEATER_WAS_ON"; const char *MAIN_SWITCH_ON_TIMEOUT_STRING = "MAIN_SWITCH_ON_TIMEOUT"; const char *MAIN_SWITCH_OFF_TIMEOUT_STRING = "MAIN_SWITCH_OFF_TIMEOUT"; const char *DEPLOYMENT_FAILED_STRING = "DEPLOYMENT_FAILED"; @@ -375,11 +378,17 @@ const char *translateEvents(Event event) { case (11401): return GPIO_PULL_LOW_FAILED_STRING; case (11402): - return SWITCH_ALREADY_ON_STRING; + return HEATER_WENT_ON_STRING; case (11403): - return SWITCH_ALREADY_OFF_STRING; + return HEATER_WENT_OFF_STRING; case (11404): + return SWITCH_ALREADY_ON_STRING; + case (11405): + return SWITCH_ALREADY_OFF_STRING; + case (11406): return MAIN_SWITCH_TIMEOUT_STRING; + case (11407): + return FAULTY_HEATER_WAS_ON_STRING; case (11500): return MAIN_SWITCH_ON_TIMEOUT_STRING; case (11501): diff --git a/generators/objects/translateObjects.cpp b/generators/objects/translateObjects.cpp index 9ae96b62..fcc2c875 100644 --- a/generators/objects/translateObjects.cpp +++ b/generators/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 118 translations. - * Generated on: 2022-05-11 17:58:22 + * Contains 129 translations. + * Generated on: 2022-05-12 20:45:27 */ #include "translateObjects.h" @@ -45,9 +45,12 @@ const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *BPX_BATT_HANDLER_STRING = "BPX_BATT_HANDLER"; const char *PLPCDU_HANDLER_STRING = "PLPCDU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *PLOC_UPDATER_STRING = "PLOC_UPDATER"; const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER"; const char *STR_HELPER_STRING = "STR_HELPER"; const char *PLOC_MPSOC_HELPER_STRING = "PLOC_MPSOC_HELPER"; +const char *AXI_PTME_CONFIG_STRING = "AXI_PTME_CONFIG"; +const char *PTME_CONFIG_STRING = "PTME_CONFIG"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER"; @@ -117,6 +120,14 @@ const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *HEATER_0_PLOC_PROC_BRD_STRING = "HEATER_0_PLOC_PROC_BRD"; +const char *HEATER_1_PCDU_BRD_STRING = "HEATER_1_PCDU_BRD"; +const char *HEATER_2_ACS_BRD_STRING = "HEATER_2_ACS_BRD"; +const char *HEATER_3_OBC_BRD_STRING = "HEATER_3_OBC_BRD"; +const char *HEATER_4_CAMERA_STRING = "HEATER_4_CAMERA"; +const char *HEATER_5_STR_STRING = "HEATER_5_STR"; +const char *HEATER_6_DRO_STRING = "HEATER_6_DRO"; +const char *HEATER_7_HPA_STRING = "HEATER_7_HPA"; const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS"; const char *SUS_BOARD_ASS_STRING = "SUS_BOARD_ASS"; const char *TCS_BOARD_ASS_STRING = "TCS_BOARD_ASS"; @@ -205,12 +216,18 @@ const char *translateObject(object_id_t object) { return PLPCDU_HANDLER_STRING; case 0x443200A5: return RAD_SENSOR_STRING; + case 0x44330000: + return PLOC_UPDATER_STRING; case 0x44330001: return PLOC_MEMORY_DUMPER_STRING; case 0x44330002: return STR_HELPER_STRING; case 0x44330003: return PLOC_MPSOC_HELPER_STRING; + case 0x44330004: + return AXI_PTME_CONFIG_STRING; + case 0x44330005: + return PTME_CONFIG_STRING; case 0x44330015: return PLOC_MPSOC_HANDLER_STRING; case 0x44330016: @@ -349,6 +366,22 @@ const char *translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x60000000: + return HEATER_0_PLOC_PROC_BRD_STRING; + case 0x60000001: + return HEATER_1_PCDU_BRD_STRING; + case 0x60000002: + return HEATER_2_ACS_BRD_STRING; + case 0x60000003: + return HEATER_3_OBC_BRD_STRING; + case 0x60000004: + return HEATER_4_CAMERA_STRING; + case 0x60000005: + return HEATER_5_STR_STRING; + case 0x60000006: + return HEATER_6_DRO_STRING; + case 0x60000007: + return HEATER_7_HPA_STRING; case 0x73000001: return ACS_BOARD_ASS_STRING; case 0x73000002: diff --git a/linux/fsfwconfig/events/translateEvents.cpp b/linux/fsfwconfig/events/translateEvents.cpp index 2cb071ea..08283d78 100644 --- a/linux/fsfwconfig/events/translateEvents.cpp +++ b/linux/fsfwconfig/events/translateEvents.cpp @@ -1,7 +1,7 @@ /** - * @brief Auto-generated event translation file. Contains 200 translations. + * @brief Auto-generated event translation file. Contains 203 translations. * @details - * Generated on: 2022-05-11 17:58:22 + * Generated on: 2022-05-12 20:45:27 */ #include "translateEvents.h" @@ -90,9 +90,12 @@ const char *SWITCHING_Q7S_DENIED_STRING = "SWITCHING_Q7S_DENIED"; const char *FDIR_REACTION_IGNORED_STRING = "FDIR_REACTION_IGNORED"; const char *GPIO_PULL_HIGH_FAILED_STRING = "GPIO_PULL_HIGH_FAILED"; const char *GPIO_PULL_LOW_FAILED_STRING = "GPIO_PULL_LOW_FAILED"; +const char *HEATER_WENT_ON_STRING = "HEATER_WENT_ON"; +const char *HEATER_WENT_OFF_STRING = "HEATER_WENT_OFF"; const char *SWITCH_ALREADY_ON_STRING = "SWITCH_ALREADY_ON"; const char *SWITCH_ALREADY_OFF_STRING = "SWITCH_ALREADY_OFF"; const char *MAIN_SWITCH_TIMEOUT_STRING = "MAIN_SWITCH_TIMEOUT"; +const char *FAULTY_HEATER_WAS_ON_STRING = "FAULTY_HEATER_WAS_ON"; const char *MAIN_SWITCH_ON_TIMEOUT_STRING = "MAIN_SWITCH_ON_TIMEOUT"; const char *MAIN_SWITCH_OFF_TIMEOUT_STRING = "MAIN_SWITCH_OFF_TIMEOUT"; const char *DEPLOYMENT_FAILED_STRING = "DEPLOYMENT_FAILED"; @@ -375,11 +378,17 @@ const char *translateEvents(Event event) { case (11401): return GPIO_PULL_LOW_FAILED_STRING; case (11402): - return SWITCH_ALREADY_ON_STRING; + return HEATER_WENT_ON_STRING; case (11403): - return SWITCH_ALREADY_OFF_STRING; + return HEATER_WENT_OFF_STRING; case (11404): + return SWITCH_ALREADY_ON_STRING; + case (11405): + return SWITCH_ALREADY_OFF_STRING; + case (11406): return MAIN_SWITCH_TIMEOUT_STRING; + case (11407): + return FAULTY_HEATER_WAS_ON_STRING; case (11500): return MAIN_SWITCH_ON_TIMEOUT_STRING; case (11501): diff --git a/linux/fsfwconfig/objects/systemObjectList.h b/linux/fsfwconfig/objects/systemObjectList.h index 05d45620..28c87d3c 100644 --- a/linux/fsfwconfig/objects/systemObjectList.h +++ b/linux/fsfwconfig/objects/systemObjectList.h @@ -52,13 +52,6 @@ enum sourceObjects : uint32_t { SPI_RW_COM_IF = 0x49020005, SPI_RTD_COM_IF = 0x49020006, - /* Custom device handler */ - PCDU_HANDLER = 0x442000A1, - SOLAR_ARRAY_DEPL_HANDLER = 0x444100A2, - SYRLINKS_HK_HANDLER = 0x445300A3, - HEATER_HANDLER = 0x444100A4, - RAD_SENSOR = 0x443200A5, - /* 0x54 ('T') for test handlers */ TEST_TASK = 0x54694269, LIBGPIOD_TEST = 0x54123456, diff --git a/linux/fsfwconfig/objects/translateObjects.cpp b/linux/fsfwconfig/objects/translateObjects.cpp index 9ae96b62..fcc2c875 100644 --- a/linux/fsfwconfig/objects/translateObjects.cpp +++ b/linux/fsfwconfig/objects/translateObjects.cpp @@ -1,8 +1,8 @@ /** * @brief Auto-generated object translation file. * @details - * Contains 118 translations. - * Generated on: 2022-05-11 17:58:22 + * Contains 129 translations. + * Generated on: 2022-05-12 20:45:27 */ #include "translateObjects.h" @@ -45,9 +45,12 @@ const char *ACU_HANDLER_STRING = "ACU_HANDLER"; const char *BPX_BATT_HANDLER_STRING = "BPX_BATT_HANDLER"; const char *PLPCDU_HANDLER_STRING = "PLPCDU_HANDLER"; const char *RAD_SENSOR_STRING = "RAD_SENSOR"; +const char *PLOC_UPDATER_STRING = "PLOC_UPDATER"; const char *PLOC_MEMORY_DUMPER_STRING = "PLOC_MEMORY_DUMPER"; const char *STR_HELPER_STRING = "STR_HELPER"; const char *PLOC_MPSOC_HELPER_STRING = "PLOC_MPSOC_HELPER"; +const char *AXI_PTME_CONFIG_STRING = "AXI_PTME_CONFIG"; +const char *PTME_CONFIG_STRING = "PTME_CONFIG"; const char *PLOC_MPSOC_HANDLER_STRING = "PLOC_MPSOC_HANDLER"; const char *PLOC_SUPERVISOR_HANDLER_STRING = "PLOC_SUPERVISOR_HANDLER"; const char *PLOC_SUPERVISOR_HELPER_STRING = "PLOC_SUPERVISOR_HELPER"; @@ -117,6 +120,14 @@ const char *DUMMY_HANDLER_STRING = "DUMMY_HANDLER"; const char *DUMMY_INTERFACE_STRING = "DUMMY_INTERFACE"; const char *LIBGPIOD_TEST_STRING = "LIBGPIOD_TEST"; const char *TEST_TASK_STRING = "TEST_TASK"; +const char *HEATER_0_PLOC_PROC_BRD_STRING = "HEATER_0_PLOC_PROC_BRD"; +const char *HEATER_1_PCDU_BRD_STRING = "HEATER_1_PCDU_BRD"; +const char *HEATER_2_ACS_BRD_STRING = "HEATER_2_ACS_BRD"; +const char *HEATER_3_OBC_BRD_STRING = "HEATER_3_OBC_BRD"; +const char *HEATER_4_CAMERA_STRING = "HEATER_4_CAMERA"; +const char *HEATER_5_STR_STRING = "HEATER_5_STR"; +const char *HEATER_6_DRO_STRING = "HEATER_6_DRO"; +const char *HEATER_7_HPA_STRING = "HEATER_7_HPA"; const char *ACS_BOARD_ASS_STRING = "ACS_BOARD_ASS"; const char *SUS_BOARD_ASS_STRING = "SUS_BOARD_ASS"; const char *TCS_BOARD_ASS_STRING = "TCS_BOARD_ASS"; @@ -205,12 +216,18 @@ const char *translateObject(object_id_t object) { return PLPCDU_HANDLER_STRING; case 0x443200A5: return RAD_SENSOR_STRING; + case 0x44330000: + return PLOC_UPDATER_STRING; case 0x44330001: return PLOC_MEMORY_DUMPER_STRING; case 0x44330002: return STR_HELPER_STRING; case 0x44330003: return PLOC_MPSOC_HELPER_STRING; + case 0x44330004: + return AXI_PTME_CONFIG_STRING; + case 0x44330005: + return PTME_CONFIG_STRING; case 0x44330015: return PLOC_MPSOC_HANDLER_STRING; case 0x44330016: @@ -349,6 +366,22 @@ const char *translateObject(object_id_t object) { return LIBGPIOD_TEST_STRING; case 0x54694269: return TEST_TASK_STRING; + case 0x60000000: + return HEATER_0_PLOC_PROC_BRD_STRING; + case 0x60000001: + return HEATER_1_PCDU_BRD_STRING; + case 0x60000002: + return HEATER_2_ACS_BRD_STRING; + case 0x60000003: + return HEATER_3_OBC_BRD_STRING; + case 0x60000004: + return HEATER_4_CAMERA_STRING; + case 0x60000005: + return HEATER_5_STR_STRING; + case 0x60000006: + return HEATER_6_DRO_STRING; + case 0x60000007: + return HEATER_7_HPA_STRING; case 0x73000001: return ACS_BOARD_ASS_STRING; case 0x73000002: diff --git a/mission/core/GenericFactory.cpp b/mission/core/GenericFactory.cpp index d2db67fd..fdf21541 100644 --- a/mission/core/GenericFactory.cpp +++ b/mission/core/GenericFactory.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -44,10 +45,13 @@ #define OBSW_TM_TO_PTME 0 #endif -void ObjectFactory::produceGenericObjects() { +void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_) { // Framework objects new EventManager(objects::EVENT_MANAGER); - new HealthTable(objects::HEALTH_TABLE); + auto healthTable = new HealthTable(objects::HEALTH_TABLE); + if (healthTable != nullptr) { + *healthTable_ = healthTable; + } new InternalErrorReporter(objects::INTERNAL_ERROR_REPORTER); new TimeStamper(objects::TIME_STAMPER); @@ -96,8 +100,9 @@ void ObjectFactory::produceGenericObjects() { new Service20ParameterManagement(objects::PUS_SERVICE_20_PARAMETERS, apid::EIVE_OBSW, pus::PUS_SERVICE_20); new CService200ModeCommanding(objects::PUS_SERVICE_200_MODE_MGMT, apid::EIVE_OBSW, - pus::PUS_SERVICE_200, 8, config::LONGEST_MODE_TIMEOUT_SECONDS); - + pus::PUS_SERVICE_200, 8); + new CService201HealthCommanding(objects::PUS_SERVICE_201_HEALTH, apid::EIVE_OBSW, + pus::PUS_SERVICE_201); #if OBSW_ADD_TCPIP_BRIDGE == 1 #if OBSW_USE_TMTC_TCP_BRIDGE == 0 auto tmtcBridge = new UdpTmTcBridge(objects::TMTC_BRIDGE, objects::CCSDS_PACKET_DISTRIBUTOR); diff --git a/mission/core/GenericFactory.h b/mission/core/GenericFactory.h index 1a3b1300..4bc6695d 100644 --- a/mission/core/GenericFactory.h +++ b/mission/core/GenericFactory.h @@ -1,9 +1,11 @@ #ifndef MISSION_CORE_GENERICFACTORY_H_ #define MISSION_CORE_GENERICFACTORY_H_ +class HealthTableIF; + namespace ObjectFactory { -void produceGenericObjects(); +void produceGenericObjects(HealthTableIF** healthTable = nullptr); } diff --git a/mission/devices/HeaterHandler.cpp b/mission/devices/HeaterHandler.cpp index 5e78bc0e..6953dc54 100644 --- a/mission/devices/HeaterHandler.cpp +++ b/mission/devices/HeaterHandler.cpp @@ -1,21 +1,38 @@ #include "HeaterHandler.h" +#include #include #include #include +#include + #include "devices/gpioIds.h" #include "devices/powerSwitcherList.h" -HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_, - CookieIF* gpioCookie_, object_id_t mainLineSwitcherObjectId_, - uint8_t mainLineSwitch_) +HeaterHandler::HeaterHandler(object_id_t setObjectId_, GpioIF* gpioInterface_, HeaterHelper helper, + PowerSwitchIF* mainLineSwitcher_, power::Switch_t mainLineSwitch_) : SystemObject(setObjectId_), - gpioDriverId(gpioDriverId_), - gpioCookie(gpioCookie_), - mainLineSwitcherObjectId(mainLineSwitcherObjectId_), + helper(helper), + gpioInterface(gpioInterface_), + mainLineSwitcher(mainLineSwitcher_), mainLineSwitch(mainLineSwitch_), actionHelper(this, nullptr) { + for (const auto& heater : helper.heaters) { + if (heater.first == nullptr) { + throw std::invalid_argument("HeaterHandler::HeaterHandler: Invalid Heater Object"); + } + } + if (gpioInterface_ == nullptr) { + throw std::invalid_argument("HeaterHandler::HeaterHandler: Invalid Gpio IF"); + } + if (mainLineSwitcher == nullptr) { + throw std::invalid_argument("HeaterHandler::HeaterHandler: Invalid PowerSwitchIF"); + } + heaterMutex = MutexFactory::instance()->createMutex(); + if (heaterMutex == nullptr) { + throw std::runtime_error("HeaterHandler::HeaterHandler: Creating Mutex failed"); + } auto mqArgs = MqArgs(setObjectId_, static_cast(this)); commandQueue = QueueFactory::instance()->createMessageQueue( cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); @@ -24,10 +41,16 @@ HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_ HeaterHandler::~HeaterHandler() {} ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) { - if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) { + try { readCommandQueue(); - handleActiveCommands(); - return RETURN_OK; + for (const auto& heater : helper.heaters) { + heater.first->performOperation(0); + } + handleSwitchHandling(); + } catch (const std::out_of_range& e) { + sif::warning << "HeaterHandler::performOperation: " + "Out of range error | " + << e.what() << std::endl; } return RETURN_OK; } @@ -43,33 +66,12 @@ ReturnValue_t HeaterHandler::initialize() { return ObjectManagerIF::CHILD_INIT_FAILED; } - gpioInterface = ObjectManager::instance()->get(gpioDriverId); - if (gpioInterface == nullptr) { - sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - result = gpioInterface->addGpios(dynamic_cast(gpioCookie)); - if (result != RETURN_OK) { - sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - - IPCStore = ObjectManager::instance()->get(objects::IPC_STORE); - if (IPCStore == nullptr) { + ipcStore = ObjectManager::instance()->get(objects::IPC_STORE); + if (ipcStore == nullptr) { sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl; return ObjectManagerIF::CHILD_INIT_FAILED; } - if (mainLineSwitcherObjectId != objects::NO_OBJECT) { - mainLineSwitcher = ObjectManager::instance()->get(mainLineSwitcherObjectId); - if (mainLineSwitcher == nullptr) { - sif::error << "HeaterHandler::initialize: Failed to get main line switcher. Make sure " - << "main line switcher object is initialized." << std::endl; - return ObjectManagerIF::CHILD_INIT_FAILED; - } - } - result = actionHelper.initialize(commandQueue); if (result != RETURN_OK) { return ObjectManagerIF::CHILD_INIT_FAILED; @@ -79,81 +81,97 @@ ReturnValue_t HeaterHandler::initialize() { } ReturnValue_t HeaterHandler::initializeHeaterMap() { - HeaterCommandInfo_t heaterCommandInfo; - for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { - std::pair status = heaterMap.emplace(switchNr, heaterCommandInfo); - if (status.second == false) { - sif::error << "HeaterHandler::initializeHeaterMap: Failed to initialize heater map" - << std::endl; - return RETURN_FAILED; - } + for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) { + heaterVec.push_back(HeaterWrapper(helper.heaters[switchNr], SwitchState::OFF)); } return RETURN_OK; } -void HeaterHandler::setInitialSwitchStates() { - for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { - switchStates[switchNr] = OFF; - } -} - void HeaterHandler::readCommandQueue() { + ReturnValue_t result = RETURN_OK; CommandMessage command; - ReturnValue_t result = commandQueue->receiveMessage(&command); - if (result != RETURN_OK) { - return; - } - - result = actionHelper.handleActionMessage(&command); - if (result == RETURN_OK) { - return; - } + do { + result = commandQueue->receiveMessage(&command); + if (result == MessageQueueIF::EMPTY) { + break; + } else if (result != RETURN_OK) { + sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl; + } + result = actionHelper.handleActionMessage(&command); + if (result == RETURN_OK) { + continue; + } + } while (result == RETURN_OK); } ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, const uint8_t* data, size_t size) { - ReturnValue_t result; - if (actionId != SWITCH_HEATER) { - result = COMMAND_NOT_SUPPORTED; - } else { - switchNr_t switchNr = *data; - HeaterMapIter heaterMapIter = heaterMap.find(switchNr); - if (heaterMapIter != heaterMap.end()) { - if (heaterMapIter->second.active) { - return COMMAND_ALREADY_WAITING; - } - heaterMapIter->second.action = *(data + 1); - heaterMapIter->second.active = true; - heaterMapIter->second.replyQueue = commandedBy; - } else { - sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl; - return INVALID_SWITCH_NR; - } - result = RETURN_OK; + if (data == nullptr or size < 3) { + return HasActionsIF::INVALID_PARAMETERS; } - return result; + if (actionId != SWITCH_HEATER) { + return COMMAND_NOT_SUPPORTED; + } + auto switchNr = data[0]; + if (switchNr > 7) { + return HasActionsIF::INVALID_PARAMETERS; + } + auto& heater = heaterVec.at(switchNr); + + auto actionRaw = data[1]; + if (actionRaw != 0 and actionRaw != 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + auto action = static_cast(data[1]); + // Always accepts OFF commands + if (action == SwitchAction::SET_SWITCH_ON) { + HasHealthIF::HealthState health = heater.healthDevice->getHealth(); + if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY or + health == HasHealthIF::NEEDS_RECOVERY) { + return HasHealthIF::OBJECT_NOT_HEALTHY; + } + CmdSourceParam cmdSource = CmdSourceParam::EXTERNAL; + uint8_t cmdSourceRaw = data[2]; + if (cmdSourceRaw > 1) { + return HasActionsIF::INVALID_PARAMETERS; + } + cmdSource = static_cast(data[2]); + if (health == HasHealthIF::EXTERNAL_CONTROL and cmdSource == CmdSourceParam::INTERNAL) { + return HasHealthIF::IS_EXTERNALLY_CONTROLLED; + } + } + + if (heater.cmdActive) { + return COMMAND_ALREADY_WAITING; + } + heater.action = action; + heater.cmdActive = true; + heater.replyQueue = commandedBy; + return RETURN_OK; } ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) { ReturnValue_t result; store_address_t storeAddress; - uint8_t commandData[2]; + uint8_t commandData[3] = {}; switch (onOff) { case PowerSwitchIF::SWITCH_ON: commandData[0] = switchNr; commandData[1] = SET_SWITCH_ON; + commandData[2] = CmdSourceParam::INTERNAL; break; case PowerSwitchIF::SWITCH_OFF: commandData[0] = switchNr; commandData[1] = SET_SWITCH_OFF; + commandData[2] = CmdSourceParam::INTERNAL; break; default: sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request" << std::endl; break; } - result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData)); + result = ipcStore->addData(&storeAddress, commandData, sizeof(commandData)); if (result == RETURN_OK) { CommandMessage message; ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress); @@ -167,16 +185,27 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o return result; } -void HeaterHandler::handleActiveCommands() { - HeaterMapIter heaterMapIter = heaterMap.begin(); - for (; heaterMapIter != heaterMap.end(); heaterMapIter++) { - if (heaterMapIter->second.active) { - switch (heaterMapIter->second.action) { +void HeaterHandler::handleSwitchHandling() { + for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) { + auto health = heaterVec[idx].healthDevice->getHealth(); + if (heaterVec[idx].switchState == SwitchState::ON) { + // If a heater is still on but the device was marked faulty by the operator, the SW + // will shut down the heater + if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) { + heaterVec[idx].cmdActive = true; + heaterVec[idx].action = SET_SWITCH_OFF; + triggerEvent(FAULTY_HEATER_WAS_ON, idx, 0); + handleSwitchOffCommand(static_cast(idx)); + continue; + } + } + if (heaterVec[idx].cmdActive) { + switch (heaterVec[idx].action) { case SET_SWITCH_ON: - handleSwitchOnCommand(heaterMapIter); + handleSwitchOnCommand(static_cast(idx)); break; case SET_SWITCH_OFF: - handleSwitchOffCommand(heaterMapIter); + handleSwitchOffCommand(static_cast(idx)); break; default: sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded" @@ -187,162 +216,139 @@ void HeaterHandler::handleActiveCommands() { } } -void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) { +void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { ReturnValue_t result = RETURN_OK; - switchNr_t switchNr; - + auto& heater = heaterVec.at(heaterIdx); /* Check if command waits for main switch being set on and whether the timeout has expired */ - if (heaterMapIter->second.waitMainSwitchOn && - heaterMapIter->second.mainSwitchCountdown.hasTimedOut()) { + if (heater.waitMainSwitchOn && heater.mainSwitchCountdown.hasTimedOut()) { // TODO - This requires the initiation of an FDIR procedure triggerEvent(MAIN_SWITCH_TIMEOUT); sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout" << std::endl; - heaterMapIter->second.active = false; - heaterMapIter->second.waitMainSwitchOn = false; - if (heaterMapIter->second.replyQueue != commandQueue->getId()) { - actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - MAIN_SWITCH_SET_TIMEOUT); + heater.cmdActive = false; + heater.waitMainSwitchOn = false; + if (heater.replyQueue != commandQueue->getId()) { + actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT); } return; } - switchNr = heaterMapIter->first; - /* Check state of main line switch */ + // Check state of main line switch ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch); if (mainSwitchState == PowerSwitchIF::SWITCH_ON) { - if (!checkSwitchState(switchNr)) { - gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); + if (checkSwitchState(heaterIdx) == SwitchState::OFF) { + gpioId_t gpioId = heater.gpioId; result = gpioInterface->pullHigh(gpioId); if (result != RETURN_OK) { sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id " << gpioId << " high" << std::endl; triggerEvent(GPIO_PULL_HIGH_FAILED, result); } else { - switchStates[switchNr] = ON; + triggerEvent(HEATER_WENT_ON, heaterIdx, 0); + heater.switchState = ON; } } else { - triggerEvent(SWITCH_ALREADY_ON, switchNr); + triggerEvent(SWITCH_ALREADY_ON, heaterIdx); } - /* There is no need to send action finish replies if the sender was the - * HeaterHandler itself. */ - if (heaterMapIter->second.replyQueue != commandQueue->getId()) { + // There is no need to send action finish replies if the sender was the + // HeaterHandler itself + if (heater.replyQueue != commandQueue->getId()) { if (result == RETURN_OK) { - actionHelper.finish(true, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - result); + actionHelper.finish(true, heater.replyQueue, heater.action, result); } else { - actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - result); + actionHelper.finish(false, heater.replyQueue, heater.action, result); } } - heaterMapIter->second.active = false; - heaterMapIter->second.waitMainSwitchOn = false; - } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && - heaterMapIter->second.waitMainSwitchOn) { - /* Just waiting for the main switch being set on */ + heater.cmdActive = false; + heater.waitMainSwitchOn = false; + } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && heater.waitMainSwitchOn) { + // Just waiting for the main switch being set on return; } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) { mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON); - heaterMapIter->second.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs()); - heaterMapIter->second.waitMainSwitchOn = true; + heater.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs()); + heater.waitMainSwitchOn = true; } else { - sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of" + sif::debug << "HeaterHandler::handleSwitchHandling: Failed to get state of" << " main line switch" << std::endl; - if (heaterMapIter->second.replyQueue != commandQueue->getId()) { - actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - mainSwitchState); + if (heater.replyQueue != commandQueue->getId()) { + actionHelper.finish(false, heater.replyQueue, heater.action, mainSwitchState); } - heaterMapIter->second.active = false; + heater.cmdActive = false; } } -void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) { +void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) { ReturnValue_t result = RETURN_OK; - switchNr_t switchNr = heaterMapIter->first; - /* Check whether switch is already off */ - if (checkSwitchState(switchNr)) { - gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); + auto& heater = heaterVec.at(heaterIdx); + // Check whether switch is already off + if (checkSwitchState(heaterIdx)) { + gpioId_t gpioId = heater.gpioId; result = gpioInterface->pullLow(gpioId); if (result != RETURN_OK) { sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId << " low" << std::endl; triggerEvent(GPIO_PULL_LOW_FAILED, result); } else { - switchStates[switchNr] = OFF; - /* When all switches are off, also main line switch will be turned off */ + auto result = heaterMutex->lockMutex(); + heater.switchState = OFF; + if (result == HasReturnvaluesIF::RETURN_OK) { + heaterMutex->unlockMutex(); + } + triggerEvent(HEATER_WENT_OFF, heaterIdx, 0); + // When all switches are off, also main line switch will be turned off if (allSwitchesOff()) { mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF); } } } else { sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl; - triggerEvent(SWITCH_ALREADY_OFF, switchNr); + triggerEvent(SWITCH_ALREADY_OFF, heaterIdx); } - if (heaterMapIter->second.replyQueue != NO_COMMANDER) { - /* Report back switch command reply if necessary */ + if (heater.replyQueue != NO_COMMANDER) { + // Report back switch command reply if necessary if (result == HasReturnvaluesIF::RETURN_OK) { - actionHelper.finish(true, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - result); + actionHelper.finish(true, heater.replyQueue, heater.action, result); } else { - actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, - result); + actionHelper.finish(false, heater.replyQueue, heater.action, result); } } - heaterMapIter->second.active = false; + heater.cmdActive = false; } -bool HeaterHandler::checkSwitchState(int switchNr) { return switchStates[switchNr]; } +HeaterHandler::SwitchState HeaterHandler::checkSwitchState(heater::Switchers switchNr) const { + MutexGuard mg(heaterMutex); + return heaterVec.at(switchNr).switchState; +} bool HeaterHandler::allSwitchesOff() { bool allSwitchesOrd = false; + MutexGuard mg(heaterMutex); /* Or all switches. As soon one switch is on, allSwitchesOrd will be true */ - for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { - allSwitchesOrd = allSwitchesOrd || switchStates[switchNr]; + for (power::Switch_t switchNr = 0; switchNr < heater::NUMBER_OF_SWITCHES; switchNr++) { + allSwitchesOrd = allSwitchesOrd || heaterVec.at(switchNr).switchState; } return !allSwitchesOrd; } -gpioId_t HeaterHandler::getGpioIdFromSwitchNr(int switchNr) { - gpioId_t gpioId = 0xFFFF; - switch (switchNr) { - case heaterSwitches::HEATER_0: - gpioId = gpioIds::HEATER_0; - break; - case heaterSwitches::HEATER_1: - gpioId = gpioIds::HEATER_1; - break; - case heaterSwitches::HEATER_2: - gpioId = gpioIds::HEATER_2; - break; - case heaterSwitches::HEATER_3: - gpioId = gpioIds::HEATER_3; - break; - case heaterSwitches::HEATER_4: - gpioId = gpioIds::HEATER_4; - break; - case heaterSwitches::HEATER_5: - gpioId = gpioIds::HEATER_5; - break; - case heaterSwitches::HEATER_6: - gpioId = gpioIds::HEATER_6; - break; - case heaterSwitches::HEATER_7: - gpioId = gpioIds::HEATER_7; - break; - default: - sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number" - << std::endl; - break; - } - return gpioId; -} - MessageQueueId_t HeaterHandler::getCommandQueue() const { return commandQueue->getId(); } ReturnValue_t HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) { return RETURN_OK; } -ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const { return 0; } +ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const { + ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch); + if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) { + return PowerSwitchIF::SWITCH_OFF; + } + if (switchNr > 7) { + return PowerSwitchIF::RETURN_FAILED; + } + if (checkSwitchState(static_cast(switchNr)) == SwitchState::ON) { + return PowerSwitchIF::SWITCH_ON; + } + return PowerSwitchIF::SWITCH_OFF; +} ReturnValue_t HeaterHandler::getFuseState(uint8_t fuseNr) const { return 0; } -uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 0; } +uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 2000; } diff --git a/mission/devices/HeaterHandler.h b/mission/devices/HeaterHandler.h index 18b821ec..85583591 100644 --- a/mission/devices/HeaterHandler.h +++ b/mission/devices/HeaterHandler.h @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include #include #include @@ -11,10 +14,20 @@ #include #include -#include +#include #include "devices/heaterSwitcherList.h" +class PowerSwitchIF; +class HealthTableIF; + +using HeaterPair = std::pair; + +struct HeaterHelper { + public: + HeaterHelper(std::array heaters) : heaters(heaters) {} + std::array heaters = {}; +}; /** * @brief This class intends the control of heaters. * @@ -33,42 +46,49 @@ class HeaterHandler : public ExecutableObjectIF, static const ReturnValue_t MAIN_SWITCH_SET_TIMEOUT = MAKE_RETURN_CODE(0xA4); static const ReturnValue_t COMMAND_ALREADY_WAITING = MAKE_RETURN_CODE(0xA5); + enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 }; + /** Device command IDs */ static const DeviceCommandId_t SWITCH_HEATER = 0x0; - HeaterHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF* gpioCookie, - object_id_t mainLineSwitcherObjectId, uint8_t mainLineSwitch); + HeaterHandler(object_id_t setObjectId, GpioIF* gpioInterface_, HeaterHelper helper, + PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch); virtual ~HeaterHandler(); - virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; + ReturnValue_t performOperation(uint8_t operationCode = 0) override; - virtual ReturnValue_t sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; - virtual ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override; + ReturnValue_t sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; + ReturnValue_t sendFuseOnCommand(uint8_t fuseNr) override; /** * @brief This function will be called from the Heater object to check * the current switch state. */ - virtual ReturnValue_t getSwitchState(uint8_t switchNr) const override; - virtual ReturnValue_t getFuseState(uint8_t fuseNr) const override; - virtual uint32_t getSwitchDelayMs(void) const override; + ReturnValue_t getSwitchState(uint8_t switchNr) const override; + ReturnValue_t getFuseState(uint8_t fuseNr) const override; + uint32_t getSwitchDelayMs(void) const override; - virtual MessageQueueId_t getCommandQueue() const override; - virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, - const uint8_t* data, size_t size) override; - virtual ReturnValue_t initialize() override; + MessageQueueId_t getCommandQueue() const override; + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override; + ReturnValue_t initialize() override; private: static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HEATER_HANDLER; - static const Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW); - static const Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); - static const Event SWITCH_ALREADY_ON = MAKE_EVENT(2, severity::LOW); - static const Event SWITCH_ALREADY_OFF = MAKE_EVENT(3, severity::LOW); - static const Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(4, severity::LOW); + static constexpr Event GPIO_PULL_HIGH_FAILED = MAKE_EVENT(0, severity::LOW); + static constexpr Event GPIO_PULL_LOW_FAILED = MAKE_EVENT(1, severity::LOW); + static constexpr Event HEATER_WENT_ON = event::makeEvent(SUBSYSTEM_ID, 2, severity::INFO); + static constexpr Event HEATER_WENT_OFF = event::makeEvent(SUBSYSTEM_ID, 3, severity::INFO); + static constexpr Event SWITCH_ALREADY_ON = MAKE_EVENT(4, severity::LOW); + static constexpr Event SWITCH_ALREADY_OFF = MAKE_EVENT(5, severity::LOW); + static constexpr Event MAIN_SWITCH_TIMEOUT = MAKE_EVENT(6, severity::MEDIUM); + //! A faulty heater was one. The SW will autonomously attempt to shut it down. P1: Heater Index + static constexpr Event FAULTY_HEATER_WAS_ON = event::makeEvent(SUBSYSTEM_ID, 7, severity::LOW); static const MessageQueueId_t NO_COMMANDER = 0; enum SwitchState : bool { ON = true, OFF = false }; + enum SwitchAction : uint8_t { SET_SWITCH_OFF, SET_SWITCH_ON, NONE }; /** * @brief Struct holding information about a heater command to execute. @@ -80,54 +100,46 @@ class HeaterHandler : public ExecutableObjectIF, * @param waitSwitchOn True if the command is waiting for the main switch being set on. * @param mainSwitchCountdown Sets timeout to wait for main switch being set on. */ - typedef struct HeaterCommandInfo { - uint8_t action; - MessageQueueId_t replyQueue; - bool active = false; + struct HeaterWrapper { + HeaterWrapper(HeaterPair pair, SwitchState initState) + : healthDevice(pair.first), gpioId(pair.second), switchState(initState) {} + HealthDevice* healthDevice = nullptr; + gpioId_t gpioId = gpio::NO_GPIO; + SwitchAction action = SwitchAction::NONE; + MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE; + bool cmdActive = false; + SwitchState switchState = SwitchState::OFF; bool waitMainSwitchOn = false; Countdown mainSwitchCountdown; - } HeaterCommandInfo_t; + }; - enum SwitchAction { SET_SWITCH_OFF, SET_SWITCH_ON }; + using HeaterMap = std::vector; - using switchNr_t = uint8_t; - using HeaterMap = std::unordered_map; - using HeaterMapIter = HeaterMap::iterator; + HeaterMap heaterVec = {}; - HeaterMap heaterMap; + MutexIF* heaterMutex = nullptr; - bool switchStates[heaterSwitches::NUMBER_OF_SWITCHES]; + HeaterHelper helper; /** Size of command queue */ size_t cmdQueueSize = 20; - /** - * The object ID of the GPIO driver which enables and disables the - * heaters. - */ - object_id_t gpioDriverId; - - CookieIF* gpioCookie; - GpioIF* gpioInterface = nullptr; /** Queue to receive messages from other objects. */ MessageQueueIF* commandQueue = nullptr; - object_id_t mainLineSwitcherObjectId; - - /** Switch number of the heater power supply switch */ - uint8_t mainLineSwitch; - /** * Power switcher object which controls the 8V main line of the heater * logic on the TCS board. */ PowerSwitchIF* mainLineSwitcher = nullptr; + /** Switch number of the heater power supply switch */ + power::Switch_t mainLineSwitch; ActionHelper actionHelper; - StorageManagerIF* IPCStore = nullptr; + StorageManagerIF* ipcStore = nullptr; void readCommandQueue(); @@ -135,18 +147,12 @@ class HeaterHandler : public ExecutableObjectIF, * @brief Returns the state of a switch (ON - true, or OFF - false). * @param switchNr The number of the switch to check. */ - bool checkSwitchState(int switchNr); - - /** - * @brief Returns the ID of the GPIO related to a heater identified by the switch number - * which is defined in the heaterSwitches list. - */ - gpioId_t getGpioIdFromSwitchNr(int switchNr); + SwitchState checkSwitchState(heater::Switchers switchNr) const; /** * @brief This function runs commands waiting for execution. */ - void handleActiveCommands(); + void handleSwitchHandling(); ReturnValue_t initializeHeaterMap(); @@ -155,9 +161,9 @@ class HeaterHandler : public ExecutableObjectIF, */ void setInitialSwitchStates(); - void handleSwitchOnCommand(HeaterMapIter heaterMapIter); + void handleSwitchOnCommand(heater::Switchers heaterIdx); - void handleSwitchOffCommand(HeaterMapIter heaterMapIter); + void handleSwitchOffCommand(heater::Switchers heaterIdx); /** * @brief Checks if all switches are off. diff --git a/tmtc b/tmtc index a6818502..bf641818 160000 --- a/tmtc +++ b/tmtc @@ -1 +1 @@ -Subproject commit a681850248fdf33c948b8cbda84acdf268d28669 +Subproject commit bf64181826de2682ec7298c2b86f500d079c26be