various improvements for heater handler #717
@ -26,6 +26,12 @@ will consitute of a breaking change warranting a new major release:
|
|||||||
|
|
||||||
- Internal error reporter set is now enabled by default and generated every 120 seconds.
|
- Internal error reporter set is now enabled by default and generated every 120 seconds.
|
||||||
- Persistent TM store dumps are now performed in chronological order.
|
- Persistent TM store dumps are now performed in chronological order.
|
||||||
|
- Various robustness improvements for the heater handler. The heater handler will now only
|
||||||
|
process the command queue if it is not busy with switch commanding which reduces the amount
|
||||||
|
of possible bugs.
|
||||||
|
- The heater handler is only able to process messages stricly sequentially now but is scheduled
|
||||||
|
twice in a 0.5 second slot so something like a consecutive heater ON or OFF command can still
|
||||||
|
be handled relatively quickly.
|
||||||
|
|
||||||
# [v5.0.0] 2023-06-26
|
# [v5.0.0] 2023-06-26
|
||||||
|
|
||||||
|
@ -324,6 +324,10 @@ void scheduling::initTasks() {
|
|||||||
if (result != returnvalue::OK) {
|
if (result != returnvalue::OK) {
|
||||||
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
||||||
}
|
}
|
||||||
|
result = tcsSystemTask->addComponent(objects::HEATER_HANDLER);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
scheduling::printAddObjectError("HEATER_HANDLER", objects::HEATER_HANDLER);
|
||||||
|
}
|
||||||
|
|
||||||
#if OBSW_ADD_SYRLINKS == 1
|
#if OBSW_ADD_SYRLINKS == 1
|
||||||
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
PeriodicTaskIF* syrlinksCom = factory->createPeriodicTask(
|
||||||
|
@ -33,8 +33,8 @@ void ObjectFactory::produce(void* args) {
|
|||||||
|
|
||||||
PersistentTmStores stores;
|
PersistentTmStores stores;
|
||||||
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
ObjectFactory::produceGenericObjects(&healthTable, &pusFunnel, &cfdpFunnel,
|
||||||
*SdCardManager::instance(), &ipcStore, &tmStore, stores,
|
*SdCardManager::instance(), &ipcStore, &tmStore, stores, 200,
|
||||||
200, true);
|
true);
|
||||||
|
|
||||||
LinuxLibgpioIF* gpioComIF = nullptr;
|
LinuxLibgpioIF* gpioComIF = nullptr;
|
||||||
SerialComIF* uartComIF = nullptr;
|
SerialComIF* uartComIF = nullptr;
|
||||||
|
@ -96,6 +96,25 @@ ReturnValue_t TemperatureSensorInserter::performOperation(uint8_t opCode) {
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case (TestCase::COLD_PLOC_CONSECUTIVE): {
|
||||||
|
if (cycles == 15) {
|
||||||
|
sif::debug << "Setting cold PLOC temperature" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
|
||||||
|
}
|
||||||
|
if (cycles == 30) {
|
||||||
|
sif::debug << "Setting warmer PLOC temperature" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
|
||||||
|
}
|
||||||
|
if (cycles == 45) {
|
||||||
|
sif::debug << "Setting cold PLOC temperature again" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(-15, true);
|
||||||
|
}
|
||||||
|
if (cycles == 60) {
|
||||||
|
sif::debug << "Setting warmer PLOC temperature again" << std::endl;
|
||||||
|
max31865DummyMap[objects::RTD_0_IC3_PLOC_HEATSPREADER]->setTemperature(0, true);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case (TestCase::COLD_CAMERA): {
|
case (TestCase::COLD_CAMERA): {
|
||||||
if (cycles == 15) {
|
if (cycles == 15) {
|
||||||
sif::debug << "Setting cold CAM temperature" << std::endl;
|
sif::debug << "Setting cold CAM temperature" << std::endl;
|
||||||
|
@ -32,6 +32,7 @@ class TemperatureSensorInserter : public ExecutableObjectIF, public SystemObject
|
|||||||
COLD_STR = 4,
|
COLD_STR = 4,
|
||||||
COLD_STR_CONSECUTIVE = 5,
|
COLD_STR_CONSECUTIVE = 5,
|
||||||
COLD_CAMERA = 6,
|
COLD_CAMERA = 6,
|
||||||
|
COLD_PLOC_CONSECUTIVE = 7,
|
||||||
};
|
};
|
||||||
int iteration = 0;
|
int iteration = 0;
|
||||||
uint32_t cycles = 0;
|
uint32_t cycles = 0;
|
||||||
|
@ -51,9 +51,13 @@ ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
|
|||||||
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == SWITCH_OFF) {
|
if (mainLineSwitcher->getSwitchState(mainLineSwitch) == SWITCH_OFF) {
|
||||||
waitForSwitchOff = false;
|
waitForSwitchOff = false;
|
||||||
mode = MODE_OFF;
|
mode = MODE_OFF;
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
modeHelper.modeChanged(mode, submode);
|
modeHelper.modeChanged(mode, submode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (busyWithSwitchCommanding and heaterCmdBusyCd.hasTimedOut()) {
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
|
}
|
||||||
} catch (const std::out_of_range& e) {
|
} catch (const std::out_of_range& e) {
|
||||||
sif::warning << "HeaterHandler::performOperation: "
|
sif::warning << "HeaterHandler::performOperation: "
|
||||||
"Out of range error | "
|
"Out of range error | "
|
||||||
@ -101,23 +105,23 @@ ReturnValue_t HeaterHandler::initializeHeaterMap() {
|
|||||||
void HeaterHandler::readCommandQueue() {
|
void HeaterHandler::readCommandQueue() {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
CommandMessage command;
|
CommandMessage command;
|
||||||
do {
|
if (not busyWithSwitchCommanding) {
|
||||||
result = commandQueue->receiveMessage(&command);
|
result = commandQueue->receiveMessage(&command);
|
||||||
if (result == MessageQueueIF::EMPTY) {
|
if (result == MessageQueueIF::EMPTY) {
|
||||||
break;
|
return;
|
||||||
} else if (result != returnvalue::OK) {
|
} else if (result != returnvalue::OK) {
|
||||||
sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl;
|
sif::warning << "HeaterHandler::readCommandQueue: Message reception error" << std::endl;
|
||||||
break;
|
return;
|
||||||
}
|
|
||||||
result = actionHelper.handleActionMessage(&command);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
result = modeHelper.handleModeCommand(&command);
|
result = modeHelper.handleModeCommand(&command);
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
continue;
|
return;
|
||||||
}
|
}
|
||||||
} while (result == returnvalue::OK);
|
result = actionHelper.handleActionMessage(&command);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
||||||
@ -167,6 +171,8 @@ ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId, MessageQueueId_t
|
|||||||
heater.action = action;
|
heater.action = action;
|
||||||
heater.cmdActive = true;
|
heater.cmdActive = true;
|
||||||
heater.replyQueue = commandedBy;
|
heater.replyQueue = commandedBy;
|
||||||
|
busyWithSwitchCommanding = true;
|
||||||
|
heaterCmdBusyCd.resetTimer();
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -249,6 +255,7 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
|
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
heater.cmdActive = false;
|
heater.cmdActive = false;
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
heater.waitMainSwitchOn = false;
|
heater.waitMainSwitchOn = false;
|
||||||
if (heater.replyQueue != commandQueue->getId()) {
|
if (heater.replyQueue != commandQueue->getId()) {
|
||||||
actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
|
actionHelper.finish(false, heater.replyQueue, heater.action, MAIN_SWITCH_SET_TIMEOUT);
|
||||||
@ -259,27 +266,25 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
// 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 (getSwitchState(heaterIdx) == SwitchState::OFF) {
|
gpioId_t gpioId = heater.gpioId;
|
||||||
gpioId_t gpioId = heater.gpioId;
|
result = gpioInterface->pullHigh(gpioId);
|
||||||
result = gpioInterface->pullHigh(gpioId);
|
if (result != returnvalue::OK) {
|
||||||
if (result != returnvalue::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 {
|
if (result == returnvalue::OK) {
|
||||||
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
triggerEvent(HEATER_WENT_ON, heaterIdx, 0);
|
||||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
{
|
||||||
MODE_ON, 0);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
{
|
heater.switchState = ON;
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
}
|
||||||
heater.switchState = ON;
|
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||||
}
|
MODE_ON, 0);
|
||||||
}
|
busyWithSwitchCommanding = false;
|
||||||
} else {
|
mode = HasModesIF::MODE_ON;
|
||||||
triggerEvent(SWITCH_ALREADY_ON, heaterIdx);
|
modeHelper.modeChanged(mode, submode);
|
||||||
}
|
}
|
||||||
mode = HasModesIF::MODE_ON;
|
|
||||||
modeHelper.modeChanged(mode, submode);
|
|
||||||
// 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 (heater.replyQueue != commandQueue->getId()) {
|
if (heater.replyQueue != commandQueue->getId()) {
|
||||||
@ -312,30 +317,33 @@ void HeaterHandler::handleSwitchOnCommand(heater::Switch heaterIdx) {
|
|||||||
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
void HeaterHandler::handleSwitchOffCommand(heater::Switch heaterIdx) {
|
||||||
ReturnValue_t result = returnvalue::OK;
|
ReturnValue_t result = returnvalue::OK;
|
||||||
auto& heater = heaterVec.at(heaterIdx);
|
auto& heater = heaterVec.at(heaterIdx);
|
||||||
// Check whether switch is already off
|
gpioId_t gpioId = heater.gpioId;
|
||||||
if (getSwitchState(heaterIdx)) {
|
result = gpioInterface->pullLow(gpioId);
|
||||||
gpioId_t gpioId = heater.gpioId;
|
if (result != returnvalue::OK) {
|
||||||
result = gpioInterface->pullLow(gpioId);
|
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
|
||||||
if (result != returnvalue::OK) {
|
<< " low" << std::endl;
|
||||||
sif::error << "HeaterHandler::handleSwitchOffCommand: Failed to pull gpio with id" << gpioId
|
triggerEvent(GPIO_PULL_LOW_FAILED, result);
|
||||||
<< " low" << std::endl;
|
}
|
||||||
triggerEvent(GPIO_PULL_LOW_FAILED, result);
|
if (result == returnvalue::OK) {
|
||||||
} else {
|
// Check whether switch is already off
|
||||||
|
if (getSwitchState(heaterIdx) == SwitchState::ON) {
|
||||||
{
|
{
|
||||||
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
MutexGuard mg(handlerLock, LOCK_TYPE, LOCK_TIMEOUT, LOCK_CTX);
|
||||||
heater.switchState = OFF;
|
heater.switchState = OFF;
|
||||||
}
|
}
|
||||||
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
triggerEvent(HEATER_WENT_OFF, heaterIdx, 0);
|
||||||
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
} else {
|
||||||
MODE_OFF, 0);
|
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
|
||||||
// When all switches are off, also main line switch will be turned off
|
}
|
||||||
if (allSwitchesOff()) {
|
EventManagerIF::triggerEvent(helper.heaters[heaterIdx].first->getObjectId(), MODE_INFO,
|
||||||
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
MODE_OFF, 0);
|
||||||
waitForSwitchOff = true;
|
// When all switches are off, also main line switch will be turned off
|
||||||
}
|
if (allSwitchesOff()) {
|
||||||
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
|
||||||
|
waitForSwitchOff = true;
|
||||||
|
} else {
|
||||||
|
busyWithSwitchCommanding = false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
triggerEvent(SWITCH_ALREADY_OFF, heaterIdx);
|
|
||||||
}
|
}
|
||||||
if (heater.replyQueue != NO_COMMANDER) {
|
if (heater.replyQueue != NO_COMMANDER) {
|
||||||
// Report back switch command reply if necessary
|
// Report back switch command reply if necessary
|
||||||
|
@ -148,6 +148,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
/** Size of command queue */
|
/** Size of command queue */
|
||||||
size_t cmdQueueSize = 20;
|
size_t cmdQueueSize = 20;
|
||||||
bool waitForSwitchOff = true;
|
bool waitForSwitchOff = true;
|
||||||
|
bool busyWithSwitchCommanding = false;
|
||||||
|
|
||||||
GpioIF* gpioInterface = nullptr;
|
GpioIF* gpioInterface = nullptr;
|
||||||
|
|
||||||
@ -163,6 +164,7 @@ class HeaterHandler : public ExecutableObjectIF,
|
|||||||
power::Switch_t mainLineSwitch;
|
power::Switch_t mainLineSwitch;
|
||||||
|
|
||||||
ActionHelper actionHelper;
|
ActionHelper actionHelper;
|
||||||
|
Countdown heaterCmdBusyCd = Countdown(2000);
|
||||||
|
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user