eive-obsw/mission/devices/HeaterHandler.cpp

374 lines
12 KiB
C++
Raw Normal View History

2021-02-14 18:30:12 +01:00
#include "HeaterHandler.h"
2021-05-17 16:37:29 +02:00
#include "devices/gpioIds.h"
#include "devices/powerSwitcherList.h"
2021-06-08 16:45:25 +02:00
#include <fsfw/objectmanager/ObjectManager.h>
#include <fsfw/ipc/QueueFactory.h>
2021-08-03 15:58:01 +02:00
#include <fsfw_hal/common/gpio/GpioCookie.h>
2021-01-28 14:55:21 +01:00
HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_,
CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) :
2021-02-14 18:30:12 +01:00
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_),
mainLineSwitcherObjectId(mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_),
actionHelper(this, nullptr) {
2021-02-22 14:25:46 +01:00
commandQueue = QueueFactory::instance()->createMessageQueue(cmdQueueSize,
MessageQueueMessage::MAX_MESSAGE_SIZE);
2021-01-23 17:22:40 +01:00
}
HeaterHandler::~HeaterHandler() {
}
2021-01-28 14:55:21 +01:00
ReturnValue_t HeaterHandler::performOperation(uint8_t operationCode) {
2021-01-23 17:22:40 +01:00
if (operationCode == DeviceHandlerIF::PERFORM_OPERATION) {
readCommandQueue();
2021-01-28 14:55:21 +01:00
handleActiveCommands();
2021-01-23 17:22:40 +01:00
return RETURN_OK;
}
return RETURN_OK;
2021-01-23 17:22:40 +01:00
}
2021-01-28 14:55:21 +01:00
ReturnValue_t HeaterHandler::initialize() {
2021-01-23 17:22:40 +01:00
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
2021-01-28 14:55:21 +01:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
result = initializeHeaterMap();
if (result != RETURN_OK) {
return ObjectManagerIF::CHILD_INIT_FAILED;
2021-01-23 17:22:40 +01:00
}
2021-06-08 16:45:25 +02:00
gpioInterface = ObjectManager::instance()->get<GpioIF>(gpioDriverId);
2021-01-23 17:22:40 +01:00
if (gpioInterface == nullptr) {
2021-01-28 14:55:21 +01:00
sif::error << "HeaterHandler::initialize: Invalid Gpio interface." << std::endl;
2021-01-23 17:22:40 +01:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
2021-02-23 13:38:43 +01:00
result = gpioInterface->addGpios(dynamic_cast<GpioCookie*>(gpioCookie));
2021-01-23 17:22:40 +01:00
if (result != RETURN_OK) {
2021-01-28 14:55:21 +01:00
sif::error << "HeaterHandler::initialize: Failed to initialize Gpio interface" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
2021-01-23 17:22:40 +01:00
}
2021-06-08 16:45:25 +02:00
IPCStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
2021-01-23 17:22:40 +01:00
if (IPCStore == nullptr) {
2021-01-28 14:55:21 +01:00
sif::error << "HeaterHandler::initialize: IPC store not set up in factory." << std::endl;
2021-01-23 17:22:40 +01:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
2021-01-28 14:55:21 +01:00
if(mainLineSwitcherObjectId != objects::NO_OBJECT) {
2021-06-08 16:45:25 +02:00
mainLineSwitcher = ObjectManager::instance()->get<PowerSwitchIF>(mainLineSwitcherObjectId);
2021-01-28 14:55:21 +01:00
if (mainLineSwitcher == nullptr) {
2021-04-15 13:17:15 +02:00
sif::error
<< "HeaterHandler::initialize: Failed to get main line switcher. Make sure "
<< "main line switcher object is initialized." << std::endl;
2021-01-23 17:22:40 +01:00
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
result = actionHelper.initialize(commandQueue);
if (result != RETURN_OK) {
2021-01-28 14:55:21 +01:00
return ObjectManagerIF::CHILD_INIT_FAILED;
2021-01-23 17:22:40 +01:00
}
return RETURN_OK;
}
2021-01-28 14:55:21 +01:00
ReturnValue_t HeaterHandler::initializeHeaterMap(){
HeaterCommandInfo_t heaterCommandInfo;
for(switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
2021-01-28 14:55:21 +01:00
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;
}
2021-01-23 17:22:40 +01:00
2021-01-28 14:55:21 +01:00
void HeaterHandler::setInitialSwitchStates() {
for (switchNr_t switchNr = 0; switchNr < heaterSwitches::NUMBER_OF_SWITCHES; switchNr++) {
2021-01-28 14:55:21 +01:00
switchStates[switchNr] = OFF;
2021-01-23 17:22:40 +01:00
}
2021-01-28 14:55:21 +01:00
}
2021-01-23 17:22:40 +01:00
2021-01-28 14:55:21 +01:00
void HeaterHandler::readCommandQueue() {
2021-01-23 17:22:40 +01:00
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == RETURN_OK) {
return;
}
}
ReturnValue_t HeaterHandler::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
ReturnValue_t result;
if (actionId != SWITCH_HEATER) {
2021-01-23 17:22:40 +01:00
result = COMMAND_NOT_SUPPORTED;
} else {
switchNr_t switchNr = *data;
HeaterMapIter heaterMapIter = heaterMap.find(switchNr);
2021-01-28 14:55:21 +01:00
if (heaterMapIter != heaterMap.end()) {
2021-02-11 08:19:48 +01:00
if (heaterMapIter->second.active) {
return COMMAND_ALREADY_WAITING;
}
heaterMapIter->second.action = *(data + 1);
heaterMapIter->second.active = true;
heaterMapIter->second.replyQueue = commandedBy;
2021-01-23 17:22:40 +01:00
}
else {
2021-01-28 14:55:21 +01:00
sif::error << "HeaterHandler::executeAction: Invalid switchNr" << std::endl;
return INVALID_SWITCH_NR;
2021-01-23 17:22:40 +01:00
}
result = RETURN_OK;
}
return result;
}
void HeaterHandler::sendSwitchCommand(uint8_t switchNr,
ReturnValue_t onOff) const {
ReturnValue_t result;
2021-01-28 14:55:21 +01:00
store_address_t storeAddress;
uint8_t commandData[2];
2021-01-23 17:22:40 +01:00
switch(onOff) {
case PowerSwitchIF::SWITCH_ON:
2021-01-28 14:55:21 +01:00
commandData[0] = switchNr;
commandData[1] = SET_SWITCH_ON;
break;
2021-01-23 17:22:40 +01:00
case PowerSwitchIF::SWITCH_OFF:
2021-01-28 14:55:21 +01:00
commandData[0] = switchNr;
commandData[1] = SET_SWITCH_OFF;
break;
2021-01-23 17:22:40 +01:00
default:
sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request"
<< std::endl;
break;
2021-01-23 17:22:40 +01:00
}
2021-01-28 14:55:21 +01:00
result = IPCStore->addData(&storeAddress, commandData, sizeof(commandData));
2021-01-23 17:22:40 +01:00
if (result == RETURN_OK) {
CommandMessage message;
ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress);
2021-01-23 17:22:40 +01:00
/* Send heater command to own command queue */
result = commandQueue->sendMessage(commandQueue->getId(), &message, 0);
2021-01-23 17:22:40 +01:00
if (result != RETURN_OK) {
sif::debug << "HeaterHandler::sendSwitchCommand: Failed to send switch"
2021-01-23 17:22:40 +01:00
<< "message" << std::endl;
}
}
}
2021-01-28 14:55:21 +01:00
void HeaterHandler::handleActiveCommands(){
2021-01-23 17:22:40 +01:00
HeaterMapIter heaterMapIter = heaterMap.begin();
for (; heaterMapIter != heaterMap.end(); heaterMapIter++) {
if (heaterMapIter->second.active) {
switch(heaterMapIter->second.action) {
2021-01-28 14:55:21 +01:00
case SET_SWITCH_ON:
handleSwitchOnCommand(heaterMapIter);
2021-01-28 14:55:21 +01:00
break;
case SET_SWITCH_OFF:
handleSwitchOffCommand(heaterMapIter);
break;
2021-01-28 14:55:21 +01:00
default:
sif::error << "HeaterHandler::handleActiveCommands: Invalid action commanded"
<< std::endl;
break;
}
2021-01-23 17:22:40 +01:00
}
}
}
void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) {
2021-02-11 08:19:48 +01:00
ReturnValue_t result = RETURN_OK;
switchNr_t switchNr;
/* Check if command waits for main switch being set on and whether the timeout has expired */
if (heaterMapIter->second.waitMainSwitchOn
&& heaterMapIter->second.mainSwitchCountdown.hasTimedOut()) {
2021-02-03 08:09:54 +01:00
//TODO - This requires the initiation of an FDIR procedure
triggerEvent(MAIN_SWITCH_TIMEOUT);
2021-02-11 08:19:48 +01:00
sif::error << "HeaterHandler::handleSwitchOnCommand: Main switch setting on timeout"
<< std::endl;
heaterMapIter->second.active = false;
2021-02-11 08:19:48 +01:00
heaterMapIter->second.waitMainSwitchOn = false;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
2021-03-05 19:31:45 +01:00
actionHelper.finish(false, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, MAIN_SWITCH_SET_TIMEOUT );
2021-02-11 08:19:48 +01:00
}
return;
}
switchNr = heaterMapIter->first;
/* 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);
2021-02-12 12:52:40 +01:00
result = gpioInterface->pullHigh(gpioId);
if (result != RETURN_OK) {
2021-02-14 09:25:40 +01:00
sif::error << "HeaterHandler::handleSwitchOnCommand: Failed to pull gpio with id "
<< gpioId << " high" << std::endl;
triggerEvent(GPIO_PULL_HIGH_FAILED, result);
}
else {
switchStates[switchNr] = ON;
}
}
else {
triggerEvent(SWITCH_ALREADY_ON, switchNr);
}
/* There is no need to send action finish replies if the sender was the
* HeaterHandler itself. */
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
2021-03-05 19:31:45 +01:00
if(result == RETURN_OK) {
actionHelper.finish(true, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
else {
actionHelper.finish(false, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
}
heaterMapIter->second.active = false;
2021-02-11 08:19:48 +01:00
heaterMapIter->second.waitMainSwitchOn = false;
}
else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF
&& heaterMapIter->second.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());
2021-02-11 08:19:48 +01:00
heaterMapIter->second.waitMainSwitchOn = true;
}
else {
sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of"
<< " main line switch" << std::endl;
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
2021-03-05 19:31:45 +01:00
actionHelper.finish(false, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, mainSwitchState);
}
heaterMapIter->second.active = false;
}
}
void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) {
2021-02-11 08:19:48 +01:00
ReturnValue_t result = RETURN_OK;
switchNr_t switchNr = heaterMapIter->first;
2021-02-11 08:19:48 +01:00
/* Check whether switch is already off */
if (checkSwitchState(switchNr)) {
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
2021-02-12 12:52:40 +01:00
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;
2021-02-11 08:19:48 +01:00
/* When all switches are off, also main line switch will be turned off */
if (allSwitchesOff()) {
mainLineSwitcher->sendSwitchCommand(mainLineSwitch, PowerSwitchIF::SWITCH_OFF);
}
}
}
else {
2021-02-11 08:19:48 +01:00
sif::info << "HeaterHandler::handleSwitchOffCommand: Switch already off" << std::endl;
triggerEvent(SWITCH_ALREADY_OFF, switchNr);
}
if (heaterMapIter->second.replyQueue != NO_COMMANDER) {
2021-03-05 19:31:45 +01:00
/* Report back switch command reply if necessary */
if(result == HasReturnvaluesIF::RETURN_OK) {
actionHelper.finish(true, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
else {
actionHelper.finish(false, heaterMapIter->second.replyQueue,
heaterMapIter->second.action, result);
}
}
heaterMapIter->second.active = false;
}
2021-01-28 14:55:21 +01:00
bool HeaterHandler::checkSwitchState(int switchNr) {
return switchStates[switchNr];
}
2021-02-11 08:19:48 +01:00
bool HeaterHandler::allSwitchesOff() {
bool allSwitchesOrd = false;
/* 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];
}
return !allSwitchesOrd;
}
gpioId_t HeaterHandler::getGpioIdFromSwitchNr(int switchNr) {
2021-01-28 14:55:21 +01:00
gpioId_t gpioId = 0xFFFF;
switch(switchNr) {
2021-02-12 14:18:34 +01:00
case heaterSwitches::HEATER_0:
2021-01-28 14:55:21 +01:00
gpioId = gpioIds::HEATER_0;
break;
2021-02-12 14:18:34 +01:00
case heaterSwitches::HEATER_1:
gpioId = gpioIds::HEATER_1;
break;
2021-02-12 15:24:37 +01:00
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;
2021-01-28 14:55:21 +01:00
default:
sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number"
<< std::endl;
break;
}
return gpioId;
}
MessageQueueId_t HeaterHandler::getCommandQueue() const {
return commandQueue->getId();
}
void HeaterHandler::sendFuseOnCommand(uint8_t fuseNr) const {
}
ReturnValue_t HeaterHandler::getSwitchState( uint8_t switchNr ) const {
return 0;
}
ReturnValue_t HeaterHandler::getFuseState( uint8_t fuseNr ) const {
return 0;
}
uint32_t HeaterHandler::getSwitchDelayMs(void) const {
return 0;
}