From e8de2fc47a1f1c6451ec5a7a6ec3767377289de7 Mon Sep 17 00:00:00 2001 From: Robin Mueller Date: Mon, 14 Sep 2020 18:29:19 +0200 Subject: [PATCH] added srv3 --- events/fwSubsystemIdRanges.h | 1 + pus/Service17Test.h | 6 +- pus/Service3Housekeeping.cpp | 262 +++++++++++++++++++++++++++ pus/Service3Housekeeping.h | 101 +++++++++++ pus/servicepackets/Service3Packets.h | 21 +++ 5 files changed, 388 insertions(+), 3 deletions(-) create mode 100644 pus/Service3Housekeeping.cpp create mode 100644 pus/Service3Housekeeping.h create mode 100644 pus/servicepackets/Service3Packets.h diff --git a/events/fwSubsystemIdRanges.h b/events/fwSubsystemIdRanges.h index a05652c22..3c57c1606 100644 --- a/events/fwSubsystemIdRanges.h +++ b/events/fwSubsystemIdRanges.h @@ -19,6 +19,7 @@ enum { SYSTEM_MANAGER_1 = 75, SYSTEM_1 = 79, PUS_SERVICE_1 = 80, + PUS_SERVICE_17 = 83, FW_SUBSYSTEM_ID_RANGE }; } diff --git a/pus/Service17Test.h b/pus/Service17Test.h index 8d6a43770..e26818659 100644 --- a/pus/Service17Test.h +++ b/pus/Service17Test.h @@ -1,5 +1,5 @@ -#ifndef MISSION_PUS_SERVICE17TEST_H_ -#define MISSION_PUS_SERVICE17TEST_H_ +#ifndef FSFW_PUS_SERVICE17TEST_H_ +#define FSFW_PUS_SERVICE17TEST_H_ #include "../tmtcservices/PusServiceBase.h" #include "../objectmanager/SystemObject.h" @@ -41,4 +41,4 @@ protected: uint16_t packetSubCounter = 0; }; -#endif /* MISSION_PUS_SERVICE17TEST_H_ */ +#endif /* FSFW_PUS_SERVICE17TEST_H_ */ diff --git a/pus/Service3Housekeeping.cpp b/pus/Service3Housekeeping.cpp new file mode 100644 index 000000000..db77328ab --- /dev/null +++ b/pus/Service3Housekeeping.cpp @@ -0,0 +1,262 @@ +#include "Service3Housekeeping.h" +#include "servicepackets/Service3Packets.h" +#include "../datapoollocal/HasLocalDataPoolIF.h" + + +Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, + uint8_t serviceId): + CommandingServiceBase(objectId, apid, serviceId, + NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {} + +Service3Housekeeping::~Service3Housekeeping() {} + +ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) { + switch(static_cast(subservice)) { + case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION: + case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION: + case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: + case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: + case Subservice::REPORT_HK_REPORT_STRUCTURES: + case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES : + case Subservice::GENERATE_ONE_PARAMETER_REPORT: + case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT: + case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL: + case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL: + return HasReturnvaluesIF::RETURN_OK; + // Telemetry or invalid subservice. + case Subservice::HK_DEFINITIONS_REPORT: + case Subservice::DIAGNOSTICS_DEFINITION_REPORT: + case Subservice::HK_REPORT: + case Subservice::DIAGNOSTICS_REPORT: + default: + return AcceptsTelecommandsIF::INVALID_SUBSERVICE; + } +} + +ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, + MessageQueueId_t *id, object_id_t *objectId) { + return HasReturnvaluesIF::RETURN_OK; + ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen); + if(result != RETURN_OK) { + return result; + } + return checkInterfaceAndAcquireMessageQueue(id,objectId); +} + +ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID( + object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) { + if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) { + return CommandingServiceBase::INVALID_TC; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { + // check OwnsLocalDataPoolIF property of target + HasLocalDataPoolIF* possibleTarget = + objectManager->get(*objectId); + if(possibleTarget == nullptr){ + return CommandingServiceBase::INVALID_OBJECT; + } + *messageQueueToSet = possibleTarget->getCommandQueue(); + return HasReturnvaluesIF::RETURN_OK; +} + + +ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) { + switch(static_cast(subservice)) { + case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION: + return prepareReportingTogglingCommand(message, true, false, + tcData, tcDataLen); + case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION: + return prepareReportingTogglingCommand(message, false, false, + tcData, tcDataLen); + case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: + return prepareReportingTogglingCommand(message, true, true, + tcData, tcDataLen); + case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: + return prepareReportingTogglingCommand(message, false, true, + tcData, tcDataLen); + case Subservice::REPORT_HK_REPORT_STRUCTURES: + return prepareStructureReportingCommand(message, false, tcData, + tcDataLen); + case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES: + return prepareStructureReportingCommand(message, true, tcData, + tcDataLen); + case Subservice::GENERATE_ONE_PARAMETER_REPORT: + return prepareOneShotReportCommand(message, false, tcData, tcDataLen); + case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT: + return prepareOneShotReportCommand(message, true, tcData, tcDataLen); + case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL: + return prepareCollectionIntervalModificationCommand(message, false, + tcData, tcDataLen); + case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL: + return prepareCollectionIntervalModificationCommand(message, true, + tcData, tcDataLen); + case Subservice::HK_DEFINITIONS_REPORT: + case Subservice::DIAGNOSTICS_DEFINITION_REPORT: + case Subservice::HK_REPORT: + case Subservice::DIAGNOSTICS_REPORT: + // Those are telemetry packets. + return CommandingServiceBase::INVALID_TC; + default: + // should never happen, subservice was already checked. + return HasReturnvaluesIF::RETURN_FAILED; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) { + switch(reply->getCommand()) { + case(HousekeepingMessage::HK_REQUEST_SUCCESS): { + return CommandingServiceBase::EXECUTION_COMPLETE; + } + case(HousekeepingMessage::HK_REQUEST_FAILURE): { + failureParameter1 = objectId; + // also provide failure reason (returnvalue) + // will be most commonly invalid SID or the set already has the desired + // reporting status. + return CommandingServiceBase::EXECUTION_COMPLETE; + } + default: + sif::error << "Service3Housekeeping::handleReply: Invalid reply!" + << std::endl; + return CommandingServiceBase::INVALID_REPLY; + } + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand( + CommandMessage *command, bool enableReporting, bool isDiagnostics, + const uint8_t* tcData, size_t tcDataLen) { + if(tcDataLen < sizeof(sid_t)) { + // It is assumed the full SID is sent for now (even if that means + // 4 bytes are redundant) + return CommandingServiceBase::INVALID_TC; + } + + sid_t targetSid; + SerializeAdapter::deSerialize(&targetSid.objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&targetSid.ownerSetId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + + HousekeepingMessage::setToggleReportingCommand(command, targetSid, + enableReporting, isDiagnostics); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand( + CommandMessage *command, bool isDiagnostics, const uint8_t* tcData, + size_t tcDataLen) { + if(tcDataLen < sizeof(sid_t)) { + // It is assumed the full SID is sent for now (even if that means + // 4 bytes are redundant) + return CommandingServiceBase::INVALID_TC; + } + + sid_t targetSid; + SerializeAdapter::deSerialize(&targetSid.objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&targetSid.ownerSetId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + + HousekeepingMessage::setStructureReportingCommand(command, targetSid, + isDiagnostics); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand( + CommandMessage *command, bool isDiagnostics, const uint8_t *tcData, + size_t tcDataLen) { + if(tcDataLen < sizeof(sid_t)) { + // It is assumed the full SID is sent for now (even if that means + // 4 bytes are redundant) + return CommandingServiceBase::INVALID_TC; + } + + sid_t targetSid; + SerializeAdapter::deSerialize(&targetSid.objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&targetSid.ownerSetId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + HousekeepingMessage::setOneShotReportCommand(command, targetSid, + isDiagnostics); + return HasReturnvaluesIF::RETURN_OK; +} + +ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand( + CommandMessage *command, bool isDiagnostics, const uint8_t *tcData, + size_t tcDataLen) { + if(tcDataLen < sizeof(sid_t) + sizeof(float)) { + // It is assumed the full SID and the new collection interval as a float + // is sent for now (even if that means 4 bytes are redundant) + return CommandingServiceBase::INVALID_TC; + } + + sid_t targetSid; + float newCollectionInterval = 0; + SerializeAdapter::deSerialize(&targetSid.objectId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&targetSid.ownerSetId, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen, + SerializeIF::Endianness::BIG); + HousekeepingMessage::setCollectionIntervalModificationCommand(command, + targetSid, newCollectionInterval, isDiagnostics); + return HasReturnvaluesIF::RETURN_OK; +} + +void Service3Housekeeping::handleUnrequestedReply( + CommandMessage* reply) { + ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; + switch(reply->getCommand()) { + case(HousekeepingMessage::DIAGNOSTICS_REPORT): { + result = generateHkReport(reply, + static_cast(Subservice::DIAGNOSTICS_REPORT)); + break; + } + case(HousekeepingMessage::HK_REPORT): { + result = generateHkReport(reply, + static_cast(Subservice::HK_REPORT)); + break; + } + default: { + sif::error << "Service3Housekeeping::handleUnrequestedReply: " + << "Invalid reply!" << std::endl; + } + } + + if(result != HasReturnvaluesIF::RETURN_OK) { + // Configuration error + sif::debug << "Service3Housekeeping::handleUnrequestedReply:" + << "Could not generate reply!" << std::endl; + } +} + +MessageQueueId_t Service3Housekeeping::getHkQueue() const { + return commandQueue->getId(); +} + +ReturnValue_t Service3Housekeeping::generateHkReport( + const CommandMessage* hkMessage, uint8_t subserviceId) { + store_address_t storeId; + + sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId); + auto resultPair = IPCStore->getData(storeId); + if(resultPair.first != HasReturnvaluesIF::RETURN_OK) { + return resultPair.first; + } + + HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size()); + return sendTmPacket(static_cast(subserviceId), + hkPacket.hkData, hkPacket.hkSize, nullptr, 0); +} diff --git a/pus/Service3Housekeeping.h b/pus/Service3Housekeeping.h new file mode 100644 index 000000000..6c5d24699 --- /dev/null +++ b/pus/Service3Housekeeping.h @@ -0,0 +1,101 @@ +#ifndef FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_ +#define FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_ + +#include "../housekeeping/AcceptsHkPacketsIF.h" +#include "../housekeeping/HousekeepingMessage.h" +#include "../tmtcservices/CommandingServiceBase.h" + +/** + * @brief Manges spacecraft housekeeping reports and + * sends pool variables (temperature, GPS data ...) to ground. + * + * @details Full Documentation: ECSS-E70-41A or ECSS-E-ST-70-41C. + * Implementation based on PUS-C + * + * The housekeeping service type provides means to control and adapt the + * spacecraft reporting plan according to the mission phases. + * The housekeeping service type provides the visibility of any + * on-board parameters assembled in housekeeping parameter report structures + * or diagnostic parameter report structures as required for the mission. + * The parameter report structures used by the housekeeping service can + * be predefined on-board or created when needed. + * + * @author R. Mueller + * @ingroup pus_services + */ +class Service3Housekeeping: public CommandingServiceBase, + public AcceptsHkPacketsIF { +public: + static constexpr uint8_t NUM_OF_PARALLEL_COMMANDS = 4; + static constexpr uint16_t COMMAND_TIMEOUT_SECONDS = 60; + + Service3Housekeeping(object_id_t objectId, uint16_t apid, uint8_t serviceId); + virtual~ Service3Housekeeping(); +protected: + /* CSB abstract functions implementation . See CSB documentation. */ + ReturnValue_t isValidSubservice(uint8_t subservice) override; + ReturnValue_t getMessageQueueAndObject(uint8_t subservice, + const uint8_t *tcData, size_t tcDataLen, MessageQueueId_t *id, + object_id_t *objectId) override; + ReturnValue_t prepareCommand(CommandMessage* message, + uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, + uint32_t *state, object_id_t objectId) override; + ReturnValue_t handleReply(const CommandMessage* reply, + Command_t previousCommand, uint32_t *state, + CommandMessage* optionalNextCommand, object_id_t objectId, + bool *isStep) override; + + virtual MessageQueueId_t getHkQueue() const; +private: + enum class Subservice { + ENABLE_PERIODIC_HK_REPORT_GENERATION = 5, //!< [EXPORT] : [TC] + DISABLE_PERIODIC_HK_REPORT_GENERATION = 6, //!< [EXPORT] : [TC] + + ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION = 7, //!< [EXPORT] : [TC] + DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION = 8, //!< [EXPORT] : [TC] + + //! [EXPORT] : [TC] Report HK structure by supplying SID + REPORT_HK_REPORT_STRUCTURES = 9, + //! [EXPORT] : [TC] Report Diagnostics structure by supplying SID + REPORT_DIAGNOSTICS_REPORT_STRUCTURES = 11, + + //! [EXPORT] : [TM] Report corresponding to Subservice 9 TC + HK_DEFINITIONS_REPORT = 10, + //! [EXPORT] : [TM] Report corresponding to Subservice 11 TC + DIAGNOSTICS_DEFINITION_REPORT = 12, + + //! [EXPORT] : [TM] Core packet. Contains Housekeeping data + HK_REPORT = 25, + //! [EXPORT] : [TM] Core packet. Contains diagnostics data + DIAGNOSTICS_REPORT = 26, + + /* PUS-C */ + GENERATE_ONE_PARAMETER_REPORT = 27, //!< [EXPORT] : [TC] + GENERATE_ONE_DIAGNOSTICS_REPORT = 28, //!< [EXPORT] : [TC] + + MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL = 31, //!< [EXPORT] : [TC] + MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL = 32, //!< [EXPORT] : [TC] + }; + + ReturnValue_t checkAndAcquireTargetID(object_id_t* objectIdToSet, + const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t checkInterfaceAndAcquireMessageQueue( + MessageQueueId_t* messageQueueToSet, object_id_t* objectId); + + ReturnValue_t generateHkReport(const CommandMessage* hkMessage, + uint8_t subserviceId); + ReturnValue_t prepareReportingTogglingCommand(CommandMessage* command, + bool enableReporting, bool isDiagnostics, const uint8_t* tcData, + size_t tcDataLen); + ReturnValue_t prepareStructureReportingCommand(CommandMessage* command, + bool isDiagnostics, const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t prepareOneShotReportCommand(CommandMessage* command, + bool isDiagnostics, const uint8_t* tcData, size_t tcDataLen); + ReturnValue_t prepareCollectionIntervalModificationCommand( + CommandMessage* command, bool isDiagnostics, const uint8_t* tcData, + size_t tcDataLen); + + void handleUnrequestedReply(CommandMessage* reply) override; +}; + +#endif /* FSFW_PUS_SERVICE3HOUSEKEEPINGSERVICE_H_ */ diff --git a/pus/servicepackets/Service3Packets.h b/pus/servicepackets/Service3Packets.h new file mode 100644 index 000000000..05732e11b --- /dev/null +++ b/pus/servicepackets/Service3Packets.h @@ -0,0 +1,21 @@ +#ifndef FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_ +#define FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_ + +#include +#include + +/** + * @brief Subservices 25 and 26: TM packets + * @ingroup spacepackets + */ +class HkPacket { //!< [EXPORT] : [SUBSERVICE] 25, 26 +public: + sid_t sid; //!< [EXPORT] : [COMMENT] Structure ID (SID) of housekeeping data. + const uint8_t* hkData; //!< [EXPORT] : [MAXSIZE] Deduced size + size_t hkSize; //!< [EXPORT] : [IGNORE] + + HkPacket(sid_t sid, const uint8_t* data, size_t size): + sid(sid), hkData(data), hkSize(size) {} +}; + +#endif /* FSFW_PUS_SERVICEPACKETS_SERVICE3PACKETS_H_ */