From e81ddaa1a56a4201adb30bb7bc63745469928382 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Thu, 12 May 2022 20:44:36 +0200 Subject: [PATCH] added auto-shutdown for faulty heaters --- bsp_q7s/core/ObjectFactory.cpp | 3 +- mission/devices/HeaterHandler.cpp | 70 +++++++++++++++++++------------ mission/devices/HeaterHandler.h | 11 +++-- 3 files changed, 51 insertions(+), 33 deletions(-) diff --git a/bsp_q7s/core/ObjectFactory.cpp b/bsp_q7s/core/ObjectFactory.cpp index 6e548741..1715fa63 100644 --- a/bsp_q7s/core/ObjectFactory.cpp +++ b/bsp_q7s/core/ObjectFactory.cpp @@ -526,7 +526,8 @@ void ObjectFactory::createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwi gpioIF->addGpios(heaterGpiosCookie); HeaterHelper helper({{ - {new HealthDevice(objects::HEATER_0_PLOC_PROC_BRD, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_0}, + {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}, diff --git a/mission/devices/HeaterHandler.cpp b/mission/devices/HeaterHandler.cpp index 5d04447f..6953dc54 100644 --- a/mission/devices/HeaterHandler.cpp +++ b/mission/devices/HeaterHandler.cpp @@ -43,10 +43,10 @@ HeaterHandler::~HeaterHandler() {} ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) { try { readCommandQueue(); - handleActiveCommands(); 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 | " @@ -117,29 +117,35 @@ ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t return HasActionsIF::INVALID_PARAMETERS; } auto& heater = heaterVec.at(switchNr); - 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) { + + auto actionRaw = data[1]; + if (actionRaw != 0 and actionRaw != 1) { return HasActionsIF::INVALID_PARAMETERS; } - cmdSource = static_cast(data[2]); - if(health == HasHealthIF::EXTERNAL_CONTROL and cmdSource == CmdSourceParam::INTERNAL) { - return HasHealthIF::IS_EXTERNALLY_CONTROLLED; + 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.active) { + + if (heater.cmdActive) { return COMMAND_ALREADY_WAITING; } - auto action = data[1]; - if (action != 0 and action != 1) { - return HasActionsIF::INVALID_PARAMETERS; - } - heater.action = static_cast(data[1]); - heater.active = true; + heater.action = action; + heater.cmdActive = true; heater.replyQueue = commandedBy; return RETURN_OK; } @@ -179,9 +185,21 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o return result; } -void HeaterHandler::handleActiveCommands() { +void HeaterHandler::handleSwitchHandling() { for (uint8_t idx = 0; idx < heater::NUMBER_OF_SWITCHES; idx++) { - if (heaterVec[idx].active) { + 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(static_cast(idx)); @@ -207,7 +225,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { triggerEvent(MAIN_SWITCH_TIMEOUT); sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout" << std::endl; - heater.active = false; + heater.cmdActive = false; heater.waitMainSwitchOn = false; if (heater.replyQueue != commandQueue->getId()) { actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT); @@ -241,7 +259,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { actionHelper.finish(false, heater.replyQueue, heater.action, result); } } - heater.active = false; + heater.cmdActive = false; heater.waitMainSwitchOn = false; } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && heater.waitMainSwitchOn) { // Just waiting for the main switch being set on @@ -251,12 +269,12 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switchers heaterIdx) { 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 (heater.replyQueue != commandQueue->getId()) { actionHelper.finish(false, heater.replyQueue, heater.action, mainSwitchState); } - heater.active = false; + heater.cmdActive = false; } } @@ -295,7 +313,7 @@ void HeaterHandler::handleSwitchOffCommand(heater::Switchers heaterIdx) { actionHelper.finish(false, heater.replyQueue, heater.action, result); } } - heater.active = false; + heater.cmdActive = false; } HeaterHandler::SwitchState HeaterHandler::checkSwitchState(heater::Switchers switchNr) const { diff --git a/mission/devices/HeaterHandler.h b/mission/devices/HeaterHandler.h index 66068ce4..85583591 100644 --- a/mission/devices/HeaterHandler.h +++ b/mission/devices/HeaterHandler.h @@ -46,10 +46,7 @@ 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 - }; + enum CmdSourceParam : uint8_t { INTERNAL = 0, EXTERNAL = 1 }; /** Device command IDs */ static const DeviceCommandId_t SWITCH_HEATER = 0x0; @@ -85,6 +82,8 @@ class HeaterHandler : public ExecutableObjectIF, 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; @@ -108,7 +107,7 @@ class HeaterHandler : public ExecutableObjectIF, gpioId_t gpioId = gpio::NO_GPIO; SwitchAction action = SwitchAction::NONE; MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE; - bool active = false; + bool cmdActive = false; SwitchState switchState = SwitchState::OFF; bool waitMainSwitchOn = false; Countdown mainSwitchCountdown; @@ -153,7 +152,7 @@ class HeaterHandler : public ExecutableObjectIF, /** * @brief This function runs commands waiting for execution. */ - void handleActiveCommands(); + void handleSwitchHandling(); ReturnValue_t initializeHeaterMap();