Heaters are own objects with HealthIF now
All checks were successful
EIVE/eive-obsw/pipeline/pr-develop This commit looks good

This commit is contained in:
Robin Müller 2022-05-02 22:45:27 +02:00
parent b98c691c2b
commit 9449919b2b
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
6 changed files with 192 additions and 255 deletions

View File

@ -152,7 +152,7 @@ void ObjectFactory::produce(void* args) {
createAcsBoardComponents(gpioComIF, uartComIF, pwrSwitcher); createAcsBoardComponents(gpioComIF, uartComIF, pwrSwitcher);
#endif #endif
createHeaterComponents(pwrSwitcher, healthTable); createHeaterComponents(gpioComIF, pwrSwitcher, healthTable);
createSolarArrayDeploymentComponents(); createSolarArrayDeploymentComponents();
createPlPcduComponents(gpioComIF, spiComIF, pwrSwitcher); createPlPcduComponents(gpioComIF, spiComIF, pwrSwitcher);
#if OBSW_ADD_SYRLINKS == 1 #if OBSW_ADD_SYRLINKS == 1
@ -581,7 +581,8 @@ void ObjectFactory::createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComI
#endif /* OBSW_ADD_ACS_HANDLERS == 1 */ #endif /* OBSW_ADD_ACS_HANDLERS == 1 */
} }
void ObjectFactory::createHeaterComponents(PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable) { void ObjectFactory::createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher,
HealthTableIF* healthTable) {
using namespace gpio; using namespace gpio;
GpioCookie* heaterGpiosCookie = new GpioCookie; GpioCookie* heaterGpiosCookie = new GpioCookie;
GpiodRegularByLineName* gpio = nullptr; GpiodRegularByLineName* gpio = nullptr;
@ -622,7 +623,19 @@ void ObjectFactory::createHeaterComponents(PowerSwitchIF* pwrSwitcher, HealthTab
Levels::LOW); Levels::LOW);
heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpio); heaterGpiosCookie->addGpio(gpioIds::HEATER_7, gpio);
new HeaterHandler(objects::HEATER_HANDLER, objects::GPIO_IF, heaterGpiosCookie, pwrSwitcher, gpioIF->addGpios(heaterGpiosCookie);
HeaterHelper helper({{
{new HealthDevice(objects::HEATER_0, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_0},
{new HealthDevice(objects::HEATER_1, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_1},
{new HealthDevice(objects::HEATER_2, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_2},
{new HealthDevice(objects::HEATER_3, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_3},
{new HealthDevice(objects::HEATER_4, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_4},
{new HealthDevice(objects::HEATER_5, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_5},
{new HealthDevice(objects::HEATER_6, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_6},
{new HealthDevice(objects::HEATER_7, MessageQueueIF::NO_QUEUE), gpioIds::HEATER_7},
}});
new HeaterHandler(objects::HEATER_HANDLER, gpioIF, helper, pwrSwitcher,
pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V); pcdu::Switches::PDU2_CH3_TCS_BOARD_HEATER_IN_8V);
} }

View File

@ -8,6 +8,7 @@ class I2cComIF;
class PowerSwitchIF; class PowerSwitchIF;
class HealthTableIF; class HealthTableIF;
class AcsBoardAssembly; class AcsBoardAssembly;
class GpioIF;
namespace ObjectFactory { namespace ObjectFactory {
@ -23,7 +24,7 @@ void createTmpComponents();
void createRadSensorComponent(LinuxLibgpioIF* gpioComIF); void createRadSensorComponent(LinuxLibgpioIF* gpioComIF);
void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF, void createAcsBoardComponents(LinuxLibgpioIF* gpioComIF, UartComIF* uartComIF,
PowerSwitchIF* pwrSwitcher); PowerSwitchIF* pwrSwitcher);
void createHeaterComponents(PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable); void createHeaterComponents(GpioIF* gpioIF, PowerSwitchIF* pwrSwitcher, HealthTableIF* healthTable);
void createSolarArrayDeploymentComponents(); void createSolarArrayDeploymentComponents();
void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher); void createSyrlinksComponents(PowerSwitchIF* pwrSwitcher);
void createPayloadComponents(LinuxLibgpioIF* gpioComIF); void createPayloadComponents(LinuxLibgpioIF* gpioComIF);

View File

@ -22,13 +22,6 @@ enum commonObjects: uint32_t {
CORE_CONTROLLER = 0x43000003, CORE_CONTROLLER = 0x43000003,
/* 0x44 ('D') for device handlers */ /* 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_0_LIS3_HANDLER = 0x44120006,
MGM_1_RM3100_HANDLER = 0x44120107, MGM_1_RM3100_HANDLER = 0x44120107,
MGM_2_LIS3_HANDLER = 0x44120208, MGM_2_LIS3_HANDLER = 0x44120208,
@ -37,12 +30,45 @@ enum commonObjects: uint32_t {
GYRO_1_L3G_HANDLER = 0x44120111, GYRO_1_L3G_HANDLER = 0x44120111,
GYRO_2_ADIS_HANDLER = 0x44120212, GYRO_2_ADIS_HANDLER = 0x44120212,
GYRO_3_L3G_HANDLER = 0x44120313, GYRO_3_L3G_HANDLER = 0x44120313,
PLPCDU_HANDLER = 0x44300000, SUS_0 = 0x44120032,
SUS_1 = 0x44120033,
SUS_2 = 0x44120034,
SUS_3 = 0x44120035,
SUS_4 = 0x44120036,
SUS_5 = 0x44120037,
SUS_6 = 0x44120038,
SUS_7 = 0x44120039,
SUS_8 = 0x44120040,
SUS_9 = 0x44120041,
SUS_10 = 0x44120042,
SUS_11 = 0x44120043,
RW1 = 0x44120047,
RW2 = 0x44120148,
RW3 = 0x44120249,
RW4 = 0x44120350,
STAR_TRACKER = 0x44130001,
GPS_CONTROLLER = 0x44130045,
IMTQ_HANDLER = 0x44140014, 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,
PLOC_MPSOC_HANDLER = 0x44330015, PLOC_MPSOC_HANDLER = 0x44330015,
PLOC_SUPERVISOR_HANDLER = 0x44330016, PLOC_SUPERVISOR_HANDLER = 0x44330016,
PLOC_SUPERVISOR_HELPER = 0x44330017, 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. * Not yet specified which pt1000 will measure which device/location in the satellite.
@ -65,35 +91,22 @@ enum commonObjects: uint32_t {
RTD_IC_17 = 0x44420030, RTD_IC_17 = 0x44420030,
RTD_IC_18 = 0x44420031, RTD_IC_18 = 0x44420031,
SUS_0 = 0x44120032,
SUS_1 = 0x44120033,
SUS_2 = 0x44120034,
SUS_3 = 0x44120035,
SUS_4 = 0x44120036,
SUS_5 = 0x44120037,
SUS_6 = 0x44120038,
SUS_7 = 0x44120039,
SUS_8 = 0x44120040,
SUS_9 = 0x44120041,
SUS_10 = 0x44120042,
SUS_11 = 0x44120043,
GPS_CONTROLLER = 0x44130045,
RW1 = 0x44120047, SYRLINKS_HK_HANDLER = 0x445300A3,
RW2 = 0x44120148,
RW3 = 0x44120249,
RW4 = 0x44120350,
STAR_TRACKER = 0x44130001,
PLOC_UPDATER = 0x44330000,
PLOC_MEMORY_DUMPER = 0x44330001,
STR_HELPER = 0x44330002,
PLOC_MPSOC_HELPER = 0x44330003,
AXI_PTME_CONFIG = 44330004, AXI_PTME_CONFIG = 44330004,
PTME_CONFIG = 44330005, PTME_CONFIG = 44330005,
// 0x60 for other stuff
HEATER_0 = 0x60000000,
HEATER_1 = 0x60000001,
HEATER_2 = 0x60000002,
HEATER_3 = 0x60000003,
HEATER_4 = 0x60000004,
HEATER_5 = 0x60000005,
HEATER_6 = 0x60000006,
HEATER_7 = 0x60000007,
// 0x73 ('s') for assemblies and system/subsystem components // 0x73 ('s') for assemblies and system/subsystem components
ACS_BOARD_ASS = 0x73000001, ACS_BOARD_ASS = 0x73000001,
SUS_BOARD_ASS = 0x73000002, SUS_BOARD_ASS = 0x73000002,

View File

@ -50,13 +50,6 @@ enum sourceObjects : uint32_t {
SPI_COM_IF = 0x49020004, SPI_COM_IF = 0x49020004,
GPIO_IF = 0x49010005, GPIO_IF = 0x49010005,
/* 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 */ /* 0x54 ('T') for test handlers */
TEST_TASK = 0x54694269, TEST_TASK = 0x54694269,
LIBGPIOD_TEST = 0x54123456, LIBGPIOD_TEST = 0x54123456,

View File

@ -10,16 +10,22 @@
#include "devices/gpioIds.h" #include "devices/gpioIds.h"
#include "devices/powerSwitcherList.h" #include "devices/powerSwitcherList.h"
HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_, HeaterHandler::HeaterHandler(object_id_t setObjectId_, GpioIF* gpioInterface_, HeaterHelper helper,
CookieIF* gpioCookie_, PowerSwitchIF* mainLineSwitcher_, PowerSwitchIF* mainLineSwitcher_, power::Switch_t mainLineSwitch_)
power::Switch_t mainLineSwitch_)
: SystemObject(setObjectId_), : SystemObject(setObjectId_),
gpioDriverId(gpioDriverId_), helper(helper),
gpioCookie(gpioCookie_), gpioInterface(gpioInterface_),
mainLineSwitcher(mainLineSwitcher_), mainLineSwitcher(mainLineSwitcher_),
mainLineSwitch(mainLineSwitch_), mainLineSwitch(mainLineSwitch_),
healthHelper(this, getObjectId()),
actionHelper(this, nullptr) { 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) { if (mainLineSwitcher == nullptr) {
throw std::invalid_argument("HeaterHandler::HeaterHandler: Invalid PowerSwitchIF"); throw std::invalid_argument("HeaterHandler::HeaterHandler: Invalid PowerSwitchIF");
} }
@ -31,10 +37,10 @@ HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_
HeaterHandler::~HeaterHandler() {} HeaterHandler::~HeaterHandler() {}
ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) { ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
readCommandQueue(); readCommandQueue();
handleActiveCommands(); handleActiveCommands();
return RETURN_OK; for (const auto& heater : helper.heaters) {
heater.first->performOperation(0);
} }
return RETURN_OK; return RETURN_OK;
} }
@ -50,22 +56,8 @@ ReturnValue_t HeaterHandler::initialize() {
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
gpioInterface = ObjectManager::instance()->get<GpioIF>(gpioDriverId); ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (gpioInterface == nullptr) { if (ipcStore == nullptr) {
sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
if (result != RETURN_OK) {
sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
healthHelper.initialize(commandQueue->getId());
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (IPCStore == nullptr) {
sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl; sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED; return ObjectManagerIF::CHILD_INIT_FAILED;
} }
@ -79,24 +71,12 @@ ReturnValue_t HeaterHandler::initialize() {
} }
ReturnValue_t HeaterHandler::initializeHeaterMap() { ReturnValue_t HeaterHandler::initializeHeaterMap() {
HeaterCommandInfo_t heaterCommandInfo; for (power::Switch_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { heaterVec.push_back(HeaterWrapper(helper.heaters[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;
}
} }
return RETURN_OK; return RETURN_OK;
} }
void HeaterHandler::setInitialSwitchStates() {
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
switchStates[switchNr] = OFF;
}
}
void HeaterHandler::readCommandQueue() { void HeaterHandler::readCommandQueue() {
ReturnValue_t result = RETURN_OK; ReturnValue_t result = RETURN_OK;
CommandMessage command; CommandMessage command;
@ -111,41 +91,44 @@ void HeaterHandler::readCommandQueue() {
if (result == RETURN_OK) { if (result == RETURN_OK) {
continue; continue;
} }
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
} while (result == RETURN_OK); } while (result == RETURN_OK);
} }
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) { const uint8_t* data, size_t size) {
ReturnValue_t result; if (data == nullptr or size < 2) {
return HasActionsIF::INVALID_PARAMETERS;
}
if (actionId != SWITCH_HEATER) { if (actionId != SWITCH_HEATER) {
result = COMMAND_NOT_SUPPORTED; return COMMAND_NOT_SUPPORTED;
} else { }
switchNr_t switchNr = *data; auto switchNr = *data;
HeaterMapIter heaterMapIter = heaterMap.find(switchNr); if (switchNr > 7) {
if (heaterMapIter != heaterMap.end()) { return HasActionsIF::INVALID_PARAMETERS;
if (heaterMapIter->second.active) { }
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;
}
if (heater.active) {
return COMMAND_ALREADY_WAITING; return COMMAND_ALREADY_WAITING;
} }
heaterMapIter->second.action = *(data + 1); auto action = data[1];
heaterMapIter->second.active = true; if (action != 0 and action != 1) {
heaterMapIter->second.replyQueue = commandedBy; return HasActionsIF::INVALID_PARAMETERS;
} else {
sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl;
return INVALID_SWITCH_NR;
} }
result = RETURN_OK; heater.action = static_cast<SwitchAction>(data[1]);
} heater.active = true;
return result; heater.replyQueue = commandedBy;
return RETURN_OK;
} }
ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) { ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) {
ReturnValue_t result; ReturnValue_t result;
store_address_t storeAddress; store_address_t storeAddress;
uint8_t commandData[2]; uint8_t commandData[2] = {};
switch (onOff) { switch (onOff) {
case PowerSwitchIF::SWITCH_ON: case PowerSwitchIF::SWITCH_ON:
@ -161,7 +144,7 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o
break; break;
} }
result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData)); result = ipcStore->addData(&storeAddress, commandData, sizeof(commandData));
if (result == RETURN_OK) { if (result == RETURN_OK) {
CommandMessage message; CommandMessage message;
ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress); ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress);
@ -176,15 +159,14 @@ ReturnValue_t HeaterHandler::sendSwitchCommand(uint8_t switchNr, ReturnValue_t o
} }
void HeaterHandler::handleActiveCommands() { void HeaterHandler::handleActiveCommands() {
HeaterMapIter heaterMapIter = heaterMap.begin(); for (uint8_t idx = 0; idx < heater::NUMBER_OF_HEATERS; idx++) {
for (; heaterMapIter != heaterMap.end(); heaterMapIter++) { if (heaterVec[idx].active) {
if (heaterMapIter->second.active) { switch (heaterVec[idx].action) {
switch (heaterMapIter->second.action) {
case SET_SWITCH_ON: case SET_SWITCH_ON:
handleSwitchOnCommand(heaterMapIter); handleSwitchOnCommand(idx);
break; break;
case SET_SWITCH_OFF: case SET_SWITCH_OFF:
handleSwitchOffCommand(heaterMapIter); handleSwitchOffCommand(idx);
break; break;
default: default:
sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded" sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
@ -195,156 +177,113 @@ void HeaterHandler::handleActiveCommands() {
} }
} }
void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) { void HeaterHandler::handleSwitchOnCommand(uint8_t heaterIdx) {
ReturnValue_t result = RETURN_OK; 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 */ /* Check if command waits for main switch being set on and whether the timeout has expired */
if (heaterMapIter->second.waitMainSwitchOn && if (heater.waitMainSwitchOn && heater.mainSwitchCountdown.hasTimedOut()) {
heaterMapIter->second.mainSwitchCountdown.hasTimedOut()) {
// TODO - This requires the initiation of an FDIR procedure // TODO - This requires the initiation of an FDIR procedure
triggerEvent(MAIN_SWITCH_TIMEOUT); triggerEvent(MAIN_SWITCH_TIMEOUT);
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout" sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
<< std::endl; << std::endl;
heaterMapIter->second.active = false; heater.active = false;
heaterMapIter->second.waitMainSwitchOn = false; heater.waitMainSwitchOn = false;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) { if (heater.replyQueue != commandQueue->getId()) {
actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
MAIN_SWITCH_SET_TIMEOUT);
} }
return; return;
} }
switchNr = heaterMapIter->first; // Check state of main line switch
/* Check state of main line switch */
ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch); ReturnValue_t mainSwitchState = mainLineSwitcher->getSwitchState(mainLineSwitch);
if (mainSwitchState == PowerSwitchIF::SWITCH_ON) { if (mainSwitchState == PowerSwitchIF::SWITCH_ON) {
if (!checkSwitchState(switchNr)) { if (!checkSwitchState(heaterIdx)) {
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullHigh(gpioId); result = gpioInterface->pullHigh(gpioId);
if (result != RETURN_OK) { if (result != RETURN_OK) {
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id " << gpioId sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id " << gpioId
<< " high" << std::endl; << " high" << std::endl;
triggerEvent(GPIO_PULL_HIGH_FAILED, result); triggerEvent(GPIO_PULL_HIGH_FAILED, result);
} else { } else {
switchStates[switchNr] = ON; heater.switchState = ON;
} }
} else { } 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 // There is no need to send action finish replies if the sender was the
* HeaterHandler itself. */ // HeaterHandler itself
if (heaterMapIter->second.replyQueue != commandQueue->getId()) { if (heater.replyQueue != commandQueue->getId()) {
if (result == RETURN_OK) { if (result == RETURN_OK) {
actionHelper.finish(true, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(true, heater.replyQueue, heater.action, result);
result);
} else { } else {
actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(false, heater.replyQueue, heater.action, result);
result);
} }
} }
heaterMapIter->second.active = false; heater.active = false;
heaterMapIter->second.waitMainSwitchOn = false; heater.waitMainSwitchOn = false;
} else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF && heater.waitMainSwitchOn) {
heaterMapIter->second.waitMainSwitchOn) { // Just waiting for the main switch being set on
/* Just waiting for the main switch being set on */
return; return;
} else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) { } else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON); mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_ON);
heaterMapIter->second.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs()); heater.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
heaterMapIter->second.waitMainSwitchOn = true; heater.waitMainSwitchOn = true;
} else { } else {
sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of" sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of"
<< " main line switch" << std::endl; << " main line switch" << std::endl;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) { if (heater.replyQueue != commandQueue->getId()) {
actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(false, heater.replyQueue, heater.action, mainSwitchState);
mainSwitchState);
} }
heaterMapIter->second.active = false; heater.active = false;
} }
} }
void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) { void HeaterHandler::handleSwitchOffCommand(uint8_t heaterIdx) {
ReturnValue_t result = RETURN_OK; ReturnValue_t result = RETURN_OK;
switchNr_t switchNr = heaterMapIter->first; auto& heater = heaterVec.at(heaterIdx);
/* Check whether switch is already off */ // Check whether switch is already off
if (checkSwitchState(switchNr)) { if (checkSwitchState(heaterIdx)) {
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr); gpioId_t gpioId = heater.gpioId;
result = gpioInterface->pullLow(gpioId); result = gpioInterface->pullLow(gpioId);
if (result != RETURN_OK) { if (result != RETURN_OK) {
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
<< " low" << std::endl; << " low" << std::endl;
triggerEvent(GPIO_PULL_LOW_FAILED, result); triggerEvent(GPIO_PULL_LOW_FAILED, result);
} else { } else {
switchStates[switchNr] = OFF; heater.switchState = OFF;
/* When all switches are off, also main line switch will be turned off */ // When all switches are off, also main line switch will be turned off
if (allSwitchesOff()) { if (allSwitchesOff()) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF); mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
} }
} }
} else { } else {
sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl; 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) { if (heater.replyQueue != NO_COMMANDER) {
/* Report back switch command reply if necessary */ // Report back switch command reply if necessary
if (result == HasReturnvaluesIF::RETURN_OK) { if (result == HasReturnvaluesIF::RETURN_OK) {
actionHelper.finish(true, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(true, heater.replyQueue, heater.action, result);
result);
} else { } else {
actionHelper.finish(false, heaterMapIter->second.replyQueue, heaterMapIter->second.action, actionHelper.finish(false, heater.replyQueue, heater.action, result);
result);
} }
} }
heaterMapIter->second.active = false; heater.active = false;
} }
bool HeaterHandler::checkSwitchState(int switchNr) { return switchStates[switchNr]; } HeaterHandler::SwitchState HeaterHandler::checkSwitchState(uint8_t switchNr) {
return heaterVec.at(switchNr).switchState;
}
bool HeaterHandler::allSwitchesOff() { bool HeaterHandler::allSwitchesOff() {
bool allSwitchesOrd = false; bool allSwitchesOrd = false;
/* Or all switches. As soon one switch is on, allSwitchesOrd will be true */ /* Or all switches. As soon one switch is on, allSwitchesOrd will be true */
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) { for (power::Switch_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
allSwitchesOrd = allSwitchesOrd || switchStates[switchNr]; allSwitchesOrd = allSwitchesOrd || heaterVec.at(switchNr).switchState;
} }
return !allSwitchesOrd; 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(); } MessageQueueId_t HeaterHandler::getCommandQueue() const { return commandQueue->getId(); }
ReturnValue_t HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) { return RETURN_OK; } ReturnValue_t HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) { return RETURN_OK; }
@ -354,10 +293,3 @@ ReturnValue_t HeaterHandler::getSwitchState(uint8_t switchNr) const { return 0;
ReturnValue_t HeaterHandler::getFuseState(uint8_t fuseNr) const { return 0; } ReturnValue_t HeaterHandler::getFuseState(uint8_t fuseNr) const { return 0; }
uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 2000; } uint32_t HeaterHandler::getSwitchDelayMs(void) const { return 2000; }
ReturnValue_t HeaterHandler::setHealth(HealthState health) {
healthHelper.setHealth(health);
return RETURN_OK;
}
HasHealthIF::HealthState HeaterHandler::getHealth() { return healthHelper.getHealth(); }

View File

@ -4,6 +4,7 @@
#include <fsfw/action/HasActionsIF.h> #include <fsfw/action/HasActionsIF.h>
#include <fsfw/devicehandlers/CookieIF.h> #include <fsfw/devicehandlers/CookieIF.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h> #include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/devicehandlers/HealthDevice.h>
#include <fsfw/health/HasHealthIF.h> #include <fsfw/health/HasHealthIF.h>
#include <fsfw/health/HealthHelper.h> #include <fsfw/health/HealthHelper.h>
#include <fsfw/objectmanager/SystemObject.h> #include <fsfw/objectmanager/SystemObject.h>
@ -13,13 +14,26 @@
#include <fsfw/timemanager/Countdown.h> #include <fsfw/timemanager/Countdown.h>
#include <fsfw_hal/common/gpio/GpioIF.h> #include <fsfw_hal/common/gpio/GpioIF.h>
#include <unordered_map> #include <vector>
#include "devices/heaterSwitcherList.h" #include "devices/heaterSwitcherList.h"
class PowerSwitchIF; class PowerSwitchIF;
class HealthTableIF; class HealthTableIF;
namespace heater {
static constexpr uint8_t NUMBER_OF_HEATERS = 8;
}
using HeaterPair = std::pair<HealthDevice*, gpioId_t>;
struct HeaterHelper {
public:
HeaterHelper(std::array<HeaterPair, heater::NUMBER_OF_HEATERS> heaters) : heaters(heaters) {}
std::array<HeaterPair, heater::NUMBER_OF_HEATERS> heaters = {};
};
/** /**
* @brief This class intends the control of heaters. * @brief This class intends the control of heaters.
* *
@ -27,7 +41,6 @@ class HealthTableIF;
*/ */
class HeaterHandler : public ExecutableObjectIF, class HeaterHandler : public ExecutableObjectIF,
public PowerSwitchIF, public PowerSwitchIF,
public HasHealthIF,
public SystemObject, public SystemObject,
public HasActionsIF { public HasActionsIF {
public: public:
@ -42,24 +55,11 @@ class HeaterHandler : public ExecutableObjectIF,
/** Device command IDs */ /** Device command IDs */
static const DeviceCommandId_t SWITCH_HEATER = 0x0; static const DeviceCommandId_t SWITCH_HEATER = 0x0;
HeaterHandler(object_id_t setObjectId, object_id_t gpioDriverId, CookieIF* gpioCookie, HeaterHandler(object_id_t setObjectId, GpioIF* gpioInterface_, HeaterHelper helper,
PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch); PowerSwitchIF* mainLineSwitcherObjectId, power::Switch_t mainLineSwitch);
virtual ~HeaterHandler(); virtual ~HeaterHandler();
/**
* @brief Set the Health State
* The parent will be informed, if the Health changes
* @param health
*/
ReturnValue_t setHealth(HealthState health) override;
/**
* @brief Get Health State
* @return Health State of the object
*/
HasHealthIF::HealthState getHealth() override;
virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override; virtual ReturnValue_t performOperation(uint8_t operationCode = 0) override;
virtual ReturnValue_t sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override; virtual ReturnValue_t sendSwitchCommand(uint8_t switchNr, ReturnValue_t onOff) override;
@ -88,6 +88,7 @@ class HeaterHandler : public ExecutableObjectIF,
static const MessageQueueId_t NO_COMMANDER = 0; static const MessageQueueId_t NO_COMMANDER = 0;
enum SwitchState : bool { ON = true, OFF = false }; 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. * @brief Struct holding information about a heater command to execute.
@ -99,35 +100,27 @@ class HeaterHandler : public ExecutableObjectIF,
* @param waitSwitchOn True if the command is waiting for the main switch being set on. * @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. * @param mainSwitchCountdown Sets timeout to wait for main switch being set on.
*/ */
typedef struct HeaterCommandInfo { struct HeaterWrapper {
uint8_t action; HeaterWrapper(HeaterPair pair) : healthDevice(pair.first), gpioId(pair.second) {}
MessageQueueId_t replyQueue; HealthDevice* healthDevice = nullptr;
gpioId_t gpioId = gpio::NO_GPIO;
SwitchAction action = SwitchAction::NONE;
MessageQueueId_t replyQueue = MessageQueueIF::NO_QUEUE;
bool active = false; bool active = false;
SwitchState switchState = SwitchState::OFF;
bool waitMainSwitchOn = false; bool waitMainSwitchOn = false;
Countdown mainSwitchCountdown; Countdown mainSwitchCountdown;
} HeaterCommandInfo_t; };
enum SwitchAction { SET_SWITCH_OFF, SET_SWITCH_ON }; using HeaterMap = std::vector<HeaterWrapper>;
using switchNr_t = uint8_t; HeaterMap heaterVec = {};
using HeaterMap = std::unordered_map<switchNr_t, HeaterCommandInfo_t>;
using HeaterMapIter = HeaterMap::iterator;
HeaterMap heaterMap; HeaterHelper helper;
bool switchStates[heaterSwitches::NUMBER_OF_SWITCHES];
/** Size of command queue */ /** Size of command queue */
size_t cmdQueueSize = 20; 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; GpioIF* gpioInterface = nullptr;
/** Queue to receive messages from other objects. */ /** Queue to receive messages from other objects. */
@ -141,11 +134,9 @@ class HeaterHandler : public ExecutableObjectIF,
/** Switch number of the heater power supply switch */ /** Switch number of the heater power supply switch */
power::Switch_t mainLineSwitch; power::Switch_t mainLineSwitch;
HealthHelper healthHelper;
ActionHelper actionHelper; ActionHelper actionHelper;
StorageManagerIF* IPCStore = nullptr; StorageManagerIF* ipcStore = nullptr;
void readCommandQueue(); void readCommandQueue();
@ -153,13 +144,7 @@ class HeaterHandler : public ExecutableObjectIF,
* @brief Returns the state of a switch (ON - true, or OFF - false). * @brief Returns the state of a switch (ON - true, or OFF - false).
* @param switchNr The number of the switch to check. * @param switchNr The number of the switch to check.
*/ */
bool checkSwitchState(int switchNr); SwitchState checkSwitchState(power::Switch_t 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);
/** /**
* @brief This function runs commands waiting for execution. * @brief This function runs commands waiting for execution.
@ -173,9 +158,9 @@ class HeaterHandler : public ExecutableObjectIF,
*/ */
void setInitialSwitchStates(); void setInitialSwitchStates();
void handleSwitchOnCommand(HeaterMapIter heaterMapIter); void handleSwitchOnCommand(uint8_t heaterIdx);
void handleSwitchOffCommand(HeaterMapIter heaterMapIter); void handleSwitchOffCommand(uint8_t heaterIdx);
/** /**
* @brief Checks if all switches are off. * @brief Checks if all switches are off.