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..106f8dc4 --- /dev/null +++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.cpp @@ -0,0 +1,142 @@ +#include "FreshDeviceHandlerBase.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()), + poolManager(this, nullptr) { + 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); +} + +[[nodiscard]] object_id_t FreshDeviceHandlerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +ReturnValue_t FreshDeviceHandlerBase::performOperation(uint8_t opCode) { + handleQueue(); + performDeviceOperation(opCode); + return returnvalue::OK; +} + +void FreshDeviceHandlerBase::startTransition(Mode_t mode_, Submode_t submode_) { + triggerEvent(CHANGING_MODE, mode_, submode_); + mode = mode_; + submode = submode_; + modeHelper.modeChanged(mode, submode); + modeChanged(mode, submode); + announceMode(false); +} + +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 = poolManager.handleHousekeepingMessage(&command); + if (result == returnvalue::OK) { + continue; + } + + result = handleCommandMessage(&command); + if (result == returnvalue::OK) { + continue; + } + command.setToUnknownCommand(); + messageQueue->reply(&command); + } +} + +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) { + if (health == HasHealthIF::FAULTY or health == HasHealthIF::PERMANENT_FAULTY) { + // TODO: Go to off where applicable. Health state machine? How does DHB do it? + } + healthHelper.setHealth(health); + return returnvalue::OK; +} + +// 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 = poolManager.initialize(messageQueue); + if (result != returnvalue::OK) { + return result; + } + return SystemObject::initialize(); +} diff --git a/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h new file mode 100644 index 00000000..ed5dd15a --- /dev/null +++ b/src/fsfw/devicehandlers/FreshDeviceHandlerBase.h @@ -0,0 +1,116 @@ +#pragma once + +#include "fsfw/action.h" +#include "fsfw/datapoollocal/HasLocalDataPoolIF.h" +#include "fsfw/datapoollocal/LocalDataPoolManager.h" +#include "fsfw/devicehandlers/DeviceHandlerIF.h" +#include "fsfw/health/HasHealthIF.h" +#include "fsfw/health/HealthHelper.h" +#include "fsfw/modes/HasModesIF.h" +#include "fsfw/objectmanager.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; + uint32_t msgQueueDepth = 10; +}; +class FreshDeviceHandlerBase : public SystemObject, + public DeviceHandlerIF, + public HasModesIF, + public HasHealthIF, + public ExecutableObjectIF, + public ModeTreeChildIF, + public ModeTreeConnectionIF, + public HasActionsIF, + public HasLocalDataPoolIF { + public: + explicit FreshDeviceHandlerBase(DhbConfig config); + virtual ~FreshDeviceHandlerBase() 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; + + /** + * Periodic helper executed function, implemented by child class. + */ + virtual void performDeviceOperation(uint8_t opCode) = 0; + + [[nodiscard]] object_id_t getObjectId() const override; + + // Executable overrides. + ReturnValue_t performOperation(uint8_t opCode) override; + ReturnValue_t initializeAfterTaskCreation() override; + + // System Object overrides. + ReturnValue_t initialize() override; + [[nodiscard]] MessageQueueId_t getCommandQueue() const override; + + // Health Overrides. + ReturnValue_t setHealth(HealthState health) override; + HasHealthIF::HealthState getHealth() override; + + // Executable Overrides. + void setTaskIF(PeriodicTaskIF* task) 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; + + // Action overrides. + virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy, + const uint8_t* data, size_t size) = 0; + + [[nodiscard]] uint32_t getPeriodicOperationFrequency() const override; + + protected: + virtual ReturnValue_t handleQueue(); + + // Mode Helpers. + virtual void modeChanged(Mode_t mode, Submode_t submode); + void startTransition(Mode_t mode, Submode_t submode) override; + void getMode(Mode_t* mode, Submode_t* submode) override; + void setToExternalControl() override; + void announceMode(bool recursive) override; + + private: + ActionHelper actionHelper; + ModeHelper modeHelper; + HealthHelper healthHelper; + LocalDataPoolManager poolManager; + + /** + * 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; + + // Pool Manager overrides. + LocalDataPoolManager* getHkManagerHandle() override; +};