Merge pull request 'health update' (#246) from KSat/fsfw:mueller/health-convergence into master

Reviewed-on: #246
This commit is contained in:
Steffen Gaisser 2020-11-02 15:26:51 +01:00
commit 719aab2a26
8 changed files with 122 additions and 99 deletions

View File

@ -1,5 +1,5 @@
#ifndef HASHEALTHIF_H_ #ifndef FSFW_HEALTH_HASHEALTHIF_H_
#define HASHEALTHIF_H_ #define FSFW_HEALTH_HASHEALTHIF_H_
#include "../events/Event.h" #include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
@ -8,9 +8,13 @@
class HasHealthIF { class HasHealthIF {
public: public:
typedef enum { enum HealthState: uint8_t {
HEALTHY = 1, FAULTY = 0, EXTERNAL_CONTROL = 2, NEEDS_RECOVERY = 3, PERMANENT_FAULTY = 4 HEALTHY = 1,
} HealthState; FAULTY = 0,
EXTERNAL_CONTROL = 2,
NEEDS_RECOVERY = 3,
PERMANENT_FAULTY = 4
};
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1); static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
@ -31,20 +35,17 @@ public:
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** /**
* set the Health State * @brief Set the Health State
*
* The parent will be informed, if the Health changes * The parent will be informed, if the Health changes
*
* @param health * @param health
*/ */
virtual ReturnValue_t setHealth(HealthState health) = 0; virtual ReturnValue_t setHealth(HealthState health) = 0;
/** /**
* get Health State * @brief Get Health State
* * @return Health State of the object
* @return Health State of the object
*/ */
virtual HasHealthIF::HealthState getHealth() = 0; virtual HasHealthIF::HealthState getHealth() = 0;
}; };
#endif /* HASHEALTHIF_H_ */ #endif /* FSFW_HEALTH_HASHEALTHIF_H_ */

View File

@ -12,13 +12,15 @@
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
/** /**
* Helper class for Objects that implement HasHealthIF * @brief Helper class for Objects that implement HasHealthIF
* @details
* It takes care of registering with the Health Table as well as handling
* health commands (including replying to the sender) and updating
* the Health Table.
* *
* It takes care of registering with the Health Table as well as handling health commands * If a parent is set in the ctor, the parent will be informed with a
* (including replying to the sender) and updating the Health Table. * @c HEALTH_INFO message about changes in the health state.
* * Note that a @c HEALTH_INFO is only generated if the Health
* If a parent is set in the ctor, the parent will be informed with a @c HEALTH_INFO message
* about changes in the health state. Note that a @c HEALTH_INFO is only generated if the Health
* changes, not for all @c HEALTH_SET commands received. * changes, not for all @c HEALTH_SET commands received.
* *
* It does NOT handle @c HEALTH_INFO messages * It does NOT handle @c HEALTH_INFO messages
@ -27,10 +29,9 @@ class HealthHelper {
public: public:
/** /**
* ctor
*
* @param owner * @param owner
* @param objectId the object Id to use when communication with the HealthTable * @param objectId The object Id to use when communication with
* the HealthTable
*/ */
HealthHelper(HasHealthIF* owner, object_id_t objectId); HealthHelper(HasHealthIF* owner, object_id_t objectId);
@ -56,8 +57,9 @@ public:
* *
* @param message * @param message
* @return * @return
* -@c RETURN_OK if the message was handled * -@c RETURN_OK if the message was handled
* -@c RETURN_FAILED if the message could not be handled (ie it was not a @c HEALTH_SET or @c HEALTH_READ message) * -@c RETURN_FAILED if the message could not be handled
* (ie it was not a @c HEALTH_SET or @c HEALTH_READ message)
*/ */
ReturnValue_t handleHealthCommand(CommandMessage *message); ReturnValue_t handleHealthCommand(CommandMessage *message);
@ -78,16 +80,19 @@ public:
HasHealthIF::HealthState getHealth(); HasHealthIF::HealthState getHealth();
/** /**
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present * @param parentQueue The queue ID of the parent object.
* Set to 0 if no parent present
*/ */
void setParentQueue(MessageQueueId_t parentQueue); void setParentQueue(MessageQueueId_t parentQueue);
/** /**
* *
* @param parentQueue the Queue id of the parent object. Set to 0 if no parent present * @param parentQueue The queue ID of the parent object.
* Set to 0 if no parent present
* @return * @return
* -@c RETURN_OK if the Health Table was found and the object could be registered * -@c RETURN_OK if the Health Table was found and the object
* -@c RETURN_FAILED else * could be registered
* -@c RETURN_FAILED else
*/ */
ReturnValue_t initialize(MessageQueueId_t parentQueue ); ReturnValue_t initialize(MessageQueueId_t parentQueue );
@ -110,11 +115,15 @@ private:
HasHealthIF* owner; HasHealthIF* owner;
/** /**
* if the #parentQueue is not NULL, a @c HEALTH_INFO message will be sent to this queue * if the #parentQueue is not NULL, a @c HEALTH_INFO message
* @param health the health is passed as parameter so that the number of calls to the health table can be minimized * will be sent to this queue
* @param health
* The health is passed as parameter so that the number of
* calls to the health table can be minimized
* @param oldHealth information of the previous health state. * @param oldHealth information of the previous health state.
*/ */
void informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth); void informParent(HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth);
void handleSetHealthCommand(CommandMessage *message); void handleSetHealthCommand(CommandMessage *message);
}; };

View File

@ -7,11 +7,13 @@ void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
message->setParameter2(oldHealth); message->setParameter2(oldHealth);
} }
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command) { void HealthMessage::setHealthMessage(CommandMessage* message,
Command_t command) {
message->setCommand(command); message->setCommand(command);
} }
HasHealthIF::HealthState HealthMessage::getHealth(const CommandMessage* message) { HasHealthIF::HealthState HealthMessage::getHealth(
const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter(); return (HasHealthIF::HealthState) message->getParameter();
} }

View File

@ -1,5 +1,5 @@
#ifndef HEALTHMESSAGE_H_ #ifndef FSFW_HEALTH_HEALTHMESSAGE_H_
#define HEALTHMESSAGE_H_ #define FSFW_HEALTH_HEALTHMESSAGE_H_
#include "HasHealthIF.h" #include "HasHealthIF.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
@ -7,14 +7,20 @@
class HealthMessage { class HealthMessage {
public: public:
static const uint8_t MESSAGE_ID = messagetypes::HEALTH_COMMAND; static const uint8_t MESSAGE_ID = messagetypes::HEALTH_COMMAND;
static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);//REPLY_COMMAND_OK/REPLY_REJECTED
static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(3); //NO REPLY! static const Command_t HEALTH_SET = MAKE_COMMAND_ID(1);
// No reply expected, health will be announced as event!
static const Command_t HEALTH_ANNOUNCE = MAKE_COMMAND_ID(2);
// Same as before, but all objects in health table will
// announce their health as events.
static const Command_t HEALTH_ANNOUNCE_ALL = MAKE_COMMAND_ID(3);
static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5); static const Command_t HEALTH_INFO = MAKE_COMMAND_ID(5);
static const Command_t REPLY_HEALTH_SET = MAKE_COMMAND_ID(6); static const Command_t REPLY_HEALTH_SET = MAKE_COMMAND_ID(6);
static void setHealthMessage(CommandMessage *message, Command_t command, static void setHealthMessage(CommandMessage *message, Command_t command,
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth = HasHealthIF::FAULTY); HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth = HasHealthIF::FAULTY);
static void setHealthMessage(CommandMessage *message, Command_t command); static void setHealthMessage(CommandMessage *message, Command_t command);
static HasHealthIF::HealthState getHealth(const CommandMessage *message); static HasHealthIF::HealthState getHealth(const CommandMessage *message);
@ -27,4 +33,4 @@ private:
HealthMessage(); HealthMessage();
}; };
#endif /* HEALTHMESSAGE_H_ */ #endif /* FSFW_HEALTH_HEALTHMESSAGE_H_ */

View File

@ -1,6 +1,7 @@
#include "HealthTable.h" #include "HealthTable.h"
#include "../serialize/SerializeAdapter.h" #include "../ipc/MutexHelper.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../serialize/SerializeAdapter.h"
HealthTable::HealthTable(object_id_t objectid) : HealthTable::HealthTable(object_id_t objectid) :
SystemObject(objectid) { SystemObject(objectid) {
@ -9,6 +10,12 @@ HealthTable::HealthTable(object_id_t objectid) :
mapIterator = healthMap.begin(); mapIterator = healthMap.begin();
} }
void HealthTable::setMutexTimeout(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
this->timeoutType = timeoutType;
this->mutexTimeoutMs = timeoutMs;
}
HealthTable::~HealthTable() { HealthTable::~HealthTable() {
MutexFactory::instance()->deleteMutex(mutex); MutexFactory::instance()->deleteMutex(mutex);
} }
@ -18,74 +25,63 @@ ReturnValue_t HealthTable::registerObject(object_id_t object,
if (healthMap.count(object) != 0) { if (healthMap.count(object) != 0) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
healthMap.insert( healthMap.emplace(object, initilialState);
std::pair<object_id_t, HasHealthIF::HealthState>(object,
initilialState));
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void HealthTable::setHealth(object_id_t object, void HealthTable::setHealth(object_id_t object,
HasHealthIF::HealthState newState) { HasHealthIF::HealthState newState) {
mutex->lockMutex(MutexIF::BLOCKING); MutexHelper(mutex, timeoutType, mutexTimeoutMs);
HealthMap::iterator iter = healthMap.find(object); HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) { if (iter != healthMap.end()) {
iter->second = newState; iter->second = newState;
} }
mutex->unlockMutex();
} }
HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) { HasHealthIF::HealthState HealthTable::getHealth(object_id_t object) {
HasHealthIF::HealthState state = HasHealthIF::HEALTHY; HasHealthIF::HealthState state = HasHealthIF::HEALTHY;
mutex->lockMutex(MutexIF::BLOCKING); MutexHelper(mutex, timeoutType, mutexTimeoutMs);
HealthMap::iterator iter = healthMap.find(object); HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) { if (iter != healthMap.end()) {
state = iter->second; state = iter->second;
} }
mutex->unlockMutex();
return state; return state;
} }
uint32_t HealthTable::getPrintSize() {
mutex->lockMutex(MutexIF::BLOCKING);
uint32_t size = healthMap.size() * 5 + 2;
mutex->unlockMutex();
return size;
}
bool HealthTable::hasHealth(object_id_t object) { bool HealthTable::hasHealth(object_id_t object) {
bool exits = false; MutexHelper(mutex, timeoutType, mutexTimeoutMs);
mutex->lockMutex(MutexIF::BLOCKING);
HealthMap::iterator iter = healthMap.find(object); HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) { if (iter != healthMap.end()) {
exits = true; return true;
} }
mutex->unlockMutex(); return false;
return exits; }
size_t HealthTable::getPrintSize() {
MutexHelper(mutex, timeoutType, mutexTimeoutMs);
uint32_t size = healthMap.size() * sizeof(object_id_t) +
sizeof(HasHealthIF::HealthState) + sizeof(uint16_t);
return size;
} }
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) { void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
mutex->lockMutex(MutexIF::BLOCKING); MutexHelper(mutex, timeoutType, mutexTimeoutMs);
size_t size = 0; size_t size = 0;
uint16_t count = healthMap.size(); uint16_t count = healthMap.size();
ReturnValue_t result = SerializeAdapter::serialize(&count, SerializeAdapter::serialize(&count,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG); &pointer, &size, maxSize, SerializeIF::Endianness::BIG);
HealthMap::iterator iter; for (const auto& health: healthMap) {
for (iter = healthMap.begin(); SerializeAdapter::serialize(&health.first,
iter != healthMap.end() && result == HasReturnvaluesIF::RETURN_OK;
++iter) {
result = SerializeAdapter::serialize(&iter->first,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG); &pointer, &size, maxSize, SerializeIF::Endianness::BIG);
uint8_t health = iter->second; uint8_t healthValue = health.second;
result = SerializeAdapter::serialize(&health, &pointer, &size, SerializeAdapter::serialize(&healthValue, &pointer, &size,
maxSize, SerializeIF::Endianness::BIG); maxSize, SerializeIF::Endianness::BIG);
} }
mutex->unlockMutex();
} }
ReturnValue_t HealthTable::iterate( ReturnValue_t HealthTable::iterate(HealthEntry *value, bool reset) {
std::pair<object_id_t, HasHealthIF::HealthState> *value, bool reset) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
mutex->lockMutex(MutexIF::BLOCKING); MutexHelper(mutex, timeoutType, mutexTimeoutMs);
if (reset) { if (reset) {
mapIterator = healthMap.begin(); mapIterator = healthMap.begin();
} }
@ -94,7 +90,5 @@ ReturnValue_t HealthTable::iterate(
} }
*value = *mapIterator; *value = *mapIterator;
mapIterator++; mapIterator++;
mutex->unlockMutex();
return result; return result;
} }

View File

@ -1,35 +1,47 @@
#ifndef HEALTHTABLE_H_ #ifndef FSFW_HEALTH_HEALTHTABLE_H_
#define HEALTHTABLE_H_ #define FSFW_HEALTH_HEALTHTABLE_H_
#include "HealthTableIF.h" #include "HealthTableIF.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
#include <map> #include <map>
typedef std::map<object_id_t, HasHealthIF::HealthState> HealthMap;
class HealthTable: public HealthTableIF, public SystemObject { class HealthTable: public HealthTableIF, public SystemObject {
public: public:
HealthTable(object_id_t objectid); HealthTable(object_id_t objectid);
virtual ~HealthTable(); virtual ~HealthTable();
virtual ReturnValue_t registerObject(object_id_t object, void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY);
virtual bool hasHealth(object_id_t object); /** HealthTableIF overrides */
virtual void setHealth(object_id_t object, HasHealthIF::HealthState newState); virtual ReturnValue_t registerObject(object_id_t object,
virtual HasHealthIF::HealthState getHealth(object_id_t); HasHealthIF::HealthState initilialState =
HasHealthIF::HEALTHY) override;
virtual size_t getPrintSize() override;
virtual void printAll(uint8_t *pointer, size_t maxSize) override;
virtual uint32_t getPrintSize(); /** ManagesHealthIF overrides */
virtual void printAll(uint8_t *pointer, size_t maxSize); virtual bool hasHealth(object_id_t object) override;
virtual void setHealth(object_id_t object,
HasHealthIF::HealthState newState) override;
virtual HasHealthIF::HealthState getHealth(object_id_t) override;
protected: protected:
using HealthMap = std::map<object_id_t, HasHealthIF::HealthState>;
using HealthEntry = std::pair<object_id_t, HasHealthIF::HealthState>;
MutexIF* mutex; MutexIF* mutex;
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t mutexTimeoutMs = 20;
HealthMap healthMap; HealthMap healthMap;
HealthMap::iterator mapIterator; HealthMap::iterator mapIterator;
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false); virtual ReturnValue_t iterate(
HealthEntry* value,
bool reset = false) override;
}; };
#endif /* HEALTHTABLE_H_ */ #endif /* FSFW_HEALTH_HEALTHTABLE_H_ */

View File

@ -1,26 +1,24 @@
#ifndef HEALTHTABLEIF_H_ #ifndef FSFW_HEALTH_HEALTHTABLEIF_H_
#define HEALTHTABLEIF_H_ #define FSFW_HEALTH_HEALTHTABLEIF_H_
#include "ManagesHealthIF.h" #include "ManagesHealthIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <map>
class HealthTableIF: public ManagesHealthIF { class HealthTableIF: public ManagesHealthIF {
friend class HealthCommandingService;
public: public:
virtual ~HealthTableIF() { virtual ~HealthTableIF() {}
}
virtual ReturnValue_t registerObject(object_id_t object, virtual ReturnValue_t registerObject(object_id_t object,
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0; HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
virtual uint32_t getPrintSize() = 0; virtual size_t getPrintSize() = 0;
virtual void printAll(uint8_t *pointer, size_t maxSize) = 0; virtual void printAll(uint8_t *pointer, size_t maxSize) = 0;
protected: protected:
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false) = 0; virtual ReturnValue_t iterate(
std::pair<object_id_t,HasHealthIF::HealthState> *value,
bool reset = false) = 0;
}; };
#endif /* HEALTHTABLEIF_H_ */ #endif /* FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ */

View File

@ -1,8 +1,9 @@
#ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ #ifndef FSFW_HEALTH_MANAGESHEALTHIF_H_
#define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ #define FSFW_HEALTH_MANAGESHEALTHIF_H_
#include "HasHealthIF.h" #include "HasHealthIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
class ManagesHealthIF { class ManagesHealthIF {
public: public:
virtual ~ManagesHealthIF() { virtual ~ManagesHealthIF() {
@ -49,4 +50,4 @@ public:
} }
}; };
#endif /* FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ */ #endif /* FSFW_HEALTH_MANAGESHEALTHIF_H_ */