From 75c824ec80cfc2e69539da1917e1913c6ef42321 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Tue, 26 Jul 2022 13:59:09 +0200 Subject: [PATCH] add new VerificationReporterIF --- src/fsfw/objectmanager/frameworkObjects.h | 1 + src/fsfw/pus/CService200ModeCommanding.cpp | 7 +- src/fsfw/pus/CService201HealthCommanding.cpp | 2 +- src/fsfw/pus/Service17Test.cpp | 12 +- src/fsfw/pus/Service20ParameterManagement.cpp | 3 +- src/fsfw/pus/Service2DeviceAccess.cpp | 6 +- src/fsfw/pus/Service3Housekeeping.cpp | 3 +- src/fsfw/pus/Service8FunctionManagement.cpp | 3 +- src/fsfw/retval.h | 6 + src/fsfw/tcdistribution/PusDistributor.cpp | 6 +- src/fsfw/tcdistribution/PusDistributor.h | 2 +- .../tmtcservices/AcceptsVerifyMessageIF.h | 4 +- .../tmtcservices/CommandingServiceBase.cpp | 142 +++++++++++------- src/fsfw/tmtcservices/CommandingServiceBase.h | 34 +++-- src/fsfw/tmtcservices/PusServiceBase.cpp | 36 ++++- src/fsfw/tmtcservices/PusServiceBase.h | 20 ++- .../tmtcservices/TmStoreAndSendHelper.cpp | 45 +++--- src/fsfw/tmtcservices/TmStoreAndSendHelper.h | 29 ++-- .../tmtcservices/VerificationReporter.cpp | 105 +++---------- src/fsfw/tmtcservices/VerificationReporter.h | 32 ++-- .../tmtcservices/VerificationReporterIF.h | 57 +++++++ src/fsfw/tmtcservices/tmHelpers.h | 56 ++++--- unittests/CatchFactory.cpp | 2 - unittests/mocks/PusServiceBaseMock.cpp | 30 ++++ unittests/mocks/PusServiceBaseMock.h | 23 +++ unittests/tmtcservices/CMakeLists.txt | 1 + unittests/tmtcservices/testPsb.cpp | 5 + .../tmtcservices/testStoreAndSendHelper.cpp | 68 +++++++++ 28 files changed, 486 insertions(+), 254 deletions(-) create mode 100644 src/fsfw/retval.h create mode 100644 src/fsfw/tmtcservices/VerificationReporterIF.h create mode 100644 unittests/mocks/PusServiceBaseMock.cpp create mode 100644 unittests/mocks/PusServiceBaseMock.h create mode 100644 unittests/tmtcservices/testPsb.cpp diff --git a/src/fsfw/objectmanager/frameworkObjects.h b/src/fsfw/objectmanager/frameworkObjects.h index cddc6ba24..be6646214 100644 --- a/src/fsfw/objectmanager/frameworkObjects.h +++ b/src/fsfw/objectmanager/frameworkObjects.h @@ -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 diff --git a/src/fsfw/pus/CService200ModeCommanding.cpp b/src/fsfw/pus/CService200ModeCommanding.cpp index ea60d00bc..9990280cf 100644 --- a/src/fsfw/pus/CService200ModeCommanding.cpp +++ b/src/fsfw/pus/CService200ModeCommanding.cpp @@ -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; diff --git a/src/fsfw/pus/CService201HealthCommanding.cpp b/src/fsfw/pus/CService201HealthCommanding.cpp index 4588907fa..c668ea522 100644 --- a/src/fsfw/pus/CService201HealthCommanding.cpp +++ b/src/fsfw/pus/CService201HealthCommanding.cpp @@ -102,5 +102,5 @@ ReturnValue_t CService201HealthCommanding::handleReply(const CommandMessage *rep auto health = static_cast(HealthMessage::getHealth(reply)); auto oldHealth = static_cast(HealthMessage::getOldHealth(reply)); HealthSetReply healthSetReply(health, oldHealth); - return tmHelper.sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply); + return sendTmPacket(Subservice::REPLY_HEALTH_SET, healthSetReply); } diff --git a/src/fsfw/pus/Service17Test.cpp b/src/fsfw/pus/Service17Test.cpp index b40d2d705..d526e055b 100644 --- a/src/fsfw/pus/Service17Test.cpp +++ b/src/fsfw/pus/Service17Test.cpp @@ -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; diff --git a/src/fsfw/pus/Service20ParameterManagement.cpp b/src/fsfw/pus/Service20ParameterManagement.cpp index 5f4795302..6d6ca3392 100644 --- a/src/fsfw/pus/Service20ParameterManagement.cpp +++ b/src/fsfw/pus/Service20ParameterManagement.cpp @@ -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(Subservice::PARAMETER_DUMP_REPLY), parameterReply); - return HasReturnvaluesIF::RETURN_OK; + return sendTmPacket(static_cast(Subservice::PARAMETER_DUMP_REPLY), parameterReply); } default: return CommandingServiceBase::INVALID_REPLY; diff --git a/src/fsfw/pus/Service2DeviceAccess.cpp b/src/fsfw/pus/Service2DeviceAccess.cpp index 008d81287..817a372ed 100644 --- a/src/fsfw/pus/Service2DeviceAccess.cpp +++ b/src/fsfw/pus/Service2DeviceAccess.cpp @@ -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(); } diff --git a/src/fsfw/pus/Service3Housekeeping.cpp b/src/fsfw/pus/Service3Housekeeping.cpp index df7cbe0ac..7ef5636dd 100644 --- a/src/fsfw/pus/Service3Housekeeping.cpp +++ b/src/fsfw/pus/Service3Housekeeping.cpp @@ -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(subserviceId), hkPacket.hkData, - hkPacket.hkSize); + return sendTmPacket(static_cast(subserviceId), hkPacket.hkData, hkPacket.hkSize); } sid_t Service3Housekeeping::buildSid(object_id_t objectId, const uint8_t** tcData, diff --git a/src/fsfw/pus/Service8FunctionManagement.cpp b/src/fsfw/pus/Service8FunctionManagement.cpp index f9a6a168b..c9da6d580 100644 --- a/src/fsfw/pus/Service8FunctionManagement.cpp +++ b/src/fsfw/pus/Service8FunctionManagement.cpp @@ -138,8 +138,7 @@ ReturnValue_t Service8FunctionManagement::handleDataReply(const CommandMessage* return result; } DataReply dataReply(objectId, actionId, buffer, size); - result = tmHelper.sendTmPacket(static_cast(Subservice::REPLY_DIRECT_COMMANDING_DATA), - dataReply); + result = sendTmPacket(static_cast(Subservice::REPLY_DIRECT_COMMANDING_DATA), dataReply); auto deletionResult = ipcStore->deleteData(storeId); if (deletionResult != HasReturnvaluesIF::RETURN_OK) { diff --git a/src/fsfw/retval.h b/src/fsfw/retval.h new file mode 100644 index 000000000..43c4e1273 --- /dev/null +++ b/src/fsfw/retval.h @@ -0,0 +1,6 @@ +#ifndef FSFW_RETVAL_H +#define FSFW_RETVAL_H + +#include "fsfw/returnvalues/HasReturnvaluesIF.h" + +#endif // FSFW_RETVAL_H diff --git a/src/fsfw/tcdistribution/PusDistributor.cpp b/src/fsfw/tcdistribution/PusDistributor.cpp index 3a7fdf34f..1cef2b9f9 100644 --- a/src/fsfw/tcdistribution/PusDistributor.cpp +++ b/src/fsfw/tcdistribution/PusDistributor.cpp @@ -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; } } diff --git a/src/fsfw/tcdistribution/PusDistributor.h b/src/fsfw/tcdistribution/PusDistributor.h index fb916263c..3849c793d 100644 --- a/src/fsfw/tcdistribution/PusDistributor.h +++ b/src/fsfw/tcdistribution/PusDistributor.h @@ -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. */ diff --git a/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h b/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h index 7e58187b5..daf67080e 100644 --- a/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h +++ b/src/fsfw/tmtcservices/AcceptsVerifyMessageIF.h @@ -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; }; diff --git a/src/fsfw/tmtcservices/CommandingServiceBase.cpp b/src/fsfw/tmtcservices/CommandingServiceBase.cpp index 7839aa876..c890ecfb6 100644 --- a/src/fsfw/tmtcservices/CommandingServiceBase.cpp +++ b/src/fsfw/tmtcservices/CommandingServiceBase.cpp @@ -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(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; +} diff --git a/src/fsfw/tmtcservices/CommandingServiceBase.h b/src/fsfw/tmtcservices/CommandingServiceBase.h index 63067b076..202dd8623 100644 --- a/src/fsfw/tmtcservices/CommandingServiceBase.h +++ b/src/fsfw/tmtcservices/CommandingServiceBase.h @@ -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(); }; diff --git a/src/fsfw/tmtcservices/PusServiceBase.cpp b/src/fsfw/tmtcservices/PusServiceBase.cpp index 26f086943..f727e415d 100644 --- a/src/fsfw/tmtcservices/PusServiceBase.cpp +++ b/src/fsfw/tmtcservices/PusServiceBase.cpp @@ -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(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; +} diff --git a/src/fsfw/tmtcservices/PusServiceBase.h b/src/fsfw/tmtcservices/PusServiceBase.h index 7df563d06..4aa6fadec 100644 --- a/src/fsfw/tmtcservices/PusServiceBase.h +++ b/src/fsfw/tmtcservices/PusServiceBase.h @@ -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: /** diff --git a/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp b/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp index 61735ab5c..cab6db448 100644 --- a/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp +++ b/src/fsfw/tmtcservices/TmStoreAndSendHelper.cpp @@ -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); } diff --git a/src/fsfw/tmtcservices/TmStoreAndSendHelper.h b/src/fsfw/tmtcservices/TmStoreAndSendHelper.h index 1a33b7d70..eef3a373c 100644 --- a/src/fsfw/tmtcservices/TmStoreAndSendHelper.h +++ b/src/fsfw/tmtcservices/TmStoreAndSendHelper.h @@ -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; diff --git a/src/fsfw/tmtcservices/VerificationReporter.cpp b/src/fsfw/tmtcservices/VerificationReporter.cpp index a9b6dd473..b08756d3e 100644 --- a/src/fsfw/tmtcservices/VerificationReporter.cpp +++ b/src/fsfw/tmtcservices/VerificationReporter.cpp @@ -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(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; } diff --git a/src/fsfw/tmtcservices/VerificationReporter.h b/src/fsfw/tmtcservices/VerificationReporter.h index 1d64fd483..8ea45f79e 100644 --- a/src/fsfw/tmtcservices/VerificationReporter.h +++ b/src/fsfw/tmtcservices/VerificationReporter.h @@ -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; }; diff --git a/src/fsfw/tmtcservices/VerificationReporterIF.h b/src/fsfw/tmtcservices/VerificationReporterIF.h new file mode 100644 index 000000000..14b6012fc --- /dev/null +++ b/src/fsfw/tmtcservices/VerificationReporterIF.h @@ -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 diff --git a/src/fsfw/tmtcservices/tmHelpers.h b/src/fsfw/tmtcservices/tmHelpers.h index 6a754bdfd..ad333eb24 100644 --- a/src/fsfw/tmtcservices/tmHelpers.h +++ b/src/fsfw/tmtcservices/tmHelpers.h @@ -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 diff --git a/unittests/CatchFactory.cpp b/unittests/CatchFactory.cpp index d5d129356..5ae5a9fb3 100644 --- a/unittests/CatchFactory.cpp +++ b/unittests/CatchFactory.cpp @@ -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; diff --git a/unittests/mocks/PusServiceBaseMock.cpp b/unittests/mocks/PusServiceBaseMock.cpp new file mode 100644 index 000000000..0303364fa --- /dev/null +++ b/unittests/mocks/PusServiceBaseMock.cpp @@ -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().swap(subserviceQueue); +} +void PsbMock::makeNextHandleReqCallFail(ReturnValue_t retval) { + handleReqFailPair.first = true; + handleReqFailPair.second = retval; +} diff --git a/unittests/mocks/PusServiceBaseMock.h b/unittests/mocks/PusServiceBaseMock.h new file mode 100644 index 000000000..f441c2a87 --- /dev/null +++ b/unittests/mocks/PusServiceBaseMock.h @@ -0,0 +1,23 @@ +#ifndef FSFW_TESTS_PUSSERVICEBASEMOCK_H +#define FSFW_TESTS_PUSSERVICEBASEMOCK_H + +#include + +#include "fsfw/tmtcservices/PusServiceBase.h" + +class PsbMock : public PusServiceBase { + public: + unsigned int handleRequestCallCnt = 0; + std::queue subserviceQueue; + unsigned int performServiceCallCnt = 0; + + std::pair handleReqFailPair; + std::pair performServiceFailPair; + ReturnValue_t handleRequest(uint8_t subservice) override; + ReturnValue_t performService() override; + + void makeNextHandleReqCallFail(ReturnValue_t retval); + void reset(); +}; + +#endif // FSFW_TESTS_PUSSERVICEBASEMOCK_H diff --git a/unittests/tmtcservices/CMakeLists.txt b/unittests/tmtcservices/CMakeLists.txt index 791066adf..4cb2dc051 100644 --- a/unittests/tmtcservices/CMakeLists.txt +++ b/unittests/tmtcservices/CMakeLists.txt @@ -1,4 +1,5 @@ target_sources(${FSFW_TEST_TGT} PRIVATE testStoreHelper.cpp testSendHelper.cpp + testStoreAndSendHelper.cpp ) diff --git a/unittests/tmtcservices/testPsb.cpp b/unittests/tmtcservices/testPsb.cpp new file mode 100644 index 000000000..43e03b48f --- /dev/null +++ b/unittests/tmtcservices/testPsb.cpp @@ -0,0 +1,5 @@ +#include + +#include "fsfw/tmtcservices/PusServiceBase.h" + +TEST_CASE("Pus Service Base", "[pus-service-base]") { auto psb = PusServiceBase() } \ No newline at end of file diff --git a/unittests/tmtcservices/testStoreAndSendHelper.cpp b/unittests/tmtcservices/testStoreAndSendHelper.cpp index 309556b67..2a5226002 100644 --- a/unittests/tmtcservices/testStoreAndSendHelper.cpp +++ b/unittests/tmtcservices/testStoreAndSendHelper.cpp @@ -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 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 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 }