diff --git a/src/fsfw/controller/ControllerBase.cpp b/src/fsfw/controller/ControllerBase.cpp index 2c151f5a..a4f51217 100644 --- a/src/fsfw/controller/ControllerBase.cpp +++ b/src/fsfw/controller/ControllerBase.cpp @@ -72,18 +72,17 @@ void ControllerBase::getMode(Mode_t* mode_, Submode_t* submode_) { *submode_ = this->submode; } -void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); } - void ControllerBase::announceMode(bool recursive) { triggerEvent(MODE_INFO, mode, submode); } +void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {} + +void ControllerBase::setToExternalControl() { healthHelper.setHealth(EXTERNAL_CONTROL); } + ReturnValue_t ControllerBase::performOperation(uint8_t opCode) { handleQueue(); performControlOperation(); return returnvalue::OK; } - -void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {} - ReturnValue_t ControllerBase::setHealth(HealthState health) { switch (health) { case HEALTHY: diff --git a/src/fsfw/devicehandlers/CMakeLists.txt b/src/fsfw/devicehandlers/CMakeLists.txt index 180a89da..77254bdd 100644 --- a/src/fsfw/devicehandlers/CMakeLists.txt +++ b/src/fsfw/devicehandlers/CMakeLists.txt @@ -7,4 +7,5 @@ target_sources( DeviceHandlerFailureIsolation.cpp DeviceHandlerMessage.cpp DeviceTmReportingWrapper.cpp + FreshDeviceHandlerBase.cpp HealthDevice.cpp) diff --git a/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp new file mode 100644 index 00000000..c113bee9 --- /dev/null +++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp @@ -0,0 +1,196 @@ +#include "FreshDeviceHandlerBase.h" + +#include "fsfw/devicehandlers/DeviceHandlerFailureIsolation.h" +#include "fsfw/ipc/QueueFactory.h" +#include "fsfw/subsystem/helper.h" + +FreshDeviceHandlerBase::FreshDeviceHandlerBase(DhbConfig config) + : SystemObject(config.objectId), + actionHelper(this, nullptr), + modeHelper(this), + healthHelper(this, getObjectId()), + paramHelper(this), + poolManager(this, nullptr), + defaultFdirParent(config.defaultFdirParent) { + auto mqArgs = MqArgs(config.objectId, static_cast(this)); + messageQueue = QueueFactory::instance()->createMessageQueue( + config.msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs); +} +FreshDeviceHandlerBase::~FreshDeviceHandlerBase() { + QueueFactory::instance()->deleteMessageQueue(messageQueue); + if (not hasCustomFdir) { + delete fdirInstance; + } +} + +[[nodiscard]] object_id_t FreshDeviceHandlerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +ReturnValue_t FreshDeviceHandlerBase::performOperation(uint8_t opCode) { + handleQueue(); + performDeviceOperation(opCode); + poolManager.performHkOperation(); + return returnvalue::OK; +} + +void FreshDeviceHandlerBase::startTransition(Mode_t mode_, Submode_t submode_) { + triggerEvent(CHANGING_MODE, mode_, submode_); + // Complete mode transition immediately by default. + setMode(mode_, submode_); +} + +void FreshDeviceHandlerBase::setMode(Mode_t newMode, Submode_t newSubmode) { + mode = newMode; + submode = newSubmode; + modeHelper.modeChanged(mode, submode); + modeChanged(mode, submode); + announceMode(false); +} + +void FreshDeviceHandlerBase::setMode(Mode_t newMode) { setMode(newMode, submode); } + +void FreshDeviceHandlerBase::getMode(Mode_t* mode_, Submode_t* submode_) { + *mode_ = this->mode; + *submode_ = this->submode; +} + +void FreshDeviceHandlerBase::announceMode(bool recursive) { + triggerEvent(MODE_INFO, mode, submode); +} + +void FreshDeviceHandlerBase::modeChanged(Mode_t mode_, Submode_t submode_) {} + +[[nodiscard]] MessageQueueId_t FreshDeviceHandlerBase::getCommandQueue() const { + return messageQueue->getId(); +} + +ReturnValue_t FreshDeviceHandlerBase::handleQueue() { + CommandMessage command; + ReturnValue_t result; + for (result = messageQueue->receiveMessage(&command); result == returnvalue::OK; + result = messageQueue->receiveMessage(&command)) { + result = actionHelper.handleActionMessage(&command); + if (result == returnvalue::OK) { + continue; + } + + result = modeHelper.handleModeCommand(&command); + if (result == returnvalue::OK) { + continue; + } + + result = healthHelper.handleHealthCommand(&command); + if (result == returnvalue::OK) { + continue; + } + + result = paramHelper.handleParameterMessage(&command); + if (result == returnvalue::OK) { + continue; + } + + result = poolManager.handleHousekeepingMessage(&command); + if (result == returnvalue::OK) { + continue; + } + + result = handleCommandMessage(&command); + if (result == returnvalue::OK) { + continue; + } + command.setToUnknownCommand(); + messageQueue->reply(&command); + } + return result; +} + +HasHealthIF::HealthState FreshDeviceHandlerBase::getHealth() { return healthHelper.getHealth(); } + +const HasHealthIF* FreshDeviceHandlerBase::getOptHealthIF() const { return this; } + +const HasModesIF& FreshDeviceHandlerBase::getModeIF() const { return *this; } + +ModeTreeChildIF& FreshDeviceHandlerBase::getModeTreeChildIF() { return *this; } + +ReturnValue_t FreshDeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenIF& parent) { + return modetree::connectModeTreeParent(parent, *this, &healthHelper, modeHelper); +} + +// Executable Overrides. +void FreshDeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; } + +// Pool Manager overrides. +LocalDataPoolManager* FreshDeviceHandlerBase::getHkManagerHandle() { return &poolManager; } + +[[nodiscard]] uint32_t FreshDeviceHandlerBase::getPeriodicOperationFrequency() const { + return this->executingTask->getPeriodMs(); +} + +ReturnValue_t FreshDeviceHandlerBase::initializeAfterTaskCreation() { + return poolManager.initializeAfterTaskCreation(); +} + +ReturnValue_t FreshDeviceHandlerBase::setHealth(HasHealthIF::HealthState health) { + // Assembly should handle commanding to OFF. + healthHelper.setHealth(health); + return returnvalue::OK; +} + +void FreshDeviceHandlerBase::triggerEvent(Event event, uint32_t parameter1, uint32_t parameter2) { + fdirInstance->triggerEvent(event, parameter1, parameter2); +} + +void FreshDeviceHandlerBase::forwardEvent(Event event, uint32_t parameter1, + uint32_t parameter2) const { + fdirInstance->triggerEvent(event, parameter1, parameter2); +} + +void FreshDeviceHandlerBase::setToExternalControl() { setHealth(HealthState::EXTERNAL_CONTROL); } + +// System Object overrides. +ReturnValue_t FreshDeviceHandlerBase::initialize() { + ReturnValue_t result = modeHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + result = healthHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + result = actionHelper.initialize(messageQueue); + if (result != returnvalue::OK) { + return result; + } + result = paramHelper.initialize(); + if (result != returnvalue::OK) { + return result; + } + + result = poolManager.initialize(messageQueue); + if (result != returnvalue::OK) { + return result; + } + if (fdirInstance == nullptr) { + hasCustomFdir = false; + fdirInstance = new DeviceHandlerFailureIsolation(getObjectId(), defaultFdirParent); + } + + result = fdirInstance->initialize(); + if (result != returnvalue::OK) { + return result; + } + return SystemObject::initialize(); +} + +ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uniqueId, + ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, + uint16_t startAtIndex) { + ReturnValue_t result = + fdirInstance->getParameter(domainId, uniqueId, parameterWrapper, newValues, startAtIndex); + if (result != INVALID_DOMAIN_ID) { + return result; + } + return INVALID_DOMAIN_ID; +} diff --git a/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h new file mode 100644 index 00000000..97f672b1 --- /dev/null +++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h @@ -0,0 +1,159 @@ +#pragma once + +#include "fsfw/action.h" +#include "fsfw/datapoollocal/HasLocalDataPoolIF.h" +#include "fsfw/datapoollocal/LocalDataPoolManager.h" +#include "fsfw/devicehandlers/DeviceHandlerIF.h" +#include "fsfw/fdir/FailureIsolationBase.h" +#include "fsfw/health/HasHealthIF.h" +#include "fsfw/health/HealthHelper.h" +#include "fsfw/modes/HasModesIF.h" +#include "fsfw/objectmanager.h" +#include "fsfw/parameters/ParameterHelper.h" +#include "fsfw/parameters/ReceivesParameterMessagesIF.h" +#include "fsfw/retval.h" +#include "fsfw/subsystem/ModeTreeChildIF.h" +#include "fsfw/subsystem/ModeTreeConnectionIF.h" +#include "fsfw/tasks/ExecutableObjectIF.h" +#include "fsfw/tasks/PeriodicTaskIF.h" + +struct DhbConfig { + explicit DhbConfig(object_id_t objectId) : objectId(objectId) {} + object_id_t objectId; + FailureIsolationBase* fdirInstance = nullptr; + object_id_t defaultFdirParent = objects::NO_OBJECT; + uint32_t msgQueueDepth = 10; +}; + +class FreshDeviceHandlerBase : public SystemObject, + public DeviceHandlerIF, + public HasModesIF, + public HasHealthIF, + public ExecutableObjectIF, + public ModeTreeChildIF, + public ModeTreeConnectionIF, + public HasActionsIF, + public ReceivesParameterMessagesIF, + public HasLocalDataPoolIF { + public: + explicit FreshDeviceHandlerBase(DhbConfig config); + ~FreshDeviceHandlerBase() override; + + /** + * Periodic helper executed function, implemented by child class. + */ + virtual void performDeviceOperation(uint8_t opCode) = 0; + + [[nodiscard]] object_id_t getObjectId() const override; + + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; + + HasHealthIF::HealthState getHealth() override; + + // Mode Tree Overrides. + [[nodiscard]] const HasHealthIF* getOptHealthIF() const override; + [[nodiscard]] const HasModesIF& getModeIF() const override; + ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override; + ModeTreeChildIF& getModeTreeChildIF() override; + + [[nodiscard]] uint32_t getPeriodicOperationFrequency() const override; + + protected: + // Pool Manager overrides. + LocalDataPoolManager* getHkManagerHandle() override; + ActionHelper actionHelper; + ModeHelper modeHelper; + HealthHelper healthHelper; + ParameterHelper paramHelper; + LocalDataPoolManager poolManager; + + bool hasCustomFdir = false; + FailureIsolationBase* fdirInstance; + object_id_t defaultFdirParent; + + /** + * Pointer to the task which executes this component, + * is invalid before setTaskIF was called. + */ + PeriodicTaskIF* executingTask = nullptr; + + Mode_t mode = HasModesIF::MODE_UNDEFINED; + Submode_t submode = 0; + + MessageQueueIF* messageQueue; + + virtual ReturnValue_t handleQueue(); + + // Mode Helpers. + virtual void modeChanged(Mode_t mode, Submode_t submode); + /** + * The default implementation sets the new mode immediately. If this is not applicable for + * certain modes, the user should provide a custom implementation, which performs rougly + * the same functionality of this function, when all the steps have been taken to reach the + * new mode. + */ + void startTransition(Mode_t mode, Submode_t submode) override; + virtual void setMode(Mode_t newMode, Submode_t newSubmode); + virtual void setMode(Mode_t newMode); + void getMode(Mode_t* mode, Submode_t* submode) override; + void setToExternalControl() override; + void announceMode(bool recursive) override; + // System Object overrides. + ReturnValue_t initialize() override; + + /** + * Implemented by child class. Handle all command messages which are + * not health, mode, action or housekeeping messages. + * @param message + * @return + */ + virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0; + + // HK manager abstract functions. + LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0; + ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap, + LocalDataPoolManager& poolManager) override = 0; + + // Mode abstract functions + ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, + uint32_t* msToReachTheMode) override = 0; + // Health Overrides. + ReturnValue_t setHealth(HealthState health) override; + // Action override. Forward to user. + ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) override = 0; + // Executable overrides. + ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initializeAfterTaskCreation() override; + + /** + * This calls the FDIR instance event trigger function. + * @param event + * @param parameter1 + * @param parameter2 + */ + void triggerEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) override; + /** + * This calls the FDIR instance event forward function. + * @param event + * @param parameter1 + * @param parameter2 + */ + void forwardEvent(Event event, uint32_t parameter1, uint32_t parameter2) const override; + /** + * This implementation handles the FDIR parameters. The user can override this to handle + * custom parameters. + * @param domainId + * @param uniqueId + * @param parameterWrapper + * @param newValues + * @param startAtIndex + * @return + */ + ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId, ParameterWrapper* parameterWrapper, + const ParameterWrapper* newValues, uint16_t startAtIndex) override; + + private: + // Executable Overrides. + void setTaskIF(PeriodicTaskIF* task) override; +};