Merge branch 'mueller/master' into mueller/DHB_separating_steps

This commit is contained in:
Robin Müller 2020-10-12 17:44:58 +02:00
commit d22c6a5fe9
275 changed files with 4916 additions and 3313 deletions

View File

@ -1,9 +1,11 @@
#include "ActionHelper.h" #include "ActionHelper.h"
#include "HasActionsIF.h" #include "HasActionsIF.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) : ActionHelper::ActionHelper(HasActionsIF* setOwner,
owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) { MessageQueueIF* useThisQueue) :
owner(setOwner), queueToUse(useThisQueue) {
} }
ActionHelper::~ActionHelper() { ActionHelper::~ActionHelper() {
@ -32,13 +34,15 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { void ActionHelper::step(uint8_t step, MessageQueueId_t reportTo,
ActionId_t commandId, ReturnValue_t result) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result); ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
queueToUse->sendMessage(reportTo, &reply); queueToUse->sendMessage(reportTo, &reply);
} }
void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result) { void ActionHelper::finish(MessageQueueId_t reportTo, ActionId_t commandId,
ReturnValue_t result) {
CommandMessage reply; CommandMessage reply;
ActionMessage::setCompletionReply(&reply, commandId, result); ActionMessage::setCompletionReply(&reply, commandId, result);
queueToUse->sendMessage(reportTo, &reply); queueToUse->sendMessage(reportTo, &reply);
@ -48,8 +52,8 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
queueToUse = queue; queueToUse = queue;
} }
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
store_address_t dataAddress) { ActionId_t actionId, store_address_t dataAddress) {
const uint8_t* dataPtr = NULL; const uint8_t* dataPtr = NULL;
size_t size = 0; size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size); ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
@ -85,21 +89,27 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
result = data->serialize(&dataPtr, &size, maxSize, SerializeIF::Endianness::BIG); result = data->serialize(&dataPtr, &size, maxSize,
SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress); ipcStore->deleteData(storeAddress);
return result; return result;
} }
//We don't need to report the objectId, as we receive REQUESTED data before the completion success message. // We don't need to report the objectId, as we receive REQUESTED data
//True aperiodic replies need to be reported with another dedicated message. // before the completion success message.
// True aperiodic replies need to be reported with
// another dedicated message.
ActionMessage::setDataReply(&reply, replyId, storeAddress); ActionMessage::setDataReply(&reply, replyId, storeAddress);
//TODO Service Implementation sucks at the moment // TODO: Service Implementation sucks at the moment
// TODO: why does it suck and why would someone need to hide the sender?
if (hideSender) { if (hideSender) {
result = MessageQueueSenderIF::sendMessage(reportTo, &reply); result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
} else { }
else {
result = queueToUse->sendMessage(reportTo, &reply); result = queueToUse->sendMessage(reportTo, &reply);
} }
if (result != HasReturnvaluesIF::RETURN_OK){ if (result != HasReturnvaluesIF::RETURN_OK){
ipcStore->deleteData(storeAddress); ipcStore->deleteData(storeAddress);
} }
@ -108,3 +118,39 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
void ActionHelper::resetHelper() { void ActionHelper::resetHelper() {
} }
ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
ActionId_t replyId, const uint8_t *data, size_t dataSize,
bool hideSender) {
CommandMessage reply;
store_address_t storeAddress;
ReturnValue_t result = ipcStore->addData(&storeAddress, data, dataSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (result != HasReturnvaluesIF::RETURN_OK) {
ipcStore->deleteData(storeAddress);
return result;
}
// We don't need to report the objectId, as we receive REQUESTED data
// before the completion success message.
// True aperiodic replies need to be reported with
// another dedicated message.
ActionMessage::setDataReply(&reply, replyId, storeAddress);
// TODO: Service Implementation sucks at the moment
// TODO: why does it suck and why would someone need to hide the sender?
if (hideSender) {
result = MessageQueueSenderIF::sendMessage(reportTo, &reply);
}
else {
result = queueToUse->sendMessage(reportTo, &reply);
}
if (result != HasReturnvaluesIF::RETURN_OK){
ipcStore->deleteData(storeAddress);
}
return result;
}

View File

@ -1,15 +1,18 @@
#ifndef ACTIONHELPER_H_ #ifndef FSFW_ACTION_ACTIONHELPER_H_
#define ACTIONHELPER_H_ #define FSFW_ACTION_ACTIONHELPER_H_
#include "ActionMessage.h" #include "ActionMessage.h"
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
/** /**
* \brief Action Helper is a helper class which handles action messages * @brief Action Helper is a helper class which handles action messages
* *
* Components which use the HasActionIF this helper can be used to handle the action messages. * Components which use the HasActionIF this helper can be used to handle
* It does handle step messages as well as other answers to action calls. It uses the executeAction function * the action messages.
* of its owner as callback. The call of the initialize function is mandatory and it needs a valid messageQueueIF pointer! * It does handle step messages as well as other answers to action calls.
* It uses the executeAction function of its owner as callback.
* The call of the initialize function is mandatory and needs a
* valid MessageQueueIF pointer!
*/ */
class HasActionsIF; class HasActionsIF;
@ -18,7 +21,8 @@ public:
/** /**
* Constructor of the action helper * Constructor of the action helper
* @param setOwner Pointer to the owner of the interface * @param setOwner Pointer to the owner of the interface
* @param useThisQueue messageQueue to be used, can be set during initialize function as well. * @param useThisQueue messageQueue to be used, can be set during
* initialize function as well.
*/ */
ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue); ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue);
@ -26,28 +30,35 @@ public:
/** /**
* Function to be called from the owner with a new command message * Function to be called from the owner with a new command message
* *
* If the message is a valid action message the helper will use the executeAction function from HasActionsIF. * If the message is a valid action message the helper will use the
* If the message is invalid or the callback fails a message reply will be send to the sender of the message automatically. * executeAction function from HasActionsIF.
* If the message is invalid or the callback fails a message reply will be
* send to the sender of the message automatically.
* *
* @param command Pointer to a command message received by the owner * @param command Pointer to a command message received by the owner
* @return HasReturnvaluesIF::RETURN_OK if the message is a action message, CommandMessage::UNKNOW_COMMAND if this message ID is unkown * @return HasReturnvaluesIF::RETURN_OK if the message is a action message,
* CommandMessage::UNKNOW_COMMAND if this message ID is unkown
*/ */
ReturnValue_t handleActionMessage(CommandMessage* command); ReturnValue_t handleActionMessage(CommandMessage* command);
/** /**
* Helper initialize function. Must be called before use of any other helper function * Helper initialize function. Must be called before use of any other
* @param queueToUse_ Pointer to the messageQueue to be used, optional if queue was set in constructor * helper function
* @param queueToUse_ Pointer to the messageQueue to be used, optional
* if queue was set in constructor
* @return Returns RETURN_OK if successful * @return Returns RETURN_OK if successful
*/ */
ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr); ReturnValue_t initialize(MessageQueueIF* queueToUse_ = nullptr);
/** /**
* Function to be called from the owner to send a step message. Success or failure will be determined by the result value. * Function to be called from the owner to send a step message.
* Success or failure will be determined by the result value.
* *
* @param step Number of steps already done * @param step Number of steps already done
* @param reportTo The messageQueueId to report the step message to * @param reportTo The messageQueueId to report the step message to
* @param commandId ID of the executed command * @param commandId ID of the executed command
* @param result Result of the execution * @param result Result of the execution
*/ */
void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void step(uint8_t step, MessageQueueId_t reportTo, ActionId_t commandId,
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
/** /**
* Function to be called by the owner to send a action completion message * Function to be called by the owner to send a action completion message
* *
@ -55,39 +66,59 @@ public:
* @param commandId ID of the executed command * @param commandId ID of the executed command
* @param result Result of the execution * @param result Result of the execution
*/ */
void finish(MessageQueueId_t reportTo, ActionId_t commandId, ReturnValue_t result = HasReturnvaluesIF::RETURN_OK); void finish(MessageQueueId_t reportTo, ActionId_t commandId,
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK);
/** /**
* Function to be called by the owner if an action does report data * Function to be called by the owner if an action does report data.
* * Takes a SerializeIF* pointer and serializes it into the IPC store.
* @param reportTo MessageQueueId_t to report the action completion message to * @param reportTo MessageQueueId_t to report the action completion
* message to
* @param replyId ID of the executed command * @param replyId ID of the executed command
* @param data Pointer to the data * @param data Pointer to the data
* @return Returns RETURN_OK if successful, otherwise failure code * @return Returns RETURN_OK if successful, otherwise failure code
*/ */
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId, SerializeIF* data, bool hideSender = false); ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
SerializeIF* data, bool hideSender = false);
/** /**
* Function to setup the MessageQueueIF* of the helper. Can be used to set the messageQueueIF* if * Function to be called by the owner if an action does report data.
* message queue is unavailable at construction and initialize but must be setup before first call of other functions. * Takes the raw data and writes it into the IPC store.
* @param reportTo MessageQueueId_t to report the action completion
* message to
* @param replyId ID of the executed command
* @param data Pointer to the data
* @return Returns RETURN_OK if successful, otherwise failure code
*/
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
const uint8_t* data, size_t dataSize, bool hideSender = false);
/**
* Function to setup the MessageQueueIF* of the helper. Can be used to
* set the MessageQueueIF* if message queue is unavailable at construction
* and initialize but must be setup before first call of other functions.
* @param queue Queue to be used by the helper * @param queue Queue to be used by the helper
*/ */
void setQueueToUse(MessageQueueIF *queue); void setQueueToUse(MessageQueueIF *queue);
protected: protected:
static const uint8_t STEP_OFFSET = 1;//!< Increase of value of this per step //!< Increase of value of this per step
static const uint8_t STEP_OFFSET = 1;
HasActionsIF* owner;//!< Pointer to the owner HasActionsIF* owner;//!< Pointer to the owner
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with //! Queue to be used as response sender, has to be set in ctor or with
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue) //! setQueueToUse
MessageQueueIF* queueToUse;
//! Pointer to an IPC Store, initialized during construction or
StorageManagerIF* ipcStore = nullptr;
/** /**
*Internal function called by handleActionMessage(CommandMessage* command) * Internal function called by handleActionMessage
*
* @param commandedBy MessageQueueID of Commander * @param commandedBy MessageQueueID of Commander
* @param actionId ID of action to be done * @param actionId ID of action to be done
* @param dataAddress Address of additional data in IPC Store * @param dataAddress Address of additional data in IPC Store
*/ */
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId, store_address_t dataAddress); virtual void prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress);
/** /**
* * @brief Default implementation is empty.
*/ */
virtual void resetHelper(); virtual void resetHelper();
}; };
#endif /* ACTIONHELPER_H_ */ #endif /* FSFW_ACTION_ACTIONHELPER_H_ */

View File

@ -47,10 +47,9 @@ public:
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** /**
* Execute or initialize the execution of a certain function. * Execute or initialize the execution of a certain function.
* Returning #EXECUTION_FINISHED or a failure code, nothing else needs to * When used in conjunction with the ActionHelper class, returning
* be done. When needing more steps, return RETURN_OK and issue steps and * a return code which is not equal to RETURN_OK will trigger a step reply
* completion manually. * with step 0.
* One "step failed" or completion report must be issued!
*/ */
virtual ReturnValue_t executeAction(ActionId_t actionId, virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0; MessageQueueId_t commandedBy, const uint8_t* data, size_t size) = 0;

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_ #ifndef FSFW_CONTAINER_ARRAYLIST_H_
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_ #define FSFW_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
@ -20,6 +20,30 @@ public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST; static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01); static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
* This is the allocating constructor.
* It allocates an array of the specified size.
* @param maxSize
*/
ArrayList(count_t maxSize) :
size(0), maxSize_(maxSize), allocated(true) {
entries = new T[maxSize];
}
/**
* This is the non-allocating constructor
*
* It expects a pointer to an array of a certain size and initializes
* itself to it.
*
* @param storage the array to use as backend
* @param maxSize size of storage
* @param size size of data already present in storage
*/
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
}
/** /**
* Copying is forbiden by declaring copy ctor and copy assignment deleted * Copying is forbiden by declaring copy ctor and copy assignment deleted
* It is too ambigous in this case. * It is too ambigous in this case.
@ -33,30 +57,6 @@ public:
*/ */
count_t size; count_t size;
/**
* This is the allocating constructor;
*
* It allocates an array of the specified size.
*
* @param maxSize
*/
ArrayList(count_t maxSize) :
size(0), maxSize_(maxSize), allocated(true) {
entries = new T[maxSize];
}
/**
* This is the non-allocating constructor
*
* It expects a pointer to an array of a certain size and initializes itself to it.
*
* @param storage the array to use as backend
* @param maxSize size of storage
* @param size size of data already present in storage
*/
ArrayList(T *storage, count_t maxSize, count_t size = 0) :
size(size), entries(storage), maxSize_(maxSize), allocated(false) {
}
/** /**
* Destructor, if the allocating constructor was used, it deletes the array. * Destructor, if the allocating constructor was used, it deletes the array.
@ -116,7 +116,11 @@ public:
return tmp; return tmp;
} }
T operator*() { T& operator*() {
return *value;
}
const T& operator*() const {
return *value; return *value;
} }
@ -127,18 +131,18 @@ public:
const T *operator->() const { const T *operator->() const {
return value; return value;
} }
//SHOULDDO this should be implemented as non-member
bool operator==(const typename ArrayList<T, count_t>::Iterator& other) const{
return (value == other.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
}; };
friend bool operator==(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) {
return (lhs.value == rhs.value);
}
friend bool operator!=(const ArrayList::Iterator& lhs,
const ArrayList::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
/** /**
* Iterator pointing to the first stored elmement * Iterator pointing to the first stored elmement
* *
@ -192,7 +196,7 @@ public:
* *
* @return maximum number of elements * @return maximum number of elements
*/ */
uint32_t maxSize() const { size_t maxSize() const {
return this->maxSize_; return this->maxSize_;
} }
@ -236,7 +240,7 @@ protected:
/** /**
* remembering the maximum size * remembering the maximum size
*/ */
uint32_t maxSize_; size_t maxSize_;
/** /**
* true if the array was allocated and needs to be deleted in the destructor. * true if the array was allocated and needs to be deleted in the destructor.
@ -244,4 +248,6 @@ protected:
bool allocated; bool allocated;
}; };
#endif /* ARRAYLIST_H_ */
#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */

View File

@ -27,14 +27,27 @@ public:
/** /**
* @brief Custom copy constructor which prevents setting the * @brief Custom copy constructor which prevents setting the
* underlying pointer wrong. * underlying pointer wrong. This function allocates memory!
* @details This is a very heavy operation so try to avoid this!
*
*/ */
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other), DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
fifoVector(other.maxCapacity) { fifoVector(other.maxCapacity) {
this->fifoVector = other.fifoVector;
this->setContainer(fifoVector.data()); this->setContainer(fifoVector.data());
} }
/**
* @brief Custom assignment operator
* @details This is a very heavy operation so try to avoid this!
* @param other DyamicFIFO to copy from
*/
DynamicFIFO& operator=(const DynamicFIFO& other){
FIFOBase<T>::operator=(other);
this->fifoVector = other.fifoVector;
this->setContainer(fifoVector.data());
return *this;
}
private: private:
std::vector<T> fifoVector; std::vector<T> fifoVector;
}; };

View File

@ -25,9 +25,21 @@ public:
* @param other * @param other
*/ */
FIFO(const FIFO& other): FIFOBase<T>(other) { FIFO(const FIFO& other): FIFOBase<T>(other) {
this->fifoArray = other.fifoArray;
this->setContainer(fifoArray.data()); this->setContainer(fifoArray.data());
} }
/**
* @brief Custom assignment operator
* @param other
*/
FIFO& operator=(const FIFO& other){
FIFOBase<T>::operator=(other);
this->fifoArray = other.fifoArray;
this->setContainer(fifoArray.data());
return *this;
}
private: private:
std::array<T, capacity> fifoArray; std::array<T, capacity> fifoArray;
}; };

View File

@ -19,32 +19,46 @@ public:
/** /**
* Insert value into FIFO * Insert value into FIFO
* @param value * @param value
* @return * @return RETURN_OK on success, FULL if full
*/ */
ReturnValue_t insert(T value); ReturnValue_t insert(T value);
/** /**
* Retrieve item from FIFO. This removes the item from the FIFO. * Retrieve item from FIFO. This removes the item from the FIFO.
* @param value * @param value Must point to a valid T
* @return * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t retrieve(T *value); ReturnValue_t retrieve(T *value);
/** /**
* Retrieve item from FIFO without removing it from FIFO. * Retrieve item from FIFO without removing it from FIFO.
* @param value * @param value Must point to a valid T
* @return * @return RETURN_OK on success, EMPTY if empty and FAILED if nullptr check failed
*/ */
ReturnValue_t peek(T * value); ReturnValue_t peek(T * value);
/** /**
* Remove item from FIFO. * Remove item from FIFO.
* @return * @return RETURN_OK on success, EMPTY if empty
*/ */
ReturnValue_t pop(); ReturnValue_t pop();
/***
* Check if FIFO is empty
* @return True if empty, False if not
*/
bool empty(); bool empty();
/***
* Check if FIFO is Full
* @return True if full, False if not
*/
bool full(); bool full();
/***
* Current used size (elements) used
* @return size_t in elements
*/
size_t size(); size_t size();
/***
* Get maximal capacity of fifo
* @return size_t with max capacity of this fifo
*/
size_t getMaxCapacity() const; size_t getMaxCapacity() const;
protected: protected:

View File

@ -26,6 +26,9 @@ inline ReturnValue_t FIFOBase<T>::retrieve(T* value) {
if (empty()) { if (empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
*value = values[readIndex]; *value = values[readIndex];
readIndex = next(readIndex); readIndex = next(readIndex);
--currentSize; --currentSize;
@ -38,6 +41,9 @@ inline ReturnValue_t FIFOBase<T>::peek(T* value) {
if(empty()) { if(empty()) {
return EMPTY; return EMPTY;
} else { } else {
if (value == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
*value = values[readIndex]; *value = values[readIndex];
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,51 +1,32 @@
#ifndef FIXEDARRAYLIST_H_ #ifndef FIXEDARRAYLIST_H_
#define FIXEDARRAYLIST_H_ #define FIXEDARRAYLIST_H_
#include "../container/ArrayList.h" #include "ArrayList.h"
#include <cmath>
/** /**
* @brief Array List with a fixed maximum size * \ingroup container
* @ingroup container
*/ */
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t> template<typename T, size_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> { class FixedArrayList: public ArrayList<T, count_t> {
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
private: private:
T data[MAX_SIZE]; T data[MAX_SIZE];
public: public:
/**
* (Robin) Maybe we should also implement move assignment and move ctor.
* Or at least delete them.
*/
FixedArrayList() : FixedArrayList() :
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
} }
// (Robin): We could create a constructor to initialize the fixed array list
// with data and the known size field
// so it can be used for serialization too (with SerialFixedArrrayListAdapter)
// is this feasible?
/**
* Initialize a fixed array list with data and number of data fields.
* Endianness of entries can be swapped optionally.
* @param data_
* @param count
* @param swapArrayListEndianess
*/
FixedArrayList(T * data_, count_t count):
ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, data_, count * sizeof(T));
this->size = count;
}
FixedArrayList(const FixedArrayList& other) : FixedArrayList(const FixedArrayList& other) :
ArrayList<T, count_t>(data, MAX_SIZE) { ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));
this->entries = data; this->entries = data;
this->size = other.size;
} }
FixedArrayList& operator=(FixedArrayList other) { FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data)); memcpy(this->data, other.data, sizeof(this->data));
this->entries = data; this->entries = data;
this->size = other.size;
return *this; return *this;
} }

View File

@ -1,19 +1,27 @@
#ifndef FIXEDMAP_H_ #ifndef FSFW_CONTAINER_FIXEDMAP_H_
#define FIXEDMAP_H_ #define FSFW_CONTAINER_FIXEDMAP_H_
#include "../container/ArrayList.h" #include "ArrayList.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <utility> #include <utility>
#include <type_traits>
/** /**
* @brief Map implementation for maps with a pre-defined size. * @brief Map implementation for maps with a pre-defined size.
* @details Can be initialized with desired maximum size. * @details
* Iterator is used to access <key,value> pair and * Can be initialized with desired maximum size.
* iterate through map entries. Complexity O(n). * Iterator is used to access <key,value> pair and iterate through map entries.
* Complexity O(n).
* @warning Iterators return a non-const key_t in the pair.
* @warning A User is not allowed to change the key, otherwise the map is corrupted.
* @ingroup container * @ingroup container
*/ */
template<typename key_t, typename T> template<typename key_t, typename T>
class FixedMap: public SerializeIF { class FixedMap: public SerializeIF {
static_assert (std::is_trivially_copyable<T>::value or
std::is_base_of<SerializeIF, T>::value,
"Types used in FixedMap must either be trivial copy-able or a "
"derived class from SerializeIF to be serialize-able");
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
@ -51,28 +59,17 @@ public:
Iterator(std::pair<key_t, T> *pair) : Iterator(std::pair<key_t, T> *pair) :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) { ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair) {
} }
T operator*() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
// -> operator overloaded, can be used to access value
T *operator->() {
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
// Can be used to access the key of the iterator
key_t first() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->first;
}
// Alternative to access value, similar to std::map implementation
T second() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
}; };
friend bool operator==(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) {
return (lhs.value == rhs.value);
}
friend bool operator!=(const typename FixedMap::Iterator& lhs,
const typename FixedMap::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
Iterator begin() const { Iterator begin() const {
return Iterator(&theMap[0]); return Iterator(&theMap[0]);
@ -86,16 +83,16 @@ public:
return _size; return _size;
} }
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) { ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr) {
if (exists(key) == HasReturnvaluesIF::RETURN_OK) { if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
return FixedMap::KEY_ALREADY_EXISTS; return KEY_ALREADY_EXISTS;
} }
if (_size == theMap.maxSize()) { if (_size == theMap.maxSize()) {
return FixedMap::MAP_FULL; return MAP_FULL;
} }
theMap[_size].first = key; theMap[_size].first = key;
theMap[_size].second = value; theMap[_size].second = value;
if (storedValue != NULL) { if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[_size]); *storedValue = Iterator(&theMap[_size]);
} }
++_size; ++_size;
@ -156,6 +153,24 @@ public:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
bool empty() {
if(_size == 0) {
return true;
}
else {
return false;
}
}
bool full() {
if(_size >= theMap.maxSize()) {
return true;
}
else {
return false;
}
}
void clear() { void clear() {
_size = 0; _size = 0;
} }
@ -164,16 +179,6 @@ public:
return theMap.maxSize(); return theMap.maxSize();
} }
bool full() {
if(_size == theMap.maxSize()) {
return true;
}
else {
return false;
}
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const { size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&this->_size, ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
@ -222,4 +227,4 @@ public:
}; };
#endif /* FIXEDMAP_H_ */ #endif /* FSFW_CONTAINER_FIXEDMAP_H_ */

View File

@ -1,171 +1,206 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ #define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#include "../container/ArrayList.h" #include "ArrayList.h"
#include <cstring> #include <cstring>
#include <set>
/** /**
* @brief Map implementation which allows entries with identical keys * @brief An associative container which allows multiple entries of the same key.
* @details * @details
* Performs no dynamic memory allocation except on initialization. * Same keys are ordered by KEY_COMPARE function which is std::less<key_t> > by default.
* Uses an ArrayList as the underlying container and thus has a linear *
* It uses the ArrayList, so technically this is not a real map, it is an array of pairs
* of type key_t, T. It is ordered by key_t as FixedMap but allows same keys. Thus it has a linear
* complexity O(n). As long as the number of entries remains low, this * complexity O(n). As long as the number of entries remains low, this
* should not be an issue. * should not be an issue.
* The number of insertion and deletion operation should be minimized * The number of insertion and deletion operation should be minimized
* as those incur exensive memory move operations (the underlying container * as those incur extensive memory move operations (the underlying container
* is not node based). * is not node based).
* @ingroup container *
* Its of fixed size so no allocations are performed after the construction.
*
* The maximum size is given as first parameter of the constructor.
*
* It provides an iterator to do list iterations.
*
* The type T must have a copy constructor if it is not trivial copy-able.
*
* @warning Iterators return a non-const key_t in the pair.
* @warning A User is not allowed to change the key, otherwise the map is corrupted.
*
* \ingroup container
*/ */
template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>> template<typename key_t, typename T, typename KEY_COMPARE = std::less<key_t>>
class FixedOrderedMultimap { class FixedOrderedMultimap {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP; static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MULTIMAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01); static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02); static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
/** /***
* Initializes the ordered multimap with a fixed maximum size. * Constructor which needs a size_t for the maximum allowed size
* @param maxSize *
* Can not be resized during runtime
*
* Allocates memory at construction
* @param maxSize size_t of Maximum allowed size
*/ */
FixedOrderedMultimap(size_t maxSize); FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
}
virtual ~FixedOrderedMultimap() {} /***
* Virtual destructor frees Memory by deleting its member
*/
virtual ~FixedOrderedMultimap() {
}
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator { /***
* Special iterator for FixedOrderedMultimap
*/
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
public: public:
/** Returns an iterator to nullptr */ Iterator() :
Iterator(); ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
/** Initializes iterator to given entry */ }
Iterator(std::pair<key_t, T> *pair);
/** Dereference operator can be used to get value */ Iterator(std::pair<key_t, T> *pair) :
T operator*(); ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
/** Arrow operator can be used to get pointer to value */ }
T *operator->();
}; };
/** Iterator to start of map */ /***
Iterator begin() const; * Returns an iterator pointing to the first element
/** Iterator to end of map */ * @return Iterator pointing to first element
Iterator end() const; */
/** Current (variable) size of the map */ Iterator begin() const {
size_t size() const; return Iterator(&theMap[0]);
}
/** /**
* Insert a key/value pair inside the map. An iterator to the stored * Returns an iterator pointing to one element past the end
* value might be returned optionally. * @return Iterator pointing to one element past the end
* @param key */
* @param value Iterator end() const {
* @param storedValue return Iterator(&theMap[_size]);
* @return }
/***
* Returns the current size of the map (not maximum size!)
* @return Current size
*/
size_t size() const{
return _size;
}
/**
* Clears the map, does not deallocate any memory
*/
void clear(){
_size = 0;
}
/**
* Returns the maximum size of the map
* @return Maximum size of the map
*/
size_t maxSize() const{
return theMap.maxSize();
}
/***
* Used to insert a key and value separately.
*
* @param[in] key Key of the new element
* @param[in] value Value of the new element
* @param[in/out] (optional) storedValue On success this points to the new value, otherwise a nullptr
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/ */
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr); ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
/**
* Insert a given std::pair<key, value> /***
* @param pair * Used to insert new pair instead of single values
* @return *
* @param pair Pair to be inserted
* @return RETURN_OK if insert was successful, MAP_FULL if no space is available
*/ */
ReturnValue_t insert(std::pair<key_t, T> pair); ReturnValue_t insert(std::pair<key_t, T> pair);
/**
* Checks existence of key in map. /***
* @param key * Can be used to check if a certain key is in the map
* @return * @param key Key to be checked
* - @c KEY_DOES_NOT_EXIST if key does not exists. * @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
* - @c RETURN_OK otherwise.
*/ */
ReturnValue_t exists(key_t key) const; ReturnValue_t exists(key_t key) const;
ReturnValue_t erase(Iterator *iter) { /***
uint32_t i; * Used to delete the element in the iterator
if ((i = findFirstIndex((*iter).value->first)) >= _size) { *
return KEY_DOES_NOT_EXIST; * The iterator will point to the element before or begin(),
} * but never to one element in front of the map.
removeFromPosition(i); *
if (*iter != begin()) { * @warning The iterator needs to be valid and dereferenceable
(*iter)--; * @param[in/out] iter Pointer to iterator to the element that needs to be ereased
} else { * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*iter = begin(); */
} ReturnValue_t erase(Iterator *iter);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t erase(key_t key) { /***
uint32_t i; * Used to erase by key
if ((i = findFirstIndex(key)) >= _size) { * @param key Key to be erased
return KEY_DOES_NOT_EXIST; * @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
} */
do { ReturnValue_t erase(key_t key);
removeFromPosition(i);
i = findFirstIndex(key, i);
} while (i < _size);
return HasReturnvaluesIF::RETURN_OK;
}
/***
* Find returns the first appearance of the key
*
* If the key does not exist, it points to end()
*
* @param key Key to search for
* @return Iterator pointing to the first entry of key
*/
Iterator find(key_t key) const{ Iterator find(key_t key) const{
ReturnValue_t result = exists(key); ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return end(); return end();
} }
return Iterator(&theMap[findFirstIndex(key)]); return Iterator(&theMap[findFirstIndex(key)]);
};
/***
* Finds first entry of the given key and returns a
* pointer to the value
*
* @param key Key to search for
* @param value Found value
* @return RETURN_OK if it points to the value,
* KEY_DOES_NOT_EXIST if the key is not in the map
*/
ReturnValue_t find(key_t key, T **value) const;
friend bool operator==(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) {
return (lhs.value == rhs.value);
} }
ReturnValue_t find(key_t key, T **value) const { friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
ReturnValue_t result = exists(key); const typename FixedOrderedMultimap::Iterator& rhs) {
if (result != HasReturnvaluesIF::RETURN_OK) { return not (lhs.value == rhs.value);
return result;
}
*value = &theMap[findFirstIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
}
void clear() {
_size = 0;
}
size_t maxSize() const {
return theMap.maxSize();
} }
private: private:
typedef KEY_COMPARE compare; typedef KEY_COMPARE compare;
compare myComp; compare myComp;
ArrayList<std::pair<key_t, T>, uint32_t> theMap; ArrayList<std::pair<key_t, T>, size_t> theMap;
size_t _size; size_t _size;
uint32_t findFirstIndex(key_t key, uint32_t startAt = 0) const { size_t findFirstIndex(key_t key, size_t startAt = 0) const;
if (startAt >= _size) {
return startAt + 1;
}
uint32_t i = startAt;
for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
uint32_t findNicePlace(key_t key) const { size_t findNicePlace(key_t key) const;
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
if (myComp(key, theMap[i].first)) {
return i;
}
}
return i;
}
void removeFromPosition(uint32_t position) { void removeFromPosition(size_t position);
if (_size <= position) {
return;
}
memmove(&theMap[position], &theMap[position + 1],
(_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size;
}
}; };
#include "FixedOrderedMultimap.tpp" #include "FixedOrderedMultimap.tpp"
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */ #endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */

View File

@ -1,59 +1,14 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ #ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ #define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_
template<typename key_t, typename T, typename KEY_COMPARE>
inline FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::Iterator():
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(){}
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::Iterator( inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
std::pair<key_t, T> *pair):
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair){}
template<typename key_t, typename T, typename KEY_COMPARE>
inline T FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::operator*() {
return ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline typename FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator
FixedOrderedMultimap<key_t, T, KEY_COMPARE>::begin() const {
return Iterator(&theMap[0]);
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline typename FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator
FixedOrderedMultimap<key_t, T, KEY_COMPARE>::end() const {
return Iterator(&theMap[_size]);
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::size() const {
return _size;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline T* FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::operator->() {
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline FixedOrderedMultimap<key_t, T, KEY_COMPARE>::FixedOrderedMultimap(
size_t maxSize): theMap(maxSize), _size(0) {}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(
key_t key, T value, Iterator *storedValue) {
if (_size == theMap.maxSize()) { if (_size == theMap.maxSize()) {
return MAP_FULL; return MAP_FULL;
} }
uint32_t position = findNicePlace(key); size_t position = findNicePlace(key);
// Compiler might emitt warning because std::pair is not a POD type (yet..) memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2342.htm#std::pair-example
// Should still work without issues.
std::memmove(&theMap[position + 1], &theMap[position],
(_size - position) * sizeof(std::pair<key_t,T>)); (_size - position) * sizeof(std::pair<key_t,T>));
theMap[position].first = key; theMap[position].first = key;
theMap[position].second = value; theMap[position].second = value;
@ -63,16 +18,13 @@ inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert( inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
std::pair<key_t, T> pair) { return insert(pair.first, pair.second);
return insert(pair.fist, pair.second);
} }
template<typename key_t, typename T, typename KEY_COMPARE> template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists( inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST; ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findFirstIndex(key) < _size) { if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK; result = HasReturnvaluesIF::RETURN_OK;
@ -80,4 +32,78 @@ inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(
return result; return result;
} }
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(Iterator *iter) {
size_t i;
if ((i = findFirstIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
removeFromPosition(i);
if (*iter != begin()) {
(*iter)--;
} else {
*iter = begin();
}
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::erase(key_t key) {
size_t i;
if ((i = findFirstIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
do {
removeFromPosition(i);
i = findFirstIndex(key, i);
} while (i < _size);
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::find(key_t key, T **value) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*value = &theMap[findFirstIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findFirstIndex(key_t key, size_t startAt) const {
if (startAt >= _size) {
return startAt + 1;
}
size_t i = startAt;
for (i = startAt; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline size_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::findNicePlace(key_t key) const {
size_t i = 0;
for (i = 0; i < _size; ++i) {
if (myComp(key, theMap[i].first)) {
return i;
}
}
return i;
}
template<typename key_t, typename T, typename KEY_COMPARE>
inline void FixedOrderedMultimap<key_t, T, KEY_COMPARE>::removeFromPosition(size_t position) {
if (_size <= position) {
return;
}
memmove(static_cast<void*>(&theMap[position]), static_cast<void*>(&theMap[position + 1]),
(_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size;
}
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */ #endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_TPP_ */

View File

@ -1,8 +1,8 @@
#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ #ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ #define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#include "../container/ArrayList.h" #include "ArrayList.h"
#include "../container/SinglyLinkedList.h" #include "SinglyLinkedList.h"
template<typename T, typename count_t = uint8_t> template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator, class HybridIterator: public LinkedElement<T>::Iterator,

View File

@ -1,50 +0,0 @@
#ifndef ISDERIVEDFROM_H_
#define ISDERIVEDFROM_H_
/**
* These template type checks are based on SFINAE
* (https://en.cppreference.com/w/cpp/language/sfinae)
*
* @tparam D Derived Type
* @tparam B Base Type
*/
template<typename D, typename B>
class IsDerivedFrom {
class No {
};
class Yes {
No no[3];
};
// This will be chosen if B is the base type
static Yes Test(B*); // declared, but not defined
// This will be chosen for anything else
static No Test(... ); // declared, but not defined
public:
enum {
Is = sizeof(Test(static_cast<D*>(0))) == sizeof(Yes)
};
};
template<typename, typename>
struct is_same {
static bool const value = false;
};
template<typename A>
struct is_same<A, A> {
static bool const value = true;
};
template<bool C, typename T = void>
struct enable_if {
typedef T type;
};
template<typename T>
struct enable_if<false, T> { };
#endif /* ISDERIVEDFROM_H_ */

View File

@ -3,26 +3,62 @@
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include <utility> #include <utility>
/**
* The Placement Factory is used to create objects at runtime in a specific pool.
* In general, this should be avoided and it should only be used if you know what you are doing.
* You are not allowed to use this container with a type that allocates memory internally like ArrayList.
*
* Also, you have to check the returned pointer in generate against nullptr!
*
* A backend of Type StorageManagerIF must be given as a place to store the new objects.
* Therefore ThreadSafety is only provided by your StorageManager Implementation.
*
* Objects must be destroyed by the user with "destroy"! Otherwise the pool will not be cleared.
*
* The concept is based on the placement new operator.
*
* @warning Do not use with any Type that allocates memory internally!
* @ingroup container
*/
class PlacementFactory { class PlacementFactory {
public: public:
PlacementFactory(StorageManagerIF* backend) : PlacementFactory(StorageManagerIF* backend) :
dataBackend(backend) { dataBackend(backend) {
} }
/***
* Generates an object of type T in the backend storage.
*
* @warning Do not use with any Type that allocates memory internally!
*
* @tparam T Type of Object
* @param args Constructor Arguments to be passed
* @return A pointer to the new object or a nullptr in case of failure
*/
template<typename T, typename ... Args> template<typename T, typename ... Args>
T* generate(Args&&... args) { T* generate(Args&&... args) {
store_address_t tempId; store_address_t tempId;
uint8_t* pData = NULL; uint8_t* pData = nullptr;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T), ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData); &pData);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL; return nullptr;
} }
T* temp = new (pData) T(std::forward<Args>(args)...); T* temp = new (pData) T(std::forward<Args>(args)...);
return temp; return temp;
} }
/***
* Function to destroy the object allocated with generate and free space in backend.
* This must be called by the user.
*
* @param thisElement Element to be destroyed
* @return RETURN_OK if the element was destroyed, different errors on failure
*/
template<typename T> template<typename T>
ReturnValue_t destroy(T* thisElement) { ReturnValue_t destroy(T* thisElement) {
if (thisElement == nullptr){
return HasReturnvaluesIF::RETURN_FAILED;
}
//Need to call destructor first, in case something was allocated by the object (shouldn't do that, however). //Need to call destructor first, in case something was allocated by the object (shouldn't do that, however).
thisElement->~T(); thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement); uint8_t* pointer = (uint8_t*) (thisElement);

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #ifndef FSFW_CONTAINER_RINGBUFFERBASE_H_
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ #define FSFW_CONTAINER_RINGBUFFERBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef> #include <cstddef>
@ -65,6 +65,7 @@ protected:
size_t read[N_READ_PTRS]; size_t read[N_READ_PTRS];
const size_t size; const size_t size;
const bool overwriteOld; const bool overwriteOld;
void incrementWrite(uint32_t amount) { void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start; write = ((write + amount - start) % size) + start;
} }
@ -90,7 +91,6 @@ protected:
} }
} }
size_t getRead(uint8_t n = 0) const { size_t getRead(uint8_t n = 0) const {
return read[n]; return read[n];
} }
@ -110,4 +110,4 @@ protected:
} }
}; };
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */ #endif /* FSFW_CONTAINER_RINGBUFFERBASE_H_ */

View File

@ -1,79 +0,0 @@
#include <iostream>
#include "SimpleRingBuffer.h"
int main() {
using namespace std;
SimpleRingBuffer buffer(64, false);
uint8_t data[8] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'};
ReturnValue_t result = buffer.writeData(data, 8);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(data, 8);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
uint8_t buffer2[47] = {0};
for (uint8_t count = 0; count<sizeof(buffer2); count++) {
buffer2[count] = count;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(buffer2, sizeof(buffer2));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
uint8_t readBuffer[64] = {0};
uint32_t writtenData = 0;
result = buffer.readData(readBuffer, 12, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(data, sizeof(data));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.readData(readBuffer, 60, true, &writtenData);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "readData failed." << endl;
} else {
cout << "Read data: " << writtenData << endl;
for (uint32_t count = 0; count < writtenData; count++) {
cout << hex << (uint16_t)readBuffer[count] << " ";
}
cout << dec << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer));
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
}
result = buffer.writeData(readBuffer, sizeof(readBuffer)-1);
if (result != HasReturnvaluesIF::RETURN_OK) {
cout << "writeData failed." << endl;
} else {
cout << "write done." << endl;
}
}

View File

@ -1,4 +1,4 @@
#include "../container/SharedRingBuffer.h" #include "SharedRingBuffer.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
@ -9,6 +9,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer, SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
const size_t size, bool overwriteOld, size_t maxExcessBytes): const size_t size, bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld, SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
@ -16,6 +17,11 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
} }
void SharedRingBuffer::setToUseReceiveSizeFIFO(uint32_t fifoDepth) {
this->fifoDepth = fifoDepth;
}
ReturnValue_t SharedRingBuffer::lockRingBufferMutex( ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) { MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
return mutex->lockMutex(timeoutType, timeout); return mutex->lockMutex(timeoutType, timeout);
@ -25,6 +31,25 @@ ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
return mutex->unlockMutex(); return mutex->unlockMutex();
} }
MutexIF* SharedRingBuffer::getMutexHandle() const { MutexIF* SharedRingBuffer::getMutexHandle() const {
return mutex; return mutex;
} }
ReturnValue_t SharedRingBuffer::initialize() {
if(fifoDepth > 0) {
receiveSizesFIFO = new DynamicFIFO<size_t>(fifoDepth);
}
return SystemObject::initialize();
}
DynamicFIFO<size_t>* SharedRingBuffer::getReceiveSizesFIFO() {
if(receiveSizesFIFO == nullptr) {
// Configuration error.
sif::warning << "SharedRingBuffer::getReceiveSizesFIFO: Ring buffer"
<< " was not configured to have sizes FIFO, returning nullptr!"
<< std::endl;
}
return receiveSizesFIFO;
}

View File

@ -1,7 +1,8 @@
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ #ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ #define FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#include "../container/SimpleRingBuffer.h" #include "SimpleRingBuffer.h"
#include "DynamicFIFO.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../timemanager/Clock.h" #include "../timemanager/Clock.h"
@ -26,6 +27,8 @@ public:
SharedRingBuffer(object_id_t objectId, const size_t size, SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes); bool overwriteOld, size_t maxExcessBytes);
void setToUseReceiveSizeFIFO(uint32_t fifoDepth);
/** /**
* This constructor takes an external buffer with the specified size. * This constructor takes an external buffer with the specified size.
* @param buffer * @param buffer
@ -59,10 +62,23 @@ public:
* @return * @return
*/ */
MutexIF* getMutexHandle() const; MutexIF* getMutexHandle() const;
ReturnValue_t initialize() override;
/**
* If the shared ring buffer was configured to have a sizes FIFO, a handle
* to that FIFO can be retrieved with this function.
* Do not forget to protect access with a lock if required!
* @return
*/
DynamicFIFO<size_t>* getReceiveSizesFIFO();
private: private:
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
size_t fifoDepth = 0;
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
}; };
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */ #endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */

View File

@ -1,4 +1,4 @@
#include "../container/SimpleRingBuffer.h" #include "SimpleRingBuffer.h"
#include <cstring> #include <cstring>
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld, SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
@ -25,12 +25,10 @@ SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
} }
} }
SimpleRingBuffer::~SimpleRingBuffer() { SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer; delete[] buffer;
} }
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer, ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
size_t amount) { size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) { if (availableWriteSpace() >= amount or overwriteOld) {
@ -131,5 +129,3 @@ ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
incrementRead(amount, READ_PTR); incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }

View File

@ -1,7 +1,7 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #ifndef FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ #define FSFW_CONTAINER_SIMPLERINGBUFFER_H_
#include "../container/RingBufferBase.h" #include "RingBufferBase.h"
#include <cstddef> #include <cstddef>
/** /**
@ -117,6 +117,7 @@ public:
*/ */
ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false, ReturnValue_t deleteData(size_t amount, bool deleteRemaining = false,
size_t* trueAmount = nullptr); size_t* trueAmount = nullptr);
private: private:
static const uint8_t READ_PTR = 0; static const uint8_t READ_PTR = 0;
uint8_t* buffer = nullptr; uint8_t* buffer = nullptr;
@ -124,5 +125,5 @@ private:
size_t excessBytes = 0; size_t excessBytes = 0;
}; };
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */ #endif /* FSFW_CONTAINER_SIMPLERINGBUFFER_H_ */

View File

@ -100,7 +100,7 @@ public:
*/ */
ElementIterator back() const { ElementIterator back() const {
LinkedElement<T> *element = start; LinkedElement<T> *element = start;
while (element != nullptr) { while (element->getNext() != nullptr) {
element = element->getNext(); element = element->getNext();
} }
return ElementIterator::Iterator(element); return ElementIterator::Iterator(element);

View File

@ -1,365 +0,0 @@
#include "FixedArrayList.h"
#include "SinglyLinkedList.h"
#include "HybridIterator.h"
#include "FixedMap.h"
#include <stdio.h>
/*
class Packet: public SinglyLinkedList {
public:
SinglyLinkedList::Element<uint32_t> element1;
SinglyLinkedList::Element<uint32_t> element2;
Packet() {
this->start = &element1;
element1.next = &element2;
}
};
class Packet2: public SinglyLinkedList {
public:
SinglyLinkedList::Element<uint32_t> element1;
SinglyLinkedList::Element<FixedArrayList<FixedArrayList<uint8_t, 5>, 2>> element2;
SinglyLinkedList::Element<uint32_t> element3;
Packet2() {
this->start = &element1;
element1.next = &element2;
element2.next = &element3;
}
};
class Packet3: public SinglyLinkedList {
public:
SinglyLinkedList::TypedElement<uint32_t> element1;
SinglyLinkedList::TypedElement<uint32_t> element2;
Packet3() {
this->start = &element1;
element1.next = &element2;
}
};
void arrayList() {
puts("** Array List **");
FixedArrayList<uint32_t, 10, uint32_t> list;
FixedArrayList<uint32_t, 10, uint32_t> list2;
list.size = 2;
list[0] = 0xcafecafe;
list[1] = 0x12345678;
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
printf("printsize: %i\n", list.getPrintSize());
list.print(&pointer, &size, 100, true);
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
pointer = buffer;
size2 = size;
printf("list2 read: %x\n", list2.read(&pointer, &size2, true));
printf("list2(%i):", list2.size);
for (ArrayList<uint32_t, uint32_t>::Iterator iter = list2.begin();
iter != list2.end(); iter++) {
printf("0x%04x ", *iter);
}
printf("\n");
HybridIterator<uint32_t, uint32_t> hiter(list.begin(),list.end());
printf("hybrid1: 0x%04x\n", *(hiter++));
printf("hybrid2: 0x%04x\n", *hiter);
}
void allocatingList() {
puts("** Allocating List **");
ArrayList<uint8_t> myList(3), myList2(2);
myList[0] = 0xab;
myList[1] = 0xcd;
myList.size = 2;
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
myList.print(&pointer, &size, 100, true);
pointer = buffer;
size2 = size;
printf("Read %x\n", myList2.read(&pointer, &size2, true));
printf("%x,%x\n", myList2[0], myList2[1]);
}
void linkedList() {
puts("** Linked List **");
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2;
Packet myPacket;
myPacket.element1.entry = 0x12345678;
myPacket.element2.entry = 0x9abcdef0;
pointer = buffer;
size = 0;
ReturnValue_t result = myPacket.print(&pointer, &size, 100, true);
printf("result %02x\n", result);
printf("printsize: %i\n", myPacket.getPrintSize());
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
Packet3 myPacket3;
myPacket3.element1.entry = 0x12345678;
myPacket3.element2.entry = 0xabcdeff;
SinglyLinkedList::TypedIterator<uint32_t> titer(&myPacket3.element1);
printf("0x%04x\n", *titer);
HybridIterator<uint32_t, uint32_t> hiter(&myPacket3.element1);
printf("hybrid1: 0x%04x\n", *hiter);
hiter++;
printf("hybrid2: 0x%04x\n", *hiter);
}
void complex() {
puts("** complex **");
uint8_t buffer[100];
uint8_t *pointer = buffer;
uint32_t size = 0;
uint32_t maxSize = 100;
uint32_t i;
int32_t size2 = size;
Packet myPacket2;
size2 = size;
pointer = buffer;
myPacket2.read(&pointer, &size2, true);
printf("packet: 0x%04x, 0x%04x\n", myPacket2.element1.entry,
myPacket2.element2.entry);
buffer[0] = 0x12;
buffer[1] = 0x34;
buffer[2] = 0x56;
buffer[3] = 0x78;
buffer[4] = 0x2;
buffer[5] = 0x3;
buffer[6] = 0xab;
buffer[7] = 0xcd;
buffer[8] = 0xef;
buffer[9] = 0x2;
buffer[10] = 0x11;
buffer[11] = 0x22;
buffer[12] = 0xca;
buffer[13] = 0xfe;
buffer[14] = 0x5a;
buffer[15] = 0xfe;
pointer = buffer;
size2 = 23;
Packet2 p2;
ReturnValue_t result = p2.read(&pointer, &size2, true);
printf("result is %02x\n", result);
printf("%04x; %i: %i: %x %x %x; %i: %x %x;; %04x\n", p2.element1.entry,
p2.element2.entry.size, p2.element2.entry[0].size,
p2.element2.entry[0][0], p2.element2.entry[0][1],
p2.element2.entry[0][2], p2.element2.entry[1].size,
p2.element2.entry[1][0], p2.element2.entry[1][1],
p2.element3.entry);
}
*/
struct Test {
uint32_t a;
uint32_t b;
};
template<typename key_t, typename T>
void printMap(FixedMap<key_t, T> *map) {
typename FixedMap<key_t, T>::Iterator iter;
printf("Map (%i): ", map->getSize());
for (iter = map->begin(); iter != map->end(); ++iter) {
printf("%x:%08x,%08x ", iter.value->first, (*iter).a, (*iter).b);
}
printf("\n");
}
template<typename T>
void map() {
puts("** Map **");
typename FixedMap<T, Test>::Iterator iter;
ReturnValue_t result;
FixedMap<T, Test> myMap(5);
printMap<T, Test>(&myMap);
Test a;
a.a = 0x01234567;
a.b = 0xabcdef89;
myMap.insert(1, a);
printMap<T, Test>(&myMap);
a.a = 0;
myMap.insert(2, a);
printMap<T, Test>(&myMap);
printf("2 exists: %x\n", myMap.exists(0x02));
printf("ff exists: %x\n", myMap.exists(0xff));
a.a = 1;
printf("insert 0x2: %x\n", myMap.insert(2, a));
result = myMap.insert(0xff, a);
a.a = 0x44;
result = myMap.insert(0xab, a);
result = myMap.insert(0xa, a);
printMap<T, Test>(&myMap);
printf("insert 0x5: %x\n", myMap.insert(5, a));
printf("erase 0xfe: %x\n", myMap.erase(0xfe));
printf("erase 0x2: %x\n", myMap.erase(0x2));
printMap<T, Test>(&myMap);
printf("erase 0xab: %x\n", myMap.erase(0xab));
printMap<T, Test>(&myMap);
printf("insert 0x5: %x\n", myMap.insert(5, a));
printMap<T, Test>(&myMap);
iter = myMap.begin();
++iter;
++iter;
++iter;
printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);
myMap.erase(&iter);
printf("iter: %i: %x,%x\n",iter.value->first, iter->a, iter->b);
printMap<T, Test>(&myMap);
}
/*
void mapPrint() {
puts("** Map Print **");
FixedMap<uint16_t, Packet2> myMap(5);
Packet2 myPacket;
myPacket.element1.entry = 0x12345678;
myPacket.element2.entry[0][0] = 0xab;
myPacket.element2.entry[0][1] = 0xcd;
myPacket.element2.entry[0].size = 2;
myPacket.element2.entry.size = 1;
myPacket.element3.entry = 0xabcdef90;
myMap.insert(0x1234, myPacket);
uint8_t buffer[100];
uint32_t size = 0, i;
uint8_t *pointer = buffer;
printf("printsize: %i\n", myMap.getPrintSize());
SerializeAdapter<FixedMap<uint16_t, Packet2>>::print(&myMap, &pointer,
&size, 100, false);
printf("buffer(%i):", size);
for (i = 0; i < size; ++i) {
printf("%02x", buffer[i]);
}
printf("\n");
int32_t size2 = size;
pointer = buffer;
FixedMap<uint16_t, Packet2> myMap2(5);
ReturnValue_t result = SerializeAdapter<FixedMap<uint16_t, Packet2>>::read(
&myMap2, &pointer, &size2, false);
Packet2 *myPacket2 = myMap2.find(0x1234);
printf("Map (%i): Packet2: %x, Array (%i): Array (%i): %x, %x; %x\n",
myMap2.getSize(), myPacket2->element1.entry,
myPacket2->element2.entry.size, myPacket2->element2.entry[0].size,
myPacket2->element2.entry[0][0], myPacket2->element2.entry[0][1],
myPacket2->element3.entry);
}
void empty() {
puts("** Empty **");
ArrayList<uint32_t> list(0);
printf("%p %p\n", list.front(), list.back());
}
*/
int main(void) {
// arrayList();
// linkedList();
// allocatingList();
// complex();
map<uint32_t>();
//
// mapPrint();
// empty();
return 0;
}

View File

@ -1,5 +1,5 @@
#include "../subsystem/SubsystemBase.h" #include "ControllerBase.h"
#include "../controller/ControllerBase.h"
#include "../subsystem/SubsystemBase.h" #include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
@ -9,7 +9,8 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF), SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this), submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId), hkSwitcher(this) { healthHelper(this, setObjectId), hkSwitcher(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth); commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth);
} }
ControllerBase::~ControllerBase() { ControllerBase::~ControllerBase() {
@ -25,7 +26,7 @@ ReturnValue_t ControllerBase::initialize() {
MessageQueueId_t parentQueue = 0; MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) { if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId); SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) { if (parent == nullptr) {
return RETURN_FAILED; return RETURN_FAILED;
} }
parentQueue = parent->getCommandQueue(); parentQueue = parent->getCommandQueue();
@ -56,8 +57,9 @@ MessageQueueId_t ControllerBase::getCommandQueue() const {
void ControllerBase::handleQueue() { void ControllerBase::handleQueue() {
CommandMessage command; CommandMessage command;
ReturnValue_t result; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK; for (result = commandQueue->receiveMessage(&command);
result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) { result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&command); result = modeHelper.handleModeCommand(&command);

View File

@ -7,12 +7,14 @@
#include "../modes/ModeHelper.h" #include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../datapool/HkSwitchHelper.h" #include "../datapool/HkSwitchHelper.h"
/** /**
* @brief Generic base class for controller classes * @brief Generic base class for controller classes
* @details * @details
* Implements common interfaces for controllers. * Implements common interfaces for controllers, which generally have
* a mode and a health state. This avoids boilerplate code.
*/ */
class ControllerBase: public HasModesIF, class ControllerBase: public HasModesIF,
public HasHealthIF, public HasHealthIF,
@ -26,24 +28,18 @@ public:
size_t commandQueueDepth = 3); size_t commandQueueDepth = 3);
virtual ~ControllerBase(); virtual ~ControllerBase();
/** SystemObject override */
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override; virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t performOperation(uint8_t opCode) override; /** HasHealthIF overrides */
virtual ReturnValue_t setHealth(HealthState health) override; virtual ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth() override; virtual HasHealthIF::HealthState getHealth() override;
/** /** ExecutableObjectIF overrides */
* Implementation of ExecutableObjectIF function virtual ReturnValue_t performOperation(uint8_t opCode) override;
* virtual void setTaskIF(PeriodicTaskIF* task) override;
* Used to setup the reference of the task, that executes this component
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF* task_) override;
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
protected: protected:
@ -56,6 +52,9 @@ protected:
*/ */
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0; virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/**
* Periodic helper, implemented by child class.
*/
virtual void performControlOperation() = 0; virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
@ -73,6 +72,7 @@ protected:
HealthHelper healthHelper; HealthHelper healthHelper;
// Is this still needed?
HkSwitchHelper hkSwitcher; HkSwitchHelper hkSwitcher;
/** /**
@ -81,13 +81,16 @@ protected:
*/ */
PeriodicTaskIF* executingTask = nullptr; PeriodicTaskIF* executingTask = nullptr;
void handleQueue(); /** Handle mode and health messages */
virtual void handleQueue();
/** Mode helpers */
virtual void modeChanged(Mode_t mode, Submode_t submode); virtual void modeChanged(Mode_t mode, Submode_t submode);
virtual void startTransition(Mode_t mode, Submode_t submode); virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void getMode(Mode_t *mode, Submode_t *submode); virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl(); virtual void setToExternalControl();
virtual void announceMode(bool recursive); virtual void announceMode(bool recursive);
/** HK helpers */
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable); virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
}; };

View File

@ -0,0 +1,114 @@
#include "ExtendedControllerBase.h"
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
object_id_t parentId, size_t commandQueueDepth):
ControllerBase(objectId, parentId, commandQueueDepth),
localPoolManager(this, commandQueue),
actionHelper(this, commandQueue) {
}
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) {
// needs to be overriden and implemented by child class.
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t ExtendedControllerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap, LocalDataPoolManager &poolManager) {
// needs to be overriden and implemented by child class.
return HasReturnvaluesIF::RETURN_OK;
}
object_id_t ExtendedControllerBase::getObjectId() const {
return SystemObject::getObjectId();
}
LocalDataPoolManager* ExtendedControllerBase::getHkManagerHandle() {
return &localPoolManager;
}
uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
ReturnValue_t ExtendedControllerBase::handleCommandMessage(
CommandMessage *message) {
ReturnValue_t result = actionHelper.handleActionMessage(message);
if(result == HasReturnvaluesIF::RETURN_OK) {
return result;
}
return localPoolManager.handleHousekeepingMessage(message);
}
void ExtendedControllerBase::handleQueue() {
CommandMessage command;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (result = commandQueue->receiveMessage(&command);
result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = actionHelper.handleActionMessage(&command);
if (result == RETURN_OK) {
continue;
}
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = localPoolManager.handleHousekeepingMessage(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == RETURN_OK) {
continue;
}
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
ReturnValue_t ExtendedControllerBase::initialize() {
ReturnValue_t result = ControllerBase::initialize();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = actionHelper.initialize(commandQueue);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return localPoolManager.initialize(commandQueue);
}
ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
return localPoolManager.initializeAfterTaskCreation();
}
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
localPoolManager.performHkOperation();
performControlOperation();
return RETURN_OK;
}
MessageQueueId_t ExtendedControllerBase::getCommandQueue() const {
return commandQueue->getId();
}
LocalPoolDataSetBase* ExtendedControllerBase::getDataSetHandle(sid_t sid) {
sif::warning << "ExtendedControllerBase::getDataSetHandle: No child "
<< " implementation provided, returning nullptr!" << std::endl;
return nullptr;
}

View File

@ -0,0 +1,72 @@
#ifndef FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#define FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#include "ControllerBase.h"
#include "../action/HasActionsIF.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../action/ActionHelper.h"
#include "../datapoollocal/LocalDataPoolManager.h"
/**
* @brief Extendes the basic ControllerBase with the common components
* HasActionsIF for commandability and HasLocalDataPoolIF to keep
* a pool of local data pool variables.
* @details
* Default implementations required for the interfaces will be empty and have
* to be implemented by child class.
*/
class ExtendedControllerBase: public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public:
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth = 3);
/** SystemObjectIF overrides */
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override;
/** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
LocalDataPoolManager localPoolManager;
ActionHelper actionHelper;
/**
* 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;
/**
* Periodic helper from ControllerBase, implemented by child class.
*/
virtual void performControlOperation() = 0;
/** Handle the four messages mentioned above */
void handleQueue() override;
/** HasActionsIF overrides */
virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data,
size_t size) override;
/** HasLocalDatapoolIF overrides */
virtual object_id_t getObjectId() const override;
virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override;
virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual uint32_t getPeriodicOperationFrequency() const override;
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
};
#endif /* FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_ */

View File

@ -1,5 +1,5 @@
#ifndef DATASETIF_H_ #ifndef FSFW_DATAPOOL_DATASETIF_H_
#define DATASETIF_H_ #define FSFW_DATAPOOL_DATASETIF_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../timemanager/Clock.h" #include "../timemanager/Clock.h"
@ -34,7 +34,6 @@ public:
*/ */
virtual ~DataSetIF() {} virtual ~DataSetIF() {}
/** /**
* @brief This operation provides a method to register local data pool * @brief This operation provides a method to register local data pool
* variables to register in a data set by passing itself * variables to register in a data set by passing itself
@ -45,4 +44,4 @@ public:
virtual uint16_t getFillCount() const = 0; virtual uint16_t getFillCount() const = 0;
}; };
#endif /* FRAMEWORK_DATAPOOL_DATASETIF_H_ */ #endif /* FSFW_DATAPOOL_DATASETIF_H_ */

View File

@ -59,6 +59,11 @@ uint16_t PoolDataSetBase::getFillCount() const {
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) { ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if(registeredVariables[count] == nullptr) {
// configuration error.
return HasReturnvaluesIF::RETURN_FAILED;
}
// These checks are often performed by the respective // These checks are often performed by the respective
// variable implementation too, but I guess a double check does not hurt. // variable implementation too, but I guess a double check does not hurt.
if (registeredVariables[count]->getReadWriteMode() != if (registeredVariables[count]->getReadWriteMode() !=

View File

@ -1,7 +1,8 @@
#ifndef FRAMEWORK_DATAPOOL_DATASETBASE_H_ #ifndef FSFW_DATAPOOL_POOLDATASETBASE_H_
#define FRAMEWORK_DATAPOOL_DATASETBASE_H_ #define FSFW_DATAPOOL_POOLDATASETBASE_H_
#include "../datapool/PoolDataSetIF.h"
#include "../datapool/PoolVariableIF.h" #include "PoolDataSetIF.h"
#include "PoolVariableIF.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
/** /**
@ -148,4 +149,4 @@ private:
ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout); ReturnValue_t handleUnreadDatasetCommit(uint32_t lockTimeout);
}; };
#endif /* FRAMEWORK_DATAPOOL_POOLPOOLDATASETBASE_H_ */ #endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */

View File

@ -1,7 +1,12 @@
#ifndef FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ #ifndef FSFW_DATAPOOL_POOLDATASETIF_H_
#define FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ #define FSFW_DATAPOOL_POOLDATASETIF_H_
#include "DataSetIF.h" #include "DataSetIF.h"
/**
* @brief Extendes the DataSetIF by adding abstract functions to lock
* and unlock a data pool and read/commit semantics.
*/
class PoolDataSetIF: public DataSetIF { class PoolDataSetIF: public DataSetIF {
public: public:
virtual~ PoolDataSetIF() {}; virtual~ PoolDataSetIF() {};
@ -25,4 +30,4 @@ public:
virtual bool isValid() const = 0; virtual bool isValid() const = 0;
}; };
#endif /* FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ */ #endif /* FSFW_DATAPOOL_POOLDATASETIF_H_ */

View File

@ -1,4 +1,5 @@
#include "../datapool/PoolEntry.h" #include "PoolEntry.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h" #include "../globalfunctions/arrayprinter.h"
#include <cstring> #include <cstring>

View File

@ -1,7 +1,7 @@
#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_ #ifndef FSFW_DATAPOOL_POOLENTRY_H_
#define FRAMEWORK_DATAPOOL_POOLENTRY_H_ #define FSFW_DATAPOOL_POOLENTRY_H_
#include "../datapool/PoolEntryIF.h" #include "PoolEntryIF.h"
#include <initializer_list> #include <initializer_list>
#include <type_traits> #include <type_traits>
@ -127,4 +127,4 @@ public:
Type getType(); Type getType();
}; };
#endif /* POOLENTRY_H_ */ #endif /* FSFW_DATAPOOL_POOLENTRY_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ #ifndef FSFW_DATAPOOL_POOLENTRYIF_H_
#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_ #define FSFW_DATAPOOL_POOLENTRYIF_H_
#include "../globalfunctions/Type.h" #include "../globalfunctions/Type.h"
#include <cstdint> #include <cstdint>
@ -60,4 +60,4 @@ public:
virtual Type getType() = 0; virtual Type getType() = 0;
}; };
#endif /* POOLENTRYIF_H_ */ #endif /* FSFW_DATAPOOL_POOLENTRYIF_H_ */

View File

@ -1,188 +0,0 @@
/**
* @file PoolRawAccessHelper.cpp
*
* @date 22.12.2019
* @author R. Mueller
*/
#include "../datapool/PoolRawAccessHelper.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <cmath>
#include <cstring>
PoolRawAccessHelper::PoolRawAccessHelper(uint32_t * poolIdBuffer_,
uint8_t numberOfParameters_):
poolIdBuffer(reinterpret_cast<uint8_t * >(poolIdBuffer_)),
numberOfParameters(numberOfParameters_), validBufferIndex(0),
validBufferIndexBit(1) {
}
PoolRawAccessHelper::~PoolRawAccessHelper() {
}
ReturnValue_t PoolRawAccessHelper::serialize(uint8_t **buffer, size_t *size,
const size_t max_size, SerializeIF::Endianness streamEndianness) {
SerializationArgs serializationArgs = {buffer, size, max_size,
streamEndianness};
ReturnValue_t result = RETURN_OK;
size_t remainingParametersSize = numberOfParameters * 4;
for(uint8_t count=0; count < numberOfParameters; count++) {
result = serializeCurrentPoolEntryIntoBuffer(serializationArgs,
&remainingParametersSize, false);
if(result != RETURN_OK) {
return result;
}
}
if(remainingParametersSize != 0) {
sif::debug << "PoolRawAccessHelper: "
"Remaining parameters size not 0 !" << std::endl;
result = RETURN_FAILED;
}
return result;
}
ReturnValue_t PoolRawAccessHelper::serializeWithValidityMask(uint8_t ** buffer,
size_t * size, const size_t max_size,
SerializeIF::Endianness streamEndianness) {
ReturnValue_t result = RETURN_OK;
SerializationArgs argStruct = {buffer, size, max_size, streamEndianness};
size_t remainingParametersSize = numberOfParameters * 4;
uint8_t validityMaskSize = ceil((float)numberOfParameters/8.0);
uint8_t validityMask[validityMaskSize];
memset(validityMask,0, validityMaskSize);
for(uint8_t count = 0; count < numberOfParameters; count++) {
result = serializeCurrentPoolEntryIntoBuffer(argStruct,
&remainingParametersSize,true,validityMask);
if (result != RETURN_OK) {
return result;
}
}
if(remainingParametersSize != 0) {
sif::debug << "PoolRawAccessHelper: Remaining "
"parameters size not 0 !" << std::endl;
result = RETURN_FAILED;
}
memcpy(*argStruct.buffer, validityMask, validityMaskSize);
*size += validityMaskSize;
validBufferIndex = 1;
validBufferIndexBit = 0;
return result;
}
ReturnValue_t PoolRawAccessHelper::serializeCurrentPoolEntryIntoBuffer(
SerializationArgs argStruct, size_t * remainingParameters,
bool withValidMask, uint8_t * validityMask) {
uint32_t currentPoolId;
// Deserialize current pool ID from pool ID buffer
ReturnValue_t result = SerializeAdapter::deSerialize(&currentPoolId,
&poolIdBuffer,remainingParameters, SerializeIF::Endianness::MACHINE);
if(result != RETURN_OK) {
sif::debug << std::hex << "PoolRawAccessHelper: Error deSeralizing "
"pool IDs" << std::dec << std::endl;
return result;
}
result = handlePoolEntrySerialization(currentPoolId, argStruct,
withValidMask, validityMask);
return result;
}
ReturnValue_t PoolRawAccessHelper::handlePoolEntrySerialization(
uint32_t currentPoolId,SerializationArgs argStruct, bool withValidMask,
uint8_t * validityMask) {
ReturnValue_t result = RETURN_FAILED;
uint8_t arrayPosition = 0;
uint8_t counter = 0;
bool poolEntrySerialized = false;
//debug << "Pool Raw Access Helper: Handling Pool ID: "
// << std::hex << currentPoolId << std::endl;
while(not poolEntrySerialized) {
if(counter > GlobDataSet::DATA_SET_MAX_SIZE) {
sif::error << "PoolRawAccessHelper: Config error, "
"max. number of possible data set variables exceeded"
<< std::endl;
return result;
}
counter ++;
GlobDataSet currentDataSet;
//debug << "Current array position: " << (int)arrayPosition << std::endl;
PoolRawAccess currentPoolRawAccess(currentPoolId, arrayPosition,
&currentDataSet, PoolVariableIF::VAR_READ);
result = currentDataSet.read();
if (result != RETURN_OK) {
sif::debug << std::hex << "PoolRawAccessHelper: Error reading raw "
"dataset with returncode 0x" << result << std::dec << std::endl;
return result;
}
result = checkRemainingSize(&currentPoolRawAccess, &poolEntrySerialized,
&arrayPosition);
if(result != RETURN_OK) {
sif::error << "Pool Raw Access Helper: Configuration Error at pool ID "
<< std::hex << currentPoolId
<< ". Size till end smaller than 0" << std::dec << std::endl;
return result;
}
// set valid mask bit if necessary
if(withValidMask) {
if(currentPoolRawAccess.isValid()) {
handleMaskModification(validityMask);
}
validBufferIndexBit ++;
}
result = currentDataSet.serialize(argStruct.buffer, argStruct.size,
argStruct.max_size, argStruct.streamEndianness);
if (result != RETURN_OK) {
sif::debug << "Pool Raw Access Helper: Error serializing pool data with "
"ID 0x" << std::hex << currentPoolId << " into send buffer "
"with return code " << result << std::dec << std::endl;
return result;
}
}
return result;
}
ReturnValue_t PoolRawAccessHelper::checkRemainingSize(PoolRawAccess*
currentPoolRawAccess, bool * isSerialized, uint8_t * arrayPosition) {
int8_t remainingSize = currentPoolRawAccess->getSizeTillEnd() -
currentPoolRawAccess->getSizeOfType();
if(remainingSize == 0) {
*isSerialized = true;
}
else if(remainingSize > 0) {
*arrayPosition += 1;
}
else {
return RETURN_FAILED;
}
return RETURN_OK;
}
void PoolRawAccessHelper::handleMaskModification(uint8_t * validityMask) {
validityMask[validBufferIndex] =
bitSetter(validityMask[validBufferIndex], validBufferIndexBit, true);
if(validBufferIndexBit == 8) {
validBufferIndex ++;
validBufferIndexBit = 1;
}
}
uint8_t PoolRawAccessHelper::bitSetter(uint8_t byte, uint8_t position,
bool value) {
if(position < 1 or position > 8) {
sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl;
return byte;
}
uint8_t shiftNumber = position + (6 - 2 * (position - 1));
byte |= 1UL << shiftNumber;
return byte;
}

View File

@ -1,111 +0,0 @@
/**
* @file PoolRawAccessHelper.h
*
* @date 22.12.2019
*/
#ifndef FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
#define FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/PoolRawAccess.h"
/**
* @brief This helper function simplifies accessing data pool entries
* via PoolRawAccess
* @details Can be used for a Housekeeping Service
* like ECSS PUS Service 3 if the type of the datapool entries is unknown.
* The provided dataset can be serialized into a provided buffer automatically by
* providing a buffer of pool IDs
* @ingroup data_pool
*/
class PoolRawAccessHelper: public HasReturnvaluesIF {
public:
/**
* Call this constructor if a dataset needs to be serialized via
* Pool Raw Access
* @param dataSet_ This dataset will be used to perform thread-safe reading
* @param poolIdBuffer_ A buffer of uint32_t pool IDs
* @param numberOfParameters_ The number of parameters / pool IDs
*/
PoolRawAccessHelper(uint32_t * poolIdBuffer_, uint8_t numberOfParameters_);
virtual ~PoolRawAccessHelper();
/**
* Serialize the datapool entries derived from the pool ID buffer
* directly into a provided buffer
* @param [out] buffer
* @param [out] size Size of the serialized buffer
* @param max_size
* @param bigEndian
* @return @c RETURN_OK On success
* @c RETURN_FAILED on failure
*/
ReturnValue_t serialize(uint8_t ** buffer, size_t * size,
const size_t max_size, SerializeIF::Endianness streamEndianness);
/**
* Serializes data pool entries into provided buffer with the validity mask buffer
* at the end of the buffer. Every bit of the validity mask denotes
* the validity of a corresponding data pool entry from left to right.
* @param [out] buffer
* @param [out] size Size of the serialized buffer plus size
* of the validity mask
* @return @c RETURN_OK On success
* @c RETURN_FAILED on failure
*/
ReturnValue_t serializeWithValidityMask(uint8_t ** buffer, size_t * size,
const size_t max_size, SerializeIF::Endianness streamEndianness);
private:
// DataSet * dataSet;
const uint8_t * poolIdBuffer;
uint8_t numberOfParameters;
uint8_t validBufferIndex;
uint8_t validBufferIndexBit;
struct SerializationArgs {
uint8_t ** buffer;
size_t * size;
const size_t max_size;
SerializeIF::Endianness streamEndianness;
};
/**
* Helper function to serialize single pool entries
* @param pPoolIdBuffer
* @param buffer
* @param remainingParameters
* @param hkDataSize
* @param max_size
* @param bigEndian
* @param withValidMask Can be set optionally to set a
* provided validity mask
* @param validityMask Can be supplied and will be set if
* @c withValidMask is set to true
* @return
*/
ReturnValue_t serializeCurrentPoolEntryIntoBuffer(
SerializationArgs argStruct, size_t * remainingParameters,
bool withValidMask = false, uint8_t * validityMask = nullptr);
ReturnValue_t handlePoolEntrySerialization(uint32_t currentPoolId,
SerializationArgs argStruct, bool withValidMask = false,
uint8_t * validityMask = nullptr);
ReturnValue_t checkRemainingSize(PoolRawAccess * currentPoolRawAccess,
bool * isSerialized, uint8_t * arrayPosition);
void handleMaskModification(uint8_t * validityMask);
/**
* Sets specific bit of a byte
* @param byte
* @param position Position of byte to set from 1 to 8
* @param value Binary value to set
* @return
*/
uint8_t bitSetter(uint8_t byte, uint8_t position, bool value);
};
#endif /* FRAMEWORK_DATAPOOL_POOLRAWACCESSHELPER_H_ */

View File

@ -1,5 +1,5 @@
#ifndef POOLVARLIST_H_ #ifndef FSFW_DATAPOOL_POOLVARLIST_H_
#define POOLVARLIST_H_ #define FSFW_DATAPOOL_POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h" #include "../datapoolglob/GlobalPoolVariable.h"
@ -8,7 +8,8 @@ class PoolVarList {
private: private:
GlobPoolVar<T> variables[n_var]; GlobPoolVar<T> variables[n_var];
public: public:
PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet, PoolVariableIF::ReadWriteMode_t setReadWriteMode ) { PoolVarList( const uint32_t set_id[n_var], DataSetIF* dataSet,
PoolVariableIF::ReadWriteMode_t setReadWriteMode ) {
//I really should have a look at the new init list c++ syntax. //I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) { if (dataSet == NULL) {
return; return;
@ -25,4 +26,4 @@ public:
#endif /* POOLVARLIST_H_ */ #endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */

View File

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ #ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
#define FRAMEWORK_DATAPOOL_POOLVARIABLEIF_H_ #define FSFW_DATAPOOL_POOLVARIABLEIF_H_
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
@ -96,4 +96,4 @@ protected:
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t; using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
#endif /* POOLVARIABLEIF_H_ */ #endif /* FSFW_DATAPOOL_POOLVARIABLEIF_H_ */

View File

@ -1,4 +1,4 @@
#include "../datapool/ControllerSet.h" #include <fsfw/datapoolglob/ControllerSet.h>
ControllerSet::ControllerSet() { ControllerSet::ControllerSet() {

View File

@ -1,5 +1,5 @@
#ifndef CONTROLLERSET_H_ #ifndef FSFW_DATAPOOLGLOB_CONTROLLERSET_H_
#define CONTROLLERSET_H_ #define FSFW_DATAPOOLGLOB_CONTROLLERSET_H_
#include "../datapoolglob/GlobalDataSet.h" #include "../datapoolglob/GlobalDataSet.h"
@ -12,4 +12,4 @@ public:
void setInvalid(); void setInvalid();
}; };
#endif /* CONTROLLERSET_H_ */ #endif /* FSFW_DATAPOOLGLOB_CONTROLLERSET_H_ */

View File

@ -1,7 +1,8 @@
#include "../datapoolglob/DataPoolAdmin.h" #include "DataPoolAdmin.h"
#include "../datapoolglob/GlobalDataSet.h" #include "GlobalDataSet.h"
#include "../datapoolglob/GlobalDataPool.h" #include "GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h" #include "PoolRawAccess.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../parameters/ParameterMessage.h" #include "../parameters/ParameterMessage.h"

View File

@ -1,5 +1,7 @@
#ifndef DATAPOOLADMIN_H_ #ifndef FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_
#define DATAPOOLADMIN_H_ #define FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_
#include "DataPoolParameterWrapper.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
@ -7,10 +9,9 @@
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../parameters/ReceivesParameterMessagesIF.h" #include "../parameters/ReceivesParameterMessagesIF.h"
#include "../memory/MemoryHelper.h"
#include "../action/SimpleActionHelper.h" #include "../action/SimpleActionHelper.h"
#include "../datapoolglob/DataPoolParameterWrapper.h" #include "../memory/MemoryHelper.h"
class DataPoolAdmin: public HasActionsIF, class DataPoolAdmin: public HasActionsIF,
public ExecutableObjectIF, public ExecutableObjectIF,
@ -56,4 +57,4 @@ private:
Command_t initialCommand); Command_t initialCommand);
}; };
#endif /* DATAPOOLADMIN_H_ */ #endif /* FSFW_DATAPOOLGLOB_DATAPOOLADMIN_H_ */

View File

@ -1,5 +1,5 @@
#ifndef GLOBALPOOLVECTOR_H_ #ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_
#define GLOBALPOOLVECTOR_H_ #define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h" #include "../datapool/PoolEntry.h"
@ -182,4 +182,4 @@ private:
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
using gp_vec_t = GlobPoolVector<T, vectorSize>; using gp_vec_t = GlobPoolVector<T, vectorSize>;
#endif /* POOLVECTOR_H_ */ #endif /* FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_H_ */

View File

@ -1,5 +1,5 @@
#ifndef GLOBALPOOLVECTOR_TPP_ #ifndef FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_
#define GLOBALPOOLVECTOR_TPP_ #define FSFW_DATAPOOLGLOB_GLOBALPOOLVECTOR_TPP_
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>

View File

@ -1,12 +1,15 @@
#ifndef FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ #ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#define FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ #define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#include "../datapool/PoolEntryIF.h" #include "../datapool/PoolEntryIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
#include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/HousekeepingMessage.h"
#include <map> #include <map>
class LocalDataPoolManager; class LocalDataPoolManager;
class DataSetIF; class LocalPoolDataSetBase;
/** /**
* @brief Type definition for local pool entries. * @brief Type definition for local pool entries.
*/ */
@ -61,11 +64,11 @@ public:
virtual LocalDataPoolManager* getHkManagerHandle() = 0; virtual LocalDataPoolManager* getHkManagerHandle() = 0;
/** /**
* Returns the minimum sampling frequency, which will usually be the * Returns the minimum sampling frequency in milliseconds, which will
* period the pool owner performs its periodic operation- * usually be the period the pool owner performs its periodic operation.
* @return * @return
*/ */
virtual dur_millis_t getPeriodicOperationFrequency() const = 0; virtual uint32_t getPeriodicOperationFrequency() const = 0;
/** /**
* This function is used by the pool manager to get a valid dataset * This function is used by the pool manager to get a valid dataset
@ -73,7 +76,7 @@ public:
* @param sid Corresponding structure ID * @param sid Corresponding structure ID
* @return * @return
*/ */
virtual DataSetIF* getDataSetHandle(sid_t sid) = 0; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0;
/* These function can be implemented by pool owner, as they are required /* These function can be implemented by pool owner, as they are required
* by the housekeeping message interface */ * by the housekeeping message interface */
@ -84,9 +87,9 @@ public:
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
}; };
virtual ReturnValue_t changeCollectionInterval(sid_t sid, virtual ReturnValue_t changeCollectionInterval(sid_t sid,
dur_seconds_t newInterval) { float newIntervalSeconds) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
}; };
}; };
#endif /* FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ */ #endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */

View File

@ -1,63 +1,75 @@
#include "../datapoollocal/LocalDataPoolManager.h" #include "LocalDataPoolManager.h"
#include "../datapoollocal/LocalDataSet.h" #include "LocalPoolDataSetBase.h"
#include "../housekeeping/HousekeepingSetPacket.h"
#include "../housekeeping/AcceptsHkPacketsIF.h" #include "../housekeeping/AcceptsHkPacketsIF.h"
#include "../ipc/MutexFactory.h" #include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../objectmanager/frameworkObjects.h"
#include <array> #include <array>
#include <cmath> #include <cmath>
object_id_t LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT; object_id_t LocalDataPoolManager::defaultHkDestination =
objects::PUS_SERVICE_3_HOUSEKEEPING;
LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner,
MessageQueueIF* queueToUse, bool appendValidityBuffer): MessageQueueIF* queueToUse, bool appendValidityBuffer):
appendValidityBuffer(appendValidityBuffer) { appendValidityBuffer(appendValidityBuffer) {
if(owner == nullptr) { if(owner == nullptr) {
sif::error << "HkManager: Invalid supplied owner!" << std::endl; sif::error << "LocalDataPoolManager::LocalDataPoolManager: "
<< "Invalid supplied owner!" << std::endl;
return; return;
} }
this->owner = owner; this->owner = owner;
mutex = MutexFactory::instance()->createMutex(); mutex = MutexFactory::instance()->createMutex();
if(mutex == nullptr) { if(mutex == nullptr) {
sif::error << "LocalDataPoolManager::LocalDataPoolManager: " sif::error << "LocalDataPoolManager::LocalDataPoolManager: "
"Could not create mutex." << std::endl; << "Could not create mutex." << std::endl;
}
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if(ipcStore == nullptr) {
sif::error << "LocalDataPoolManager::LocalDataPoolManager: "
"Could not set IPC store." << std::endl;
} }
hkQueue = queueToUse; hkQueue = queueToUse;
if(defaultHkDestination != objects::NO_OBJECT) {
AcceptsHkPacketsIF* hkPacketReceiver =
objectManager->get<AcceptsHkPacketsIF>(defaultHkDestination);
if(hkPacketReceiver != nullptr) {
defaultHkDestinationId = hkPacketReceiver->getHkQueue();
}
}
} }
LocalDataPoolManager::~LocalDataPoolManager() {} LocalDataPoolManager::~LocalDataPoolManager() {}
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) { ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
if(queueToUse == nullptr) { if(queueToUse == nullptr) {
sif::error << "LocalDataPoolManager::initialize: Supplied queue " sif::error << "LocalDataPoolManager::initialize: "
"invalid!" << std::endl; << std::hex << "0x" << owner->getObjectId() << ". Supplied "
<< "queue invalid!" << std::dec << std::endl;
} }
hkQueue = queueToUse; hkQueue = queueToUse;
ipcStore = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if(ipcStore == nullptr) {
sif::error << "LocalDataPoolManager::initialize: "
<< std::hex << "0x" << owner->getObjectId() << ": Could not "
<< "set IPC store." <<std::dec << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
if(defaultHkDestination != objects::NO_OBJECT) {
AcceptsHkPacketsIF* hkPacketReceiver =
objectManager->get<AcceptsHkPacketsIF>(defaultHkDestination);
if(hkPacketReceiver != nullptr) {
hkDestinationId = hkPacketReceiver->getHkQueue();
}
else {
sif::error << "LocalDataPoolManager::LocalDataPoolManager: "
<< "Default HK destination object is invalid!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation( ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(
uint8_t nonDiagInvlFactor) { uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor); setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
diagnosticMinimumInterval = owner->getPeriodicOperationFrequency();
regularMinimumInterval = diagnosticMinimumInterval *
nonDiagnosticIntervalFactor;
return initializeHousekeepingPoolEntriesOnce(); return initializeHousekeepingPoolEntriesOnce();
} }
@ -71,20 +83,17 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
return result; return result;
} }
sif::warning << "HousekeepingManager: The map should only be initialized " sif::warning << "HousekeepingManager: The map should only be initialized "
"once!" << std::endl; << "once!" << std::endl;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::performHkOperation() { ReturnValue_t LocalDataPoolManager::performHkOperation() {
for(auto& hkReceiversIter: hkReceiversMap) { for(auto& receiver: hkReceiversMap) {
HkReceiver* receiver = &hkReceiversIter.second; //HkReceiver* receiver = &hkReceiversIter.second;
if(not receiver->reportingEnabled) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(receiver->reportingType) { switch(receiver.reportingType) {
case(ReportingType::PERIODIC): { case(ReportingType::PERIODIC): {
if(receiver->dataId.dataSetSid.notSet()) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
// Periodic packets shall only be generated from datasets. // Periodic packets shall only be generated from datasets.
continue; continue;
} }
@ -110,50 +119,100 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
objectManager->get<AcceptsHkPacketsIF>(packetDestination); objectManager->get<AcceptsHkPacketsIF>(packetDestination);
if(hkReceiverObject == nullptr) { if(hkReceiverObject == nullptr) {
sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:" sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:"
" Invalid receiver!"<< std::endl; << " Invalid receiver!"<< std::endl;
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
struct HkReceiver hkReceiver; struct HkReceiver hkReceiver;
hkReceiver.dataId.dataSetSid = sid; hkReceiver.dataId.sid = sid;
hkReceiver.reportingType = ReportingType::PERIODIC; hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
hkReceiver.reportingEnabled = enableReporting;
if(not isDiagnostics) { LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
hkReceiver.hkParameter.collectionIntervalTicks = if(dataSet != nullptr) {
intervalSecondsToInterval(isDiagnostics, collectionInterval * dataSet->setReportingEnabled(enableReporting);
nonDiagnosticIntervalFactor); dataSet->setDiagnostic(isDiagnostics);
} dataSet->initializePeriodicHelper(collectionInterval,
else { owner->getPeriodicOperationFrequency(), isDiagnostics);
hkReceiver.hkParameter.collectionIntervalTicks =
intervalSecondsToInterval(isDiagnostics, collectionInterval);
} }
hkReceiver.isDiagnostics = isDiagnostics; hkReceiversMap.push_back(hkReceiver);
hkReceiver.intervalCounter = 1;
hkReceiversMap.emplace(packetDestination, hkReceiver);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
CommandMessage* message) { CommandMessage* message) {
Command_t command = message->getCommand(); Command_t command = message->getCommand();
sid_t sid = HousekeepingMessage::getSid(message);
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
switch(command) { switch(command) {
// I think those are the only commands which can be handled here.. case(HousekeepingMessage::ENABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
case(HousekeepingMessage::ADD_HK_REPORT_STRUCT): result = togglePeriodicGeneration(sid, true, true);
case(HousekeepingMessage::ADD_DIAGNOSTICS_REPORT_STRUCT): break;
// We should use OwnsLocalPoolDataIF to specify those functions.. }
return HasReturnvaluesIF::RETURN_OK;
case(HousekeepingMessage::DISABLE_PERIODIC_DIAGNOSTICS_GENERATION): {
result = togglePeriodicGeneration(sid, false, true);
break;
}
case(HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, true, false);
break;
}
case(HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, false, false);
break;
}
case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES):
return generateSetStructurePacket(sid, true);
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES):
//return generateSetStructurePacket(message->getSid()); return generateSetStructurePacket(sid, false);
case(HousekeepingMessage::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL):
case(HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message,
&newCollIntvl);
if(command == HousekeepingMessage::
MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL) {
result = changeCollectionInterval(sid, newCollIntvl, true);
}
else {
result = changeCollectionInterval(sid, newCollIntvl, false);
}
break;
}
case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
//return generateHousekeepingPacket(message->getSid()); LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT
and dataSet->isDiagnostics()) {
return WRONG_HK_PACKET_TYPE;
}
else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT
and not dataSet->isDiagnostics()) {
return WRONG_HK_PACKET_TYPE;
}
return generateHousekeepingPacket(HousekeepingMessage::getSid(message),
dataSet, true);
}
default: default:
return CommandMessageIF::UNKNOWN_COMMAND; return CommandMessageIF::UNKNOWN_COMMAND;
} }
CommandMessage reply;
if(result != HasReturnvaluesIF::RETURN_OK) {
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
}
else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
}
hkQueue->sendMessage(hkDestinationId, &reply);
return result;
} }
ReturnValue_t LocalDataPoolManager::printPoolEntry( ReturnValue_t LocalDataPoolManager::printPoolEntry(
@ -161,7 +220,7 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry(
auto poolIter = localPoolMap.find(localPoolId); auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) { if (poolIter == localPoolMap.end()) {
sif::debug << "HousekeepingManager::fechPoolEntry:" sif::debug << "HousekeepingManager::fechPoolEntry:"
" Pool entry not found." << std::endl; << " Pool entry not found." << std::endl;
return POOL_ENTRY_NOT_FOUND; return POOL_ENTRY_NOT_FOUND;
} }
poolIter->second->print(); poolIter->second->print();
@ -172,40 +231,47 @@ MutexIF* LocalDataPoolManager::getMutexHandle() {
return mutex; return mutex;
} }
const HasLocalDataPoolIF* LocalDataPoolManager::getOwner() const { HasLocalDataPoolIF* LocalDataPoolManager::getOwner() {
return owner; return owner;
} }
ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
float collectionInterval, MessageQueueId_t destination) { LocalPoolDataSetBase* dataSet, bool forDownlink,
LocalPoolDataSetBase* dataSetToSerialize = MessageQueueId_t destination) {
dynamic_cast<LocalPoolDataSetBase*>(owner->getDataSetHandle(sid)); if(dataSet == nullptr) {
if(dataSetToSerialize == nullptr) { // Configuration error.
sif::warning << "HousekeepingManager::generateHousekeepingPacket:" sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
" Set ID not found or dataset not assigned!" << std::endl; << " Set ID not found or dataset not assigned!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
sif::info << "hk gen called" << std::endl;
store_address_t storeId; store_address_t storeId;
HousekeepingPacketDownlink hkPacket(sid, collectionInterval, HousekeepingPacketDownlink hkPacket(sid, dataSet);
dataSetToSerialize->getFillCount(), dataSetToSerialize); size_t serializedSize = 0;
ReturnValue_t result = serializeHkPacketIntoStore(hkPacket, &storeId); ReturnValue_t result = serializeHkPacketIntoStore(hkPacket, storeId,
if(result != HasReturnvaluesIF::RETURN_OK) { forDownlink, &serializedSize);
if(result != HasReturnvaluesIF::RETURN_OK or serializedSize == 0) {
return result; return result;
} }
// and now we set a HK message and send it the HK packet destination. // and now we set a HK message and send it the HK packet destination.
CommandMessage hkMessage; CommandMessage hkMessage;
HousekeepingMessage::setHkReportMessage(&hkMessage, sid, storeId); if(dataSet->isDiagnostics()) {
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
}
else {
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
}
if(hkQueue == nullptr) { if(hkQueue == nullptr) {
return QUEUE_OR_DESTINATION_NOT_SET; return QUEUE_OR_DESTINATION_NOT_SET;
} }
if(destination == MessageQueueIF::NO_QUEUE) { if(destination == MessageQueueIF::NO_QUEUE) {
if(defaultHkDestinationId == MessageQueueIF::NO_QUEUE) { if(hkDestinationId == MessageQueueIF::NO_QUEUE) {
// error, all destinations invalid // error, all destinations invalid
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
destination = defaultHkDestinationId; destination = hkDestinationId;
} }
return hkQueue->sendMessage(destination, &hkMessage); return hkQueue->sendMessage(destination, &hkMessage);
@ -213,46 +279,22 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(
HousekeepingPacketDownlink& hkPacket, HousekeepingPacketDownlink& hkPacket,
store_address_t *storeId) { store_address_t& storeId, bool forDownlink,
size_t* serializedSize) {
uint8_t* dataPtr = nullptr; uint8_t* dataPtr = nullptr;
size_t serializedSize = 0;
const size_t maxSize = hkPacket.getSerializedSize(); const size_t maxSize = hkPacket.getSerializedSize();
ReturnValue_t result = ipcStore->getFreeElement(storeId,
serializedSize, &dataPtr);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return hkPacket.serialize(&dataPtr, &serializedSize, maxSize,
SerializeIF::Endianness::MACHINE);
}
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid));
if(dataSet == nullptr) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
" Set ID not found" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
size_t expectedSize = dataSet->getFillCount() * sizeof(lp_id_t);
uint8_t* storePtr = nullptr;
store_address_t storeId;
ReturnValue_t result = ipcStore->getFreeElement(&storeId, ReturnValue_t result = ipcStore->getFreeElement(&storeId,
expectedSize,&storePtr); maxSize, &dataPtr);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "HousekeepingManager::generateHousekeepingPacket: "
"Could not get free element from IPC store." << std::endl;
return result; return result;
} }
size_t size = 0;
result = dataSet->serializeLocalPoolIds(&storePtr, &size, if(forDownlink) {
expectedSize, SerializeIF::Endianness::BIG); return hkPacket.serialize(&dataPtr, serializedSize, maxSize,
if(expectedSize != size) { SerializeIF::Endianness::BIG);
sif::error << "HousekeepingManager::generateSetStructurePacket: "
"Expected size is not equal to serialized size" << std::endl;
} }
return result; return hkPacket.serialize(&dataPtr, serializedSize, maxSize,
SerializeIF::Endianness::MACHINE);
} }
void LocalDataPoolManager::setNonDiagnosticIntervalFactor( void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
@ -260,46 +302,126 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
} }
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(not dataSet->getReportingEnabled()) {
return;
}
if(dataSet->periodicHelper == nullptr) {
// Configuration error.
return;
}
if(not dataSet->periodicHelper->checkOpNecessary()) {
return;
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) {
if(receiver->intervalCounter >=
receiver->hkParameter.collectionIntervalTicks) {
ReturnValue_t result = generateHousekeepingPacket( ReturnValue_t result = generateHousekeepingPacket(
receiver->dataId.dataSetSid); sid, dataSet, true);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// configuration error // configuration error
sif::debug << "LocalDataPoolManager::performHkOperation:" sif::debug << "LocalDataPoolManager::performHkOperation:"
<< "0x" << std::setfill('0') << std::setw(8) << "0x" << std::hex << std::setfill('0') << std::setw(8)
<< owner->getObjectId() << " Error generating " << owner->getObjectId() << " Error generating "
<< "HK packet" << std::setfill(' ') << std::endl; << "HK packet" << std::setfill(' ') << std::dec << std::endl;
}
receiver->intervalCounter = 1;
}
else {
receiver->intervalCounter++;
} }
} }
uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics,
float collectionIntervalSeconds) { ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
if(isDiagnostics) { bool enable, bool isDiagnostics) {
return std::ceil(collectionIntervalSeconds * 1000 LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
/diagnosticMinimumInterval); if((dataSet->isDiagnostics() and not isDiagnostics) or
} (not dataSet->isDiagnostics() and isDiagnostics)) {
else { return WRONG_HK_PACKET_TYPE;
return std::ceil(collectionIntervalSeconds * 1000
/regularMinimumInterval);
}
} }
float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics, if((dataSet->getReportingEnabled() and enable) or
uint32_t collectionInterval) { (not dataSet->getReportingEnabled() and not enable)) {
return REPORTING_STATUS_UNCHANGED;
}
dataSet->setReportingEnabled(enable);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
bool targetIsDiagnostics = dataSet->isDiagnostics();
if((targetIsDiagnostics and not isDiagnostics) or
(not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
if(dataSet->periodicHelper == nullptr) {
// config error
return PERIODIC_HELPER_INVALID;
}
dataSet->periodicHelper->changeCollectionInterval(newCollectionInterval);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
bool isDiagnostics) {
// Get and check dataset first.
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid));
if(dataSet == nullptr) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
<< " Set ID not found" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
bool targetIsDiagnostics = dataSet->isDiagnostics();
if((targetIsDiagnostics and not isDiagnostics) or
(not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
bool valid = dataSet->isValid();
bool reportingEnabled = dataSet->getReportingEnabled();
float collectionInterval =
dataSet->periodicHelper->getCollectionIntervalInSeconds();
// Generate set packet which can be serialized.
HousekeepingSetPacket setPacket(sid,
reportingEnabled, valid, collectionInterval, dataSet);
size_t expectedSize = setPacket.getSerializedSize();
uint8_t* storePtr = nullptr;
store_address_t storeId;
ReturnValue_t result = ipcStore->getFreeElement(&storeId,
expectedSize,&storePtr);
if(result != HasReturnvaluesIF::RETURN_OK) {
sif::error << "HousekeepingManager::generateHousekeepingPacket: "
<< "Could not get free element from IPC store." << std::endl;
return result;
}
// Serialize set packet into store.
size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize,
SerializeIF::Endianness::BIG);
if(expectedSize != size) {
sif::error << "HousekeepingManager::generateSetStructurePacket: "
<< "Expected size is not equal to serialized size" << std::endl;
}
// Send structure reporting reply.
CommandMessage reply;
if(isDiagnostics) { if(isDiagnostics) {
return static_cast<float>(collectionInterval * HousekeepingMessage::setDiagnosticsStuctureReportReply(&reply,
diagnosticMinimumInterval); sid, storeId);
} }
else { else {
return static_cast<float>(collectionInterval * HousekeepingMessage::setHkStuctureReportReply(&reply,
regularMinimumInterval); sid, storeId);
} }
hkQueue->reply(&reply);
return result;
} }

View File

@ -1,14 +1,15 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ #define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#include "HasLocalDataPoolIF.h"
#include "../housekeeping/HousekeepingPacketDownlink.h" #include "../housekeeping/HousekeepingPacketDownlink.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../datapool/PoolEntry.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../ipc/MutexHelper.h" #include "../ipc/MutexHelper.h"
@ -23,7 +24,7 @@ class LocalDataSetBase;
/** /**
* @brief This class is the managing instance for local data pool. * @brief This class is the managing instance for the local data pool.
* @details * @details
* The actual data pool structure is a member of this class. Any class which * The actual data pool structure is a member of this class. Any class which
* has a local data pool shall have this class as a member and implement * has a local data pool shall have this class as a member and implement
@ -49,10 +50,14 @@ class LocalDataPoolManager {
public: public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x0); static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1); static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x2); static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x02);
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(0x03);
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(0x04);
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(0x05);
/** /**
* This constructor is used by a class which wants to implement * This constructor is used by a class which wants to implement
@ -69,16 +74,30 @@ public:
virtual~ LocalDataPoolManager(); virtual~ LocalDataPoolManager();
/** /**
* Initializes the map by calling the map initialization function of the * Assigns the queue to use.
* owner and assigns the queue to use.
* @param queueToUse * @param queueToUse
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc * @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
* @return * @return
*/ */
ReturnValue_t initialize(MessageQueueIF* queueToUse); ReturnValue_t initialize(MessageQueueIF* queueToUse);
/**
* Initializes the map by calling the map initialization function and
* setting the periodic factor for non-diagnostic packets.
* Don't forget to call this, otherwise the map will be invalid!
* @param nonDiagInvlFactor
* @return
*/
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5); ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
/**
* This should be called in the periodic handler of the owner.
* It performs all the periodic functionalities of the data pool manager,
* for example generating periodic HK packets.
* @return
*/
ReturnValue_t performHkOperation();
/** /**
* @return * @return
*/ */
@ -97,12 +116,6 @@ public:
*/ */
void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor); void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor);
/**
* This should be called in the periodic handler of the owner.
* It performs all the periodic functionalities of the data pool manager.
* @return
*/
ReturnValue_t performHkOperation();
/** /**
* Generate a housekeeping packet with a given SID. * Generate a housekeeping packet with a given SID.
@ -110,9 +123,8 @@ public:
* @return * @return
*/ */
ReturnValue_t generateHousekeepingPacket(sid_t sid, ReturnValue_t generateHousekeepingPacket(sid_t sid,
float collectionInterval = 0, LocalPoolDataSetBase* dataSet, bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE); MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t generateSetStructurePacket(sid_t sid);
ReturnValue_t handleHousekeepingMessage(CommandMessage* message); ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
@ -124,26 +136,27 @@ public:
*/ */
ReturnValue_t initializeHousekeepingPoolEntriesOnce(); ReturnValue_t initializeHousekeepingPoolEntriesOnce();
const HasLocalDataPoolIF* getOwner() const; HasLocalDataPoolIF* getOwner();
ReturnValue_t printPoolEntry(lp_id_t localPoolId); ReturnValue_t printPoolEntry(lp_id_t localPoolId);
/** /**
* Different types of housekeeping reporting are possible. * Different types of housekeeping reporting are possible.
* 1. PERIODIC: HK packets are generated in fixed intervals and sent to * 1. PERIODIC:
* HK packets are generated in fixed intervals and sent to
* destination. Fromat will be raw. * destination. Fromat will be raw.
* 2. UPDATED: Notification will be sent out if HK data has changed. * 2. UPDATE_NOTIFICATION:
* Question: Send Raw data directly or just the message? * Notification will be sent out if HK data has changed.
* 3. REQUESTED: HK packets are only generated if explicitely requested. * 3. UPDATE_SNAPSHOT:
* HK packets are only generated if explicitely requested.
* Propably not necessary, just use multiple local data sets or * Propably not necessary, just use multiple local data sets or
* shared datasets. * shared datasets.
*
* Notifications should also be possible for single variables instead of
* full dataset updates.
*/ */
enum class ReportingType: uint8_t { enum class ReportingType: uint8_t {
//! Periodic generation of HK packets. //! Periodic generation of HK packets.
PERIODIC, PERIODIC,
//! Housekeeping packet will be generated if values have changed.
UPDATE_HK,
//! Update notification will be sent out as message. //! Update notification will be sent out as message.
UPDATE_NOTIFICATION, UPDATE_NOTIFICATION,
//! Notification will be sent out as message and a snapshot of the //! Notification will be sent out as message and a snapshot of the
@ -151,6 +164,17 @@ public:
UPDATE_SNAPSHOT, UPDATE_SNAPSHOT,
}; };
/**
* Different data types are possible in the HK receiver map.
* For example, updates can be requested for full datasets or
* for single pool variables. Periodic reporting is only possible for
* data sets.
*/
enum class DataType: uint8_t {
LOCAL_POOL_VARIABLE,
DATA_SET
};
/* Copying forbidden */ /* Copying forbidden */
LocalDataPoolManager(const LocalDataPoolManager &) = delete; LocalDataPoolManager(const LocalDataPoolManager &) = delete;
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
@ -160,51 +184,37 @@ private:
//! Every housekeeping data manager has a mutex to protect access //! Every housekeeping data manager has a mutex to protect access
//! to it's data pool. //! to it's data pool.
MutexIF* mutex = nullptr; MutexIF* mutex = nullptr;
/** The class which actually owns the manager (and its datapool). */ /** The class which actually owns the manager (and its datapool). */
HasLocalDataPoolIF* owner = nullptr; HasLocalDataPoolIF* owner = nullptr;
uint8_t nonDiagnosticIntervalFactor = 0; uint8_t nonDiagnosticIntervalFactor = 0;
dur_millis_t regularMinimumInterval = 0;
dur_millis_t diagnosticMinimumInterval = 0;
/** Default receiver for periodic HK packets */ /** Default receiver for periodic HK packets */
static object_id_t defaultHkDestination; static object_id_t defaultHkDestination;
MessageQueueId_t defaultHkDestinationId = MessageQueueIF::NO_QUEUE; MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
/** The data pool manager will keep an internal map of HK receivers. */ /** The data pool manager will keep an internal map of HK receivers. */
struct HkReceiver { struct HkReceiver {
/** Different member of this union will be used depending on the /** Object ID of receiver */
type of data the receiver is interested in (full datasets or object_id_t objectId = objects::NO_OBJECT;
single data variables. */
DataType dataType = DataType::DATA_SET;
union DataId { union DataId {
DataId(): dataSetSid() {} DataId(): sid() {};
/** Will be initialized to INVALID_ADDRESS */ sid_t sid;
sid_t dataSetSid; lp_id_t localPoolId;
lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID;
}; };
DataId dataId; DataId dataId;
ReportingType reportingType = ReportingType::PERIODIC; ReportingType reportingType = ReportingType::PERIODIC;
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE; MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
bool reportingEnabled = true;
/** Different members of this union will be used depending on reporting
type */
union HkParameter {
/** This parameter will be used for the PERIODIC type */
uint32_t collectionIntervalTicks = 0;
/** This parameter will be used for the ON_UPDATE type */
bool hkDataChanged;
};
HkParameter hkParameter;
bool isDiagnostics;
/** General purpose counter which is used for periodic generation. */
uint32_t intervalCounter;
}; };
/** Using a multimap as the same object might request multiple datasets */ /** This vector will contain the list of HK receivers. */
using HkReceiversMap = std::multimap<object_id_t, struct HkReceiver>; using HkReceivers = std::vector<struct HkReceiver>;
HkReceiversMap hkReceiversMap; HkReceivers hkReceiversMap;
/** This is the map holding the actual data. Should only be initialized /** This is the map holding the actual data. Should only be initialized
* once ! */ * once ! */
@ -245,17 +255,16 @@ private:
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
PoolEntry<T> **poolEntry); PoolEntry<T> **poolEntry);
void setMinimalSamplingFrequency(float frequencySeconds);
ReturnValue_t serializeHkPacketIntoStore( ReturnValue_t serializeHkPacketIntoStore(
HousekeepingPacketDownlink& hkPacket, HousekeepingPacketDownlink& hkPacket,
store_address_t *storeId); store_address_t& storeId, bool forDownlink, size_t* serializedSize);
uint32_t intervalSecondsToInterval(bool isDiagnostics, void performPeriodicHkGeneration(HkReceiver& hkReceiver);
float collectionIntervalSeconds); ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
float intervalToIntervalSeconds(bool isDiagnostics, bool isDiagnostics);
uint32_t collectionInterval); ReturnValue_t changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics);
void performPeriodicHkGeneration(HkReceiver* hkReceiver); ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
}; };
@ -279,4 +288,4 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
} }
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */ #endif /* FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */

View File

@ -1,6 +1,7 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALDATASET_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ #define FSFW_DATAPOOLLOCAL_LOCALDATASET_H_
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "LocalPoolDataSetBase.h"
#include <vector> #include <vector>
class LocalDataSet: public LocalPoolDataSetBase { class LocalDataSet: public LocalPoolDataSetBase {
@ -17,4 +18,4 @@ private:
std::vector<PoolVariableIF*> poolVarList; std::vector<PoolVariableIF*> poolVarList;
}; };
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ */ #endif /* FSFW_DATAPOOLLOCAL_LOCALDATASET_H_ */

View File

@ -1,5 +1,6 @@
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
#include <cmath> #include <cmath>
@ -7,16 +8,22 @@
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
uint32_t setId, PoolVariableIF** registeredVariablesArray, uint32_t setId, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables): const size_t maxNumberOfVariables, bool noPeriodicHandling):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" // Configuration error.
<< std::endl; sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
this->sid.objectId = hkOwner->getObjectId(); this->sid.objectId = hkOwner->getObjectId();
this->sid.ownerSetId = setId; this->sid.ownerSetId = setId;
// Data creators get a periodic helper for periodic HK data generation.
if(not noPeriodicHandling) {
periodicHelper = new PeriodicHousekeepingHelper(this);
}
} }
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
@ -26,8 +33,9 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>( HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
sid.objectId); sid.objectId);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" // Configuration error.
<< std::endl; sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
@ -111,8 +119,14 @@ ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
} }
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer, ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
size_t* size, size_t maxSize, size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness,
SerializeIF::Endianness streamEndianness) const { bool serializeFillCount) const {
// Serialize as uint8_t
uint8_t fillCount = this->fillCount;
if(serializeFillCount) {
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize,
streamEndianness);
}
for (uint16_t count = 0; count < fillCount; count++) { for (uint16_t count = 0; count < fillCount; count++) {
lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId(); lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId();
auto result = SerializeAdapter::serialize(&currentPoolId, buffer, auto result = SerializeAdapter::serialize(&currentPoolId, buffer,
@ -127,6 +141,16 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
} }
uint8_t LocalPoolDataSetBase::getLocalPoolIdsSerializedSize(
bool serializeFillCount) const {
if(serializeFillCount) {
return fillCount * sizeof(lp_id_t) + sizeof(uint8_t);
}
else {
return fillCount * sizeof(lp_id_t);
}
}
size_t LocalPoolDataSetBase::getSerializedSize() const { size_t LocalPoolDataSetBase::getSerializedSize() const {
if(withValidityBuffer) { if(withValidityBuffer) {
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0); uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
@ -175,6 +199,41 @@ void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
*byte |= 1 << shiftNumber; *byte |= 1 << shiftNumber;
} }
void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) {
this->diagnostic = isDiagnostics;
}
bool LocalPoolDataSetBase::isDiagnostics() const {
return diagnostic;
}
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
this->reportingEnabled = reportingEnabled;
}
bool LocalPoolDataSetBase::getReportingEnabled() const {
return reportingEnabled;
}
void LocalPoolDataSetBase::initializePeriodicHelper(
float collectionInterval, dur_millis_t minimumPeriodicInterval,
bool isDiagnostics, uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval,
isDiagnostics, nonDiagIntervalFactor);
}
void LocalPoolDataSetBase::setChanged(bool changed) {
this->changed = changed;
}
bool LocalPoolDataSetBase::isChanged() const {
return changed;
}
sid_t LocalPoolDataSetBase::getSid() const {
return sid;
}
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
uint8_t position) const { uint8_t position) const {
if(position > 7) { if(position > 7) {
@ -190,4 +249,11 @@ bool LocalPoolDataSetBase::isValid() const {
return this->valid; return this->valid;
} }
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
if(setEntriesRecursively) {
for(size_t idx = 0; idx < this->getFillCount(); idx++) {
registeredVariables[idx] -> setValid(valid);
}
}
this->valid = valid;
}

View File

@ -1,27 +1,36 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#include "HasLocalDataPoolIF.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolDataSetBase.h" #include "../datapool/PoolDataSetBase.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../serialize/SerializeIF.h" #include "../serialize/SerializeIF.h"
#include <vector> #include <vector>
class LocalDataPoolManager; class LocalDataPoolManager;
class PeriodicHousekeepingHelper;
/** /**
* @brief The LocalDataSet class manages a set of locally checked out * @brief The LocalDataSet class manages a set of locally checked out
* variables for local data pools * variables for local data pools
* @details * @details
* Extends the PoolDataSetBase class for local data pools by introducing
* a validity state, a flag to mark the set as changed, and various other
* functions to make it usable by the LocalDataPoolManager class.
*
* This class manages a list, where a set of local variables (or pool variables) * This class manages a list, where a set of local variables (or pool variables)
* are registered. They are checked-out (i.e. their values are looked * are registered. They are checked-out (i.e. their values are looked
* up and copied) with the read call. After the user finishes working with the * up and copied) with the read call. After the user finishes working with the
* pool variables, he can write back all variable values to the pool with * pool variables, he can write back all variable values to the pool with
* the commit call. The data set manages locking and freeing the local data pools, * the commit call. The data set manages locking and freeing the local data
* to ensure thread-safety. * pools, to ensure thread-safety.
*
* Pool variables can be added to the dataset by using the constructor
* argument of the pool variable or using the #registerVariable member function.
* *
* An internal state manages usage of this class. Variables may only be * An internal state manages usage of this class. Variables may only be
* registered before the read call is made, and the commit call only * registered before any read call is made, and the commit call can only happen
* after the read call. * after the read call.
* *
* If pool variables are writable and not committed until destruction * If pool variables are writable and not committed until destruction
@ -31,17 +40,21 @@ class LocalDataPoolManager;
* @ingroup data_pool * @ingroup data_pool
*/ */
class LocalPoolDataSetBase: public PoolDataSetBase { class LocalPoolDataSetBase: public PoolDataSetBase {
friend class LocalDataPoolManager;
friend class PeriodicHousekeepingHelper;
public: public:
/** /**
* @brief Constructor for the creator of local pool data. * @brief Constructor for the creator of local pool data.
* @details
* This constructor also initializes the components required for
* periodic handling.
*/ */
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
uint32_t setId, PoolVariableIF** registeredVariablesArray, uint32_t setId, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables); const size_t maxNumberOfVariables, bool noPeriodicHandling = false);
/** /**
* @brief Constructor for users of local pool data. The passed pool * @brief Constructor for users of local pool data.
* owner should implement the HasHkPoolParametersIF.
* @details * @details
* @param sid Unique identifier of dataset consisting of object ID and * @param sid Unique identifier of dataset consisting of object ID and
* set ID. * set ID.
@ -63,6 +76,9 @@ public:
void setValidityBufferGeneration(bool withValidityBuffer); void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const;
/** SerializeIF overrides */
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override; SerializeIF::Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size,
@ -73,7 +89,7 @@ public:
* Special version of the serilization function which appends a * Special version of the serilization function which appends a
* validity buffer at the end. Each bit of this validity buffer * validity buffer at the end. Each bit of this validity buffer
* denotes whether the container data set entries are valid from left * denotes whether the container data set entries are valid from left
* to right, MSB first. * to right, MSB first. (length = ceil(N/8), N = number of pool variables)
* @param buffer * @param buffer
* @param size * @param size
* @param maxSize * @param maxSize
@ -88,18 +104,58 @@ public:
size_t *size, SerializeIF::Endianness streamEndianness); size_t *size, SerializeIF::Endianness streamEndianness);
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer, ReturnValue_t serializeLocalPoolIds(uint8_t** buffer,
size_t* size, size_t maxSize, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const; SerializeIF::Endianness streamEndianness,
bool serializeFillCount = true) const;
uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const;
/**
* Set the dataset valid or invalid
* @param setEntriesRecursively
* If this is true, all contained datasets will also be set recursively.
*/
void setValidity(bool valid, bool setEntriesRecursively);
bool isValid() const override; bool isValid() const override;
void setChanged(bool changed);
bool isChanged() const;
protected: protected:
sid_t sid; sid_t sid;
bool diagnostic = false;
void setDiagnostic(bool diagnostics);
bool isDiagnostics() const;
/**
* Used for periodic generation.
*/
bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
bool getReportingEnabled() const;
void initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
/** /**
* If the valid state of a dataset is always relevant to the whole * If the valid state of a dataset is always relevant to the whole
* data set we can use this flag. * data set we can use this flag.
*/ */
bool valid = false; bool valid = false;
/**
* Can be used to mark the dataset as changed, which is used
* by the LocalDataPoolManager to send out update messages.
*/
bool changed = false;
/**
* Specify whether the validity buffer is serialized too when serializing
* or deserializing the packet. Each bit of the validity buffer will
* contain the validity state of the pool variables from left to right.
* The size of validity buffer thus will be ceil(N / 8) with N = number of
* pool variables.
*/
bool withValidityBuffer = true; bool withValidityBuffer = true;
/** /**
@ -125,9 +181,10 @@ protected:
*/ */
void bitSetter(uint8_t* byte, uint8_t position) const; void bitSetter(uint8_t* byte, uint8_t position) const;
bool bitGetter(const uint8_t* byte, uint8_t position) const; bool bitGetter(const uint8_t* byte, uint8_t position) const;
private:
PeriodicHousekeepingHelper* periodicHelper = nullptr;
}; };
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ */
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ */

View File

@ -1,12 +1,12 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#include "HasLocalDataPoolIF.h"
#include "LocalDataPoolManager.h"
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
/** /**
@ -38,13 +38,13 @@ public:
* @param poolId ID of the local pool entry. * @param poolId ID of the local pool entry.
* @param hkOwner Pointer of the owner. This will generally be the calling * @param hkOwner Pointer of the owner. This will generally be the calling
* class itself which passes "this". * class itself which passes "this".
* @param setReadWriteMode Specify the read-write mode of the pool variable.
* @param dataSet The data set in which the variable shall register itself. * @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered. * If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*/ */
LocalPoolVar(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, LocalPoolVar(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/** /**
* This constructor is used by data users like controllers to have * This constructor is used by data users like controllers to have
@ -58,13 +58,14 @@ public:
* the pool variable in that dataset directly. * the pool variable in that dataset directly.
* @param poolId ID of the local pool entry. * @param poolId ID of the local pool entry.
* @param hkOwner object ID of the pool owner. * @param hkOwner object ID of the pool owner.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
* @param dataSet The data set in which the variable shall register itself. * @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered. * If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*
*/ */
LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, LocalPoolVar(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
virtual~ LocalPoolVar() {}; virtual~ LocalPoolVar() {};
@ -173,4 +174,4 @@ using lp_float_t = LocalPoolVar<float>;
using lp_double_t = LocalPoolVar<double>; using lp_double_t = LocalPoolVar<double>;
#endif #endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ */

View File

@ -1,22 +1,22 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp! #error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
#endif #endif
template<typename T> template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId, inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId,
HasLocalDataPoolIF* hkOwner, pool_rwm_t setReadWriteMode, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
DataSetIF* dataSet): pool_rwm_t setReadWriteMode):
localPoolId(poolId), readWriteMode(setReadWriteMode) { localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
"NO_PARAMETER value!" << std::endl; << "which is the NO_PARAMETER value!" << std::endl;
} }
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner is a nullptr!" sif::error << "LocalPoolVar<T>::LocalPoolVar: The supplied pool "
<< std::endl; << "owner is a invalid!" << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
@ -27,17 +27,18 @@ inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId,
template<typename T> template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId, object_id_t poolOwner, inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode, DataSetIF *dataSet): DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
readWriteMode(setReadWriteMode) { localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
"NO_PARAMETER value!" << std::endl; << "which is the NO_PARAMETER value!" << std::endl;
} }
HasLocalDataPoolIF* hkOwner = HasLocalDataPoolIF* hkOwner =
objectManager->get<HasLocalDataPoolIF>(poolOwner); objectManager->get<HasLocalDataPoolIF>(poolOwner);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner did not implement" sif::error << "LocalPoolVariable: The supplied pool owner did not "
"the correct interface HasHkPoolParametersIF!" << std::endl; << "implement the correct interface "
<< "HasLocalDataPoolIF!" << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();

View File

@ -47,8 +47,9 @@ public:
* If nullptr, the variable is not registered. * If nullptr, the variable is not registered.
*/ */
LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE
);
/** /**
* This constructor is used by data users like controllers to have * This constructor is used by data users like controllers to have
@ -65,8 +66,9 @@ public:
* If nullptr, the variable is not registered. * If nullptr, the variable is not registered.
*/ */
LocalPoolVector(lp_id_t poolId, object_id_t poolOwner, LocalPoolVector(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE
);
/** /**
* @brief This is the local copy of the data pool entry. * @brief This is the local copy of the data pool entry.
@ -192,7 +194,7 @@ private:
}; };
#include "../datapoollocal/LocalPoolVector.tpp" #include "LocalPoolVector.tpp"
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
using lp_vec_t = LocalPoolVector<T, vectorSize>; using lp_vec_t = LocalPoolVector<T, vectorSize>;

View File

@ -7,14 +7,14 @@
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(lp_id_t poolId, inline LocalPoolVector<T, vectorSize>::LocalPoolVector(lp_id_t poolId,
HasLocalDataPoolIF* hkOwner, pool_rwm_t setReadWriteMode, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
DataSetIF* dataSet) : pool_rwm_t setReadWriteMode):
localPoolId(poolId), valid(false), readWriteMode(setReadWriteMode) { localPoolId(poolId), valid(false), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " sif::warning << "LocalPoolVector: PoolVariableIF::NO_PARAMETER passed "
"NO_PARAMETER value!" << std::endl; << "as pool ID, which is the NO_PARAMETER value!" << std::endl;
} }
memset(this->value, 0, vectorSize * sizeof(T)); std::memset(this->value, 0, vectorSize * sizeof(T));
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
if (dataSet != nullptr) { if (dataSet != nullptr) {
dataSet->registerVariable(this); dataSet->registerVariable(this);
@ -23,17 +23,18 @@ inline LocalPoolVector<T, vectorSize>::LocalPoolVector(lp_id_t poolId,
template<typename T, uint16_t vectorSize> template<typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(lp_id_t poolId, inline LocalPoolVector<T, vectorSize>::LocalPoolVector(lp_id_t poolId,
object_id_t poolOwner, pool_rwm_t setReadWriteMode, DataSetIF *dataSet): object_id_t poolOwner, DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
readWriteMode(readWriteMode) { readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) { if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the " sif::warning << "LocalPoolVector: PoolVariableIF::NO_PARAMETER passed "
"NO_PARAMETER value!" << std::endl; << "as pool ID, which is the NO_PARAMETER value!" << std::endl;
} }
HasLocalDataPoolIF* hkOwner = HasLocalDataPoolIF* hkOwner =
objectManager->get<HasLocalDataPoolIF>(poolOwner); objectManager->get<HasLocalDataPoolIF>(poolOwner);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner did not implement" sif::error << "LocalPoolVariable: The supplied pool owner did not "
"the correct interface HasHkPoolParametersIF!" << std::endl; << "implement the correct interface HasHkPoolParametersIF!"
<< std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
@ -67,7 +68,7 @@ inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
std::dec << " failed." << std::endl; std::dec << " failed." << std::endl;
return result; return result;
} }
memcpy(this->value, poolEntry->address, poolEntry->getByteSize()); std::memcpy(this->value, poolEntry->address, poolEntry->getByteSize());
this->valid = poolEntry->valid; this->valid = poolEntry->valid;
return RETURN_OK; return RETURN_OK;
} }
@ -96,7 +97,7 @@ inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
std::dec << " failed.\n" << std::flush; std::dec << " failed.\n" << std::flush;
return result; return result;
} }
memcpy(poolEntry->address, this->value, poolEntry->getByteSize()); std::memcpy(poolEntry->address, this->value, poolEntry->getByteSize());
poolEntry->valid = this->valid; poolEntry->valid = this->valid;
return RETURN_OK; return RETURN_OK;
} }

View File

@ -1,17 +1,11 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ #ifndef FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#define FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ #define FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#include "LocalPoolDataSetBase.h"
#include "../datapool/SharedDataSetIF.h" #include "../datapool/SharedDataSetIF.h"
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include <vector> #include <vector>
/**
* Baseline question: If this dataset is shared, is there once instance
* shared among many objects or multiple instances? Maybe be flexible
* and provide both ways? Sharing one instance requires a mutex lock.
* If there are multiple instances, it is not shared anymore, to be fair..
* Then a regular local data set is sufficient.
*/
class SharedLocalDataSet: public SystemObject, class SharedLocalDataSet: public SystemObject,
public LocalPoolDataSetBase, public LocalPoolDataSetBase,
public SharedDataSetIF { public SharedDataSetIF {
@ -27,5 +21,4 @@ private:
}; };
#endif /* FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */
#endif /* FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */

View File

@ -1,5 +1,6 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ #ifndef FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#define FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ #define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include <array> #include <array>
@ -7,21 +8,43 @@
/** /**
* @brief This local dataset type is created on the stack. * @brief This local dataset type is created on the stack.
* @details * @details
* Size of data set specified as a constructor argument. It is recommended * This will is the primary data structure to organize pool variables into
* to use the default LocalDataSet of the dataset is constructed on the heap * sets which can be accessed via the housekeeping service interface or
* and the SharedLocalDataSet if it created on the heap and used by multiple * which can be sent to other software objects.
* other software objects. *
* @tparam capacity * It is recommended to read the documentation of the LocalPoolDataSetBase
* class for more information on how this class works and how to use it.
* @tparam capacity Capacity of the static dataset, which is usually known
* beforehand.
*/ */
template <uint8_t NUM_VARIABLES> template <uint8_t NUM_VARIABLES>
class StaticLocalDataSet: public LocalPoolDataSetBase { class StaticLocalDataSet: public LocalPoolDataSetBase {
public: public:
StaticLocalDataSet(sid_t sid): /**
LocalPoolDataSetBase(sid, poolVarList.data(), NUM_VARIABLES) { * Constructor used by data owner and creator like device handlers.
* This constructor also initialized the components required for
* periodic handling.
* @param hkOwner
* @param setId
*/
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner,
uint32_t setId): LocalPoolDataSetBase(hkOwner, setId, nullptr,
NUM_VARIABLES) {
this->setContainer(poolVarList.data());
}
/**
* Constructor used by data users like controllers.
* @param hkOwner
* @param setId
*/
StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr,
NUM_VARIABLES) {
this->setContainer(poolVarList.data());
} }
private: private:
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList; std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList;
}; };
#endif /* FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */ #endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */

View File

@ -122,7 +122,7 @@ uint32_t CommunicationMessage::getUint32Data() const{
} }
void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) { void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) {
if(0 <= position && position <= 3) { if(position <= 3) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), &byte, sizeof(byte)); memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), &byte, sizeof(byte));
} }
else { else {
@ -131,7 +131,7 @@ void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) {
} }
uint8_t CommunicationMessage::getDataByte(uint8_t position) const { uint8_t CommunicationMessage::getDataByte(uint8_t position) const {
if(0 <= position && position <= 3) { if(position <= 3) {
uint8_t byte; uint8_t byte;
memcpy(&byte, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), sizeof(byte)); memcpy(&byte, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), sizeof(byte));
return byte; return byte;

View File

@ -1,18 +1,18 @@
#include "../devicehandlers/DeviceHandlerBase.h" #include "DeviceHandlerBase.h"
#include "AcceptsDeviceResponsesIF.h"
#include "DeviceTmReportingWrapper.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../objectmanager/ObjectManager.h" #include "../objectmanager/ObjectManager.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include "../thermal/ThermalComponentIF.h" #include "../thermal/ThermalComponentIF.h"
#include "../devicehandlers/AcceptsDeviceResponsesIF.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../devicehandlers/DeviceTmReportingWrapper.h"
#include "../globalfunctions/CRC.h" #include "../globalfunctions/CRC.h"
#include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/HousekeepingMessage.h"
#include "../ipc/MessageQueueMessage.h" #include "../ipc/MessageQueueMessage.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../subsystem/SubsystemBase.h"
#include <iomanip> #include <iomanip>
@ -399,7 +399,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode,
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
PoolDataSetIF* replyDataSet, size_t replyLen, bool periodic, LocalPoolDataSetBase* replyDataSet, size_t replyLen, bool periodic,
bool hasDifferentReplyId, DeviceCommandId_t replyId) { bool hasDifferentReplyId, DeviceCommandId_t replyId) {
//No need to check, as we may try to insert multiple times. //No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand); insertInCommandMap(deviceCommand);
@ -413,7 +413,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
} }
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, PoolDataSetIF* dataSet, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet,
size_t replyLen, bool periodic) { size_t replyLen, bool periodic) {
DeviceReplyInfo info; DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles; info.maxDelayCycles = maxDelayCycles;
@ -463,7 +463,7 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF *dataSet) { LocalPoolDataSetBase *dataSet) {
auto replyIter = deviceReplyMap.find(replyId); auto replyIter = deviceReplyMap.find(replyId);
if(replyIter == deviceReplyMap.end()) { if(replyIter == deviceReplyMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
@ -1286,10 +1286,14 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (iter == deviceCommandMap.end()) { if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED; result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) { } else if (iter->second.isExecuting) {
//so we can track misconfigurations
sif::debug << std::hex << getObjectId() sif::debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Command " << ": DHB::buildInternalCommand: Command "
<< deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations << deviceCommandId << " isExecuting" << std::dec
return; //this is an internal command, no need to report a failure here, missed reply will track if a reply is too late, otherwise, it's ok << std::endl;
// this is an internal command, no need to report a failure here,
// missed reply will track if a reply is too late, otherwise, it's ok
return;
} else { } else {
iter->second.sendReplyTo = NO_COMMANDER; iter->second.sendReplyTo = NO_COMMANDER;
iter->second.isExecuting = true; iter->second.isExecuting = true;
@ -1396,10 +1400,14 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
pstIntervalMs = executingTask->getPeriodMs(); pstIntervalMs = executingTask->getPeriodMs();
} }
this->hkManager.initializeAfterTaskCreation(); this->hkManager.initializeAfterTaskCreation();
if(setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE);
}
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) { LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
auto iter = deviceReplyMap.find(sid.ownerSetId); auto iter = deviceReplyMap.find(sid.ownerSetId);
if(iter != deviceReplyMap.end()) { if(iter != deviceReplyMap.end()) {
return iter->second.dataSet; return iter->second.dataSet;
@ -1413,6 +1421,10 @@ object_id_t DeviceHandlerBase::getObjectId() const {
return SystemObject::getObjectId(); return SystemObject::getObjectId();
} }
void DeviceHandlerBase::setStartUpImmediately() {
this->setStartupImmediately = true;
}
dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
return pstIntervalMs; return pstIntervalMs;
} }

View File

@ -1,25 +1,26 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ #define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#include "DeviceHandlerIF.h"
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
#include "../objectmanager/SystemObject.h" #include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../devicehandlers/DeviceHandlerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
#include "../datapool/PoolVariableIF.h" #include "../datapool/PoolVariableIF.h"
#include "../devicehandlers/DeviceCommunicationIF.h"
#include "../modes/HasModesIF.h" #include "../modes/HasModesIF.h"
#include "../power/PowerSwitchIF.h" #include "../power/PowerSwitchIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../tasks/PeriodicTaskIF.h" #include "../tasks/PeriodicTaskIF.h"
#include "../action/ActionHelper.h" #include "../action/ActionHelper.h"
#include "../health/HealthHelper.h" #include "../health/HealthHelper.h"
#include "../parameters/ParameterHelper.h" #include "../parameters/ParameterHelper.h"
#include "../datapool/HkSwitchHelper.h" #include "../datapool/HkSwitchHelper.h"
#include "../datapoollocal/HasLocalDataPoolIF.h" #include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include <map> #include <map>
namespace Factory{ namespace Factory{
@ -104,6 +105,18 @@ public:
void setHkDestination(object_id_t hkDestination); void setHkDestination(object_id_t hkDestination);
void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId, void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId); uint32_t thermalRequestPoolId);
/**
* @brief Helper function to ease device handler development.
* This will instruct the transition to MODE_ON immediately
* (leading to doStartUp() being called for the transition to the ON mode),
* so external mode commanding is not necessary anymore.
*
* This has to be called before the task is started!
* (e.g. in the task factory). This is only a helper function for
* development. Regular mode commanding should be performed by commanding
* the AssemblyBase or Subsystem objects resposible for the device handler.
*/
void setStartUpImmediately();
/** /**
* @brief This function is the device handler base core component and is * @brief This function is the device handler base core component and is
@ -149,6 +162,14 @@ public:
* @return * @return
*/ */
virtual ReturnValue_t initialize(); virtual ReturnValue_t initialize();
/**
* @brief Intialization steps performed after all tasks have been created.
* This function will be called by the executing task.
* @return
*/
virtual ReturnValue_t initializeAfterTaskCreation() override;
/** Destructor. */ /** Destructor. */
virtual ~DeviceHandlerBase(); virtual ~DeviceHandlerBase();
@ -370,7 +391,8 @@ protected:
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, PoolDataSetIF* replyDataSet = nullptr, uint16_t maxDelayCycles,
LocalPoolDataSetBase* replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false, size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
@ -385,7 +407,7 @@ protected:
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, PoolDataSetIF* dataSet = nullptr, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
size_t replyLen = 0, bool periodic = false); size_t replyLen = 0, bool periodic = false);
/** /**
@ -415,7 +437,7 @@ protected:
bool periodic = false); bool periodic = false);
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF* dataset); LocalPoolDataSetBase* dataset);
/** /**
* @brief Can be implemented by child handler to * @brief Can be implemented by child handler to
@ -645,7 +667,7 @@ protected:
//! The dataset used to access housekeeping data related to the //! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by //! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified) //! the child handler (if one is specified)
PoolDataSetIF* dataSet = nullptr; LocalPoolDataSetBase* dataSet;
//! The command that expects this reply. //! The command that expects this reply.
DeviceCommandMap::iterator command; DeviceCommandMap::iterator command;
}; };
@ -946,14 +968,17 @@ protected:
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode); uint32_t *msToReachTheMode);
virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void setToExternalControl(); /* HasModesIF overrides */
virtual void announceMode(bool recursive); virtual void startTransition(Mode_t mode, Submode_t submode) override;
virtual void setToExternalControl() override;
virtual void announceMode(bool recursive) override;
virtual ReturnValue_t letChildHandleMessage(CommandMessage *message); virtual ReturnValue_t letChildHandleMessage(CommandMessage *message);
/** /**
* Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper" faster about executed events. * Overwrites SystemObject::triggerEvent in order to inform FDIR"Helper"
* faster about executed events.
* This is a bit sneaky, but improves responsiveness of the device FDIR. * This is a bit sneaky, but improves responsiveness of the device FDIR.
* @param event The event to be thrown * @param event The event to be thrown
* @param parameter1 Optional parameter 1 * @param parameter1 Optional parameter 1
@ -1045,6 +1070,8 @@ private:
*/ */
uint32_t timeoutStart = 0; uint32_t timeoutStart = 0;
bool setStartupImmediately = false;
/** /**
* Delay for the current mode transition, used for time out * Delay for the current mode transition, used for time out
*/ */
@ -1163,7 +1190,6 @@ private:
ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data, ReturnValue_t getStorageData(store_address_t storageAddress, uint8_t **data,
uint32_t *len); uint32_t *len);
/** /**
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!! * @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!!
*/ */
@ -1174,28 +1200,14 @@ private:
*/ */
void callChildStatemachine(); void callChildStatemachine();
/**
* Switches the channel of the cookie used for the communication
*
*
* @param newChannel the object Id of the channel to switch to
* @return
* - @c RETURN_OK when cookie was changed
* - @c RETURN_FAILED when cookies could not be changed,
* e.g. because the newChannel is not enabled
* - @c returnvalues of RMAPChannelIF::isActive()
*/
ReturnValue_t switchCookieChannel(object_id_t newChannelId);
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual DataSetIF* getDataSetHandle(sid_t sid) override;
virtual dur_millis_t getPeriodicOperationFrequency() const override;
void parseReply(const uint8_t* receivedData, void parseReply(const uint8_t* receivedData,
size_t receivedDataLen); size_t receivedDataLen);
virtual dur_millis_t getPeriodicOperationFrequency() const override;
}; };
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -247,6 +247,14 @@ bool DeviceHandlerFailureIsolation::isFdirInActionOrAreWeFaulty(
} }
return true; return true;
} }
if (owner == nullptr) {
// Configuration error.
sif::error << "DeviceHandlerFailureIsolation::"
<< "isFdirInActionOrAreWeFaulty: Owner not set!" << std::endl;
return false;
}
if (owner->getHealth() == HasHealthIF::FAULTY if (owner->getHealth() == HasHealthIF::FAULTY
|| owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) { || owner->getHealth() == HasHealthIF::PERMANENT_FAULTY) {
//Ignore all events in case device is already faulty. //Ignore all events in case device is already faulty.

View File

@ -1,12 +1,19 @@
#ifndef DEVICEHANDLERIF_H_ #ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#define DEVICEHANDLERIF_H_ #define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#include "DeviceHandlerMessage.h"
#include "../action/HasActionsIF.h" #include "../action/HasActionsIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../events/Event.h" #include "../events/Event.h"
#include "../modes/HasModesIF.h" #include "../modes/HasModesIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
/**
* This is used to uniquely identify commands that are sent to a device
* The values are defined in the device-specific implementations
*/
using DeviceCommandId_t = uint32_t;
/** /**
* @brief This is the Interface used to communicate with a device handler. * @brief This is the Interface used to communicate with a device handler.
* @details Includes all expected return values, events and modes. * @details Includes all expected return values, events and modes.
@ -15,6 +22,7 @@
class DeviceHandlerIF { class DeviceHandlerIF {
public: public:
static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20; static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10; static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
@ -153,4 +161,4 @@ public:
}; };
#endif /* DEVICEHANDLERIF_H_ */ #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */

View File

@ -1,9 +1,5 @@
#include "DeviceHandlerMessage.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../objectmanager/ObjectManagerIF.h"
DeviceHandlerMessage::DeviceHandlerMessage() {
}
store_address_t DeviceHandlerMessage::getStoreAddress( store_address_t DeviceHandlerMessage::getStoreAddress(
const CommandMessage* message) { const CommandMessage* message) {
@ -25,14 +21,6 @@ uint8_t DeviceHandlerMessage::getWiretappingMode(
return message->getParameter(); return message->getParameter();
} }
//void DeviceHandlerMessage::setDeviceHandlerDirectCommandMessage(
// CommandMessage* message, DeviceCommandId_t deviceCommand,
// store_address_t commandParametersStoreId) {
// message->setCommand(CMD_DIRECT);
// message->setParameter(deviceCommand);
// message->setParameter2(commandParametersStoreId.raw);
//}
void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage( void DeviceHandlerMessage::setDeviceHandlerRawCommandMessage(
CommandMessage* message, store_address_t rawPacketStoreId) { CommandMessage* message, store_address_t rawPacketStoreId) {
message->setCommand(CMD_RAW); message->setCommand(CMD_RAW);
@ -79,13 +67,12 @@ void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply(
void DeviceHandlerMessage::clear(CommandMessage* message) { void DeviceHandlerMessage::clear(CommandMessage* message) {
switch (message->getCommand()) { switch (message->getCommand()) {
case CMD_RAW: case CMD_RAW:
// case CMD_DIRECT:
case REPLY_RAW_COMMAND: case REPLY_RAW_COMMAND:
case REPLY_RAW_REPLY: case REPLY_RAW_REPLY:
case REPLY_DIRECT_COMMAND_DATA: { case REPLY_DIRECT_COMMAND_DATA: {
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>( StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
objects::IPC_STORE); objects::IPC_STORE);
if (ipcStore != NULL) { if (ipcStore != nullptr) {
ipcStore->deleteData(getStoreAddress(message)); ipcStore->deleteData(getStoreAddress(message));
} }
} }

View File

@ -1,69 +1,56 @@
#ifndef DEVICEHANDLERMESSAGE_H_ #ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_
#define DEVICEHANDLERMESSAGE_H_ #define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_
#include "../action/ActionMessage.h" #include "../action/ActionMessage.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
//SHOULDDO: rework the static constructors to name the type of command they are building, maybe even hide setting the commandID. // SHOULDDO: rework the static constructors to name the type of command
// they are building, maybe even hide setting the commandID.
/** /**
* This is used to uniquely identify commands that are sent to a device * @brief The DeviceHandlerMessage is used to send commands to classes
* * implementing DeviceHandlerIF
* The values are defined in the device-specific implementations
*/
typedef uint32_t DeviceCommandId_t;
/**
* The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF
*/ */
class DeviceHandlerMessage { class DeviceHandlerMessage {
private:
DeviceHandlerMessage();
public: public:
/**
* Instantiation forbidden. Instead, use static functions to operate
* on messages.
*/
DeviceHandlerMessage() = delete;
virtual ~DeviceHandlerMessage() {}
/** /**
* These are the commands that can be sent to a DeviceHandlerBase * These are the commands that can be sent to a DeviceHandlerBase
*/ */
static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND; static const uint8_t MESSAGE_ID = messagetypes::DEVICE_HANDLER_COMMAND;
static const Command_t CMD_RAW = MAKE_COMMAND_ID( 1 ); //!< Sends a raw command, setParameter is a ::store_id_t containing the raw packet to send //! Sends a raw command, setParameter is a storeId containing the
// static const Command_t CMD_DIRECT = MAKE_COMMAND_ID( 2 ); //!< Sends a direct command, setParameter is a ::DeviceCommandId_t, setParameter2 is a ::store_id_t containing the data needed for the command //! raw packet to send
static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID( 3 ); //!< Requests a IO-Board switch, setParameter() is the IO-Board identifier static const Command_t CMD_RAW = MAKE_COMMAND_ID(1);
static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate //! Requests a IO-Board switch, setParameter() is the IO-Board identifier
static const Command_t CMD_SWITCH_ADDRESS = MAKE_COMMAND_ID(3);
//! (De)Activates the monitoring of all raw traffic in DeviceHandlers,
//! setParameter is 0 to deactivate, 1 to activate
static const Command_t CMD_WIRETAPPING = MAKE_COMMAND_ID(4);
/*static const Command_t REPLY_SWITCHED_IOBOARD = MAKE_COMMAND_ID(1 );//!< Reply to a @c CMD_SWITCH_IOBOARD, indicates switch was successful, getParameter() contains the board switched to (0: nominal, 1: redundant) //! Signals that a direct command was sent
static const Command_t REPLY_CANT_SWITCH_IOBOARD = MAKE_COMMAND_ID( 2); //!< Reply to a @c CMD_SWITCH_IOBOARD, indicating the switch could not be performed, getParameter() contains the error message static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS;
static const Command_t REPLY_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled //! Contains a raw command sent to the Device
static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11);
static const Command_t REPLY_COMMAND_WAS_SENT = MAKE_COMMAND_ID(4 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was successfully sent to the device, getParameter() contains the ::DeviceCommandId_t //! Contains a raw reply from the Device, getParameter() is the ObjcetId
static const Command_t REPLY_COMMAND_NOT_SUPPORTED = MAKE_COMMAND_ID(5 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t is not supported, getParameter() contains the requested ::DeviceCommand_t, getParameter2() contains the ::DeviceCommandId_t //! of the sender, getParameter2() is a ::store_id_t containing the
static const Command_t REPLY_COMMAND_WAS_NOT_SENT = MAKE_COMMAND_ID(6 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates the command was not sent, getParameter contains the RMAP Return code (@see rmap.h), getParameter2() contains the ::DeviceCommandId_t //! raw packet received
static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID(0x12);
static const Command_t REPLY_COMMAND_ALREADY_SENT = MAKE_COMMAND_ID(7 );//!< Reply to a @c CMD_DIRECT, the requested ::DeviceCommand_t has already been sent to the device and not ye been answered
static const Command_t REPLY_WRONG_MODE_FOR_CMD = MAKE_COMMAND_ID(8 );//!< Reply to a @c CMD_RAW or @c CMD_DIRECT, indicates that the requested command can not be sent in the curent mode, getParameter() contains the DeviceHandlerCommand_t
static const Command_t REPLY_NO_DATA = MAKE_COMMAND_ID(9 ); //!< Reply to a CMD_RAW or @c CMD_DIRECT, indicates that the ::store_id_t was invalid, getParameter() contains the ::DeviceCommandId_t, getPrameter2() contains the error code
*/
static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS; //!< Signals that a direct command was sent
static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11 ); //!< Contains a raw command sent to the Device
static const Command_t REPLY_RAW_REPLY = MAKE_COMMAND_ID( 0x12); //!< Contains a raw reply from the Device, getParameter() is the ObjcetId of the sender, getParameter2() is a ::store_id_t containing the raw packet received
static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY; static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY;
/**
* Default Destructor
*/
virtual ~DeviceHandlerMessage() {
}
static store_address_t getStoreAddress(const CommandMessage* message); static store_address_t getStoreAddress(const CommandMessage* message);
static uint32_t getDeviceCommandId(const CommandMessage* message); static uint32_t getDeviceCommandId(const CommandMessage* message);
static object_id_t getDeviceObjectId(const CommandMessage *message); static object_id_t getDeviceObjectId(const CommandMessage *message);
static object_id_t getIoBoardObjectId(const CommandMessage* message); static object_id_t getIoBoardObjectId(const CommandMessage* message);
static uint8_t getWiretappingMode(const CommandMessage* message); static uint8_t getWiretappingMode(const CommandMessage* message);
// static void setDeviceHandlerDirectCommandMessage(CommandMessage* message,
// DeviceCommandId_t deviceCommand,
// store_address_t commandParametersStoreId);
static void setDeviceHandlerDirectCommandReply(CommandMessage* message, static void setDeviceHandlerDirectCommandReply(CommandMessage* message,
object_id_t deviceObjectid, object_id_t deviceObjectid,
store_address_t commandParametersStoreId); store_address_t commandParametersStoreId);
@ -75,11 +62,6 @@ public:
object_id_t deviceObjectid, store_address_t rawPacketStoreId, object_id_t deviceObjectid, store_address_t rawPacketStoreId,
bool isCommand); bool isCommand);
// static void setDeviceHandlerMessage(CommandMessage* message,
// Command_t command, DeviceCommandId_t deviceCommand,
// store_address_t commandParametersStoreId);
// static void setDeviceHandlerMessage(CommandMessage* message,
// Command_t command, store_address_t rawPacketStoreId);
static void setDeviceHandlerWiretappingMessage(CommandMessage* message, static void setDeviceHandlerWiretappingMessage(CommandMessage* message,
uint8_t wiretappingMode); uint8_t wiretappingMode);
static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message, static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message,
@ -88,4 +70,4 @@ public:
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
}; };
#endif /* DEVICEHANDLERMESSAGE_H_ */ #endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */

View File

@ -1,4 +1,5 @@
#include "Event.h" #include "Event.h"
namespace EVENT { namespace EVENT {
EventId_t getEventId(Event event) { EventId_t getEventId(Event event) {
return (event & 0xFFFF); return (event & 0xFFFF);
@ -8,7 +9,8 @@ EventSeverity_t getSeverity(Event event) {
return ((event >> 16) & 0xFF); return ((event >> 16) & 0xFF);
} }
Event makeEvent(EventId_t eventId, EventSeverity_t eventSeverity) { Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
return (eventSeverity << 16) + (eventId & 0xFFFF); EventSeverity_t eventSeverity) {
return (eventSeverity << 16) + (subsystemId * 100) + uniqueEventId;
} }
} }

View File

@ -4,7 +4,7 @@
#include <stdint.h> #include <stdint.h>
#include "fwSubsystemIdRanges.h" #include "fwSubsystemIdRanges.h"
//could be move to more suitable location //could be move to more suitable location
#include <config/tmtc/subsystemIdRanges.h> #include <subsystemIdRanges.h>
typedef uint16_t EventId_t; typedef uint16_t EventId_t;
typedef uint8_t EventSeverity_t; typedef uint8_t EventSeverity_t;
@ -18,9 +18,10 @@ EventId_t getEventId(Event event);
EventSeverity_t getSeverity(Event event); EventSeverity_t getSeverity(Event event);
Event makeEvent(EventId_t eventId, EventSeverity_t eventSeverity); Event makeEvent(uint8_t subsystemId, uint8_t uniqueEventId,
EventSeverity_t eventSeverity);
} }
namespace SEVERITY { namespace SEVERITY {
static const EventSeverity_t INFO = 1; static const EventSeverity_t INFO = 1;
static const EventSeverity_t LOW = 2; static const EventSeverity_t LOW = 2;

View File

@ -109,13 +109,13 @@ ReturnValue_t EventManager::unsubscribeFromEventRange(MessageQueueId_t listener,
return result; return result;
} }
#ifdef DEBUG #if FSFW_DEBUG_OUTPUT == 1
void EventManager::printEvent(EventMessage* message) { void EventManager::printEvent(EventMessage* message) {
const char *string = 0; const char *string = 0;
switch (message->getSeverity()) { switch (message->getSeverity()) {
case SEVERITY::INFO: case SEVERITY::INFO:
#ifdef DEBUG_INFO_EVENT #if DEBUG_INFO_EVENT == 1
string = translateObject(message->getReporter()); string = translateObject(message->getReporter());
sif::info << "EVENT: "; sif::info << "EVENT: ";
if (string != 0) { if (string != 0) {

View File

@ -8,9 +8,11 @@
#include "../tasks/ExecutableObjectIF.h" #include "../tasks/ExecutableObjectIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../ipc/MutexIF.h" #include "../ipc/MutexIF.h"
#include <FSFWConfig.h>
#include <map> #include <map>
#ifdef DEBUG #if FSFW_DEBUG_OUTPUT == 1
// forward declaration, should be implemented by mission // forward declaration, should be implemented by mission
extern const char* translateObject(object_id_t object); extern const char* translateObject(object_id_t object);
extern const char* translateEvents(Event event); extern const char* translateEvents(Event event);
@ -55,7 +57,7 @@ protected:
void notifyListeners(EventMessage *message); void notifyListeners(EventMessage *message);
#ifdef DEBUG #if FSFW_DEBUG_OUTPUT == 1
void printEvent(EventMessage *message); void printEvent(EventMessage *message);
#endif #endif

View File

@ -1,10 +1,11 @@
#ifndef EVENTMANAGERIF_H_ #ifndef EVENTMANAGERIF_H_
#define EVENTMANAGERIF_H_ #define EVENTMANAGERIF_H_
#include "eventmatching/eventmatching.h"
#include "EventMessage.h" #include "EventMessage.h"
#include "eventmatching/eventmatching.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
#include "../ipc/MessageQueueIF.h"
class EventManagerIF { class EventManagerIF {
public: public:
@ -16,7 +17,8 @@ public:
virtual MessageQueueId_t getEventReportQueue() = 0; virtual MessageQueueId_t getEventReportQueue() = 0;
virtual ReturnValue_t registerListener(MessageQueueId_t listener, bool forwardAllButSelected = false) = 0; virtual ReturnValue_t registerListener(MessageQueueId_t listener,
bool forwardAllButSelected = false) = 0;
virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener, virtual ReturnValue_t subscribeToEvent(MessageQueueId_t listener,
EventId_t event) = 0; EventId_t event) = 0;
virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener, virtual ReturnValue_t subscribeToAllEventsFrom(MessageQueueId_t listener,
@ -31,18 +33,22 @@ public:
bool reporterInverted = false) = 0; bool reporterInverted = false) = 0;
static void triggerEvent(object_id_t reportingObject, Event event, static void triggerEvent(object_id_t reportingObject, Event event,
uint32_t parameter1 = 0, uint32_t parameter2 = 0, MessageQueueId_t sentFrom = 0) { uint32_t parameter1 = 0, uint32_t parameter2 = 0,
MessageQueueId_t sentFrom = 0) {
EventMessage message(event, reportingObject, parameter1, parameter2); EventMessage message(event, reportingObject, parameter1, parameter2);
triggerEvent(&message, sentFrom); triggerEvent(&message, sentFrom);
} }
static void triggerEvent(EventMessage* message, MessageQueueId_t sentFrom = 0) {
static MessageQueueId_t eventmanagerQueue = 0; static void triggerEvent(EventMessage* message,
if (eventmanagerQueue == 0) { MessageQueueId_t sentFrom = 0) {
static MessageQueueId_t eventmanagerQueue = MessageQueueIF::NO_QUEUE;
if (eventmanagerQueue == MessageQueueIF::NO_QUEUE) {
EventManagerIF *eventmanager = objectManager->get<EventManagerIF>( EventManagerIF *eventmanager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER); objects::EVENT_MANAGER);
if (eventmanager != NULL) { if (eventmanager == nullptr) {
eventmanagerQueue = eventmanager->getEventReportQueue(); return;
} }
eventmanagerQueue = eventmanager->getEventReportQueue();
} }
MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom); MessageQueueSenderIF::sendMessage(eventmanagerQueue, message, sentFrom);
} }

View File

@ -19,6 +19,8 @@ enum {
SYSTEM_MANAGER_1 = 75, SYSTEM_MANAGER_1 = 75,
SYSTEM_1 = 79, SYSTEM_1 = 79,
PUS_SERVICE_1 = 80, PUS_SERVICE_1 = 80,
PUS_SERVICE_9 = 89,
PUS_SERVICE_17 = 97,
FW_SUBSYSTEM_ID_RANGE FW_SUBSYSTEM_ID_RANGE
}; };
} }

View File

@ -4,7 +4,6 @@
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueSenderIF.h" #include "../ipc/MessageQueueSenderIF.h"
// TODO: Documentation.
class ConfirmsFailuresIF { class ConfirmsFailuresIF {
public: public:
static const uint8_t INTERFACE_ID = CLASS_ID::HANDLES_FAILURES_IF; static const uint8_t INTERFACE_ID = CLASS_ID::HANDLES_FAILURES_IF;

View File

@ -1,4 +1,4 @@
#include "../fdir/EventCorrelation.h" #include "EventCorrelation.h"
EventCorrelation::EventCorrelation(uint32_t timeout) : EventCorrelation::EventCorrelation(uint32_t timeout) :
eventPending(false) { eventPending(false) {

View File

@ -1,5 +1,5 @@
#include "../events/EventManagerIF.h" #include "../events/EventManagerIF.h"
#include "../fdir/FailureIsolationBase.h" #include "FailureIsolationBase.h"
#include "../health/HasHealthIF.h" #include "../health/HasHealthIF.h"
#include "../health/HealthMessage.h" #include "../health/HealthMessage.h"
#include "../ipc/QueueFactory.h" #include "../ipc/QueueFactory.h"

View File

@ -2,8 +2,8 @@
#define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ #define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_
#include "../events/EventMessage.h" #include "../events/EventMessage.h"
#include "../fdir/ConfirmsFailuresIF.h" #include "ConfirmsFailuresIF.h"
#include "../fdir/FaultCounter.h" #include "FaultCounter.h"
#include "../health/HealthMessage.h" #include "../health/HealthMessage.h"
#include "../parameters/HasParametersIF.h" #include "../parameters/HasParametersIF.h"
#include "../returnvalues/HasReturnvaluesIF.h" #include "../returnvalues/HasReturnvaluesIF.h"

View File

@ -1,4 +1,4 @@
#include "../fdir/FaultCounter.h" #include "FaultCounter.h"
FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs, FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain) : uint8_t setParameterDomain) :

13
fsfw.mk
View File

@ -31,12 +31,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp)
# select the OS # select the OS
ifeq ($(OS_FSFW),rtems) ifeq ($(OS_FSFW),rtems)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp)
else ifeq ($(OS_FSFW),linux) else ifeq ($(OS_FSFW),linux)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp)
else ifeq ($(OS_FSFW),freeRTOS) else ifeq ($(OS_FSFW),freeRTOS)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp)
else ifeq ($(OS_FSFW),host) else ifeq ($(OS_FSFW),host)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp) CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/host/*.cpp)
ifeq ($(OS),Windows_NT)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/windows/*.cpp)
else
# For now, the linux UDP bridge sources needs to be included manually by upper makefile
# for host OS because we can't be sure the OS is linux.
# Following lines can be used to do this:
# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp
# CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp
endif
else else
$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host) $(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host)
endif endif

View File

@ -1,4 +1,4 @@
#include "../globalfunctions/AsciiConverter.h" #include "AsciiConverter.h"
#include <limits> #include <limits>
#include <cmath> #include <cmath>

View File

@ -1,4 +1,4 @@
#include "../globalfunctions/CRC.h" #include "CRC.h"
#include <math.h> #include <math.h>
const uint16_t CRC::crc16ccitt_table[256] = { const uint16_t CRC::crc16ccitt_table[256] = {

View File

@ -92,7 +92,7 @@ ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
else { else {
/* The next byte is a STX, DTX or 0x0D character which /* The next byte is a STX, DTX or 0x0D character which
* was escaped by a DLE character. The actual byte was * was escaped by a DLE character. The actual byte was
* also encoded by adding + 0x40 to preven having control chars, * also encoded by adding + 0x40 to prevent having control chars,
* in the stream at all, so we convert it back. */ * in the stream at all, so we convert it back. */
if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) { if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) {
destStream[decodedIndex] = nextByte - 0x40; destStream[decodedIndex] = nextByte - 0x40;

View File

@ -15,12 +15,12 @@
* char based transmission systems. * char based transmission systems.
* The passed source strean is converted into a encoded stream by adding * The passed source strean is converted into a encoded stream by adding
* a STX marker at the start of the stream and an ETX marker at the end of * a STX marker at the start of the stream and an ETX marker at the end of
* the stream. Any STX, ETX, DLE and CR occurences in the source stream are * the stream. Any STX, ETX, DLE and CR occurrences in the source stream are
* escaped by a DLE character. The encoder also replaces escaped control chars * escaped by a DLE character. The encoder also replaces escaped control chars
* by another char, so STX, ETX and CR should not appear anywhere in the actual * by another char, so STX, ETX and CR should not appear anywhere in the actual
* encoded data stream. * encoded data stream.
* *
* When using a strictly char based reception of packets enoded with DLE, * When using a strictly char based reception of packets encoded with DLE,
* STX can be used to notify a reader that actual data will start to arrive * STX can be used to notify a reader that actual data will start to arrive
* while ETX can be used to notify the reader that the data has ended. * while ETX can be used to notify the reader that the data has ended.
*/ */
@ -38,7 +38,7 @@ public:
static constexpr uint8_t STX_CHAR = 0x02; static constexpr uint8_t STX_CHAR = 0x02;
//! End Of Text character. Last character in encoded stream //! End Of Text character. Last character in encoded stream
static constexpr uint8_t ETX_CHAR = 0x03; static constexpr uint8_t ETX_CHAR = 0x03;
//! Data Link Escape character. Used to escape STX, ETX and DLE occurences //! Data Link Escape character. Used to escape STX, ETX and DLE occurrences
//! in the source stream. //! in the source stream.
static constexpr uint8_t DLE_CHAR = 0x10; static constexpr uint8_t DLE_CHAR = 0x10;
static constexpr uint8_t CARRIAGE_RETURN = 0x0D; static constexpr uint8_t CARRIAGE_RETURN = 0x0D;
@ -47,7 +47,7 @@ public:
* Encodes the give data stream by preceding it with the STX marker * Encodes the give data stream by preceding it with the STX marker
* and ending it with an ETX marker. STX, ETX and DLE characters inside * and ending it with an ETX marker. STX, ETX and DLE characters inside
* the stream are escaped by DLE characters and also replaced by adding * the stream are escaped by DLE characters and also replaced by adding
* 0x40 (which is reverted in the decoing process). * 0x40 (which is reverted in the decoding process).
* @param sourceStream * @param sourceStream
* @param sourceLen * @param sourceLen
* @param destStream * @param destStream

View File

@ -0,0 +1,44 @@
#include "PeriodicOperationDivider.h"
PeriodicOperationDivider::PeriodicOperationDivider(uint32_t divider,
bool resetAutomatically): resetAutomatically(resetAutomatically),
counter(divider), divider(divider) {
}
bool PeriodicOperationDivider::checkAndIncrement() {
bool opNecessary = check();
if(opNecessary) {
if(resetAutomatically) {
counter = 0;
}
return opNecessary;
}
counter ++;
return opNecessary;
}
bool PeriodicOperationDivider::check() {
if(counter >= divider) {
return true;
}
return false;
}
void PeriodicOperationDivider::resetCounter() {
counter = 0;
}
void PeriodicOperationDivider::setDivider(uint32_t newDivider) {
divider = newDivider;
}
uint32_t PeriodicOperationDivider::getCounter() const {
return counter;
}
uint32_t PeriodicOperationDivider::getDivider() const {
return divider;
}

View File

@ -0,0 +1,65 @@
#ifndef FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_
#define FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_
#include <cstdint>
/**
* @brief Lightweight helper class to facilitate periodic operation with
* decreased frequencies.
* @details
* This class is useful to perform operations which have to be performed
* with a reduced frequency, like debugging printouts in high periodic tasks
* or low priority operations.
*/
class PeriodicOperationDivider {
public:
/**
* Initialize with the desired divider and specify whether the internal
* counter will be reset automatically.
* @param divider
* @param resetAutomatically
*/
PeriodicOperationDivider(uint32_t divider, bool resetAutomatically = true);
/**
* Check whether operation is necessary.
* If an operation is necessary and the class has been
* configured to be reset automatically, the counter will be reset.
*
* @return
* -@c true if the counter is larger or equal to the divider
* -@c false otherwise
*/
bool checkAndIncrement();
/**
* Checks whether an operation is necessary.
* This function will not increment the counter!
* @return
* -@c true if the counter is larger or equal to the divider
* -@c false otherwise
*/
bool check();
/**
* Can be used to reset the counter to 0 manually.
*/
void resetCounter();
uint32_t getCounter() const;
/**
* Can be used to set a new divider value.
* @param newDivider
*/
void setDivider(uint32_t newDivider);
uint32_t getDivider() const;
private:
bool resetAutomatically = true;
uint32_t counter = 0;
uint32_t divider = 0;
};
#endif /* FSFW_GLOBALFUNCTIONS_PERIODICOPERATIONDIVIDER_H_ */

View File

@ -1,4 +1,4 @@
#include "../globalfunctions/arrayprinter.h" #include "arrayprinter.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include <bitset> #include <bitset>
@ -27,7 +27,7 @@ void arrayprinter::printHex(const uint8_t *data, size_t size,
if(i < size - 1){ if(i < size - 1){
sif::info << " , "; sif::info << " , ";
if(i > 0 and i % maxCharPerLine == 0) { if(i > 0 and i % maxCharPerLine == 0) {
sif::info << "\r\n" << std::flush; sif::info << std::endl;
} }
} }

View File

@ -1,7 +1,7 @@
#ifndef BINARYMATCHER_H_ #ifndef BINARYMATCHER_H_
#define BINARYMATCHER_H_ #define BINARYMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h" #include "MatcherIF.h"
template<typename T> template<typename T>
class BinaryMatcher: public MatcherIF<T> { class BinaryMatcher: public MatcherIF<T> {

View File

@ -1,7 +1,7 @@
#ifndef DECIMALMATCHER_H_ #ifndef DECIMALMATCHER_H_
#define DECIMALMATCHER_H_ #define DECIMALMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h" #include "MatcherIF.h"
template<typename T> template<typename T>
class DecimalMatcher: public MatcherIF<T> { class DecimalMatcher: public MatcherIF<T> {

View File

@ -2,7 +2,7 @@
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
#include "../../container/BinaryTree.h" #include "../../container/BinaryTree.h"
#include "../../globalfunctions/matching/SerializeableMatcherIF.h" #include "SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h" #include "../../serialize/SerializeAdapter.h"
template<typename T> template<typename T>

View File

@ -1,7 +1,7 @@
#ifndef RANGEMATCHER_H_ #ifndef RANGEMATCHER_H_
#define RANGEMATCHER_H_ #define RANGEMATCHER_H_
#include "../../globalfunctions/matching/SerializeableMatcherIF.h" #include "SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h" #include "../../serialize/SerializeAdapter.h"
template<typename T> template<typename T>

View File

@ -1,7 +1,7 @@
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ #ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ #define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#include "../../globalfunctions/matching/MatcherIF.h" #include "MatcherIF.h"
#include "../../serialize/SerializeIF.h" #include "../../serialize/SerializeIF.h"
template<typename T> template<typename T>

View File

@ -1,5 +1,5 @@
#include "QuaternionOperations.h" #include "QuaternionOperations.h"
#include "../../globalfunctions/math/VectorOperations.h" #include "VectorOperations.h"
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>

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

@ -1,4 +1,4 @@
#include "../health/HealthHelper.h" #include "HealthHelper.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) : HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) :
@ -71,7 +71,7 @@ void HealthHelper::setHealth(HasHealthIF::HealthState health) {
void HealthHelper::informParent(HasHealthIF::HealthState health, void HealthHelper::informParent(HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth) { HasHealthIF::HealthState oldHealth) {
if (parentQueue == MessageQueueMessageIF::NO_QUEUE) { if (parentQueue == MessageQueueIF::NO_QUEUE) {
return; return;
} }
CommandMessage information; CommandMessage information;
@ -86,7 +86,7 @@ void HealthHelper::informParent(HasHealthIF::HealthState health,
void HealthHelper::handleSetHealthCommand(CommandMessage* command) { void HealthHelper::handleSetHealthCommand(CommandMessage* command) {
ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command)); ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command));
if (command->getSender() == MessageQueueMessageIF::NO_QUEUE) { if (command->getSender() == MessageQueueIF::NO_QUEUE) {
return; return;
} }
CommandMessage reply; CommandMessage reply;

View File

@ -1,23 +1,26 @@
#ifndef FRAMEWORK_HEALTH_HEALTHHELPER_H_ #ifndef FSFW_HEALTH_HEALTHHELPER_H_
#define FRAMEWORK_HEALTH_HEALTHHELPER_H_ #define FSFW_HEALTH_HEALTHHELPER_H_
#include "HasHealthIF.h"
#include "HealthMessage.h"
#include "HealthTableIF.h"
#include "../events/EventManagerIF.h" #include "../events/EventManagerIF.h"
#include "../events/EventReportingProxyIF.h" #include "../events/EventReportingProxyIF.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthMessage.h"
#include "../health/HealthTableIF.h"
#include "../ipc/MessageQueueIF.h" #include "../ipc/MessageQueueIF.h"
#include "../objectmanager/ObjectManagerIF.h" #include "../objectmanager/ObjectManagerIF.h"
#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
@ -26,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,7 +58,8 @@ 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);
@ -77,15 +80,18 @@ 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
* could be registered
* -@c RETURN_FAILED else * -@c RETURN_FAILED else
*/ */
ReturnValue_t initialize(MessageQueueId_t parentQueue ); ReturnValue_t initialize(MessageQueueId_t parentQueue );
@ -109,13 +115,17 @@ 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);
}; };
#endif /* HEALTHHELPER_H_ */ #endif /* FSFW_HEALTH_HEALTHHELPER_H_ */

View File

@ -1,4 +1,4 @@
#include "../health/HealthMessage.h" #include "HealthMessage.h"
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command, void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) { HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) {
@ -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,20 +1,26 @@
#ifndef HEALTHMESSAGE_H_ #ifndef FSFW_HEALTH_HEALTHMESSAGE_H_
#define HEALTHMESSAGE_H_ #define FSFW_HEALTH_HEALTHMESSAGE_H_
#include "../health/HasHealthIF.h" #include "HasHealthIF.h"
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
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 "../health/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) {
@ -18,74 +19,64 @@ 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, MutexIF::TimeoutType::WAITING, 20);
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, MutexIF::TimeoutType::WAITING, 20);
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); bool HealthTable::hasHealth(object_id_t object) {
uint32_t size = healthMap.size() * 5 + 2; MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
mutex->unlockMutex(); HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) {
return true;
}
return false;
}
size_t HealthTable::getPrintSize() {
MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
uint32_t size = healthMap.size() * sizeof(object_id_t) +
sizeof(HasHealthIF::HealthState) + sizeof(uint16_t);
return size; return size;
} }
bool HealthTable::hasHealth(object_id_t object) {
bool exits = false;
mutex->lockMutex(MutexIF::BLOCKING);
HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) {
exits = true;
}
mutex->unlockMutex();
return exits;
}
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) { void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
mutex->lockMutex(MutexIF::BLOCKING); MutexHelper(mutex, MutexIF::TimeoutType::WAITING, 20);
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, MutexIF::TimeoutType::WAITING, 20);
if (reset) { if (reset) {
mapIterator = healthMap.begin(); mapIterator = healthMap.begin();
} }
@ -94,7 +85,5 @@ ReturnValue_t HealthTable::iterate(
} }
*value = *mapIterator; *value = *mapIterator;
mapIterator++; mapIterator++;
mutex->unlockMutex();
return result; return result;
} }

View File

@ -1,35 +1,42 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLE_H_ #ifndef FSFW_HEALTH_HEALTHTABLE_H_
#define FRAMEWORK_HEALTH_HEALTHTABLE_H_ #define FSFW_HEALTH_HEALTHTABLE_H_
#include "../health/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();
/** HealthTableIF overrides */
virtual ReturnValue_t registerObject(object_id_t object, virtual ReturnValue_t registerObject(object_id_t object,
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY); HasHealthIF::HealthState initilialState =
HasHealthIF::HEALTHY) override;
virtual size_t getPrintSize() override;
virtual void printAll(uint8_t *pointer, size_t maxSize) override;
virtual bool hasHealth(object_id_t object); /** ManagesHealthIF overrides */
virtual void setHealth(object_id_t object, HasHealthIF::HealthState newState); virtual bool hasHealth(object_id_t object) override;
virtual HasHealthIF::HealthState getHealth(object_id_t); virtual void setHealth(object_id_t object,
HasHealthIF::HealthState newState) override;
virtual uint32_t getPrintSize(); virtual HasHealthIF::HealthState getHealth(object_id_t) override;
virtual void printAll(uint8_t *pointer, size_t maxSize);
protected: protected:
using HealthMap = std::map<object_id_t, HasHealthIF::HealthState>;
using HealthEntry = std::pair<object_id_t, HasHealthIF::HealthState>;
MutexIF* mutex; MutexIF* mutex;
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,28 +1,24 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ #ifndef FSFW_HEALTH_HEALTHTABLEIF_H_
#define FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ #define FSFW_HEALTH_HEALTHTABLEIF_H_
#include "../health/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 {
// TODO: This is in the mission folder and not in the framework folder.
// delete it?
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 /* FRAMEWORK_HEALTH_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 "../health/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_ */

View File

@ -1,9 +1,10 @@
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include "HousekeepingMessage.h" #include "HousekeepingMessage.h"
#include <cstring> #include <cstring>
HousekeepingMessage::~HousekeepingMessage() {} HousekeepingMessage::~HousekeepingMessage() {}
void HousekeepingMessage::setHkReportMessage(CommandMessage* message, sid_t sid, void HousekeepingMessage::setHkReportReply(CommandMessage* message, sid_t sid,
store_address_t storeId) { store_address_t storeId) {
message->setCommand(HK_REPORT); message->setCommand(HK_REPORT);
message->setMessageSize(HK_MESSAGE_SIZE); message->setMessageSize(HK_MESSAGE_SIZE);
@ -11,7 +12,7 @@ void HousekeepingMessage::setHkReportMessage(CommandMessage* message, sid_t sid,
message->setParameter3(storeId.raw); message->setParameter3(storeId.raw);
} }
void HousekeepingMessage::setHkDiagnosticsMessage(CommandMessage* message, void HousekeepingMessage::setHkDiagnosticsReply(CommandMessage* message,
sid_t sid, store_address_t storeId) { sid_t sid, store_address_t storeId) {
message->setCommand(DIAGNOSTICS_REPORT); message->setCommand(DIAGNOSTICS_REPORT);
message->setMessageSize(HK_MESSAGE_SIZE); message->setMessageSize(HK_MESSAGE_SIZE);
@ -19,7 +20,7 @@ void HousekeepingMessage::setHkDiagnosticsMessage(CommandMessage* message,
message->setParameter3(storeId.raw); message->setParameter3(storeId.raw);
} }
sid_t HousekeepingMessage::getHkReportMessage(const CommandMessage *message, sid_t HousekeepingMessage::getHkDataReply(const CommandMessage *message,
store_address_t *storeIdToSet) { store_address_t *storeIdToSet) {
if(storeIdToSet != nullptr) { if(storeIdToSet != nullptr) {
*storeIdToSet = message->getParameter3(); *storeIdToSet = message->getParameter3();
@ -27,6 +28,96 @@ sid_t HousekeepingMessage::getHkReportMessage(const CommandMessage *message,
return getSid(message); return getSid(message);
} }
void HousekeepingMessage::setToggleReportingCommand(CommandMessage *message,
sid_t sid, bool enableReporting, bool isDiagnostics) {
if(isDiagnostics) {
if(enableReporting) {
message->setCommand(ENABLE_PERIODIC_DIAGNOSTICS_GENERATION);
}
else {
message->setCommand(DISABLE_PERIODIC_DIAGNOSTICS_GENERATION);
}
}
else {
if(enableReporting) {
message->setCommand(ENABLE_PERIODIC_HK_REPORT_GENERATION);
}
else {
message->setCommand(DISABLE_PERIODIC_HK_REPORT_GENERATION);
}
}
setSid(message, sid);
}
void HousekeepingMessage::setStructureReportingCommand(CommandMessage *command,
sid_t sid, bool isDiagnostics) {
if(isDiagnostics) {
command->setCommand(REPORT_DIAGNOSTICS_REPORT_STRUCTURES);
}
else {
command->setCommand(REPORT_HK_REPORT_STRUCTURES);
}
setSid(command, sid);
}
void HousekeepingMessage::setOneShotReportCommand(CommandMessage *command,
sid_t sid, bool isDiagnostics) {
if(isDiagnostics) {
command->setCommand(GENERATE_ONE_DIAGNOSTICS_REPORT);
}
else {
command->setCommand(GENERATE_ONE_PARAMETER_REPORT);
}
setSid(command, sid);
}
void HousekeepingMessage::setCollectionIntervalModificationCommand(
CommandMessage *command, sid_t sid, float collectionInterval,
bool isDiagnostics) {
if(isDiagnostics) {
command->setCommand(MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL);
}
else {
command->setCommand(MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL);
}
command->setParameter3(collectionInterval);
setSid(command, sid);
}
sid_t HousekeepingMessage::getCollectionIntervalModificationCommand(
const CommandMessage* command, float* newCollectionInterval) {
if(newCollectionInterval != nullptr) {
*newCollectionInterval = command->getParameter3();
}
return getSid(command);
}
void HousekeepingMessage::setHkRequestSuccessReply(CommandMessage *reply,
sid_t sid) {
setSid(reply, sid);
reply->setCommand(HK_REQUEST_SUCCESS);
}
void HousekeepingMessage::setHkRequestFailureReply(CommandMessage *reply,
sid_t sid, ReturnValue_t error) {
setSid(reply, sid);
reply->setCommand(HK_REQUEST_FAILURE);
reply->setParameter3(error);
}
sid_t HousekeepingMessage::getHkRequestFailureReply(const CommandMessage *reply,
ReturnValue_t *error) {
if(error != nullptr) {
*error = reply->getParameter3();
}
return getSid(reply);
}
sid_t HousekeepingMessage::getSid(const CommandMessage* message) { sid_t HousekeepingMessage::getSid(const CommandMessage* message) {
sid_t sid; sid_t sid;
std::memcpy(&sid.raw, message->getData(), sizeof(sid.raw)); std::memcpy(&sid.raw, message->getData(), sizeof(sid.raw));
@ -37,3 +128,35 @@ void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw)); std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
} }
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply,
sid_t sid, store_address_t storeId) {
reply->setCommand(HK_DEFINITIONS_REPORT);
setSid(reply, sid);
reply->setParameter3(storeId.raw);
}
void HousekeepingMessage::setDiagnosticsStuctureReportReply(
CommandMessage *reply, sid_t sid, store_address_t storeId) {
reply->setCommand(DIAGNOSTICS_DEFINITION_REPORT);
setSid(reply, sid);
reply->setParameter3(storeId.raw);
}
void HousekeepingMessage::clear(CommandMessage* message) {
switch(message->getCommand()) {
case(HK_REPORT):
case(DIAGNOSTICS_REPORT):
case(HK_DEFINITIONS_REPORT):
case(DIAGNOSTICS_DEFINITION_REPORT):
case(UPDATE_SNAPSHOT): {
store_address_t storeId;
getHkDataReply(message, &storeId);
StorageManagerIF *ipcStore = objectManager->get<StorageManagerIF>(
objects::IPC_STORE);
if (ipcStore != nullptr) {
ipcStore->deleteData(storeId);
}
}
}
message->setCommand(CommandMessage::CMD_NONE);
}

View File

@ -1,16 +1,17 @@
#ifndef FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_ #ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#define FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_ #define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../ipc/FwMessageTypes.h" #include "../ipc/FwMessageTypes.h"
#include "../objectmanager/frameworkObjects.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include <limits>
union sid_t { union sid_t {
static constexpr uint64_t INVALID_ADDRESS = static constexpr uint64_t INVALID_SID = -1;
std::numeric_limits<uint64_t>::max(); static constexpr uint32_t INVALID_SET_ID = -1;
sid_t(): raw(INVALID_ADDRESS) {} static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
sid_t(): raw(INVALID_SID) {}
sid_t(object_id_t objectId, uint32_t setId): sid_t(object_id_t objectId, uint32_t setId):
objectId(objectId), objectId(objectId),
@ -31,7 +32,15 @@ union sid_t {
uint64_t raw; uint64_t raw;
bool notSet() const { bool notSet() const {
return raw == INVALID_ADDRESS; return raw == INVALID_SID;
}
bool operator==(const sid_t& other) const {
return raw == other.raw;
}
bool operator!=(const sid_t& other) const {
return not (raw == other.raw);
} }
}; };
@ -49,25 +58,15 @@ public:
sizeof(sid_t) + sizeof(uint32_t); sizeof(sid_t) + sizeof(uint32_t);
/** /**
* The HK message is initialized with a pointer to a message which holds * Concrete instance is not used, instead this class operates on
* the message data, see CommandMessageIF and getInternalMessage(). * command message instances.
* @param message
*/ */
HousekeepingMessage() = delete; HousekeepingMessage() = delete;
virtual ~HousekeepingMessage(); virtual ~HousekeepingMessage();
static constexpr uint8_t MESSAGE_ID = messagetypes::HOUSEKEEPING; static constexpr uint8_t MESSAGE_ID = messagetypes::HOUSEKEEPING;
static constexpr Command_t ADD_HK_REPORT_STRUCT = static constexpr Command_t ENABLE_PERIODIC_HK_REPORT_GENERATION =
MAKE_COMMAND_ID(1);
static constexpr Command_t ADD_DIAGNOSTICS_REPORT_STRUCT =
MAKE_COMMAND_ID(2);
static constexpr Command_t DELETE_HK_REPORT_STRUCT = MAKE_COMMAND_ID(3);
static constexpr Command_t DELETE_DIAGNOSTICS_REPORT_STRUCT =
MAKE_COMMAND_ID(4);
static constexpr Command_t ENABLE_PERIODIC_HK_GENERATION =
MAKE_COMMAND_ID(5); MAKE_COMMAND_ID(5);
static constexpr Command_t DISABLE_PERIODIC_HK_REPORT_GENERATION = static constexpr Command_t DISABLE_PERIODIC_HK_REPORT_GENERATION =
MAKE_COMMAND_ID(6); MAKE_COMMAND_ID(6);
@ -92,31 +91,67 @@ public:
static constexpr Command_t GENERATE_ONE_DIAGNOSTICS_REPORT = static constexpr Command_t GENERATE_ONE_DIAGNOSTICS_REPORT =
MAKE_COMMAND_ID(28); MAKE_COMMAND_ID(28);
static constexpr Command_t APPEND_PARAMETERS_TO_PARAMETER_REPORT_STRUCTURE =
MAKE_COMMAND_ID(29);
static constexpr Command_t APPEND_PARAMETERS_TO_DIAGNOSTICS_REPORT_STRUCTURE =
MAKE_COMMAND_ID(30);
static constexpr Command_t MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL = static constexpr Command_t MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL =
MAKE_COMMAND_ID(31); MAKE_COMMAND_ID(31);
static constexpr Command_t MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL = static constexpr Command_t MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL =
MAKE_COMMAND_ID(32); MAKE_COMMAND_ID(32);
static constexpr Command_t HK_REQUEST_SUCCESS =
MAKE_COMMAND_ID(128);
static constexpr Command_t HK_REQUEST_FAILURE =
MAKE_COMMAND_ID(129);
static constexpr Command_t UPDATE_NOTIFICATION = MAKE_COMMAND_ID(130);
static constexpr Command_t UPDATE_SNAPSHOT = MAKE_COMMAND_ID(131);
static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(132);
static sid_t getSid(const CommandMessage* message); static sid_t getSid(const CommandMessage* message);
static void setHkReportMessage(CommandMessage* message, sid_t sid, /** Setter functions */
static void setToggleReportingCommand(CommandMessage* command, sid_t sid,
bool enableReporting, bool isDiagnostics);
static void setStructureReportingCommand(CommandMessage* command, sid_t sid,
bool isDiagnostics);
static void setOneShotReportCommand(CommandMessage* command, sid_t sid,
bool isDiagnostics);
static void setCollectionIntervalModificationCommand(
CommandMessage* command, sid_t sid, float collectionInterval,
bool isDiagnostics);
static void setHkReportReply(CommandMessage* reply, sid_t sid,
store_address_t storeId); store_address_t storeId);
static void setHkDiagnosticsMessage(CommandMessage* message, sid_t sid, static void setHkDiagnosticsReply(CommandMessage* reply, sid_t sid,
store_address_t storeId); store_address_t storeId);
//! Get the respective SID and store ID. Command ID can be used beforehand static void setHkRequestSuccessReply(CommandMessage* reply, sid_t sid);
//! to distinguish between diagnostics and regular HK packets static void setHkRequestFailureReply(CommandMessage* reply, sid_t sid,
static sid_t getHkReportMessage(const CommandMessage* message, ReturnValue_t error);
static void setHkStuctureReportReply(CommandMessage* reply,
sid_t sid, store_address_t storeId);
static void setDiagnosticsStuctureReportReply(CommandMessage* reply,
sid_t sid, store_address_t storeId);
static sid_t getHkRequestFailureReply(const CommandMessage* reply,
ReturnValue_t* error);
/**
* @brief Generic getter function for housekeeping data replies
* @details
* Command ID can be used beforehand to distinguish between diagnostics and
* regular HK packets. This getter function should be used for the
* command IDs 10, 12, 25 and 26.
*/
static sid_t getHkDataReply(const CommandMessage* message,
store_address_t * storeIdToSet); store_address_t * storeIdToSet);
static sid_t getCollectionIntervalModificationCommand(
const CommandMessage* command, float* newCollectionInterval);
static void clear(CommandMessage* message);
private: private:
static void setSid(CommandMessage* message, sid_t sid); static void setSid(CommandMessage* message, sid_t sid);
}; };
#endif /* FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_ */ #endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ */

View File

@ -1,8 +1,7 @@
#ifndef FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ #ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#define FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ #define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#include "../datapoollocal/LocalPoolDataSetBase.h" #include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../serialize/SerialLinkedListAdapter.h" #include "../serialize/SerialLinkedListAdapter.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
@ -15,67 +14,21 @@
*/ */
class HousekeepingPacketDownlink: public SerialLinkedListAdapter<SerializeIF> { class HousekeepingPacketDownlink: public SerialLinkedListAdapter<SerializeIF> {
public: public:
HousekeepingPacketDownlink(sid_t sid, float collectionInterval, uint8_t HousekeepingPacketDownlink(sid_t sid, LocalPoolDataSetBase* dataSetPtr):
numberOfParameters, LocalPoolDataSetBase* dataSetPtr): sourceId(sid.objectId), setId(sid.ownerSetId), hkData(dataSetPtr) {
sourceId(sid.objectId), setId(sid.ownerSetId),
collectionInterval(collectionInterval),
numberOfParameters(numberOfParameters), hkData(dataSetPtr) {
setLinks(); setLinks();
} }
/**
* Helper functions which can be used to move HK data from the IPC store
* to the telemetry store. TODO: maybe not needed.
* @param formerStore
* @param storeId
* @param newStore
* @param newStoreId [out]
* @return
*/
virtual ReturnValue_t moveToOtherStore(StorageManagerIF* formerStore,
store_address_t storeId, StorageManagerIF* newStore,
store_address_t* newStoreId) {
const uint8_t* dataPtr = nullptr;
size_t hkDataSize = 0;
ReturnValue_t result = formerStore->getData(storeId, &dataPtr,
&hkDataSize);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return newStore->addData(newStoreId, dataPtr, hkDataSize);
}
private: private:
void setLinks() { void setLinks() {
setStart(&sourceId); setStart(&sourceId);
sourceId.setNext(&setId); sourceId.setNext(&setId);
setId.setNext(&collectionInterval); setId.setNext(&hkData);
collectionInterval.setNext(&numberOfParameters);
numberOfParameters.setNext(&hkData);
} }
SerializeElement<object_id_t> sourceId; SerializeElement<object_id_t> sourceId;
SerializeElement<uint32_t> setId; SerializeElement<uint32_t> setId;
SerializeElement<float> collectionInterval;
SerializeElement<uint8_t> numberOfParameters;
LinkedElement<SerializeIF> hkData; LinkedElement<SerializeIF> hkData;
}; };
#endif /* FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ */ #endif /* FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ */
// virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
// size_t maxSize, Endianness streamEndianness) const override {
// ReturnValue_t result = SerialLinkedListAdapter::serialize(buffer, size,
// maxSize, streamEndianness);
// if(result != HasReturnvaluesIF::RETURN_OK) {
// return result;
// }
// return dataSetPtr->serialize(buffer, size, maxSize, streamEndianness);
// }
//
// virtual size_t getSerializedSize() const override {
//
// }

Some files were not shown because too many files have changed in this diff Show More