2020-08-13 20:53:35 +02:00
|
|
|
#include "Service8FunctionManagement.h"
|
|
|
|
#include "servicepackets/Service8Packets.h"
|
|
|
|
|
|
|
|
#include "../objectmanager/SystemObjectIF.h"
|
|
|
|
#include "../action/HasActionsIF.h"
|
|
|
|
#include "../devicehandlers/DeviceHandlerIF.h"
|
|
|
|
#include "../serialize/SerializeAdapter.h"
|
|
|
|
#include "../serviceinterface/ServiceInterfaceStream.h"
|
|
|
|
|
2020-11-09 21:33:09 +01:00
|
|
|
Service8FunctionManagement::Service8FunctionManagement(object_id_t objectId,
|
2020-08-13 20:53:35 +02:00
|
|
|
uint16_t apid, uint8_t serviceId, uint8_t numParallelCommands,
|
|
|
|
uint16_t commandTimeoutSeconds):
|
2020-11-09 21:33:09 +01:00
|
|
|
CommandingServiceBase(objectId, apid, serviceId, numParallelCommands,
|
2020-08-13 20:53:35 +02:00
|
|
|
commandTimeoutSeconds) {}
|
|
|
|
|
|
|
|
Service8FunctionManagement::~Service8FunctionManagement() {}
|
|
|
|
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::isValidSubservice(
|
|
|
|
uint8_t subservice) {
|
|
|
|
switch(static_cast<Subservice>(subservice)) {
|
2020-11-09 21:33:09 +01:00
|
|
|
case Subservice::COMMAND_DIRECT_COMMANDING:
|
2020-08-13 20:53:35 +02:00
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
default:
|
|
|
|
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::getMessageQueueAndObject(
|
|
|
|
uint8_t subservice, const uint8_t* tcData, size_t tcDataLen,
|
|
|
|
MessageQueueId_t* id, object_id_t* objectId) {
|
|
|
|
if(tcDataLen < sizeof(object_id_t)) {
|
|
|
|
return CommandingServiceBase::INVALID_TC;
|
|
|
|
}
|
|
|
|
SerializeAdapter::deSerialize(objectId, &tcData,
|
|
|
|
&tcDataLen, SerializeIF::Endianness::BIG);
|
|
|
|
|
|
|
|
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::checkInterfaceAndAcquireMessageQueue(
|
|
|
|
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
|
|
|
// check HasActionIF property of target
|
|
|
|
HasActionsIF* possibleTarget = objectManager->get<HasActionsIF>(*objectId);
|
|
|
|
if(possibleTarget == nullptr){
|
|
|
|
return CommandingServiceBase::INVALID_OBJECT;
|
|
|
|
}
|
|
|
|
*messageQueueToSet = possibleTarget->getCommandQueue();
|
|
|
|
return HasReturnvaluesIF::RETURN_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::prepareCommand(
|
|
|
|
CommandMessage* message, uint8_t subservice, const uint8_t* tcData,
|
|
|
|
size_t tcDataLen, uint32_t* state, object_id_t objectId) {
|
|
|
|
return prepareDirectCommand(dynamic_cast<CommandMessage*>(message),
|
|
|
|
tcData, tcDataLen);
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::prepareDirectCommand(
|
|
|
|
CommandMessage *message, const uint8_t *tcData, size_t tcDataLen) {
|
|
|
|
if(tcDataLen < sizeof(object_id_t) + sizeof(ActionId_t)) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2020-08-13 20:53:35 +02:00
|
|
|
sif::debug << "Service8FunctionManagement::prepareDirectCommand:"
|
|
|
|
<< " TC size smaller thant minimum size of direct command."
|
|
|
|
<< std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2020-08-13 20:53:35 +02:00
|
|
|
return CommandingServiceBase::INVALID_TC;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create direct command instance by extracting data from Telecommand
|
|
|
|
DirectCommand command(tcData, tcDataLen);
|
|
|
|
|
|
|
|
// store additional parameters into the IPC Store
|
|
|
|
store_address_t parameterAddress;
|
|
|
|
ReturnValue_t result = IPCStore->addData(¶meterAddress,
|
|
|
|
command.getParameters(),command.getParametersSize());
|
|
|
|
|
|
|
|
// setCommand expects a Command Message, an Action ID and a store adress
|
|
|
|
// pointing to additional parameters
|
|
|
|
ActionMessage::setCommand(message,command.getActionId(),parameterAddress);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::handleReply(
|
|
|
|
const CommandMessage* reply, Command_t previousCommand,
|
|
|
|
uint32_t* state, CommandMessage* optionalNextCommand,
|
|
|
|
object_id_t objectId, bool* isStep) {
|
|
|
|
Command_t replyId = reply->getCommand();
|
|
|
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
|
|
|
ActionId_t actionId = ActionMessage::getActionId(reply);
|
|
|
|
ReturnValue_t returnCode = ActionMessage::getReturnCode(reply);
|
|
|
|
|
|
|
|
switch(replyId) {
|
|
|
|
case ActionMessage::COMPLETION_SUCCESS: {
|
|
|
|
DirectReply completionReply(objectId, actionId,returnCode);
|
|
|
|
result = CommandingServiceBase::EXECUTION_COMPLETE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ActionMessage::STEP_SUCCESS: {
|
|
|
|
*isStep = true;
|
|
|
|
result = HasReturnvaluesIF::RETURN_OK;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ActionMessage::DATA_REPLY: {
|
2021-01-27 14:18:51 +01:00
|
|
|
/* Multiple data replies are possible, so declare data reply as step */
|
2021-01-27 13:36:18 +01:00
|
|
|
*isStep = true;
|
2020-08-13 20:53:35 +02:00
|
|
|
result = handleDataReply(reply, objectId, actionId);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case ActionMessage::STEP_FAILED:
|
|
|
|
*isStep = true;
|
2021-01-27 14:18:51 +01:00
|
|
|
/* No break, falls through */
|
2020-08-13 20:53:35 +02:00
|
|
|
case ActionMessage::COMPLETION_FAILED:
|
|
|
|
result = ActionMessage::getReturnCode(reply);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
result = INVALID_REPLY;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReturnValue_t Service8FunctionManagement::handleDataReply(
|
|
|
|
const CommandMessage* reply, object_id_t objectId,
|
|
|
|
ActionId_t actionId) {
|
|
|
|
store_address_t storeId = ActionMessage::getStoreId(reply);
|
|
|
|
size_t size = 0;
|
|
|
|
const uint8_t * buffer = nullptr;
|
|
|
|
ReturnValue_t result = IPCStore->getData(storeId, &buffer, &size);
|
|
|
|
if(result != RETURN_OK) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2020-08-13 20:53:35 +02:00
|
|
|
sif::error << "Service 8: Could not retrieve data for data reply"
|
|
|
|
<< std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2020-08-13 20:53:35 +02:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
DataReply dataReply(objectId, actionId, buffer, size);
|
|
|
|
result = sendTmPacket(static_cast<uint8_t>(
|
2020-11-09 21:33:09 +01:00
|
|
|
Subservice::REPLY_DIRECT_COMMANDING_DATA), &dataReply);
|
2020-08-13 20:53:35 +02:00
|
|
|
|
|
|
|
auto deletionResult = IPCStore->deleteData(storeId);
|
|
|
|
if(deletionResult != HasReturnvaluesIF::RETURN_OK) {
|
2021-01-03 14:16:52 +01:00
|
|
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
2020-08-13 20:53:35 +02:00
|
|
|
sif::warning << "Service8FunctionManagement::handleReply: Deletion"
|
|
|
|
<< " of data in pool failed." << std::endl;
|
2021-01-03 13:58:18 +01:00
|
|
|
#endif
|
2020-08-13 20:53:35 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|