2021-01-23 17:22:40 +01:00
|
|
|
#include <mission/devices/HeaterHandler.h>
|
2021-01-28 14:55:21 +01:00
|
|
|
#include <fsfwconfig/devices/powerSwitcherList.h>
|
2021-02-01 11:17:20 +01:00
|
|
|
#include <fsfw/ipc/QueueFactory.h>
|
|
|
|
#include <devices/gpioIds.h>
|
2021-01-28 14:55:21 +01:00
|
|
|
|
2021-02-01 11:17:20 +01:00
|
|
|
HeaterHandler::HeaterHandler(object_id_t setObjectId_, object_id_t gpioDriverId_,
|
|
|
|
CookieIF * gpioCookie_, object_id_t mainLineSwitcherObjectId_, uint8_t mainLineSwitch_) :
|
|
|
|
SystemObject(setObjectId_), gpioDriverId(gpioDriverId_), gpioCookie(gpioCookie_), mainLineSwitcherObjectId(
|
|
|
|
mainLineSwitcherObjectId_), mainLineSwitch(mainLineSwitch_), actionHelper(this,
|
|
|
|
nullptr) {
|
2021-01-28 14:55:21 +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;
|
|
|
|
}
|
2021-02-01 11:17:20 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
|
|
|
gpioInterface = objectManager->get<GpioIF>(gpioDriverId);
|
|
|
|
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-01 11:17:20 +01:00
|
|
|
result = gpioInterface->initialize(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
|
|
|
}
|
|
|
|
|
|
|
|
IPCStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
|
|
|
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) {
|
|
|
|
mainLineSwitcher = objectManager->get<PowerSwitchIF>(mainLineSwitcherObjectId);
|
|
|
|
if (mainLineSwitcher == nullptr) {
|
|
|
|
sif::error << "HeaterHandler::initialize: Main line switcher failed to fetch object"
|
|
|
|
<< "from object ID." << 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;
|
2021-02-01 11:17:20 +01:00
|
|
|
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() {
|
2021-02-01 11:17:20 +01:00
|
|
|
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) {
|
2021-02-01 11:17:20 +01:00
|
|
|
ReturnValue_t result;
|
|
|
|
if (actionId != SWITCH_HEATER) {
|
2021-01-23 17:22:40 +01:00
|
|
|
result = COMMAND_NOT_SUPPORTED;
|
|
|
|
} else {
|
2021-02-01 11:17:20 +01:00
|
|
|
switchNr_t switchNr = *data;
|
|
|
|
HeaterMapIter heaterMapIter = heaterMap.find(switchNr);
|
2021-01-28 14:55:21 +01:00
|
|
|
if (heaterMapIter != heaterMap.end()) {
|
2021-02-01 11:17:20 +01:00
|
|
|
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;
|
2021-02-01 11:17:20 +01:00
|
|
|
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;
|
2021-02-01 11:17:20 +01:00
|
|
|
break;
|
2021-01-23 17:22:40 +01:00
|
|
|
default:
|
|
|
|
sif::error << "HeaterHandler::sendSwitchCommand: Invalid switch request"
|
|
|
|
<< std::endl;
|
2021-02-01 11:17:20 +01:00
|
|
|
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;
|
2021-02-01 11:17:20 +01:00
|
|
|
ActionMessage::setCommand(&message, SWITCH_HEATER, storeAddress);
|
2021-01-23 17:22:40 +01:00
|
|
|
/* Send heater command to own command queue */
|
2021-02-01 11:17:20 +01:00
|
|
|
result = commandQueue->sendMessage(commandQueue->getId(), &message, 0);
|
2021-01-23 17:22:40 +01:00
|
|
|
if (result != RETURN_OK) {
|
2021-02-01 11:17:20 +01:00
|
|
|
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
|
|
|
|
2021-02-01 11:17:20 +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:
|
2021-02-01 11:17:20 +01:00
|
|
|
handleSwitchOnCommand(heaterMapIter);
|
2021-01-28 14:55:21 +01:00
|
|
|
break;
|
|
|
|
case SET_SWITCH_OFF:
|
2021-02-01 11:17:20 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-01 11:17:20 +01:00
|
|
|
void HeaterHandler::handleSwitchOnCommand(HeaterMapIter heaterMapIter) {
|
|
|
|
|
|
|
|
ReturnValue_t result;
|
|
|
|
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
|
2021-02-01 11:17:20 +01:00
|
|
|
triggerEvent(MAIN_SWITCH_TIMEOUT);
|
|
|
|
heaterMapIter->second.active = false;
|
|
|
|
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);
|
|
|
|
result = gpioInterface->pullHigh(gpioId);
|
|
|
|
if (result != RETURN_OK) {
|
|
|
|
sif::error << "HeaterHandler::handleSwitchOffCommand: 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()) {
|
|
|
|
actionHelper.finish(heaterMapIter->second.replyQueue,
|
|
|
|
heaterMapIter->second.action, result);
|
|
|
|
}
|
|
|
|
heaterMapIter->second.active = false;
|
|
|
|
}
|
|
|
|
else if (mainSwitchState == PowerSwitchIF::SWITCH_OFF) {
|
|
|
|
mainLineSwitcher->sendSwitchCommand(mainLineSwitch,
|
|
|
|
PowerSwitchIF::SWITCH_ON);
|
|
|
|
heaterMapIter->second.mainSwitchCountdown.setTimeout(mainLineSwitcher->getSwitchDelayMs());
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
sif::debug << "HeaterHandler::handleActiveCommands: Failed to get state of"
|
|
|
|
<< " main line switch" << std::endl;
|
|
|
|
if (heaterMapIter->second.replyQueue != commandQueue->getId()) {
|
|
|
|
actionHelper.finish(heaterMapIter->second.replyQueue,
|
|
|
|
heaterMapIter->second.action, mainSwitchState);
|
|
|
|
}
|
|
|
|
heaterMapIter->second.active = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void HeaterHandler::handleSwitchOffCommand(HeaterMapIter heaterMapIter) {
|
|
|
|
ReturnValue_t result;
|
|
|
|
switchNr_t switchNr = heaterMapIter->first;
|
|
|
|
if (checkSwitchState(switchNr)) {
|
|
|
|
gpioId_t gpioId = getGpioIdFromSwitchNr(switchNr);
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
triggerEvent(SWITCH_ALREADY_OFF, switchNr);
|
|
|
|
}
|
|
|
|
if (heaterMapIter->second.replyQueue != NO_COMMANDER) {
|
|
|
|
actionHelper.finish(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-01 11:17:20 +01:00
|
|
|
gpioId_t HeaterHandler::getGpioIdFromSwitchNr(int switchNr) {
|
2021-01-28 14:55:21 +01:00
|
|
|
gpioId_t gpioId = 0xFFFF;
|
|
|
|
switch(switchNr) {
|
|
|
|
case heaterSwitches::PAYLOAD_CAMERA:
|
|
|
|
gpioId = gpioIds::HEATER_0;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
sif::error << "HeaterHandler::getGpioIdFromSwitchNr: Unknown heater switch number"
|
|
|
|
<< std::endl;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
return gpioId;
|
|
|
|
}
|
|
|
|
|
2021-02-01 11:17:20 +01:00
|
|
|
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;
|
|
|
|
}
|