From b665b2effe5af3f877c58e8c8f781c8573b64b15 Mon Sep 17 00:00:00 2001 From: "spahr@ksat-stuttgart.de" Date: Wed, 2 Apr 2025 22:13:50 +0200 Subject: [PATCH 1/4] add an adaption point which a user can use to convert a objectId of a shared power switch into a objectId of a device handler --- src/fsfw/devicehandlers/AssemblyBase.cpp | 4 ++-- src/fsfw/subsystem/SubsystemBase.cpp | 8 ++++++-- src/fsfw/subsystem/SubsystemBase.h | 6 ++++++ 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/fsfw/devicehandlers/AssemblyBase.cpp b/src/fsfw/devicehandlers/AssemblyBase.cpp index ada7c4a8..e2a5f524 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.cpp +++ b/src/fsfw/devicehandlers/AssemblyBase.cpp @@ -71,7 +71,7 @@ bool AssemblyBase::handleChildrenChangedHealth() { if (iter == childrenMap.end()) { return false; } - HealthState healthState = healthHelper.healthTable->getHealth(iter->first); + HealthState healthState = healthHelper.healthTable->getHealth(convertToDeviceObjectId(iter->first)); if (healthState == HasHealthIF::NEEDS_RECOVERY) { triggerEvent(TRYING_RECOVERY, iter->first, 0); recoveryState = RECOVERY_STARTED; @@ -170,7 +170,7 @@ ReturnValue_t AssemblyBase::checkChildrenStateOff() { ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) { ChildInfo childInfo = childrenMap.find(objectId)->second; - if (healthHelper.healthTable->isCommandable(objectId)) { + if (healthHelper.healthTable->isCommandable(convertToDeviceObjectId(objectId))) { if (childInfo.submode != SUBMODE_NONE) { return returnvalue::FAILED; } else { diff --git a/src/fsfw/subsystem/SubsystemBase.cpp b/src/fsfw/subsystem/SubsystemBase.cpp index 87fcfebf..7bedfadb 100644 --- a/src/fsfw/subsystem/SubsystemBase.cpp +++ b/src/fsfw/subsystem/SubsystemBase.cpp @@ -78,9 +78,9 @@ void SubsystemBase::executeTable(HybridIterator tableIter, Submod submodeToCommand = targetSubmode; } - if (healthHelper.healthTable->hasHealth(object)) { + if (healthHelper.healthTable->hasHealth(convertToDeviceObjectId(object))) { - switch (healthHelper.healthTable->getHealth(object)) { + switch (healthHelper.healthTable->getHealth(convertToDeviceObjectId(object))) { case NEEDS_RECOVERY: case FAULTY: case PERMANENT_FAULTY: @@ -353,3 +353,7 @@ ReturnValue_t SubsystemBase::registerChild(object_id_t childObjectId, MessageQue } return returnvalue::OK; } + +object_id_t SubsystemBase::convertToDeviceObjectId(object_id_t id) { + return id; +} \ No newline at end of file diff --git a/src/fsfw/subsystem/SubsystemBase.h b/src/fsfw/subsystem/SubsystemBase.h index 072b4ca4..5c21c5fd 100644 --- a/src/fsfw/subsystem/SubsystemBase.h +++ b/src/fsfw/subsystem/SubsystemBase.h @@ -153,6 +153,12 @@ class SubsystemBase : public SystemObject, virtual void announceMode(bool recursive) override; virtual void modeChanged(); + + /** + * @brief Provides an adaptation point for the user to change an objectId into + * a different objectId. + */ + virtual object_id_t convertToDeviceObjectId(object_id_t id); }; #endif /* FSFW_SUBSYSTEM_SUBSYSTEMBASE_H_ */ From 95520d7d0ced439d00e6a0f7f983511f02c0d69d Mon Sep 17 00:00:00 2001 From: "spahr@ksat-stuttgart.de" Date: Wed, 2 Apr 2025 22:18:31 +0200 Subject: [PATCH 2/4] Check if objectId exists in childrednmap first; this will prevent a hardfault --- src/fsfw/devicehandlers/AssemblyBase.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/fsfw/devicehandlers/AssemblyBase.cpp b/src/fsfw/devicehandlers/AssemblyBase.cpp index e2a5f524..72298384 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.cpp +++ b/src/fsfw/devicehandlers/AssemblyBase.cpp @@ -264,7 +264,15 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth); internalState = STATE_OVERWRITE_HEALTH; modeHelper.setForced(true); - sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL); + if(childrenMap.find(objectId) != childrenMap.end()) { + sendHealthCommand(childrenMap.at(objectId).commandQueue, EXTERNAL_CONTROL); + } else { +#if FSFW_CPP_OSTREAM_ENABLED == 1 + sif::debug << std::hex << SystemObject::getObjectId() << ": invalid mode table entry" + << std::endl; +#endif + } + } void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) { From 297ec261ce62b9e6f3cfde9a089ef5c2f61d3d3a Mon Sep 17 00:00:00 2001 From: "spahr@ksat-stuttgart.de" Date: Fri, 4 Apr 2025 10:11:11 +0200 Subject: [PATCH 3/4] make the recovery timeout accessable to the user --- src/fsfw/devicehandlers/AssemblyBase.cpp | 6 +++++- src/fsfw/devicehandlers/AssemblyBase.h | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/fsfw/devicehandlers/AssemblyBase.cpp b/src/fsfw/devicehandlers/AssemblyBase.cpp index 72298384..33a5148c 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.cpp +++ b/src/fsfw/devicehandlers/AssemblyBase.cpp @@ -227,7 +227,7 @@ bool AssemblyBase::checkAndHandleRecovery() { case RECOVERY_STARTED: // The recovery was already start in #handleChildrenChangedHealth and we just need // to wait for an off time period. - // TODO: make time period configurable + // The timeout can be defined by #setRecoveryWaitTimer recoveryState = RECOVERY_WAIT; recoveryOffTimer.resetTimer(); return true; @@ -282,3 +282,7 @@ void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) { triggerEvent(CHANGING_MODE, mode, submode); } } + +void AssemblyBase::setRecoveryWaitTimer(uint32_t timeoutMS) { + recoveryOffTimer.setTimeout(timeoutMS); +} diff --git a/src/fsfw/devicehandlers/AssemblyBase.h b/src/fsfw/devicehandlers/AssemblyBase.h index 5e0d826f..ac4feccd 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.h +++ b/src/fsfw/devicehandlers/AssemblyBase.h @@ -206,6 +206,8 @@ class AssemblyBase : public SubsystemBase { void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth); void triggerModeHelperEvents(Mode_t mode, Submode_t submode); + + void setRecoveryWaitTimer(uint32_t timeoutMS); }; #endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */ From b13b5b456db7eb147482afa341cfe8d5417be11f Mon Sep 17 00:00:00 2001 From: "spahr@ksat-stuttgart.de" Date: Mon, 14 Apr 2025 00:06:34 +0200 Subject: [PATCH 4/4] Give AssemblyBase more functionality: Support one-by-one commanding for childrend instead of sending all mode messages on one shot --- src/fsfw/devicehandlers/AssemblyBase.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/fsfw/devicehandlers/AssemblyBase.cpp b/src/fsfw/devicehandlers/AssemblyBase.cpp index 33a5148c..c22bd4ee 100644 --- a/src/fsfw/devicehandlers/AssemblyBase.cpp +++ b/src/fsfw/devicehandlers/AssemblyBase.cpp @@ -92,10 +92,15 @@ void AssemblyBase::handleChildrenTransition() { if (commandsOutstanding <= 0) { switch (internalState) { case STATE_NEED_SECOND_STEP: + { internalState = STATE_SECOND_STEP; - commandChildren(targetMode, targetSubmode); + ReturnValue_t result = commandChildren(targetMode, targetSubmode); + if(result == NEED_SECOND_STEP) { + internalState = STATE_NEED_SECOND_STEP; + } return; - case STATE_OVERWRITE_HEALTH: { + } + case STATE_OVERWRITE_HEALTH: { internalState = STATE_SINGLE_STEP; ReturnValue_t result = commandChildren(mode, submode); if (result == NEED_SECOND_STEP) {