add new VerificationReporterIF
fsfw/fsfw/pipeline/pr-development This commit looks good Details

This commit is contained in:
Robin Müller 2022-07-26 13:59:09 +02:00
parent 332e9dbfd5
commit 75c824ec80
No known key found for this signature in database
GPG Key ID: 71B58F8A3CDFA9AC
28 changed files with 486 additions and 254 deletions

View File

@ -33,6 +33,7 @@ enum framework_objects : object_id_t {
TC_STORE = 0x534f0100,
TM_STORE = 0x534f0200,
TIME_STAMPER = 0x53500010,
TC_VERIFICATOR = 0x53500020,
FSFW_OBJECTS_END = 0x53ffffff,
NO_OBJECT = 0xFFFFFFFF

View File

@ -96,13 +96,13 @@ ReturnValue_t CService200ModeCommanding::handleReply(const CommandMessage *reply
ReturnValue_t CService200ModeCommanding::prepareModeReply(const CommandMessage *reply,
object_id_t objectId) {
ModePacket modeReplyPacket(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply));
return tmHelper.sendTmPacket(Subservice::REPLY_MODE_REPLY, modeReplyPacket);
return sendTmPacket(Subservice::REPLY_MODE_REPLY, modeReplyPacket);
}
ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(const CommandMessage *reply,
object_id_t objectId) {
ModePacket wrongModeReply(objectId, ModeMessage::getMode(reply), ModeMessage::getSubmode(reply));
ReturnValue_t result = tmHelper.sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, wrongModeReply);
ReturnValue_t result = sendTmPacket(Subservice::REPLY_WRONG_MODE_REPLY, wrongModeReply);
if (result == RETURN_OK) {
// We want to produce an error here in any case because the mode was not correct
return RETURN_FAILED;
@ -113,8 +113,7 @@ ReturnValue_t CService200ModeCommanding::prepareWrongModeReply(const CommandMess
ReturnValue_t CService200ModeCommanding::prepareCantReachModeReply(const CommandMessage *reply,
object_id_t objectId) {
CantReachModePacket cantReachModePacket(objectId, ModeMessage::getCantReachModeReason(reply));
ReturnValue_t result =
tmHelper.sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, cantReachModePacket);
ReturnValue_t result = sendTmPacket(Subservice::REPLY_CANT_REACH_MODE, cantReachModePacket);
if (result == RETURN_OK) {
// We want to produce an error here in any case because the mode was not reached
return RETURN_FAILED;

View File

@ -102,5 +102,5 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep
auto health = static_cast<uint8_t>(HealthMessage::getHealth(reply));
auto oldHealth = static_cast<uint8_t>(HealthMessage::getOldHealth(reply));
HealthSetReply healthSetReply(health, oldHealth);
return tmHelper.sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply);
}

View File

@ -15,11 +15,19 @@ Service17Test::~Service17Test() = default;
ReturnValue_t Service17Test::handleRequest(uint8_t subservice) {
switch (subservice) {
case Subservice::CONNECTION_TEST: {
return tmHelper.sendTmPacket(Subservice::CONNECTION_TEST_REPORT);
ReturnValue_t result = tmHelper.prepareTmPacket(Subservice::CONNECTION_TEST_REPORT);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
case Subservice::EVENT_TRIGGER_TEST: {
triggerEvent(TEST, 1234, 5678);
return tmHelper.sendTmPacket(Subservice::EVENT_TRIGGER_TEST);
ReturnValue_t result = tmHelper.prepareTmPacket(Subservice::EVENT_TRIGGER_TEST);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;

View File

@ -176,8 +176,7 @@ ReturnValue_t Service20ParameterManagement::handleReply(const CommandMessage* re
ParameterId_t parameterId = ParameterMessage::getParameterId(reply);
ParameterDumpReply parameterReply(objectId, parameterId, parameterData.second.data(),
parameterData.second.size());
tmHelper.sendTmPacket(static_cast<uint8_t>(Subservice::PARAMETER_DUMP_REPLY), parameterReply);
return HasReturnvaluesIF::RETURN_OK;
return sendTmPacket(static_cast<uint8_t>(Subservice::PARAMETER_DUMP_REPLY), parameterReply);
}
default:
return CommandingServiceBase::INVALID_REPLY;

View File

@ -148,7 +148,11 @@ void Service2DeviceAccess::sendWiretappingTm(CommandMessage* reply, uint8_t subs
// Init our dummy packet and correct endianness of object ID before
// sending it back.
WiretappingPacket tmPacket(DeviceHandlerMessage::getDeviceObjectId(reply), data);
tmHelper.sendTmPacket(subservice, tmPacket.objectId, tmPacket.data, size);
result = sendTmPacket(subservice, tmPacket.objectId, tmPacket.data, size);
if (result != retval::OK) {
// TODO: Warning
return;
}
}
MessageQueueId_t Service2DeviceAccess::getDeviceQueue() { return commandQueue->getId(); }

View File

@ -290,8 +290,7 @@ ReturnValue_t Service3Housekeeping::generateHkReply(const CommandMessage* hkMess
}
HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size());
return tmHelper.sendTmPacket(static_cast<uint8_t>(subserviceId), hkPacket.hkData,
hkPacket.hkSize);
return sendTmPacket(static_cast<uint8_t>(subserviceId), hkPacket.hkData, hkPacket.hkSize);
}
sid_t Service3Housekeeping::buildSid(object_id_t objectId, const uint8_t** tcData,

View File

@ -138,8 +138,7 @@ ReturnValue_t Service8FunctionManagement::handleDataReply(const CommandMessage*
return result;
}
DataReply dataReply(objectId, actionId, buffer, size);
result = tmHelper.sendTmPacket(static_cast<uint8_t>(Subservice::REPLY_DIRECT_COMMANDING_DATA),
dataReply);
result = sendTmPacket(static_cast<uint8_t>(Subservice::REPLY_DIRECT_COMMANDING_DATA), dataReply);
auto deletionResult = ipcStore->deleteData(storeId);
if (deletionResult != HasReturnvaluesIF::RETURN_OK) {

6
src/fsfw/retval.h Normal file
View File

@ -0,0 +1,6 @@
#ifndef FSFW_RETVAL_H
#define FSFW_RETVAL_H
#include "fsfw/returnvalues/HasReturnvaluesIF.h"
#endif // FSFW_RETVAL_H

View File

@ -12,7 +12,6 @@ PusDistributor::PusDistributor(StorageManagerIF* store_, uint16_t setApid, objec
: TcDistributor(setObjectId),
store(store_),
checker(setApid, ccsds::PacketType::TC),
verifyChannel(),
tcStatus(RETURN_FAILED),
packetSource(setPacketSource) {}
@ -120,13 +119,14 @@ ReturnValue_t PusDistributor::callbackAfterSending(ReturnValue_t queueStatus) {
tcStatus = queueStatus;
}
if (tcStatus != RETURN_OK) {
this->verifyChannel.sendFailureReport(tcverif::ACCEPTANCE_FAILURE, &reader, tcStatus);
verifyChannel->sendFailureReport(
VerifFailureParams(tcverif::ACCEPTANCE_FAILURE, reader, tcStatus));
// A failed packet is deleted immediately after reporting,
// otherwise it will block memory.
store->deleteData(currentMessage.getStorageId());
return RETURN_FAILED;
} else {
this->verifyChannel.sendSuccessReport(tcverif::ACCEPTANCE_SUCCESS, &reader);
verifyChannel->sendSuccessReport(VerifSuccessParams(tcverif::ACCEPTANCE_SUCCESS, reader));
return RETURN_OK;
}
}

View File

@ -48,7 +48,7 @@ class PusDistributor : public TcDistributor, public PUSDistributorIF, public Acc
* With this class, verification messages are sent to the
* TC Verification service.
*/
VerificationReporter verifyChannel;
VerificationReporterIF* verifyChannel = nullptr;
/**
* The currently handled packet is stored here.
*/

View File

@ -1,11 +1,11 @@
#ifndef FSFW_TMTCSERVICES_ACCEPTSVERIFICATIONMESSAGEIF_H_
#define FSFW_TMTCSERVICES_ACCEPTSVERIFICATIONMESSAGEIF_H_
#include "../ipc/MessageQueueSenderIF.h"
#include "fsfw/ipc/MessageQueueSenderIF.h"
class AcceptsVerifyMessageIF {
public:
virtual ~AcceptsVerifyMessageIF() {}
virtual ~AcceptsVerifyMessageIF() = default;
virtual MessageQueueId_t getVerificationQueue() = 0;
};

View File

@ -15,13 +15,15 @@ object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT
CommandingServiceBase::CommandingServiceBase(object_id_t setObjectId, uint16_t apid,
uint8_t service, uint8_t numberOfParallelCommands,
uint16_t commandTimeoutSeconds, size_t queueDepth)
uint16_t commandTimeoutSeconds, size_t queueDepth,
VerificationReporterIF* verificationReporter)
: SystemObject(setObjectId),
apid(apid),
service(service),
timeoutSeconds(commandTimeoutSeconds),
tmStoreHelper(apid),
tmHelper(service, tmStoreHelper, tmSendHelper),
verificationReporter(verificationReporter),
commandMap(numberOfParallelCommands) {
commandQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
requestQueue = QueueFactory::instance()->createMessageQueue(queueDepth);
@ -105,12 +107,19 @@ ReturnValue_t CommandingServiceBase::initialize() {
tmSendHelper.setInternalErrorReporter(errReporter);
}
}
if (verificationReporter == nullptr) {
verificationReporter =
ObjectManager::instance()->get<VerificationReporterIF>(objects::TC_VERIFICATOR);
if (verificationReporter == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
return RETURN_OK;
}
void CommandingServiceBase::handleCommandQueue() {
CommandMessage reply;
ReturnValue_t result = RETURN_FAILED;
ReturnValue_t result;
while (true) {
result = commandQueue->receiveMessage(&reply);
if (result == HasReturnvaluesIF::RETURN_OK) {
@ -175,16 +184,14 @@ void CommandingServiceBase::handleCommandMessage(CommandMessage* reply) {
break;
default:
if (isStep) {
verificationReporter.sendFailureReport(
tcverif::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, result, ++iter->second.step, failureParameter1,
failureParameter2);
prepareVerificationFailureWithFullInfo(tcverif::PROGRESS_FAILURE, iter->second.tcInfo,
result, true);
failParams.step = ++iter->second.step;
} else {
verificationReporter.sendFailureReport(
tcverif::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags,
iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, result, 0,
failureParameter1, failureParameter2);
prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo,
result, true);
}
verificationReporter->sendFailureReport(failParams);
failureParameter1 = 0;
failureParameter2 = 0;
checkAndExecuteFifo(iter);
@ -207,28 +214,26 @@ void CommandingServiceBase::handleReplyHandlerResult(ReturnValue_t result, Comma
if (sendResult == RETURN_OK) {
if (isStep and result != NO_STEP_MESSAGE) {
verificationReporter.sendSuccessReport(
tcverif::PROGRESS_SUCCESS, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, ++iter->second.step);
prepareVerificationSuccessWithFullInfo(tcverif::PROGRESS_SUCCESS, iter->second.tcInfo);
successParams.step = ++iter->second.step;
verificationReporter->sendSuccessReport(successParams);
} else {
verificationReporter.sendSuccessReport(
tcverif::COMPLETION_SUCCESS, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, 0);
prepareVerificationSuccessWithFullInfo(tcverif::COMPLETION_SUCCESS, iter->second.tcInfo);
verificationReporter->sendSuccessReport(successParams);
checkAndExecuteFifo(iter);
}
} else {
if (isStep) {
prepareVerificationFailureWithFullInfo(tcverif::PROGRESS_FAILURE, iter->second.tcInfo, result,
true);
failParams.step = ++iter->second.step;
nextCommand->clearCommandMessage();
verificationReporter.sendFailureReport(
tcverif::PROGRESS_FAILURE, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, sendResult, ++iter->second.step, failureParameter1,
failureParameter2);
verificationReporter->sendFailureReport(failParams);
} else {
prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo,
result, true);
nextCommand->clearCommandMessage();
verificationReporter.sendFailureReport(
tcverif::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, sendResult, 0, failureParameter1,
failureParameter2);
verificationReporter->sendFailureReport(failParams);
}
failureParameter1 = 0;
failureParameter2 = 0;
@ -247,19 +252,19 @@ void CommandingServiceBase::handleRequestQueue() {
result = setUpTcReader(message.getStorageId());
if (result != HasReturnvaluesIF::RETURN_OK) {
// TODO: Warning?
rejectPacket(tcverif::START_FAILURE, address, &tcReader, result);
rejectPacket(tcverif::START_FAILURE, address, result);
continue;
}
if ((tcReader.getSubService() == 0) or
(isValidSubservice(tcReader.getSubService()) != RETURN_OK)) {
rejectPacket(tcverif::START_FAILURE, address, &tcReader, INVALID_SUBSERVICE);
rejectPacket(tcverif::START_FAILURE, address, INVALID_SUBSERVICE);
continue;
}
result = getMessageQueueAndObject(tcReader.getSubService(), tcReader.getUserData(),
tcReader.getUserDataLen(), &queue, &objectId);
if (result != HasReturnvaluesIF::RETURN_OK) {
rejectPacket(tcverif::START_FAILURE, address, &tcReader, result);
rejectPacket(tcverif::START_FAILURE, address, result);
continue;
}
@ -270,14 +275,14 @@ void CommandingServiceBase::handleRequestQueue() {
if (iter != commandMap.end()) {
result = iter->second.fifo.insert(address);
if (result != RETURN_OK) {
rejectPacket(tcverif::START_FAILURE, address, &tcReader, OBJECT_BUSY);
rejectPacket(tcverif::START_FAILURE, address, OBJECT_BUSY);
}
} else {
CommandInfo newInfo; // Info will be set by startExecution if neccessary
newInfo.objectId = objectId;
result = commandMap.insert(queue, newInfo, &iter);
if (result != RETURN_OK) {
rejectPacket(tcverif::START_FAILURE, address, &tcReader, BUSY);
rejectPacket(tcverif::START_FAILURE, address, BUSY);
} else {
startExecution(address, iter);
}
@ -287,24 +292,37 @@ void CommandingServiceBase::handleRequestQueue() {
ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, const uint8_t* sourceData,
size_t sourceDataLen) {
return tmHelper.sendTmPacket(subservice, sourceData, sourceDataLen);
ReturnValue_t result = tmHelper.prepareTmPacket(subservice, sourceData, sourceDataLen);
if (result != retval::OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, object_id_t objectId,
const uint8_t* data, size_t dataLen) {
return tmHelper.sendTmPacket(subservice, objectId, data, dataLen);
telemetry::DataWithObjectIdPrefix dataWithObjId(objectId, data, dataLen);
ReturnValue_t result = tmHelper.prepareTmPacket(subservice, dataWithObjId);
if (result != retval::OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
ReturnValue_t CommandingServiceBase::sendTmPacket(uint8_t subservice, SerializeIF& sourceData) {
return tmHelper.sendTmPacket(subservice, sourceData);
ReturnValue_t result = tmHelper.prepareTmPacket(subservice, sourceData);
if (result != retval::OK) {
return result;
}
return tmHelper.storeAndSendTmPacket();
}
void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIter iter) {
ReturnValue_t result = RETURN_OK;
void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIter& iter) {
CommandMessage command;
iter->second.subservice = tcReader.getSubService();
result = prepareCommand(&command, iter->second.subservice, tcReader.getUserData(),
tcReader.getUserDataLen(), &iter->second.state, iter->second.objectId);
ReturnValue_t result =
prepareCommand(&command, iter->second.subservice, tcReader.getUserData(),
tcReader.getUserDataLen(), &iter->second.state, iter->second.objectId);
ReturnValue_t sendResult = RETURN_OK;
switch (result) {
@ -320,10 +338,10 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt
iter->second.tcInfo.ackFlags = tcReader.getAcknowledgeFlags();
iter->second.tcInfo.tcPacketId = tcReader.getPacketIdRaw();
iter->second.tcInfo.tcSequenceControl = tcReader.getPacketSeqCtrlRaw();
acceptPacket(tcverif::START_SUCCESS, storeId, &tcReader);
acceptPacket(tcverif::START_SUCCESS, storeId);
} else {
command.clearCommandMessage();
rejectPacket(tcverif::START_FAILURE, storeId, &tcReader, sendResult);
rejectPacket(tcverif::START_FAILURE, storeId, sendResult);
checkAndExecuteFifo(iter);
}
break;
@ -333,31 +351,31 @@ void CommandingServiceBase::startExecution(store_address_t storeId, CommandMapIt
sendResult = commandQueue->sendMessage(iter.value->first, &command);
}
if (sendResult == RETURN_OK) {
verificationReporter.sendSuccessReport(tcverif::START_SUCCESS, &tcReader);
acceptPacket(tcverif::COMPLETION_SUCCESS, storeId, &tcReader);
verificationReporter->sendSuccessReport(
VerifSuccessParams(tcverif::START_SUCCESS, tcReader));
acceptPacket(tcverif::COMPLETION_SUCCESS, storeId);
checkAndExecuteFifo(iter);
} else {
command.clearCommandMessage();
rejectPacket(tcverif::START_FAILURE, storeId, &tcReader, sendResult);
rejectPacket(tcverif::START_FAILURE, storeId, sendResult);
checkAndExecuteFifo(iter);
}
break;
default:
rejectPacket(tcverif::START_FAILURE, storeId, &tcReader, result);
rejectPacket(tcverif::START_FAILURE, storeId, result);
checkAndExecuteFifo(iter);
break;
}
}
void CommandingServiceBase::rejectPacket(uint8_t reportId, store_address_t tcStoreId,
PusTcReader* correspondingTc, ReturnValue_t errorCode) {
verificationReporter.sendFailureReport(reportId, correspondingTc, errorCode);
ReturnValue_t errorCode) {
verificationReporter->sendFailureReport(VerifFailureParams(reportId, tcReader, errorCode));
tcStore->deleteData(tcStoreId);
}
void CommandingServiceBase::acceptPacket(uint8_t reportId, store_address_t tcStoreId,
PusTcReader* packet) {
verificationReporter.sendSuccessReport(reportId, packet);
void CommandingServiceBase::acceptPacket(uint8_t reportId, store_address_t tcStoreId) {
verificationReporter->sendSuccessReport(VerifSuccessParams(reportId, tcReader));
tcStore->deleteData(tcStoreId);
}
@ -371,7 +389,7 @@ void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter& iter) {
startExecution(address, iter);
} else {
// TODO: Warning?
rejectPacket(tcverif::START_FAILURE, address, &tcReader, result);
rejectPacket(tcverif::START_FAILURE, address, result);
}
}
}
@ -390,9 +408,9 @@ void CommandingServiceBase::checkTimeout() {
CommandMapIter iter;
for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) {
if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {
verificationReporter.sendFailureReport(
tcverif::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, iter->second.tcInfo.tcPacketId,
iter->second.tcInfo.tcSequenceControl, TIMEOUT);
prepareVerificationFailureWithFullInfo(tcverif::COMPLETION_FAILURE, iter->second.tcInfo,
TIMEOUT, false);
verificationReporter->sendFailureReport(failParams);
checkAndExecuteFifo(iter);
}
}
@ -406,3 +424,25 @@ void CommandingServiceBase::setCustomTmStore(StorageManagerIF& store) {
ReturnValue_t CommandingServiceBase::setUpTcReader(store_address_t storeId) {
return tc::prepareTcReader(tcStore, storeId, tcReader);
}
void CommandingServiceBase::prepareVerificationFailureWithFullInfo(uint8_t reportId,
CommandInfo::TcInfo& tcInfo,
ReturnValue_t errorCode,
bool setCachedFailParams) {
failParams.reportId = reportId;
failParams.tcPacketId = tcInfo.tcPacketId;
failParams.tcPsc = tcInfo.tcSequenceControl;
failParams.ackFlags = tcInfo.ackFlags;
failParams.errorCode = errorCode;
if (setCachedFailParams) {
failParams.errorParam1 = failureParameter1;
failParams.errorParam2 = failureParameter2;
}
}
void CommandingServiceBase::prepareVerificationSuccessWithFullInfo(
uint8_t reportId, CommandingServiceBase::CommandInfo::TcInfo& tcInfo) {
failParams.reportId = reportId;
failParams.tcPacketId = tcInfo.tcPacketId;
failParams.tcPsc = tcInfo.tcSequenceControl;
failParams.ackFlags = tcInfo.ackFlags;
}

View File

@ -68,7 +68,7 @@ class CommandingServiceBase : public SystemObject,
*/
CommandingServiceBase(object_id_t setObjectId, uint16_t apid, uint8_t service,
uint8_t numberOfParallelCommands, uint16_t commandTimeoutSeconds,
size_t queueDepth = 20);
size_t queueDepth = 20, VerificationReporterIF* reporter = nullptr);
~CommandingServiceBase() override;
void setCustomTmStore(StorageManagerIF& store);
@ -218,7 +218,7 @@ class CommandingServiceBase : public SystemObject,
virtual void doPeriodicOperation();
struct CommandInfo : public SerializeIF {
struct tcInfo {
struct TcInfo {
uint8_t ackFlags;
uint16_t tcPacketId;
uint16_t tcSequenceControl;
@ -263,7 +263,7 @@ class CommandingServiceBase : public SystemObject,
MessageQueueIF* commandQueue = nullptr;
MessageQueueIF* requestQueue = nullptr;
VerificationReporter verificationReporter;
VerificationReporterIF* verificationReporter;
InternalErrorReporterIF* errReporter = nullptr;
@ -284,19 +284,19 @@ class CommandingServiceBase : public SystemObject,
*/
PeriodicTaskIF* executingTask = nullptr;
[[deprecated("Use function with same name provided by tmHelper")]] ReturnValue_t sendTmPacket(
uint8_t subservice, const uint8_t* sourceData, size_t sourceDataLen);
[[deprecated("Use function with same name provided by tmHelper")]] ReturnValue_t sendTmPacket(
uint8_t subservice, object_id_t objectId, const uint8_t* data, size_t dataLen);
[[deprecated("Use function with same name provided by tmHelper")]] ReturnValue_t sendTmPacket(
uint8_t subservice, SerializeIF& sourceData);
ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t* sourceData, size_t sourceDataLen);
ReturnValue_t sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t* data,
size_t dataLen);
ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF& sourceData);
void checkAndExecuteFifo(CommandMapIter& iter);
VerifFailureParams failParams;
VerifSuccessParams successParams;
private:
/**
* This method handles internal execution of a command,
* once it has been started by @sa{startExecution()} in the request
* once it has been started by @startExecution in the request
* queue handler.
* It handles replies generated by the devices and relayed by the specific
* service implementation. This means that it determines further course of
@ -316,26 +316,28 @@ class CommandingServiceBase : public SystemObject,
* @brief Handler function for request queue
* @details
* Sequence of request queue handling:
* isValidSubservice -> getMessageQueueAndObject -> startExecution
* @isValidSubservice -> @getMessageQueueAndObject -> @startExecution
* Generates a Start Success Reports TM[1,3] in subfunction
* @sa{startExecution()} or a Start Failure Report TM[1,4] by using the
* @startExecution or a Start Failure Report TM[1,4] by using the
* TC Verification Service.
*/
void handleRequestQueue();
ReturnValue_t setUpTcReader(store_address_t storeId);
void rejectPacket(uint8_t reportId, store_address_t tcStoreId, PusTcReader* tcPacket,
ReturnValue_t errorCode);
void rejectPacket(uint8_t reportId, store_address_t tcStoreId, ReturnValue_t errorCode);
void acceptPacket(uint8_t reportId, store_address_t tcStoreId, PusTcReader* tcPacket);
void acceptPacket(uint8_t reportId, store_address_t tcStoreId);
void startExecution(store_address_t storeId, CommandMapIter iter);
void startExecution(store_address_t storeId, CommandMapIter& iter);
void handleCommandMessage(CommandMessage* reply);
void handleReplyHandlerResult(ReturnValue_t result, CommandMapIter iter,
CommandMessage* nextCommand, CommandMessage* reply, bool& isStep);
void prepareVerificationFailureWithFullInfo(uint8_t reportId, CommandInfo::TcInfo& tcInfo,
ReturnValue_t errorCode, bool setCachedFailParams);
void prepareVerificationSuccessWithFullInfo(uint8_t reportId, CommandInfo::TcInfo& tcInfo);
void checkTimeout();
};

View File

@ -12,8 +12,12 @@
object_id_t PusServiceBase::packetSource = 0;
object_id_t PusServiceBase::packetDestination = 0;
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId)
: SystemObject(setObjectId), apid(setApid), serviceId(setServiceId) {
PusServiceBase::PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId,
VerificationReporterIF* verifyReporter)
: SystemObject(setObjectId),
apid(setApid),
serviceId(setServiceId),
verifyReporter(verifyReporter) {
requestQueue = QueueFactory::instance()->createMessageQueue(PUS_SERVICE_MAX_RECEPTION);
}
@ -65,16 +69,21 @@ void PusServiceBase::handleRequestQueue() {
}
result = tc::prepareTcReader(tcStore, message.getStorageId(), currentPacket);
if (result != HasReturnvaluesIF::RETURN_OK) {
this->verifyReporter.sendFailureReport(tcverif::START_FAILURE, &this->currentPacket, result,
0, errorParameter1, errorParameter2);
auto params = VerifFailureParams(tcverif::START_FAILURE, currentPacket, result);
params.errorParam1 = errorParameter1;
params.errorParam2 = errorParameter2;
verifyReporter->sendFailureReport(params);
continue;
}
result = this->handleRequest(currentPacket.getSubService());
result = handleRequest(currentPacket.getSubService());
if (result == RETURN_OK) {
this->verifyReporter.sendSuccessReport(tcverif::COMPLETION_SUCCESS, &this->currentPacket);
verifyReporter->sendSuccessReport(
VerifSuccessParams(tcverif::COMPLETION_SUCCESS, currentPacket));
} else {
this->verifyReporter.sendFailureReport(tcverif::COMPLETION_FAILURE, &this->currentPacket,
result, 0, errorParameter1, errorParameter2);
auto params = VerifFailureParams(tcverif::COMPLETION_FAILURE, currentPacket, result);
params.errorParam1 = errorParameter1;
params.errorParam2 = errorParameter2;
verifyReporter->sendFailureReport(params);
}
tcStore->deleteData(message.getStorageId());
errorParameter1 = 0;
@ -109,6 +118,13 @@ ReturnValue_t PusServiceBase::initialize() {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
if (verifyReporter == nullptr) {
verifyReporter =
ObjectManager::instance()->get<VerificationReporterIF>(objects::TC_VERIFICATOR);
if (verifyReporter == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
@ -145,3 +161,7 @@ void PusServiceBase::initializeTmSendHelper(TmSendHelper& tmSendHelper) {
void PusServiceBase::initializeTmStoreHelper(TmStoreHelper& tmStoreHelper) const {
tmStoreHelper.setApid(apid);
}
void PusServiceBase::setVerificationReporter(VerificationReporterIF* reporter) {
verifyReporter = reporter;
}

View File

@ -53,18 +53,33 @@ class PusServiceBase : public ExecutableObjectIF,
* @param setServiceId
* The Service Identifier as specified in ECSS PUS.
*/
PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId);
PusServiceBase(object_id_t setObjectId, uint16_t setApid, uint8_t setServiceId,
VerificationReporterIF* reporter = nullptr);
/**
* The destructor is empty.
*/
~PusServiceBase() override;
void setCustomTcStore(StorageManagerIF* tcStore);
void setVerificationReporter(VerificationReporterIF* reporter);
void setCustomErrorReporter(InternalErrorReporterIF* errReporter);
/**
* Helper methods if the implementing class wants to send telemetry
* @param tmSendHelper
*/
void initializeTmSendHelper(TmSendHelper& tmSendHelper);
/**
* Helper methods if the implementing class wants to store telemetry
* @param tmSendHelper
*/
void initializeTmStoreHelper(TmStoreHelper& tmStoreHelper) const;
/**
* Helper methods if the implementing class wants to both send and store telemetry
* @param tmSendHelper
*/
void initializeTmHelpers(TmSendHelper& tmSendHelper, TmStoreHelper& tmStoreHelper);
/**
* @brief The handleRequest method shall handle any kind of Telecommand
* Request immediately.
@ -146,7 +161,7 @@ class PusServiceBase : public ExecutableObjectIF,
* An instance of the VerificationReporter class, that simplifies
* sending any kind of verification message to the TC Verification Service.
*/
VerificationReporter verifyReporter;
VerificationReporterIF* verifyReporter;
/**
* The current Telecommand to be processed.
@ -159,6 +174,7 @@ class PusServiceBase : public ExecutableObjectIF,
static object_id_t packetSource;
static object_id_t packetDestination;
VerifSuccessParams successParams;
private:
/**

View File

@ -24,29 +24,36 @@ ReturnValue_t TmStoreAndSendWrapper::storeAndSendTmPacket() {
return result;
}
ReturnValue_t TmStoreAndSendWrapper::sendTmPacket(uint8_t subservice, const uint8_t* sourceData,
size_t sourceDataLen) {
storeHelper.preparePacket(defaultService, subservice, sendCounter);
storeHelper.setSourceDataRaw(sourceData, sourceDataLen);
return storeAndSendTmPacket();
ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice, const uint8_t* sourceData,
size_t sourceDataLen) {
ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return storeHelper.setSourceDataRaw(sourceData, sourceDataLen);
}
ReturnValue_t TmStoreAndSendWrapper::sendTmPacket(uint8_t subservice, object_id_t objectId,
const uint8_t* data, size_t dataLen) {
telemetry::DataWithObjectIdPrefix dataWithObjId(objectId, data, dataLen);
storeHelper.preparePacket(defaultService, subservice, sendCounter);
storeHelper.setSourceDataSerializable(dataWithObjId);
return storeAndSendTmPacket();
ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(
uint8_t subservice, telemetry::DataWithObjectIdPrefix& dataWithObjectId) {
ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return storeHelper.setSourceDataSerializable(dataWithObjectId);
}
ReturnValue_t TmStoreAndSendWrapper::sendTmPacket(uint8_t subservice, SerializeIF& sourceData) {
storeHelper.preparePacket(defaultService, subservice, sendCounter);
storeHelper.setSourceDataSerializable(sourceData);
return storeAndSendTmPacket();
ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice, SerializeIF& sourceData) {
ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return storeHelper.setSourceDataSerializable(sourceData);
}
ReturnValue_t TmStoreAndSendWrapper::sendTmPacket(uint8_t subservice) {
storeHelper.preparePacket(defaultService, subservice, sendCounter);
storeHelper.setSourceDataRaw(nullptr, 0);
return storeAndSendTmPacket();
ReturnValue_t TmStoreAndSendWrapper::prepareTmPacket(uint8_t subservice) {
ReturnValue_t result = storeHelper.preparePacket(defaultService, subservice, sendCounter);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return storeHelper.setSourceDataRaw(nullptr, 0);
}

View File

@ -3,6 +3,7 @@
#include "TmSendHelper.h"
#include "TmStoreHelper.h"
#include "tmHelpers.h"
/**
* Wrapper class intended to help with PUS TM handling. This wrapper class also caches the current
@ -12,37 +13,41 @@ class TmStoreAndSendWrapper {
public:
TmStoreAndSendWrapper(uint8_t defaultService, TmStoreHelper& storeHelper,
TmSendHelper& sendHelper);
ReturnValue_t storeAndSendTmPacket();
ReturnValue_t sendTmPacket(uint8_t subservice);
/**
* @brief Send TM data from pointer to data.
* If a header is supplied it is added before data
* Prepares a TM packet with the given parameters. It will also set the default service.
* @param subservice
* @return
*/
ReturnValue_t prepareTmPacket(uint8_t subservice);
/**
* Prepares a TM packet with the given parameters. It will also set the default service.
* @param subservice Number of subservice
* @param sourceData Custom source data
* @param sourceDataLen Lenght of data in the Packet
*/
ReturnValue_t sendTmPacket(uint8_t subservice, const uint8_t* sourceData, size_t sourceDataLen);
ReturnValue_t prepareTmPacket(uint8_t subservice, const uint8_t* sourceData,
size_t sourceDataLen);
/**
* @brief To send TM packets of objects that still need to be serialized
* and consist of an object ID with appended data.
* Prepares a TM packet with the given parameters. It will also set the default service.
* @param subservice Number of subservice
* @param objectId ObjectId is placed before data
* @param data Data to append to the packet
* @param dataLen Length of Data
*/
ReturnValue_t sendTmPacket(uint8_t subservice, object_id_t objectId, const uint8_t* data,
size_t dataLen);
ReturnValue_t prepareTmPacket(uint8_t subservice,
telemetry::DataWithObjectIdPrefix& dataWithObjectId);
/**
* @brief To send packets which are contained inside a class implementing
* SerializeIF.
* Prepares a TM packet with the given parameters. It will also set the default service.
* @param subservice Number of subservice
* @param content This is a pointer to the serialized packet
* @param header Serialize IF header which will be placed before content
*/
ReturnValue_t sendTmPacket(uint8_t subservice, SerializeIF& sourceData);
ReturnValue_t prepareTmPacket(uint8_t subservice, SerializeIF& sourceData);
ReturnValue_t storeAndSendTmPacket();
bool incrementSendCounter = true;
TmStoreHelper& storeHelper;

View File

@ -1,29 +1,25 @@
#include "fsfw/tmtcservices/VerificationReporter.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/objectmanager/frameworkObjects.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/tmtcservices/AcceptsVerifyMessageIF.h"
#include "fsfw/tmtcservices/PusVerificationReport.h"
object_id_t VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
VerificationReporter::VerificationReporter() : acknowledgeQueue(MessageQueueIF::NO_QUEUE) {}
VerificationReporter::VerificationReporter(AcceptsVerifyMessageIF* receiver, object_id_t objectId)
: SystemObject(objectId) {
if (receiver != nullptr) {
acknowledgeQueue = receiver->getVerificationQueue();
}
}
VerificationReporter::~VerificationReporter() = default;
void VerificationReporter::sendSuccessReport(uint8_t set_report_id, PusTcReader* correspondingTc,
uint8_t set_step) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
if (correspondingTc == nullptr) {
return;
}
PusVerificationMessage message(set_report_id, correspondingTc->getAcknowledgeFlags(),
correspondingTc->getPacketIdRaw(),
correspondingTc->getPacketSeqCtrlRaw(), 0, set_step);
void VerificationReporter::setReceiver(AcceptsVerifyMessageIF& receiver) {
acknowledgeQueue = receiver.getVerificationQueue();
}
ReturnValue_t VerificationReporter::sendFailureReport(VerifFailureParams params) {
PusVerificationMessage message(params.reportId, params.ackFlags, params.tcPacketId, params.tcPsc,
params.errorCode, params.step, params.errorParam1,
params.errorParam2);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
if (status != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -31,16 +27,12 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id, PusTcReader*
<< "to queue. Code: " << std::hex << status << std::dec << std::endl;
#endif
}
return status;
}
void VerificationReporter::sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags,
uint16_t tcPacketId, uint16_t tcSequenceControl,
uint8_t set_step) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(set_report_id, ackFlags, tcPacketId, tcSequenceControl, 0,
set_step);
ReturnValue_t VerificationReporter::sendSuccessReport(VerifSuccessParams params) {
PusVerificationMessage message(params.reportId, params.ackFlags, params.tcPacketId, params.tcPsc,
retval::OK, params.step);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
if (status != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -48,64 +40,5 @@ void VerificationReporter::sendSuccessReport(uint8_t set_report_id, uint8_t ackF
<< "to queue. Code: " << std::hex << status << std::dec << std::endl;
#endif
}
}
void VerificationReporter::sendFailureReport(uint8_t report_id, PusTcReader* correspondingTc,
ReturnValue_t errorCode, uint8_t step,
uint32_t parameter1, uint32_t parameter2) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
if (correspondingTc == nullptr) {
return;
}
PusVerificationMessage message(
report_id, correspondingTc->getAcknowledgeFlags(), correspondingTc->getPacketIdRaw(),
correspondingTc->getPacketSeqCtrlRaw(), errorCode, step, parameter1, parameter2);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
if (status != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << "0x" << status << std::dec << std::endl;
#endif
}
}
void VerificationReporter::sendFailureReport(uint8_t report_id, uint8_t ackFlags,
uint16_t tcPacketId, uint16_t tcSequenceControl,
ReturnValue_t error_code, uint8_t step,
uint32_t parameter1, uint32_t parameter2) {
if (acknowledgeQueue == MessageQueueIF::NO_QUEUE) {
this->initialize();
}
PusVerificationMessage message(report_id, ackFlags, tcPacketId, tcSequenceControl, error_code,
step, parameter1, parameter2);
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, &message);
if (status != HasReturnvaluesIF::RETURN_OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << "0x" << status << std::dec << std::endl;
#endif
}
}
void VerificationReporter::initialize() {
if (messageReceiver == objects::NO_OBJECT) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "VerificationReporter::initialize: Verification message"
" receiver object ID not set yet in Factory!"
<< std::endl;
#endif
return;
}
auto* temp = ObjectManager::instance()->get<AcceptsVerifyMessageIF>(messageReceiver);
if (temp == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "VerificationReporter::initialize: Message "
<< "receiver invalid. Make sure it is set up properly and "
<< "implementsAcceptsVerifyMessageIF" << std::endl;
#endif
return;
}
this->acknowledgeQueue = temp->getVerificationQueue();
return status;
}

View File

@ -2,12 +2,11 @@
#define FSFW_TMTCSERVICES_VERIFICATIONREPORTER_H_
#include "PusVerificationReport.h"
#include "VerificationReporterIF.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "fsfw/tmtcpacket/pus/tc/PusTcCreator.h"
namespace Factory {
void setStaticFrameworkObjectIds();
}
#include "fsfw/tmtcservices/AcceptsVerifyMessageIF.h"
/**
* @brief This helper object is used to forward verification messages
@ -20,30 +19,21 @@ void setStaticFrameworkObjectIds();
* to the PUS standard.
*
*/
class VerificationReporter {
friend void(Factory::setStaticFrameworkObjectIds)();
class VerificationReporter : public SystemObject, public VerificationReporterIF {
public:
VerificationReporter();
virtual ~VerificationReporter();
explicit VerificationReporter(AcceptsVerifyMessageIF* receiver,
object_id_t objectId = objects::TC_VERIFICATOR);
~VerificationReporter() override;
void setReceiver(AcceptsVerifyMessageIF& receiver);
// TODO: The API is a little bit bloated. It might be better to group all the parameters
// into a dedicated struct
void sendSuccessReport(uint8_t set_report_id, PusTcReader* correspondingTc, uint8_t set_step = 0);
void sendSuccessReport(uint8_t set_report_id, uint8_t ackFlags, uint16_t tcPacketId,
uint16_t tcSequenceControl, uint8_t set_step = 0);
ReturnValue_t sendSuccessReport(VerifSuccessParams params) override;
void sendFailureReport(uint8_t report_id, PusTcReader* correspondingTc,
ReturnValue_t errorCode = 0, uint8_t step = 0, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
void sendFailureReport(uint8_t report_id, uint8_t ackFlags, uint16_t tcPacketId,
uint16_t tcSequenceControl, ReturnValue_t errorCode = 0, uint8_t step = 0,
uint32_t parameter1 = 0, uint32_t parameter2 = 0);
void initialize();
ReturnValue_t sendFailureReport(VerifFailureParams params) override;
private:
static object_id_t messageReceiver;
MessageQueueId_t acknowledgeQueue;
};

View File

@ -0,0 +1,57 @@
#ifndef FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H
#define FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H
#include "fsfw/retval.h"
#include "fsfw/tmtcpacket/pus/tc.h"
struct VerifParamsBase {
VerifParamsBase() : reportId(0), tcPacketId(0), tcPsc(0) {}
VerifParamsBase(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc)
: reportId(reportId), tcPacketId(tcPacketId), tcPsc(tcPsc) {}
uint8_t reportId;
uint16_t tcPacketId;
uint16_t tcPsc;
uint8_t ackFlags = ecss::ACK_ALL;
uint8_t step = 0;
};
struct VerifSuccessParams : public VerifParamsBase {
VerifSuccessParams() = default;
VerifSuccessParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc)
: VerifParamsBase(reportId, tcPacketId, tcPsc) {}
VerifSuccessParams(uint8_t reportId, PusTcIF& tc)
: VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()) {}
};
struct VerifFailureParams : public VerifParamsBase {
VerifFailureParams() = default;
VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc, ReturnValue_t errorCode,
uint32_t errorParam1, uint32_t errorParams2)
: VerifParamsBase(reportId, tcPacketId, tcPsc), errorCode(errorCode) {
errorParam1 = errorParam1;
errorParams2 = errorParams2;
}
VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc, ReturnValue_t errorCode)
: VerifParamsBase(reportId, tcPacketId, tcPsc), errorCode(errorCode) {}
VerifFailureParams(uint8_t reportId, uint16_t tcPacketId, uint16_t tcPsc)
: VerifParamsBase(reportId, tcPacketId, tcPsc) {}
VerifFailureParams(uint8_t reportId, PusTcIF& tc, ReturnValue_t errorCode)
: VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()),
errorCode(errorCode) {}
VerifFailureParams(uint8_t reportId, PusTcIF& tc)
: VerifParamsBase(reportId, tc.getPacketIdRaw(), tc.getPacketSeqCtrlRaw()) {}
ReturnValue_t errorCode = retval::OK;
uint8_t step = 0;
uint32_t errorParam1 = 0;
uint32_t errorParam2 = 0;
};
class VerificationReporterIF {
public:
virtual ~VerificationReporterIF() = default;
virtual ReturnValue_t sendSuccessReport(VerifSuccessParams params) = 0;
virtual ReturnValue_t sendFailureReport(VerifFailureParams params) = 0;
};
#endif // FSFW_TMTCSERVICES_VERIFICATIONREPORTERIF_H

View File

@ -10,38 +10,60 @@ namespace telemetry {
class DataWithObjectIdPrefix : public SerializeIF {
public:
DataWithObjectIdPrefix(object_id_t objectId, const uint8_t* srcData, size_t srcDataLen)
: objectId(objectId), srcData(srcData), srcDataLen(srcDataLen) {}
: objectId(objectId) {
dataWrapper.type = ecss::DataTypes::RAW;
dataWrapper.dataUnion.raw.data = srcData;
dataWrapper.dataUnion.raw.len = srcDataLen;
}
DataWithObjectIdPrefix(object_id_t objectId, SerializeIF& serializable) : objectId(objectId) {
dataWrapper.type = ecss::DataTypes::SERIALIZABLE;
dataWrapper.dataUnion.serializable = &serializable;
}
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override {
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
if (dataWrapper.type != ecss::DataTypes::RAW) {
if ((dataWrapper.dataUnion.raw.data == nullptr) and (dataWrapper.dataUnion.raw.len > 0)) {
return retval::FAILED;
}
} else if (dataWrapper.type == ecss::DataTypes::SERIALIZABLE) {
if (dataWrapper.dataUnion.serializable == nullptr) {
return retval::FAILED;
}
}
ReturnValue_t result =
SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
std::memcpy(*buffer, srcData, srcDataLen);
*buffer += srcDataLen;
*size += srcDataLen;
return HasReturnvaluesIF::RETURN_OK;
}
[[nodiscard]] size_t getSerializedSize() const override { return sizeof(objectId) + srcDataLen; }
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override {
ReturnValue_t result = SerializeAdapter::deSerialize(&objectId, buffer, size, streamEndianness);
if (result != retval::OK) {
return result;
}
if (dataWrapper.type != ecss::DataTypes::RAW) {
std::memcpy(*buffer, dataWrapper.dataUnion.raw.data, dataWrapper.dataUnion.raw.len);
*buffer += dataWrapper.dataUnion.raw.len;
*size += dataWrapper.dataUnion.raw.len;
} else {
return dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize, streamEndianness);
}
return retval::OK;
}
[[nodiscard]] size_t getSerializedSize() const override {
return sizeof(objectId) + dataWrapper.getLength();
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override {
// As long as there is no way to know how long the expected data will be, this function
// does not make sense
return retval::FAILED;
}
private:
object_id_t objectId;
const uint8_t* srcData;
size_t srcDataLen;
ecss::DataWrapper dataWrapper{};
};
} // namespace telemetry

View File

@ -60,8 +60,6 @@ void Factory::setStaticFrameworkObjectIds() {
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
VerificationReporter::messageReceiver = objects::PUS_SERVICE_1_VERIFICATION;
DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;

View File

@ -0,0 +1,30 @@
#include "PusServiceBaseMock.h"
ReturnValue_t PsbMock::handleRequest(uint8_t subservice) {
handleRequestCallCnt++;
subserviceQueue.push(subservice);
if (handleReqFailPair.first) {
handleReqFailPair.first = false;
return handleReqFailPair.second;
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PsbMock::performService() {
performServiceCallCnt++;
if (performServiceFailPair.first) {
performServiceFailPair.first = false;
return performServiceFailPair.second;
}
return HasReturnvaluesIF::RETURN_OK;
}
void PsbMock::reset() {
handleRequestCallCnt = 0;
performServiceCallCnt = 0;
std::queue<uint8_t>().swap(subserviceQueue);
}
void PsbMock::makeNextHandleReqCallFail(ReturnValue_t retval) {
handleReqFailPair.first = true;
handleReqFailPair.second = retval;
}

View File

@ -0,0 +1,23 @@
#ifndef FSFW_TESTS_PUSSERVICEBASEMOCK_H
#define FSFW_TESTS_PUSSERVICEBASEMOCK_H
#include <queue>
#include "fsfw/tmtcservices/PusServiceBase.h"
class PsbMock : public PusServiceBase {
public:
unsigned int handleRequestCallCnt = 0;
std::queue<uint8_t> subserviceQueue;
unsigned int performServiceCallCnt = 0;
std::pair<bool, ReturnValue_t> handleReqFailPair;
std::pair<bool, ReturnValue_t> performServiceFailPair;
ReturnValue_t handleRequest(uint8_t subservice) override;
ReturnValue_t performService() override;
void makeNextHandleReqCallFail(ReturnValue_t retval);
void reset();
};
#endif // FSFW_TESTS_PUSSERVICEBASEMOCK_H

View File

@ -1,4 +1,5 @@
target_sources(${FSFW_TEST_TGT} PRIVATE
testStoreHelper.cpp
testSendHelper.cpp
testStoreAndSendHelper.cpp
)

View File

@ -0,0 +1,5 @@
#include <catch2/catch_test_macros.hpp>
#include "fsfw/tmtcservices/PusServiceBase.h"
TEST_CASE("Pus Service Base", "[pus-service-base]") { auto psb = PusServiceBase() }

View File

@ -2,8 +2,12 @@
#include "fsfw/storagemanager/LocalPool.h"
#include "fsfw/tmtcservices/TmSendHelper.h"
#include "fsfw/tmtcservices/TmStoreAndSendHelper.h"
#include "fsfw/tmtcservices/TmStoreHelper.h"
#include "mocks/CdsShortTimestamperMock.h"
#include "mocks/InternalErrorReporterMock.h"
#include "mocks/MessageQueueMock.h"
#include "mocks/SimpleSerializable.h"
TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
auto timeStamper = CdsShortTimestamperMock();
@ -16,4 +20,68 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
auto msgQueue = MessageQueueMock();
msgQueue.setDefaultDestination(destId);
TmSendHelper sendHelper(msgQueue, errReporter, destId);
TmStoreAndSendWrapper tmHelper(17, storeHelper, sendHelper);
SECTION("State") {
CHECK(tmHelper.sendCounter == 0);
CHECK(tmHelper.defaultService == 17);
CHECK(tmHelper.delOnFailure);
CHECK(tmHelper.incrementSendCounter);
CHECK(&tmHelper.sendHelper == &sendHelper);
CHECK(&tmHelper.storeHelper == &storeHelper);
}
SECTION("Base Test") {
tmHelper.prepareTmPacket(2);
auto& creator = storeHelper.getCreatorRef();
REQUIRE(creator.getSubService() == 2);
REQUIRE(creator.getService() == 17);
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == ecss::DataTypes::RAW);
REQUIRE(params.dataWrapper.dataUnion.raw.data == nullptr);
REQUIRE(params.dataWrapper.dataUnion.raw.len == 0);
REQUIRE(tmHelper.sendCounter == 0);
REQUIRE(tmHelper.storeAndSendTmPacket() == retval::OK);
REQUIRE(tmHelper.sendCounter == 1);
auto storeId = storeHelper.getCurrentAddr();
REQUIRE(msgQueue.wasMessageSent());
REQUIRE(msgQueue.numberOfSentMessagesToDefault() == 1);
TmTcMessage msg;
REQUIRE(msgQueue.getNextSentMessage(msg) == retval::OK);
REQUIRE(msg.getStorageId() == storeId);
REQUIRE(pool.hasDataAtId(msg.getStorageId()));
storeHelper.deletePacket();
}
SECTION("Raw Data Helper") {
std::array<uint8_t, 3> data = {1, 2, 3};
REQUIRE(tmHelper.prepareTmPacket(2, data.data(), data.size()) == retval::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == ecss::DataTypes::RAW);
REQUIRE(params.dataWrapper.dataUnion.raw.data == data.data());
REQUIRE(params.dataWrapper.dataUnion.raw.len == data.size());
}
SECTION("Serializable Helper") {
auto simpleSer = SimpleSerializable();
REQUIRE(tmHelper.prepareTmPacket(2, simpleSer) == retval::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == ecss::DataTypes::SERIALIZABLE);
REQUIRE(params.dataWrapper.dataUnion.serializable == &simpleSer);
}
SECTION("Object ID prefix Helper") {
uint32_t objectId = 0x01020304;
std::array<uint8_t, 3> data = {1, 2, 3};
telemetry::DataWithObjectIdPrefix dataWithObjId(objectId, data.data(), data.size());
REQUIRE(tmHelper.prepareTmPacket(2, dataWithObjId) == retval::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == ecss::DataTypes::SERIALIZABLE);
REQUIRE(params.dataWrapper.dataUnion.serializable == &dataWithObjId);
}
// TODO: Error handling
}