1
0
forked from fsfw/fsfw

Merge branch 'mueller/master' into mueller/DHB_separating_steps

This commit is contained in:
2020-10-12 17:44:58 +02:00
275 changed files with 4916 additions and 3313 deletions
action
container
controller
datapool
datapoolglob
datapoollocal
devicehandlers
events
fdir
fsfw.mk
globalfunctions
health
housekeeping
internalError
ipc
memory
modes
monitoring
objectmanager
osal
power
pus
returnvalues
serialize
serviceinterface
storagemanager
subsystem
tasks
tcdistribution
timemanager
tmtcpacket/pus
tmtcservices

@ -1,9 +1,11 @@
#include "ActionHelper.h"
#include "HasActionsIF.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../objectmanager/ObjectManagerIF.h"
ActionHelper::ActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue) :
owner(setOwner), queueToUse(useThisQueue), ipcStore(nullptr) {
ActionHelper::ActionHelper(HasActionsIF* setOwner,
MessageQueueIF* useThisQueue) :
owner(setOwner), queueToUse(useThisQueue) {
}
ActionHelper::~ActionHelper() {
@ -32,13 +34,15 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
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;
ActionMessage::setStepReply(&reply, commandId, step + STEP_OFFSET, result);
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;
ActionMessage::setCompletionReply(&reply, commandId, result);
queueToUse->sendMessage(reportTo, &reply);
@ -48,8 +52,8 @@ void ActionHelper::setQueueToUse(MessageQueueIF* queue) {
queueToUse = queue;
}
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy,
ActionId_t actionId, store_address_t dataAddress) {
const uint8_t* dataPtr = NULL;
size_t size = 0;
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
@ -85,22 +89,28 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
if (result != HasReturnvaluesIF::RETURN_OK) {
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) {
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.
// 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
if (hideSender){
// 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 {
}
else {
result = queueToUse->sendMessage(reportTo, &reply);
}
if ( result != HasReturnvaluesIF::RETURN_OK){
if (result != HasReturnvaluesIF::RETURN_OK){
ipcStore->deleteData(storeAddress);
}
return result;
@ -108,3 +118,39 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo,
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;
}

@ -1,15 +1,18 @@
#ifndef ACTIONHELPER_H_
#define ACTIONHELPER_H_
#ifndef FSFW_ACTION_ACTIONHELPER_H_
#define FSFW_ACTION_ACTIONHELPER_H_
#include "ActionMessage.h"
#include "../serialize/SerializeIF.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.
* 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 it needs a valid messageQueueIF pointer!
* Components which use the HasActionIF this helper can be used to handle
* the action messages.
* 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;
@ -18,7 +21,8 @@ public:
/**
* Constructor of the action helper
* @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);
@ -26,28 +30,35 @@ public:
/**
* 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 invalid or the callback fails a message reply will be send to the sender of the message automatically.
* If the message is a valid action message the helper will use the
* 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
* @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);
/**
* Helper initialize function. Must be called before use of any other helper function
* @param queueToUse_ Pointer to the messageQueue to be used, optional if queue was set in constructor
* Helper initialize function. Must be called before use of any other
* helper function
* @param queueToUse_ Pointer to the messageQueue to be used, optional
* if queue was set in constructor
* @return Returns RETURN_OK if successful
*/
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 reportTo The messageQueueId to report the step message to
* @param commandId ID of the executed command
* @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
*
@ -55,39 +66,59 @@ public:
* @param commandId ID of the executed command
* @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
*
* @param reportTo MessageQueueId_t to report the action completion message to
* 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 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, SerializeIF* data, bool hideSender = false);
ReturnValue_t reportData(MessageQueueId_t reportTo, ActionId_t replyId,
SerializeIF* data, bool hideSender = false);
/**
* Function to be called by the owner if an action does report data.
* 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.
* 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
*/
void setQueueToUse(MessageQueueIF *queue);
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
MessageQueueIF* queueToUse;//!< Queue to be used as response sender, has to be set with
StorageManagerIF* ipcStore;//!< Pointer to an IPC Store, initialized during construction or initialize(MessageQueueIF* queueToUse_) or with setQueueToUse(MessageQueueIF *queue)
//! Queue to be used as response sender, has to be set in ctor or with
//! 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 actionId ID of action to be done
* @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();
};
#endif /* ACTIONHELPER_H_ */
#endif /* FSFW_ACTION_ACTIONHELPER_H_ */

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

@ -1,5 +1,5 @@
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_
#ifndef FSFW_CONTAINER_ARRAYLIST_H_
#define FSFW_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h"
@ -20,11 +20,35 @@ public:
static const uint8_t INTERFACE_ID = CLASS_ID::ARRAY_LIST;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(0x01);
/**
* Copying is forbiden by declaring copy ctor and copy assignment deleted
* It is too ambigous in this case.
* (Allocate a new backend? Use the same? What to do in an modifying call?)
*/
/**
* 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
* It is too ambigous in this case.
* (Allocate a new backend? Use the same? What to do in an modifying call?)
*/
ArrayList(const ArrayList& other) = delete;
const ArrayList& operator=(const ArrayList& other) = delete;
@ -33,30 +57,6 @@ public:
*/
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.
@ -67,77 +67,81 @@ public:
}
}
/**
* An Iterator to go trough an ArrayList
*
* It stores a pointer to an element and increments the
* pointer when incremented itself.
*/
class Iterator {
public:
/**
* Empty ctor, points to NULL
*/
Iterator(): value(0) {}
/**
* An Iterator to go trough an ArrayList
*
* It stores a pointer to an element and increments the
* pointer when incremented itself.
*/
class Iterator {
public:
/**
* Empty ctor, points to NULL
*/
Iterator(): value(0) {}
/**
* Initializes the Iterator to point to an element
*
* @param initialize
*/
Iterator(T *initialize) {
value = initialize;
}
/**
* Initializes the Iterator to point to an element
*
* @param initialize
*/
Iterator(T *initialize) {
value = initialize;
}
/**
* The current element the iterator points to
*/
T *value;
/**
* The current element the iterator points to
*/
T *value;
Iterator& operator++() {
value++;
return *this;
}
Iterator& operator++() {
value++;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
T operator*() {
return *value;
}
T& operator*() {
return *value;
}
T *operator->() {
return value;
}
const T& operator*() const {
return *value;
}
const T *operator->() const{
return value;
}
T *operator->() {
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);
}
const T *operator->() const {
return 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
@ -192,7 +196,7 @@ public:
*
* @return maximum number of elements
*/
uint32_t maxSize() const {
size_t maxSize() const {
return this->maxSize_;
}
@ -236,7 +240,7 @@ protected:
/**
* remembering the maximum size
*/
uint32_t maxSize_;
size_t maxSize_;
/**
* true if the array was allocated and needs to be deleted in the destructor.
@ -244,4 +248,6 @@ protected:
bool allocated;
};
#endif /* ARRAYLIST_H_ */
#endif /* FSFW_CONTAINER_ARRAYLIST_H_ */

@ -27,14 +27,27 @@ public:
/**
* @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),
fifoVector(other.maxCapacity) {
this->fifoVector = other.fifoVector;
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:
std::vector<T> fifoVector;
};

@ -25,9 +25,21 @@ public:
* @param other
*/
FIFO(const FIFO& other): FIFOBase<T>(other) {
this->fifoArray = other.fifoArray;
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:
std::array<T, capacity> fifoArray;
};

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

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

@ -1,51 +1,32 @@
#ifndef 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> {
static_assert(MAX_SIZE <= (pow(2,sizeof(count_t)*8)-1), "count_t is not large enough to hold MAX_SIZE");
private:
T data[MAX_SIZE];
public:
/**
* (Robin) Maybe we should also implement move assignment and move ctor.
* Or at least delete them.
*/
FixedArrayList() :
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) :
ArrayList<T, count_t>(data, MAX_SIZE) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
}
FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
this->size = other.size;
return *this;
}

@ -1,19 +1,27 @@
#ifndef FIXEDMAP_H_
#define FIXEDMAP_H_
#ifndef FSFW_CONTAINER_FIXEDMAP_H_
#define FSFW_CONTAINER_FIXEDMAP_H_
#include "../container/ArrayList.h"
#include "ArrayList.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <utility>
#include <type_traits>
/**
* @brief Map implementation for maps with a pre-defined size.
* @details Can be initialized with desired maximum size.
* Iterator is used to access <key,value> pair and
* iterate through map entries. Complexity O(n).
* @brief Map implementation for maps with a pre-defined size.
* @details
* Can be initialized with desired maximum size.
* 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
*/
template<typename key_t, typename T>
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:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
@ -51,28 +59,17 @@ public:
Iterator(std::pair<key_t, T> *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 {
return Iterator(&theMap[0]);
@ -86,16 +83,16 @@ public:
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) {
return FixedMap::KEY_ALREADY_EXISTS;
return KEY_ALREADY_EXISTS;
}
if (_size == theMap.maxSize()) {
return FixedMap::MAP_FULL;
return MAP_FULL;
}
theMap[_size].first = key;
theMap[_size].second = value;
if (storedValue != NULL) {
if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[_size]);
}
++_size;
@ -156,6 +153,24 @@ public:
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() {
_size = 0;
}
@ -164,16 +179,6 @@ public:
return theMap.maxSize();
}
bool full() {
if(_size == theMap.maxSize()) {
return true;
}
else {
return false;
}
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&this->_size,
@ -222,4 +227,4 @@ public:
};
#endif /* FIXEDMAP_H_ */
#endif /* FSFW_CONTAINER_FIXEDMAP_H_ */

@ -1,171 +1,206 @@
#ifndef FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#ifndef FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#define FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_
#include "../container/ArrayList.h"
#include "ArrayList.h"
#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
* Performs no dynamic memory allocation except on initialization.
* Uses an ArrayList as the underlying container and thus has a linear
* Same keys are ordered by KEY_COMPARE function which is std::less<key_t> > by default.
*
* 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
* should not be an issue.
* 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).
* @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>>
class FixedOrderedMultimap {
public:
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(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x02);
/***
* Constructor which needs a size_t for the maximum allowed size
*
* Can not be resized during runtime
*
* Allocates memory at construction
* @param maxSize size_t of Maximum allowed size
*/
FixedOrderedMultimap(size_t maxSize):theMap(maxSize), _size(0){
}
/***
* Virtual destructor frees Memory by deleting its member
*/
virtual ~FixedOrderedMultimap() {
}
/***
* Special iterator for FixedOrderedMultimap
*/
class Iterator: public ArrayList<std::pair<key_t, T>, size_t>::Iterator {
public:
Iterator() :
ArrayList<std::pair<key_t, T>, size_t>::Iterator() {
}
Iterator(std::pair<key_t, T> *pair) :
ArrayList<std::pair<key_t, T>, size_t>::Iterator(pair) {
}
};
/***
* Returns an iterator pointing to the first element
* @return Iterator pointing to first element
*/
Iterator begin() const {
return Iterator(&theMap[0]);
}
/**
* Initializes the ordered multimap with a fixed maximum size.
* @param maxSize
* Returns an iterator pointing to one element past the end
* @return Iterator pointing to one element past the end
*/
FixedOrderedMultimap(size_t maxSize);
Iterator end() const {
return Iterator(&theMap[_size]);
}
virtual ~FixedOrderedMultimap() {}
/***
* Returns the current size of the map (not maximum size!)
* @return Current size
*/
size_t size() const{
return _size;
}
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
public:
/** Returns an iterator to nullptr */
Iterator();
/** Initializes iterator to given entry */
Iterator(std::pair<key_t, T> *pair);
/** Dereference operator can be used to get value */
T operator*();
/** Arrow operator can be used to get pointer to value */
T *operator->();
};
/**
* Clears the map, does not deallocate any memory
*/
void clear(){
_size = 0;
}
/** Iterator to start of map */
Iterator begin() const;
/** Iterator to end of map */
Iterator end() const;
/** Current (variable) size of the map */
size_t size() const;
/**
* Returns the maximum size of the map
* @return Maximum size of the map
*/
size_t maxSize() const{
return theMap.maxSize();
}
/**
* Insert a key/value pair inside the map. An iterator to the stored
* value might be returned optionally.
* @param key
* @param value
* @param storedValue
* @return
*/
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = nullptr);
/**
* Insert a given std::pair<key, value>
* @param pair
* @return
*/
ReturnValue_t insert(std::pair<key_t, T> pair);
/**
* Checks existence of key in map.
* @param key
* @return
* - @c KEY_DOES_NOT_EXIST if key does not exists.
* - @c RETURN_OK otherwise.
*/
ReturnValue_t exists(key_t key) const;
/***
* 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 erase(Iterator *iter) {
uint32_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;
}
/***
* Used to insert new pair instead of single values
*
* @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 erase(key_t key) {
uint32_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;
}
/***
* Can be used to check if a certain key is in the map
* @param key Key to be checked
* @return RETURN_OK if the key exists KEY_DOES_NOT_EXIST otherwise
*/
ReturnValue_t exists(key_t key) const;
Iterator find(key_t key) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return end();
}
return Iterator(&theMap[findFirstIndex(key)]);
}
/***
* Used to delete the element in the iterator
*
* The iterator will point to the element before or begin(),
* but never to one element in front of the map.
*
* @warning The iterator needs to be valid and dereferenceable
* @param[in/out] iter Pointer to iterator to the element that needs to be ereased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/
ReturnValue_t erase(Iterator *iter);
ReturnValue_t 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;
}
/***
* Used to erase by key
* @param key Key to be erased
* @return RETURN_OK if erased, KEY_DOES_NOT_EXIST if the there is no element like this
*/
ReturnValue_t erase(key_t key);
void clear() {
_size = 0;
}
/***
* 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{
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return end();
}
return Iterator(&theMap[findFirstIndex(key)]);
};
size_t maxSize() const {
return theMap.maxSize();
}
/***
* 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);
}
friend bool operator!=(const typename FixedOrderedMultimap::Iterator& lhs,
const typename FixedOrderedMultimap::Iterator& rhs) {
return not (lhs.value == rhs.value);
}
private:
typedef KEY_COMPARE compare;
compare myComp;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
ArrayList<std::pair<key_t, T>, size_t> theMap;
size_t _size;
uint32_t findFirstIndex(key_t key, uint32_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;
}
size_t findFirstIndex(key_t key, size_t startAt = 0) const;
uint32_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;
}
size_t findNicePlace(key_t key) const;
void removeFromPosition(uint32_t position) {
if (_size <= position) {
return;
}
memmove(&theMap[position], &theMap[position + 1],
(_size - position - 1) * sizeof(std::pair<key_t,T>));
--_size;
}
void removeFromPosition(size_t position);
};
#include "FixedOrderedMultimap.tpp"
#endif /* FRAMEWORK_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */
#endif /* FSFW_CONTAINER_FIXEDORDEREDMULTIMAP_H_ */

@ -1,83 +1,109 @@
#ifndef 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>
inline FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::Iterator(
std::pair<key_t, T> *pair):
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator(pair){}
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(key_t key, T value, Iterator *storedValue) {
if (_size == theMap.maxSize()) {
return MAP_FULL;
}
size_t position = findNicePlace(key);
memmove(static_cast<void*>(&theMap[position + 1]),static_cast<void*>(&theMap[position]),
(_size - position) * sizeof(std::pair<key_t,T>));
theMap[position].first = key;
theMap[position].second = value;
++_size;
if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[position]);
}
return HasReturnvaluesIF::RETURN_OK;
}
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;
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.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]);
inline ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
}
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;
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 T* FixedOrderedMultimap<key_t, T, KEY_COMPARE>::Iterator::operator->() {
return &ArrayList<std::pair<key_t, T>, uint32_t>::Iterator::value->second;
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 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()) {
return MAP_FULL;
}
uint32_t position = findNicePlace(key);
// Compiler might emitt warning because std::pair is not a POD type (yet..)
// 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>));
theMap[position].first = key;
theMap[position].second = value;
++_size;
if (storedValue != nullptr) {
*storedValue = Iterator(&theMap[position]);
}
return HasReturnvaluesIF::RETURN_OK;
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 ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::insert(
std::pair<key_t, T> pair) {
return insert(pair.fist, pair.second);
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 ReturnValue_t FixedOrderedMultimap<key_t, T, KEY_COMPARE>::exists(
key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findFirstIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
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_ */

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

@ -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_ */

@ -3,26 +3,62 @@
#include "../storagemanager/StorageManagerIF.h"
#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 {
public:
PlacementFactory(StorageManagerIF* 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>
T* generate(Args&&... args) {
store_address_t tempId;
uint8_t* pData = NULL;
uint8_t* pData = nullptr;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData);
if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL;
return nullptr;
}
T* temp = new (pData) T(std::forward<Args>(args)...);
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>
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).
thisElement->~T();
uint8_t* pointer = (uint8_t*) (thisElement);

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

@ -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;
}
}

@ -1,4 +1,4 @@
#include "../container/SharedRingBuffer.h"
#include "SharedRingBuffer.h"
#include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h"
@ -9,6 +9,7 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
mutex = MutexFactory::instance()->createMutex();
}
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
const size_t size, bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(buffer, size, overwriteOld,
@ -16,6 +17,11 @@ SharedRingBuffer::SharedRingBuffer(object_id_t objectId, uint8_t *buffer,
mutex = MutexFactory::instance()->createMutex();
}
void SharedRingBuffer::setToUseReceiveSizeFIFO(uint32_t fifoDepth) {
this->fifoDepth = fifoDepth;
}
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
return mutex->lockMutex(timeoutType, timeout);
@ -25,6 +31,25 @@ ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
return mutex->unlockMutex();
}
MutexIF* SharedRingBuffer::getMutexHandle() const {
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;
}

@ -1,7 +1,8 @@
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#ifndef FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#define FSFW_CONTAINER_SHAREDRINGBUFFER_H_
#include "../container/SimpleRingBuffer.h"
#include "SimpleRingBuffer.h"
#include "DynamicFIFO.h"
#include "../ipc/MutexIF.h"
#include "../objectmanager/SystemObject.h"
#include "../timemanager/Clock.h"
@ -26,6 +27,8 @@ public:
SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
void setToUseReceiveSizeFIFO(uint32_t fifoDepth);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
@ -59,10 +62,23 @@ public:
* @return
*/
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:
MutexIF* mutex = nullptr;
size_t fifoDepth = 0;
DynamicFIFO<size_t>* receiveSizesFIFO = nullptr;
};
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */
#endif /* FSFW_CONTAINER_SHAREDRINGBUFFER_H_ */

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

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

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

@ -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;
}

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

@ -7,12 +7,14 @@
#include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../datapool/HkSwitchHelper.h"
/**
* @brief Generic base class for controller classes
* @brief Generic base class for controller classes
* @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,
public HasHealthIF,
@ -26,24 +28,18 @@ public:
size_t commandQueueDepth = 3);
virtual ~ControllerBase();
/** SystemObject override */
virtual ReturnValue_t initialize() 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 HasHealthIF::HealthState getHealth() override;
/**
* Implementation of ExecutableObjectIF function
*
* 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;
/** ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual void setTaskIF(PeriodicTaskIF* task) override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
@ -56,6 +52,9 @@ protected:
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
/**
* Periodic helper, implemented by child class.
*/
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
@ -73,6 +72,7 @@ protected:
HealthHelper healthHelper;
// Is this still needed?
HkSwitchHelper hkSwitcher;
/**
@ -81,13 +81,16 @@ protected:
*/
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 startTransition(Mode_t mode, Submode_t submode);
virtual void getMode(Mode_t *mode, Submode_t *submode);
virtual void setToExternalControl();
virtual void announceMode(bool recursive);
/** HK helpers */
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
};

@ -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;
}

@ -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_ */

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

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

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

@ -1,7 +1,12 @@
#ifndef FRAMEWORK_DATAPOOL_POOLDATASETIF_H_
#define FRAMEWORK_DATAPOOL_POOLDATASETIF_H_
#ifndef FSFW_DATAPOOL_POOLDATASETIF_H_
#define FSFW_DATAPOOL_POOLDATASETIF_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 {
public:
virtual~ PoolDataSetIF() {};
@ -25,4 +30,4 @@ public:
virtual bool isValid() const = 0;
};
#endif /* FRAMEWORK_DATAPOOL_POOLDATASETIF_H_ */
#endif /* FSFW_DATAPOOL_POOLDATASETIF_H_ */

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

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

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

@ -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;
}

@ -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_ */

@ -1,5 +1,5 @@
#ifndef POOLVARLIST_H_
#define POOLVARLIST_H_
#ifndef FSFW_DATAPOOL_POOLVARLIST_H_
#define FSFW_DATAPOOL_POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h"
@ -8,7 +8,8 @@ class PoolVarList {
private:
GlobPoolVar<T> variables[n_var];
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.
if (dataSet == NULL) {
return;
@ -25,4 +26,4 @@ public:
#endif /* POOLVARLIST_H_ */
#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */

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

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

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

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

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

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

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

@ -1,12 +1,15 @@
#ifndef FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_
#define FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#include "../datapool/PoolEntryIF.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../housekeeping/HousekeepingMessage.h"
#include <map>
class LocalDataPoolManager;
class DataSetIF;
class LocalPoolDataSetBase;
/**
* @brief Type definition for local pool entries.
*/
@ -61,11 +64,11 @@ public:
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
/**
* Returns the minimum sampling frequency, which will usually be the
* period the pool owner performs its periodic operation-
* Returns the minimum sampling frequency in milliseconds, which will
* usually be the period the pool owner performs its periodic operation.
* @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
@ -73,7 +76,7 @@ public:
* @param sid Corresponding structure ID
* @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
* by the housekeeping message interface */
@ -84,9 +87,9 @@ public:
return HasReturnvaluesIF::RETURN_FAILED;
};
virtual ReturnValue_t changeCollectionInterval(sid_t sid,
dur_seconds_t newInterval) {
float newIntervalSeconds) {
return HasReturnvaluesIF::RETURN_FAILED;
};
};
#endif /* FRAMEWORK_DATAPOOL_HASHKPOOLPARAMETERSIF_H_ */
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */

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

@ -1,14 +1,15 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#include "HasLocalDataPoolIF.h"
#include "../housekeeping/HousekeepingPacketDownlink.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../ipc/MutexIF.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../datapool/PoolEntry.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../ipc/CommandMessage.h"
#include "../ipc/MessageQueueIF.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
* 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
@ -37,7 +38,7 @@ class LocalDataSetBase;
* value is stored. The helper classes offer a read() and commit() interface
* through the PoolVariableIF which is used to read and update values.
* Each pool entry has a valid state too.
* @author R. Mueller
* @author R. Mueller
*/
class LocalDataPoolManager {
template<typename T>
@ -49,10 +50,14 @@ class LocalDataPoolManager {
public:
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_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1);
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
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
@ -69,16 +74,30 @@ public:
virtual~ LocalDataPoolManager();
/**
* Initializes the map by calling the map initialization function of the
* owner and assigns the queue to use.
* Assigns the queue to use.
* @param queueToUse
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
* @return
*/
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);
/**
* 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
*/
@ -97,12 +116,6 @@ public:
*/
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.
@ -110,9 +123,8 @@ public:
* @return
*/
ReturnValue_t generateHousekeepingPacket(sid_t sid,
float collectionInterval = 0,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t generateSetStructurePacket(sid_t sid);
LocalPoolDataSetBase* dataSet, bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
@ -124,26 +136,27 @@ public:
*/
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
const HasLocalDataPoolIF* getOwner() const;
HasLocalDataPoolIF* getOwner();
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
/**
* 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.
* 2. UPDATED: Notification will be sent out if HK data has changed.
* Question: Send Raw data directly or just the message?
* 3. REQUESTED: HK packets are only generated if explicitely requested.
* 2. UPDATE_NOTIFICATION:
* Notification will be sent out if HK data has changed.
* 3. UPDATE_SNAPSHOT:
* HK packets are only generated if explicitely requested.
* Propably not necessary, just use multiple local data sets or
* shared datasets.
*
* Notifications should also be possible for single variables instead of
* full dataset updates.
*/
enum class ReportingType: uint8_t {
//! Periodic generation of HK packets.
PERIODIC,
//! Housekeeping packet will be generated if values have changed.
UPDATE_HK,
//! Update notification will be sent out as message.
UPDATE_NOTIFICATION,
//! Notification will be sent out as message and a snapshot of the
@ -151,6 +164,17 @@ public:
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 */
LocalDataPoolManager(const LocalDataPoolManager &) = delete;
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
@ -160,51 +184,37 @@ private:
//! Every housekeeping data manager has a mutex to protect access
//! to it's data pool.
MutexIF* mutex = nullptr;
/** The class which actually owns the manager (and its datapool). */
HasLocalDataPoolIF* owner = nullptr;
uint8_t nonDiagnosticIntervalFactor = 0;
dur_millis_t regularMinimumInterval = 0;
dur_millis_t diagnosticMinimumInterval = 0;
/** Default receiver for periodic HK packets */
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. */
struct HkReceiver {
/** Different member of this union will be used depending on the
type of data the receiver is interested in (full datasets or
single data variables. */
/** Object ID of receiver */
object_id_t objectId = objects::NO_OBJECT;
DataType dataType = DataType::DATA_SET;
union DataId {
DataId(): dataSetSid() {}
/** Will be initialized to INVALID_ADDRESS */
sid_t dataSetSid;
lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID;
DataId(): sid() {};
sid_t sid;
lp_id_t localPoolId;
};
DataId dataId;
ReportingType reportingType = ReportingType::PERIODIC;
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 */
using HkReceiversMap = std::multimap<object_id_t, struct HkReceiver>;
/** This vector will contain the list of HK receivers. */
using HkReceivers = std::vector<struct HkReceiver>;
HkReceiversMap hkReceiversMap;
HkReceivers hkReceiversMap;
/** This is the map holding the actual data. Should only be initialized
* once ! */
@ -245,17 +255,16 @@ private:
template <class T> ReturnValue_t fetchPoolEntry(lp_id_t localPoolId,
PoolEntry<T> **poolEntry);
void setMinimalSamplingFrequency(float frequencySeconds);
ReturnValue_t serializeHkPacketIntoStore(
HousekeepingPacketDownlink& hkPacket,
store_address_t *storeId);
store_address_t& storeId, bool forDownlink, size_t* serializedSize);
uint32_t intervalSecondsToInterval(bool isDiagnostics,
float collectionIntervalSeconds);
float intervalToIntervalSeconds(bool isDiagnostics,
uint32_t collectionInterval);
void performPeriodicHkGeneration(HkReceiver* hkReceiver);
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics);
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_ */

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

@ -1,5 +1,6 @@
#include "LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../serialize/SerializeAdapter.h"
#include <cmath>
@ -7,16 +8,22 @@
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
uint32_t setId, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
<< std::endl;
return;
}
const size_t maxNumberOfVariables, bool noPeriodicHandling):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
if(hkOwner == nullptr) {
// Configuration error.
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
this->sid.objectId = hkOwner->getObjectId();
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,
@ -26,8 +33,9 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
sid.objectId);
if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
<< std::endl;
// Configuration error.
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
@ -111,8 +119,14 @@ ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
}
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
size_t* size, size_t maxSize,SerializeIF::Endianness streamEndianness,
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++) {
lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId();
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 {
if(withValidityBuffer) {
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;
}
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,
uint8_t position) const {
if(position > 7) {
@ -190,4 +249,11 @@ bool LocalPoolDataSetBase::isValid() const {
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;
}

@ -1,27 +1,36 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#include "HasLocalDataPoolIF.h"
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolDataSetBase.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../serialize/SerializeIF.h"
#include <vector>
class LocalDataPoolManager;
class PeriodicHousekeepingHelper;
/**
* @brief The LocalDataSet class manages a set of locally checked out
* variables for local data pools
* @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)
* 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
* 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,
* to ensure thread-safety.
* the commit call. The data set manages locking and freeing the local data
* 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
* 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.
*
* If pool variables are writable and not committed until destruction
@ -31,17 +40,21 @@ class LocalDataPoolManager;
* @ingroup data_pool
*/
class LocalPoolDataSetBase: public PoolDataSetBase {
friend class LocalDataPoolManager;
friend class PeriodicHousekeepingHelper;
public:
/**
* @brief Constructor for the creator of local pool data.
* @details
* This constructor also initializes the components required for
* periodic handling.
*/
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
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
* owner should implement the HasHkPoolParametersIF.
* @brief Constructor for users of local pool data.
* @details
* @param sid Unique identifier of dataset consisting of object ID and
* set ID.
@ -63,6 +76,9 @@ public:
void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const;
/** SerializeIF overrides */
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size,
@ -73,7 +89,7 @@ public:
* Special version of the serilization function which appends a
* validity buffer at the end. Each bit of this validity buffer
* 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 size
* @param maxSize
@ -88,18 +104,58 @@ public:
size_t *size, SerializeIF::Endianness streamEndianness);
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer,
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;
void setChanged(bool changed);
bool isChanged() const;
protected:
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
* data set we can use this flag.
*/
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;
/**
@ -125,9 +181,10 @@ protected:
*/
void bitSetter(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_ */

@ -1,12 +1,12 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#include "HasLocalDataPoolIF.h"
#include "LocalDataPoolManager.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapool/DataSetIF.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerializeAdapter.h"
/**
@ -38,13 +38,13 @@ public:
* @param poolId ID of the local pool entry.
* @param hkOwner Pointer of the owner. This will generally be the calling
* 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.
* 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,
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
@ -58,13 +58,14 @@ public:
* the pool variable in that dataset directly.
* @param poolId ID of the local pool entry.
* @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.
* 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,
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() {};
@ -173,4 +174,4 @@ using lp_float_t = LocalPoolVar<float>;
using lp_double_t = LocalPoolVar<double>;
#endif
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ */

@ -1,44 +1,45 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#ifndef FSFW_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!
#endif
template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId,
HasLocalDataPoolIF* hkOwner, pool_rwm_t setReadWriteMode,
DataSetIF* dataSet):
localPoolId(poolId),readWriteMode(setReadWriteMode) {
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode):
localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the "
"NO_PARAMETER value!" << std::endl;
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
<< "which is the NO_PARAMETER value!" << std::endl;
}
if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner is a nullptr!"
<< std::endl;
sif::error << "LocalPoolVar<T>::LocalPoolVar: The supplied pool "
<< "owner is a invalid!" << std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
if(dataSet != nullptr) {
dataSet->registerVariable(this);
dataSet->registerVariable(this);
}
}
template<typename T>
inline LocalPoolVar<T>::LocalPoolVar(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode, DataSetIF *dataSet):
readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVector: 0 passed as pool ID, which is the "
"NO_PARAMETER value!" << std::endl;
}
HasLocalDataPoolIF* hkOwner =
objectManager->get<HasLocalDataPoolIF>(poolOwner);
if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner did not implement"
"the correct interface HasHkPoolParametersIF!" << std::endl;
return;
DataSetIF *dataSet, pool_rwm_t setReadWriteMode):
localPoolId(poolId), readWriteMode(setReadWriteMode) {
if(poolId == PoolVariableIF::NO_PARAMETER) {
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
<< "which is the NO_PARAMETER value!" << std::endl;
}
HasLocalDataPoolIF* hkOwner =
objectManager->get<HasLocalDataPoolIF>(poolOwner);
if(hkOwner == nullptr) {
sif::error << "LocalPoolVariable: The supplied pool owner did not "
<< "implement the correct interface "
<< "HasLocalDataPoolIF!" << std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
if(dataSet != nullptr) {

@ -47,8 +47,9 @@ public:
* If nullptr, the variable is not registered.
*/
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
@ -65,8 +66,9 @@ public:
* If nullptr, the variable is not registered.
*/
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.
@ -192,7 +194,7 @@ private:
};
#include "../datapoollocal/LocalPoolVector.tpp"
#include "LocalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using lp_vec_t = LocalPoolVector<T, vectorSize>;

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

@ -1,17 +1,11 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#define FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#ifndef FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#define FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#include "LocalPoolDataSetBase.h"
#include "../datapool/SharedDataSetIF.h"
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../objectmanager/SystemObject.h"
#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,
public LocalPoolDataSetBase,
public SharedDataSetIF {
@ -27,5 +21,4 @@ private:
};
#endif /* FRAMEWORK_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */
#endif /* FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */

@ -1,5 +1,6 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#define FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#ifndef FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#include "LocalPoolDataSetBase.h"
#include "../objectmanager/SystemObjectIF.h"
#include <array>
@ -7,21 +8,43 @@
/**
* @brief This local dataset type is created on the stack.
* @details
* Size of data set specified as a constructor argument. It is recommended
* to use the default LocalDataSet of the dataset is constructed on the heap
* and the SharedLocalDataSet if it created on the heap and used by multiple
* other software objects.
* @tparam capacity
* This will is the primary data structure to organize pool variables into
* sets which can be accessed via the housekeeping service interface or
* which can be sent to other software objects.
*
* 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>
class StaticLocalDataSet: public LocalPoolDataSetBase {
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:
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList;
};
#endif /* FRAMEWORK_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */
#endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */

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

@ -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 "../storagemanager/StorageManagerIF.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 "../housekeeping/HousekeepingMessage.h"
#include "../ipc/MessageQueueMessage.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../subsystem/SubsystemBase.h"
#include <iomanip>
@ -399,7 +399,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode,
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
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) {
//No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand);
@ -413,7 +413,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
}
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, PoolDataSetIF* dataSet,
uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet,
size_t replyLen, bool periodic) {
DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles;
@ -463,7 +463,7 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF *dataSet) {
LocalPoolDataSetBase *dataSet) {
auto replyIter = deviceReplyMap.find(replyId);
if(replyIter == deviceReplyMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED;
@ -1286,10 +1286,14 @@ void DeviceHandlerBase::buildInternalCommand(void) {
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
//so we can track misconfigurations
sif::debug << std::hex << getObjectId()
<< ": DHB::buildInternalCommand: Command "
<< deviceCommandId << " isExecuting" << std::endl; //so we can track misconfigurations
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
<< deviceCommandId << " isExecuting" << std::dec
<< 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 {
iter->second.sendReplyTo = NO_COMMANDER;
iter->second.isExecuting = true;
@ -1396,10 +1400,14 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
pstIntervalMs = executingTask->getPeriodMs();
}
this->hkManager.initializeAfterTaskCreation();
if(setStartupImmediately) {
startTransition(MODE_ON, SUBMODE_NONE);
}
return HasReturnvaluesIF::RETURN_OK;
}
DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
auto iter = deviceReplyMap.find(sid.ownerSetId);
if(iter != deviceReplyMap.end()) {
return iter->second.dataSet;
@ -1413,6 +1421,10 @@ object_id_t DeviceHandlerBase::getObjectId() const {
return SystemObject::getObjectId();
}
void DeviceHandlerBase::setStartUpImmediately() {
this->setStartupImmediately = true;
}
dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
return pstIntervalMs;
}

@ -1,25 +1,26 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#define FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#include "DeviceHandlerIF.h"
#include "DeviceCommunicationIF.h"
#include "DeviceHandlerFailureIsolation.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../devicehandlers/DeviceHandlerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../action/HasActionsIF.h"
#include "../datapool/PoolVariableIF.h"
#include "../devicehandlers/DeviceCommunicationIF.h"
#include "../modes/HasModesIF.h"
#include "../power/PowerSwitchIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../tasks/PeriodicTaskIF.h"
#include "../action/ActionHelper.h"
#include "../health/HealthHelper.h"
#include "../parameters/ParameterHelper.h"
#include "../datapool/HkSwitchHelper.h"
#include "../datapoollocal/HasLocalDataPoolIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
#include <map>
namespace Factory{
@ -104,6 +105,18 @@ public:
void setHkDestination(object_id_t hkDestination);
void setThermalStateRequestPoolIds(uint32_t thermalStatePoolId,
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
@ -149,6 +162,14 @@ public:
* @return
*/
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. */
virtual ~DeviceHandlerBase();
@ -370,7 +391,8 @@ protected:
* - @c RETURN_FAILED else.
*/
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,
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
@ -385,7 +407,7 @@ protected:
* - @c RETURN_FAILED else.
*/
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);
/**
@ -415,7 +437,7 @@ protected:
bool periodic = false);
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF* dataset);
LocalPoolDataSetBase* dataset);
/**
* @brief Can be implemented by child handler to
@ -645,7 +667,7 @@ protected:
//! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified)
PoolDataSetIF* dataSet = nullptr;
LocalPoolDataSetBase* dataSet;
//! The command that expects this reply.
DeviceCommandMap::iterator command;
};
@ -946,14 +968,17 @@ protected:
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void setToExternalControl();
virtual void announceMode(bool recursive);
/* HasModesIF overrides */
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);
/**
* 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.
* @param event The event to be thrown
* @param parameter1 Optional parameter 1
@ -1045,6 +1070,8 @@ private:
*/
uint32_t timeoutStart = 0;
bool setStartupImmediately = false;
/**
* 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,
uint32_t *len);
/**
* @param modeTo either @c MODE_ON, MODE_NORMAL or MODE_RAW NOTHING ELSE!!!
*/
@ -1174,28 +1200,14 @@ private:
*/
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);
virtual ReturnValue_t initializeAfterTaskCreation() override;
virtual DataSetIF* getDataSetHandle(sid_t sid) override;
void parseReply(const uint8_t* receivedData,
size_t receivedDataLen);
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual dur_millis_t getPeriodicOperationFrequency() const override;
void parseReply(const uint8_t* receivedData,
size_t receivedDataLen);
};
#endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

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

@ -1,12 +1,19 @@
#ifndef DEVICEHANDLERIF_H_
#define DEVICEHANDLERIF_H_
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#include "DeviceHandlerMessage.h"
#include "../action/HasActionsIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../events/Event.h"
#include "../modes/HasModesIF.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.
* @details Includes all expected return values, events and modes.
@ -15,6 +22,7 @@
class DeviceHandlerIF {
public:
static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
@ -153,4 +161,4 @@ public:
};
#endif /* DEVICEHANDLERIF_H_ */
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_ */

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

@ -1,69 +1,56 @@
#ifndef DEVICEHANDLERMESSAGE_H_
#define DEVICEHANDLERMESSAGE_H_
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_
#include "../action/ActionMessage.h"
#include "../ipc/CommandMessage.h"
#include "../objectmanager/SystemObjectIF.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
*
* The values are defined in the device-specific implementations
*/
typedef uint32_t DeviceCommandId_t;
/**
* The DeviceHandlerMessage is used to send Commands to a DeviceHandlerIF
* @brief The DeviceHandlerMessage is used to send commands to classes
* implementing DeviceHandlerIF
*/
class DeviceHandlerMessage {
private:
DeviceHandlerMessage();
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
*/
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
// 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
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_WIRETAPPING = MAKE_COMMAND_ID( 4 ); //!< (De)Activates the monitoring of all raw traffic in DeviceHandlers, setParameter is 0 to deactivate, 1 to activate
//! Sends a raw command, setParameter is a storeId containing the
//! raw packet to send
static const Command_t CMD_RAW = MAKE_COMMAND_ID(1);
//! 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)
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_WIRETAPPING = MAKE_COMMAND_ID( 3); //!< Reply to a @c CMD_WIRETAPPING, getParameter() is the current state, 1 enabled, 0 disabled
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
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
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
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
//! Signals that a direct command was sent
static const Command_t REPLY_DIRECT_COMMAND_SENT = ActionMessage::STEP_SUCCESS;
//! Contains a raw command sent to the Device
static const Command_t REPLY_RAW_COMMAND = MAKE_COMMAND_ID(0x11);
//! 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_RAW_REPLY = MAKE_COMMAND_ID(0x12);
static const Command_t REPLY_DIRECT_COMMAND_DATA = ActionMessage::DATA_REPLY;
/**
* Default Destructor
*/
virtual ~DeviceHandlerMessage() {
}
static store_address_t getStoreAddress(const CommandMessage* message);
static uint32_t getDeviceCommandId(const CommandMessage* message);
static object_id_t getDeviceObjectId(const CommandMessage *message);
static object_id_t getIoBoardObjectId(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,
object_id_t deviceObjectid,
store_address_t commandParametersStoreId);
@ -75,11 +62,6 @@ public:
object_id_t deviceObjectid, store_address_t rawPacketStoreId,
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,
uint8_t wiretappingMode);
static void setDeviceHandlerSwitchIoBoardMessage(CommandMessage* message,
@ -88,4 +70,4 @@ public:
static void clear(CommandMessage* message);
};
#endif /* DEVICEHANDLERMESSAGE_H_ */
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERMESSAGE_H_ */

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

@ -4,7 +4,7 @@
#include <stdint.h>
#include "fwSubsystemIdRanges.h"
//could be move to more suitable location
#include <config/tmtc/subsystemIdRanges.h>
#include <subsystemIdRanges.h>
typedef uint16_t EventId_t;
typedef uint8_t EventSeverity_t;
@ -18,9 +18,10 @@ EventId_t getEventId(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 {
static const EventSeverity_t INFO = 1;
static const EventSeverity_t LOW = 2;

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

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

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

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

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

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

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

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

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

13
fsfw.mk

@ -31,12 +31,25 @@ CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/*.cpp)
# select the OS
ifeq ($(OS_FSFW),rtems)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/rtems/*.cpp)
else ifeq ($(OS_FSFW),linux)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/linux/*.cpp)
else ifeq ($(OS_FSFW),freeRTOS)
CXXSRC += $(wildcard $(FRAMEWORK_PATH)/osal/FreeRTOS/*.cpp)
else ifeq ($(OS_FSFW),host)
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
$(error invalid OS_FSFW specified, valid OS_FSFW are rtems, linux, freeRTOS, host)
endif

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

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

@ -92,7 +92,7 @@ ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
else {
/* The next byte is a STX, DTX or 0x0D character which
* 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. */
if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) {
destStream[decodedIndex] = nextByte - 0x40;

@ -15,12 +15,12 @@
* char based transmission systems.
* 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
* 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
* by another char, so STX, ETX and CR should not appear anywhere in the actual
* 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
* 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;
//! End Of Text character. Last character in encoded stream
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.
static constexpr uint8_t DLE_CHAR = 0x10;
static constexpr uint8_t CARRIAGE_RETURN = 0x0D;
@ -47,7 +47,7 @@ public:
* 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
* 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 sourceLen
* @param destStream

@ -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;
}

@ -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_ */

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

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

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

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

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

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

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

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

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

@ -1,23 +1,26 @@
#ifndef FRAMEWORK_HEALTH_HEALTHHELPER_H_
#define FRAMEWORK_HEALTH_HEALTHHELPER_H_
#ifndef FSFW_HEALTH_HEALTHHELPER_H_
#define FSFW_HEALTH_HEALTHHELPER_H_
#include "HasHealthIF.h"
#include "HealthMessage.h"
#include "HealthTableIF.h"
#include "../events/EventManagerIF.h"
#include "../events/EventReportingProxyIF.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthMessage.h"
#include "../health/HealthTableIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../objectmanager/ObjectManagerIF.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
* (including replying to the sender) and updating the Health Table.
*
* 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
* 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.
*
* It does NOT handle @c HEALTH_INFO messages
@ -26,10 +29,9 @@ class HealthHelper {
public:
/**
* ctor
*
* @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);
@ -55,8 +57,9 @@ public:
*
* @param message
* @return
* -@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_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)
*/
ReturnValue_t handleHealthCommand(CommandMessage *message);
@ -77,16 +80,19 @@ public:
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);
/**
*
* @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
* -@c RETURN_OK if the Health Table was found and the object could be registered
* -@c RETURN_FAILED else
* -@c RETURN_OK if the Health Table was found and the object
* could be registered
* -@c RETURN_FAILED else
*/
ReturnValue_t initialize(MessageQueueId_t parentQueue );
@ -109,13 +115,17 @@ private:
HasHealthIF* owner;
/**
* if the #parentQueue is not NULL, a @c HEALTH_INFO message 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
* if the #parentQueue is not NULL, a @c HEALTH_INFO message
* 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.
*/
void informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth);
void informParent(HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth);
void handleSetHealthCommand(CommandMessage *message);
};
#endif /* HEALTHHELPER_H_ */
#endif /* FSFW_HEALTH_HEALTHHELPER_H_ */

@ -1,4 +1,4 @@
#include "../health/HealthMessage.h"
#include "HealthMessage.h"
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) {
@ -7,11 +7,13 @@ void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
message->setParameter2(oldHealth);
}
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command) {
void HealthMessage::setHealthMessage(CommandMessage* message,
Command_t command) {
message->setCommand(command);
}
HasHealthIF::HealthState HealthMessage::getHealth(const CommandMessage* message) {
HasHealthIF::HealthState HealthMessage::getHealth(
const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter();
}

@ -1,20 +1,26 @@
#ifndef HEALTHMESSAGE_H_
#define HEALTHMESSAGE_H_
#ifndef FSFW_HEALTH_HEALTHMESSAGE_H_
#define FSFW_HEALTH_HEALTHMESSAGE_H_
#include "../health/HasHealthIF.h"
#include "HasHealthIF.h"
#include "../ipc/CommandMessage.h"
class HealthMessage {
public:
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 REPLY_HEALTH_SET = MAKE_COMMAND_ID(6);
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 HasHealthIF::HealthState getHealth(const CommandMessage *message);
@ -27,4 +33,4 @@ private:
HealthMessage();
};
#endif /* HEALTHMESSAGE_H_ */
#endif /* FSFW_HEALTH_HEALTHMESSAGE_H_ */

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

@ -1,35 +1,42 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLE_H_
#define FRAMEWORK_HEALTH_HEALTHTABLE_H_
#ifndef FSFW_HEALTH_HEALTHTABLE_H_
#define FSFW_HEALTH_HEALTHTABLE_H_
#include "../health/HealthTableIF.h"
#include "HealthTableIF.h"
#include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h"
#include <map>
typedef std::map<object_id_t, HasHealthIF::HealthState> HealthMap;
class HealthTable: public HealthTableIF, public SystemObject {
public:
HealthTable(object_id_t objectid);
virtual ~HealthTable();
virtual ReturnValue_t registerObject(object_id_t object,
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY);
/** HealthTableIF overrides */
virtual ReturnValue_t registerObject(object_id_t object,
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);
virtual void setHealth(object_id_t object, HasHealthIF::HealthState newState);
virtual HasHealthIF::HealthState getHealth(object_id_t);
virtual uint32_t getPrintSize();
virtual void printAll(uint8_t *pointer, size_t maxSize);
/** ManagesHealthIF overrides */
virtual bool hasHealth(object_id_t object) override;
virtual void setHealth(object_id_t object,
HasHealthIF::HealthState newState) override;
virtual HasHealthIF::HealthState getHealth(object_id_t) override;
protected:
using HealthMap = std::map<object_id_t, HasHealthIF::HealthState>;
using HealthEntry = std::pair<object_id_t, HasHealthIF::HealthState>;
MutexIF* mutex;
HealthMap healthMap;
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_ */

@ -1,28 +1,24 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#define FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#ifndef FSFW_HEALTH_HEALTHTABLEIF_H_
#define FSFW_HEALTH_HEALTHTABLEIF_H_
#include "../health/ManagesHealthIF.h"
#include "ManagesHealthIF.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <map>
class HealthTableIF: public ManagesHealthIF {
// TODO: This is in the mission folder and not in the framework folder.
// delete it?
friend class HealthCommandingService;
public:
virtual ~HealthTableIF() {
}
virtual ~HealthTableIF() {}
virtual ReturnValue_t registerObject(object_id_t object,
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;
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_ */

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

@ -1,9 +1,10 @@
#include <fsfw/objectmanager/ObjectManagerIF.h>
#include "HousekeepingMessage.h"
#include <cstring>
HousekeepingMessage::~HousekeepingMessage() {}
void HousekeepingMessage::setHkReportMessage(CommandMessage* message, sid_t sid,
void HousekeepingMessage::setHkReportReply(CommandMessage* message, sid_t sid,
store_address_t storeId) {
message->setCommand(HK_REPORT);
message->setMessageSize(HK_MESSAGE_SIZE);
@ -11,7 +12,7 @@ void HousekeepingMessage::setHkReportMessage(CommandMessage* message, sid_t sid,
message->setParameter3(storeId.raw);
}
void HousekeepingMessage::setHkDiagnosticsMessage(CommandMessage* message,
void HousekeepingMessage::setHkDiagnosticsReply(CommandMessage* message,
sid_t sid, store_address_t storeId) {
message->setCommand(DIAGNOSTICS_REPORT);
message->setMessageSize(HK_MESSAGE_SIZE);
@ -19,7 +20,7 @@ void HousekeepingMessage::setHkDiagnosticsMessage(CommandMessage* message,
message->setParameter3(storeId.raw);
}
sid_t HousekeepingMessage::getHkReportMessage(const CommandMessage *message,
sid_t HousekeepingMessage::getHkDataReply(const CommandMessage *message,
store_address_t *storeIdToSet) {
if(storeIdToSet != nullptr) {
*storeIdToSet = message->getParameter3();
@ -27,6 +28,96 @@ sid_t HousekeepingMessage::getHkReportMessage(const CommandMessage *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 sid;
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));
}
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);
}

@ -1,16 +1,17 @@
#ifndef FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_
#define FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#include "../ipc/CommandMessage.h"
#include "../ipc/FwMessageTypes.h"
#include "../objectmanager/frameworkObjects.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../storagemanager/StorageManagerIF.h"
#include <limits>
union sid_t {
static constexpr uint64_t INVALID_ADDRESS =
std::numeric_limits<uint64_t>::max();
sid_t(): raw(INVALID_ADDRESS) {}
static constexpr uint64_t INVALID_SID = -1;
static constexpr uint32_t INVALID_SET_ID = -1;
static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
sid_t(): raw(INVALID_SID) {}
sid_t(object_id_t objectId, uint32_t setId):
objectId(objectId),
@ -31,7 +32,15 @@ union sid_t {
uint64_t raw;
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);
/**
* The HK message is initialized with a pointer to a message which holds
* the message data, see CommandMessageIF and getInternalMessage().
* @param message
* Concrete instance is not used, instead this class operates on
* command message instances.
*/
HousekeepingMessage() = delete;
virtual ~HousekeepingMessage();
static constexpr uint8_t MESSAGE_ID = messagetypes::HOUSEKEEPING;
static constexpr Command_t ADD_HK_REPORT_STRUCT =
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 =
static constexpr Command_t ENABLE_PERIODIC_HK_REPORT_GENERATION =
MAKE_COMMAND_ID(5);
static constexpr Command_t DISABLE_PERIODIC_HK_REPORT_GENERATION =
MAKE_COMMAND_ID(6);
@ -92,31 +91,67 @@ public:
static constexpr Command_t GENERATE_ONE_DIAGNOSTICS_REPORT =
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 =
MAKE_COMMAND_ID(31);
static constexpr Command_t MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL =
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 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);
static void setHkDiagnosticsMessage(CommandMessage* message, sid_t sid,
static void setHkDiagnosticsReply(CommandMessage* reply, sid_t sid,
store_address_t storeId);
//! Get the respective SID and store ID. Command ID can be used beforehand
//! to distinguish between diagnostics and regular HK packets
static sid_t getHkReportMessage(const CommandMessage* message,
static void setHkRequestSuccessReply(CommandMessage* reply, sid_t sid);
static void setHkRequestFailureReply(CommandMessage* reply, sid_t sid,
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);
static sid_t getCollectionIntervalModificationCommand(
const CommandMessage* command, float* newCollectionInterval);
static void clear(CommandMessage* message);
private:
static void setSid(CommandMessage* message, sid_t sid);
};
#endif /* FRAMEWORK_HK_HOUSEKEEPINGMESSAGE_H_ */
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ */

@ -1,8 +1,7 @@
#ifndef FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#define FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "../storagemanager/StorageManagerIF.h"
@ -15,67 +14,21 @@
*/
class HousekeepingPacketDownlink: public SerialLinkedListAdapter<SerializeIF> {
public:
HousekeepingPacketDownlink(sid_t sid, float collectionInterval, uint8_t
numberOfParameters, LocalPoolDataSetBase* dataSetPtr):
sourceId(sid.objectId), setId(sid.ownerSetId),
collectionInterval(collectionInterval),
numberOfParameters(numberOfParameters), hkData(dataSetPtr) {
HousekeepingPacketDownlink(sid_t sid, LocalPoolDataSetBase* dataSetPtr):
sourceId(sid.objectId), setId(sid.ownerSetId), hkData(dataSetPtr) {
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:
void setLinks() {
setStart(&sourceId);
sourceId.setNext(&setId);
setId.setNext(&collectionInterval);
collectionInterval.setNext(&numberOfParameters);
numberOfParameters.setNext(&hkData);
setId.setNext(&hkData);
}
SerializeElement<object_id_t> sourceId;
SerializeElement<uint32_t> setId;
SerializeElement<float> collectionInterval;
SerializeElement<uint8_t> numberOfParameters;
LinkedElement<SerializeIF> hkData;
};
#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