2020-08-13 20:53:35 +02:00
|
|
|
#include "ActionHelper.h"
|
|
|
|
#include "HasActionsIF.h"
|
2020-11-02 15:51:52 +01:00
|
|
|
|
2020-09-15 16:58:38 +02:00
|
|
|
#include "../ipc/MessageQueueSenderIF.h"
|
2020-08-13 20:53:35 +02:00
|
|
|
#include "../objectmanager/ObjectManagerIF.h"
|
2021-02-08 14:20:36 +01:00
|
|
|
#include "../serviceinterface/ServiceInterface.h"
|
2020-07-16 12:49:53 +02:00
|
|
|
|
2020-10-10 17:04:43 +02:00
|
|
|
ActionHelper::ActionHelper(HasActionsIF* setOwner,
|
|
|
|
MessageQueueIF* useThisQueue) :
|
2021-01-28 11:38:45 +01:00
|
|
|
owner(setOwner), queueToUse(useThisQueue) {
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
ActionHelper::~ActionHelper() {
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
2021-01-28 11:38:45 +01:00
|
|
|
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
|
|
|
ActionId_t currentAction = ActionMessage::getActionId(command);
|
|
|
|
prepareExecution(command->getSender(), currentAction,
|
|
|
|
ActionMessage::getStoreId(command));
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
} else {
|
|
|
|
return CommandMessage::UNKNOWN_COMMAND;
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-13 18:28:26 +02:00
|
|
|
ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
2021-01-28 11:38:45 +01:00
|
|
|
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
|
|
|
|
if (ipcStore == nullptr) {
|
|
|
|
return HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
}
|
|
|
|
if(queueToUse_ != nullptr) {
|
|
|
|
setQueueToUse(queueToUse_);
|
|
|
|
}
|
2018-07-13 18:28:26 +02:00
|
|
|
|
2021-01-28 11:38:45 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2020-10-10 17:04:43 +02:00
|
|
|
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
|
|
|
|
ActionId_t commandId, ReturnValue_t result) {
|
2021-01-28 11:38:45 +01:00
|
|
|
CommandMessage reply;
|
|
|
|
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
|
|
|
|
queueToUse->sendMessage(reportTo, &reply);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2020-10-10 17:04:43 +02:00
|
|
|
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
|
|
|
|
ReturnValue_t result) {
|
2021-01-28 11:38:45 +01:00
|
|
|
CommandMessage reply;
|
|
|
|
ActionMessage::setCompletionReply(&reply, commandId, result);
|
|
|
|
queueToUse->sendMessage(reportTo, &reply);
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2018-07-12 16:29:32 +02:00
|
|
|
void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
|
2021-01-28 11:38:45 +01:00
|
|
|
queueToUse = queue;
|
2018-07-12 16:29:32 +02:00
|
|
|
}
|
|
|
|
|
2020-10-10 17:04:43 +02:00
|
|
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
|
|
|
|
ActionId_t actionId, store_address_t dataAddress) {
|
2021-01-28 11:38:45 +01:00
|
|
|
const uint8_t* dataPtr = NULL;
|
|
|
|
size_t size = 0;
|
|
|
|
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
CommandMessage reply;
|
|
|
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
|
|
|
queueToUse->sendMessage(commandedBy, &reply);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
|
|
|
ipcStore->deleteData(dataAddress);
|
|
|
|
if(result == HasActionsIF::EXECUTION_FINISHED) {
|
|
|
|
CommandMessage reply;
|
|
|
|
ActionMessage::setCompletionReply(&reply, actionId, result);
|
|
|
|
queueToUse->sendMessage(commandedBy, &reply);
|
|
|
|
}
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
CommandMessage reply;
|
|
|
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
|
|
|
queueToUse->sendMessage(commandedBy, &reply);
|
|
|
|
return;
|
|
|
|
}
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
|
|
|
|
2020-07-16 12:49:53 +02:00
|
|
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
2021-01-28 11:38:45 +01:00
|
|
|
ActionId_t replyId, SerializeIF* data, bool hideSender) {
|
|
|
|
CommandMessage reply;
|
|
|
|
store_address_t storeAddress;
|
|
|
|
uint8_t *dataPtr;
|
|
|
|
size_t maxSize = data->getSerializedSize();
|
|
|
|
if (maxSize == 0) {
|
2021-02-08 14:20:36 +01:00
|
|
|
/* No error, there's simply nothing to report. */
|
2021-01-28 11:38:45 +01:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
size_t size = 0;
|
|
|
|
ReturnValue_t result = ipcStore->getFreeElement(&storeAddress, maxSize,
|
|
|
|
&dataPtr);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
2021-02-08 14:20:36 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::warning << "ActionHelper::reportData: Getting free element from IPC store failed!" <<
|
|
|
|
std::endl;
|
|
|
|
#else
|
|
|
|
sif::printWarning("ActionHelper::reportData: Getting free element from IPC "
|
|
|
|
"store failed!\n");
|
|
|
|
#endif
|
2021-01-28 11:38:45 +01:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
result = data->serialize(&dataPtr, &size, maxSize,
|
|
|
|
SerializeIF::Endianness::BIG);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
ipcStore->deleteData(storeAddress);
|
|
|
|
return result;
|
|
|
|
}
|
2021-02-08 14:20:36 +01:00
|
|
|
|
|
|
|
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
|
|
|
success message. True aperiodic replies need to be reported with another dedicated message. */
|
2021-01-28 11:38:45 +01:00
|
|
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
2018-07-12 16:29:32 +02:00
|
|
|
|
2021-02-08 14:20:36 +01:00
|
|
|
/* If the sender needs to be hidden, for example to handle packet
|
|
|
|
as unrequested reply, this will be done here. */
|
2021-01-28 11:38:45 +01:00
|
|
|
if (hideSender) {
|
|
|
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result = queueToUse->sendMessage(reportTo, &reply);
|
|
|
|
}
|
2020-10-12 16:58:04 +02:00
|
|
|
|
2021-01-28 11:38:45 +01:00
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK){
|
|
|
|
ipcStore->deleteData(storeAddress);
|
|
|
|
}
|
|
|
|
return result;
|
2016-06-15 23:48:41 +02:00
|
|
|
}
|
2018-07-13 18:28:26 +02:00
|
|
|
|
|
|
|
void ActionHelper::resetHelper() {
|
|
|
|
}
|
2020-10-12 16:58:04 +02:00
|
|
|
|
|
|
|
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
|
|
|
|
ActionId_t replyId, const uint8_t *data, size_t dataSize,
|
|
|
|
bool hideSender) {
|
|
|
|
CommandMessage reply;
|
|
|
|
store_address_t storeAddress;
|
|
|
|
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
2021-02-08 14:20:36 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
|
|
sif::warning << "ActionHelper::reportData: Adding data to IPC store failed!" << std::endl;
|
|
|
|
#else
|
|
|
|
sif::printWarning("ActionHelper::reportData: Adding data to IPC store failed!\n");
|
|
|
|
#endif
|
2020-10-12 16:58:04 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
|
|
|
ipcStore->deleteData(storeAddress);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-02-08 14:20:36 +01:00
|
|
|
/* We don't need to report the objectId, as we receive REQUESTED data before the completion
|
|
|
|
success message. True aperiodic replies need to be reported with another dedicated message. */
|
2020-10-12 16:58:04 +02:00
|
|
|
ActionMessage::setDataReply(&reply, replyId, storeAddress);
|
|
|
|
|
2021-02-08 14:20:36 +01:00
|
|
|
/* If the sender needs to be hidden, for example to handle packet
|
|
|
|
as unrequested reply, this will be done here. */
|
2020-10-12 16:58:04 +02:00
|
|
|
if (hideSender) {
|
|
|
|
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
result = queueToUse->sendMessage(reportTo, &reply);
|
|
|
|
}
|
|
|
|
|
2021-01-27 14:18:51 +01:00
|
|
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
2020-10-12 16:58:04 +02:00
|
|
|
ipcStore->deleteData(storeAddress);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|