renormalized line endings

This commit is contained in:
Robin Müller 2020-08-28 18:33:29 +02:00
parent 9abd796e6f
commit 1b9c8446b7
381 changed files with 38723 additions and 38723 deletions

View File

@ -1,247 +1,247 @@
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h"
/**
* @brief A List that stores its values in an array.
* @details
* The underlying storage is an array that can be allocated by the class
* itself or supplied via ctor.
*
* @ingroup container
*/
template<typename T, typename count_t = uint8_t>
class ArrayList {
template<typename U, typename count> friend class SerialArrayListAdapter;
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?)
*/
ArrayList(const ArrayList& other) = delete;
const ArrayList& operator=(const ArrayList& other) = delete;
/**
* Number of Elements stored in this List
*/
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.
*/
virtual ~ArrayList() {
if (allocated) {
delete[] entries;
}
}
/**
* 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;
}
/**
* The current element the iterator points to
*/
T *value;
Iterator& operator++() {
value++;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
T operator*() {
return *value;
}
T *operator->() {
return 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 (value == other.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
};
/**
* Iterator pointing to the first stored elmement
*
* @return Iterator to the first element
*/
Iterator begin() const {
return Iterator(&entries[0]);
}
/**
* returns an Iterator pointing to the element after the last stored entry
*
* @return Iterator to the element after the last entry
*/
Iterator end() const {
return Iterator(&entries[size]);
}
T & operator[](count_t i) const {
return entries[i];
}
/**
* The first element
*
* @return pointer to the first stored element
*/
T *front() {
return entries;
}
/**
* The last element
*
* does not return a valid pointer if called on an empty list.
*
* @return pointer to the last stored element
*/
T *back() {
return &entries[size - 1];
//Alternative solution
//return const_cast<T*>(static_cast<const T*>(*this).back());
}
const T* back() const{
return &entries[size-1];
}
/**
* The maximum number of elements this List can contain
*
* @return maximum number of elements
*/
uint32_t maxSize() const {
return this->maxSize_;
}
/**
* Insert a new element into the list.
*
* The new element is inserted after the last stored element.
*
* @param entry
* @return
* -@c FULL if the List is full
* -@c RETURN_OK else
*/
ReturnValue_t insert(T entry) {
if (size >= maxSize_) {
return FULL;
}
entries[size] = entry;
++size;
return HasReturnvaluesIF::RETURN_OK;
}
/**
* clear the List
*
* This does not actually clear all entries, it only sets the size to 0.
*/
void clear() {
size = 0;
}
count_t remaining() {
return (maxSize_ - size);
}
protected:
/**
* pointer to the array in which the entries are stored
*/
T *entries;
/**
* remembering the maximum size
*/
uint32_t maxSize_;
/**
* true if the array was allocated and needs to be deleted in the destructor.
*/
bool allocated;
};
#endif /* ARRAYLIST_H_ */
#ifndef FRAMEWORK_CONTAINER_ARRAYLIST_H_
#define FRAMEWORK_CONTAINER_ARRAYLIST_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serialize/SerializeIF.h"
/**
* @brief A List that stores its values in an array.
* @details
* The underlying storage is an array that can be allocated by the class
* itself or supplied via ctor.
*
* @ingroup container
*/
template<typename T, typename count_t = uint8_t>
class ArrayList {
template<typename U, typename count> friend class SerialArrayListAdapter;
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?)
*/
ArrayList(const ArrayList& other) = delete;
const ArrayList& operator=(const ArrayList& other) = delete;
/**
* Number of Elements stored in this List
*/
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.
*/
virtual ~ArrayList() {
if (allocated) {
delete[] entries;
}
}
/**
* 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;
}
/**
* The current element the iterator points to
*/
T *value;
Iterator& operator++() {
value++;
return *this;
}
Iterator operator++(int) {
Iterator tmp(*this);
operator++();
return tmp;
}
Iterator& operator--() {
value--;
return *this;
}
Iterator operator--(int) {
Iterator tmp(*this);
operator--();
return tmp;
}
T operator*() {
return *value;
}
T *operator->() {
return 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 (value == other.value);
}
//SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other);
}
};
/**
* Iterator pointing to the first stored elmement
*
* @return Iterator to the first element
*/
Iterator begin() const {
return Iterator(&entries[0]);
}
/**
* returns an Iterator pointing to the element after the last stored entry
*
* @return Iterator to the element after the last entry
*/
Iterator end() const {
return Iterator(&entries[size]);
}
T & operator[](count_t i) const {
return entries[i];
}
/**
* The first element
*
* @return pointer to the first stored element
*/
T *front() {
return entries;
}
/**
* The last element
*
* does not return a valid pointer if called on an empty list.
*
* @return pointer to the last stored element
*/
T *back() {
return &entries[size - 1];
//Alternative solution
//return const_cast<T*>(static_cast<const T*>(*this).back());
}
const T* back() const{
return &entries[size-1];
}
/**
* The maximum number of elements this List can contain
*
* @return maximum number of elements
*/
uint32_t maxSize() const {
return this->maxSize_;
}
/**
* Insert a new element into the list.
*
* The new element is inserted after the last stored element.
*
* @param entry
* @return
* -@c FULL if the List is full
* -@c RETURN_OK else
*/
ReturnValue_t insert(T entry) {
if (size >= maxSize_) {
return FULL;
}
entries[size] = entry;
++size;
return HasReturnvaluesIF::RETURN_OK;
}
/**
* clear the List
*
* This does not actually clear all entries, it only sets the size to 0.
*/
void clear() {
size = 0;
}
count_t remaining() {
return (maxSize_ - size);
}
protected:
/**
* pointer to the array in which the entries are stored
*/
T *entries;
/**
* remembering the maximum size
*/
uint32_t maxSize_;
/**
* true if the array was allocated and needs to be deleted in the destructor.
*/
bool allocated;
};
#endif /* ARRAYLIST_H_ */

View File

@ -1,42 +1,42 @@
#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
#include "../container/FIFOBase.h"
#include <vector>
/**
* @brief Simple First-In-First-Out data structure. The maximum size
* can be set in the constructor.
* @details
* The maximum capacity can be determined at run-time, so this container
* performs dynamic memory allocation!
* The public interface of FIFOBase exposes the user interface for the FIFO.
* @tparam T Entry Type
* @tparam capacity Maximum capacity
*/
template<typename T>
class DynamicFIFO: public FIFOBase<T> {
public:
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
fifoVector(maxCapacity) {
// trying to pass the pointer of the uninitialized vector
// to the FIFOBase constructor directly lead to a super evil bug.
// So we do it like this now.
this->setData(fifoVector.data());
};
/**
* @brief Custom copy constructor which prevents setting the
* underlying pointer wrong.
*/
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
fifoVector(other.maxCapacity) {
this->setData(fifoVector.data());
}
private:
std::vector<T> fifoVector;
};
#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */
#ifndef FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
#define FRAMEWORK_CONTAINER_DYNAMICFIFO_H_
#include "../container/FIFOBase.h"
#include <vector>
/**
* @brief Simple First-In-First-Out data structure. The maximum size
* can be set in the constructor.
* @details
* The maximum capacity can be determined at run-time, so this container
* performs dynamic memory allocation!
* The public interface of FIFOBase exposes the user interface for the FIFO.
* @tparam T Entry Type
* @tparam capacity Maximum capacity
*/
template<typename T>
class DynamicFIFO: public FIFOBase<T> {
public:
DynamicFIFO(size_t maxCapacity): FIFOBase<T>(nullptr, maxCapacity),
fifoVector(maxCapacity) {
// trying to pass the pointer of the uninitialized vector
// to the FIFOBase constructor directly lead to a super evil bug.
// So we do it like this now.
this->setData(fifoVector.data());
};
/**
* @brief Custom copy constructor which prevents setting the
* underlying pointer wrong.
*/
DynamicFIFO(const DynamicFIFO& other): FIFOBase<T>(other),
fifoVector(other.maxCapacity) {
this->setData(fifoVector.data());
}
private:
std::vector<T> fifoVector;
};
#endif /* FRAMEWORK_CONTAINER_DYNAMICFIFO_H_ */

View File

@ -1,34 +1,34 @@
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
#define FRAMEWORK_CONTAINER_FIFO_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../container/FIFOBase.h"
#include <array>
/**
* @brief Simple First-In-First-Out data structure with size fixed at
* compile time
* @details
* Performs no dynamic memory allocation.
* The public interface of FIFOBase exposes the user interface for the FIFO.
* @tparam T Entry Type
* @tparam capacity Maximum capacity
*/
template<typename T, size_t capacity>
class FIFO: public FIFOBase<T> {
public:
FIFO(): FIFOBase<T>(fifoArray.data(), capacity) {};
/**
* @brief Custom copy constructor to set pointer correctly.
* @param other
*/
FIFO(const FIFO& other): FIFOBase<T>(other) {
this->setData(fifoArray.data());
}
private:
std::array<T, capacity> fifoArray;
};
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */
#ifndef FRAMEWORK_CONTAINER_FIFO_H_
#define FRAMEWORK_CONTAINER_FIFO_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../container/FIFOBase.h"
#include <array>
/**
* @brief Simple First-In-First-Out data structure with size fixed at
* compile time
* @details
* Performs no dynamic memory allocation.
* The public interface of FIFOBase exposes the user interface for the FIFO.
* @tparam T Entry Type
* @tparam capacity Maximum capacity
*/
template<typename T, size_t capacity>
class FIFO: public FIFOBase<T> {
public:
FIFO(): FIFOBase<T>(fifoArray.data(), capacity) {};
/**
* @brief Custom copy constructor to set pointer correctly.
* @param other
*/
FIFO(const FIFO& other): FIFOBase<T>(other) {
this->setData(fifoArray.data());
}
private:
std::array<T, capacity> fifoArray;
};
#endif /* FRAMEWORK_CONTAINERS_STATICFIFO_H_ */

View File

@ -1,65 +1,65 @@
#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_
#define FRAMEWORK_CONTAINER_FIFOBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
#include <cstring>
template <typename T>
class FIFOBase {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
/** Default ctor, takes pointer to first entry of underlying container
* and maximum capacity */
FIFOBase(T* values, const size_t maxCapacity);
/**
* Insert value into FIFO
* @param value
* @return
*/
ReturnValue_t insert(T value);
/**
* Retrieve item from FIFO. This removes the item from the FIFO.
* @param value
* @return
*/
ReturnValue_t retrieve(T *value);
/**
* Retrieve item from FIFO without removing it from FIFO.
* @param value
* @return
*/
ReturnValue_t peek(T * value);
/**
* Remove item from FIFO.
* @return
*/
ReturnValue_t pop();
bool empty();
bool full();
size_t size();
size_t getMaxCapacity() const;
protected:
void setData(T* data);
size_t maxCapacity = 0;
T* values;
size_t readIndex = 0;
size_t writeIndex = 0;
size_t currentSize = 0;
size_t next(size_t current);
};
#include "../container/FIFOBase.tpp"
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */
#ifndef FRAMEWORK_CONTAINER_FIFOBASE_H_
#define FRAMEWORK_CONTAINER_FIFOBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
#include <cstring>
template <typename T>
class FIFOBase {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIFO_CLASS;
static const ReturnValue_t FULL = MAKE_RETURN_CODE(1);
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(2);
/** Default ctor, takes pointer to first entry of underlying container
* and maximum capacity */
FIFOBase(T* values, const size_t maxCapacity);
/**
* Insert value into FIFO
* @param value
* @return
*/
ReturnValue_t insert(T value);
/**
* Retrieve item from FIFO. This removes the item from the FIFO.
* @param value
* @return
*/
ReturnValue_t retrieve(T *value);
/**
* Retrieve item from FIFO without removing it from FIFO.
* @param value
* @return
*/
ReturnValue_t peek(T * value);
/**
* Remove item from FIFO.
* @return
*/
ReturnValue_t pop();
bool empty();
bool full();
size_t size();
size_t getMaxCapacity() const;
protected:
void setData(T* data);
size_t maxCapacity = 0;
T* values;
size_t readIndex = 0;
size_t writeIndex = 0;
size_t currentSize = 0;
size_t next(size_t current);
};
#include "../container/FIFOBase.tpp"
#endif /* FRAMEWORK_CONTAINER_FIFOBASE_H_ */

View File

@ -1,57 +1,57 @@
#ifndef FIXEDARRAYLIST_H_
#define FIXEDARRAYLIST_H_
#include "../container/ArrayList.h"
/**
* @brief Array List with a fixed maximum size
* @ingroup container
*/
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> {
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;
}
FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
return *this;
}
virtual ~FixedArrayList() {
}
};
#endif /* FIXEDARRAYLIST_H_ */
#ifndef FIXEDARRAYLIST_H_
#define FIXEDARRAYLIST_H_
#include "../container/ArrayList.h"
/**
* @brief Array List with a fixed maximum size
* @ingroup container
*/
template<typename T, uint32_t MAX_SIZE, typename count_t = uint8_t>
class FixedArrayList: public ArrayList<T, count_t> {
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;
}
FixedArrayList& operator=(FixedArrayList other) {
memcpy(this->data, other.data, sizeof(this->data));
this->entries = data;
return *this;
}
virtual ~FixedArrayList() {
}
};
#endif /* FIXEDARRAYLIST_H_ */

View File

@ -1,225 +1,225 @@
#ifndef FIXEDMAP_H_
#define FIXEDMAP_H_
#include "../container/ArrayList.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <utility>
/**
* @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).
* @ingroup container
*/
template<typename key_t, typename T>
class FixedMap: public SerializeIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private:
static const key_t EMPTY_SLOT = -1;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
uint32_t _size;
uint32_t findIndex(key_t key) const {
if (_size == 0) {
return 1;
}
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
public:
FixedMap(uint32_t maxSize) :
theMap(maxSize), _size(0) {
}
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
public:
Iterator() :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
}
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;
}
};
Iterator begin() const {
return Iterator(&theMap[0]);
}
Iterator end() const {
return Iterator(&theMap[_size]);
}
uint32_t size() const {
return _size;
}
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) {
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
return FixedMap::KEY_ALREADY_EXISTS;
}
if (_size == theMap.maxSize()) {
return FixedMap::MAP_FULL;
}
theMap[_size].first = key;
theMap[_size].second = value;
if (storedValue != NULL) {
*storedValue = Iterator(&theMap[_size]);
}
++_size;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.second);
}
ReturnValue_t exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
}
ReturnValue_t erase(Iterator *iter) {
uint32_t i;
if ((i = findIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
--((*iter).value);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t erase(key_t key) {
uint32_t i;
if ((i = findIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
return HasReturnvaluesIF::RETURN_OK;
}
T *findValue(key_t key) const {
return &theMap[findIndex(key)].second;
}
Iterator find(key_t key) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return end();
}
return Iterator(&theMap[findIndex(key)]);
}
ReturnValue_t find(key_t key, T **value) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*value = &theMap[findIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
}
void clear() {
_size = 0;
}
uint32_t maxSize() const {
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,
buffer, size, maxSize, streamEndianness);
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
size, maxSize, streamEndianness);
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
maxSize, streamEndianness);
++i;
}
return result;
}
virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size);
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
printSize += SerializeAdapter::getSerializedSize(
&theMap[i].first);
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
}
return printSize;
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
buffer, size, streamEndianness);
if (this->_size > theMap.maxSize()) {
return SerializeIF::TOO_MANY_ELEMENTS;
}
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
size, streamEndianness);
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
streamEndianness);
++i;
}
return result;
}
};
#endif /* FIXEDMAP_H_ */
#ifndef FIXEDMAP_H_
#define FIXEDMAP_H_
#include "../container/ArrayList.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include <utility>
/**
* @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).
* @ingroup container
*/
template<typename key_t, typename T>
class FixedMap: public SerializeIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::FIXED_MAP;
static const ReturnValue_t KEY_ALREADY_EXISTS = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t MAP_FULL = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t KEY_DOES_NOT_EXIST = MAKE_RETURN_CODE(0x03);
private:
static const key_t EMPTY_SLOT = -1;
ArrayList<std::pair<key_t, T>, uint32_t> theMap;
uint32_t _size;
uint32_t findIndex(key_t key) const {
if (_size == 0) {
return 1;
}
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
if (theMap[i].first == key) {
return i;
}
}
return i;
}
public:
FixedMap(uint32_t maxSize) :
theMap(maxSize), _size(0) {
}
class Iterator: public ArrayList<std::pair<key_t, T>, uint32_t>::Iterator {
public:
Iterator() :
ArrayList<std::pair<key_t, T>, uint32_t>::Iterator() {
}
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;
}
};
Iterator begin() const {
return Iterator(&theMap[0]);
}
Iterator end() const {
return Iterator(&theMap[_size]);
}
uint32_t size() const {
return _size;
}
ReturnValue_t insert(key_t key, T value, Iterator *storedValue = NULL) {
if (exists(key) == HasReturnvaluesIF::RETURN_OK) {
return FixedMap::KEY_ALREADY_EXISTS;
}
if (_size == theMap.maxSize()) {
return FixedMap::MAP_FULL;
}
theMap[_size].first = key;
theMap[_size].second = value;
if (storedValue != NULL) {
*storedValue = Iterator(&theMap[_size]);
}
++_size;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t insert(std::pair<key_t, T> pair) {
return insert(pair.first, pair.second);
}
ReturnValue_t exists(key_t key) const {
ReturnValue_t result = KEY_DOES_NOT_EXIST;
if (findIndex(key) < _size) {
result = HasReturnvaluesIF::RETURN_OK;
}
return result;
}
ReturnValue_t erase(Iterator *iter) {
uint32_t i;
if ((i = findIndex((*iter).value->first)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
--((*iter).value);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t erase(key_t key) {
uint32_t i;
if ((i = findIndex(key)) >= _size) {
return KEY_DOES_NOT_EXIST;
}
theMap[i] = theMap[_size - 1];
--_size;
return HasReturnvaluesIF::RETURN_OK;
}
T *findValue(key_t key) const {
return &theMap[findIndex(key)].second;
}
Iterator find(key_t key) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return end();
}
return Iterator(&theMap[findIndex(key)]);
}
ReturnValue_t find(key_t key, T **value) const {
ReturnValue_t result = exists(key);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
*value = &theMap[findIndex(key)].second;
return HasReturnvaluesIF::RETURN_OK;
}
void clear() {
_size = 0;
}
uint32_t maxSize() const {
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,
buffer, size, maxSize, streamEndianness);
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::serialize(&theMap[i].first, buffer,
size, maxSize, streamEndianness);
result = SerializeAdapter::serialize(&theMap[i].second, buffer, size,
maxSize, streamEndianness);
++i;
}
return result;
}
virtual size_t getSerializedSize() const {
uint32_t printSize = sizeof(_size);
uint32_t i = 0;
for (i = 0; i < _size; ++i) {
printSize += SerializeAdapter::getSerializedSize(
&theMap[i].first);
printSize += SerializeAdapter::getSerializedSize(&theMap[i].second);
}
return printSize;
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&this->_size,
buffer, size, streamEndianness);
if (this->_size > theMap.maxSize()) {
return SerializeIF::TOO_MANY_ELEMENTS;
}
uint32_t i = 0;
while ((result == HasReturnvaluesIF::RETURN_OK) && (i < this->_size)) {
result = SerializeAdapter::deSerialize(&theMap[i].first, buffer,
size, streamEndianness);
result = SerializeAdapter::deSerialize(&theMap[i].second, buffer, size,
streamEndianness);
++i;
}
return result;
}
};
#endif /* FIXEDMAP_H_ */

View File

@ -1,90 +1,90 @@
#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#include "../container/ArrayList.h"
#include "../container/SinglyLinkedList.h"
template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator,
public ArrayList<T, count_t>::Iterator {
public:
HybridIterator() {}
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
LinkedElement<T>::Iterator(*iter), value(iter->value),
linked(true) {
}
HybridIterator(LinkedElement<T> *start) :
LinkedElement<T>::Iterator(start), value(start->value),
linked(true) {
}
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
typename ArrayList<T, count_t>::Iterator end) :
ArrayList<T, count_t>::Iterator(start), value(start.value),
linked(false), end(end.value) {
if (value == this->end) {
value = NULL;
}
}
HybridIterator(T *firstElement, T *lastElement) :
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
linked(false), end(++lastElement) {
if (value == end) {
value = NULL;
}
}
HybridIterator& operator++() {
if (linked) {
LinkedElement<T>::Iterator::operator++();
if (LinkedElement<T>::Iterator::value != nullptr) {
value = LinkedElement<T>::Iterator::value->value;
} else {
value = nullptr;
}
} else {
ArrayList<T, count_t>::Iterator::operator++();
value = ArrayList<T, count_t>::Iterator::value;
if (value == end) {
value = nullptr;
}
}
return *this;
}
HybridIterator operator++(int) {
HybridIterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const HybridIterator& other) const {
return value == other.value;
}
bool operator!=(const HybridIterator& other) const {
return !(*this == other);
}
T operator*() {
return *value;
}
T *operator->() {
return value;
}
T* value = nullptr;
private:
bool linked = false;
T *end = nullptr;
};
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */
#ifndef FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#define FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_
#include "../container/ArrayList.h"
#include "../container/SinglyLinkedList.h"
template<typename T, typename count_t = uint8_t>
class HybridIterator: public LinkedElement<T>::Iterator,
public ArrayList<T, count_t>::Iterator {
public:
HybridIterator() {}
HybridIterator(typename LinkedElement<T>::Iterator *iter) :
LinkedElement<T>::Iterator(*iter), value(iter->value),
linked(true) {
}
HybridIterator(LinkedElement<T> *start) :
LinkedElement<T>::Iterator(start), value(start->value),
linked(true) {
}
HybridIterator(typename ArrayList<T, count_t>::Iterator start,
typename ArrayList<T, count_t>::Iterator end) :
ArrayList<T, count_t>::Iterator(start), value(start.value),
linked(false), end(end.value) {
if (value == this->end) {
value = NULL;
}
}
HybridIterator(T *firstElement, T *lastElement) :
ArrayList<T, count_t>::Iterator(firstElement), value(firstElement),
linked(false), end(++lastElement) {
if (value == end) {
value = NULL;
}
}
HybridIterator& operator++() {
if (linked) {
LinkedElement<T>::Iterator::operator++();
if (LinkedElement<T>::Iterator::value != nullptr) {
value = LinkedElement<T>::Iterator::value->value;
} else {
value = nullptr;
}
} else {
ArrayList<T, count_t>::Iterator::operator++();
value = ArrayList<T, count_t>::Iterator::value;
if (value == end) {
value = nullptr;
}
}
return *this;
}
HybridIterator operator++(int) {
HybridIterator tmp(*this);
operator++();
return tmp;
}
bool operator==(const HybridIterator& other) const {
return value == other.value;
}
bool operator!=(const HybridIterator& other) const {
return !(*this == other);
}
T operator*() {
return *value;
}
T *operator->() {
return value;
}
T* value = nullptr;
private:
bool linked = false;
T *end = nullptr;
};
#endif /* FRAMEWORK_CONTAINER_HYBRIDITERATOR_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +1,35 @@
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
#include "../storagemanager/StorageManagerIF.h"
#include <utility>
class PlacementFactory {
public:
PlacementFactory(StorageManagerIF* backend) :
dataBackend(backend) {
}
template<typename T, typename ... Args>
T* generate(Args&&... args) {
store_address_t tempId;
uint8_t* pData = NULL;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData);
if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL;
}
T* temp = new (pData) T(std::forward<Args>(args)...);
return temp;
}
template<typename T>
ReturnValue_t destroy(T* thisElement) {
//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);
return dataBackend->deleteData(pointer, sizeof(T));
}
private:
StorageManagerIF* dataBackend;
};
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */
#ifndef FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
#define FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_
#include "../storagemanager/StorageManagerIF.h"
#include <utility>
class PlacementFactory {
public:
PlacementFactory(StorageManagerIF* backend) :
dataBackend(backend) {
}
template<typename T, typename ... Args>
T* generate(Args&&... args) {
store_address_t tempId;
uint8_t* pData = NULL;
ReturnValue_t result = dataBackend->getFreeElement(&tempId, sizeof(T),
&pData);
if (result != HasReturnvaluesIF::RETURN_OK) {
return NULL;
}
T* temp = new (pData) T(std::forward<Args>(args)...);
return temp;
}
template<typename T>
ReturnValue_t destroy(T* thisElement) {
//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);
return dataBackend->deleteData(pointer, sizeof(T));
}
private:
StorageManagerIF* dataBackend;
};
#endif /* FRAMEWORK_CONTAINER_PLACEMENTFACTORY_H_ */

View File

@ -1,113 +1,113 @@
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
template<uint8_t N_READ_PTRS = 1>
class RingBufferBase {
public:
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size),
overwriteOld(overwriteOld) {
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = startAddress;
}
}
virtual ~RingBufferBase() {}
bool isFull(uint8_t n = 0) {
return (availableWriteSpace(n) == 0);
}
bool isEmpty(uint8_t n = 0) {
return (getAvailableReadData(n) == 0);
}
size_t getAvailableReadData(uint8_t n = 0) const {
return ((write + size) - read[n]) % size;
}
size_t availableWriteSpace(uint8_t n = 0) const {
//One less to avoid ambiguous full/empty problem.
return (((read[n] + size) - write - 1) % size);
}
bool overwritesOld() const {
return overwriteOld;
}
size_t getMaxSize() const {
return size - 1;
}
void clear() {
write = start;
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = start;
}
}
size_t writeTillWrap() {
return (start + size) - write;
}
size_t readTillWrap(uint8_t n = 0) {
return (start + size) - read[n];
}
size_t getStart() const {
return start;
}
protected:
const size_t start;
size_t write;
size_t read[N_READ_PTRS];
const size_t size;
const bool overwriteOld;
void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start;
}
void incrementRead(uint32_t amount, uint8_t n = 0) {
read[n] = ((read[n] + amount - start) % size) + start;
}
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (getAvailableReadData(n) >= amount) {
incrementRead(amount, n);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t writeData(uint32_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
size_t getRead(uint8_t n = 0) const {
return read[n];
}
void setRead(uint32_t read, uint8_t n = 0) {
if (read >= start && read < (start+size)) {
this->read[n] = read;
}
}
uint32_t getWrite() const {
return write;
}
void setWrite(uint32_t write) {
this->write = write;
}
};
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */
#ifndef FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#define FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
template<uint8_t N_READ_PTRS = 1>
class RingBufferBase {
public:
RingBufferBase(size_t startAddress, const size_t size, bool overwriteOld) :
start(startAddress), write(startAddress), size(size),
overwriteOld(overwriteOld) {
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = startAddress;
}
}
virtual ~RingBufferBase() {}
bool isFull(uint8_t n = 0) {
return (availableWriteSpace(n) == 0);
}
bool isEmpty(uint8_t n = 0) {
return (getAvailableReadData(n) == 0);
}
size_t getAvailableReadData(uint8_t n = 0) const {
return ((write + size) - read[n]) % size;
}
size_t availableWriteSpace(uint8_t n = 0) const {
//One less to avoid ambiguous full/empty problem.
return (((read[n] + size) - write - 1) % size);
}
bool overwritesOld() const {
return overwriteOld;
}
size_t getMaxSize() const {
return size - 1;
}
void clear() {
write = start;
for (uint8_t count = 0; count < N_READ_PTRS; count++) {
read[count] = start;
}
}
size_t writeTillWrap() {
return (start + size) - write;
}
size_t readTillWrap(uint8_t n = 0) {
return (start + size) - read[n];
}
size_t getStart() const {
return start;
}
protected:
const size_t start;
size_t write;
size_t read[N_READ_PTRS];
const size_t size;
const bool overwriteOld;
void incrementWrite(uint32_t amount) {
write = ((write + amount - start) % size) + start;
}
void incrementRead(uint32_t amount, uint8_t n = 0) {
read[n] = ((read[n] + amount - start) % size) + start;
}
ReturnValue_t readData(uint32_t amount, uint8_t n = 0) {
if (getAvailableReadData(n) >= amount) {
incrementRead(amount, n);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t writeData(uint32_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
size_t getRead(uint8_t n = 0) const {
return read[n];
}
void setRead(uint32_t read, uint8_t n = 0) {
if (read >= start && read < (start+size)) {
this->read[n] = read;
}
}
uint32_t getWrite() const {
return write;
}
void setWrite(uint32_t write) {
this->write = write;
}
};
#endif /* FRAMEWORK_CONTAINER_RINGBUFFERBASE_H_ */

View File

@ -1,30 +1,30 @@
#include "../container/SharedRingBuffer.h"
#include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h"
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
maxExcessBytes) {
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,
maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
return mutex->lockMutex(timeoutType, timeout);
}
ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
return mutex->unlockMutex();
}
MutexIF* SharedRingBuffer::getMutexHandle() const {
return mutex;
}
#include "../container/SharedRingBuffer.h"
#include "../ipc/MutexFactory.h"
#include "../ipc/MutexHelper.h"
SharedRingBuffer::SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes):
SystemObject(objectId), SimpleRingBuffer(size, overwriteOld,
maxExcessBytes) {
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,
maxExcessBytes) {
mutex = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedRingBuffer::lockRingBufferMutex(
MutexIF::TimeoutType timeoutType, dur_millis_t timeout) {
return mutex->lockMutex(timeoutType, timeout);
}
ReturnValue_t SharedRingBuffer::unlockRingBufferMutex() {
return mutex->unlockMutex();
}
MutexIF* SharedRingBuffer::getMutexHandle() const {
return mutex;
}

View File

@ -1,68 +1,68 @@
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#include "../container/SimpleRingBuffer.h"
#include "../ipc/MutexIF.h"
#include "../objectmanager/SystemObject.h"
#include "../timemanager/Clock.h"
/**
* @brief Ring buffer which can be shared among multiple objects
* @details
* This class offers a mutex to perform thread-safe operation on the ring
* buffer. It is still up to the developer to actually perform the lock
* and unlock operations.
*/
class SharedRingBuffer: public SystemObject,
public SimpleRingBuffer {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* Unless a read-only constant value is read, all operations on the
* shared ring buffer should be protected by calling this function.
* @param timeoutType
* @param timeout
* @return
*/
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
dur_millis_t timeout);
/**
* Any locked mutex also has to be unlocked, otherwise, access to the
* shared ring buffer will be blocked.
* @return
*/
virtual ReturnValue_t unlockRingBufferMutex();
/**
* The mutex handle can be accessed directly, for example to perform
* the lock with the #MutexHelper for a RAII compliant lock operation.
* @return
*/
MutexIF* getMutexHandle() const;
private:
MutexIF* mutex = nullptr;
};
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */
#ifndef FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_
#include "../container/SimpleRingBuffer.h"
#include "../ipc/MutexIF.h"
#include "../objectmanager/SystemObject.h"
#include "../timemanager/Clock.h"
/**
* @brief Ring buffer which can be shared among multiple objects
* @details
* This class offers a mutex to perform thread-safe operation on the ring
* buffer. It is still up to the developer to actually perform the lock
* and unlock operations.
*/
class SharedRingBuffer: public SystemObject,
public SimpleRingBuffer {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
*/
SharedRingBuffer(object_id_t objectId, uint8_t* buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes);
/**
* Unless a read-only constant value is read, all operations on the
* shared ring buffer should be protected by calling this function.
* @param timeoutType
* @param timeout
* @return
*/
virtual ReturnValue_t lockRingBufferMutex(MutexIF::TimeoutType timeoutType,
dur_millis_t timeout);
/**
* Any locked mutex also has to be unlocked, otherwise, access to the
* shared ring buffer will be blocked.
* @return
*/
virtual ReturnValue_t unlockRingBufferMutex();
/**
* The mutex handle can be accessed directly, for example to perform
* the lock with the #MutexHelper for a RAII compliant lock operation.
* @return
*/
MutexIF* getMutexHandle() const;
private:
MutexIF* mutex = nullptr;
};
#endif /* FRAMEWORK_CONTAINER_SHAREDRINGBUFFER_H_ */

View File

@ -1,135 +1,135 @@
#include "../container/SimpleRingBuffer.h"
#include <cstring>
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes) :
RingBufferBase<>(0, size, overwriteOld),
maxExcessBytes(maxExcessBytes) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
buffer = new uint8_t[size + maxExcessBytes];
}
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
}
SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer;
}
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap < amount) {
if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
return HasReturnvaluesIF::RETURN_FAILED;
}
excessBytes = amount - amountTillWrap;
}
*writePointer = &buffer[write];
return HasReturnvaluesIF::RETURN_OK;
}
else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
if(getExcessBytes() > 0) {
moveExcessBytesToStart();
}
incrementWrite(amount);
}
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) {
// remaining size in buffer is sufficient to fit full amount.
memcpy(&buffer[write], data, amount);
}
else {
memcpy(&buffer[write], data, amountTillWrap);
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
}
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
size_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) {
if (readRemaining) {
// more data available than amount specified.
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
if (amountTillWrap >= amount) {
memcpy(data, &buffer[read[READ_PTR]], amount);
} else {
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
}
if(incrementReadPtr) {
deleteData(amount, readRemaining);
}
return HasReturnvaluesIF::RETURN_OK;
}
size_t SimpleRingBuffer::getExcessBytes() const {
return excessBytes;
}
void SimpleRingBuffer::moveExcessBytesToStart() {
if(excessBytes > 0) {
std::memcpy(buffer, &buffer[size], excessBytes);
excessBytes = 0;
}
}
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
bool deleteRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
if (availableData < amount) {
if (deleteRemaining) {
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK;
}
#include "../container/SimpleRingBuffer.h"
#include <cstring>
SimpleRingBuffer::SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes) :
RingBufferBase<>(0, size, overwriteOld),
maxExcessBytes(maxExcessBytes) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
buffer = new uint8_t[size + maxExcessBytes];
}
SimpleRingBuffer::SimpleRingBuffer(uint8_t *buffer, const size_t size,
bool overwriteOld, size_t maxExcessBytes):
RingBufferBase<>(0, size, overwriteOld), buffer(buffer) {
if(maxExcessBytes > size) {
this->maxExcessBytes = size;
}
else {
this->maxExcessBytes = maxExcessBytes;
}
}
SimpleRingBuffer::~SimpleRingBuffer() {
delete[] buffer;
}
ReturnValue_t SimpleRingBuffer::getFreeElement(uint8_t **writePointer,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap < amount) {
if((amount - amountTillWrap + excessBytes) > maxExcessBytes) {
return HasReturnvaluesIF::RETURN_FAILED;
}
excessBytes = amount - amountTillWrap;
}
*writePointer = &buffer[write];
return HasReturnvaluesIF::RETURN_OK;
}
else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
void SimpleRingBuffer::confirmBytesWritten(size_t amount) {
if(getExcessBytes() > 0) {
moveExcessBytesToStart();
}
incrementWrite(amount);
}
ReturnValue_t SimpleRingBuffer::writeData(const uint8_t* data,
size_t amount) {
if (availableWriteSpace() >= amount or overwriteOld) {
size_t amountTillWrap = writeTillWrap();
if (amountTillWrap >= amount) {
// remaining size in buffer is sufficient to fit full amount.
memcpy(&buffer[write], data, amount);
}
else {
memcpy(&buffer[write], data, amountTillWrap);
memcpy(buffer, data + amountTillWrap, amount - amountTillWrap);
}
incrementWrite(amount);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
ReturnValue_t SimpleRingBuffer::readData(uint8_t* data, size_t amount,
bool incrementReadPtr, bool readRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
size_t amountTillWrap = readTillWrap(READ_PTR);
if (availableData < amount) {
if (readRemaining) {
// more data available than amount specified.
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
if (amountTillWrap >= amount) {
memcpy(data, &buffer[read[READ_PTR]], amount);
} else {
memcpy(data, &buffer[read[READ_PTR]], amountTillWrap);
memcpy(data + amountTillWrap, buffer, amount - amountTillWrap);
}
if(incrementReadPtr) {
deleteData(amount, readRemaining);
}
return HasReturnvaluesIF::RETURN_OK;
}
size_t SimpleRingBuffer::getExcessBytes() const {
return excessBytes;
}
void SimpleRingBuffer::moveExcessBytesToStart() {
if(excessBytes > 0) {
std::memcpy(buffer, &buffer[size], excessBytes);
excessBytes = 0;
}
}
ReturnValue_t SimpleRingBuffer::deleteData(size_t amount,
bool deleteRemaining, size_t* trueAmount) {
size_t availableData = getAvailableReadData(READ_PTR);
if (availableData < amount) {
if (deleteRemaining) {
amount = availableData;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
if (trueAmount != nullptr) {
*trueAmount = amount;
}
incrementRead(amount, READ_PTR);
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,128 +1,128 @@
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#include "../container/RingBufferBase.h"
#include <cstddef>
/**
* @brief Circular buffer implementation, useful for buffering
* into data streams.
* @details
* Note that the deleteData() has to be called to increment the read pointer.
* This class allocated dynamically, so
* @ingroup containers
*/
class SimpleRingBuffer: public RingBufferBase<> {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
*
* @param size
* @param overwriteOld If the ring buffer is overflowing at a write
* operation, the oldest data will be overwritten.
* @param maxExcessBytes These additional bytes will be allocated in addtion
* to the specified size to accomodate contiguous write operations
* with getFreeElement.
*
*/
SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
* @param maxExcessBytes
* If the buffer can accomodate additional bytes for contigous write
* operations with getFreeElement, this is the maximum allowed additional
* size
*/
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
virtual ~SimpleRingBuffer();
/**
* Write to circular buffer and increment write pointer by amount.
* @param data
* @param amount
* @return -@c RETURN_OK if write operation was successfull
* -@c RETURN_FAILED if
*/
ReturnValue_t writeData(const uint8_t* data, size_t amount);
/**
* Returns a pointer to a free element. If the remaining buffer is
* not large enough, the data will be written past the actual size
* and the amount of excess bytes will be cached. This function
* does not increment the write pointer!
* @param writePointer Pointer to a pointer which can be used to write
* contiguous blocks into the ring buffer
* @param amount
* @return
*/
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
/**
* This increments the write pointer and also copies the excess bytes
* to the beginning. It should be called if the write operation
* conducted after calling getFreeElement() was performed.
* @return
*/
void confirmBytesWritten(size_t amount);
virtual size_t getExcessBytes() const;
/**
* Helper functions which moves any excess bytes to the start
* of the ring buffer.
* @return
*/
virtual void moveExcessBytesToStart();
/**
* Read from circular buffer at read pointer.
* @param data
* @param amount
* @param incrementReadPtr
* If this is set to true, the read pointer will be incremented.
* If readRemaining is set to true, the read pointer will be incremented
* accordingly.
* @param readRemaining
* If this is set to true, the data will be read even if the amount
* specified exceeds the read data available.
* @param trueAmount [out]
* If readRemaining was set to true, the true amount read will be assigned
* to the passed value.
* @return
* - @c RETURN_OK if data was read successfully
* - @c RETURN_FAILED if not enough data was available and readRemaining
* was set to false.
*/
ReturnValue_t readData(uint8_t* data, size_t amount,
bool incrementReadPtr = false, bool readRemaining = false,
size_t* trueAmount = nullptr);
/**
* Delete data by incrementing read pointer.
* @param amount
* @param deleteRemaining
* If the amount specified is larger than the remaing size to read and this
* is set to true, the remaining amount will be deleted as well
* @param trueAmount [out]
* If deleteRemaining was set to true, the amount deleted will be assigned
* to the passed value.
* @return
*/
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;
size_t maxExcessBytes;
size_t excessBytes = 0;
};
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */
#ifndef FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#define FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_
#include "../container/RingBufferBase.h"
#include <cstddef>
/**
* @brief Circular buffer implementation, useful for buffering
* into data streams.
* @details
* Note that the deleteData() has to be called to increment the read pointer.
* This class allocated dynamically, so
* @ingroup containers
*/
class SimpleRingBuffer: public RingBufferBase<> {
public:
/**
* This constructor allocates a new internal buffer with the supplied size.
*
* @param size
* @param overwriteOld If the ring buffer is overflowing at a write
* operation, the oldest data will be overwritten.
* @param maxExcessBytes These additional bytes will be allocated in addtion
* to the specified size to accomodate contiguous write operations
* with getFreeElement.
*
*/
SimpleRingBuffer(const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
/**
* This constructor takes an external buffer with the specified size.
* @param buffer
* @param size
* @param overwriteOld
* If the ring buffer is overflowing at a write operartion, the oldest data
* will be overwritten.
* @param maxExcessBytes
* If the buffer can accomodate additional bytes for contigous write
* operations with getFreeElement, this is the maximum allowed additional
* size
*/
SimpleRingBuffer(uint8_t* buffer, const size_t size, bool overwriteOld,
size_t maxExcessBytes = 0);
virtual ~SimpleRingBuffer();
/**
* Write to circular buffer and increment write pointer by amount.
* @param data
* @param amount
* @return -@c RETURN_OK if write operation was successfull
* -@c RETURN_FAILED if
*/
ReturnValue_t writeData(const uint8_t* data, size_t amount);
/**
* Returns a pointer to a free element. If the remaining buffer is
* not large enough, the data will be written past the actual size
* and the amount of excess bytes will be cached. This function
* does not increment the write pointer!
* @param writePointer Pointer to a pointer which can be used to write
* contiguous blocks into the ring buffer
* @param amount
* @return
*/
ReturnValue_t getFreeElement(uint8_t** writePointer, size_t amount);
/**
* This increments the write pointer and also copies the excess bytes
* to the beginning. It should be called if the write operation
* conducted after calling getFreeElement() was performed.
* @return
*/
void confirmBytesWritten(size_t amount);
virtual size_t getExcessBytes() const;
/**
* Helper functions which moves any excess bytes to the start
* of the ring buffer.
* @return
*/
virtual void moveExcessBytesToStart();
/**
* Read from circular buffer at read pointer.
* @param data
* @param amount
* @param incrementReadPtr
* If this is set to true, the read pointer will be incremented.
* If readRemaining is set to true, the read pointer will be incremented
* accordingly.
* @param readRemaining
* If this is set to true, the data will be read even if the amount
* specified exceeds the read data available.
* @param trueAmount [out]
* If readRemaining was set to true, the true amount read will be assigned
* to the passed value.
* @return
* - @c RETURN_OK if data was read successfully
* - @c RETURN_FAILED if not enough data was available and readRemaining
* was set to false.
*/
ReturnValue_t readData(uint8_t* data, size_t amount,
bool incrementReadPtr = false, bool readRemaining = false,
size_t* trueAmount = nullptr);
/**
* Delete data by incrementing read pointer.
* @param amount
* @param deleteRemaining
* If the amount specified is larger than the remaing size to read and this
* is set to true, the remaining amount will be deleted as well
* @param trueAmount [out]
* If deleteRemaining was set to true, the amount deleted will be assigned
* to the passed value.
* @return
*/
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;
size_t maxExcessBytes;
size_t excessBytes = 0;
};
#endif /* FRAMEWORK_CONTAINER_SIMPLERINGBUFFER_H_ */

File diff suppressed because it is too large Load Diff

View File

@ -1,117 +1,117 @@
#ifndef _sgp4unit_
#define _sgp4unit_
/* ----------------------------------------------------------------
*
* sgp4unit.h
*
* this file contains the sgp4 procedures for analytical propagation
* of a satellite. the code was originally released in the 1980 and 1986
* spacetrack papers. a detailed discussion of the theory and history
* may be found in the 2006 aiaa paper by vallado, crawford, hujsak,
* and kelso.
*
* companion code for
* fundamentals of astrodynamics and applications
* 2007
* by david vallado
*
* (w) 719-573-2600, email dvallado@agi.com
*
* current :
* 20 apr 07 david vallado
* misc fixes for constants
* changes :
* 11 aug 06 david vallado
* chg lyddane choice back to strn3, constants, misc doc
* 15 dec 05 david vallado
* misc fixes
* 26 jul 05 david vallado
* fixes for paper
* note that each fix is preceded by a
* comment with "sgp4fix" and an explanation of
* what was changed
* 10 aug 04 david vallado
* 2nd printing baseline working
* 14 may 01 david vallado
* 2nd edition baseline
* 80 norad
* original baseline
* ---------------------------------------------------------------- */
#include <math.h>
#include <stdio.h>
// -------------------------- structure declarations ----------------------------
typedef enum
{
wgs72old,
wgs72,
wgs84
} gravconsttype;
typedef struct elsetrec
{
long int satnum;
int epochyr, epochtynumrev;
int error;
char init, method;
/* Near Earth */
int isimp;
double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 ,
delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof ,
t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof ,
nodecf;
/* Deep Space */
int irez;
double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 ,
d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt ,
dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco ,
plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 ,
si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 ,
xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 ,
xl4 , xlamo , zmol , zmos , atime , xli , xni;
double a , altp , alta , epochdays, jdsatepoch , nddot , ndot ,
bstar , rcse , inclo , nodeo , ecco , argpo , mo ,
no;
} elsetrec;
// --------------------------- function declarations ----------------------------
int sgp4init
(
gravconsttype whichconst, const int satn, const double epoch,
const double xbstar, const double xecco, const double xargpo,
const double xinclo, const double xmo, const double xno,
const double xnodeo,
elsetrec& satrec
);
int sgp4
(
gravconsttype whichconst,
elsetrec& satrec, double tsince,
double r[], double v[]
);
double gstime
(
double
);
void getgravconst
(
gravconsttype,
double&,
double&,
double&,
double&,
double&,
double&,
double&,
double&
);
#endif
#ifndef _sgp4unit_
#define _sgp4unit_
/* ----------------------------------------------------------------
*
* sgp4unit.h
*
* this file contains the sgp4 procedures for analytical propagation
* of a satellite. the code was originally released in the 1980 and 1986
* spacetrack papers. a detailed discussion of the theory and history
* may be found in the 2006 aiaa paper by vallado, crawford, hujsak,
* and kelso.
*
* companion code for
* fundamentals of astrodynamics and applications
* 2007
* by david vallado
*
* (w) 719-573-2600, email dvallado@agi.com
*
* current :
* 20 apr 07 david vallado
* misc fixes for constants
* changes :
* 11 aug 06 david vallado
* chg lyddane choice back to strn3, constants, misc doc
* 15 dec 05 david vallado
* misc fixes
* 26 jul 05 david vallado
* fixes for paper
* note that each fix is preceded by a
* comment with "sgp4fix" and an explanation of
* what was changed
* 10 aug 04 david vallado
* 2nd printing baseline working
* 14 may 01 david vallado
* 2nd edition baseline
* 80 norad
* original baseline
* ---------------------------------------------------------------- */
#include <math.h>
#include <stdio.h>
// -------------------------- structure declarations ----------------------------
typedef enum
{
wgs72old,
wgs72,
wgs84
} gravconsttype;
typedef struct elsetrec
{
long int satnum;
int epochyr, epochtynumrev;
int error;
char init, method;
/* Near Earth */
int isimp;
double aycof , con41 , cc1 , cc4 , cc5 , d2 , d3 , d4 ,
delmo , eta , argpdot, omgcof , sinmao , t , t2cof, t3cof ,
t4cof , t5cof , x1mth2 , x7thm1 , mdot , nodedot, xlcof , xmcof ,
nodecf;
/* Deep Space */
int irez;
double d2201 , d2211 , d3210 , d3222 , d4410 , d4422 , d5220 , d5232 ,
d5421 , d5433 , dedt , del1 , del2 , del3 , didt , dmdt ,
dnodt , domdt , e3 , ee2 , peo , pgho , pho , pinco ,
plo , se2 , se3 , sgh2 , sgh3 , sgh4 , sh2 , sh3 ,
si2 , si3 , sl2 , sl3 , sl4 , gsto , xfact , xgh2 ,
xgh3 , xgh4 , xh2 , xh3 , xi2 , xi3 , xl2 , xl3 ,
xl4 , xlamo , zmol , zmos , atime , xli , xni;
double a , altp , alta , epochdays, jdsatepoch , nddot , ndot ,
bstar , rcse , inclo , nodeo , ecco , argpo , mo ,
no;
} elsetrec;
// --------------------------- function declarations ----------------------------
int sgp4init
(
gravconsttype whichconst, const int satn, const double epoch,
const double xbstar, const double xecco, const double xargpo,
const double xinclo, const double xmo, const double xno,
const double xnodeo,
elsetrec& satrec
);
int sgp4
(
gravconsttype whichconst,
elsetrec& satrec, double tsince,
double r[], double v[]
);
double gstime
(
double
);
void getgravconst
(
gravconsttype,
double&,
double&,
double&,
double&,
double&,
double&,
double&,
double&
);
#endif

View File

@ -1,140 +1,140 @@
#include "../subsystem/SubsystemBase.h"
#include "../controller/ControllerBase.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h"
#include "../action/HasActionsIF.h"
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId), hkSwitcher(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
ControllerBase::~ControllerBase() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
MessageQueueId_t ControllerBase::getCommandQueue() const {
return commandQueue->getId();
}
void ControllerBase::handleQueue() {
CommandMessage command;
ReturnValue_t result;
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == RETURN_OK) {
continue;
}
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
this->mode = mode;
this->submode = submode;
modeHelper.modeChanged(mode, submode);
modeChanged(mode, submode);
announceMode(false);
changeHK(this->mode, this->submode, true);
}
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode;
*submode = this->submode;
}
void ControllerBase::setToExternalControl() {
healthHelper.setHealth(EXTERNAL_CONTROL);
}
void ControllerBase::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
}
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
performControlOperation();
return RETURN_OK;
}
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
return;
}
ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:
case EXTERNAL_CONTROL:
healthHelper.setHealth(health);
return RETURN_OK;
default:
return INVALID_HEALTH_STATE;
}
}
HasHealthIF::HealthState ControllerBase::getHealth() {
return healthHelper.getHealth();
}
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_;
}
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() {
return HasReturnvaluesIF::RETURN_OK;
}
#include "../subsystem/SubsystemBase.h"
#include "../controller/ControllerBase.h"
#include "../subsystem/SubsystemBase.h"
#include "../ipc/QueueFactory.h"
#include "../action/HasActionsIF.h"
ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth) :
SystemObject(setObjectId), parentId(parentId), mode(MODE_OFF),
submode(SUBMODE_NONE), modeHelper(this),
healthHelper(this, setObjectId), hkSwitcher(this) {
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
ControllerBase::~ControllerBase() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t ControllerBase::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != RETURN_OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
result = healthHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
result = modeHelper.initialize(parentQueue);
if (result != RETURN_OK) {
return result;
}
result = hkSwitcher.initialize();
if (result != RETURN_OK) {
return result;
}
return RETURN_OK;
}
MessageQueueId_t ControllerBase::getCommandQueue() const {
return commandQueue->getId();
}
void ControllerBase::handleQueue() {
CommandMessage command;
ReturnValue_t result;
for (result = commandQueue->receiveMessage(&command); result == RETURN_OK;
result = commandQueue->receiveMessage(&command)) {
result = modeHelper.handleModeCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = healthHelper.handleHealthCommand(&command);
if (result == RETURN_OK) {
continue;
}
result = handleCommandMessage(&command);
if (result == RETURN_OK) {
continue;
}
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
void ControllerBase::startTransition(Mode_t mode, Submode_t submode) {
changeHK(this->mode, this->submode, false);
triggerEvent(CHANGING_MODE, mode, submode);
this->mode = mode;
this->submode = submode;
modeHelper.modeChanged(mode, submode);
modeChanged(mode, submode);
announceMode(false);
changeHK(this->mode, this->submode, true);
}
void ControllerBase::getMode(Mode_t* mode, Submode_t* submode) {
*mode = this->mode;
*submode = this->submode;
}
void ControllerBase::setToExternalControl() {
healthHelper.setHealth(EXTERNAL_CONTROL);
}
void ControllerBase::announceMode(bool recursive) {
triggerEvent(MODE_INFO, mode, submode);
}
ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
handleQueue();
hkSwitcher.performOperation();
performControlOperation();
return RETURN_OK;
}
void ControllerBase::modeChanged(Mode_t mode, Submode_t submode) {
return;
}
ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:
case EXTERNAL_CONTROL:
healthHelper.setHealth(health);
return RETURN_OK;
default:
return INVALID_HEALTH_STATE;
}
}
HasHealthIF::HealthState ControllerBase::getHealth() {
return healthHelper.getHealth();
}
void ControllerBase::setTaskIF(PeriodicTaskIF* task_){
executingTask = task_;
}
void ControllerBase::changeHK(Mode_t mode, Submode_t submode, bool enable) {
}
ReturnValue_t ControllerBase::initializeAfterTaskCreation() {
return HasReturnvaluesIF::RETURN_OK;
}

View File

@ -1,94 +1,94 @@
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../modes/HasModesIF.h"
#include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../datapool/HkSwitchHelper.h"
/**
* @brief Generic base class for controller classes
* @details
* Implements common interfaces for controllers.
*/
class ControllerBase: public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public SystemObject,
public HasReturnvaluesIF {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth = 3);
virtual ~ControllerBase();
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
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;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
/**
* Implemented by child class. Handle command messages which are not
* mode or health messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;
MessageQueueIF* commandQueue = nullptr;
ModeHelper modeHelper;
HealthHelper healthHelper;
HkSwitchHelper hkSwitcher;
/**
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.
*/
PeriodicTaskIF* executingTask = nullptr;
void handleQueue();
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);
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
};
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../modes/HasModesIF.h"
#include "../modes/ModeHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../datapool/HkSwitchHelper.h"
/**
* @brief Generic base class for controller classes
* @details
* Implements common interfaces for controllers.
*/
class ControllerBase: public HasModesIF,
public HasHealthIF,
public ExecutableObjectIF,
public SystemObject,
public HasReturnvaluesIF {
public:
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId,
size_t commandQueueDepth = 3);
virtual ~ControllerBase();
virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
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;
virtual ReturnValue_t initializeAfterTaskCreation() override;
protected:
/**
* Implemented by child class. Handle command messages which are not
* mode or health messages.
* @param message
* @return
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage *message) = 0;
virtual void performControlOperation() = 0;
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode) = 0;
const object_id_t parentId;
Mode_t mode;
Submode_t submode;
MessageQueueIF* commandQueue = nullptr;
ModeHelper modeHelper;
HealthHelper healthHelper;
HkSwitchHelper hkSwitcher;
/**
* Pointer to the task which executes this component,
* is invalid before setTaskIF was called.
*/
PeriodicTaskIF* executingTask = nullptr;
void handleQueue();
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);
virtual void changeHK(Mode_t mode, Submode_t submode, bool enable);
};
#endif /* FSFW_CONTROLLER_CONTROLLERBASE_H_ */

View File

@ -1,14 +1,14 @@
#include "../datapool/ControllerSet.h"
ControllerSet::ControllerSet() {
}
ControllerSet::~ControllerSet() {
}
void ControllerSet::setInvalid() {
read();
setToDefault();
commit(PoolVariableIF::INVALID);
}
#include "../datapool/ControllerSet.h"
ControllerSet::ControllerSet() {
}
ControllerSet::~ControllerSet() {
}
void ControllerSet::setInvalid() {
read();
setToDefault();
commit(PoolVariableIF::INVALID);
}

View File

@ -1,15 +1,15 @@
#ifndef CONTROLLERSET_H_
#define CONTROLLERSET_H_
#include "../datapoolglob/GlobalDataSet.h"
class ControllerSet :public GlobDataSet {
public:
ControllerSet();
virtual ~ControllerSet();
virtual void setToDefault() = 0;
void setInvalid();
};
#endif /* CONTROLLERSET_H_ */
#ifndef CONTROLLERSET_H_
#define CONTROLLERSET_H_
#include "../datapoolglob/GlobalDataSet.h"
class ControllerSet :public GlobDataSet {
public:
ControllerSet();
virtual ~ControllerSet();
virtual void setToDefault() = 0;
void setInvalid();
};
#endif /* CONTROLLERSET_H_ */

View File

@ -1,75 +1,75 @@
#include "../datapool/HkSwitchHelper.h"
#include "../ipc/QueueFactory.h"
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
commandActionHelper(this), eventProxy(eventProxy) {
actionQueue = QueueFactory::instance()->createMessageQueue();
}
HkSwitchHelper::~HkSwitchHelper() {
// TODO Auto-generated destructor stub
}
ReturnValue_t HkSwitchHelper::initialize() {
ReturnValue_t result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
CommandMessage command;
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
ReturnValue_t result = commandActionHelper.handleReply(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
command.setToUnknownCommand();
actionQueue->reply(&command);
}
return HasReturnvaluesIF::RETURN_OK;
}
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {
}
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data,
uint32_t size) {
}
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {
}
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
// ActionId_t action = HKService::DISABLE_HK;
// if (enable) {
// action = HKService::ENABLE_HK;
// }
//
// ReturnValue_t result = commandActionHelper.commandAction(
// objects::PUS_HK_SERVICE, action, sids);
//
// if (result != HasReturnvaluesIF::RETURN_OK) {
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
// }
// return result;
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() {
return actionQueue;
}
#include "../datapool/HkSwitchHelper.h"
#include "../ipc/QueueFactory.h"
HkSwitchHelper::HkSwitchHelper(EventReportingProxyIF* eventProxy) :
commandActionHelper(this), eventProxy(eventProxy) {
actionQueue = QueueFactory::instance()->createMessageQueue();
}
HkSwitchHelper::~HkSwitchHelper() {
// TODO Auto-generated destructor stub
}
ReturnValue_t HkSwitchHelper::initialize() {
ReturnValue_t result = commandActionHelper.initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return result;
}
ReturnValue_t HkSwitchHelper::performOperation(uint8_t operationCode) {
CommandMessage command;
while (actionQueue->receiveMessage(&command) == HasReturnvaluesIF::RETURN_OK) {
ReturnValue_t result = commandActionHelper.handleReply(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
continue;
}
command.setToUnknownCommand();
actionQueue->reply(&command);
}
return HasReturnvaluesIF::RETURN_OK;
}
void HkSwitchHelper::stepSuccessfulReceived(ActionId_t actionId, uint8_t step) {
}
void HkSwitchHelper::stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
void HkSwitchHelper::dataReceived(ActionId_t actionId, const uint8_t* data,
uint32_t size) {
}
void HkSwitchHelper::completionSuccessfulReceived(ActionId_t actionId) {
}
void HkSwitchHelper::completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode) {
eventProxy->forwardEvent(SWITCHING_TM_FAILED, returnCode, actionId);
}
ReturnValue_t HkSwitchHelper::switchHK(SerializeIF* sids, bool enable) {
// ActionId_t action = HKService::DISABLE_HK;
// if (enable) {
// action = HKService::ENABLE_HK;
// }
//
// ReturnValue_t result = commandActionHelper.commandAction(
// objects::PUS_HK_SERVICE, action, sids);
//
// if (result != HasReturnvaluesIF::RETURN_OK) {
// eventProxy->forwardEvent(SWITCHING_TM_FAILED, result);
// }
// return result;
return HasReturnvaluesIF::RETURN_OK;
}
MessageQueueIF* HkSwitchHelper::getCommandQueuePtr() {
return actionQueue;
}

View File

@ -1,46 +1,46 @@
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#include "../tasks/ExecutableObjectIF.h"
#include "../action/CommandsActionsIF.h"
#include "../events/EventReportingProxyIF.h"
//TODO this class violations separation between mission and framework
//but it is only a transitional solution until the Datapool is
//implemented decentrally
class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
HkSwitchHelper(EventReportingProxyIF *eventProxy);
virtual ~HkSwitchHelper();
ReturnValue_t initialize();
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
virtual void setTaskIF(PeriodicTaskIF* task_){};
protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode);
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
uint32_t size);
virtual void completionSuccessfulReceived(ActionId_t actionId);
virtual void completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode);
virtual MessageQueueIF* getCommandQueuePtr();
private:
CommandActionHelper commandActionHelper;
MessageQueueIF* actionQueue;
EventReportingProxyIF *eventProxy;
};
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */
#ifndef FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#define FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_
#include "../tasks/ExecutableObjectIF.h"
#include "../action/CommandsActionsIF.h"
#include "../events/EventReportingProxyIF.h"
//TODO this class violations separation between mission and framework
//but it is only a transitional solution until the Datapool is
//implemented decentrally
class HkSwitchHelper: public ExecutableObjectIF, public CommandsActionsIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::HK;
static const Event SWITCHING_TM_FAILED = MAKE_EVENT(1, SEVERITY::LOW); //!< Commanding the HK Service failed, p1: error code, p2 action: 0 disable / 1 enable
HkSwitchHelper(EventReportingProxyIF *eventProxy);
virtual ~HkSwitchHelper();
ReturnValue_t initialize();
virtual ReturnValue_t performOperation(uint8_t operationCode = 0);
ReturnValue_t switchHK(SerializeIF *sids, bool enable);
virtual void setTaskIF(PeriodicTaskIF* task_){};
protected:
virtual void stepSuccessfulReceived(ActionId_t actionId, uint8_t step);
virtual void stepFailedReceived(ActionId_t actionId, uint8_t step,
ReturnValue_t returnCode);
virtual void dataReceived(ActionId_t actionId, const uint8_t* data,
uint32_t size);
virtual void completionSuccessfulReceived(ActionId_t actionId);
virtual void completionFailedReceived(ActionId_t actionId,
ReturnValue_t returnCode);
virtual MessageQueueIF* getCommandQueuePtr();
private:
CommandActionHelper commandActionHelper;
MessageQueueIF* actionQueue;
EventReportingProxyIF *eventProxy;
};
#endif /* FRAMEWORK_DATAPOOL_HKSWITCHHELPER_H_ */

View File

@ -1,87 +1,87 @@
#include "../datapool/PoolEntry.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, uint8_t setLength,
bool setValid ) : length(setLength), valid(setValid) {
this->address = new T[this->length];
if(initValue.size() == 0) {
std::memset(this->address, 0, this->getByteSize());
}
else if (initValue.size() != setLength){
sif::warning << "PoolEntry: setLength is not equal to initializer list"
"length! Performing zero initialization with given setLength"
<< std::endl;
std::memset(this->address, 0, this->getByteSize());
}
else {
std::copy(initValue.begin(), initValue.end(), this->address);
}
}
template <typename T>
PoolEntry<T>::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) :
length(setLength), valid(setValid) {
this->address = new T[this->length];
if (initValue != nullptr) {
std::memcpy(this->address, initValue, this->getByteSize() );
} else {
std::memset(this->address, 0, this->getByteSize() );
}
}
//As the data pool is global, this dtor is only be called on program exit.
//Warning! Never copy pool entries!
template <typename T>
PoolEntry<T>::~PoolEntry() {
delete[] this->address;
}
template <typename T>
uint16_t PoolEntry<T>::getByteSize() {
return ( sizeof(T) * this->length );
}
template <typename T>
uint8_t PoolEntry<T>::getSize() {
return this->length;
}
template <typename T>
void* PoolEntry<T>::getRawData() {
return this->address;
}
template <typename T>
void PoolEntry<T>::setValid(bool isValid) {
this->valid = isValid;
}
template <typename T>
bool PoolEntry<T>::getValid() {
return valid;
}
template <typename T>
void PoolEntry<T>::print() {
sif::debug << "Pool Entry Validity: " <<
(this->valid? " (valid) " : " (invalid) ") << std::endl;
arrayprinter::print(reinterpret_cast<uint8_t*>(address), length);
sif::debug << std::dec << std::endl;
}
template<typename T>
Type PoolEntry<T>::getType() {
return PodTypeConversion<T>::type;
}
template class PoolEntry<uint8_t>;
template class PoolEntry<uint16_t>;
template class PoolEntry<uint32_t>;
template class PoolEntry<int8_t>;
template class PoolEntry<int16_t>;
template class PoolEntry<int32_t>;
template class PoolEntry<float>;
template class PoolEntry<double>;
#include "../datapool/PoolEntry.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
template <typename T>
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValue, uint8_t setLength,
bool setValid ) : length(setLength), valid(setValid) {
this->address = new T[this->length];
if(initValue.size() == 0) {
std::memset(this->address, 0, this->getByteSize());
}
else if (initValue.size() != setLength){
sif::warning << "PoolEntry: setLength is not equal to initializer list"
"length! Performing zero initialization with given setLength"
<< std::endl;
std::memset(this->address, 0, this->getByteSize());
}
else {
std::copy(initValue.begin(), initValue.end(), this->address);
}
}
template <typename T>
PoolEntry<T>::PoolEntry( T* initValue, uint8_t setLength, bool setValid ) :
length(setLength), valid(setValid) {
this->address = new T[this->length];
if (initValue != nullptr) {
std::memcpy(this->address, initValue, this->getByteSize() );
} else {
std::memset(this->address, 0, this->getByteSize() );
}
}
//As the data pool is global, this dtor is only be called on program exit.
//Warning! Never copy pool entries!
template <typename T>
PoolEntry<T>::~PoolEntry() {
delete[] this->address;
}
template <typename T>
uint16_t PoolEntry<T>::getByteSize() {
return ( sizeof(T) * this->length );
}
template <typename T>
uint8_t PoolEntry<T>::getSize() {
return this->length;
}
template <typename T>
void* PoolEntry<T>::getRawData() {
return this->address;
}
template <typename T>
void PoolEntry<T>::setValid(bool isValid) {
this->valid = isValid;
}
template <typename T>
bool PoolEntry<T>::getValid() {
return valid;
}
template <typename T>
void PoolEntry<T>::print() {
sif::debug << "Pool Entry Validity: " <<
(this->valid? " (valid) " : " (invalid) ") << std::endl;
arrayprinter::print(reinterpret_cast<uint8_t*>(address), length);
sif::debug << std::dec << std::endl;
}
template<typename T>
Type PoolEntry<T>::getType() {
return PodTypeConversion<T>::type;
}
template class PoolEntry<uint8_t>;
template class PoolEntry<uint16_t>;
template class PoolEntry<uint32_t>;
template class PoolEntry<int8_t>;
template class PoolEntry<int16_t>;
template class PoolEntry<int32_t>;
template class PoolEntry<float>;
template class PoolEntry<double>;

View File

@ -1,130 +1,130 @@
#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_
#define FRAMEWORK_DATAPOOL_POOLENTRY_H_
#include "../datapool/PoolEntryIF.h"
#include <initializer_list>
#include <type_traits>
#include <cstddef>
/**
* @brief This is a small helper class that defines a single data pool entry.
* @details
* The helper is used to store all information together with the data as a
* single data pool entry. The content's type is defined by the template
* argument.
*
* It is prepared for use with plain old data types, but may be
* extended to complex types if necessary. It can be initialized with a
* certain value, size and validity flag.
*
* It holds a pointer to the real data and offers methods to access this data
* and to acquire additional information (such as validity and array/byte size).
* It is NOT intended to be used outside DataPool implementations as it performs
* dynamic memory allocation.
*
* @ingroup data_pool
*/
template <typename T>
class PoolEntry : public PoolEntryIF {
public:
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "
"uint8_t");
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential init values are copied to that space.
* @details
* Not passing any arguments will initialize an non-array pool entry
* (setLength = 1) with an initial invalid state.
* Please note that if an initializer list is passed, the correct
* corresponding length should be passed too, otherwise a zero
* initialization will be performed with the given setLength.
* @param initValue
* Initializer list with values to initialize with, for example {0,0} to
* initialize the two entries to zero.
* @param setLength
* Defines the array length of this entry. Should be equal to the
* intializer list length.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(std::initializer_list<T> initValue = {}, uint8_t setLength = 1,
bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential init values are copied to that space.
* @param initValue
* A pointer to the single value or array that holds the init value.
* With the default value (nullptr), the entry is initalized with all 0.
* @param setLength
* Defines the array length of this entry.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
//! Explicitely deleted copy ctor, copying is not allowed!
PoolEntry(const PoolEntry&) = delete;
//! Explicitely deleted copy assignment, copying is not allowed!
PoolEntry& operator=(const PoolEntry&) = delete;
/**
* @brief The allocated memory for the variable is freed
* in the destructor.
* @details
* As the data pool is global, this dtor is only called on program exit.
* PoolEntries shall never be copied, as a copy might delete the variable
* on the heap.
*/
~PoolEntry();
/**
* @brief This is the address pointing to the allocated memory.
*/
T* address;
/**
* @brief This attribute stores the length information.
*/
uint8_t length;
/**
* @brief Here, the validity information for a variable is stored.
* Every entry (single variable or vector) has one valid flag.
*/
uint8_t valid;
/**
* @brief getSize returns the array size of the entry.
* @details A single parameter has size 1.
*/
uint8_t getSize();
/**
* @brief This operation returns the size in bytes.
* @details The size is calculated by sizeof(type) * array_size.
*/
uint16_t getByteSize();
/**
* @brief This operation returns a the address pointer casted to void*.
*/
void* getRawData();
/**
* @brief This method allows to set the valid information
* of the pool entry.
*/
void setValid( bool isValid );
/**
* @brief This method allows to get the valid information
* of the pool entry.
*/
bool getValid();
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.
*/
void print();
Type getType();
};
#endif /* POOLENTRY_H_ */
#ifndef FRAMEWORK_DATAPOOL_POOLENTRY_H_
#define FRAMEWORK_DATAPOOL_POOLENTRY_H_
#include "../datapool/PoolEntryIF.h"
#include <initializer_list>
#include <type_traits>
#include <cstddef>
/**
* @brief This is a small helper class that defines a single data pool entry.
* @details
* The helper is used to store all information together with the data as a
* single data pool entry. The content's type is defined by the template
* argument.
*
* It is prepared for use with plain old data types, but may be
* extended to complex types if necessary. It can be initialized with a
* certain value, size and validity flag.
*
* It holds a pointer to the real data and offers methods to access this data
* and to acquire additional information (such as validity and array/byte size).
* It is NOT intended to be used outside DataPool implementations as it performs
* dynamic memory allocation.
*
* @ingroup data_pool
*/
template <typename T>
class PoolEntry : public PoolEntryIF {
public:
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t "
"instead! The ECSS standard defines a boolean as a one bit "
"field. Therefore it is preferred to store a boolean as an "
"uint8_t");
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential init values are copied to that space.
* @details
* Not passing any arguments will initialize an non-array pool entry
* (setLength = 1) with an initial invalid state.
* Please note that if an initializer list is passed, the correct
* corresponding length should be passed too, otherwise a zero
* initialization will be performed with the given setLength.
* @param initValue
* Initializer list with values to initialize with, for example {0,0} to
* initialize the two entries to zero.
* @param setLength
* Defines the array length of this entry. Should be equal to the
* intializer list length.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(std::initializer_list<T> initValue = {}, uint8_t setLength = 1,
bool setValid = false);
/**
* @brief In the classe's constructor, space is allocated on the heap and
* potential init values are copied to that space.
* @param initValue
* A pointer to the single value or array that holds the init value.
* With the default value (nullptr), the entry is initalized with all 0.
* @param setLength
* Defines the array length of this entry.
* @param setValid
* Sets the initialization flag. It is invalid by default.
*/
PoolEntry(T* initValue, uint8_t setLength = 1, bool setValid = false);
//! Explicitely deleted copy ctor, copying is not allowed!
PoolEntry(const PoolEntry&) = delete;
//! Explicitely deleted copy assignment, copying is not allowed!
PoolEntry& operator=(const PoolEntry&) = delete;
/**
* @brief The allocated memory for the variable is freed
* in the destructor.
* @details
* As the data pool is global, this dtor is only called on program exit.
* PoolEntries shall never be copied, as a copy might delete the variable
* on the heap.
*/
~PoolEntry();
/**
* @brief This is the address pointing to the allocated memory.
*/
T* address;
/**
* @brief This attribute stores the length information.
*/
uint8_t length;
/**
* @brief Here, the validity information for a variable is stored.
* Every entry (single variable or vector) has one valid flag.
*/
uint8_t valid;
/**
* @brief getSize returns the array size of the entry.
* @details A single parameter has size 1.
*/
uint8_t getSize();
/**
* @brief This operation returns the size in bytes.
* @details The size is calculated by sizeof(type) * array_size.
*/
uint16_t getByteSize();
/**
* @brief This operation returns a the address pointer casted to void*.
*/
void* getRawData();
/**
* @brief This method allows to set the valid information
* of the pool entry.
*/
void setValid( bool isValid );
/**
* @brief This method allows to get the valid information
* of the pool entry.
*/
bool getValid();
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.
*/
void print();
Type getType();
};
#endif /* POOLENTRY_H_ */

View File

@ -1,63 +1,63 @@
#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
#include "../globalfunctions/Type.h"
#include <cstdint>
/**
* @brief This interface defines the access possibilities to a
* single data pool entry.
* @details
* The interface provides methods to determine the size and the validity
* information of a value. It also defines a method to receive a pointer to the
* raw data content. It is mainly used by DataPool itself, but also as a
* return pointer.
*
* @author Bastian Baetz
* @ingroup data_pool
*
*/
class PoolEntryIF {
public:
/**
* @brief This is an empty virtual destructor,
* as it is required for C++ interfaces.
*/
virtual ~PoolEntryIF() {
}
/**
* @brief getSize returns the array size of the entry.
* A single variable parameter has size 1.
*/
virtual uint8_t getSize() = 0;
/**
* @brief This operation returns the size in bytes, which is calculated by
* sizeof(type) * array_size.
*/
virtual uint16_t getByteSize() = 0;
/**
* @brief This operation returns a the address pointer casted to void*.
*/
virtual void* getRawData() = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual void setValid(bool isValid) = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual bool getValid() = 0;
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.
* @details
* Also displays whether the pool entry is valid or invalid.
*/
virtual void print() = 0;
/**
* Returns the type of the entry.
*/
virtual Type getType() = 0;
};
#endif /* POOLENTRYIF_H_ */
#ifndef FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
#define FRAMEWORK_DATAPOOL_POOLENTRYIF_H_
#include "../globalfunctions/Type.h"
#include <cstdint>
/**
* @brief This interface defines the access possibilities to a
* single data pool entry.
* @details
* The interface provides methods to determine the size and the validity
* information of a value. It also defines a method to receive a pointer to the
* raw data content. It is mainly used by DataPool itself, but also as a
* return pointer.
*
* @author Bastian Baetz
* @ingroup data_pool
*
*/
class PoolEntryIF {
public:
/**
* @brief This is an empty virtual destructor,
* as it is required for C++ interfaces.
*/
virtual ~PoolEntryIF() {
}
/**
* @brief getSize returns the array size of the entry.
* A single variable parameter has size 1.
*/
virtual uint8_t getSize() = 0;
/**
* @brief This operation returns the size in bytes, which is calculated by
* sizeof(type) * array_size.
*/
virtual uint16_t getByteSize() = 0;
/**
* @brief This operation returns a the address pointer casted to void*.
*/
virtual void* getRawData() = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual void setValid(bool isValid) = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual bool getValid() = 0;
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.
* @details
* Also displays whether the pool entry is valid or invalid.
*/
virtual void print() = 0;
/**
* Returns the type of the entry.
*/
virtual Type getType() = 0;
};
#endif /* POOLENTRYIF_H_ */

View File

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

View File

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

View File

@ -1,28 +1,28 @@
#ifndef POOLVARLIST_H_
#define POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h"
template <class T, uint8_t n_var>
class PoolVarList {
private:
GlobPoolVar<T> variables[n_var];
public:
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;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].dataPoolId = set_id[count];
variables[count].readWriteMode = setReadWriteMode;
dataSet->registerVariable(&variables[count]);
}
}
GlobPoolVar<T> &operator [](int i) { return variables[i]; }
};
#endif /* POOLVARLIST_H_ */
#ifndef POOLVARLIST_H_
#define POOLVARLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/GlobalPoolVariable.h"
template <class T, uint8_t n_var>
class PoolVarList {
private:
GlobPoolVar<T> variables[n_var];
public:
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;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].dataPoolId = set_id[count];
variables[count].readWriteMode = setReadWriteMode;
dataSet->registerVariable(&variables[count]);
}
}
GlobPoolVar<T> &operator [](int i) { return variables[i]; }
};
#endif /* POOLVARLIST_H_ */

View File

@ -1,300 +1,300 @@
#include "../datapoolglob/DataPoolAdmin.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../ipc/CommandMessage.h"
#include "../ipc/QueueFactory.h"
#include "../parameters/ParameterMessage.h"
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
this, NULL), actionHelper(this, NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue();
}
DataPoolAdmin::~DataPoolAdmin() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
handleCommand();
return RETURN_OK;
}
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
return commandQueue->getId();
}
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
if (actionId != SET_VALIDITY) {
return INVALID_ACTION_ID;
}
if (size != 5) {
return INVALID_PARAMETERS;
}
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
| data[3];
uint8_t valid = data[4];
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
GlobDataSet mySet;
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
ReturnValue_t status = mySet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
if (valid != 0) {
variable.setValid(PoolVariableIF::VALID);
} else {
variable.setValid(PoolVariableIF::INVALID);
}
mySet.commit();
return EXECUTION_FINISHED;
}
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
return HasReturnvaluesIF::RETURN_FAILED;
}
void DataPoolAdmin::handleCommand() {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = handleParameterCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = memoryHelper.handleMemoryCommand(&command);
if (result != RETURN_OK) {
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
const uint8_t* data, size_t size, uint8_t** dataPointer) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size % typeSize != 0) {
return INVALID_SIZE;
}
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
const uint8_t* readPosition = data;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ_WRITE);
status = rawSet.read();
if (status == RETURN_OK) {
status = variable.setEntryFromBigEndian(readPosition, typeSize);
if (status == RETURN_OK) {
status = rawSet.commit();
}
}
arrayIndex += 1;
readPosition += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
uint8_t* ptrToCopy = copyHere;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ);
status = rawSet.read();
if (status == RETURN_OK) {
size_t temp = 0;
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
if (status != RETURN_OK) {
return RETURN_FAILED;
}
} else {
//Error reading parameter.
}
arrayIndex += 1;
ptrToCopy += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = memoryHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (storage == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
result = actionHelper.initialize(commandQueue);
return result;
}
//mostly identical to ParameterHelper::handleParameterMessage()
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
switch (command->getCommand()) {
case ParameterMessage::CMD_PARAMETER_DUMP: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
DataPoolParameterWrapper wrapper;
result = wrapper.set(domain, parameterId);
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &wrapper);
}
}
break;
case ParameterMessage::CMD_PARAMETER_LOAD: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
uint8_t index = HasParametersIF::getIndex(
ParameterMessage::getParameterId(command));
const uint8_t *storedStream;
size_t storedStreamSize;
result = storage->getData(ParameterMessage::getStoreId(command),
&storedStream, &storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
break;
}
ParameterWrapper streamWrapper;
result = streamWrapper.set(storedStream, storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
DataPoolParameterWrapper poolWrapper;
result = poolWrapper.set(domain, parameterId);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
result = poolWrapper.copyFrom(&streamWrapper, index);
storage->deleteData(ParameterMessage::getStoreId(command));
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &poolWrapper);
}
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
if (result != HasReturnvaluesIF::RETURN_OK) {
rejectCommand(command->getSender(), result, command->getCommand());
}
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::sendParameter()
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper) {
size_t serializedSize = wrapper->getSerializedSize();
uint8_t *storeElement;
store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
&storeElement);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t storeElementSize = 0;
result = wrapper->serialize(&storeElement, &storeElementSize,
serializedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(address);
return result;
}
CommandMessage reply;
ParameterMessage::setParameterDumpReply(&reply, id, address);
commandQueue->sendMessage(to, &reply);
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::rejectCommand()
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand) {
CommandMessage reply;
reply.setReplyRejected(reason, initialCommand);
commandQueue->sendMessage(to, &reply);
}
#include "../datapoolglob/DataPoolAdmin.h"
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../ipc/CommandMessage.h"
#include "../ipc/QueueFactory.h"
#include "../parameters/ParameterMessage.h"
DataPoolAdmin::DataPoolAdmin(object_id_t objectId) :
SystemObject(objectId), storage(NULL), commandQueue(NULL), memoryHelper(
this, NULL), actionHelper(this, NULL) {
commandQueue = QueueFactory::instance()->createMessageQueue();
}
DataPoolAdmin::~DataPoolAdmin() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t DataPoolAdmin::performOperation(uint8_t opCode) {
handleCommand();
return RETURN_OK;
}
MessageQueueId_t DataPoolAdmin::getCommandQueue() const {
return commandQueue->getId();
}
ReturnValue_t DataPoolAdmin::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size) {
if (actionId != SET_VALIDITY) {
return INVALID_ACTION_ID;
}
if (size != 5) {
return INVALID_PARAMETERS;
}
uint32_t address = (data[0] << 24) | (data[1] << 16) | (data[2] << 8)
| data[3];
uint8_t valid = data[4];
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
GlobDataSet mySet;
PoolRawAccess variable(poolId, 0, &mySet, PoolVariableIF::VAR_READ_WRITE);
ReturnValue_t status = mySet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
if (valid != 0) {
variable.setValid(PoolVariableIF::VALID);
} else {
variable.setValid(PoolVariableIF::INVALID);
}
mySet.commit();
return EXECUTION_FINISHED;
}
ReturnValue_t DataPoolAdmin::getParameter(uint8_t domainId,
uint16_t parameterId, ParameterWrapper* parameterWrapper,
const ParameterWrapper* newValues, uint16_t startAtIndex) {
return HasReturnvaluesIF::RETURN_FAILED;
}
void DataPoolAdmin::handleCommand() {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result != RETURN_OK) {
return;
}
result = actionHelper.handleActionMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = handleParameterCommand(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
return;
}
result = memoryHelper.handleMemoryCommand(&command);
if (result != RETURN_OK) {
command.setToUnknownCommand();
commandQueue->reply(&command);
}
}
ReturnValue_t DataPoolAdmin::handleMemoryLoad(uint32_t address,
const uint8_t* data, size_t size, uint8_t** dataPointer) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size % typeSize != 0) {
return INVALID_SIZE;
}
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
const uint8_t* readPosition = data;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ_WRITE);
status = rawSet.read();
if (status == RETURN_OK) {
status = variable.setEntryFromBigEndian(readPosition, typeSize);
if (status == RETURN_OK) {
status = rawSet.commit();
}
}
arrayIndex += 1;
readPosition += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere) {
uint32_t poolId = glob::dataPool.PIDToDataPoolId(address);
uint8_t arrayIndex = glob::dataPool.PIDToArrayIndex(address);
GlobDataSet testSet;
PoolRawAccess varToGetSize(poolId, arrayIndex, &testSet,
PoolVariableIF::VAR_READ);
ReturnValue_t status = testSet.read();
if (status != RETURN_OK) {
return INVALID_ADDRESS;
}
uint8_t typeSize = varToGetSize.getSizeOfType();
if (size > varToGetSize.getSizeTillEnd()) {
return INVALID_SIZE;
}
uint8_t* ptrToCopy = copyHere;
for (; size > 0; size -= typeSize) {
GlobDataSet rawSet;
PoolRawAccess variable(poolId, arrayIndex, &rawSet,
PoolVariableIF::VAR_READ);
status = rawSet.read();
if (status == RETURN_OK) {
size_t temp = 0;
status = variable.getEntryEndianSafe(ptrToCopy, &temp, size);
if (status != RETURN_OK) {
return RETURN_FAILED;
}
} else {
//Error reading parameter.
}
arrayIndex += 1;
ptrToCopy += typeSize;
}
return ACTIVITY_COMPLETED;
}
ReturnValue_t DataPoolAdmin::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = memoryHelper.initialize(commandQueue);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
storage = objectManager->get<StorageManagerIF>(objects::IPC_STORE);
if (storage == NULL) {
return HasReturnvaluesIF::RETURN_FAILED;
}
result = actionHelper.initialize(commandQueue);
return result;
}
//mostly identical to ParameterHelper::handleParameterMessage()
ReturnValue_t DataPoolAdmin::handleParameterCommand(CommandMessage* command) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
switch (command->getCommand()) {
case ParameterMessage::CMD_PARAMETER_DUMP: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
DataPoolParameterWrapper wrapper;
result = wrapper.set(domain, parameterId);
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &wrapper);
}
}
break;
case ParameterMessage::CMD_PARAMETER_LOAD: {
uint8_t domain = HasParametersIF::getDomain(
ParameterMessage::getParameterId(command));
uint16_t parameterId = HasParametersIF::getMatrixId(
ParameterMessage::getParameterId(command));
uint8_t index = HasParametersIF::getIndex(
ParameterMessage::getParameterId(command));
const uint8_t *storedStream;
size_t storedStreamSize;
result = storage->getData(ParameterMessage::getStoreId(command),
&storedStream, &storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
break;
}
ParameterWrapper streamWrapper;
result = streamWrapper.set(storedStream, storedStreamSize);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
DataPoolParameterWrapper poolWrapper;
result = poolWrapper.set(domain, parameterId);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(ParameterMessage::getStoreId(command));
break;
}
result = poolWrapper.copyFrom(&streamWrapper, index);
storage->deleteData(ParameterMessage::getStoreId(command));
if (result == HasReturnvaluesIF::RETURN_OK) {
result = sendParameter(command->getSender(),
ParameterMessage::getParameterId(command), &poolWrapper);
}
}
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
if (result != HasReturnvaluesIF::RETURN_OK) {
rejectCommand(command->getSender(), result, command->getCommand());
}
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::sendParameter()
ReturnValue_t DataPoolAdmin::sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper) {
size_t serializedSize = wrapper->getSerializedSize();
uint8_t *storeElement;
store_address_t address;
ReturnValue_t result = storage->getFreeElement(&address, serializedSize,
&storeElement);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
size_t storeElementSize = 0;
result = wrapper->serialize(&storeElement, &storeElementSize,
serializedSize, SerializeIF::Endianness::BIG);
if (result != HasReturnvaluesIF::RETURN_OK) {
storage->deleteData(address);
return result;
}
CommandMessage reply;
ParameterMessage::setParameterDumpReply(&reply, id, address);
commandQueue->sendMessage(to, &reply);
return HasReturnvaluesIF::RETURN_OK;
}
//identical to ParameterHelper::rejectCommand()
void DataPoolAdmin::rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand) {
CommandMessage reply;
reply.setReplyRejected(reason, initialCommand);
commandQueue->sendMessage(to, &reply);
}

View File

@ -1,59 +1,59 @@
#ifndef DATAPOOLADMIN_H_
#define DATAPOOLADMIN_H_
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../action/HasActionsIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../parameters/ReceivesParameterMessagesIF.h"
#include "../memory/MemoryHelper.h"
#include "../action/SimpleActionHelper.h"
#include "../datapoolglob/DataPoolParameterWrapper.h"
class DataPoolAdmin: public HasActionsIF,
public ExecutableObjectIF,
public AcceptsMemoryMessagesIF,
public HasReturnvaluesIF,
public ReceivesParameterMessagesIF,
public SystemObject {
public:
static const ActionId_t SET_VALIDITY = 1;
DataPoolAdmin(object_id_t objectId);
~DataPoolAdmin();
ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
size_t size, uint8_t** dataPointer);
ReturnValue_t handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere);
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
//not implemented as ParameterHelper is no used
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ReturnValue_t initialize();
private:
StorageManagerIF *storage;
MessageQueueIF* commandQueue;
MemoryHelper memoryHelper;
SimpleActionHelper actionHelper;
void handleCommand();
ReturnValue_t handleParameterCommand(CommandMessage *command);
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper);
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand);
};
#endif /* DATAPOOLADMIN_H_ */
#ifndef DATAPOOLADMIN_H_
#define DATAPOOLADMIN_H_
#include "../objectmanager/SystemObject.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../action/HasActionsIF.h"
#include "../ipc/MessageQueueIF.h"
#include "../parameters/ReceivesParameterMessagesIF.h"
#include "../memory/MemoryHelper.h"
#include "../action/SimpleActionHelper.h"
#include "../datapoolglob/DataPoolParameterWrapper.h"
class DataPoolAdmin: public HasActionsIF,
public ExecutableObjectIF,
public AcceptsMemoryMessagesIF,
public HasReturnvaluesIF,
public ReceivesParameterMessagesIF,
public SystemObject {
public:
static const ActionId_t SET_VALIDITY = 1;
DataPoolAdmin(object_id_t objectId);
~DataPoolAdmin();
ReturnValue_t performOperation(uint8_t opCode);
MessageQueueId_t getCommandQueue() const;
ReturnValue_t handleMemoryLoad(uint32_t address, const uint8_t* data,
size_t size, uint8_t** dataPointer);
ReturnValue_t handleMemoryDump(uint32_t address, size_t size,
uint8_t** dataPointer, uint8_t* copyHere);
ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, size_t size);
//not implemented as ParameterHelper is no used
ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
ReturnValue_t initialize();
private:
StorageManagerIF *storage;
MessageQueueIF* commandQueue;
MemoryHelper memoryHelper;
SimpleActionHelper actionHelper;
void handleCommand();
ReturnValue_t handleParameterCommand(CommandMessage *command);
ReturnValue_t sendParameter(MessageQueueId_t to, uint32_t id,
const DataPoolParameterWrapper* wrapper);
void rejectCommand(MessageQueueId_t to, ReturnValue_t reason,
Command_t initialCommand);
};
#endif /* DATAPOOLADMIN_H_ */

View File

@ -1,179 +1,179 @@
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/DataPoolParameterWrapper.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../parameters/HasParametersIF.h"
DataPoolParameterWrapper::DataPoolParameterWrapper() :
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
PoolVariableIF::NO_PARAMETER) {
}
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
}
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
uint16_t parameterId) {
poolId = (domainId << 16) + parameterId;
GlobDataSet mySet;
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
ReturnValue_t status = mySet.read();
if (status != HasReturnvaluesIF::RETURN_OK) {
//should only fail for invalid pool id
return HasParametersIF::INVALID_MATRIX_ID;
}
type = raw.getType();
rows = raw.getArraySize();
columns = 1;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result;
result = SerializeAdapter::serialize(&type, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&columns, buffer, size,
maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&rows, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
for (uint8_t index = 0; index < rows; index++){
GlobDataSet mySet;
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
mySet.read();
result = raw.serialize(buffer,size,maxSize,streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK){
return result;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
//same as ParameterWrapper
size_t DataPoolParameterWrapper::getSerializedSize() const {
size_t serializedSize = 0;
serializedSize += type.getSerializedSize();
serializedSize += sizeof(rows);
serializedSize += sizeof(columns);
serializedSize += rows * columns * type.getSize();
return serializedSize;
}
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) {
return HasReturnvaluesIF::RETURN_FAILED;
}
template<typename T>
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
uint8_t startingColumn, const void* from, uint8_t fromRows) {
//treat from as a continuous Stream as we copy all of it
const uint8_t *fromAsStream = (const uint8_t *) from;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
GlobDataSet mySet;
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
fromAsStream += sizeof(T);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
mySet.commit();
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
uint16_t startWritingAtIndex) {
if (poolId == PoolVariableIF::NO_PARAMETER) {
return ParameterWrapper::NOT_SET;
}
if (type != from->type) {
return ParameterWrapper::DATATYPE_MISSMATCH;
}
//check if from fits into this
uint8_t startingRow = startWritingAtIndex / columns;
uint8_t startingColumn = startWritingAtIndex % columns;
if ((from->rows > (rows - startingRow))
|| (from->columns > (columns - startingColumn))) {
return ParameterWrapper::TOO_BIG;
}
ReturnValue_t result;
//copy data
if (from->pointsToStream) {
switch (type) {
case Type::UINT8_T:
result = deSerializeData<uint8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT8_T:
result = deSerializeData<int8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT16_T:
result = deSerializeData<uint16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT16_T:
result = deSerializeData<int16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT32_T:
result = deSerializeData<uint32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT32_T:
result = deSerializeData<int32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::FLOAT:
result = deSerializeData<float>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::DOUBLE:
result = deSerializeData<double>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
default:
result = ParameterWrapper::UNKNOW_DATATYPE;
break;
}
} else {
//not supported
return HasReturnvaluesIF::RETURN_FAILED;
}
return result;
}
#include "../datapoolglob/GlobalDataSet.h"
#include "../datapoolglob/DataPoolParameterWrapper.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../parameters/HasParametersIF.h"
DataPoolParameterWrapper::DataPoolParameterWrapper() :
type(Type::UNKNOWN_TYPE), rows(0), columns(0), poolId(
PoolVariableIF::NO_PARAMETER) {
}
DataPoolParameterWrapper::~DataPoolParameterWrapper() {
}
ReturnValue_t DataPoolParameterWrapper::set(uint8_t domainId,
uint16_t parameterId) {
poolId = (domainId << 16) + parameterId;
GlobDataSet mySet;
PoolRawAccess raw(poolId, 0, &mySet, PoolVariableIF::VAR_READ);
ReturnValue_t status = mySet.read();
if (status != HasReturnvaluesIF::RETURN_OK) {
//should only fail for invalid pool id
return HasParametersIF::INVALID_MATRIX_ID;
}
type = raw.getType();
rows = raw.getArraySize();
columns = 1;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result;
result = SerializeAdapter::serialize(&type, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&columns, buffer, size,
maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&rows, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
for (uint8_t index = 0; index < rows; index++){
GlobDataSet mySet;
PoolRawAccess raw(poolId, index, &mySet,PoolVariableIF::VAR_READ);
mySet.read();
result = raw.serialize(buffer,size,maxSize,streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK){
return result;
}
}
return HasReturnvaluesIF::RETURN_OK;
}
//same as ParameterWrapper
size_t DataPoolParameterWrapper::getSerializedSize() const {
size_t serializedSize = 0;
serializedSize += type.getSerializedSize();
serializedSize += sizeof(rows);
serializedSize += sizeof(columns);
serializedSize += rows * columns * type.getSize();
return serializedSize;
}
ReturnValue_t DataPoolParameterWrapper::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) {
return HasReturnvaluesIF::RETURN_FAILED;
}
template<typename T>
ReturnValue_t DataPoolParameterWrapper::deSerializeData(uint8_t startingRow,
uint8_t startingColumn, const void* from, uint8_t fromRows) {
//treat from as a continuous Stream as we copy all of it
const uint8_t *fromAsStream = (const uint8_t *) from;
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
for (uint8_t fromRow = 0; fromRow < fromRows; fromRow++) {
GlobDataSet mySet;
PoolRawAccess raw(poolId, startingRow + fromRow, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
result = raw.setEntryFromBigEndian(fromAsStream, sizeof(T));
fromAsStream += sizeof(T);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
mySet.commit();
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t DataPoolParameterWrapper::copyFrom(const ParameterWrapper* from,
uint16_t startWritingAtIndex) {
if (poolId == PoolVariableIF::NO_PARAMETER) {
return ParameterWrapper::NOT_SET;
}
if (type != from->type) {
return ParameterWrapper::DATATYPE_MISSMATCH;
}
//check if from fits into this
uint8_t startingRow = startWritingAtIndex / columns;
uint8_t startingColumn = startWritingAtIndex % columns;
if ((from->rows > (rows - startingRow))
|| (from->columns > (columns - startingColumn))) {
return ParameterWrapper::TOO_BIG;
}
ReturnValue_t result;
//copy data
if (from->pointsToStream) {
switch (type) {
case Type::UINT8_T:
result = deSerializeData<uint8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT8_T:
result = deSerializeData<int8_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT16_T:
result = deSerializeData<uint16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT16_T:
result = deSerializeData<int16_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::UINT32_T:
result = deSerializeData<uint32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::INT32_T:
result = deSerializeData<int32_t>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::FLOAT:
result = deSerializeData<float>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
case Type::DOUBLE:
result = deSerializeData<double>(startingRow, startingColumn,
from->readonlyData, from->rows);
break;
default:
result = ParameterWrapper::UNKNOW_DATATYPE;
break;
}
} else {
//not supported
return HasReturnvaluesIF::RETURN_FAILED;
}
return result;
}

View File

@ -1,38 +1,38 @@
#ifndef DATAPOOLPARAMETERWRAPPER_H_
#define DATAPOOLPARAMETERWRAPPER_H_
#include "../globalfunctions/Type.h"
#include "../parameters/ParameterWrapper.h"
class DataPoolParameterWrapper: public SerializeIF {
public:
DataPoolParameterWrapper();
virtual ~DataPoolParameterWrapper();
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
ReturnValue_t copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex);
private:
Type type;
uint8_t rows;
uint8_t columns;
uint32_t poolId;
template<typename T>
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
const void *from, uint8_t fromRows);
};
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */
#ifndef DATAPOOLPARAMETERWRAPPER_H_
#define DATAPOOLPARAMETERWRAPPER_H_
#include "../globalfunctions/Type.h"
#include "../parameters/ParameterWrapper.h"
class DataPoolParameterWrapper: public SerializeIF {
public:
DataPoolParameterWrapper();
virtual ~DataPoolParameterWrapper();
ReturnValue_t set(uint8_t domainId, uint16_t parameterId);
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
ReturnValue_t copyFrom(const ParameterWrapper *from,
uint16_t startWritingAtIndex);
private:
Type type;
uint8_t rows;
uint8_t columns;
uint32_t poolId;
template<typename T>
ReturnValue_t deSerializeData(uint8_t startingRow, uint8_t startingColumn,
const void *from, uint8_t fromRows);
};
#endif /* DATAPOOLPARAMETERWRAPPER_H_ */

View File

@ -1,133 +1,133 @@
#include "../datapoolglob/GlobalDataPool.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/MutexFactory.h"
GlobalDataPool::GlobalDataPool(
void(*initFunction)(GlobPoolMap* pool_map)) {
mutex = MutexFactory::instance()->createMutex();
if (initFunction != NULL ) {
initFunction( &this->globDataPool );
}
}
GlobalDataPool::~GlobalDataPool() {
MutexFactory::instance()->deleteMutex(mutex);
for(GlobPoolMapIter it = this->globDataPool.begin();
it != this->globDataPool.end(); ++it )
{
delete it->second;
}
}
// The function checks PID, type and array length before returning a copy of
// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr.
template <typename T> PoolEntry<T>* GlobalDataPool::getData( uint32_t data_pool_id,
uint8_t sizeOrPosition ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
PoolEntry<T>* entry = dynamic_cast< PoolEntry<T>* >( it->second );
if (entry != nullptr ) {
if ( sizeOrPosition <= entry->length ) {
return entry;
}
}
}
return nullptr;
}
PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
return it->second;
} else {
return nullptr;
}
}
ReturnValue_t GlobalDataPool::unlockDataPool() {
ReturnValue_t status = mutex->unlockMutex();
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: unlock of mutex failed with"
" error code: " << status << std::endl;
}
return status;
}
ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) {
ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
timeoutMs);
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: lock of mutex failed "
"with error code: " << status << std::endl;
}
return status;
}
void GlobalDataPool::print() {
sif::debug << "DataPool contains: " << std::endl;
std::map<uint32_t, PoolEntryIF*>::iterator dataPoolIt;
dataPoolIt = this->globDataPool.begin();
while( dataPoolIt != this->globDataPool.end() ) {
sif::debug << std::hex << dataPoolIt->first << std::dec << " |";
dataPoolIt->second->print();
dataPoolIt++;
}
}
uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) {
return (parameter_id >> 8) & 0x00FFFFFF;
}
uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) {
return (parameter_id & 0x000000FF);
}
uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
return (poolId << 8) + index;
}
//SHOULDDO: Do we need a mutex lock here... I don't think so,
//as we only check static const values of elements in a list that do not change.
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) {
GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id));
if ( it != this->globDataPool.end() ) {
*type = it->second->getType();
return RETURN_OK;
} else {
*type = Type::UNKNOWN_TYPE;
return RETURN_FAILED;
}
}
bool GlobalDataPool::exists(uint32_t parameterId) {
uint32_t poolId = PIDToDataPoolId(parameterId);
uint32_t index = PIDToArrayIndex(parameterId);
GlobPoolMapIter it = this->globDataPool.find( poolId );
if (it != globDataPool.end()) {
if (it->second->getSize() >= index) {
return true;
}
}
return false;
}
template PoolEntry<uint8_t>* GlobalDataPool::getData<uint8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint16_t>* GlobalDataPool::getData<uint16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint32_t>* GlobalDataPool::getData<uint32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint64_t>* GlobalDataPool::getData<uint64_t>(
uint32_t data_pool_id, uint8_t size);
template PoolEntry<int8_t>* GlobalDataPool::getData<int8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int16_t>* GlobalDataPool::getData<int16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int32_t>* GlobalDataPool::getData<int32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<float>* GlobalDataPool::getData<float>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<double>* GlobalDataPool::getData<double>(
uint32_t data_pool_id, uint8_t size);
#include "../datapoolglob/GlobalDataPool.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../ipc/MutexFactory.h"
GlobalDataPool::GlobalDataPool(
void(*initFunction)(GlobPoolMap* pool_map)) {
mutex = MutexFactory::instance()->createMutex();
if (initFunction != NULL ) {
initFunction( &this->globDataPool );
}
}
GlobalDataPool::~GlobalDataPool() {
MutexFactory::instance()->deleteMutex(mutex);
for(GlobPoolMapIter it = this->globDataPool.begin();
it != this->globDataPool.end(); ++it )
{
delete it->second;
}
}
// The function checks PID, type and array length before returning a copy of
// the PoolEntry. In failure case, it returns a temp-Entry with size 0 and NULL-ptr.
template <typename T> PoolEntry<T>* GlobalDataPool::getData( uint32_t data_pool_id,
uint8_t sizeOrPosition ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
PoolEntry<T>* entry = dynamic_cast< PoolEntry<T>* >( it->second );
if (entry != nullptr ) {
if ( sizeOrPosition <= entry->length ) {
return entry;
}
}
}
return nullptr;
}
PoolEntryIF* GlobalDataPool::getRawData( uint32_t data_pool_id ) {
GlobPoolMapIter it = this->globDataPool.find( data_pool_id );
if ( it != this->globDataPool.end() ) {
return it->second;
} else {
return nullptr;
}
}
ReturnValue_t GlobalDataPool::unlockDataPool() {
ReturnValue_t status = mutex->unlockMutex();
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: unlock of mutex failed with"
" error code: " << status << std::endl;
}
return status;
}
ReturnValue_t GlobalDataPool::lockDataPool(uint32_t timeoutMs) {
ReturnValue_t status = mutex->lockMutex(MutexIF::TimeoutType::WAITING,
timeoutMs);
if(status != RETURN_OK) {
sif::error << "DataPool::DataPool: lock of mutex failed "
"with error code: " << status << std::endl;
}
return status;
}
void GlobalDataPool::print() {
sif::debug << "DataPool contains: " << std::endl;
std::map<uint32_t, PoolEntryIF*>::iterator dataPoolIt;
dataPoolIt = this->globDataPool.begin();
while( dataPoolIt != this->globDataPool.end() ) {
sif::debug << std::hex << dataPoolIt->first << std::dec << " |";
dataPoolIt->second->print();
dataPoolIt++;
}
}
uint32_t GlobalDataPool::PIDToDataPoolId(uint32_t parameter_id) {
return (parameter_id >> 8) & 0x00FFFFFF;
}
uint8_t GlobalDataPool::PIDToArrayIndex(uint32_t parameter_id) {
return (parameter_id & 0x000000FF);
}
uint32_t GlobalDataPool::poolIdAndPositionToPid(uint32_t poolId, uint8_t index) {
return (poolId << 8) + index;
}
//SHOULDDO: Do we need a mutex lock here... I don't think so,
//as we only check static const values of elements in a list that do not change.
//there is no guarantee in the standard, but it seems to me that the implementation is safe -UM
ReturnValue_t GlobalDataPool::getType(uint32_t parameter_id, Type* type) {
GlobPoolMapIter it = this->globDataPool.find( PIDToDataPoolId(parameter_id));
if ( it != this->globDataPool.end() ) {
*type = it->second->getType();
return RETURN_OK;
} else {
*type = Type::UNKNOWN_TYPE;
return RETURN_FAILED;
}
}
bool GlobalDataPool::exists(uint32_t parameterId) {
uint32_t poolId = PIDToDataPoolId(parameterId);
uint32_t index = PIDToArrayIndex(parameterId);
GlobPoolMapIter it = this->globDataPool.find( poolId );
if (it != globDataPool.end()) {
if (it->second->getSize() >= index) {
return true;
}
}
return false;
}
template PoolEntry<uint8_t>* GlobalDataPool::getData<uint8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint16_t>* GlobalDataPool::getData<uint16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint32_t>* GlobalDataPool::getData<uint32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<uint64_t>* GlobalDataPool::getData<uint64_t>(
uint32_t data_pool_id, uint8_t size);
template PoolEntry<int8_t>* GlobalDataPool::getData<int8_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int16_t>* GlobalDataPool::getData<int16_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<int32_t>* GlobalDataPool::getData<int32_t>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<float>* GlobalDataPool::getData<float>(
uint32_t data_pool_id, uint8_t size );
template PoolEntry<double>* GlobalDataPool::getData<double>(
uint32_t data_pool_id, uint8_t size);

View File

@ -1,149 +1,149 @@
#ifndef GLOBALDATAPOOL_H_
#define GLOBALDATAPOOL_H_
#include "../datapool/PoolEntry.h"
#include "../globalfunctions/Type.h"
#include "../ipc/MutexIF.h"
#include <map>
/**
* @defgroup data_pool Global data pool
* This is the group, where all classes associated with global
* data pool handling belong to.
* This includes classes to access Data Pool variables.
*/
/**
* Typedefs for the global pool representations
*/
using GlobPoolMap = std::map<uint32_t, PoolEntryIF*>;
using GlobPoolMapIter = GlobPoolMap::iterator;
/**
* @brief This class represents the OBSW global data-pool.
*
* @details
* All variables are registered and space is allocated in an initialization
* function, which is passed do the constructor. Space for the variables is
* allocated on the heap (with a new call).
*
* The data is found by a data pool id, which uniquely represents a variable.
* Data pool variables should be used with a blackboard logic in mind,
* which means read data is valid (if flagged so),
* but not necessarily up-to-date.
*
* Variables are either single values or arrays.
* @author Bastian Baetz
* @ingroup data_pool
*/
class GlobalDataPool : public HasReturnvaluesIF {
private:
/**
* @brief This is the actual data pool itself.
* @details It is represented by a map with the data pool id as index
* and a pointer to a single PoolEntry as value.
*/
GlobPoolMap globDataPool;
/**
* @brief The mutex is created in the constructor and makes
* access mutual exclusive.
* @details Locking and unlocking the pool is only done by the DataSet class.
*/
MutexIF* mutex;
public:
/**
* @brief In the classes constructor,
* the passed initialization function is called.
* @details
* To enable filling the pool, a pointer to the map is passed,
* allowing direct access to the pool's content.
* On runtime, adding or removing variables is forbidden.
*/
GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) );
/**
* @brief The destructor iterates through the data_pool map and
* calls all entries destructors to clean up the heap.
*/
~GlobalDataPool();
/**
* @brief This is the default call to access the pool.
* @details
* A pointer to the PoolEntry object is returned.
* The call checks data pool id, type and array size.
* Returns NULL in case of failure.
* @param data_pool_id The data pool id to search.
* @param sizeOrPosition The array size (not byte size!) of the pool entry,
* or the position the user wants to read.
* If smaller than the entry size, everything's ok.
*/
template <typename T> PoolEntry<T>* getData( uint32_t data_pool_id,
uint8_t sizeOrPosition );
/**
* @brief An alternative call to get a data pool entry in case the type is not implicitly known
* (i.e. in Housekeeping Telemetry).
* @details It returns a basic interface and does NOT perform
* a size check. The caller has to assure he does not copy too much data.
* Returns NULL in case the entry is not found.
* @param data_pool_id The data pool id to search.
*/
PoolEntryIF* getRawData( uint32_t data_pool_id );
/**
* @brief This is a small helper function to facilitate locking the global data pool.
* @details It fetches the pool's mutex id and tries to acquire the mutex.
*/
ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING);
/**
* @brief This is a small helper function to facilitate unlocking the global data pool.
* @details It fetches the pool's mutex id and tries to free the mutex.
*/
ReturnValue_t unlockDataPool();
/**
* @brief The print call is a simple debug method.
* @details It prints the current content of the data pool.
* It iterates through the data_pool map and calls each entry's print() method.
*/
void print();
/**
* Extracts the data pool id from a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The data pool id as used within the OBSW.
*/
static uint32_t PIDToDataPoolId( uint32_t parameter_id );
/**
* Extracts an array index out of a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The index of the corresponding data pool entry.
*/
static uint8_t PIDToArrayIndex( uint32_t parameter_id );
/**
* Retransforms a data pool id and an array index to a SCOS 2000 PID.
*/
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
/**
* Method to return the type of a pool variable.
* @param parameter_id A parameterID (not pool id) of a DP member.
* @param type Returns the type or TYPE::UNKNOWN_TYPE
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
*/
ReturnValue_t getType( uint32_t parameter_id, Type* type );
/**
* Method to check if a PID exists. Does not lock, as there's no
* possibility to alter the list that is checked during run-time.
* @param parameterId The PID (not pool id!) of a parameter.
* @return true if exists, false else.
*/
bool exists(uint32_t parameterId);
};
//We assume someone globally instantiates a DataPool.
namespace glob {
extern GlobalDataPool dataPool;
}
#endif /* DATAPOOL_H_ */
#ifndef GLOBALDATAPOOL_H_
#define GLOBALDATAPOOL_H_
#include "../datapool/PoolEntry.h"
#include "../globalfunctions/Type.h"
#include "../ipc/MutexIF.h"
#include <map>
/**
* @defgroup data_pool Global data pool
* This is the group, where all classes associated with global
* data pool handling belong to.
* This includes classes to access Data Pool variables.
*/
/**
* Typedefs for the global pool representations
*/
using GlobPoolMap = std::map<uint32_t, PoolEntryIF*>;
using GlobPoolMapIter = GlobPoolMap::iterator;
/**
* @brief This class represents the OBSW global data-pool.
*
* @details
* All variables are registered and space is allocated in an initialization
* function, which is passed do the constructor. Space for the variables is
* allocated on the heap (with a new call).
*
* The data is found by a data pool id, which uniquely represents a variable.
* Data pool variables should be used with a blackboard logic in mind,
* which means read data is valid (if flagged so),
* but not necessarily up-to-date.
*
* Variables are either single values or arrays.
* @author Bastian Baetz
* @ingroup data_pool
*/
class GlobalDataPool : public HasReturnvaluesIF {
private:
/**
* @brief This is the actual data pool itself.
* @details It is represented by a map with the data pool id as index
* and a pointer to a single PoolEntry as value.
*/
GlobPoolMap globDataPool;
/**
* @brief The mutex is created in the constructor and makes
* access mutual exclusive.
* @details Locking and unlocking the pool is only done by the DataSet class.
*/
MutexIF* mutex;
public:
/**
* @brief In the classes constructor,
* the passed initialization function is called.
* @details
* To enable filling the pool, a pointer to the map is passed,
* allowing direct access to the pool's content.
* On runtime, adding or removing variables is forbidden.
*/
GlobalDataPool( void ( *initFunction )( GlobPoolMap* pool_map ) );
/**
* @brief The destructor iterates through the data_pool map and
* calls all entries destructors to clean up the heap.
*/
~GlobalDataPool();
/**
* @brief This is the default call to access the pool.
* @details
* A pointer to the PoolEntry object is returned.
* The call checks data pool id, type and array size.
* Returns NULL in case of failure.
* @param data_pool_id The data pool id to search.
* @param sizeOrPosition The array size (not byte size!) of the pool entry,
* or the position the user wants to read.
* If smaller than the entry size, everything's ok.
*/
template <typename T> PoolEntry<T>* getData( uint32_t data_pool_id,
uint8_t sizeOrPosition );
/**
* @brief An alternative call to get a data pool entry in case the type is not implicitly known
* (i.e. in Housekeeping Telemetry).
* @details It returns a basic interface and does NOT perform
* a size check. The caller has to assure he does not copy too much data.
* Returns NULL in case the entry is not found.
* @param data_pool_id The data pool id to search.
*/
PoolEntryIF* getRawData( uint32_t data_pool_id );
/**
* @brief This is a small helper function to facilitate locking the global data pool.
* @details It fetches the pool's mutex id and tries to acquire the mutex.
*/
ReturnValue_t lockDataPool(uint32_t timeoutMs = MutexIF::BLOCKING);
/**
* @brief This is a small helper function to facilitate unlocking the global data pool.
* @details It fetches the pool's mutex id and tries to free the mutex.
*/
ReturnValue_t unlockDataPool();
/**
* @brief The print call is a simple debug method.
* @details It prints the current content of the data pool.
* It iterates through the data_pool map and calls each entry's print() method.
*/
void print();
/**
* Extracts the data pool id from a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The data pool id as used within the OBSW.
*/
static uint32_t PIDToDataPoolId( uint32_t parameter_id );
/**
* Extracts an array index out of a SCOS 2000 PID.
* @param parameter_id The passed Parameter ID.
* @return The index of the corresponding data pool entry.
*/
static uint8_t PIDToArrayIndex( uint32_t parameter_id );
/**
* Retransforms a data pool id and an array index to a SCOS 2000 PID.
*/
static uint32_t poolIdAndPositionToPid( uint32_t poolId, uint8_t index );
/**
* Method to return the type of a pool variable.
* @param parameter_id A parameterID (not pool id) of a DP member.
* @param type Returns the type or TYPE::UNKNOWN_TYPE
* @return RETURN_OK if parameter exists, RETURN_FAILED else.
*/
ReturnValue_t getType( uint32_t parameter_id, Type* type );
/**
* Method to check if a PID exists. Does not lock, as there's no
* possibility to alter the list that is checked during run-time.
* @param parameterId The PID (not pool id!) of a parameter.
* @return true if exists, false else.
*/
bool exists(uint32_t parameterId);
};
//We assume someone globally instantiates a DataPool.
namespace glob {
extern GlobalDataPool dataPool;
}
#endif /* DATAPOOL_H_ */

View File

@ -1,213 +1,213 @@
#ifndef GLOBALPOOLVARIABLE_H_
#define GLOBALPOOLVARIABLE_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapool/PoolEntry.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename T, uint8_t n_var> class PoolVarList;
/**
* @brief This is the access class for non-array data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly
* on the data pool entries, but on local copies. This class provides simple
* type-safe access to single data pool entries (i.e. entries with length = 1).
* The class can be instantiated as read-write and read only.
* It provides a commit-and-roll-back semantic, which means that the
* variable's value in the data pool is not changed until the
* commit call is executed.
* @tparam T The template parameter sets the type of the variable.
* Currently, all plain data types are supported, but in principle
* any type is possible.
* @ingroup data_pool
*/
template<typename T>
class GlobPoolVar: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PoolVarList;
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t instead!"
"There is no boolean type in CCSDS.");
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if nullptr is not passed).
* @details
* It DOES NOT fetch the current value from the data pool, but
* sets the value attribute to default (0).
* The value is fetched within the read() operation.
* @param set_id This is the id in the global data pool
* this instance of the access class corresponds to.
* @param dataSet The data set in which the variable shall register
* itself. If NULL, the variable is not registered.
* @param setWritable If this flag is set to true, changes in the value
* attribute can be written back to the data pool, otherwise not.
*/
GlobPoolVar(uint32_t set_id, DataSetIF* dataSet,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a simple local variable.
*/
T value = 0;
/**
* @brief Copy ctor to copy classes containing Pool Variables.
* (Robin): This only copies member variables, which is done
* by the default copy ctor. maybe we can ommit this ctor?
*/
GlobPoolVar(const GlobPoolVar& rhs);
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVar() {}
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
* The commit call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool is
* copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or read-only
* is stored here.
*/
pool_rwm_t readWriteMode;
/**
* Empty ctor for List initialization
*/
GlobPoolVar();
public:
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const override;
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const override;
/**
* This operation sets the data pool id of the variable.
* The method is necessary to set id's of data pool member variables with bad initialization.
*/
void setDataPoolId(uint32_t poolId);
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const override;
uint8_t getValid();
void setValid(bool valid) override;
operator T() {
return value;
}
operator T() const {
return value;
}
GlobPoolVar<T> &operator=(T newValue) {
value = newValue;
return *this;
}
GlobPoolVar<T> &operator=(GlobPoolVar<T> newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size,
SerializeIF::Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, max_size,
streamEndianness);
}
virtual size_t getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#include "../datapoolglob/GlobalPoolVariable.tpp"
typedef GlobPoolVar<uint8_t> gp_bool_t;
typedef GlobPoolVar<uint8_t> gp_uint8_t;
typedef GlobPoolVar<uint16_t> gp_uint16_t;
typedef GlobPoolVar<uint32_t> gp_uint32_t;
typedef GlobPoolVar<int8_t> gp_int8_t;
typedef GlobPoolVar<int16_t> gp_int16_t;
typedef GlobPoolVar<int32_t> gp_int32_t;
typedef GlobPoolVar<float> gp_float_t;
typedef GlobPoolVar<double> gp_double_t;
#endif /* POOLVARIABLE_H_ */
#ifndef GLOBALPOOLVARIABLE_H_
#define GLOBALPOOLVARIABLE_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapool/PoolEntry.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename T, uint8_t n_var> class PoolVarList;
/**
* @brief This is the access class for non-array data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly
* on the data pool entries, but on local copies. This class provides simple
* type-safe access to single data pool entries (i.e. entries with length = 1).
* The class can be instantiated as read-write and read only.
* It provides a commit-and-roll-back semantic, which means that the
* variable's value in the data pool is not changed until the
* commit call is executed.
* @tparam T The template parameter sets the type of the variable.
* Currently, all plain data types are supported, but in principle
* any type is possible.
* @ingroup data_pool
*/
template<typename T>
class GlobPoolVar: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PoolVarList;
static_assert(not std::is_same<T, bool>::value,
"Do not use boolean for the PoolEntry type, use uint8_t instead!"
"There is no boolean type in CCSDS.");
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if nullptr is not passed).
* @details
* It DOES NOT fetch the current value from the data pool, but
* sets the value attribute to default (0).
* The value is fetched within the read() operation.
* @param set_id This is the id in the global data pool
* this instance of the access class corresponds to.
* @param dataSet The data set in which the variable shall register
* itself. If NULL, the variable is not registered.
* @param setWritable If this flag is set to true, changes in the value
* attribute can be written back to the data pool, otherwise not.
*/
GlobPoolVar(uint32_t set_id, DataSetIF* dataSet,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a simple local variable.
*/
T value = 0;
/**
* @brief Copy ctor to copy classes containing Pool Variables.
* (Robin): This only copies member variables, which is done
* by the default copy ctor. maybe we can ommit this ctor?
*/
GlobPoolVar(const GlobPoolVar& rhs);
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVar() {}
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The operation does NOT provide any mutual exclusive protection by itself.
* The commit call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool is
* copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or read-only
* is stored here.
*/
pool_rwm_t readWriteMode;
/**
* Empty ctor for List initialization
*/
GlobPoolVar();
public:
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const override;
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const override;
/**
* This operation sets the data pool id of the variable.
* The method is necessary to set id's of data pool member variables with bad initialization.
*/
void setDataPoolId(uint32_t poolId);
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const override;
uint8_t getValid();
void setValid(bool valid) override;
operator T() {
return value;
}
operator T() const {
return value;
}
GlobPoolVar<T> &operator=(T newValue) {
value = newValue;
return *this;
}
GlobPoolVar<T> &operator=(GlobPoolVar<T> newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t max_size,
SerializeIF::Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, max_size,
streamEndianness);
}
virtual size_t getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#include "../datapoolglob/GlobalPoolVariable.tpp"
typedef GlobPoolVar<uint8_t> gp_bool_t;
typedef GlobPoolVar<uint8_t> gp_uint8_t;
typedef GlobPoolVar<uint16_t> gp_uint16_t;
typedef GlobPoolVar<uint32_t> gp_uint32_t;
typedef GlobPoolVar<int8_t> gp_int8_t;
typedef GlobPoolVar<int16_t> gp_int16_t;
typedef GlobPoolVar<int32_t> gp_int32_t;
typedef GlobPoolVar<float> gp_float_t;
typedef GlobPoolVar<double> gp_double_t;
#endif /* POOLVARIABLE_H_ */

View File

@ -1,185 +1,185 @@
#ifndef GLOBALPOOLVECTOR_H_
#define GLOBALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
/**
* @brief This is the access class for array-type data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly on the
* data pool entries, but on local copies. This class provides simple type-
* and length-safe access to vector-style data pool entries (i.e. entries with
* length > 1). The class can be instantiated as read-write and read only.
*
* It provides a commit-and-roll-back semantic, which means that no array
* entry in the data pool is changed until the commit call is executed.
* There are two template parameters:
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template<typename T, uint16_t vectorSize>
class GlobPoolVector: public PoolVariableIF {
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if no nullptr is passed).
* @details
* It DOES NOT fetch the current value from the data pool, but sets the
* value attribute to default (0). The value is fetched within the
* read() operation.
* @param set_id
* This is the id in the global data pool this instance of the access
* class corresponds to.
* @param dataSet
* The data set in which the variable shall register itself. If nullptr,
* the variable is not registered.
* @param setWritable
* If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
GlobPoolVector(uint32_t set_id, DataSetIF* set,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a local array of this type.
*/
T value[vectorSize];
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVector() {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() {
return vectorSize;
}
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return dataPoolId;
}
/**
* @brief This operation sets the data pool id of the variable.
* @details
* The method is necessary to set id's of data pool member variables
* with bad initialization.
*/
void setDataPoolId(uint32_t poolId) {
dataPoolId = poolId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return readWriteMode;
}
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void setValid(bool valid) {this->valid = valid;}
uint8_t getValid() {return valid;}
T &operator [](int i) {return value[i];}
const T &operator [](int i) const {return value[i];}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t max_size, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies all array values
* and the valid information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The commit call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
private:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#include "../datapoolglob/GlobalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using gp_vec_t = GlobPoolVector<T, vectorSize>;
#endif /* POOLVECTOR_H_ */
#ifndef GLOBALPOOLVECTOR_H_
#define GLOBALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
/**
* @brief This is the access class for array-type data pool entries.
*
* @details
* To ensure safe usage of the data pool, operation is not done directly on the
* data pool entries, but on local copies. This class provides simple type-
* and length-safe access to vector-style data pool entries (i.e. entries with
* length > 1). The class can be instantiated as read-write and read only.
*
* It provides a commit-and-roll-back semantic, which means that no array
* entry in the data pool is changed until the commit call is executed.
* There are two template parameters:
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template<typename T, uint16_t vectorSize>
class GlobPoolVector: public PoolVariableIF {
public:
/**
* @brief In the constructor, the variable can register itself in a
* DataSet (if no nullptr is passed).
* @details
* It DOES NOT fetch the current value from the data pool, but sets the
* value attribute to default (0). The value is fetched within the
* read() operation.
* @param set_id
* This is the id in the global data pool this instance of the access
* class corresponds to.
* @param dataSet
* The data set in which the variable shall register itself. If nullptr,
* the variable is not registered.
* @param setWritable
* If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
GlobPoolVector(uint32_t set_id, DataSetIF* set,
ReadWriteMode_t setReadWriteMode);
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a local array of this type.
*/
T value[vectorSize];
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~GlobPoolVector() {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() {
return vectorSize;
}
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return dataPoolId;
}
/**
* @brief This operation sets the data pool id of the variable.
* @details
* The method is necessary to set id's of data pool member variables
* with bad initialization.
*/
void setDataPoolId(uint32_t poolId) {
dataPoolId = poolId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return readWriteMode;
}
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void setValid(bool valid) {this->valid = valid;}
uint8_t getValid() {return valid;}
T &operator [](int i) {return value[i];}
const T &operator [](int i) const {return value[i];}
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t max_size, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies all array values
* and the valid information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The commit call is protected by a lock of the global data pool.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
private:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t dataPoolId;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
uint8_t valid;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#include "../datapoolglob/GlobalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using gp_vec_t = GlobPoolVector<T, vectorSize>;
#endif /* POOLVECTOR_H_ */

View File

@ -1,164 +1,164 @@
#ifndef PIDREADER_H_
#define PIDREADER_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename U, uint8_t n_var> class PIDReaderList;
template<typename T>
class PIDReader: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PIDReaderList;
protected:
uint32_t parameterId;
uint8_t valid;
ReturnValue_t readWithoutLock() {
uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId);
PoolEntry<T> *read_out = glob::dataPool.getData<T>(
GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex);
if (read_out != NULL) {
valid = read_out->valid;
value = read_out->address[arrayIndex];
return HasReturnvaluesIF::RETURN_OK;
} else {
value = 0;
valid = false;
sif::error << "PIDReader: read of PID 0x" << std::hex << parameterId
<< std::dec << " failed." << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
/**
* Never commit, is read-only.
* Reason is the possibility to access a single DP vector element, but if we commit,
* we set validity of the whole vector.
*/
ReturnValue_t commit(uint32_t lockTimeout) override {
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t commitWithoutLock() override {
return HasReturnvaluesIF::RETURN_FAILED;
}
/**
* Empty ctor for List initialization
*/
PIDReader() :
parameterId(PoolVariableIF::NO_PARAMETER), valid(
PoolVariableIF::INVALID), value(0) {
}
public:
/**
* \brief This is the local copy of the data pool entry.
*/
T value;
/**
* \brief In the constructor, the variable can register itself in a DataSet (if not NULL is
* passed).
* \details It DOES NOT fetch the current value from the data pool, but sets the value
* attribute to default (0). The value is fetched within the read() operation.
* \param set_id This is the id in the global data pool this instance of the access class
* corresponds to.
* \param dataSet The data set in which the variable shall register itself. If NULL,
* the variable is not registered.
* \param setWritable If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
PIDReader(uint32_t setParameterId, DataSetIF *dataSet) :
parameterId(setParameterId), valid(PoolVariableIF::INVALID), value(
0) {
if (dataSet != NULL) {
dataSet->registerVariable(this);
}
}
ReturnValue_t read(uint32_t lockTimeout) override {
ReturnValue_t result = glob::dataPool.lockDataPool();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "PIDReader::read: Could not unlock data pool!"
<< std::endl;
}
return result;
}
/**
* Copy ctor to copy classes containing Pool Variables.
*/
PIDReader(const PIDReader &rhs) :
parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) {
}
/**
* \brief The classes destructor is empty.
*/
~PIDReader() {
}
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return GlobalDataPool::PIDToDataPoolId(parameterId);
}
uint32_t getParameterId() const {
return parameterId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return VAR_READ;
}
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid)
return true;
else
return false;
}
uint8_t getValid() {
return valid;
}
void setValid(bool valid) {
this->valid = valid;
}
operator T() {
return value;
}
PIDReader<T>& operator=(T newValue) {
value = newValue;
return *this;
}
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, maxSize,
streamEndianness);
}
virtual size_t getSerializedSize() const override {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#endif /* PIDREADER_H_ */
#ifndef PIDREADER_H_
#define PIDREADER_H_
#include "../datapool/DataSetIF.h"
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
template<typename U, uint8_t n_var> class PIDReaderList;
template<typename T>
class PIDReader: public PoolVariableIF {
template<typename U, uint8_t n_var> friend class PIDReaderList;
protected:
uint32_t parameterId;
uint8_t valid;
ReturnValue_t readWithoutLock() {
uint8_t arrayIndex = GlobalDataPool::PIDToArrayIndex(parameterId);
PoolEntry<T> *read_out = glob::dataPool.getData<T>(
GlobalDataPool::PIDToDataPoolId(parameterId), arrayIndex);
if (read_out != NULL) {
valid = read_out->valid;
value = read_out->address[arrayIndex];
return HasReturnvaluesIF::RETURN_OK;
} else {
value = 0;
valid = false;
sif::error << "PIDReader: read of PID 0x" << std::hex << parameterId
<< std::dec << " failed." << std::endl;
return HasReturnvaluesIF::RETURN_FAILED;
}
}
/**
* Never commit, is read-only.
* Reason is the possibility to access a single DP vector element, but if we commit,
* we set validity of the whole vector.
*/
ReturnValue_t commit(uint32_t lockTimeout) override {
return HasReturnvaluesIF::RETURN_FAILED;
}
ReturnValue_t commitWithoutLock() override {
return HasReturnvaluesIF::RETURN_FAILED;
}
/**
* Empty ctor for List initialization
*/
PIDReader() :
parameterId(PoolVariableIF::NO_PARAMETER), valid(
PoolVariableIF::INVALID), value(0) {
}
public:
/**
* \brief This is the local copy of the data pool entry.
*/
T value;
/**
* \brief In the constructor, the variable can register itself in a DataSet (if not NULL is
* passed).
* \details It DOES NOT fetch the current value from the data pool, but sets the value
* attribute to default (0). The value is fetched within the read() operation.
* \param set_id This is the id in the global data pool this instance of the access class
* corresponds to.
* \param dataSet The data set in which the variable shall register itself. If NULL,
* the variable is not registered.
* \param setWritable If this flag is set to true, changes in the value attribute can be
* written back to the data pool, otherwise not.
*/
PIDReader(uint32_t setParameterId, DataSetIF *dataSet) :
parameterId(setParameterId), valid(PoolVariableIF::INVALID), value(
0) {
if (dataSet != NULL) {
dataSet->registerVariable(this);
}
}
ReturnValue_t read(uint32_t lockTimeout) override {
ReturnValue_t result = glob::dataPool.lockDataPool();
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "PIDReader::read: Could not unlock data pool!"
<< std::endl;
}
return result;
}
/**
* Copy ctor to copy classes containing Pool Variables.
*/
PIDReader(const PIDReader &rhs) :
parameterId(rhs.parameterId), valid(rhs.valid), value(rhs.value) {
}
/**
* \brief The classes destructor is empty.
*/
~PIDReader() {
}
/**
* \brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const {
return GlobalDataPool::PIDToDataPoolId(parameterId);
}
uint32_t getParameterId() const {
return parameterId;
}
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const {
return VAR_READ;
}
/**
* \brief With this call, the valid information of the variable is returned.
*/
bool isValid() const {
if (valid)
return true;
else
return false;
}
uint8_t getValid() {
return valid;
}
void setValid(bool valid) {
this->valid = valid;
}
operator T() {
return value;
}
PIDReader<T>& operator=(T newValue) {
value = newValue;
return *this;
}
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override {
return SerializeAdapter::serialize(&value, buffer, size, maxSize,
streamEndianness);
}
virtual size_t getSerializedSize() const override {
return SerializeAdapter::getSerializedSize(&value);
}
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
return SerializeAdapter::deSerialize(&value, buffer, size,
streamEndianness);
}
};
#endif /* PIDREADER_H_ */

View File

@ -1,27 +1,27 @@
#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/PIDReader.h"
template <class T, uint8_t n_var>
class PIDReaderList {
private:
PIDReader<T> variables[n_var];
public:
PIDReaderList( const uint32_t setPid[n_var], DataSetIF* dataSet) {
//I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) {
return;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].parameterId = setPid[count];
dataSet->registerVariable(&variables[count]);
}
}
PIDReader<T> &operator [](int i) { return variables[i]; }
};
#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */
#ifndef FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#define FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_
#include "../datapool/PoolVariableIF.h"
#include "../datapoolglob/PIDReader.h"
template <class T, uint8_t n_var>
class PIDReaderList {
private:
PIDReader<T> variables[n_var];
public:
PIDReaderList( const uint32_t setPid[n_var], DataSetIF* dataSet) {
//I really should have a look at the new init list c++ syntax.
if (dataSet == NULL) {
return;
}
for (uint8_t count = 0; count < n_var; count++) {
variables[count].parameterId = setPid[count];
dataSet->registerVariable(&variables[count]);
}
}
PIDReader<T> &operator [](int i) { return variables[i]; }
};
#endif /* FRAMEWORK_DATAPOOLGLOB_PIDREADERLIST_H_ */

View File

@ -1,239 +1,239 @@
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serialize/EndianConverter.h"
#include <cstring>
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
readWriteMode(setReadWriteMode) {
memset(value, 0, sizeof(value));
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
PoolRawAccess::~PoolRawAccess() {}
ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::readWithoutLock() {
ReturnValue_t result = RETURN_FAILED;
PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
if (readOut != nullptr) {
result = handleReadOut(readOut);
if(result == RETURN_OK) {
return result;
}
} else {
result = READ_ENTRY_NON_EXISTENT;
}
handleReadError(result);
return result;
}
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
ReturnValue_t result = RETURN_FAILED;
valid = readOut->getValid();
if (readOut->getSize() > arrayEntry) {
arraySize = readOut->getSize();
typeSize = readOut->getByteSize() / readOut->getSize();
type = readOut->getType();
if (typeSize <= sizeof(value)) {
uint16_t arrayPosition = arrayEntry * typeSize;
sizeTillEnd = readOut->getByteSize() - arrayPosition;
uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
memcpy(value, ptr, typeSize);
return RETURN_OK;
} else {
result = READ_TYPE_TOO_LARGE;
}
} else {
//debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
result = READ_INDEX_TOO_LARGE;
}
return result;
}
void PoolRawAccess::handleReadError(ReturnValue_t result) {
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
sif::error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
sif::error << "index too large." << std::endl;
}
else if(result == READ_ENTRY_NON_EXISTENT) {
sif::error << "entry does not exist." << std::endl;
}
valid = INVALID;
typeSize = 0;
sizeTillEnd = 0;
memset(value, 0, sizeof(value));
}
ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commitWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::commitWithoutLock() {
PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId);
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
write_back->setValid(valid);
uint8_t array_position = arrayEntry * typeSize;
uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position];
memcpy(ptr, value, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t* PoolRawAccess::getEntry() {
return value;
}
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
size_t* writtenBytes, size_t max_size) {
uint8_t* data_ptr = getEntry();
// debug << "PoolRawAccess::getEntry: Array position: " <<
// index * size_of_type << " Size of T: " << (int)size_of_type <<
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
if (typeSize == 0)
return DATA_POOL_ACCESS_FAILED;
if (typeSize > max_size)
return INCORRECT_SIZE;
EndianConverter::convertBigEndian(buffer, data_ptr, typeSize);
*writtenBytes = typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
if (typeSize + *size <= maxSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(*buffer, value, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(*buffer, value, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(*buffer, value, typeSize);
break;
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() {
return type;
}
size_t PoolRawAccess::getSizeOfType() {
return typeSize;
}
size_t PoolRawAccess::getArraySize(){
return arraySize;
}
uint32_t PoolRawAccess::getDataPoolId() const {
return dataPoolId;
}
PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
return readWriteMode;
}
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer,
size_t setSize) {
if (typeSize == setSize) {
EndianConverter::convertBigEndian(value, buffer, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: "
"Internal" << (uint32_t) typeSize << ", Requested: " << setSize
<< std::endl;
return INCORRECT_SIZE;
}
}
bool PoolRawAccess::isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void PoolRawAccess::setValid(bool valid) {
this->valid = valid;
}
size_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd;
}
size_t PoolRawAccess::getSerializedSize() const {
return typeSize;
}
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if (*size >= typeSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(value, *buffer, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(value, *buffer, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(value, *buffer, typeSize);
break;
}
*size -= typeSize;
*buffer += typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SerializeIF::STREAM_TOO_SHORT;
}
}
#include "../datapoolglob/GlobalDataPool.h"
#include "../datapoolglob/PoolRawAccess.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../serialize/EndianConverter.h"
#include <cstring>
PoolRawAccess::PoolRawAccess(uint32_t set_id, uint8_t setArrayEntry,
DataSetIF* dataSet, ReadWriteMode_t setReadWriteMode) :
dataPoolId(set_id), arrayEntry(setArrayEntry), valid(false),
type(Type::UNKNOWN_TYPE), typeSize(0), arraySize(0), sizeTillEnd(0),
readWriteMode(setReadWriteMode) {
memset(value, 0, sizeof(value));
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
PoolRawAccess::~PoolRawAccess() {}
ReturnValue_t PoolRawAccess::read(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = readWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::readWithoutLock() {
ReturnValue_t result = RETURN_FAILED;
PoolEntryIF* readOut = glob::dataPool.getRawData(dataPoolId);
if (readOut != nullptr) {
result = handleReadOut(readOut);
if(result == RETURN_OK) {
return result;
}
} else {
result = READ_ENTRY_NON_EXISTENT;
}
handleReadError(result);
return result;
}
ReturnValue_t PoolRawAccess::handleReadOut(PoolEntryIF* readOut) {
ReturnValue_t result = RETURN_FAILED;
valid = readOut->getValid();
if (readOut->getSize() > arrayEntry) {
arraySize = readOut->getSize();
typeSize = readOut->getByteSize() / readOut->getSize();
type = readOut->getType();
if (typeSize <= sizeof(value)) {
uint16_t arrayPosition = arrayEntry * typeSize;
sizeTillEnd = readOut->getByteSize() - arrayPosition;
uint8_t* ptr = &((uint8_t*) readOut->getRawData())[arrayPosition];
memcpy(value, ptr, typeSize);
return RETURN_OK;
} else {
result = READ_TYPE_TOO_LARGE;
}
} else {
//debug << "PoolRawAccess: Size: " << (int)read_out->getSize() << std::endl;
result = READ_INDEX_TOO_LARGE;
}
return result;
}
void PoolRawAccess::handleReadError(ReturnValue_t result) {
sif::error << "PoolRawAccess: read of DP Variable 0x" << std::hex << dataPoolId
<< std::dec << " failed, ";
if(result == READ_TYPE_TOO_LARGE) {
sif::error << "type too large." << std::endl;
}
else if(result == READ_INDEX_TOO_LARGE) {
sif::error << "index too large." << std::endl;
}
else if(result == READ_ENTRY_NON_EXISTENT) {
sif::error << "entry does not exist." << std::endl;
}
valid = INVALID;
typeSize = 0;
sizeTillEnd = 0;
memset(value, 0, sizeof(value));
}
ReturnValue_t PoolRawAccess::commit(uint32_t lockTimeout) {
ReturnValue_t result = glob::dataPool.lockDataPool(lockTimeout);
if(result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = commitWithoutLock();
ReturnValue_t unlockResult = glob::dataPool.unlockDataPool();
if(unlockResult != HasReturnvaluesIF::RETURN_OK) {
sif::error << "GlobPoolVar::read: Could not unlock global data pool"
<< std::endl;
}
return result;
}
ReturnValue_t PoolRawAccess::commitWithoutLock() {
PoolEntryIF* write_back = glob::dataPool.getRawData(dataPoolId);
if ((write_back != NULL) && (readWriteMode != VAR_READ)) {
write_back->setValid(valid);
uint8_t array_position = arrayEntry * typeSize;
uint8_t* ptr = &((uint8_t*) write_back->getRawData())[array_position];
memcpy(ptr, value, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
return HasReturnvaluesIF::RETURN_FAILED;
}
}
uint8_t* PoolRawAccess::getEntry() {
return value;
}
ReturnValue_t PoolRawAccess::getEntryEndianSafe(uint8_t* buffer,
size_t* writtenBytes, size_t max_size) {
uint8_t* data_ptr = getEntry();
// debug << "PoolRawAccess::getEntry: Array position: " <<
// index * size_of_type << " Size of T: " << (int)size_of_type <<
// " ByteSize: " << byte_size << " Position: " << *size << std::endl;
if (typeSize == 0)
return DATA_POOL_ACCESS_FAILED;
if (typeSize > max_size)
return INCORRECT_SIZE;
EndianConverter::convertBigEndian(buffer, data_ptr, typeSize);
*writtenBytes = typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t PoolRawAccess::serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
if (typeSize + *size <= maxSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(*buffer, value, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(*buffer, value, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(*buffer, value, typeSize);
break;
}
*size += typeSize;
(*buffer) += typeSize;
return HasReturnvaluesIF::RETURN_OK;
} else {
return SerializeIF::BUFFER_TOO_SHORT;
}
}
Type PoolRawAccess::getType() {
return type;
}
size_t PoolRawAccess::getSizeOfType() {
return typeSize;
}
size_t PoolRawAccess::getArraySize(){
return arraySize;
}
uint32_t PoolRawAccess::getDataPoolId() const {
return dataPoolId;
}
PoolVariableIF::ReadWriteMode_t PoolRawAccess::getReadWriteMode() const {
return readWriteMode;
}
ReturnValue_t PoolRawAccess::setEntryFromBigEndian(const uint8_t *buffer,
size_t setSize) {
if (typeSize == setSize) {
EndianConverter::convertBigEndian(value, buffer, typeSize);
return HasReturnvaluesIF::RETURN_OK;
} else {
sif::error << "PoolRawAccess::setEntryFromBigEndian: Illegal sizes: "
"Internal" << (uint32_t) typeSize << ", Requested: " << setSize
<< std::endl;
return INCORRECT_SIZE;
}
}
bool PoolRawAccess::isValid() const {
if (valid != INVALID)
return true;
else
return false;
}
void PoolRawAccess::setValid(bool valid) {
this->valid = valid;
}
size_t PoolRawAccess::getSizeTillEnd() const {
return sizeTillEnd;
}
size_t PoolRawAccess::getSerializedSize() const {
return typeSize;
}
ReturnValue_t PoolRawAccess::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
if (*size >= typeSize) {
switch(streamEndianness) {
case(Endianness::BIG):
EndianConverter::convertBigEndian(value, *buffer, typeSize);
break;
case(Endianness::LITTLE):
EndianConverter::convertLittleEndian(value, *buffer, typeSize);
break;
case(Endianness::MACHINE):
default:
memcpy(value, *buffer, typeSize);
break;
}
*size -= typeSize;
*buffer += typeSize;
return HasReturnvaluesIF::RETURN_OK;
}
else {
return SerializeIF::STREAM_TOO_SHORT;
}
}

View File

@ -1,220 +1,220 @@
#ifndef POOLRAWACCESS_H_
#define POOLRAWACCESS_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntryIF.h"
#include "../datapool/PoolVariableIF.h"
#include "../globalfunctions/Type.h"
/**
* @brief This class allows accessing Data Pool variables as raw bytes.
* @details
* This is necessary to have an access method for HK data, as the PID's alone
* do not provide type information. Please note that the the raw pool access
* read() and commit() calls are not thread-safe.
*
* Please supply a data set and use the data set read(), commit() calls for
* thread-safe data pool access.
* @ingroup data_pool
*/
class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
public:
/**
* This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied
* and the data pool entry with the given ID is registered to that data set.
* Please note that a pool raw access buffer only has a buffer
* with a size of double. As such, for vector entries which have
* @param data_pool_id Target data pool entry ID
* @param arrayEntry
* @param data_set Dataset to register data pool entry to
* @param setReadWriteMode
* @param registerVectors If set to true, the constructor checks if
* there are multiple vector entries to registers
* and registers all of them recursively into the data_set
*
*/
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ);
/**
* @brief This operation returns a pointer to the entry fetched.
* @details Return pointer to the buffer containing the raw data
* Size and number of data can be retrieved by other means.
*/
uint8_t* getEntry();
/**
* @brief This operation returns the fetched entry from the data pool and
* flips the bytes, if necessary.
* @details It makes use of the getEntry call of this function, but additionally flips the
* bytes to big endian, which is the default for external communication (as House-
* keeping telemetry). To achieve this, the data is copied directly to the passed
* buffer, if it fits in the given max_size.
* @param buffer A pointer to a buffer to write to
* @param writtenBytes The number of bytes written is returned with this value.
* @param max_size The maximum size that the function may write to buffer.
* @return - @c RETURN_OK if entry could be acquired
* - @c RETURN_FAILED else.
*/
ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size,
size_t maxSize);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
/**
* With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set
* @param size Size of the data to write. Must fit this->size.
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
size_t setSize);
/**
* @brief This operation returns the type of the entry currently stored.
*/
Type getType();
/**
* @brief This operation returns the size of the entry currently stored.
*/
size_t getSizeOfType();
/**
*
* @return the size of the datapool array
*/
size_t getArraySize();
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const;
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE];
/**
* @brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~PoolRawAccess();
/**
* This method returns if the variable is read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const;
void setValid(bool valid);
/**
* Getter for the remaining size.
*/
size_t getSizeTillEnd() const;
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The call is protected by a lock of the global data pool.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The call is protected by a lock of the global data pool.
*
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
void handleReadError(ReturnValue_t result);
private:
/**
* @brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* @brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* @brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* @brief This value contains the type of the data pool entry.
*/
Type type;
/**
* @brief This value contains the size of the data pool entry type in bytes.
*/
size_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
size_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
size_t sizeTillEnd;
/**
* @brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#endif /* POOLRAWACCESS_H_ */
#ifndef POOLRAWACCESS_H_
#define POOLRAWACCESS_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntryIF.h"
#include "../datapool/PoolVariableIF.h"
#include "../globalfunctions/Type.h"
/**
* @brief This class allows accessing Data Pool variables as raw bytes.
* @details
* This is necessary to have an access method for HK data, as the PID's alone
* do not provide type information. Please note that the the raw pool access
* read() and commit() calls are not thread-safe.
*
* Please supply a data set and use the data set read(), commit() calls for
* thread-safe data pool access.
* @ingroup data_pool
*/
class PoolRawAccess: public PoolVariableIF, HasReturnvaluesIF {
public:
/**
* This constructor is used to access a data pool entry with a
* given ID if the target type is not known. A DataSet object is supplied
* and the data pool entry with the given ID is registered to that data set.
* Please note that a pool raw access buffer only has a buffer
* with a size of double. As such, for vector entries which have
* @param data_pool_id Target data pool entry ID
* @param arrayEntry
* @param data_set Dataset to register data pool entry to
* @param setReadWriteMode
* @param registerVectors If set to true, the constructor checks if
* there are multiple vector entries to registers
* and registers all of them recursively into the data_set
*
*/
PoolRawAccess(uint32_t data_pool_id, uint8_t arrayEntry,
DataSetIF* data_set, ReadWriteMode_t setReadWriteMode =
PoolVariableIF::VAR_READ);
/**
* @brief This operation returns a pointer to the entry fetched.
* @details Return pointer to the buffer containing the raw data
* Size and number of data can be retrieved by other means.
*/
uint8_t* getEntry();
/**
* @brief This operation returns the fetched entry from the data pool and
* flips the bytes, if necessary.
* @details It makes use of the getEntry call of this function, but additionally flips the
* bytes to big endian, which is the default for external communication (as House-
* keeping telemetry). To achieve this, the data is copied directly to the passed
* buffer, if it fits in the given max_size.
* @param buffer A pointer to a buffer to write to
* @param writtenBytes The number of bytes written is returned with this value.
* @param max_size The maximum size that the function may write to buffer.
* @return - @c RETURN_OK if entry could be acquired
* - @c RETURN_FAILED else.
*/
ReturnValue_t getEntryEndianSafe(uint8_t *buffer, size_t *size,
size_t maxSize);
/**
* @brief Serialize raw pool entry into provided buffer directly
* @param buffer Provided buffer. Raw pool data will be copied here
* @param size [out] Increment provided size value by serialized size
* @param max_size Maximum allowed serialization size
* @param bigEndian Specify endianess
* @return - @c RETURN_OK if serialization was successfull
* - @c SerializeIF::BUFFER_TOO_SHORT if range check failed
*/
ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
/**
* With this method, the content can be set from a big endian buffer safely.
* @param buffer Pointer to the data to set
* @param size Size of the data to write. Must fit this->size.
* @return - @c RETURN_OK on success
* - @c RETURN_FAILED on failure
*/
ReturnValue_t setEntryFromBigEndian(const uint8_t* buffer,
size_t setSize);
/**
* @brief This operation returns the type of the entry currently stored.
*/
Type getType();
/**
* @brief This operation returns the size of the entry currently stored.
*/
size_t getSizeOfType();
/**
*
* @return the size of the datapool array
*/
size_t getArraySize();
/**
* @brief This operation returns the data pool id of the variable.
*/
uint32_t getDataPoolId() const;
static const uint8_t INTERFACE_ID = CLASS_ID::POOL_RAW_ACCESS_CLASS;
static const ReturnValue_t INCORRECT_SIZE = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t DATA_POOL_ACCESS_FAILED = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t READ_TYPE_TOO_LARGE = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t READ_INDEX_TOO_LARGE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t READ_ENTRY_NON_EXISTENT = MAKE_RETURN_CODE(0x05);
static const uint8_t RAW_MAX_SIZE = sizeof(double);
uint8_t value[RAW_MAX_SIZE];
/**
* @brief The classes destructor is empty. If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~PoolRawAccess();
/**
* This method returns if the variable is read-write or read-only.
*/
ReadWriteMode_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const;
void setValid(bool valid);
/**
* Getter for the remaining size.
*/
size_t getSizeTillEnd() const;
/**
* @brief This is a call to read the value from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the global data pool and copies the value and the valid
* information to its local attributes. In case of a failure (wrong type or
* pool id not found), the variable is set to zero and invalid.
* The call is protected by a lock of the global data pool.
* @return -@c RETURN_OK Read successfull
* -@c READ_TYPE_TOO_LARGE
* -@c READ_INDEX_TOO_LARGE
* -@c READ_ENTRY_NON_EXISTENT
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call writes back the variable's value to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the valid flag is automatically set to "valid".
* The call is protected by a lock of the global data pool.
*
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
ReturnValue_t handleReadOut(PoolEntryIF* read_out);
void handleReadError(ReturnValue_t result);
private:
/**
* @brief To access the correct data pool entry on read and commit calls, the data pool id
* is stored.
*/
uint32_t dataPoolId;
/**
* @brief The array entry that is fetched from the data pool.
*/
uint8_t arrayEntry;
/**
* @brief The valid information as it was stored in the data pool is copied to this attribute.
*/
uint8_t valid;
/**
* @brief This value contains the type of the data pool entry.
*/
Type type;
/**
* @brief This value contains the size of the data pool entry type in bytes.
*/
size_t typeSize;
/**
* The size of the DP array (single values return 1)
*/
size_t arraySize;
/**
* The size (in bytes) from the selected entry till the end of this DataPool variable.
*/
size_t sizeTillEnd;
/**
* @brief The information whether the class is read-write or read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
};
#endif /* POOLRAWACCESS_H_ */

View File

@ -1,200 +1,200 @@
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
/**
* @brief This is the access class for array-type data pool entries.
* @details
* To ensure safe usage of the data pool, operation is not done directly on the
* data pool entries, but on local copies. This class provides simple type-
* and length-safe access to vector-style data pool entries (i.e. entries with
* length > 1). The class can be instantiated as read-write and read only.
*
* It provides a commit-and-roll-back semantic, which means that no array
* entry in the data pool is changed until the commit call is executed.
* There are two template parameters:
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template<typename T, uint16_t vectorSize>
class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF {
public:
LocalPoolVector() = delete;
/**
* This constructor is used by the data creators to have pool variable
* instances which can also be stored in datasets.
* It does not fetch the current value from the data pool. This is performed
* by the read() operation (which is not thread-safe).
* Datasets can be used to access local pool entires in a thread-safe way.
* @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.
*/
LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
DataSetIF* dataSet = nullptr);
/**
* This constructor is used by data users like controllers to have
* access to the local pool variables of data creators by supplying
* the respective creator object ID.
* It does not fetch the current value from the data pool. This is performed
* by the read() operation (which is not thread-safe).
* Datasets can be used to access local pool entires in a thread-safe way.
* @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.
*/
LocalPoolVector(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
DataSetIF* dataSet = nullptr);
/**
* @brief This is the local copy of the data pool entry.
* @details
* The user can work on this attribute just like he would on a local
* array of this type.
*/
T value[vectorSize];
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~LocalPoolVector() {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() {
return vectorSize;
}
uint32_t getDataPoolId() const override;
/**
* @brief This operation sets the data pool ID of the variable.
* @details
* The method is necessary to set id's of data pool member variables
* with bad initialization.
*/
void setDataPoolId(uint32_t poolId);
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
pool_rwm_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const override;
void setValid(bool valid) override;
uint8_t getValid() const;
T& operator [](int i);
const T &operator [](int i) const;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the data pool and copies all array values and the valid
* information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the local valid flag is written back as well.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
private:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t localPoolId;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
bool valid;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
//! @brief Pointer to the class which manages the HK pool.
LocalDataPoolManager* hkManager;
// std::ostream is the type for object std::cout
template <typename U, uint16_t otherSize>
friend std::ostream& operator<< (std::ostream &out,
const LocalPoolVector<U, otherSize> &var);
};
#include "../datapoollocal/LocalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using lp_vec_t = LocalPoolVector<T, vectorSize>;
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */
#ifndef FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#define FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
/**
* @brief This is the access class for array-type data pool entries.
* @details
* To ensure safe usage of the data pool, operation is not done directly on the
* data pool entries, but on local copies. This class provides simple type-
* and length-safe access to vector-style data pool entries (i.e. entries with
* length > 1). The class can be instantiated as read-write and read only.
*
* It provides a commit-and-roll-back semantic, which means that no array
* entry in the data pool is changed until the commit call is executed.
* There are two template parameters:
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template<typename T, uint16_t vectorSize>
class LocalPoolVector: public PoolVariableIF, public HasReturnvaluesIF {
public:
LocalPoolVector() = delete;
/**
* This constructor is used by the data creators to have pool variable
* instances which can also be stored in datasets.
* It does not fetch the current value from the data pool. This is performed
* by the read() operation (which is not thread-safe).
* Datasets can be used to access local pool entires in a thread-safe way.
* @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.
*/
LocalPoolVector(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
DataSetIF* dataSet = nullptr);
/**
* This constructor is used by data users like controllers to have
* access to the local pool variables of data creators by supplying
* the respective creator object ID.
* It does not fetch the current value from the data pool. This is performed
* by the read() operation (which is not thread-safe).
* Datasets can be used to access local pool entires in a thread-safe way.
* @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.
*/
LocalPoolVector(lp_id_t poolId, object_id_t poolOwner,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE,
DataSetIF* dataSet = nullptr);
/**
* @brief This is the local copy of the data pool entry.
* @details
* The user can work on this attribute just like he would on a local
* array of this type.
*/
T value[vectorSize];
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~LocalPoolVector() {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() {
return vectorSize;
}
uint32_t getDataPoolId() const override;
/**
* @brief This operation sets the data pool ID of the variable.
* @details
* The method is necessary to set id's of data pool member variables
* with bad initialization.
*/
void setDataPoolId(uint32_t poolId);
/**
* This method returns if the variable is write-only, read-write or read-only.
*/
pool_rwm_t getReadWriteMode() const;
/**
* @brief With this call, the valid information of the variable is returned.
*/
bool isValid() const override;
void setValid(bool valid) override;
uint8_t getValid() const;
T& operator [](int i);
const T &operator [](int i) const;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the data pool and copies all array values and the valid
* information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(uint32_t lockTimeout = MutexIF::BLOCKING) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the local valid flag is written back as well.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(uint32_t lockTimeout = MutexIF::BLOCKING) override;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
private:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t localPoolId;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
bool valid;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode;
//! @brief Pointer to the class which manages the HK pool.
LocalDataPoolManager* hkManager;
// std::ostream is the type for object std::cout
template <typename U, uint16_t otherSize>
friend std::ostream& operator<< (std::ostream &out,
const LocalPoolVector<U, otherSize> &var);
};
#include "../datapoollocal/LocalPoolVector.tpp"
template<typename T, uint16_t vectorSize>
using lp_vec_t = LocalPoolVector<T, vectorSize>;
#endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */

View File

@ -1,16 +1,16 @@
#include "SharedLocalDataSet.h"
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
const size_t maxSize): SystemObject(objectId),
LocalPoolDataSetBase(sid, nullptr, maxSize) {
this->setContainer(poolVarVector.data());
datasetLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) {
return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout);
}
ReturnValue_t SharedLocalDataSet::unlockDataset() {
return datasetLock->unlockMutex();
}
#include "SharedLocalDataSet.h"
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
const size_t maxSize): SystemObject(objectId),
LocalPoolDataSetBase(sid, nullptr, maxSize) {
this->setContainer(poolVarVector.data());
datasetLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedLocalDataSet::lockDataset(dur_millis_t mutexTimeout) {
return datasetLock->lockMutex(MutexIF::TimeoutType::WAITING, mutexTimeout);
}
ReturnValue_t SharedLocalDataSet::unlockDataset() {
return datasetLock->unlockMutex();
}

View File

@ -1,19 +1,19 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
#define FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
#include "../ipc/MessageQueueSenderIF.h"
/**
* This interface is used by the device handler to send a device response
* to the queue ID, which is returned in the implemented abstract method.
*/
class AcceptsDeviceResponsesIF {
public:
/**
* Default empty virtual destructor.
*/
virtual ~AcceptsDeviceResponsesIF() {}
virtual MessageQueueId_t getDeviceQueue() = 0;
};
#endif /* FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ */
#ifndef FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
#define FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_
#include "../ipc/MessageQueueSenderIF.h"
/**
* This interface is used by the device handler to send a device response
* to the queue ID, which is returned in the implemented abstract method.
*/
class AcceptsDeviceResponsesIF {
public:
/**
* Default empty virtual destructor.
*/
virtual ~AcceptsDeviceResponsesIF() {}
virtual MessageQueueId_t getDeviceQueue() = 0;
};
#endif /* FRAMEWORK_DEVICEHANDLERS_ACCEPTSDEVICERESPONSESIF_H_ */

View File

@ -1,273 +1,273 @@
#include "../devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId,
uint16_t commandQueueDepth) :
SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE), recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()), targetMode(MODE_OFF),
targetSubmode(SUBMODE_NONE) {
recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS);
}
AssemblyBase::~AssemblyBase() {
}
ReturnValue_t AssemblyBase::handleCommandMessage(CommandMessage* message) {
return handleHealthReply(message);
}
void AssemblyBase::performChildOperation() {
if (isInTransition()) {
handleChildrenTransition();
} else {
handleChildrenChanged();
}
}
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
targetMode = mode;
targetSubmode = submode;
internalState = STATE_SINGLE_STEP;
ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
}
}
bool AssemblyBase::isInTransition() {
return (internalState != STATE_NONE) || (recoveryState != RECOVERY_IDLE);
}
bool AssemblyBase::handleChildrenChanged() {
if (childrenChangedMode) {
ReturnValue_t result = checkChildrenState();
if (result != RETURN_OK) {
handleChildrenLostMode(result);
}
return true;
} else {
return handleChildrenChangedHealth();
}
}
void AssemblyBase::handleChildrenLostMode(ReturnValue_t result) {
triggerEvent(CANT_KEEP_MODE, mode, submode);
startTransition(MODE_OFF, SUBMODE_NONE);
}
bool AssemblyBase::handleChildrenChangedHealth() {
auto iter = childrenMap.begin();
for (; iter != childrenMap.end(); iter++) {
if (iter->second.healthChanged) {
iter->second.healthChanged = false;
break;
}
}
if (iter == childrenMap.end()) {
return false;
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
doStartTransition(mode, submode);
}
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, targetMode, targetSubmode);
}
return true;
}
void AssemblyBase::handleChildrenTransition() {
if (commandsOutstanding <= 0) {
switch (internalState) {
case STATE_NEED_SECOND_STEP:
internalState = STATE_SECOND_STEP;
commandChildren(targetMode, targetSubmode);
return;
case STATE_OVERWRITE_HEALTH: {
internalState = STATE_SINGLE_STEP;
ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
}
return;
}
case STATE_NONE:
//Valid state, used in recovery.
case STATE_SINGLE_STEP:
case STATE_SECOND_STEP:
if (checkAndHandleRecovery()) {
return;
}
break;
}
ReturnValue_t result = checkChildrenState();
if (result == RETURN_OK) {
handleModeReached();
} else {
handleModeTransitionFailed(result);
}
}
}
void AssemblyBase::handleModeReached() {
internalState = STATE_NONE;
setMode(targetMode, targetSubmode);
}
void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
//always accept transition to OFF, there is nothing we can do except sending an info event
//In theory this should never happen, but we would risk an infinite loop otherwise
if (targetMode == MODE_OFF) {
triggerEvent(CHILD_PROBLEMS, result);
internalState = STATE_NONE;
setMode(targetMode, targetSubmode);
} else {
if (handleChildrenChangedHealth()) {
//If any health change is pending, handle that first.
return;
}
triggerEvent(MODE_TRANSITION_FAILED, result);
startTransition(MODE_OFF, SUBMODE_NONE);
}
}
void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
HealthState health) {
CommandMessage command;
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
health);
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
commandsOutstanding++;
}
}
ReturnValue_t AssemblyBase::checkChildrenState() {
if (targetMode == MODE_OFF) {
return checkChildrenStateOff();
} else {
return checkChildrenStateOn(targetMode, targetSubmode);
}
}
ReturnValue_t AssemblyBase::checkChildrenStateOff() {
for (const auto& childIter: childrenMap) {
if (checkChildOff(childIter.first) != RETURN_OK) {
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
}
}
return RETURN_OK;
}
ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) {
ChildInfo childInfo = childrenMap.find(objectId)->second;
if (healthHelper.healthTable->isCommandable(objectId)) {
if (childInfo.submode != SUBMODE_NONE) {
return RETURN_FAILED;
} else {
if ((childInfo.mode != MODE_OFF)
&& (childInfo.mode != DeviceHandlerIF::MODE_ERROR_ON)) {
return RETURN_FAILED;
}
}
}
return RETURN_OK;
}
ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
//always accept transition to OFF
if (mode == MODE_OFF) {
if (submode != SUBMODE_NONE) {
return INVALID_SUBMODE;
}
return RETURN_OK;
}
if ((mode != MODE_ON) && (mode != DeviceHandlerIF::MODE_NORMAL)) {
return INVALID_MODE;
}
if (internalState != STATE_NONE) {
return IN_TRANSITION;
}
return isModeCombinationValid(mode, submode);
}
ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
if (message->getCommand() == HealthMessage::HEALTH_INFO) {
HealthState health = HealthMessage::getHealth(message);
if (health != EXTERNAL_CONTROL) {
updateChildChangedHealth(message->getSender(), true);
}
return RETURN_OK;
}
if (message->getCommand() == HealthMessage::REPLY_HEALTH_SET
|| (message->getCommand() == CommandMessage::REPLY_REJECTED
&& message->getParameter2() == HealthMessage::HEALTH_SET)) {
if (isInTransition()) {
commandsOutstanding--;
}
return RETURN_OK;
}
return RETURN_FAILED;
}
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
case RECOVERY_WAIT:
if (recoveryOffTimer.isBusy()) {
return true;
}
triggerEvent(RECOVERY_STEP, 0);
sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY);
internalState = STATE_NONE;
recoveryState = RECOVERY_ONGOING;
//Don't check state!
return true;
case RECOVERY_ONGOING:
triggerEvent(RECOVERY_STEP, 1);
recoveryState = RECOVERY_ONGOING_2;
recoveringDevice->second.healthChanged = false;
//Device should be healthy again, so restart a transition.
//Might be including second step, but that's already handled.
doStartTransition(targetMode, targetSubmode);
return true;
case RECOVERY_ONGOING_2:
triggerEvent(RECOVERY_DONE);
//Now we're through, but not sure if it was successful.
recoveryState = RECOVERY_IDLE;
return false;
case RECOVERY_IDLE:
default:
return false;
}
}
void AssemblyBase::overwriteDeviceHealth(object_id_t objectId,
HasHealthIF::HealthState oldHealth) {
triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth);
internalState = STATE_OVERWRITE_HEALTH;
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}
#include "../devicehandlers/AssemblyBase.h"
AssemblyBase::AssemblyBase(object_id_t objectId, object_id_t parentId,
uint16_t commandQueueDepth) :
SubsystemBase(objectId, parentId, MODE_OFF, commandQueueDepth),
internalState(STATE_NONE), recoveryState(RECOVERY_IDLE),
recoveringDevice(childrenMap.end()), targetMode(MODE_OFF),
targetSubmode(SUBMODE_NONE) {
recoveryOffTimer.setTimeout(POWER_OFF_TIME_MS);
}
AssemblyBase::~AssemblyBase() {
}
ReturnValue_t AssemblyBase::handleCommandMessage(CommandMessage* message) {
return handleHealthReply(message);
}
void AssemblyBase::performChildOperation() {
if (isInTransition()) {
handleChildrenTransition();
} else {
handleChildrenChanged();
}
}
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}
void AssemblyBase::doStartTransition(Mode_t mode, Submode_t submode) {
targetMode = mode;
targetSubmode = submode;
internalState = STATE_SINGLE_STEP;
ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
}
}
bool AssemblyBase::isInTransition() {
return (internalState != STATE_NONE) || (recoveryState != RECOVERY_IDLE);
}
bool AssemblyBase::handleChildrenChanged() {
if (childrenChangedMode) {
ReturnValue_t result = checkChildrenState();
if (result != RETURN_OK) {
handleChildrenLostMode(result);
}
return true;
} else {
return handleChildrenChangedHealth();
}
}
void AssemblyBase::handleChildrenLostMode(ReturnValue_t result) {
triggerEvent(CANT_KEEP_MODE, mode, submode);
startTransition(MODE_OFF, SUBMODE_NONE);
}
bool AssemblyBase::handleChildrenChangedHealth() {
auto iter = childrenMap.begin();
for (; iter != childrenMap.end(); iter++) {
if (iter->second.healthChanged) {
iter->second.healthChanged = false;
break;
}
}
if (iter == childrenMap.end()) {
return false;
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
doStartTransition(mode, submode);
}
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, targetMode, targetSubmode);
}
return true;
}
void AssemblyBase::handleChildrenTransition() {
if (commandsOutstanding <= 0) {
switch (internalState) {
case STATE_NEED_SECOND_STEP:
internalState = STATE_SECOND_STEP;
commandChildren(targetMode, targetSubmode);
return;
case STATE_OVERWRITE_HEALTH: {
internalState = STATE_SINGLE_STEP;
ReturnValue_t result = commandChildren(mode, submode);
if (result == NEED_SECOND_STEP) {
internalState = STATE_NEED_SECOND_STEP;
}
return;
}
case STATE_NONE:
//Valid state, used in recovery.
case STATE_SINGLE_STEP:
case STATE_SECOND_STEP:
if (checkAndHandleRecovery()) {
return;
}
break;
}
ReturnValue_t result = checkChildrenState();
if (result == RETURN_OK) {
handleModeReached();
} else {
handleModeTransitionFailed(result);
}
}
}
void AssemblyBase::handleModeReached() {
internalState = STATE_NONE;
setMode(targetMode, targetSubmode);
}
void AssemblyBase::handleModeTransitionFailed(ReturnValue_t result) {
//always accept transition to OFF, there is nothing we can do except sending an info event
//In theory this should never happen, but we would risk an infinite loop otherwise
if (targetMode == MODE_OFF) {
triggerEvent(CHILD_PROBLEMS, result);
internalState = STATE_NONE;
setMode(targetMode, targetSubmode);
} else {
if (handleChildrenChangedHealth()) {
//If any health change is pending, handle that first.
return;
}
triggerEvent(MODE_TRANSITION_FAILED, result);
startTransition(MODE_OFF, SUBMODE_NONE);
}
}
void AssemblyBase::sendHealthCommand(MessageQueueId_t sendTo,
HealthState health) {
CommandMessage command;
HealthMessage::setHealthMessage(&command, HealthMessage::HEALTH_SET,
health);
if (commandQueue->sendMessage(sendTo, &command) == RETURN_OK) {
commandsOutstanding++;
}
}
ReturnValue_t AssemblyBase::checkChildrenState() {
if (targetMode == MODE_OFF) {
return checkChildrenStateOff();
} else {
return checkChildrenStateOn(targetMode, targetSubmode);
}
}
ReturnValue_t AssemblyBase::checkChildrenStateOff() {
for (const auto& childIter: childrenMap) {
if (checkChildOff(childIter.first) != RETURN_OK) {
return NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE;
}
}
return RETURN_OK;
}
ReturnValue_t AssemblyBase::checkChildOff(uint32_t objectId) {
ChildInfo childInfo = childrenMap.find(objectId)->second;
if (healthHelper.healthTable->isCommandable(objectId)) {
if (childInfo.submode != SUBMODE_NONE) {
return RETURN_FAILED;
} else {
if ((childInfo.mode != MODE_OFF)
&& (childInfo.mode != DeviceHandlerIF::MODE_ERROR_ON)) {
return RETURN_FAILED;
}
}
}
return RETURN_OK;
}
ReturnValue_t AssemblyBase::checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) {
//always accept transition to OFF
if (mode == MODE_OFF) {
if (submode != SUBMODE_NONE) {
return INVALID_SUBMODE;
}
return RETURN_OK;
}
if ((mode != MODE_ON) && (mode != DeviceHandlerIF::MODE_NORMAL)) {
return INVALID_MODE;
}
if (internalState != STATE_NONE) {
return IN_TRANSITION;
}
return isModeCombinationValid(mode, submode);
}
ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
if (message->getCommand() == HealthMessage::HEALTH_INFO) {
HealthState health = HealthMessage::getHealth(message);
if (health != EXTERNAL_CONTROL) {
updateChildChangedHealth(message->getSender(), true);
}
return RETURN_OK;
}
if (message->getCommand() == HealthMessage::REPLY_HEALTH_SET
|| (message->getCommand() == CommandMessage::REPLY_REJECTED
&& message->getParameter2() == HealthMessage::HEALTH_SET)) {
if (isInTransition()) {
commandsOutstanding--;
}
return RETURN_OK;
}
return RETURN_FAILED;
}
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
case RECOVERY_WAIT:
if (recoveryOffTimer.isBusy()) {
return true;
}
triggerEvent(RECOVERY_STEP, 0);
sendHealthCommand(recoveringDevice->second.commandQueue, HEALTHY);
internalState = STATE_NONE;
recoveryState = RECOVERY_ONGOING;
//Don't check state!
return true;
case RECOVERY_ONGOING:
triggerEvent(RECOVERY_STEP, 1);
recoveryState = RECOVERY_ONGOING_2;
recoveringDevice->second.healthChanged = false;
//Device should be healthy again, so restart a transition.
//Might be including second step, but that's already handled.
doStartTransition(targetMode, targetSubmode);
return true;
case RECOVERY_ONGOING_2:
triggerEvent(RECOVERY_DONE);
//Now we're through, but not sure if it was successful.
recoveryState = RECOVERY_IDLE;
return false;
case RECOVERY_IDLE:
default:
return false;
}
}
void AssemblyBase::overwriteDeviceHealth(object_id_t objectId,
HasHealthIF::HealthState oldHealth) {
triggerEvent(OVERWRITING_HEALTH, objectId, oldHealth);
internalState = STATE_OVERWRITE_HEALTH;
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}

View File

@ -1,163 +1,163 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
#define FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
#include "../container/FixedArrayList.h"
#include "../devicehandlers/DeviceHandlerBase.h"
#include "../subsystem/SubsystemBase.h"
/**
* @brief Base class to implement reconfiguration and failure handling for
* redundant devices by monitoring their modes health states.
* @details
* Documentation: Dissertation Baetz p.156, 157.
*
* This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices.
*
* The template class monitors mode and health state of its children
* and checks availability of devices on every detected change.
* AssemblyBase does not implement any redundancy logic by itself, but provides
* adaptation points for implementations to do so. Since most monitoring
* activities rely on mode and health state only and are therefore
* generic, it is sufficient for subclasses to provide:
*
* 1. check logic when active-> checkChildrenStateOn
* 2. transition logic to change the mode -> commandChildren
*
*/
class AssemblyBase: public SubsystemBase {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t CHILD_NOT_COMMANDABLE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE =
MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, object_id_t parentId,
uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase();
protected:
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
// (or return internalState directly?)
/**
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* @param mode
* @param submode
* @return
* - @c RETURN_OK if ok
* - @c NEED_SECOND_STEP if children need to be commanded again
*/
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
/**
* Check whether desired assembly mode was achieved by checking the modes
* or/and health states of child device handlers.
* The assembly template class will also call this function if a health
* or mode change of a child device handler was detected.
* @param wantedMode
* @param wantedSubmode
* @return
*/
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
Submode_t wantedSubmode) = 0;
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode) = 0;
enum InternalState {
STATE_NONE,
STATE_OVERWRITE_HEALTH,
STATE_NEED_SECOND_STEP,
STATE_SINGLE_STEP,
STATE_SECOND_STEP,
} internalState;
enum RecoveryState {
RECOVERY_IDLE,
RECOVERY_STARTED,
RECOVERY_ONGOING,
RECOVERY_ONGOING_2,
RECOVERY_WAIT
} recoveryState; //!< Indicates if one of the children requested a recovery.
ChildrenMap::iterator recoveringDevice;
/**
* the mode the current transition is trying to achieve.
* Can be different from the modehelper.commandedMode!
*/
Mode_t targetMode;
/**
* the submode the current transition is trying to achieve.
* Can be different from the modehelper.commandedSubmode!
*/
Submode_t targetSubmode;
Countdown recoveryOffTimer;
static const uint32_t POWER_OFF_TIME_MS = 1000;
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
virtual void performChildOperation();
bool handleChildrenChanged();
/**
* This method is called if the children changed its mode in a way that
* the current mode can't be kept.
* Default behavior is to go to MODE_OFF.
* @param result The failure code which was returned by checkChildrenState.
*/
virtual void handleChildrenLostMode(ReturnValue_t result);
bool handleChildrenChangedHealth();
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
virtual void handleModeReached();
virtual void handleModeTransitionFailed(ReturnValue_t result);
void sendHealthCommand(MessageQueueId_t sendTo, HealthState health);
virtual ReturnValue_t checkChildrenStateOff();
ReturnValue_t checkChildrenState();
virtual ReturnValue_t checkChildOff(uint32_t objectId);
/**
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
* Also sets state to STATE_OVERWRITE_HEATH.
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
};
#endif /* FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_ */
#ifndef FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
#define FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_
#include "../container/FixedArrayList.h"
#include "../devicehandlers/DeviceHandlerBase.h"
#include "../subsystem/SubsystemBase.h"
/**
* @brief Base class to implement reconfiguration and failure handling for
* redundant devices by monitoring their modes health states.
* @details
* Documentation: Dissertation Baetz p.156, 157.
*
* This class reduces the complexity of controller components which would
* otherwise be needed for the handling of redundant devices.
*
* The template class monitors mode and health state of its children
* and checks availability of devices on every detected change.
* AssemblyBase does not implement any redundancy logic by itself, but provides
* adaptation points for implementations to do so. Since most monitoring
* activities rely on mode and health state only and are therefore
* generic, it is sufficient for subclasses to provide:
*
* 1. check logic when active-> checkChildrenStateOn
* 2. transition logic to change the mode -> commandChildren
*
*/
class AssemblyBase: public SubsystemBase {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ASSEMBLY_BASE;
static const ReturnValue_t NEED_SECOND_STEP = MAKE_RETURN_CODE(0x01);
static const ReturnValue_t NEED_TO_RECONFIGURE = MAKE_RETURN_CODE(0x02);
static const ReturnValue_t MODE_FALLBACK = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t CHILD_NOT_COMMANDABLE = MAKE_RETURN_CODE(0x04);
static const ReturnValue_t NEED_TO_CHANGE_HEALTH = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t NOT_ENOUGH_CHILDREN_IN_CORRECT_STATE =
MAKE_RETURN_CODE(0xa1);
AssemblyBase(object_id_t objectId, object_id_t parentId,
uint16_t commandQueueDepth = 8);
virtual ~AssemblyBase();
protected:
// SHOULDDO: Change that OVERWRITE_HEALTH may be returned
// (or return internalState directly?)
/**
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* @param mode
* @param submode
* @return
* - @c RETURN_OK if ok
* - @c NEED_SECOND_STEP if children need to be commanded again
*/
virtual ReturnValue_t commandChildren(Mode_t mode, Submode_t submode) = 0;
/**
* Check whether desired assembly mode was achieved by checking the modes
* or/and health states of child device handlers.
* The assembly template class will also call this function if a health
* or mode change of a child device handler was detected.
* @param wantedMode
* @param wantedSubmode
* @return
*/
virtual ReturnValue_t checkChildrenStateOn(Mode_t wantedMode,
Submode_t wantedSubmode) = 0;
virtual ReturnValue_t isModeCombinationValid(Mode_t mode,
Submode_t submode) = 0;
enum InternalState {
STATE_NONE,
STATE_OVERWRITE_HEALTH,
STATE_NEED_SECOND_STEP,
STATE_SINGLE_STEP,
STATE_SECOND_STEP,
} internalState;
enum RecoveryState {
RECOVERY_IDLE,
RECOVERY_STARTED,
RECOVERY_ONGOING,
RECOVERY_ONGOING_2,
RECOVERY_WAIT
} recoveryState; //!< Indicates if one of the children requested a recovery.
ChildrenMap::iterator recoveringDevice;
/**
* the mode the current transition is trying to achieve.
* Can be different from the modehelper.commandedMode!
*/
Mode_t targetMode;
/**
* the submode the current transition is trying to achieve.
* Can be different from the modehelper.commandedSubmode!
*/
Submode_t targetSubmode;
Countdown recoveryOffTimer;
static const uint32_t POWER_OFF_TIME_MS = 1000;
virtual ReturnValue_t handleCommandMessage(CommandMessage *message);
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
virtual void performChildOperation();
bool handleChildrenChanged();
/**
* This method is called if the children changed its mode in a way that
* the current mode can't be kept.
* Default behavior is to go to MODE_OFF.
* @param result The failure code which was returned by checkChildrenState.
*/
virtual void handleChildrenLostMode(ReturnValue_t result);
bool handleChildrenChangedHealth();
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t *msToReachTheMode);
virtual void startTransition(Mode_t mode, Submode_t submode);
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
virtual void handleModeReached();
virtual void handleModeTransitionFailed(ReturnValue_t result);
void sendHealthCommand(MessageQueueId_t sendTo, HealthState health);
virtual ReturnValue_t checkChildrenStateOff();
ReturnValue_t checkChildrenState();
virtual ReturnValue_t checkChildOff(uint32_t objectId);
/**
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
* Also sets state to STATE_OVERWRITE_HEATH.
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
};
#endif /* FRAMEWORK_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -1,47 +1,47 @@
#include "../subsystem/SubsystemBase.h"
#include "../devicehandlers/ChildHandlerBase.h"
#include "../subsystem/SubsystemBase.h"
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
object_id_t deviceCommunication, CookieIF * cookie,
object_id_t hkDestination, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId,
object_id_t parent,
FailureIsolationBase* customFdir, size_t cmdQueueSize) :
DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
(customFdir == nullptr? &childHandlerFdir : customFdir),
cmdQueueSize),
parentId(parent), childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(thermalStatePoolId,
thermalRequestPoolId);
}
ChildHandlerBase::~ChildHandlerBase() {
}
ReturnValue_t ChildHandlerBase::initialize() {
ReturnValue_t result = DeviceHandlerBase::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
healthHelper.setParentQueue(parentQueue);
modeHelper.setParentQueue(parentQueue);
return RETURN_OK;
}
#include "../subsystem/SubsystemBase.h"
#include "../devicehandlers/ChildHandlerBase.h"
#include "../subsystem/SubsystemBase.h"
ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId,
object_id_t deviceCommunication, CookieIF * cookie,
object_id_t hkDestination, uint32_t thermalStatePoolId,
uint32_t thermalRequestPoolId,
object_id_t parent,
FailureIsolationBase* customFdir, size_t cmdQueueSize) :
DeviceHandlerBase(setObjectId, deviceCommunication, cookie,
(customFdir == nullptr? &childHandlerFdir : customFdir),
cmdQueueSize),
parentId(parent), childHandlerFdir(setObjectId) {
this->setHkDestination(hkDestination);
this->setThermalStateRequestPoolIds(thermalStatePoolId,
thermalRequestPoolId);
}
ChildHandlerBase::~ChildHandlerBase() {
}
ReturnValue_t ChildHandlerBase::initialize() {
ReturnValue_t result = DeviceHandlerBase::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
MessageQueueId_t parentQueue = 0;
if (parentId != objects::NO_OBJECT) {
SubsystemBase *parent = objectManager->get<SubsystemBase>(parentId);
if (parent == NULL) {
return RETURN_FAILED;
}
parentQueue = parent->getCommandQueue();
parent->registerChild(getObjectId());
}
healthHelper.setParentQueue(parentQueue);
modeHelper.setParentQueue(parentQueue);
return RETURN_OK;
}

View File

@ -1,24 +1,24 @@
#ifndef PAYLOADHANDLERBASE_H_
#define PAYLOADHANDLERBASE_H_
#include "../devicehandlers/ChildHandlerFDIR.h"
#include "../devicehandlers/DeviceHandlerBase.h"
class ChildHandlerBase: public DeviceHandlerBase {
public:
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
CookieIF * cookie, object_id_t hkDestination,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
object_id_t parent = objects::NO_OBJECT,
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize();
protected:
const uint32_t parentId;
ChildHandlerFDIR childHandlerFdir;
};
#endif /* PAYLOADHANDLERBASE_H_ */
#ifndef PAYLOADHANDLERBASE_H_
#define PAYLOADHANDLERBASE_H_
#include "../devicehandlers/ChildHandlerFDIR.h"
#include "../devicehandlers/DeviceHandlerBase.h"
class ChildHandlerBase: public DeviceHandlerBase {
public:
ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication,
CookieIF * cookie, object_id_t hkDestination,
uint32_t thermalStatePoolId, uint32_t thermalRequestPoolId,
object_id_t parent = objects::NO_OBJECT,
FailureIsolationBase* customFdir = nullptr, size_t cmdQueueSize = 20);
virtual ~ChildHandlerBase();
virtual ReturnValue_t initialize();
protected:
const uint32_t parentId;
ChildHandlerFDIR childHandlerFdir;
};
#endif /* PAYLOADHANDLERBASE_H_ */

View File

@ -1,10 +1,10 @@
#include "../devicehandlers/ChildHandlerFDIR.h"
ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) :
DeviceHandlerFailureIsolation(owner, faultTreeParent) {
recoveryCounter.setFailureThreshold(recoveryCount);
}
ChildHandlerFDIR::~ChildHandlerFDIR() {
}
#include "../devicehandlers/ChildHandlerFDIR.h"
ChildHandlerFDIR::ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent, uint32_t recoveryCount) :
DeviceHandlerFailureIsolation(owner, faultTreeParent) {
recoveryCounter.setFailureThreshold(recoveryCount);
}
ChildHandlerFDIR::~ChildHandlerFDIR() {
}

View File

@ -1,20 +1,20 @@
#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
/**
* Very simple extension to normal FDIR.
* Does not have a default fault tree parent and
* allows to make the recovery count settable to 0.
*/
class ChildHandlerFDIR: public DeviceHandlerFailureIsolation {
public:
ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent =
NO_FAULT_TREE_PARENT, uint32_t recoveryCount = 0);
virtual ~ChildHandlerFDIR();
protected:
static const object_id_t NO_FAULT_TREE_PARENT = 0;
};
#endif /* FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ */
#ifndef FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#define FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_
#include "../devicehandlers/DeviceHandlerFailureIsolation.h"
/**
* Very simple extension to normal FDIR.
* Does not have a default fault tree parent and
* allows to make the recovery count settable to 0.
*/
class ChildHandlerFDIR: public DeviceHandlerFailureIsolation {
public:
ChildHandlerFDIR(object_id_t owner, object_id_t faultTreeParent =
NO_FAULT_TREE_PARENT, uint32_t recoveryCount = 0);
virtual ~ChildHandlerFDIR();
protected:
static const object_id_t NO_FAULT_TREE_PARENT = 0;
};
#endif /* FRAMEWORK_DEVICEHANDLERS_CHILDHANDLERFDIR_H_ */

View File

@ -1,201 +1,201 @@
/**
* @file CommunicationMessage.cpp
*
* @date 28.02.2020
*/
#include "../devicehandlers/CommunicationMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstring>
CommunicationMessage::CommunicationMessage(): uninitialized(true) {
}
CommunicationMessage::~CommunicationMessage() {}
void CommunicationMessage::setSendRequestFromPointer(uint32_t address,
uint32_t dataLen, const uint8_t * data) {
setMessageType(SEND_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setSendRequestFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(SEND_DATA_FROM_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition) {
setMessageType(SEND_DATA_RAW);
setAddress(address);
setDataLen(length);
if(sendBufferPosition != 0) {
setBufferPosition(sendBufferPosition);
}
}
void CommunicationMessage::setDataReplyFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(REPLY_DATA_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setDataReplyFromPointer(uint32_t address,
uint32_t dataLen, uint8_t *data) {
setMessageType(REPLY_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setDataReplyRaw(uint32_t address,
uint32_t length, uint16_t receiveBufferPosition) {
setMessageType(REPLY_DATA_RAW);
setAddress(address);
setDataLen(length);
if(receiveBufferPosition != 0) {
setBufferPosition(receiveBufferPosition);
}
}
void CommunicationMessage::setMessageType(messageType status) {
uint8_t status_uint8 = status;
memcpy(getData() + sizeof(uint32_t), &status_uint8, sizeof(status_uint8));
}
void CommunicationMessage::setAddress(address_t address) {
memcpy(getData(),&address,sizeof(address));
}
address_t CommunicationMessage::getAddress() const {
address_t address;
memcpy(&address,getData(),sizeof(address));
return address;
}
void CommunicationMessage::setBufferPosition(uint16_t bufferPosition) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint16_t),
&bufferPosition, sizeof(bufferPosition));
}
uint16_t CommunicationMessage::getBufferPosition() const {
uint16_t bufferPosition;
memcpy(&bufferPosition,
getData() + sizeof(uint32_t) + sizeof(uint16_t), sizeof(bufferPosition));
return bufferPosition;
}
void CommunicationMessage::setDataPointer(const void * data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(uint32_t));
}
void CommunicationMessage::setStoreId(store_address_t storeId) {
memcpy(getData() + 2 * sizeof(uint32_t), &storeId.raw, sizeof(uint32_t));
}
store_address_t CommunicationMessage::getStoreId() const{
store_address_t temp;
memcpy(&temp.raw,getData() + 2 * sizeof(uint32_t), sizeof(uint32_t));
return temp;
}
void CommunicationMessage::setDataLen(uint32_t length) {
memcpy(getData() + 2 * sizeof(uint32_t), &length, sizeof(length));
}
uint32_t CommunicationMessage::getDataLen() const {
uint32_t len;
memcpy(&len, getData() + 2 * sizeof(uint32_t), sizeof(len));
return len;
}
void CommunicationMessage::setUint32Data(uint32_t data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(data));
}
uint32_t CommunicationMessage::getUint32Data() const{
uint32_t data;
memcpy(&data,getData() + 3 * sizeof(uint32_t), sizeof(data));
return data;
}
void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) {
if(0 <= position && position <= 3) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), &byte, sizeof(byte));
}
else {
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint8_t CommunicationMessage::getDataByte(uint8_t position) const {
if(0 <= position && position <= 3) {
uint8_t byte;
memcpy(&byte, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), sizeof(byte));
return byte;
}
else {
return 0;
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
void CommunicationMessage::setDataUint16(uint16_t data, uint8_t position) {
if(position == 0 || position == 1) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), &data, sizeof(data));
}
else {
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint16_t CommunicationMessage::getDataUint16(uint8_t position) const{
if(position == 0 || position == 1) {
uint16_t data;
memcpy(&data, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), sizeof(data));
return data;
}
else {
return 0;
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
CommunicationMessage::messageType CommunicationMessage::getMessageType() const{
messageType messageType;
memcpy(&messageType, getData() + sizeof(uint32_t),sizeof(uint8_t));
return messageType;
}
void CommunicationMessage::setMessageId(uint8_t messageId) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint8_t), &messageId, sizeof(messageId));
}
uint8_t CommunicationMessage::getMessageId() const {
uint8_t messageId;
memcpy(&messageId, getData() + sizeof(uint32_t) + sizeof(uint8_t), sizeof(messageId));
return messageId;
}
void CommunicationMessage::clearCommunicationMessage() {
messageType messageType = getMessageType();
switch(messageType) {
case(messageType::REPLY_DATA_IPC_STORE):
case(messageType::SEND_DATA_FROM_IPC_STORE): {
store_address_t storeId = getStoreId();
StorageManagerIF *ipcStore = objectManager->
get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL) {
ipcStore->deleteData(storeId);
}
}
/* NO BREAK falls through*/
default:
memset(getData(),0,4*sizeof(uint32_t));
break;
}
}
/**
* @file CommunicationMessage.cpp
*
* @date 28.02.2020
*/
#include "../devicehandlers/CommunicationMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstring>
CommunicationMessage::CommunicationMessage(): uninitialized(true) {
}
CommunicationMessage::~CommunicationMessage() {}
void CommunicationMessage::setSendRequestFromPointer(uint32_t address,
uint32_t dataLen, const uint8_t * data) {
setMessageType(SEND_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setSendRequestFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(SEND_DATA_FROM_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition) {
setMessageType(SEND_DATA_RAW);
setAddress(address);
setDataLen(length);
if(sendBufferPosition != 0) {
setBufferPosition(sendBufferPosition);
}
}
void CommunicationMessage::setDataReplyFromIpcStore(uint32_t address, store_address_t storeId) {
setMessageType(REPLY_DATA_IPC_STORE);
setAddress(address);
setStoreId(storeId.raw);
}
void CommunicationMessage::setDataReplyFromPointer(uint32_t address,
uint32_t dataLen, uint8_t *data) {
setMessageType(REPLY_DATA_FROM_POINTER);
setAddress(address);
setDataLen(dataLen);
setDataPointer(data);
}
void CommunicationMessage::setDataReplyRaw(uint32_t address,
uint32_t length, uint16_t receiveBufferPosition) {
setMessageType(REPLY_DATA_RAW);
setAddress(address);
setDataLen(length);
if(receiveBufferPosition != 0) {
setBufferPosition(receiveBufferPosition);
}
}
void CommunicationMessage::setMessageType(messageType status) {
uint8_t status_uint8 = status;
memcpy(getData() + sizeof(uint32_t), &status_uint8, sizeof(status_uint8));
}
void CommunicationMessage::setAddress(address_t address) {
memcpy(getData(),&address,sizeof(address));
}
address_t CommunicationMessage::getAddress() const {
address_t address;
memcpy(&address,getData(),sizeof(address));
return address;
}
void CommunicationMessage::setBufferPosition(uint16_t bufferPosition) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint16_t),
&bufferPosition, sizeof(bufferPosition));
}
uint16_t CommunicationMessage::getBufferPosition() const {
uint16_t bufferPosition;
memcpy(&bufferPosition,
getData() + sizeof(uint32_t) + sizeof(uint16_t), sizeof(bufferPosition));
return bufferPosition;
}
void CommunicationMessage::setDataPointer(const void * data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(uint32_t));
}
void CommunicationMessage::setStoreId(store_address_t storeId) {
memcpy(getData() + 2 * sizeof(uint32_t), &storeId.raw, sizeof(uint32_t));
}
store_address_t CommunicationMessage::getStoreId() const{
store_address_t temp;
memcpy(&temp.raw,getData() + 2 * sizeof(uint32_t), sizeof(uint32_t));
return temp;
}
void CommunicationMessage::setDataLen(uint32_t length) {
memcpy(getData() + 2 * sizeof(uint32_t), &length, sizeof(length));
}
uint32_t CommunicationMessage::getDataLen() const {
uint32_t len;
memcpy(&len, getData() + 2 * sizeof(uint32_t), sizeof(len));
return len;
}
void CommunicationMessage::setUint32Data(uint32_t data) {
memcpy(getData() + 3 * sizeof(uint32_t), &data, sizeof(data));
}
uint32_t CommunicationMessage::getUint32Data() const{
uint32_t data;
memcpy(&data,getData() + 3 * sizeof(uint32_t), sizeof(data));
return data;
}
void CommunicationMessage::setDataByte(uint8_t byte, uint8_t position) {
if(0 <= position && position <= 3) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), &byte, sizeof(byte));
}
else {
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint8_t CommunicationMessage::getDataByte(uint8_t position) const {
if(0 <= position && position <= 3) {
uint8_t byte;
memcpy(&byte, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint8_t), sizeof(byte));
return byte;
}
else {
return 0;
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
void CommunicationMessage::setDataUint16(uint16_t data, uint8_t position) {
if(position == 0 || position == 1) {
memcpy(getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), &data, sizeof(data));
}
else {
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
uint16_t CommunicationMessage::getDataUint16(uint8_t position) const{
if(position == 0 || position == 1) {
uint16_t data;
memcpy(&data, getData() + 3 * sizeof(uint32_t) + position * sizeof(uint16_t), sizeof(data));
return data;
}
else {
return 0;
sif::error << "Comm Message: Invalid byte position" << std::endl;
}
}
CommunicationMessage::messageType CommunicationMessage::getMessageType() const{
messageType messageType;
memcpy(&messageType, getData() + sizeof(uint32_t),sizeof(uint8_t));
return messageType;
}
void CommunicationMessage::setMessageId(uint8_t messageId) {
memcpy(getData() + sizeof(uint32_t) + sizeof(uint8_t), &messageId, sizeof(messageId));
}
uint8_t CommunicationMessage::getMessageId() const {
uint8_t messageId;
memcpy(&messageId, getData() + sizeof(uint32_t) + sizeof(uint8_t), sizeof(messageId));
return messageId;
}
void CommunicationMessage::clearCommunicationMessage() {
messageType messageType = getMessageType();
switch(messageType) {
case(messageType::REPLY_DATA_IPC_STORE):
case(messageType::SEND_DATA_FROM_IPC_STORE): {
store_address_t storeId = getStoreId();
StorageManagerIF *ipcStore = objectManager->
get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != NULL) {
ipcStore->deleteData(storeId);
}
}
/* NO BREAK falls through*/
default:
memset(getData(),0,4*sizeof(uint32_t));
break;
}
}

View File

@ -1,173 +1,173 @@
/**
* @file CommunicationMessage.h
*
* @date 28.02.2020
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#define FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#include "../devicehandlers/CommunicationMessage.h"
#include "../ipc/MessageQueueMessage.h"
#include "../storagemanager/StorageManagerIF.h"
#include "../devicehandlers/DeviceHandlerBase.h"
/**
* @brief Message type to send larger messages
*
* @details
* Can be used to pass information like data pointers and
* data sizes between communication tasks.
*
*/
class CommunicationMessage: public MessageQueueMessage {
public:
enum messageType {
NONE,
SEND_DATA_FROM_POINTER,
SEND_DATA_FROM_IPC_STORE,
SEND_DATA_RAW,
REPLY_DATA_FROM_POINTER,
REPLY_DATA_IPC_STORE,
REPLY_DATA_RAW,
FAULTY,
};
//Add other messageIDs here if necessary.
static const uint8_t COMMUNICATION_MESSAGE_SIZE = HEADER_SIZE + 4 * sizeof(uint32_t);
CommunicationMessage();
virtual ~CommunicationMessage();
/**
* Message Type is stored as the fifth byte of the message data
* @param status
*/
void setMessageType(messageType status);
messageType getMessageType() const;
/**
* This is a unique ID which can be used to handle different kinds of messages.
* For example, the same interface (e.g. SPI) could be used to exchange raw data
* (e.g. sensor values) and data stored in the IPC store.
* The ID can be used to distinguish the messages in child implementations.
* The message ID is stored as the sixth byte of the message data.
* @param messageId
*/
void setMessageId(uint8_t messageId);
uint8_t getMessageId() const;
/**
* Send requests with pointer to the data to be sent and send data length
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestFromPointer(uint32_t address, uint32_t dataLen, const uint8_t * data);
/**
* Send requests with a store ID, using the IPC store
* @param address Target Address, first four bytes
* @param storeId Store ID in the IPC store
*
*/
void setSendRequestFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Send requests with data length and data in message (max. 4 bytes)
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition = 0);
/**
* Data message with data stored in IPC store
* @param address Target Address, first four bytes
* @param length
* @param storeId
*/
void setDataReplyFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Data reply with data stored in buffer, passing the pointer to
* the buffer and the data size
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to the data
*/
void setDataReplyFromPointer(uint32_t address, uint32_t dataLen, uint8_t * data);
/**
* Data message with data stored in actual message.
* 4 byte datafield is intialized with 0.
* Set data with specific setter functions below.
* Can also be used to supply information at which position the raw data should be stored
* in a receive buffer.
*/
void setDataReplyRaw(uint32_t address, uint32_t length, uint16_t receiveBufferPosition = 0);
/**
* First four bytes of message data
* @param address
*/
void setAddress(address_t address);
address_t getAddress() const;
/**
* Set byte as position of 4 byte data field
* @param byte
* @param position Position, 0 to 3 possible
*/
void setDataByte(uint8_t byte, uint8_t position);
uint8_t getDataByte(uint8_t position) const;
/**
* Set 2 byte value at position 1 or 2 of data field
* @param data
* @param position 0 or 1 possible
*/
void setDataUint16(uint16_t data, uint8_t position);
uint16_t getDataUint16(uint8_t position) const;
void setUint32Data(uint32_t data);
uint32_t getUint32Data() const;
/**
* Stored in Bytes 13-16 of message data
* @param length
*/
void setDataLen(uint32_t length);
uint32_t getDataLen() const;
/**
* Stored in last four bytes (Bytes 17-20) of message data
* @param sendData
*/
void setDataPointer(const void * data);
/**
* In case the send request data or reply data is to be stored in a buffer,
* a buffer Position can be stored here as the seventh and eigth byte of
* the message, so the receive buffer can't be larger than sizeof(uint16_t) for now.
* @param bufferPosition In case the data is stored in a buffer, the position can be supplied here
*/
void setBufferPosition(uint16_t bufferPosition);
uint16_t getBufferPosition() const;
void setStoreId(store_address_t storeId);
store_address_t getStoreId() const;
/**
* Clear the message. Deletes IPC Store data
* and sets all data to 0. Also sets message type to NONE
*/
void clearCommunicationMessage();
private:
bool uninitialized; //!< Could be used to warn if data has not been set.
};
#endif /* FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_ */
/**
* @file CommunicationMessage.h
*
* @date 28.02.2020
*/
#ifndef FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#define FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_
#include "../devicehandlers/CommunicationMessage.h"
#include "../ipc/MessageQueueMessage.h"
#include "../storagemanager/StorageManagerIF.h"
#include "../devicehandlers/DeviceHandlerBase.h"
/**
* @brief Message type to send larger messages
*
* @details
* Can be used to pass information like data pointers and
* data sizes between communication tasks.
*
*/
class CommunicationMessage: public MessageQueueMessage {
public:
enum messageType {
NONE,
SEND_DATA_FROM_POINTER,
SEND_DATA_FROM_IPC_STORE,
SEND_DATA_RAW,
REPLY_DATA_FROM_POINTER,
REPLY_DATA_IPC_STORE,
REPLY_DATA_RAW,
FAULTY,
};
//Add other messageIDs here if necessary.
static const uint8_t COMMUNICATION_MESSAGE_SIZE = HEADER_SIZE + 4 * sizeof(uint32_t);
CommunicationMessage();
virtual ~CommunicationMessage();
/**
* Message Type is stored as the fifth byte of the message data
* @param status
*/
void setMessageType(messageType status);
messageType getMessageType() const;
/**
* This is a unique ID which can be used to handle different kinds of messages.
* For example, the same interface (e.g. SPI) could be used to exchange raw data
* (e.g. sensor values) and data stored in the IPC store.
* The ID can be used to distinguish the messages in child implementations.
* The message ID is stored as the sixth byte of the message data.
* @param messageId
*/
void setMessageId(uint8_t messageId);
uint8_t getMessageId() const;
/**
* Send requests with pointer to the data to be sent and send data length
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestFromPointer(uint32_t address, uint32_t dataLen, const uint8_t * data);
/**
* Send requests with a store ID, using the IPC store
* @param address Target Address, first four bytes
* @param storeId Store ID in the IPC store
*
*/
void setSendRequestFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Send requests with data length and data in message (max. 4 bytes)
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to data to send
*
*/
void setSendRequestRaw(uint32_t address, uint32_t length,
uint16_t sendBufferPosition = 0);
/**
* Data message with data stored in IPC store
* @param address Target Address, first four bytes
* @param length
* @param storeId
*/
void setDataReplyFromIpcStore(uint32_t address, store_address_t storeId);
/**
* Data reply with data stored in buffer, passing the pointer to
* the buffer and the data size
* @param address Target Address, first four bytes
* @param dataLen Length of data to send, next four bytes
* @param data Pointer to the data
*/
void setDataReplyFromPointer(uint32_t address, uint32_t dataLen, uint8_t * data);
/**
* Data message with data stored in actual message.
* 4 byte datafield is intialized with 0.
* Set data with specific setter functions below.
* Can also be used to supply information at which position the raw data should be stored
* in a receive buffer.
*/
void setDataReplyRaw(uint32_t address, uint32_t length, uint16_t receiveBufferPosition = 0);
/**
* First four bytes of message data
* @param address
*/
void setAddress(address_t address);
address_t getAddress() const;
/**
* Set byte as position of 4 byte data field
* @param byte
* @param position Position, 0 to 3 possible
*/
void setDataByte(uint8_t byte, uint8_t position);
uint8_t getDataByte(uint8_t position) const;
/**
* Set 2 byte value at position 1 or 2 of data field
* @param data
* @param position 0 or 1 possible
*/
void setDataUint16(uint16_t data, uint8_t position);
uint16_t getDataUint16(uint8_t position) const;
void setUint32Data(uint32_t data);
uint32_t getUint32Data() const;
/**
* Stored in Bytes 13-16 of message data
* @param length
*/
void setDataLen(uint32_t length);
uint32_t getDataLen() const;
/**
* Stored in last four bytes (Bytes 17-20) of message data
* @param sendData
*/
void setDataPointer(const void * data);
/**
* In case the send request data or reply data is to be stored in a buffer,
* a buffer Position can be stored here as the seventh and eigth byte of
* the message, so the receive buffer can't be larger than sizeof(uint16_t) for now.
* @param bufferPosition In case the data is stored in a buffer, the position can be supplied here
*/
void setBufferPosition(uint16_t bufferPosition);
uint16_t getBufferPosition() const;
void setStoreId(store_address_t storeId);
store_address_t getStoreId() const;
/**
* Clear the message. Deletes IPC Store data
* and sets all data to 0. Also sets message type to NONE
*/
void clearCommunicationMessage();
private:
bool uninitialized; //!< Could be used to warn if data has not been set.
};
#endif /* FRAMEWORK_DEVICEHANDLERS_COMMUNICATIONMESSAGE_H_ */

View File

@ -1,127 +1,127 @@
#ifndef FRAMEWORK_DEVICES_DEVICECOMMUNICATIONIF_H_
#define FRAMEWORK_DEVICES_DEVICECOMMUNICATIONIF_H_
#include "../devicehandlers/CookieIF.h"
#include "../devicehandlers/DeviceHandlerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
/**
* @defgroup interfaces Interfaces
* @brief Interfaces for flight software objects
*/
/**
* @defgroup comm Communication
* @brief Communication software components.
*/
/**
* @brief This is an interface to decouple device communication from
* the device handler to allow reuse of these components.
* @details
* Documentation: Dissertation Baetz p.138.
* It works with the assumption that received data is polled by a component.
* There are four generic steps of device communication:
*
* 1. Send data to a device
* 2. Get acknowledgement for sending
* 3. Request reading data from a device
* 4. Read received data
*
* To identify different connection over a single interface can return
* so-called cookies to components.
* The CommunicationMessage message type can be used to extend the
* functionality of the ComIF if a separate polling task is required.
* @ingroup interfaces
* @ingroup comm
*/
class DeviceCommunicationIF: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF;
//! This is returned in readReceivedMessage() if no reply was reived.
static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0x01);
//! General protocol error. Define more concrete errors in child handler
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02);
//! If cookie is a null pointer
static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04);
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
virtual ~DeviceCommunicationIF() {}
/**
* @brief Device specific initialization, using the cookie.
* @details
* The cookie is already prepared in the factory. If the communication
* interface needs to be set up in some way and requires cookie information,
* this can be performed in this function, which is called on device handler
* initialization.
* @param cookie
* @return
* - @c RETURN_OK if initialization was successfull
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendWrite().
* This function is used to send data to the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len If this is 0, nothing shall be sent.
* @return
* - @c RETURN_OK for successfull send
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t sendMessage(CookieIF *cookie,
const uint8_t * sendData, size_t sendLen) = 0;
/**
* Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie
* @return - @c RETURN_OK if data was sent successfull
* - Everything else triggers falure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendRead().
* It is assumed that it is always possible to request a reply
* from a device. If a requestLen of 0 is supplied, no reply was enabled
* and communication specific action should be taken (e.g. read nothing
* or read everything).
*
* @param cookie
* @param requestLen Size of data to read
* @return - @c RETURN_OK to confirm the request for data has been sent.
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie,
size_t requestLen) = 0;
/**
* Called by DHB in the GET_WRITE doGetRead().
* This function is used to receive data from the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param buffer [out] Set reply here (by using *buffer = ...)
* @param size [out] size pointer to set (by using *size = ...).
* Set to 0 if no reply was received
* @return - @c RETURN_OK for successfull receive
* - @c NO_REPLY_RECEIVED if not reply was received. Setting size to
* 0 has the same effect
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) = 0;
};
#endif /* DEVICECOMMUNICATIONIF_H_ */
#ifndef FRAMEWORK_DEVICES_DEVICECOMMUNICATIONIF_H_
#define FRAMEWORK_DEVICES_DEVICECOMMUNICATIONIF_H_
#include "../devicehandlers/CookieIF.h"
#include "../devicehandlers/DeviceHandlerIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
/**
* @defgroup interfaces Interfaces
* @brief Interfaces for flight software objects
*/
/**
* @defgroup comm Communication
* @brief Communication software components.
*/
/**
* @brief This is an interface to decouple device communication from
* the device handler to allow reuse of these components.
* @details
* Documentation: Dissertation Baetz p.138.
* It works with the assumption that received data is polled by a component.
* There are four generic steps of device communication:
*
* 1. Send data to a device
* 2. Get acknowledgement for sending
* 3. Request reading data from a device
* 4. Read received data
*
* To identify different connection over a single interface can return
* so-called cookies to components.
* The CommunicationMessage message type can be used to extend the
* functionality of the ComIF if a separate polling task is required.
* @ingroup interfaces
* @ingroup comm
*/
class DeviceCommunicationIF: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_COMMUNICATION_IF;
//! This is returned in readReceivedMessage() if no reply was reived.
static const ReturnValue_t NO_REPLY_RECEIVED = MAKE_RETURN_CODE(0x01);
//! General protocol error. Define more concrete errors in child handler
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0x02);
//! If cookie is a null pointer
static const ReturnValue_t NULLPOINTER = MAKE_RETURN_CODE(0x03);
static const ReturnValue_t INVALID_COOKIE_TYPE = MAKE_RETURN_CODE(0x04);
// is this needed if there is no open/close call?
static const ReturnValue_t NOT_ACTIVE = MAKE_RETURN_CODE(0x05);
static const ReturnValue_t TOO_MUCH_DATA = MAKE_RETURN_CODE(0x06);
virtual ~DeviceCommunicationIF() {}
/**
* @brief Device specific initialization, using the cookie.
* @details
* The cookie is already prepared in the factory. If the communication
* interface needs to be set up in some way and requires cookie information,
* this can be performed in this function, which is called on device handler
* initialization.
* @param cookie
* @return
* - @c RETURN_OK if initialization was successfull
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t initializeInterface(CookieIF * cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendWrite().
* This function is used to send data to the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param data
* @param len If this is 0, nothing shall be sent.
* @return
* - @c RETURN_OK for successfull send
* - Everything else triggers failure event with returnvalue as parameter 1
*/
virtual ReturnValue_t sendMessage(CookieIF *cookie,
const uint8_t * sendData, size_t sendLen) = 0;
/**
* Called by DHB in the GET_WRITE doGetWrite().
* Get send confirmation that the data in sendMessage() was sent successfully.
* @param cookie
* @return - @c RETURN_OK if data was sent successfull
* - Everything else triggers falure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t getSendSuccess(CookieIF *cookie) = 0;
/**
* Called by DHB in the SEND_WRITE doSendRead().
* It is assumed that it is always possible to request a reply
* from a device. If a requestLen of 0 is supplied, no reply was enabled
* and communication specific action should be taken (e.g. read nothing
* or read everything).
*
* @param cookie
* @param requestLen Size of data to read
* @return - @c RETURN_OK to confirm the request for data has been sent.
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t requestReceiveMessage(CookieIF *cookie,
size_t requestLen) = 0;
/**
* Called by DHB in the GET_WRITE doGetRead().
* This function is used to receive data from the physical device
* by implementing and calling related drivers or wrapper functions.
* @param cookie
* @param buffer [out] Set reply here (by using *buffer = ...)
* @param size [out] size pointer to set (by using *size = ...).
* Set to 0 if no reply was received
* @return - @c RETURN_OK for successfull receive
* - @c NO_REPLY_RECEIVED if not reply was received. Setting size to
* 0 has the same effect
* - Everything else triggers failure event with
* returnvalue as parameter 1
*/
virtual ReturnValue_t readReceivedMessage(CookieIF *cookie,
uint8_t **buffer, size_t *size) = 0;
};
#endif /* DEVICECOMMUNICATIONIF_H_ */

View File

@ -1,155 +1,155 @@
#ifndef DEVICEHANDLERIF_H_
#define DEVICEHANDLERIF_H_
#include "../action/HasActionsIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../events/Event.h"
#include "../modes/HasModesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
/**
* @brief This is the Interface used to communicate with a device handler.
* @details Includes all expected return values, events and modes.
*
*/
class DeviceHandlerIF {
public:
static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
/**
* @brief This is the mode the <strong>device handler</strong> is in.
*
* @details The mode of the device handler must not be confused with the mode the device is in.
* The mode of the device itself is transparent to the user but related to the mode of the handler.
* MODE_ON and MODE_OFF are included in hasModesIF.h
*/
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on.
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
static const Mode_t MODE_NORMAL = 2;
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object.
static const Mode_t MODE_RAW = 3;
//! The device is shut down but the switch could not be turned off, so the
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
// Standard codes used when building commands.
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected.
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB3);
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
// Standard codes used in buildCommandFromCommand
static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1);
/**
* Communication action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum CommunicationAction_t: uint8_t {
SEND_WRITE,//!< Send write
GET_WRITE, //!< Get write
SEND_READ, //!< Send read
GET_READ, //!< Get read
NOTHING //!< Do nothing.
};
/**
* Default Destructor
*/
virtual ~DeviceHandlerIF() {}
/**
* This MessageQueue is used to command the device handler.
* @return the id of the MessageQueue
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
};
#endif /* DEVICEHANDLERIF_H_ */
#ifndef DEVICEHANDLERIF_H_
#define DEVICEHANDLERIF_H_
#include "../action/HasActionsIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../events/Event.h"
#include "../modes/HasModesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
/**
* @brief This is the Interface used to communicate with a device handler.
* @details Includes all expected return values, events and modes.
*
*/
class DeviceHandlerIF {
public:
static const uint8_t TRANSITION_MODE_CHILD_ACTION_MASK = 0x20;
static const uint8_t TRANSITION_MODE_BASE_ACTION_MASK = 0x10;
/**
* @brief This is the mode the <strong>device handler</strong> is in.
*
* @details The mode of the device handler must not be confused with the mode the device is in.
* The mode of the device itself is transparent to the user but related to the mode of the handler.
* MODE_ON and MODE_OFF are included in hasModesIF.h
*/
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no commands are sent by the device handler itself, but direct commands van be commanded and will be interpreted
// MODE_OFF = 1, //!< The device is powered off. The only command accepted in this mode is a mode change to on.
//! The device is powered on and the device handler periodically sends
//! commands. The commands to be sent are selected by the handler
//! according to the submode.
static const Mode_t MODE_NORMAL = 2;
//! The device is powered on and ready to perform operations. In this mode,
//! raw commands can be sent. The device handler will send all replies
//! received from the command back to the commanding object.
static const Mode_t MODE_RAW = 3;
//! The device is shut down but the switch could not be turned off, so the
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
//! can be commanded, which tries to switch off the device again.
static const Mode_t MODE_ERROR_ON = 4;
//! This is a transitional state which can not be commanded. The device
//! handler performs all commands to get the device in a state ready to
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
static const Mode_t _MODE_START_UP = TRANSITION_MODE_CHILD_ACTION_MASK | 5;
//! This is a transitional state which can not be commanded.
//! The device handler performs all actions and commands to get the device
//! shut down. When the device is off, the mode changes to @c MODE_OFF.
//! It is possible to set the mode to _MODE_SHUT_DOWN to use the to off
//! transition if available.
static const Mode_t _MODE_SHUT_DOWN = TRANSITION_MODE_CHILD_ACTION_MASK | 6;
//! It is possible to set the mode to _MODE_TO_ON to use the to on
//! transition if available.
static const Mode_t _MODE_TO_ON = TRANSITION_MODE_CHILD_ACTION_MASK | HasModesIF::MODE_ON;
//! It is possible to set the mode to _MODE_TO_RAW to use the to raw
//! transition if available.
static const Mode_t _MODE_TO_RAW = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_RAW;
//! It is possible to set the mode to _MODE_TO_NORMAL to use the to normal
//! transition if available.
static const Mode_t _MODE_TO_NORMAL = TRANSITION_MODE_CHILD_ACTION_MASK | MODE_NORMAL;
//! This is a transitional state which can not be commanded.
//! The device is shut down and ready to be switched off.
//! After the command to set the switch off has been sent,
//! the mode changes to @c MODE_WAIT_OFF
static const Mode_t _MODE_POWER_DOWN = TRANSITION_MODE_BASE_ACTION_MASK | 1;
//! This is a transitional state which can not be commanded. The device
//! will be switched on in this state. After the command to set the switch
//! on has been sent, the mode changes to @c MODE_WAIT_ON.
static const Mode_t _MODE_POWER_ON = TRANSITION_MODE_BASE_ACTION_MASK | 2;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and the handler waits for it to be off.
//! When the switch is off, the mode changes to @c MODE_OFF.
static const Mode_t _MODE_WAIT_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 3;
//! This is a transitional state which can not be commanded. The switch
//! has been commanded on and the handler waits for it to be on.
//! When the switch is on, the mode changes to @c MODE_TO_ON.
static const Mode_t _MODE_WAIT_ON = TRANSITION_MODE_BASE_ACTION_MASK | 4;
//! This is a transitional state which can not be commanded. The switch has
//! been commanded off and is off now. This state is only to do an RMAP
//! cycle once more where the doSendRead() function will set the mode to
//! MODE_OFF. The reason to do this is to get rid of stuck packets in the IO Board.
static const Mode_t _MODE_SWITCH_IS_OFF = TRANSITION_MODE_BASE_ACTION_MASK | 5;
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::CDH;
static const Event DEVICE_BUILDING_COMMAND_FAILED = MAKE_EVENT(0, SEVERITY::LOW);
static const Event DEVICE_SENDING_COMMAND_FAILED = MAKE_EVENT(1, SEVERITY::LOW);
static const Event DEVICE_REQUESTING_REPLY_FAILED = MAKE_EVENT(2, SEVERITY::LOW);
static const Event DEVICE_READING_REPLY_FAILED = MAKE_EVENT(3, SEVERITY::LOW);
static const Event DEVICE_INTERPRETING_REPLY_FAILED = MAKE_EVENT(4, SEVERITY::LOW);
static const Event DEVICE_MISSED_REPLY = MAKE_EVENT(5, SEVERITY::LOW);
static const Event DEVICE_UNKNOWN_REPLY = MAKE_EVENT(6, SEVERITY::LOW);
static const Event DEVICE_UNREQUESTED_REPLY = MAKE_EVENT(7, SEVERITY::LOW);
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, SEVERITY::LOW); //!< Indicates a SW bug in child class.
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, SEVERITY::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, SEVERITY::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;
// Standard codes used when building commands.
static const ReturnValue_t NO_COMMAND_DATA = MAKE_RETURN_CODE(0xA0); //!< If no command data was given when expected.
static const ReturnValue_t COMMAND_NOT_SUPPORTED = MAKE_RETURN_CODE(0xA1); //!< Command ID not in commandMap. Checked in DHB
static const ReturnValue_t COMMAND_ALREADY_SENT = MAKE_RETURN_CODE(0xA2); //!< Command was already executed. Checked in DHB
static const ReturnValue_t COMMAND_WAS_NOT_SENT = MAKE_RETURN_CODE(0xA3);
static const ReturnValue_t CANT_SWITCH_ADDRESS = MAKE_RETURN_CODE(0xA4);
static const ReturnValue_t WRONG_MODE_FOR_COMMAND = MAKE_RETURN_CODE(0xA5);
static const ReturnValue_t TIMEOUT = MAKE_RETURN_CODE(0xA6);
static const ReturnValue_t BUSY = MAKE_RETURN_CODE(0xA7);
static const ReturnValue_t NO_REPLY_EXPECTED = MAKE_RETURN_CODE(0xA8); //!< Used to indicate that this is a command-only command.
static const ReturnValue_t NON_OP_TEMPERATURE = MAKE_RETURN_CODE(0xA9);
static const ReturnValue_t COMMAND_NOT_IMPLEMENTED = MAKE_RETURN_CODE(0xAA);
// Standard codes used in scanForReply
static const ReturnValue_t CHECKSUM_ERROR = MAKE_RETURN_CODE(0xB0);
static const ReturnValue_t LENGTH_MISSMATCH = MAKE_RETURN_CODE(0xB1);
static const ReturnValue_t INVALID_DATA = MAKE_RETURN_CODE(0xB2);
static const ReturnValue_t PROTOCOL_ERROR = MAKE_RETURN_CODE(0xB3);
// Standard codes used in interpretDeviceReply
static const ReturnValue_t DEVICE_DID_NOT_EXECUTE = MAKE_RETURN_CODE(0xC0); //the device reported, that it did not execute the command
static const ReturnValue_t DEVICE_REPORTED_ERROR = MAKE_RETURN_CODE(0xC1);
static const ReturnValue_t UNKNOW_DEVICE_REPLY = MAKE_RETURN_CODE(0xC2); //the deviceCommandId reported by scanforReply is unknown
static const ReturnValue_t DEVICE_REPLY_INVALID = MAKE_RETURN_CODE(0xC3); //syntax etc is correct but still not ok, eg parameters where none are expected
// Standard codes used in buildCommandFromCommand
static const ReturnValue_t INVALID_COMMAND_PARAMETER = MAKE_RETURN_CODE(0xD0);
static const ReturnValue_t INVALID_NUMBER_OR_LENGTH_OF_PARAMETERS = MAKE_RETURN_CODE(0xD1);
/**
* Communication action that will be executed.
*
* This is used by the child class to tell the base class what to do.
*/
enum CommunicationAction_t: uint8_t {
SEND_WRITE,//!< Send write
GET_WRITE, //!< Get write
SEND_READ, //!< Send read
GET_READ, //!< Get read
NOTHING //!< Do nothing.
};
/**
* Default Destructor
*/
virtual ~DeviceHandlerIF() {}
/**
* This MessageQueue is used to command the device handler.
* @return the id of the MessageQueue
*/
virtual MessageQueueId_t getCommandQueue() const = 0;
};
#endif /* DEVICEHANDLERIF_H_ */

View File

@ -1,101 +1,101 @@
#include "../objectmanager/ObjectManagerIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../objectmanager/ObjectManagerIF.h"
DeviceHandlerMessage::DeviceHandlerMessage() {
}
store_address_t DeviceHandlerMessage::getStoreAddress(
const CommandMessage* message) {
return store_address_t(message->getParameter2());
}
uint32_t DeviceHandlerMessage::getDeviceCommandId(
const CommandMessage* message) {
return message->getParameter();
}
object_id_t DeviceHandlerMessage::getIoBoardObjectId(
const CommandMessage* message) {
return message->getParameter();
}
uint8_t DeviceHandlerMessage::getWiretappingMode(
const CommandMessage* message) {
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);
message->setParameter2(rawPacketStoreId.raw);
}
void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(
CommandMessage* message, uint8_t wiretappingMode) {
message->setCommand(CMD_WIRETAPPING);
message->setParameter(wiretappingMode);
}
void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage(
CommandMessage* message, uint32_t ioBoardIdentifier) {
message->setCommand(CMD_SWITCH_ADDRESS);
message->setParameter(ioBoardIdentifier);
}
object_id_t DeviceHandlerMessage::getDeviceObjectId(
const CommandMessage* message) {
return message->getParameter();
}
void DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(
CommandMessage* message, object_id_t deviceObjectid,
store_address_t rawPacketStoreId, bool isCommand) {
if (isCommand) {
message->setCommand(REPLY_RAW_COMMAND);
} else {
message->setCommand(REPLY_RAW_REPLY);
}
message->setParameter(deviceObjectid);
message->setParameter2(rawPacketStoreId.raw);
}
void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply(
CommandMessage* message, object_id_t deviceObjectid,
store_address_t commandParametersStoreId) {
message->setCommand(REPLY_DIRECT_COMMAND_DATA);
message->setParameter(deviceObjectid);
message->setParameter2(commandParametersStoreId.raw);
}
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) {
ipcStore->deleteData(getStoreAddress(message));
}
}
/* NO BREAK falls through*/
case CMD_SWITCH_ADDRESS:
case CMD_WIRETAPPING:
message->setCommand(CommandMessage::CMD_NONE);
message->setParameter(0);
message->setParameter2(0);
break;
}
}
#include "../objectmanager/ObjectManagerIF.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../objectmanager/ObjectManagerIF.h"
DeviceHandlerMessage::DeviceHandlerMessage() {
}
store_address_t DeviceHandlerMessage::getStoreAddress(
const CommandMessage* message) {
return store_address_t(message->getParameter2());
}
uint32_t DeviceHandlerMessage::getDeviceCommandId(
const CommandMessage* message) {
return message->getParameter();
}
object_id_t DeviceHandlerMessage::getIoBoardObjectId(
const CommandMessage* message) {
return message->getParameter();
}
uint8_t DeviceHandlerMessage::getWiretappingMode(
const CommandMessage* message) {
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);
message->setParameter2(rawPacketStoreId.raw);
}
void DeviceHandlerMessage::setDeviceHandlerWiretappingMessage(
CommandMessage* message, uint8_t wiretappingMode) {
message->setCommand(CMD_WIRETAPPING);
message->setParameter(wiretappingMode);
}
void DeviceHandlerMessage::setDeviceHandlerSwitchIoBoardMessage(
CommandMessage* message, uint32_t ioBoardIdentifier) {
message->setCommand(CMD_SWITCH_ADDRESS);
message->setParameter(ioBoardIdentifier);
}
object_id_t DeviceHandlerMessage::getDeviceObjectId(
const CommandMessage* message) {
return message->getParameter();
}
void DeviceHandlerMessage::setDeviceHandlerRawReplyMessage(
CommandMessage* message, object_id_t deviceObjectid,
store_address_t rawPacketStoreId, bool isCommand) {
if (isCommand) {
message->setCommand(REPLY_RAW_COMMAND);
} else {
message->setCommand(REPLY_RAW_REPLY);
}
message->setParameter(deviceObjectid);
message->setParameter2(rawPacketStoreId.raw);
}
void DeviceHandlerMessage::setDeviceHandlerDirectCommandReply(
CommandMessage* message, object_id_t deviceObjectid,
store_address_t commandParametersStoreId) {
message->setCommand(REPLY_DIRECT_COMMAND_DATA);
message->setParameter(deviceObjectid);
message->setParameter2(commandParametersStoreId.raw);
}
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) {
ipcStore->deleteData(getStoreAddress(message));
}
}
/* NO BREAK falls through*/
case CMD_SWITCH_ADDRESS:
case CMD_WIRETAPPING:
message->setCommand(CommandMessage::CMD_NONE);
message->setParameter(0);
message->setParameter2(0);
break;
}
}

View File

@ -1,91 +1,91 @@
#ifndef DEVICEHANDLERMESSAGE_H_
#define 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.
/**
* 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
*/
class DeviceHandlerMessage {
private:
DeviceHandlerMessage();
public:
/**
* 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
/*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
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);
static void setDeviceHandlerRawCommandMessage(CommandMessage* message,
store_address_t rawPacketStoreId);
static void setDeviceHandlerRawReplyMessage(CommandMessage* message,
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,
object_id_t ioBoardIdentifier);
static void clear(CommandMessage* message);
};
#endif /* DEVICEHANDLERMESSAGE_H_ */
#ifndef DEVICEHANDLERMESSAGE_H_
#define 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.
/**
* 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
*/
class DeviceHandlerMessage {
private:
DeviceHandlerMessage();
public:
/**
* 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
/*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
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);
static void setDeviceHandlerRawCommandMessage(CommandMessage* message,
store_address_t rawPacketStoreId);
static void setDeviceHandlerRawReplyMessage(CommandMessage* message,
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,
object_id_t ioBoardIdentifier);
static void clear(CommandMessage* message);
};
#endif /* DEVICEHANDLERMESSAGE_H_ */

View File

@ -1,46 +1,46 @@
#include "../serialize/SerializeAdapter.h"
#include "../devicehandlers/DeviceTmReportingWrapper.h"
#include "../serialize/SerializeAdapter.h"
DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId,
ActionId_t actionId, SerializeIF* data) :
objectId(objectId), actionId(actionId), data(data) {
}
DeviceTmReportingWrapper::~DeviceTmReportingWrapper() {
}
ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&objectId,
buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&actionId, buffer,
size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return data->serialize(buffer, size, maxSize, streamEndianness);
}
size_t DeviceTmReportingWrapper::getSerializedSize() const {
return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize();
}
ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&objectId,
buffer, size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&actionId, buffer,
size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return data->deSerialize(buffer, size, streamEndianness);
}
#include "../serialize/SerializeAdapter.h"
#include "../devicehandlers/DeviceTmReportingWrapper.h"
#include "../serialize/SerializeAdapter.h"
DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId,
ActionId_t actionId, SerializeIF* data) :
objectId(objectId), actionId(actionId), data(data) {
}
DeviceTmReportingWrapper::~DeviceTmReportingWrapper() {
}
ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer,
size_t* size, size_t maxSize, Endianness streamEndianness) const {
ReturnValue_t result = SerializeAdapter::serialize(&objectId,
buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&actionId, buffer,
size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return data->serialize(buffer, size, maxSize, streamEndianness);
}
size_t DeviceTmReportingWrapper::getSerializedSize() const {
return sizeof(objectId) + sizeof(ActionId_t) + data->getSerializedSize();
}
ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer,
size_t* size, Endianness streamEndianness) {
ReturnValue_t result = SerializeAdapter::deSerialize(&objectId,
buffer, size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&actionId, buffer,
size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return data->deSerialize(buffer, size, streamEndianness);
}

View File

@ -1,27 +1,27 @@
#ifndef DEVICETMREPORTINGWRAPPER_H_
#define DEVICETMREPORTINGWRAPPER_H_
#include "../action/HasActionsIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../serialize/SerializeIF.h"
class DeviceTmReportingWrapper: public SerializeIF {
public:
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId,
SerializeIF *data);
virtual ~DeviceTmReportingWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
private:
object_id_t objectId;
ActionId_t actionId;
SerializeIF *data;
};
#endif /* DEVICETMREPORTINGWRAPPER_H_ */
#ifndef DEVICETMREPORTINGWRAPPER_H_
#define DEVICETMREPORTINGWRAPPER_H_
#include "../action/HasActionsIF.h"
#include "../objectmanager/SystemObjectIF.h"
#include "../serialize/SerializeIF.h"
class DeviceTmReportingWrapper: public SerializeIF {
public:
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId,
SerializeIF *data);
virtual ~DeviceTmReportingWrapper();
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
private:
object_id_t objectId;
ActionId_t actionId;
SerializeIF *data;
};
#endif /* DEVICETMREPORTINGWRAPPER_H_ */

View File

@ -1,59 +1,59 @@
#include "../devicehandlers/HealthDevice.h"
#include "../ipc/QueueFactory.h"
HealthDevice::HealthDevice(object_id_t setObjectId,
MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::MINIMUM_COMMAND_MESSAGE_SIZE);
}
HealthDevice::~HealthDevice() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
healthHelper.handleHealthCommand(&command);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t HealthDevice::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (parentQueue != 0) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
}
MessageQueueId_t HealthDevice::getCommandQueue() const {
return commandQueue->getId();
}
void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) {
healthHelper.setParentQueue(parentQueue);
}
bool HealthDevice::hasHealthChanged() {
bool changed;
HealthState currentHealth = healthHelper.getHealth();
changed = currentHealth != lastHealth;
lastHealth = currentHealth;
return changed;
}
ReturnValue_t HealthDevice::setHealth(HealthState health) {
healthHelper.setHealth(health);
return HasReturnvaluesIF::RETURN_OK;
}
HasHealthIF::HealthState HealthDevice::getHealth() {
return healthHelper.getHealth();
}
#include "../devicehandlers/HealthDevice.h"
#include "../ipc/QueueFactory.h"
HealthDevice::HealthDevice(object_id_t setObjectId,
MessageQueueId_t parentQueue) :
SystemObject(setObjectId), lastHealth(HEALTHY), parentQueue(
parentQueue), commandQueue(), healthHelper(this, setObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue(3, CommandMessage::MINIMUM_COMMAND_MESSAGE_SIZE);
}
HealthDevice::~HealthDevice() {
QueueFactory::instance()->deleteMessageQueue(commandQueue);
}
ReturnValue_t HealthDevice::performOperation(uint8_t opCode) {
CommandMessage command;
ReturnValue_t result = commandQueue->receiveMessage(&command);
if (result == HasReturnvaluesIF::RETURN_OK) {
healthHelper.handleHealthCommand(&command);
}
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t HealthDevice::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (parentQueue != 0) {
return healthHelper.initialize(parentQueue);
} else {
return healthHelper.initialize();
}
}
MessageQueueId_t HealthDevice::getCommandQueue() const {
return commandQueue->getId();
}
void HealthDevice::setParentQueue(MessageQueueId_t parentQueue) {
healthHelper.setParentQueue(parentQueue);
}
bool HealthDevice::hasHealthChanged() {
bool changed;
HealthState currentHealth = healthHelper.getHealth();
changed = currentHealth != lastHealth;
lastHealth = currentHealth;
return changed;
}
ReturnValue_t HealthDevice::setHealth(HealthState health) {
healthHelper.setHealth(health);
return HasReturnvaluesIF::RETURN_OK;
}
HasHealthIF::HealthState HealthDevice::getHealth() {
return healthHelper.getHealth();
}

View File

@ -1,40 +1,40 @@
#ifndef HEALTHDEVICE_H_
#define HEALTHDEVICE_H_
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../ipc/MessageQueueIF.h"
class HealthDevice: public SystemObject,
public ExecutableObjectIF,
public HasHealthIF {
public:
HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue);
virtual ~HealthDevice();
ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize();
virtual MessageQueueId_t getCommandQueue() const;
void setParentQueue(MessageQueueId_t parentQueue);
bool hasHealthChanged();
virtual ReturnValue_t setHealth(HealthState health);
virtual HealthState getHealth();
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};
#endif /* HEALTHDEVICE_H_ */
#ifndef HEALTHDEVICE_H_
#define HEALTHDEVICE_H_
#include "../health/HasHealthIF.h"
#include "../health/HealthHelper.h"
#include "../objectmanager/SystemObject.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../ipc/MessageQueueIF.h"
class HealthDevice: public SystemObject,
public ExecutableObjectIF,
public HasHealthIF {
public:
HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue);
virtual ~HealthDevice();
ReturnValue_t performOperation(uint8_t opCode);
ReturnValue_t initialize();
virtual MessageQueueId_t getCommandQueue() const;
void setParentQueue(MessageQueueId_t parentQueue);
bool hasHealthChanged();
virtual ReturnValue_t setHealth(HealthState health);
virtual HealthState getHealth();
protected:
HealthState lastHealth;
MessageQueueId_t parentQueue;
MessageQueueIF* commandQueue;
public:
HealthHelper healthHelper;
};
#endif /* HEALTHDEVICE_H_ */

View File

@ -1,20 +1,20 @@
#ifndef FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_
#define FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
// TODO: Documentation.
class ConfirmsFailuresIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::HANDLES_FAILURES_IF;
static const ReturnValue_t YOUR_FAULT = MAKE_RETURN_CODE(0);
static const ReturnValue_t MY_FAULT = MAKE_RETURN_CODE(1);
static const ReturnValue_t CONFIRM_LATER = MAKE_RETURN_CODE(2);
virtual ~ConfirmsFailuresIF() {}
virtual MessageQueueId_t getEventReceptionQueue() = 0;
};
#endif /* FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ */
#ifndef FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_
#define FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
// TODO: Documentation.
class ConfirmsFailuresIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::HANDLES_FAILURES_IF;
static const ReturnValue_t YOUR_FAULT = MAKE_RETURN_CODE(0);
static const ReturnValue_t MY_FAULT = MAKE_RETURN_CODE(1);
static const ReturnValue_t CONFIRM_LATER = MAKE_RETURN_CODE(2);
virtual ~ConfirmsFailuresIF() {}
virtual MessageQueueId_t getEventReceptionQueue() = 0;
};
#endif /* FRAMEWORK_FDIR_CONFIRMSFAILURESIF_H_ */

View File

@ -1,44 +1,44 @@
#include "../fdir/EventCorrelation.h"
EventCorrelation::EventCorrelation(uint32_t timeout) :
eventPending(false) {
correlationTimer.setTimeout(timeout);
}
EventCorrelation::~EventCorrelation() {
}
EventCorrelation::State EventCorrelation::doesEventCorrelate() {
if (correlationTimer.isBusy()) {
eventPending = false;
return CORRELATED;
} else {
if (eventPending) {
return ALREADY_STARTED;
} else {
eventPending = true;
correlationTimer.resetTimer();
return CORRELATION_STARTED;
}
}
}
bool EventCorrelation::isEventPending() {
if (eventPending) {
eventPending = false;
return true;
} else {
correlationTimer.resetTimer();
return false;
}
}
bool EventCorrelation::hasPendingEventTimedOut() {
if (correlationTimer.hasTimedOut()) {
bool temp = eventPending;
eventPending = false;
return temp;
} else {
return false;
}
}
#include "../fdir/EventCorrelation.h"
EventCorrelation::EventCorrelation(uint32_t timeout) :
eventPending(false) {
correlationTimer.setTimeout(timeout);
}
EventCorrelation::~EventCorrelation() {
}
EventCorrelation::State EventCorrelation::doesEventCorrelate() {
if (correlationTimer.isBusy()) {
eventPending = false;
return CORRELATED;
} else {
if (eventPending) {
return ALREADY_STARTED;
} else {
eventPending = true;
correlationTimer.resetTimer();
return CORRELATION_STARTED;
}
}
}
bool EventCorrelation::isEventPending() {
if (eventPending) {
eventPending = false;
return true;
} else {
correlationTimer.resetTimer();
return false;
}
}
bool EventCorrelation::hasPendingEventTimedOut() {
if (correlationTimer.hasTimedOut()) {
bool temp = eventPending;
eventPending = false;
return temp;
} else {
return false;
}
}

View File

@ -1,23 +1,23 @@
#ifndef FRAMEWORK_FDIR_EVENTCORRELATION_H_
#define FRAMEWORK_FDIR_EVENTCORRELATION_H_
#include "../timemanager/Countdown.h"
class EventCorrelation {
public:
enum State {
CORRELATION_STARTED,
CORRELATED,
ALREADY_STARTED
};
EventCorrelation(uint32_t timeout);
~EventCorrelation();
EventCorrelation::State doesEventCorrelate();
bool isEventPending();
bool hasPendingEventTimedOut();
Countdown correlationTimer;
private:
bool eventPending;
};
#endif /* FRAMEWORK_FDIR_EVENTCORRELATION_H_ */
#ifndef FRAMEWORK_FDIR_EVENTCORRELATION_H_
#define FRAMEWORK_FDIR_EVENTCORRELATION_H_
#include "../timemanager/Countdown.h"
class EventCorrelation {
public:
enum State {
CORRELATION_STARTED,
CORRELATED,
ALREADY_STARTED
};
EventCorrelation(uint32_t timeout);
~EventCorrelation();
EventCorrelation::State doesEventCorrelate();
bool isEventPending();
bool hasPendingEventTimedOut();
Countdown correlationTimer;
private:
bool eventPending;
};
#endif /* FRAMEWORK_FDIR_EVENTCORRELATION_H_ */

View File

@ -1,164 +1,164 @@
#include "../events/EventManagerIF.h"
#include "../fdir/FailureIsolationBase.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthMessage.h"
#include "../ipc/QueueFactory.h"
#include "../objectmanager/ObjectManagerIF.h"
FailureIsolationBase::FailureIsolationBase(object_id_t owner,
object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) :
ownerId(owner), faultTreeParent(parent),
parameterDomainBase(parameterDomainBase) {
eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
EventMessage::EVENT_MESSAGE_SIZE);
}
FailureIsolationBase::~FailureIsolationBase() {
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}
ReturnValue_t FailureIsolationBase::initialize() {
EventManagerIF* manager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER);
if (manager == nullptr) {
sif::error << "FailureIsolationBase::initialize: Event Manager has not"
" been initialized!" << std::endl;
return RETURN_FAILED;
}
ReturnValue_t result = manager->registerListener(eventQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (ownerId != objects::NO_OBJECT) {
result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
owner = objectManager->get<HasHealthIF>(ownerId);
if (owner == nullptr) {
sif::error << "FailureIsolationBase::intialize: Owner object "
"invalid. Make sure it implements HasHealthIF" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
if (faultTreeParent != objects::NO_OBJECT) {
ConfirmsFailuresIF* parentIF = objectManager->get<ConfirmsFailuresIF>(
faultTreeParent);
if (parentIF == nullptr) {
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF."
<< std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
return RETURN_FAILED;
}
eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue());
}
return RETURN_OK;
}
void FailureIsolationBase::checkForFailures() {
EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event);
result == RETURN_OK; result = eventQueue->receiveMessage(&event)) {
if (event.getSender() == eventQueue->getId()) {
//We already got this event, because we sent it.
continue;
}
switch (event.getMessageId()) {
case EventMessage::EVENT_MESSAGE:
if (isFdirDisabledForSeverity(event.getSeverity())) {
//We do not handle events when disabled.
continue;
}
eventReceived(&event);
break;
case EventMessage::CONFIRMATION_REQUEST:
doConfirmFault(&event);
break;
case EventMessage::YOUR_FAULT:
eventConfirmed(&event);
break;
case EventMessage::MY_FAULT:
wasParentsFault(&event);
break;
default:
break;
}
}
decrementFaultCounters();
}
void FailureIsolationBase::setOwnerHealth(HasHealthIF::HealthState health) {
if (owner != NULL) {
owner->setHealth(health);
}
//else: owner has no health.
}
MessageQueueId_t FailureIsolationBase::getEventReceptionQueue() {
return eventQueue->getId();
}
ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event,
MessageQueueId_t destination) {
event->setMessageId(EventMessage::CONFIRMATION_REQUEST);
if (destination != MessageQueueIF::NO_QUEUE) {
return eventQueue->sendMessage(destination, event);
} else if (faultTreeParent != objects::NO_OBJECT) {
return eventQueue->sendToDefault(event);
}
return RETURN_FAILED;
}
void FailureIsolationBase::eventConfirmed(EventMessage* event) {
}
void FailureIsolationBase::wasParentsFault(EventMessage* event) {
}
void FailureIsolationBase::doConfirmFault(EventMessage* event) {
ReturnValue_t result = confirmFault(event);
if (result == YOUR_FAULT) {
event->setMessageId(EventMessage::YOUR_FAULT);
eventQueue->reply(event);
} else if (result == MY_FAULT) {
event->setMessageId(EventMessage::MY_FAULT);
eventQueue->reply(event);
} else {
}
}
ReturnValue_t FailureIsolationBase::confirmFault(EventMessage* event) {
return YOUR_FAULT;
}
void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
//With this mechanism, all events are disabled for a certain device.
//That's not so good for visibility.
if (isFdirDisabledForSeverity(EVENT::getSeverity(event))) {
return;
}
EventMessage message(event, ownerId, parameter1, parameter2);
EventManagerIF::triggerEvent(&message, eventQueue->getId());
eventReceived(&message);
}
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) {
if ((owner != NULL) && (severity != SEVERITY::INFO)) {
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
//External control disables handling of fault messages.
return true;
}
}
return false;
}
void FailureIsolationBase::throwFdirEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
EventMessage message(event, ownerId, parameter1, parameter2);
EventManagerIF::triggerEvent(&message, eventQueue->getId());
}
#include "../events/EventManagerIF.h"
#include "../fdir/FailureIsolationBase.h"
#include "../health/HasHealthIF.h"
#include "../health/HealthMessage.h"
#include "../ipc/QueueFactory.h"
#include "../objectmanager/ObjectManagerIF.h"
FailureIsolationBase::FailureIsolationBase(object_id_t owner,
object_id_t parent, uint8_t messageDepth, uint8_t parameterDomainBase) :
ownerId(owner), faultTreeParent(parent),
parameterDomainBase(parameterDomainBase) {
eventQueue = QueueFactory::instance()->createMessageQueue(messageDepth,
EventMessage::EVENT_MESSAGE_SIZE);
}
FailureIsolationBase::~FailureIsolationBase() {
QueueFactory::instance()->deleteMessageQueue(eventQueue);
}
ReturnValue_t FailureIsolationBase::initialize() {
EventManagerIF* manager = objectManager->get<EventManagerIF>(
objects::EVENT_MANAGER);
if (manager == nullptr) {
sif::error << "FailureIsolationBase::initialize: Event Manager has not"
" been initialized!" << std::endl;
return RETURN_FAILED;
}
ReturnValue_t result = manager->registerListener(eventQueue->getId());
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (ownerId != objects::NO_OBJECT) {
result = manager->subscribeToAllEventsFrom(eventQueue->getId(), ownerId);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
owner = objectManager->get<HasHealthIF>(ownerId);
if (owner == nullptr) {
sif::error << "FailureIsolationBase::intialize: Owner object "
"invalid. Make sure it implements HasHealthIF" << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
}
if (faultTreeParent != objects::NO_OBJECT) {
ConfirmsFailuresIF* parentIF = objectManager->get<ConfirmsFailuresIF>(
faultTreeParent);
if (parentIF == nullptr) {
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF."
<< std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
return RETURN_FAILED;
}
eventQueue->setDefaultDestination(parentIF->getEventReceptionQueue());
}
return RETURN_OK;
}
void FailureIsolationBase::checkForFailures() {
EventMessage event;
for (ReturnValue_t result = eventQueue->receiveMessage(&event);
result == RETURN_OK; result = eventQueue->receiveMessage(&event)) {
if (event.getSender() == eventQueue->getId()) {
//We already got this event, because we sent it.
continue;
}
switch (event.getMessageId()) {
case EventMessage::EVENT_MESSAGE:
if (isFdirDisabledForSeverity(event.getSeverity())) {
//We do not handle events when disabled.
continue;
}
eventReceived(&event);
break;
case EventMessage::CONFIRMATION_REQUEST:
doConfirmFault(&event);
break;
case EventMessage::YOUR_FAULT:
eventConfirmed(&event);
break;
case EventMessage::MY_FAULT:
wasParentsFault(&event);
break;
default:
break;
}
}
decrementFaultCounters();
}
void FailureIsolationBase::setOwnerHealth(HasHealthIF::HealthState health) {
if (owner != NULL) {
owner->setHealth(health);
}
//else: owner has no health.
}
MessageQueueId_t FailureIsolationBase::getEventReceptionQueue() {
return eventQueue->getId();
}
ReturnValue_t FailureIsolationBase::sendConfirmationRequest(EventMessage* event,
MessageQueueId_t destination) {
event->setMessageId(EventMessage::CONFIRMATION_REQUEST);
if (destination != MessageQueueIF::NO_QUEUE) {
return eventQueue->sendMessage(destination, event);
} else if (faultTreeParent != objects::NO_OBJECT) {
return eventQueue->sendToDefault(event);
}
return RETURN_FAILED;
}
void FailureIsolationBase::eventConfirmed(EventMessage* event) {
}
void FailureIsolationBase::wasParentsFault(EventMessage* event) {
}
void FailureIsolationBase::doConfirmFault(EventMessage* event) {
ReturnValue_t result = confirmFault(event);
if (result == YOUR_FAULT) {
event->setMessageId(EventMessage::YOUR_FAULT);
eventQueue->reply(event);
} else if (result == MY_FAULT) {
event->setMessageId(EventMessage::MY_FAULT);
eventQueue->reply(event);
} else {
}
}
ReturnValue_t FailureIsolationBase::confirmFault(EventMessage* event) {
return YOUR_FAULT;
}
void FailureIsolationBase::triggerEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
//With this mechanism, all events are disabled for a certain device.
//That's not so good for visibility.
if (isFdirDisabledForSeverity(EVENT::getSeverity(event))) {
return;
}
EventMessage message(event, ownerId, parameter1, parameter2);
EventManagerIF::triggerEvent(&message, eventQueue->getId());
eventReceived(&message);
}
bool FailureIsolationBase::isFdirDisabledForSeverity(EventSeverity_t severity) {
if ((owner != NULL) && (severity != SEVERITY::INFO)) {
if (owner->getHealth() == HasHealthIF::EXTERNAL_CONTROL) {
//External control disables handling of fault messages.
return true;
}
}
return false;
}
void FailureIsolationBase::throwFdirEvent(Event event, uint32_t parameter1,
uint32_t parameter2) {
EventMessage message(event, ownerId, parameter1, parameter2);
EventManagerIF::triggerEvent(&message, eventQueue->getId());
}

View File

@ -1,56 +1,56 @@
#ifndef FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_
#define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_
#include "../events/EventMessage.h"
#include "../fdir/ConfirmsFailuresIF.h"
#include "../fdir/FaultCounter.h"
#include "../health/HealthMessage.h"
#include "../parameters/HasParametersIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueIF.h"
class FailureIsolationBase: public HasReturnvaluesIF,
public ConfirmsFailuresIF,
public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, SEVERITY::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, SEVERITY::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner,
object_id_t parent = objects::NO_OBJECT,
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
virtual ~FailureIsolationBase();
virtual ReturnValue_t initialize();
/**
* This is called by the DHB in performOperation()
*/
void checkForFailures();
MessageQueueId_t getEventReceptionQueue() override;
virtual void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
protected:
MessageQueueIF* eventQueue = nullptr;
object_id_t ownerId;
HasHealthIF* owner = nullptr;
object_id_t faultTreeParent;
uint8_t parameterDomainBase;
void setOwnerHealth(HasHealthIF::HealthState health);
virtual ReturnValue_t eventReceived(EventMessage* event) = 0;
virtual void eventConfirmed(EventMessage* event);
virtual void wasParentsFault(EventMessage* event);
virtual ReturnValue_t confirmFault(EventMessage* event);
virtual void decrementFaultCounters() = 0;
ReturnValue_t sendConfirmationRequest(EventMessage* event,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
void throwFdirEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
private:
void doConfirmFault(EventMessage* event);bool isFdirDisabledForSeverity(
EventSeverity_t severity);
};
#endif /* FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ */
#ifndef FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_
#define FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_
#include "../events/EventMessage.h"
#include "../fdir/ConfirmsFailuresIF.h"
#include "../fdir/FaultCounter.h"
#include "../health/HealthMessage.h"
#include "../parameters/HasParametersIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueIF.h"
class FailureIsolationBase: public HasReturnvaluesIF,
public ConfirmsFailuresIF,
public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, SEVERITY::INFO); //!< FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, SEVERITY::MEDIUM); //!< FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, SEVERITY::MEDIUM); //!< FDIR turns off device. Par1: event that caused recovery.
FailureIsolationBase(object_id_t owner,
object_id_t parent = objects::NO_OBJECT,
uint8_t messageDepth = 10, uint8_t parameterDomainBase = 0xF0);
virtual ~FailureIsolationBase();
virtual ReturnValue_t initialize();
/**
* This is called by the DHB in performOperation()
*/
void checkForFailures();
MessageQueueId_t getEventReceptionQueue() override;
virtual void triggerEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
protected:
MessageQueueIF* eventQueue = nullptr;
object_id_t ownerId;
HasHealthIF* owner = nullptr;
object_id_t faultTreeParent;
uint8_t parameterDomainBase;
void setOwnerHealth(HasHealthIF::HealthState health);
virtual ReturnValue_t eventReceived(EventMessage* event) = 0;
virtual void eventConfirmed(EventMessage* event);
virtual void wasParentsFault(EventMessage* event);
virtual ReturnValue_t confirmFault(EventMessage* event);
virtual void decrementFaultCounters() = 0;
ReturnValue_t sendConfirmationRequest(EventMessage* event,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
void throwFdirEvent(Event event, uint32_t parameter1 = 0,
uint32_t parameter2 = 0);
private:
void doConfirmFault(EventMessage* event);bool isFdirDisabledForSeverity(
EventSeverity_t severity);
};
#endif /* FRAMEWORK_FDIR_FAILUREISOLATIONBASE_H_ */

View File

@ -1,86 +1,86 @@
#include "../fdir/FaultCounter.h"
FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain) :
parameterDomain(setParameterDomain), timer(), faultCount(0), failureThreshold(
failureThreshold) {
timer.setTimeout(decrementAfterMs);
}
FaultCounter::~FaultCounter() {
}
void FaultCounter::increment(uint32_t amount) {
if (faultCount == 0) {
timer.resetTimer();
}
faultCount += amount;
}
bool FaultCounter::checkForDecrement() {
if (timer.hasTimedOut()) {
timer.resetTimer();
if (faultCount > 0) {
faultCount--;
return true;
}
}
return false;
}
bool FaultCounter::incrementAndCheck(uint32_t amount) {
increment(amount);
return aboveThreshold();
}
bool FaultCounter::aboveThreshold() {
if (faultCount > failureThreshold) {
faultCount = 0;
return true;
} else {
return false;
}
}
void FaultCounter::clear() {
faultCount = 0;
}
void FaultCounter::setFailureThreshold(uint32_t failureThreshold) {
this->failureThreshold = failureThreshold;
}
void FaultCounter::setFaultDecrementTimeMs(uint32_t timeMs) {
timer.setTimeout(timeMs);
}
FaultCounter::FaultCounter() :
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
}
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
if (domainId != parameterDomain) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
case 0:
parameterWrapper->set(failureThreshold);
break;
case 1:
parameterWrapper->set(faultCount);
break;
case 2:
parameterWrapper->set(timer.timeout);
break;
default:
return INVALID_MATRIX_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FaultCounter::setParameterDomain(uint8_t domain) {
parameterDomain = domain;
}
#include "../fdir/FaultCounter.h"
FaultCounter::FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain) :
parameterDomain(setParameterDomain), timer(), faultCount(0), failureThreshold(
failureThreshold) {
timer.setTimeout(decrementAfterMs);
}
FaultCounter::~FaultCounter() {
}
void FaultCounter::increment(uint32_t amount) {
if (faultCount == 0) {
timer.resetTimer();
}
faultCount += amount;
}
bool FaultCounter::checkForDecrement() {
if (timer.hasTimedOut()) {
timer.resetTimer();
if (faultCount > 0) {
faultCount--;
return true;
}
}
return false;
}
bool FaultCounter::incrementAndCheck(uint32_t amount) {
increment(amount);
return aboveThreshold();
}
bool FaultCounter::aboveThreshold() {
if (faultCount > failureThreshold) {
faultCount = 0;
return true;
} else {
return false;
}
}
void FaultCounter::clear() {
faultCount = 0;
}
void FaultCounter::setFailureThreshold(uint32_t failureThreshold) {
this->failureThreshold = failureThreshold;
}
void FaultCounter::setFaultDecrementTimeMs(uint32_t timeMs) {
timer.setTimeout(timeMs);
}
FaultCounter::FaultCounter() :
parameterDomain(0), timer(), faultCount(0), failureThreshold(0) {
}
ReturnValue_t FaultCounter::getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper* parameterWrapper, const ParameterWrapper* newValues,
uint16_t startAtIndex) {
if (domainId != parameterDomain) {
return INVALID_DOMAIN_ID;
}
switch (parameterId) {
case 0:
parameterWrapper->set(failureThreshold);
break;
case 1:
parameterWrapper->set(faultCount);
break;
case 2:
parameterWrapper->set(timer.timeout);
break;
default:
return INVALID_MATRIX_ID;
}
return HasReturnvaluesIF::RETURN_OK;
}
void FaultCounter::setParameterDomain(uint8_t domain) {
parameterDomain = domain;
}

View File

@ -1,38 +1,38 @@
#ifndef FRAMEWORK_FDIR_FAULTCOUNTER_H_
#define FRAMEWORK_FDIR_FAULTCOUNTER_H_
#include "../parameters/HasParametersIF.h"
#include "../timemanager/Countdown.h"
class FaultCounter: public HasParametersIF {
public:
FaultCounter();
FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain = 0);
virtual ~FaultCounter();
bool incrementAndCheck(uint32_t amount = 1);
void increment(uint32_t amount = 1);
bool checkForDecrement();
bool aboveThreshold();
void clear();
void setFailureThreshold(uint32_t failureThreshold);
void setFaultDecrementTimeMs(uint32_t timeMs);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
void setParameterDomain(uint8_t domain);
private:
uint8_t parameterDomain;
Countdown timer;
uint32_t faultCount;
uint32_t failureThreshold;
};
#endif /* FRAMEWORK_FDIR_FAULTCOUNTER_H_ */
#ifndef FRAMEWORK_FDIR_FAULTCOUNTER_H_
#define FRAMEWORK_FDIR_FAULTCOUNTER_H_
#include "../parameters/HasParametersIF.h"
#include "../timemanager/Countdown.h"
class FaultCounter: public HasParametersIF {
public:
FaultCounter();
FaultCounter(uint32_t failureThreshold, uint32_t decrementAfterMs,
uint8_t setParameterDomain = 0);
virtual ~FaultCounter();
bool incrementAndCheck(uint32_t amount = 1);
void increment(uint32_t amount = 1);
bool checkForDecrement();
bool aboveThreshold();
void clear();
void setFailureThreshold(uint32_t failureThreshold);
void setFaultDecrementTimeMs(uint32_t timeMs);
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
ParameterWrapper *parameterWrapper,
const ParameterWrapper *newValues, uint16_t startAtIndex);
void setParameterDomain(uint8_t domain);
private:
uint8_t parameterDomain;
Countdown timer;
uint32_t faultCount;
uint32_t failureThreshold;
};
#endif /* FRAMEWORK_FDIR_FAULTCOUNTER_H_ */

View File

@ -1,230 +1,230 @@
#include "../globalfunctions/AsciiConverter.h"
#include <limits>
#include <cmath>
template<typename T>
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber(const uint8_t** dataPtr,
uint8_t len, T* value) {
if (len > std::numeric_limits<T>().digits10) {
return TOO_LONG_FOR_TARGET_TYPE;
}
double temp;
ReturnValue_t result = scanAsciiDecimalNumber_(dataPtr, len, &temp);
*value = temp;
return result;
}
ReturnValue_t AsciiConverter::scanAsciiHexByte(const uint8_t** dataPtr,
uint8_t* value) {
int8_t tmp;
tmp = convertHexChar(*dataPtr);
(*dataPtr)++;
if (tmp == -1) {
return INVALID_CHARACTERS;
}
if (tmp == -2) {
tmp = 0;
}
*value = tmp << 4;
tmp = convertHexChar(*dataPtr);
(*dataPtr)++;
if (tmp == -1) {
return INVALID_CHARACTERS;
}
if (tmp != -2) {
*value += tmp;
} else {
*value = *value >> 4;
}
return RETURN_OK;
}
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber_(uint8_t const ** dataPtr,
uint8_t len, double* value) {
uint8_t const *ptr = *dataPtr;
int8_t sign = 1;
float decimal = 0;
bool abort = false;
*value = 0;
//ignore leading space
ptr = clearSpace(ptr, len);
while ((ptr - *dataPtr < len) && !abort) {
switch (*ptr) {
case '+':
sign = 1;
break;
case '-':
sign = -1;
break;
case '.':
decimal = 1;
break;
case ' ':
case 0x0d:
case 0x0a:
//ignore trailing space
ptr = clearSpace(ptr, len - (ptr - *dataPtr)) - 1; //before aborting the loop, ptr will be incremented
abort = true;
break;
default:
if ((*ptr < 0x30) || (*ptr > 0x39)) {
return INVALID_CHARACTERS;
}
*value = *value * 10 + (*ptr - 0x30);
if (decimal > 0) {
decimal *= 10;
}
break;
}
ptr++;
}
if (decimal == 0) {
decimal = 1;
}
*value = *value / (decimal) * sign;
*dataPtr = ptr;
return RETURN_OK;
}
ReturnValue_t AsciiConverter::printFloat(uint8_t* buffer, uint32_t bufferLength,
float value, uint8_t decimalPlaces, uint32_t *printedSize) {
*printedSize = 0;
uint32_t streamposition = 0, integerSize;
bool negative = (value < 0);
int32_t digits = bufferLength - decimalPlaces - 1;
if (digits <= 0) {
return BUFFER_TOO_SMALL;
}
if (negative) {
digits -= 1;
buffer[streamposition++] = '-';
value = -value;
}
float maximumNumber = pow(10, digits);
if (value >= maximumNumber) {
return BUFFER_TOO_SMALL;
}
//print the numbers before the decimal point;
ReturnValue_t result = printInteger(buffer + streamposition,
bufferLength - streamposition - decimalPlaces - 1, value,
&integerSize);
if (result != RETURN_OK) {
return result;
}
streamposition += integerSize;
//The decimal Point
buffer[streamposition++] = '.';
//Print the decimals
uint32_t integerValue = value;
value -= integerValue;
value = value * pow(10, decimalPlaces);
result = printInteger(buffer + streamposition, decimalPlaces, round(value),
&integerSize, true);
*printedSize = integerSize + streamposition;
return result;
}
ReturnValue_t AsciiConverter::printInteger(uint8_t* buffer,
uint32_t bufferLength, uint32_t value, uint32_t *printedSize,
bool leadingZeros) {
*printedSize = 0;
if (bufferLength == 0) {
return BUFFER_TOO_SMALL;
}
uint32_t maximumNumber = -1;
if (bufferLength < 10) {
maximumNumber = pow(10, bufferLength);
if (value >= maximumNumber) {
return BUFFER_TOO_SMALL;
}
maximumNumber /= 10;
} else {
if (!(value <= maximumNumber)) {
return BUFFER_TOO_SMALL;
}
maximumNumber = 1000000000;
}
if (!leadingZeros && (value == 0)) {
buffer[(*printedSize)++] = '0';
return RETURN_OK;
}
while (maximumNumber >= 1) {
uint8_t number = value / maximumNumber;
value = value - (number * maximumNumber);
if (!leadingZeros && number == 0) {
maximumNumber /= 10;
} else {
leadingZeros = true;
buffer[(*printedSize)++] = '0' + number;
maximumNumber /= 10;
}
}
return RETURN_OK;
}
ReturnValue_t AsciiConverter::printSignedInteger(uint8_t* buffer,
uint32_t bufferLength, int32_t value, uint32_t *printedSize) {
bool negative = false;
if ((bufferLength > 0) && (value < 0)) {
*buffer++ = '-';
bufferLength--;
value = -value;
negative = true;
}
ReturnValue_t result = printInteger(buffer, bufferLength, value,
printedSize);
if (negative) {
(*printedSize)++;
}
return result;
}
int8_t AsciiConverter::convertHexChar(const uint8_t* character) {
if ((*character > 0x60) && (*character < 0x67)) {
return *character - 0x61 + 10;
} else if ((*character > 0x40) && (*character < 0x47)) {
return *character - 0x41 + 10;
} else if ((*character > 0x2F) && (*character < 0x3A)) {
return *character - 0x30;
} else if (*character == ' ') {
return -2;
}
return -1;
}
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<float>(
const uint8_t** dataPtr, uint8_t len, float* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint8_t>(
const uint8_t** dataPtr, uint8_t len, uint8_t* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint16_t>(
const uint8_t** dataPtr, uint8_t len, uint16_t* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<double>(
const uint8_t** dataPtr, uint8_t len, double* value);
const uint8_t* AsciiConverter::clearSpace(const uint8_t* data, uint8_t len) {
while (len > 0) {
if ((*data != ' ') && (*data != 0x0a) && (*data != 0x0d)) {
return data;
}
data++;
len--;
}
return data;
}
#include "../globalfunctions/AsciiConverter.h"
#include <limits>
#include <cmath>
template<typename T>
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber(const uint8_t** dataPtr,
uint8_t len, T* value) {
if (len > std::numeric_limits<T>().digits10) {
return TOO_LONG_FOR_TARGET_TYPE;
}
double temp;
ReturnValue_t result = scanAsciiDecimalNumber_(dataPtr, len, &temp);
*value = temp;
return result;
}
ReturnValue_t AsciiConverter::scanAsciiHexByte(const uint8_t** dataPtr,
uint8_t* value) {
int8_t tmp;
tmp = convertHexChar(*dataPtr);
(*dataPtr)++;
if (tmp == -1) {
return INVALID_CHARACTERS;
}
if (tmp == -2) {
tmp = 0;
}
*value = tmp << 4;
tmp = convertHexChar(*dataPtr);
(*dataPtr)++;
if (tmp == -1) {
return INVALID_CHARACTERS;
}
if (tmp != -2) {
*value += tmp;
} else {
*value = *value >> 4;
}
return RETURN_OK;
}
ReturnValue_t AsciiConverter::scanAsciiDecimalNumber_(uint8_t const ** dataPtr,
uint8_t len, double* value) {
uint8_t const *ptr = *dataPtr;
int8_t sign = 1;
float decimal = 0;
bool abort = false;
*value = 0;
//ignore leading space
ptr = clearSpace(ptr, len);
while ((ptr - *dataPtr < len) && !abort) {
switch (*ptr) {
case '+':
sign = 1;
break;
case '-':
sign = -1;
break;
case '.':
decimal = 1;
break;
case ' ':
case 0x0d:
case 0x0a:
//ignore trailing space
ptr = clearSpace(ptr, len - (ptr - *dataPtr)) - 1; //before aborting the loop, ptr will be incremented
abort = true;
break;
default:
if ((*ptr < 0x30) || (*ptr > 0x39)) {
return INVALID_CHARACTERS;
}
*value = *value * 10 + (*ptr - 0x30);
if (decimal > 0) {
decimal *= 10;
}
break;
}
ptr++;
}
if (decimal == 0) {
decimal = 1;
}
*value = *value / (decimal) * sign;
*dataPtr = ptr;
return RETURN_OK;
}
ReturnValue_t AsciiConverter::printFloat(uint8_t* buffer, uint32_t bufferLength,
float value, uint8_t decimalPlaces, uint32_t *printedSize) {
*printedSize = 0;
uint32_t streamposition = 0, integerSize;
bool negative = (value < 0);
int32_t digits = bufferLength - decimalPlaces - 1;
if (digits <= 0) {
return BUFFER_TOO_SMALL;
}
if (negative) {
digits -= 1;
buffer[streamposition++] = '-';
value = -value;
}
float maximumNumber = pow(10, digits);
if (value >= maximumNumber) {
return BUFFER_TOO_SMALL;
}
//print the numbers before the decimal point;
ReturnValue_t result = printInteger(buffer + streamposition,
bufferLength - streamposition - decimalPlaces - 1, value,
&integerSize);
if (result != RETURN_OK) {
return result;
}
streamposition += integerSize;
//The decimal Point
buffer[streamposition++] = '.';
//Print the decimals
uint32_t integerValue = value;
value -= integerValue;
value = value * pow(10, decimalPlaces);
result = printInteger(buffer + streamposition, decimalPlaces, round(value),
&integerSize, true);
*printedSize = integerSize + streamposition;
return result;
}
ReturnValue_t AsciiConverter::printInteger(uint8_t* buffer,
uint32_t bufferLength, uint32_t value, uint32_t *printedSize,
bool leadingZeros) {
*printedSize = 0;
if (bufferLength == 0) {
return BUFFER_TOO_SMALL;
}
uint32_t maximumNumber = -1;
if (bufferLength < 10) {
maximumNumber = pow(10, bufferLength);
if (value >= maximumNumber) {
return BUFFER_TOO_SMALL;
}
maximumNumber /= 10;
} else {
if (!(value <= maximumNumber)) {
return BUFFER_TOO_SMALL;
}
maximumNumber = 1000000000;
}
if (!leadingZeros && (value == 0)) {
buffer[(*printedSize)++] = '0';
return RETURN_OK;
}
while (maximumNumber >= 1) {
uint8_t number = value / maximumNumber;
value = value - (number * maximumNumber);
if (!leadingZeros && number == 0) {
maximumNumber /= 10;
} else {
leadingZeros = true;
buffer[(*printedSize)++] = '0' + number;
maximumNumber /= 10;
}
}
return RETURN_OK;
}
ReturnValue_t AsciiConverter::printSignedInteger(uint8_t* buffer,
uint32_t bufferLength, int32_t value, uint32_t *printedSize) {
bool negative = false;
if ((bufferLength > 0) && (value < 0)) {
*buffer++ = '-';
bufferLength--;
value = -value;
negative = true;
}
ReturnValue_t result = printInteger(buffer, bufferLength, value,
printedSize);
if (negative) {
(*printedSize)++;
}
return result;
}
int8_t AsciiConverter::convertHexChar(const uint8_t* character) {
if ((*character > 0x60) && (*character < 0x67)) {
return *character - 0x61 + 10;
} else if ((*character > 0x40) && (*character < 0x47)) {
return *character - 0x41 + 10;
} else if ((*character > 0x2F) && (*character < 0x3A)) {
return *character - 0x30;
} else if (*character == ' ') {
return -2;
}
return -1;
}
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<float>(
const uint8_t** dataPtr, uint8_t len, float* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint8_t>(
const uint8_t** dataPtr, uint8_t len, uint8_t* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<uint16_t>(
const uint8_t** dataPtr, uint8_t len, uint16_t* value);
template ReturnValue_t AsciiConverter::scanAsciiDecimalNumber<double>(
const uint8_t** dataPtr, uint8_t len, double* value);
const uint8_t* AsciiConverter::clearSpace(const uint8_t* data, uint8_t len) {
while (len > 0) {
if ((*data != ' ') && (*data != 0x0a) && (*data != 0x0d)) {
return data;
}
data++;
len--;
}
return data;
}

View File

@ -1,39 +1,39 @@
#ifndef ASCIICONVERTER_H_
#define ASCIICONVERTER_H_
#include "../returnvalues/HasReturnvaluesIF.h"
class AsciiConverter: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ASCII_CONVERTER;
static const ReturnValue_t TOO_LONG_FOR_TARGET_TYPE = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_CHARACTERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t BUFFER_TOO_SMALL = MAKE_RETURN_CODE(0x3);
template<typename T>
static ReturnValue_t scanAsciiDecimalNumber(const uint8_t **dataPtr,
uint8_t len, T *value);
static ReturnValue_t scanAsciiHexByte(const uint8_t **dataPtr,
uint8_t *value);
static ReturnValue_t printFloat(uint8_t *buffer, uint32_t bufferLength,
float value, uint8_t decimalPlaces, uint32_t *printedSize);
static ReturnValue_t printInteger(uint8_t *buffer, uint32_t bufferLength,
uint32_t value, uint32_t *printedSize, bool leadingZeros = false);
static ReturnValue_t printSignedInteger(uint8_t *buffer,
uint32_t bufferLength, int32_t value, uint32_t *printedSize);
private:
AsciiConverter();
static ReturnValue_t scanAsciiDecimalNumber_(const uint8_t **dataPtr,
uint8_t len, double *value);
static int8_t convertHexChar(const uint8_t *character);
static const uint8_t *clearSpace(const uint8_t *data, uint8_t len);
};
#endif /* ASCIICONVERTER_H_ */
#ifndef ASCIICONVERTER_H_
#define ASCIICONVERTER_H_
#include "../returnvalues/HasReturnvaluesIF.h"
class AsciiConverter: public HasReturnvaluesIF {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::ASCII_CONVERTER;
static const ReturnValue_t TOO_LONG_FOR_TARGET_TYPE = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_CHARACTERS = MAKE_RETURN_CODE(2);
static const ReturnValue_t BUFFER_TOO_SMALL = MAKE_RETURN_CODE(0x3);
template<typename T>
static ReturnValue_t scanAsciiDecimalNumber(const uint8_t **dataPtr,
uint8_t len, T *value);
static ReturnValue_t scanAsciiHexByte(const uint8_t **dataPtr,
uint8_t *value);
static ReturnValue_t printFloat(uint8_t *buffer, uint32_t bufferLength,
float value, uint8_t decimalPlaces, uint32_t *printedSize);
static ReturnValue_t printInteger(uint8_t *buffer, uint32_t bufferLength,
uint32_t value, uint32_t *printedSize, bool leadingZeros = false);
static ReturnValue_t printSignedInteger(uint8_t *buffer,
uint32_t bufferLength, int32_t value, uint32_t *printedSize);
private:
AsciiConverter();
static ReturnValue_t scanAsciiDecimalNumber_(const uint8_t **dataPtr,
uint8_t len, double *value);
static int8_t convertHexChar(const uint8_t *character);
static const uint8_t *clearSpace(const uint8_t *data, uint8_t len);
};
#endif /* ASCIICONVERTER_H_ */

View File

@ -1,139 +1,139 @@
#include "../globalfunctions/CRC.h"
#include <math.h>
const uint16_t CRC::crc16ccitt_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
// CRC implementation
uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t startingCrc)
{
uint8_t *data = (uint8_t *)input;
unsigned int tbl_idx;
while (length--) {
tbl_idx = ((startingCrc >> 8) ^ *data) & 0xff;
startingCrc = (crc16ccitt_table[tbl_idx] ^ (startingCrc << 8)) & 0xffff;
data++;
}
return startingCrc & 0xffff;
//The part below is not used!
// bool temr[16];
// bool xor_out[16];
// bool r[16];
// bool d[8];
// uint16_t crc_value = 0;
//
//
// for (int i=0; i<16 ;i++) {
// temr[i] = false;
// xor_out[i] = false;
// }
//
//
// for (int i=0; i<16 ;i++)
// r[i] = true; // initialize with 0xFFFF
//
//
//
// for (int j=0; j<length ;j++)
// {
//
// for (int i=0; i<8 ;i++)
// if ((input[j] & 1<<i) == 1<<i)
// d[7-i]=true; // reverse input data
// else
// d[7-i]=false; // reverse input data
//
//
//
// temr[0] = d[4] ^ d[0];
// temr[1] = d[5] ^ d[1];
// temr[2] = d[6] ^ d[2];
// temr[3] = d[7] ^ d[3];
// temr[4] = r[12] ^ r[8];
// temr[5] = r[13] ^ r[9];
// temr[6] = r[14] ^ r[10];
// temr[7] = r[15] ^ r[11];
// temr[8] = d[4] ^ r[12];
// temr[9] = d[5] ^ r[13];
// temr[10] = d[6] ^ r[14];
// temr[11] = d[7] ^ r[15];
// temr[12] = temr[0] ^ temr[4];
// temr[13] = temr[1] ^ temr[5];
// temr[14] = temr[2] ^ temr[6];
// temr[15] = temr[3] ^ temr[7];
//
//
// xor_out[0] = temr[12];
// xor_out[1] = temr[13];
// xor_out[2] = temr[14];
// xor_out[3] = temr[15];
// xor_out[4] = temr[8];
// xor_out[5] = temr[9] ^ temr[12];
// xor_out[6] = temr[10] ^ temr[13];
// xor_out[7] = temr[11] ^ temr[14];
// xor_out[8] = temr[15] ^ r[0];
// xor_out[9] = temr[8] ^ r[1];
// xor_out[10] = temr[9] ^ r[2];
// xor_out[11] = temr[10] ^ r[3];
// xor_out[12] = temr[11] ^ temr[12] ^ r[4];
// xor_out[13] = temr[13] ^ r[5];
// xor_out[14] = temr[14] ^ r[6];
// xor_out[15] = temr[15] ^ r[7];
//
// for (int i=0; i<16 ;i++)
// {
// r[i]= xor_out[i] ;
// }
//
// }
//
//
//
// for (int i=0; i<16 ;i++)
// {
// if (xor_out[i] == true)
// crc_value = crc_value + pow(2,(15 -i)); // reverse CrC result before Final XOR
// }
//
// crc_value = 0;// for debug mode
// return (crc_value);
} /* Calculate_CRC() */
#include "../globalfunctions/CRC.h"
#include <math.h>
const uint16_t CRC::crc16ccitt_table[256] = {
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50a5, 0x60c6, 0x70e7,
0x8108, 0x9129, 0xa14a, 0xb16b, 0xc18c, 0xd1ad, 0xe1ce, 0xf1ef,
0x1231, 0x0210, 0x3273, 0x2252, 0x52b5, 0x4294, 0x72f7, 0x62d6,
0x9339, 0x8318, 0xb37b, 0xa35a, 0xd3bd, 0xc39c, 0xf3ff, 0xe3de,
0x2462, 0x3443, 0x0420, 0x1401, 0x64e6, 0x74c7, 0x44a4, 0x5485,
0xa56a, 0xb54b, 0x8528, 0x9509, 0xe5ee, 0xf5cf, 0xc5ac, 0xd58d,
0x3653, 0x2672, 0x1611, 0x0630, 0x76d7, 0x66f6, 0x5695, 0x46b4,
0xb75b, 0xa77a, 0x9719, 0x8738, 0xf7df, 0xe7fe, 0xd79d, 0xc7bc,
0x48c4, 0x58e5, 0x6886, 0x78a7, 0x0840, 0x1861, 0x2802, 0x3823,
0xc9cc, 0xd9ed, 0xe98e, 0xf9af, 0x8948, 0x9969, 0xa90a, 0xb92b,
0x5af5, 0x4ad4, 0x7ab7, 0x6a96, 0x1a71, 0x0a50, 0x3a33, 0x2a12,
0xdbfd, 0xcbdc, 0xfbbf, 0xeb9e, 0x9b79, 0x8b58, 0xbb3b, 0xab1a,
0x6ca6, 0x7c87, 0x4ce4, 0x5cc5, 0x2c22, 0x3c03, 0x0c60, 0x1c41,
0xedae, 0xfd8f, 0xcdec, 0xddcd, 0xad2a, 0xbd0b, 0x8d68, 0x9d49,
0x7e97, 0x6eb6, 0x5ed5, 0x4ef4, 0x3e13, 0x2e32, 0x1e51, 0x0e70,
0xff9f, 0xefbe, 0xdfdd, 0xcffc, 0xbf1b, 0xaf3a, 0x9f59, 0x8f78,
0x9188, 0x81a9, 0xb1ca, 0xa1eb, 0xd10c, 0xc12d, 0xf14e, 0xe16f,
0x1080, 0x00a1, 0x30c2, 0x20e3, 0x5004, 0x4025, 0x7046, 0x6067,
0x83b9, 0x9398, 0xa3fb, 0xb3da, 0xc33d, 0xd31c, 0xe37f, 0xf35e,
0x02b1, 0x1290, 0x22f3, 0x32d2, 0x4235, 0x5214, 0x6277, 0x7256,
0xb5ea, 0xa5cb, 0x95a8, 0x8589, 0xf56e, 0xe54f, 0xd52c, 0xc50d,
0x34e2, 0x24c3, 0x14a0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
0xa7db, 0xb7fa, 0x8799, 0x97b8, 0xe75f, 0xf77e, 0xc71d, 0xd73c,
0x26d3, 0x36f2, 0x0691, 0x16b0, 0x6657, 0x7676, 0x4615, 0x5634,
0xd94c, 0xc96d, 0xf90e, 0xe92f, 0x99c8, 0x89e9, 0xb98a, 0xa9ab,
0x5844, 0x4865, 0x7806, 0x6827, 0x18c0, 0x08e1, 0x3882, 0x28a3,
0xcb7d, 0xdb5c, 0xeb3f, 0xfb1e, 0x8bf9, 0x9bd8, 0xabbb, 0xbb9a,
0x4a75, 0x5a54, 0x6a37, 0x7a16, 0x0af1, 0x1ad0, 0x2ab3, 0x3a92,
0xfd2e, 0xed0f, 0xdd6c, 0xcd4d, 0xbdaa, 0xad8b, 0x9de8, 0x8dc9,
0x7c26, 0x6c07, 0x5c64, 0x4c45, 0x3ca2, 0x2c83, 0x1ce0, 0x0cc1,
0xef1f, 0xff3e, 0xcf5d, 0xdf7c, 0xaf9b, 0xbfba, 0x8fd9, 0x9ff8,
0x6e17, 0x7e36, 0x4e55, 0x5e74, 0x2e93, 0x3eb2, 0x0ed1, 0x1ef0
};
// CRC implementation
uint16_t CRC::crc16ccitt(uint8_t const input[], uint32_t length, uint16_t startingCrc)
{
uint8_t *data = (uint8_t *)input;
unsigned int tbl_idx;
while (length--) {
tbl_idx = ((startingCrc >> 8) ^ *data) & 0xff;
startingCrc = (crc16ccitt_table[tbl_idx] ^ (startingCrc << 8)) & 0xffff;
data++;
}
return startingCrc & 0xffff;
//The part below is not used!
// bool temr[16];
// bool xor_out[16];
// bool r[16];
// bool d[8];
// uint16_t crc_value = 0;
//
//
// for (int i=0; i<16 ;i++) {
// temr[i] = false;
// xor_out[i] = false;
// }
//
//
// for (int i=0; i<16 ;i++)
// r[i] = true; // initialize with 0xFFFF
//
//
//
// for (int j=0; j<length ;j++)
// {
//
// for (int i=0; i<8 ;i++)
// if ((input[j] & 1<<i) == 1<<i)
// d[7-i]=true; // reverse input data
// else
// d[7-i]=false; // reverse input data
//
//
//
// temr[0] = d[4] ^ d[0];
// temr[1] = d[5] ^ d[1];
// temr[2] = d[6] ^ d[2];
// temr[3] = d[7] ^ d[3];
// temr[4] = r[12] ^ r[8];
// temr[5] = r[13] ^ r[9];
// temr[6] = r[14] ^ r[10];
// temr[7] = r[15] ^ r[11];
// temr[8] = d[4] ^ r[12];
// temr[9] = d[5] ^ r[13];
// temr[10] = d[6] ^ r[14];
// temr[11] = d[7] ^ r[15];
// temr[12] = temr[0] ^ temr[4];
// temr[13] = temr[1] ^ temr[5];
// temr[14] = temr[2] ^ temr[6];
// temr[15] = temr[3] ^ temr[7];
//
//
// xor_out[0] = temr[12];
// xor_out[1] = temr[13];
// xor_out[2] = temr[14];
// xor_out[3] = temr[15];
// xor_out[4] = temr[8];
// xor_out[5] = temr[9] ^ temr[12];
// xor_out[6] = temr[10] ^ temr[13];
// xor_out[7] = temr[11] ^ temr[14];
// xor_out[8] = temr[15] ^ r[0];
// xor_out[9] = temr[8] ^ r[1];
// xor_out[10] = temr[9] ^ r[2];
// xor_out[11] = temr[10] ^ r[3];
// xor_out[12] = temr[11] ^ temr[12] ^ r[4];
// xor_out[13] = temr[13] ^ r[5];
// xor_out[14] = temr[14] ^ r[6];
// xor_out[15] = temr[15] ^ r[7];
//
// for (int i=0; i<16 ;i++)
// {
// r[i]= xor_out[i] ;
// }
//
// }
//
//
//
// for (int i=0; i<16 ;i++)
// {
// if (xor_out[i] == true)
// crc_value = crc_value + pow(2,(15 -i)); // reverse CrC result before Final XOR
// }
//
// crc_value = 0;// for debug mode
// return (crc_value);
} /* Calculate_CRC() */

View File

@ -1,124 +1,124 @@
#include "../globalfunctions/DleEncoder.h"
DleEncoder::DleEncoder() {}
DleEncoder::~DleEncoder() {}
ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
size_t sourceLen, uint8_t* destStream, size_t maxDestLen,
size_t* encodedLen, bool addStxEtx) {
if (maxDestLen < 2) {
return STREAM_TOO_SHORT;
}
size_t encodedIndex = 0, sourceIndex = 0;
uint8_t nextByte;
if (addStxEtx) {
destStream[0] = STX_CHAR;
++encodedIndex;
}
while (encodedIndex < maxDestLen and sourceIndex < sourceLen)
{
nextByte = sourceStream[sourceIndex];
// STX, ETX and CR characters in the stream need to be escaped with DLE
if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) {
if (encodedIndex + 1 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
else {
destStream[encodedIndex] = DLE_CHAR;
++encodedIndex;
/* Escaped byte will be actual byte + 0x40. This prevents
* STX, ETX, and carriage return characters from appearing
* in the encoded data stream at all, so when polling an
* encoded stream, the transmission can be stopped at ETX.
* 0x40 was chosen at random with special requirements:
* - Prevent going from one control char to another
* - Prevent overflow for common characters */
destStream[encodedIndex] = nextByte + 0x40;
}
}
// DLE characters are simply escaped with DLE.
else if (nextByte == DLE_CHAR) {
if (encodedIndex + 1 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
else {
destStream[encodedIndex] = DLE_CHAR;
++encodedIndex;
destStream[encodedIndex] = DLE_CHAR;
}
}
else {
destStream[encodedIndex] = nextByte;
}
++encodedIndex;
++sourceIndex;
}
if (sourceIndex == sourceLen and encodedIndex < maxDestLen) {
if (addStxEtx) {
destStream[encodedIndex] = ETX_CHAR;
++encodedIndex;
}
*encodedLen = encodedIndex;
return RETURN_OK;
}
else {
return STREAM_TOO_SHORT;
}
}
ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen) {
size_t encodedIndex = 0, decodedIndex = 0;
uint8_t nextByte;
if (*sourceStream != STX_CHAR) {
return DECODING_ERROR;
}
++encodedIndex;
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)
&& (sourceStream[encodedIndex] != ETX_CHAR)
&& (sourceStream[encodedIndex] != STX_CHAR)) {
if (sourceStream[encodedIndex] == DLE_CHAR) {
nextByte = sourceStream[encodedIndex + 1];
// The next byte is a DLE character that was escaped by another
// DLE character, so we can write it to the destination stream.
if (nextByte == DLE_CHAR) {
destStream[decodedIndex] = nextByte;
}
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,
* in the stream at all, so we convert it back. */
if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) {
destStream[decodedIndex] = nextByte - 0x40;
}
else {
return DECODING_ERROR;
}
}
++encodedIndex;
}
else {
destStream[decodedIndex] = sourceStream[encodedIndex];
}
++encodedIndex;
++decodedIndex;
}
if (sourceStream[encodedIndex] != ETX_CHAR) {
*readLen = ++encodedIndex;
return DECODING_ERROR;
}
else {
*readLen = ++encodedIndex;
*decodedLen = decodedIndex;
return RETURN_OK;
}
}
#include "../globalfunctions/DleEncoder.h"
DleEncoder::DleEncoder() {}
DleEncoder::~DleEncoder() {}
ReturnValue_t DleEncoder::encode(const uint8_t* sourceStream,
size_t sourceLen, uint8_t* destStream, size_t maxDestLen,
size_t* encodedLen, bool addStxEtx) {
if (maxDestLen < 2) {
return STREAM_TOO_SHORT;
}
size_t encodedIndex = 0, sourceIndex = 0;
uint8_t nextByte;
if (addStxEtx) {
destStream[0] = STX_CHAR;
++encodedIndex;
}
while (encodedIndex < maxDestLen and sourceIndex < sourceLen)
{
nextByte = sourceStream[sourceIndex];
// STX, ETX and CR characters in the stream need to be escaped with DLE
if (nextByte == STX_CHAR or nextByte == ETX_CHAR or nextByte == CARRIAGE_RETURN) {
if (encodedIndex + 1 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
else {
destStream[encodedIndex] = DLE_CHAR;
++encodedIndex;
/* Escaped byte will be actual byte + 0x40. This prevents
* STX, ETX, and carriage return characters from appearing
* in the encoded data stream at all, so when polling an
* encoded stream, the transmission can be stopped at ETX.
* 0x40 was chosen at random with special requirements:
* - Prevent going from one control char to another
* - Prevent overflow for common characters */
destStream[encodedIndex] = nextByte + 0x40;
}
}
// DLE characters are simply escaped with DLE.
else if (nextByte == DLE_CHAR) {
if (encodedIndex + 1 >= maxDestLen) {
return STREAM_TOO_SHORT;
}
else {
destStream[encodedIndex] = DLE_CHAR;
++encodedIndex;
destStream[encodedIndex] = DLE_CHAR;
}
}
else {
destStream[encodedIndex] = nextByte;
}
++encodedIndex;
++sourceIndex;
}
if (sourceIndex == sourceLen and encodedIndex < maxDestLen) {
if (addStxEtx) {
destStream[encodedIndex] = ETX_CHAR;
++encodedIndex;
}
*encodedLen = encodedIndex;
return RETURN_OK;
}
else {
return STREAM_TOO_SHORT;
}
}
ReturnValue_t DleEncoder::decode(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen) {
size_t encodedIndex = 0, decodedIndex = 0;
uint8_t nextByte;
if (*sourceStream != STX_CHAR) {
return DECODING_ERROR;
}
++encodedIndex;
while ((encodedIndex < sourceStreamLen) && (decodedIndex < maxDestStreamlen)
&& (sourceStream[encodedIndex] != ETX_CHAR)
&& (sourceStream[encodedIndex] != STX_CHAR)) {
if (sourceStream[encodedIndex] == DLE_CHAR) {
nextByte = sourceStream[encodedIndex + 1];
// The next byte is a DLE character that was escaped by another
// DLE character, so we can write it to the destination stream.
if (nextByte == DLE_CHAR) {
destStream[decodedIndex] = nextByte;
}
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,
* in the stream at all, so we convert it back. */
if (nextByte == 0x42 or nextByte == 0x43 or nextByte == 0x4D) {
destStream[decodedIndex] = nextByte - 0x40;
}
else {
return DECODING_ERROR;
}
}
++encodedIndex;
}
else {
destStream[decodedIndex] = sourceStream[encodedIndex];
}
++encodedIndex;
++decodedIndex;
}
if (sourceStream[encodedIndex] != ETX_CHAR) {
*readLen = ++encodedIndex;
return DECODING_ERROR;
}
else {
*readLen = ++encodedIndex;
*decodedLen = decodedIndex;
return RETURN_OK;
}
}

View File

@ -1,79 +1,79 @@
#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
/**
* @brief This DLE Encoder (Data Link Encoder) can be used to encode and
* decode arbitrary data with ASCII control characters
* @details
* List of control codes:
* https://en.wikipedia.org/wiki/C0_and_C1_control_codes
*
* This encoder can be used to achieve a basic transport layer when using
* 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
* 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,
* 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.
*/
class DleEncoder: public HasReturnvaluesIF {
private:
DleEncoder();
virtual ~DleEncoder();
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER;
static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02);
//! Start Of Text character. First character is encoded stream
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
//! in the source stream.
static constexpr uint8_t DLE_CHAR = 0x10;
static constexpr uint8_t CARRIAGE_RETURN = 0x0D;
/**
* 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).
* @param sourceStream
* @param sourceLen
* @param destStream
* @param maxDestLen
* @param encodedLen
* @param addStxEtx
* Adding STX and ETX can be omitted, if they are added manually.
* @return
*/
static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen,
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
bool addStxEtx = true);
/**
* Converts an encoded stream back.
* @param sourceStream
* @param sourceStreamLen
* @param readLen
* @param destStream
* @param maxDestStreamlen
* @param decodedLen
* @return
*/
static ReturnValue_t decode(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen);
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */
#ifndef FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
#define FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include <cstddef>
/**
* @brief This DLE Encoder (Data Link Encoder) can be used to encode and
* decode arbitrary data with ASCII control characters
* @details
* List of control codes:
* https://en.wikipedia.org/wiki/C0_and_C1_control_codes
*
* This encoder can be used to achieve a basic transport layer when using
* 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
* 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,
* 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.
*/
class DleEncoder: public HasReturnvaluesIF {
private:
DleEncoder();
virtual ~DleEncoder();
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DLE_ENCODER;
static constexpr ReturnValue_t STREAM_TOO_SHORT = MAKE_RETURN_CODE(0x01);
static constexpr ReturnValue_t DECODING_ERROR = MAKE_RETURN_CODE(0x02);
//! Start Of Text character. First character is encoded stream
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
//! in the source stream.
static constexpr uint8_t DLE_CHAR = 0x10;
static constexpr uint8_t CARRIAGE_RETURN = 0x0D;
/**
* 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).
* @param sourceStream
* @param sourceLen
* @param destStream
* @param maxDestLen
* @param encodedLen
* @param addStxEtx
* Adding STX and ETX can be omitted, if they are added manually.
* @return
*/
static ReturnValue_t encode(const uint8_t *sourceStream, size_t sourceLen,
uint8_t *destStream, size_t maxDestLen, size_t *encodedLen,
bool addStxEtx = true);
/**
* Converts an encoded stream back.
* @param sourceStream
* @param sourceStreamLen
* @param readLen
* @param destStream
* @param maxDestStreamlen
* @param decodedLen
* @return
*/
static ReturnValue_t decode(const uint8_t *sourceStream,
size_t sourceStreamLen, size_t *readLen, uint8_t *destStream,
size_t maxDestStreamlen, size_t *decodedLen);
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_DLEENCODER_H_ */

View File

@ -1,181 +1,181 @@
#include "../globalfunctions/Type.h"
#include "../serialize/SerializeAdapter.h"
Type::Type() :
actualType(UNKNOWN_TYPE) {
}
Type::Type(ActualType_t actualType) :
actualType(actualType) {
}
Type::Type(const Type& type) :
actualType(type.actualType) {
}
Type& Type::operator =(Type rhs) {
this->actualType = rhs.actualType;
return *this;
}
Type& Type::operator =(ActualType_t actualType) {
this->actualType = actualType;
return *this;
}
Type::operator Type::ActualType_t() const {
return actualType;
}
bool Type::operator ==(const Type& rhs) {
return this->actualType == rhs.actualType;
}
bool Type::operator !=(const Type& rhs) {
return !operator==(rhs);
}
uint8_t Type::getSize() const {
switch (actualType) {
case UINT8_T:
return sizeof(uint8_t);
case INT8_T:
return sizeof(int8_t);
case UINT16_T:
return sizeof(uint16_t);
case INT16_T:
return sizeof(int16_t);
case UINT32_T:
return sizeof(uint32_t);
case INT32_T:
return sizeof(int32_t);
case FLOAT:
return sizeof(float);
case DOUBLE:
return sizeof(double);
default:
return 0;
}
}
ReturnValue_t Type::serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
uint8_t ptc;
uint8_t pfc;
ReturnValue_t result = getPtcPfc(&ptc, &pfc);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&ptc, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&pfc, buffer, size, maxSize,
streamEndianness);
return result;
}
size_t Type::getSerializedSize() const {
uint8_t dontcare = 0;
return 2 * SerializeAdapter::getSerializedSize(&dontcare);
}
ReturnValue_t Type::deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
uint8_t ptc;
uint8_t pfc;
ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer,
size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&pfc, buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
actualType = getActualType(ptc, pfc);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Type::getPtcPfc(uint8_t* ptc, uint8_t* pfc) const {
switch (actualType) {
case UINT8_T:
*ptc = 3;
*pfc = 4;
break;
case INT8_T:
*ptc = 4;
*pfc = 4;
break;
case UINT16_T:
*ptc = 3;
*pfc = 12;
break;
case INT16_T:
*ptc = 4;
*pfc = 12;
break;
case UINT32_T:
*ptc = 3;
*pfc = 14;
break;
case INT32_T:
*ptc = 4;
*pfc = 14;
break;
case FLOAT:
*ptc = 5;
*pfc = 1;
break;
case DOUBLE:
*ptc = 5;
*pfc = 2;
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
Type::ActualType_t Type::getActualType(uint8_t ptc, uint8_t pfc) {
switch (ptc) {
case 3:
switch (pfc) {
case 4:
return UINT8_T;
case 12:
return UINT16_T;
case 14:
return UINT32_T;
}
break;
case 4:
switch (pfc) {
case 4:
return INT8_T;
case 12:
return INT16_T;
case 14:
return INT32_T;
}
break;
case 5:
switch (pfc) {
case 1:
return FLOAT;
case 2:
return DOUBLE;
}
break;
}
return UNKNOWN_TYPE;
}
#include "../globalfunctions/Type.h"
#include "../serialize/SerializeAdapter.h"
Type::Type() :
actualType(UNKNOWN_TYPE) {
}
Type::Type(ActualType_t actualType) :
actualType(actualType) {
}
Type::Type(const Type& type) :
actualType(type.actualType) {
}
Type& Type::operator =(Type rhs) {
this->actualType = rhs.actualType;
return *this;
}
Type& Type::operator =(ActualType_t actualType) {
this->actualType = actualType;
return *this;
}
Type::operator Type::ActualType_t() const {
return actualType;
}
bool Type::operator ==(const Type& rhs) {
return this->actualType == rhs.actualType;
}
bool Type::operator !=(const Type& rhs) {
return !operator==(rhs);
}
uint8_t Type::getSize() const {
switch (actualType) {
case UINT8_T:
return sizeof(uint8_t);
case INT8_T:
return sizeof(int8_t);
case UINT16_T:
return sizeof(uint16_t);
case INT16_T:
return sizeof(int16_t);
case UINT32_T:
return sizeof(uint32_t);
case INT32_T:
return sizeof(int32_t);
case FLOAT:
return sizeof(float);
case DOUBLE:
return sizeof(double);
default:
return 0;
}
}
ReturnValue_t Type::serialize(uint8_t** buffer, size_t* size,
size_t maxSize, Endianness streamEndianness) const {
uint8_t ptc;
uint8_t pfc;
ReturnValue_t result = getPtcPfc(&ptc, &pfc);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&ptc, buffer, size, maxSize,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&pfc, buffer, size, maxSize,
streamEndianness);
return result;
}
size_t Type::getSerializedSize() const {
uint8_t dontcare = 0;
return 2 * SerializeAdapter::getSerializedSize(&dontcare);
}
ReturnValue_t Type::deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) {
uint8_t ptc;
uint8_t pfc;
ReturnValue_t result = SerializeAdapter::deSerialize(&ptc, buffer,
size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&pfc, buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
actualType = getActualType(ptc, pfc);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t Type::getPtcPfc(uint8_t* ptc, uint8_t* pfc) const {
switch (actualType) {
case UINT8_T:
*ptc = 3;
*pfc = 4;
break;
case INT8_T:
*ptc = 4;
*pfc = 4;
break;
case UINT16_T:
*ptc = 3;
*pfc = 12;
break;
case INT16_T:
*ptc = 4;
*pfc = 12;
break;
case UINT32_T:
*ptc = 3;
*pfc = 14;
break;
case INT32_T:
*ptc = 4;
*pfc = 14;
break;
case FLOAT:
*ptc = 5;
*pfc = 1;
break;
case DOUBLE:
*ptc = 5;
*pfc = 2;
break;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
return HasReturnvaluesIF::RETURN_OK;
}
Type::ActualType_t Type::getActualType(uint8_t ptc, uint8_t pfc) {
switch (ptc) {
case 3:
switch (pfc) {
case 4:
return UINT8_T;
case 12:
return UINT16_T;
case 14:
return UINT32_T;
}
break;
case 4:
switch (pfc) {
case 4:
return INT8_T;
case 12:
return INT16_T;
case 14:
return INT32_T;
}
break;
case 5:
switch (pfc) {
case 1:
return FLOAT;
case 2:
return DOUBLE;
}
break;
}
return UNKNOWN_TYPE;
}

View File

@ -1,94 +1,94 @@
#ifndef TYPE_H_
#define TYPE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeIF.h"
/**
* @brief Type definition for CCSDS or ECSS.
*/
class Type: public SerializeIF {
public:
enum ActualType_t {
UINT8_T,
INT8_T,
UINT16_T,
INT16_T,
UINT32_T,
INT32_T,
FLOAT,
DOUBLE,
UNKNOWN_TYPE
};
Type();
Type(ActualType_t actualType);
Type(const Type &type);
Type& operator=(Type rhs);
Type& operator=(ActualType_t actualType);
operator ActualType_t() const;
bool operator==(const Type &rhs);
bool operator!=(const Type &rhs);
uint8_t getSize() const;
ReturnValue_t getPtcPfc(uint8_t *ptc, uint8_t *pfc) const;
static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
ActualType_t actualType;
};
template<typename T>
struct PodTypeConversion {
static const Type::ActualType_t type = Type::UNKNOWN_TYPE;
};
template<>
struct PodTypeConversion<uint8_t> {
static const Type::ActualType_t type = Type::UINT8_T;
};
template<>
struct PodTypeConversion<uint16_t> {
static const Type::ActualType_t type = Type::UINT16_T;
};
template<>
struct PodTypeConversion<uint32_t> {
static const Type::ActualType_t type = Type::UINT32_T;
};
template<>
struct PodTypeConversion<int8_t> {
static const Type::ActualType_t type = Type::INT8_T;
};
template<>
struct PodTypeConversion<int16_t> {
static const Type::ActualType_t type = Type::INT16_T;
};
template<>
struct PodTypeConversion<int32_t> {
static const Type::ActualType_t type = Type::INT32_T;
};
template<>
struct PodTypeConversion<float> {
static const Type::ActualType_t type = Type::FLOAT;
};
template<>
struct PodTypeConversion<double> {
static const Type::ActualType_t type = Type::DOUBLE;
};
#endif /* TYPE_H_ */
#ifndef TYPE_H_
#define TYPE_H_
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../serialize/SerializeIF.h"
/**
* @brief Type definition for CCSDS or ECSS.
*/
class Type: public SerializeIF {
public:
enum ActualType_t {
UINT8_T,
INT8_T,
UINT16_T,
INT16_T,
UINT32_T,
INT32_T,
FLOAT,
DOUBLE,
UNKNOWN_TYPE
};
Type();
Type(ActualType_t actualType);
Type(const Type &type);
Type& operator=(Type rhs);
Type& operator=(ActualType_t actualType);
operator ActualType_t() const;
bool operator==(const Type &rhs);
bool operator!=(const Type &rhs);
uint8_t getSize() const;
ReturnValue_t getPtcPfc(uint8_t *ptc, uint8_t *pfc) const;
static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size,
size_t maxSize, Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
private:
ActualType_t actualType;
};
template<typename T>
struct PodTypeConversion {
static const Type::ActualType_t type = Type::UNKNOWN_TYPE;
};
template<>
struct PodTypeConversion<uint8_t> {
static const Type::ActualType_t type = Type::UINT8_T;
};
template<>
struct PodTypeConversion<uint16_t> {
static const Type::ActualType_t type = Type::UINT16_T;
};
template<>
struct PodTypeConversion<uint32_t> {
static const Type::ActualType_t type = Type::UINT32_T;
};
template<>
struct PodTypeConversion<int8_t> {
static const Type::ActualType_t type = Type::INT8_T;
};
template<>
struct PodTypeConversion<int16_t> {
static const Type::ActualType_t type = Type::INT16_T;
};
template<>
struct PodTypeConversion<int32_t> {
static const Type::ActualType_t type = Type::INT32_T;
};
template<>
struct PodTypeConversion<float> {
static const Type::ActualType_t type = Type::FLOAT;
};
template<>
struct PodTypeConversion<double> {
static const Type::ActualType_t type = Type::DOUBLE;
};
#endif /* TYPE_H_ */

View File

@ -1,61 +1,61 @@
#include "../globalfunctions/arrayprinter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <bitset>
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
bool printInfo, size_t maxCharPerLine) {
if(printInfo) {
sif::info << "Printing data with size " << size << ": ";
}
sif::info << "[";
if(type == OutputType::HEX) {
arrayprinter::printHex(data, size, maxCharPerLine);
}
else if (type == OutputType::DEC) {
arrayprinter::printDec(data, size, maxCharPerLine);
}
else if(type == OutputType::BIN) {
arrayprinter::printBin(data, size);
}
}
void arrayprinter::printHex(const uint8_t *data, size_t size,
size_t maxCharPerLine) {
sif::info << std::hex;
for(size_t i = 0; i < size; i++) {
sif::info << "0x" << static_cast<int>(data[i]);
if(i < size - 1){
sif::info << " , ";
if(i > 0 and i % maxCharPerLine == 0) {
sif::info << "\r\n" << std::flush;
}
}
}
sif::info << std::dec;
sif::info << "]" << std::endl;
}
void arrayprinter::printDec(const uint8_t *data, size_t size,
size_t maxCharPerLine) {
sif::info << std::dec;
for(size_t i = 0; i < size; i++) {
sif::info << static_cast<int>(data[i]);
if(i < size - 1){
sif::info << " , ";
if(i > 0 and i % maxCharPerLine == 0) {
sif::info << std::endl;
}
}
}
sif::info << "]" << std::endl;
}
void arrayprinter::printBin(const uint8_t *data, size_t size) {
sif::info << "\n" << std::flush;
for(size_t i = 0; i < size; i++) {
sif::info << "Byte " << i + 1 << ": 0b"<<
std::bitset<8>(data[i]) << ",\n" << std::flush;
}
sif::info << "]" << std::endl;
}
#include "../globalfunctions/arrayprinter.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include <bitset>
void arrayprinter::print(const uint8_t *data, size_t size, OutputType type,
bool printInfo, size_t maxCharPerLine) {
if(printInfo) {
sif::info << "Printing data with size " << size << ": ";
}
sif::info << "[";
if(type == OutputType::HEX) {
arrayprinter::printHex(data, size, maxCharPerLine);
}
else if (type == OutputType::DEC) {
arrayprinter::printDec(data, size, maxCharPerLine);
}
else if(type == OutputType::BIN) {
arrayprinter::printBin(data, size);
}
}
void arrayprinter::printHex(const uint8_t *data, size_t size,
size_t maxCharPerLine) {
sif::info << std::hex;
for(size_t i = 0; i < size; i++) {
sif::info << "0x" << static_cast<int>(data[i]);
if(i < size - 1){
sif::info << " , ";
if(i > 0 and i % maxCharPerLine == 0) {
sif::info << "\r\n" << std::flush;
}
}
}
sif::info << std::dec;
sif::info << "]" << std::endl;
}
void arrayprinter::printDec(const uint8_t *data, size_t size,
size_t maxCharPerLine) {
sif::info << std::dec;
for(size_t i = 0; i < size; i++) {
sif::info << static_cast<int>(data[i]);
if(i < size - 1){
sif::info << " , ";
if(i > 0 and i % maxCharPerLine == 0) {
sif::info << std::endl;
}
}
}
sif::info << "]" << std::endl;
}
void arrayprinter::printBin(const uint8_t *data, size_t size) {
sif::info << "\n" << std::flush;
for(size_t i = 0; i < size; i++) {
sif::info << "Byte " << i + 1 << ": 0b"<<
std::bitset<8>(data[i]) << ",\n" << std::flush;
}
sif::info << "]" << std::endl;
}

View File

@ -1,41 +1,41 @@
#ifndef BINARYMATCHER_H_
#define BINARYMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h"
template<typename T>
class BinaryMatcher: public MatcherIF<T> {
public:
bool inverted;
T mask, matchField;
BinaryMatcher() :
inverted(false), mask(0), matchField(0) {
}
BinaryMatcher(T mask, T match, bool inverted = false) :
inverted(inverted), mask(mask), matchField(match) {
}
bool match(T input) {
if (inverted) {
return ~doMatch(input, mask, matchField);
} else {
return doMatch(input, mask, matchField);
}
}
protected:
bool doMatch(T input, T mask, T match) {
match = match & mask;
input = input & mask;
if (input == match) {
return true;
} else {
return false;
}
}
};
#endif /* BINARYMATCHER_H_ */
#ifndef BINARYMATCHER_H_
#define BINARYMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h"
template<typename T>
class BinaryMatcher: public MatcherIF<T> {
public:
bool inverted;
T mask, matchField;
BinaryMatcher() :
inverted(false), mask(0), matchField(0) {
}
BinaryMatcher(T mask, T match, bool inverted = false) :
inverted(inverted), mask(mask), matchField(match) {
}
bool match(T input) {
if (inverted) {
return ~doMatch(input, mask, matchField);
} else {
return doMatch(input, mask, matchField);
}
}
protected:
bool doMatch(T input, T mask, T match) {
match = match & mask;
input = input & mask;
if (input == match) {
return true;
} else {
return false;
}
}
};
#endif /* BINARYMATCHER_H_ */

View File

@ -1,50 +1,50 @@
#ifndef DECIMALMATCHER_H_
#define DECIMALMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h"
template<typename T>
class DecimalMatcher: public MatcherIF<T> {
public:
bool inverted;
T mask, matchField;
DecimalMatcher() :
inverted(false), mask(0), matchField(0) {
}
DecimalMatcher(T mask, T match, bool inverted = false) :
inverted(inverted), mask(mask), matchField(match) {
}
bool match(T input) {
if (inverted) {
return ~doMatch(input, mask, matchField);
} else {
return doMatch(input, mask, matchField);
}
}
protected:
bool doMatch(T input, T mask, T match) {
T decimal = 1, remainderMask, remainderMatch, remainderInput;
while (mask != 0) {
remainderMask = mask % (decimal * 10);
remainderMatch = match % (decimal * 10);
remainderInput = input % (decimal * 10);
if (remainderMask != 0) {
if (remainderMatch != remainderInput) {
return false;
}
}
mask -= remainderMask;
match -= remainderMatch;
input -= remainderInput;
decimal *= 10;
}
return true;
}
};
#endif /* DECIMALMATCHER_H_ */
#ifndef DECIMALMATCHER_H_
#define DECIMALMATCHER_H_
#include "../../globalfunctions/matching/MatcherIF.h"
template<typename T>
class DecimalMatcher: public MatcherIF<T> {
public:
bool inverted;
T mask, matchField;
DecimalMatcher() :
inverted(false), mask(0), matchField(0) {
}
DecimalMatcher(T mask, T match, bool inverted = false) :
inverted(inverted), mask(mask), matchField(match) {
}
bool match(T input) {
if (inverted) {
return ~doMatch(input, mask, matchField);
} else {
return doMatch(input, mask, matchField);
}
}
protected:
bool doMatch(T input, T mask, T match) {
T decimal = 1, remainderMask, remainderMatch, remainderInput;
while (mask != 0) {
remainderMask = mask % (decimal * 10);
remainderMatch = match % (decimal * 10);
remainderInput = input % (decimal * 10);
if (remainderMask != 0) {
if (remainderMatch != remainderInput) {
return false;
}
}
mask -= remainderMask;
match -= remainderMatch;
input -= remainderInput;
decimal *= 10;
}
return true;
}
};
#endif /* DECIMALMATCHER_H_ */

View File

@ -1,216 +1,216 @@
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
#include "../../container/BinaryTree.h"
#include "../../globalfunctions/matching/SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h"
template<typename T>
class MatchTree: public SerializeableMatcherIF<T>, public BinaryTree<
SerializeableMatcherIF<T>> {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::MATCH_TREE_CLASS;
static const ReturnValue_t TOO_DETAILED_REQUEST = MAKE_RETURN_CODE(1);
static const ReturnValue_t TOO_GENERAL_REQUEST = MAKE_RETURN_CODE(2);
static const ReturnValue_t NO_MATCH = MAKE_RETURN_CODE(3);
static const ReturnValue_t FULL = MAKE_RETURN_CODE(4);
static const ReturnValue_t NEW_NODE_CREATED = MAKE_RETURN_CODE(5);
typedef typename BinaryTree<SerializeableMatcherIF<T>>::iterator iterator;
typedef BinaryNode<SerializeableMatcherIF<T>> Node;
static const bool AND = true; //LEFT
static const bool OR = false; //RIGHT
MatchTree(BinaryNode<SerializeableMatcherIF<T>>* root,
uint8_t maxDepth = -1) :
BinaryTree<SerializeableMatcherIF<T>>(root), maxDepth(maxDepth) {
}
MatchTree(iterator root, uint8_t maxDepth = -1) :
BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(
maxDepth) {
}
MatchTree() :
BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {
}
virtual ~MatchTree() {
}
virtual bool match(T number) {
return matchesTree(number);
}
bool matchesTree(T number) {
iterator iter = this->begin();
if (iter == this->end()) {
return false;
}
return matchSubtree(iter, number);
}
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, SerializeIF::Endianness streamEndianness) const override {
iterator iter = this->begin();
uint8_t count = this->countRight(iter);
ReturnValue_t result = SerializeAdapter::serialize(&count,
buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (iter == this->end()) {
return HasReturnvaluesIF::RETURN_OK;
}
result = iter->serialize(buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
result = temp.serialize(buffer, size, maxSize, streamEndianness);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
iter = iter.right();
while (iter != this->end()) {
result = iter->serialize(buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
result = temp.serialize(buffer, size, maxSize, streamEndianness);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
iter = iter.right();
}
return result;
}
size_t getSerializedSize() const override {
//Analogous to serialize!
uint32_t size = 1; //One for count
iterator iter = this->begin();
if (iter == this->end()) {
return size;
}
//Count object itself
size += iter->getSerializedSize();
//Handle everything below on AND side
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
size += temp.getSerializedSize();
}
//Handle everything on OR side
iter = iter.right();
//Iterate over every object on the OR branch
while (iter != this->end()) {
size += iter->getSerializedSize();
if (maxDepth > 0) {
//If we are allowed to go deeper, handle AND elements.
MatchTree<T> temp(iter.left(), maxDepth - 1);
size += temp.getSerializedSize();
}
iter = iter.right();
}
return size;
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override {
return HasReturnvaluesIF::RETURN_OK;
}
protected:
bool isOnAndBranch(iterator position) {
if ((position == this->end()) || (position.up() == this->end())) {
return false;
}
if (position.up().left() == position) {
return true;
} else {
return false;
}
}
//SHOULDDO: What to do if insertion/deletion fails. Throw event?
ReturnValue_t removeElementAndAllChildren(iterator position) {
auto children = this->erase(position);
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (children.first != this->end()) {
result = removeElementAndAllChildren(children.first);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (children.second != this->end()) {
result = removeElementAndAllChildren(children.second);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
//Delete element itself.
return cleanUpElement(position);
}
ReturnValue_t removeElementAndReconnectChildren(iterator position) {
if (position == this->end()) {
return HasReturnvaluesIF::RETURN_OK;
}
//Delete everything from the AND branch.
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (position.left() != this->end()) {
result = removeElementAndAllChildren(position.left());
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
if (position.right() != this->end()) {
//There's something at the OR branch, reconnect to parent.
if (isOnAndBranch(position)) {
//Either one hierarchy up AND branch...
this->insert(AND, position.up(), position.right().element);
} else {
//or on another OR'ed element (or install new root node).
this->insert(OR, position.up(), position.right().element);
}
} else {
if (isOnAndBranch(position)) {
//Recursively delete parent node as well, because it is not expected to be there anymore.
return removeElementAndReconnectChildren(position.up());
} else {
//simply delete self.
this->erase(position);
}
}
//Delete element itself.
return cleanUpElement(position);
}
virtual ReturnValue_t cleanUpElement(iterator position) {
return HasReturnvaluesIF::RETURN_OK;
}
bool matchSubtree(iterator iter, T number) {
bool isMatch = iter->match(number);
if (isMatch) {
if (iter.left() == this->end()) {
return true;
}
isMatch = matchSubtree(iter.left(), number);
if (isMatch) {
return true;
}
}
if (iter.right() == this->end()) {
return false;
}
return matchSubtree(iter.right(), number);
}
private:
uint8_t maxDepth;
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ */
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_
#include "../../container/BinaryTree.h"
#include "../../globalfunctions/matching/SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h"
template<typename T>
class MatchTree: public SerializeableMatcherIF<T>, public BinaryTree<
SerializeableMatcherIF<T>> {
public:
static const uint8_t INTERFACE_ID = CLASS_ID::MATCH_TREE_CLASS;
static const ReturnValue_t TOO_DETAILED_REQUEST = MAKE_RETURN_CODE(1);
static const ReturnValue_t TOO_GENERAL_REQUEST = MAKE_RETURN_CODE(2);
static const ReturnValue_t NO_MATCH = MAKE_RETURN_CODE(3);
static const ReturnValue_t FULL = MAKE_RETURN_CODE(4);
static const ReturnValue_t NEW_NODE_CREATED = MAKE_RETURN_CODE(5);
typedef typename BinaryTree<SerializeableMatcherIF<T>>::iterator iterator;
typedef BinaryNode<SerializeableMatcherIF<T>> Node;
static const bool AND = true; //LEFT
static const bool OR = false; //RIGHT
MatchTree(BinaryNode<SerializeableMatcherIF<T>>* root,
uint8_t maxDepth = -1) :
BinaryTree<SerializeableMatcherIF<T>>(root), maxDepth(maxDepth) {
}
MatchTree(iterator root, uint8_t maxDepth = -1) :
BinaryTree<SerializeableMatcherIF<T>>(root.element), maxDepth(
maxDepth) {
}
MatchTree() :
BinaryTree<SerializeableMatcherIF<T>>(), maxDepth(-1) {
}
virtual ~MatchTree() {
}
virtual bool match(T number) {
return matchesTree(number);
}
bool matchesTree(T number) {
iterator iter = this->begin();
if (iter == this->end()) {
return false;
}
return matchSubtree(iter, number);
}
ReturnValue_t serialize(uint8_t** buffer, size_t* size,
size_t maxSize, SerializeIF::Endianness streamEndianness) const override {
iterator iter = this->begin();
uint8_t count = this->countRight(iter);
ReturnValue_t result = SerializeAdapter::serialize(&count,
buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (iter == this->end()) {
return HasReturnvaluesIF::RETURN_OK;
}
result = iter->serialize(buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
result = temp.serialize(buffer, size, maxSize, streamEndianness);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
iter = iter.right();
while (iter != this->end()) {
result = iter->serialize(buffer, size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
result = temp.serialize(buffer, size, maxSize, streamEndianness);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
iter = iter.right();
}
return result;
}
size_t getSerializedSize() const override {
//Analogous to serialize!
uint32_t size = 1; //One for count
iterator iter = this->begin();
if (iter == this->end()) {
return size;
}
//Count object itself
size += iter->getSerializedSize();
//Handle everything below on AND side
if (maxDepth > 0) {
MatchTree<T> temp(iter.left(), maxDepth - 1);
size += temp.getSerializedSize();
}
//Handle everything on OR side
iter = iter.right();
//Iterate over every object on the OR branch
while (iter != this->end()) {
size += iter->getSerializedSize();
if (maxDepth > 0) {
//If we are allowed to go deeper, handle AND elements.
MatchTree<T> temp(iter.left(), maxDepth - 1);
size += temp.getSerializedSize();
}
iter = iter.right();
}
return size;
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override {
return HasReturnvaluesIF::RETURN_OK;
}
protected:
bool isOnAndBranch(iterator position) {
if ((position == this->end()) || (position.up() == this->end())) {
return false;
}
if (position.up().left() == position) {
return true;
} else {
return false;
}
}
//SHOULDDO: What to do if insertion/deletion fails. Throw event?
ReturnValue_t removeElementAndAllChildren(iterator position) {
auto children = this->erase(position);
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (children.first != this->end()) {
result = removeElementAndAllChildren(children.first);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
if (children.second != this->end()) {
result = removeElementAndAllChildren(children.second);
}
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
//Delete element itself.
return cleanUpElement(position);
}
ReturnValue_t removeElementAndReconnectChildren(iterator position) {
if (position == this->end()) {
return HasReturnvaluesIF::RETURN_OK;
}
//Delete everything from the AND branch.
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
if (position.left() != this->end()) {
result = removeElementAndAllChildren(position.left());
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
}
if (position.right() != this->end()) {
//There's something at the OR branch, reconnect to parent.
if (isOnAndBranch(position)) {
//Either one hierarchy up AND branch...
this->insert(AND, position.up(), position.right().element);
} else {
//or on another OR'ed element (or install new root node).
this->insert(OR, position.up(), position.right().element);
}
} else {
if (isOnAndBranch(position)) {
//Recursively delete parent node as well, because it is not expected to be there anymore.
return removeElementAndReconnectChildren(position.up());
} else {
//simply delete self.
this->erase(position);
}
}
//Delete element itself.
return cleanUpElement(position);
}
virtual ReturnValue_t cleanUpElement(iterator position) {
return HasReturnvaluesIF::RETURN_OK;
}
bool matchSubtree(iterator iter, T number) {
bool isMatch = iter->match(number);
if (isMatch) {
if (iter.left() == this->end()) {
return true;
}
isMatch = matchSubtree(iter.left(), number);
if (isMatch) {
return true;
}
}
if (iter.right() == this->end()) {
return false;
}
return matchSubtree(iter.right(), number);
}
private:
uint8_t maxDepth;
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_MATCHING_MATCHTREE_H_ */

View File

@ -1,70 +1,70 @@
#ifndef RANGEMATCHER_H_
#define RANGEMATCHER_H_
#include "../../globalfunctions/matching/SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h"
template<typename T>
class RangeMatcher: public SerializeableMatcherIF<T> {
public:
bool inverted;
T lowerBound;
T upperBound;
RangeMatcher() :
inverted(true), lowerBound(1), upperBound(0) {
}
RangeMatcher(T lowerBound, T upperBound, bool inverted = false) :
inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {
}
bool match(T input) {
if (inverted) {
return !doMatch(input);
} else {
return doMatch(input);
}
}
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override {
ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer,
size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&upperBound, buffer, size,
maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerializeAdapter::serialize(&inverted, buffer, size, maxSize,
streamEndianness);
}
size_t getSerializedSize() const override {
return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool);
}
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) override {
ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound,
buffer, size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&upperBound, buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerializeAdapter::deSerialize(&inverted, buffer, size,
streamEndianness);
}
protected:
bool doMatch(T input) {
return (input >= lowerBound) && (input <= upperBound);
}
};
#endif /* RANGEMATCHER_H_ */
#ifndef RANGEMATCHER_H_
#define RANGEMATCHER_H_
#include "../../globalfunctions/matching/SerializeableMatcherIF.h"
#include "../../serialize/SerializeAdapter.h"
template<typename T>
class RangeMatcher: public SerializeableMatcherIF<T> {
public:
bool inverted;
T lowerBound;
T upperBound;
RangeMatcher() :
inverted(true), lowerBound(1), upperBound(0) {
}
RangeMatcher(T lowerBound, T upperBound, bool inverted = false) :
inverted(inverted), lowerBound(lowerBound), upperBound(upperBound) {
}
bool match(T input) {
if (inverted) {
return !doMatch(input);
} else {
return doMatch(input);
}
}
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override {
ReturnValue_t result = SerializeAdapter::serialize(&lowerBound, buffer,
size, maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::serialize(&upperBound, buffer, size,
maxSize, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerializeAdapter::serialize(&inverted, buffer, size, maxSize,
streamEndianness);
}
size_t getSerializedSize() const override {
return sizeof(lowerBound) + sizeof(upperBound) + sizeof(bool);
}
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) override {
ReturnValue_t result = SerializeAdapter::deSerialize(&lowerBound,
buffer, size, streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
result = SerializeAdapter::deSerialize(&upperBound, buffer, size,
streamEndianness);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return SerializeAdapter::deSerialize(&inverted, buffer, size,
streamEndianness);
}
protected:
bool doMatch(T input) {
return (input >= lowerBound) && (input <= upperBound);
}
};
#endif /* RANGEMATCHER_H_ */

View File

@ -1,13 +1,13 @@
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#include "../../globalfunctions/matching/MatcherIF.h"
#include "../../serialize/SerializeIF.h"
template<typename T>
class SerializeableMatcherIF : public MatcherIF<T>, public SerializeIF {
public:
virtual ~SerializeableMatcherIF() {}
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ */
#ifndef FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#define FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_
#include "../../globalfunctions/matching/MatcherIF.h"
#include "../../serialize/SerializeIF.h"
template<typename T>
class SerializeableMatcherIF : public MatcherIF<T>, public SerializeIF {
public:
virtual ~SerializeableMatcherIF() {}
};
#endif /* FRAMEWORK_GLOBALFUNCTIONS_MATCHING_SERIALIZEABLEMATCHERIF_H_ */

View File

@ -1,156 +1,156 @@
#include "QuaternionOperations.h"
#include "../../globalfunctions/math/VectorOperations.h"
#include <cmath>
#include <cstring>
#include <stdint.h>
QuaternionOperations::~QuaternionOperations() {
}
void QuaternionOperations::multiply(const double* q1, const double* q2,
double* q) {
double out[4];
out[0] = q1[3] * q2[0] + q1[2] * q2[1] - q1[1] * q2[2] + q1[0] * q2[3];
out[1] = -q1[2] * q2[0] + q1[3] * q2[1] + q1[0] * q2[2] + q1[1] * q2[3];
out[2] = q1[1] * q2[0] - q1[0] * q2[1] + q1[3] * q2[2] + q1[2] * q2[3];
out[3] = -q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] + q1[3] * q2[3];
memcpy(q, out, 4 * sizeof(*q));
}
void QuaternionOperations::toDcm(const double* quaternion, double dcm[][3]) {
dcm[0][0] = 2
* (quaternion[0] * quaternion[0] + quaternion[3] * quaternion[3])
- 1;
dcm[0][1] = 2
* (quaternion[0] * quaternion[1] + quaternion[2] * quaternion[3]);
dcm[0][2] = 2
* (quaternion[0] * quaternion[2] - quaternion[1] * quaternion[3]);
dcm[1][0] = 2
* (quaternion[0] * quaternion[1] - quaternion[2] * quaternion[3]);
dcm[1][1] = 2
* (quaternion[1] * quaternion[1] + quaternion[3] * quaternion[3])
- 1;
dcm[1][2] = 2
* (quaternion[1] * quaternion[2] + quaternion[0] * quaternion[3]);
dcm[2][0] = 2
* (quaternion[0] * quaternion[2] + quaternion[1] * quaternion[3]);
dcm[2][1] = 2
* (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]);
dcm[2][2] = 2
* (quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3])
- 1;
}
void QuaternionOperations::inverse(const double* quaternion,
double* inverseQuaternion) {
memcpy(inverseQuaternion, quaternion, 4 * sizeof(*quaternion));
VectorOperations<double>::mulScalar(inverseQuaternion, -1,
inverseQuaternion, 3);
}
QuaternionOperations::QuaternionOperations() {
}
void QuaternionOperations::normalize(const double* quaternion,
double* unitQuaternion) {
VectorOperations<double>::normalize(quaternion, unitQuaternion, 4);
}
float QuaternionOperations::norm(const double* quaternion) {
return VectorOperations<double>::norm(quaternion, 4);
}
void QuaternionOperations::fromDcm(const double dcm[][3], double* quaternion,
uint8_t *index) {
double a[4];
a[0] = 1 + dcm[0][0] - dcm[1][1] - dcm[2][2];
a[1] = 1 - dcm[0][0] + dcm[1][1] - dcm[2][2];
a[2] = 1 - dcm[0][0] - dcm[1][1] + dcm[2][2];
a[3] = 1 + dcm[0][0] + dcm[1][1] + dcm[2][2];
uint8_t maxAIndex = 0;
VectorOperations<double>::maxValue(a, 4, &maxAIndex);
if (index != 0) {
*index = maxAIndex;
}
switch (maxAIndex) {
case 0:
quaternion[0] = 0.5 * sqrt(a[0]);
quaternion[1] = (dcm[0][1] + dcm[1][0]) / (2 * sqrt(a[0]));
quaternion[2] = (dcm[0][2] + dcm[2][0]) / (2 * sqrt(a[0]));
quaternion[3] = (dcm[1][2] - dcm[2][1]) / (2 * sqrt(a[0]));
break;
case 1:
quaternion[0] = (dcm[0][1] + dcm[1][0]) / (2 * sqrt(a[1]));
quaternion[1] = 0.5 * sqrt(a[1]);
quaternion[2] = (dcm[1][2] + dcm[2][1]) / (2 * sqrt(a[1]));
quaternion[3] = (dcm[2][0] - dcm[0][2]) / (2 * sqrt(a[1]));
break;
case 2:
quaternion[0] = (dcm[0][2] + dcm[2][0]) / (2 * sqrt(a[2]));
quaternion[1] = (dcm[1][2] + dcm[2][1]) / (2 * sqrt(a[2]));
quaternion[2] = 0.5 * sqrt(a[2]);
quaternion[3] = (dcm[0][1] - dcm[1][0]) / (2 * sqrt(a[2]));
break;
case 3:
quaternion[0] = (dcm[1][2] - dcm[2][1]) / (2 * sqrt(a[3]));
quaternion[1] = (dcm[2][0] - dcm[0][2]) / (2 * sqrt(a[3]));
quaternion[2] = (dcm[0][1] - dcm[1][0]) / (2 * sqrt(a[3]));
quaternion[3] = 0.5 * sqrt(a[3]);
break;
}
}
void QuaternionOperations::toDcm(const double* quaternion, float dcm[][3]) {
dcm[0][0] = 2
* (quaternion[0] * quaternion[0] + quaternion[3] * quaternion[3])
- 1;
dcm[0][1] = 2
* (quaternion[0] * quaternion[1] + quaternion[2] * quaternion[3]);
dcm[0][2] = 2
* (quaternion[0] * quaternion[2] - quaternion[1] * quaternion[3]);
dcm[1][0] = 2
* (quaternion[0] * quaternion[1] - quaternion[2] * quaternion[3]);
dcm[1][1] = 2
* (quaternion[1] * quaternion[1] + quaternion[3] * quaternion[3])
- 1;
dcm[1][2] = 2
* (quaternion[1] * quaternion[2] + quaternion[0] * quaternion[3]);
dcm[2][0] = 2
* (quaternion[0] * quaternion[2] + quaternion[1] * quaternion[3]);
dcm[2][1] = 2
* (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]);
dcm[2][2] = 2
* (quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3])
- 1;
}
void QuaternionOperations::normalize(double* quaternion) {
normalize(quaternion, quaternion);
}
double QuaternionOperations::getAngle(const double* quaternion, bool abs) {
if (quaternion[3] >= 0) {
return 2 * acos(quaternion[3]);
} else {
if (abs) {
return 2 * acos(-quaternion[3]);
} else {
return -2 * acos(-quaternion[3]);
}
}
}
#include "QuaternionOperations.h"
#include "../../globalfunctions/math/VectorOperations.h"
#include <cmath>
#include <cstring>
#include <stdint.h>
QuaternionOperations::~QuaternionOperations() {
}
void QuaternionOperations::multiply(const double* q1, const double* q2,
double* q) {
double out[4];
out[0] = q1[3] * q2[0] + q1[2] * q2[1] - q1[1] * q2[2] + q1[0] * q2[3];
out[1] = -q1[2] * q2[0] + q1[3] * q2[1] + q1[0] * q2[2] + q1[1] * q2[3];
out[2] = q1[1] * q2[0] - q1[0] * q2[1] + q1[3] * q2[2] + q1[2] * q2[3];
out[3] = -q1[0] * q2[0] - q1[1] * q2[1] - q1[2] * q2[2] + q1[3] * q2[3];
memcpy(q, out, 4 * sizeof(*q));
}
void QuaternionOperations::toDcm(const double* quaternion, double dcm[][3]) {
dcm[0][0] = 2
* (quaternion[0] * quaternion[0] + quaternion[3] * quaternion[3])
- 1;
dcm[0][1] = 2
* (quaternion[0] * quaternion[1] + quaternion[2] * quaternion[3]);
dcm[0][2] = 2
* (quaternion[0] * quaternion[2] - quaternion[1] * quaternion[3]);
dcm[1][0] = 2
* (quaternion[0] * quaternion[1] - quaternion[2] * quaternion[3]);
dcm[1][1] = 2
* (quaternion[1] * quaternion[1] + quaternion[3] * quaternion[3])
- 1;
dcm[1][2] = 2
* (quaternion[1] * quaternion[2] + quaternion[0] * quaternion[3]);
dcm[2][0] = 2
* (quaternion[0] * quaternion[2] + quaternion[1] * quaternion[3]);
dcm[2][1] = 2
* (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]);
dcm[2][2] = 2
* (quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3])
- 1;
}
void QuaternionOperations::inverse(const double* quaternion,
double* inverseQuaternion) {
memcpy(inverseQuaternion, quaternion, 4 * sizeof(*quaternion));
VectorOperations<double>::mulScalar(inverseQuaternion, -1,
inverseQuaternion, 3);
}
QuaternionOperations::QuaternionOperations() {
}
void QuaternionOperations::normalize(const double* quaternion,
double* unitQuaternion) {
VectorOperations<double>::normalize(quaternion, unitQuaternion, 4);
}
float QuaternionOperations::norm(const double* quaternion) {
return VectorOperations<double>::norm(quaternion, 4);
}
void QuaternionOperations::fromDcm(const double dcm[][3], double* quaternion,
uint8_t *index) {
double a[4];
a[0] = 1 + dcm[0][0] - dcm[1][1] - dcm[2][2];
a[1] = 1 - dcm[0][0] + dcm[1][1] - dcm[2][2];
a[2] = 1 - dcm[0][0] - dcm[1][1] + dcm[2][2];
a[3] = 1 + dcm[0][0] + dcm[1][1] + dcm[2][2];
uint8_t maxAIndex = 0;
VectorOperations<double>::maxValue(a, 4, &maxAIndex);
if (index != 0) {
*index = maxAIndex;
}
switch (maxAIndex) {
case 0:
quaternion[0] = 0.5 * sqrt(a[0]);
quaternion[1] = (dcm[0][1] + dcm[1][0]) / (2 * sqrt(a[0]));
quaternion[2] = (dcm[0][2] + dcm[2][0]) / (2 * sqrt(a[0]));
quaternion[3] = (dcm[1][2] - dcm[2][1]) / (2 * sqrt(a[0]));
break;
case 1:
quaternion[0] = (dcm[0][1] + dcm[1][0]) / (2 * sqrt(a[1]));
quaternion[1] = 0.5 * sqrt(a[1]);
quaternion[2] = (dcm[1][2] + dcm[2][1]) / (2 * sqrt(a[1]));
quaternion[3] = (dcm[2][0] - dcm[0][2]) / (2 * sqrt(a[1]));
break;
case 2:
quaternion[0] = (dcm[0][2] + dcm[2][0]) / (2 * sqrt(a[2]));
quaternion[1] = (dcm[1][2] + dcm[2][1]) / (2 * sqrt(a[2]));
quaternion[2] = 0.5 * sqrt(a[2]);
quaternion[3] = (dcm[0][1] - dcm[1][0]) / (2 * sqrt(a[2]));
break;
case 3:
quaternion[0] = (dcm[1][2] - dcm[2][1]) / (2 * sqrt(a[3]));
quaternion[1] = (dcm[2][0] - dcm[0][2]) / (2 * sqrt(a[3]));
quaternion[2] = (dcm[0][1] - dcm[1][0]) / (2 * sqrt(a[3]));
quaternion[3] = 0.5 * sqrt(a[3]);
break;
}
}
void QuaternionOperations::toDcm(const double* quaternion, float dcm[][3]) {
dcm[0][0] = 2
* (quaternion[0] * quaternion[0] + quaternion[3] * quaternion[3])
- 1;
dcm[0][1] = 2
* (quaternion[0] * quaternion[1] + quaternion[2] * quaternion[3]);
dcm[0][2] = 2
* (quaternion[0] * quaternion[2] - quaternion[1] * quaternion[3]);
dcm[1][0] = 2
* (quaternion[0] * quaternion[1] - quaternion[2] * quaternion[3]);
dcm[1][1] = 2
* (quaternion[1] * quaternion[1] + quaternion[3] * quaternion[3])
- 1;
dcm[1][2] = 2
* (quaternion[1] * quaternion[2] + quaternion[0] * quaternion[3]);
dcm[2][0] = 2
* (quaternion[0] * quaternion[2] + quaternion[1] * quaternion[3]);
dcm[2][1] = 2
* (quaternion[1] * quaternion[2] - quaternion[0] * quaternion[3]);
dcm[2][2] = 2
* (quaternion[2] * quaternion[2] + quaternion[3] * quaternion[3])
- 1;
}
void QuaternionOperations::normalize(double* quaternion) {
normalize(quaternion, quaternion);
}
double QuaternionOperations::getAngle(const double* quaternion, bool abs) {
if (quaternion[3] >= 0) {
return 2 * acos(quaternion[3]);
} else {
if (abs) {
return 2 * acos(-quaternion[3]);
} else {
return -2 * acos(-quaternion[3]);
}
}
}

View File

@ -1,99 +1,99 @@
#include "timevalOperations.h"
timeval& operator+=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator+(timeval lhs, const timeval& rhs) {
lhs += rhs;
return lhs;
}
timeval& operator-=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum -= rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator-(timeval lhs, const timeval& rhs) {
lhs -= rhs;
return lhs;
}
double operator/(const timeval& lhs, const timeval& rhs) {
double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 / rhs64;
}
timeval& operator/=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product /= scalar;
lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator/(timeval lhs, double scalar) {
lhs /= scalar;
return lhs;
}
timeval& operator*=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product *= scalar;
lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator*(timeval lhs, double scalar) {
lhs *= scalar;
return lhs;
}
timeval operator*(double scalar, timeval rhs) {
rhs *= scalar;
return rhs;
}
bool operator==(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 == rhs64;
}
bool operator!=(const timeval& lhs, const timeval& rhs) {
return !operator==(lhs, rhs);
}
bool operator<(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 < rhs64;
}
bool operator>(const timeval& lhs, const timeval& rhs) {
return operator<(rhs, lhs);
}
bool operator<=(const timeval& lhs, const timeval& rhs) {
return !operator>(lhs, rhs);
}
bool operator>=(const timeval& lhs, const timeval& rhs) {
return !operator<(lhs, rhs);
}
double timevalOperations::toDouble(const timeval timeval) {
double result = timeval.tv_sec * 1000000. + timeval.tv_usec;
return result / 1000000.;
}
timeval timevalOperations::toTimeval(const double seconds) {
timeval tval;
tval.tv_sec = seconds;
tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6);
return tval;
}
#include "timevalOperations.h"
timeval& operator+=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum += rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator+(timeval lhs, const timeval& rhs) {
lhs += rhs;
return lhs;
}
timeval& operator-=(timeval& lhs, const timeval& rhs) {
int64_t sum = lhs.tv_sec * 1000000. + lhs.tv_usec;
sum -= rhs.tv_sec * 1000000. + rhs.tv_usec;
lhs.tv_sec = sum / 1000000;
lhs.tv_usec = sum - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator-(timeval lhs, const timeval& rhs) {
lhs -= rhs;
return lhs;
}
double operator/(const timeval& lhs, const timeval& rhs) {
double lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
double rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 / rhs64;
}
timeval& operator/=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product /= scalar;
lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator/(timeval lhs, double scalar) {
lhs /= scalar;
return lhs;
}
timeval& operator*=(timeval& lhs, double scalar) {
int64_t product = lhs.tv_sec * 1000000. + lhs.tv_usec;
product *= scalar;
lhs.tv_sec = product / 1000000;
lhs.tv_usec = product - lhs.tv_sec * 1000000;
return lhs;
}
timeval operator*(timeval lhs, double scalar) {
lhs *= scalar;
return lhs;
}
timeval operator*(double scalar, timeval rhs) {
rhs *= scalar;
return rhs;
}
bool operator==(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 == rhs64;
}
bool operator!=(const timeval& lhs, const timeval& rhs) {
return !operator==(lhs, rhs);
}
bool operator<(const timeval& lhs, const timeval& rhs) {
int64_t lhs64 = lhs.tv_sec * 1000000. + lhs.tv_usec;
int64_t rhs64 = rhs.tv_sec * 1000000. + rhs.tv_usec;
return lhs64 < rhs64;
}
bool operator>(const timeval& lhs, const timeval& rhs) {
return operator<(rhs, lhs);
}
bool operator<=(const timeval& lhs, const timeval& rhs) {
return !operator>(lhs, rhs);
}
bool operator>=(const timeval& lhs, const timeval& rhs) {
return !operator<(lhs, rhs);
}
double timevalOperations::toDouble(const timeval timeval) {
double result = timeval.tv_sec * 1000000. + timeval.tv_usec;
return result / 1000000.;
}
timeval timevalOperations::toTimeval(const double seconds) {
timeval tval;
tval.tv_sec = seconds;
tval.tv_usec = seconds *(double) 1e6 - (tval.tv_sec *1e6);
return tval;
}

View File

@ -1,50 +1,50 @@
#ifndef HASHEALTHIF_H_
#define HASHEALTHIF_H_
#include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
class HasHealthIF {
public:
typedef enum {
HEALTHY = 1, FAULTY = 0, EXTERNAL_CONTROL = 2, NEEDS_RECOVERY = 3, PERMANENT_FAULTY = 4
} HealthState;
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
static const Event HEALTH_INFO = MAKE_EVENT(6, SEVERITY::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, SEVERITY::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, SEVERITY::LOW);
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, SEVERITY::LOW); //!< Assembly overwrites health information of children to keep satellite alive.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, SEVERITY::MEDIUM); //!< Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event RECOVERY_STEP = MAKE_EVENT(11, SEVERITY::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_DONE = MAKE_EVENT(12, SEVERITY::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {
}
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* 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
*/
virtual HasHealthIF::HealthState getHealth() = 0;
};
#endif /* HASHEALTHIF_H_ */
#ifndef HASHEALTHIF_H_
#define HASHEALTHIF_H_
#include "../events/Event.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#include "../ipc/MessageQueueSenderIF.h"
class HasHealthIF {
public:
typedef enum {
HEALTHY = 1, FAULTY = 0, EXTERNAL_CONTROL = 2, NEEDS_RECOVERY = 3, PERMANENT_FAULTY = 4
} HealthState;
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static const ReturnValue_t OBJECT_NOT_HEALTHY = MAKE_RETURN_CODE(1);
static const ReturnValue_t INVALID_HEALTH_STATE = MAKE_RETURN_CODE(2);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER_1;
static const Event HEALTH_INFO = MAKE_EVENT(6, SEVERITY::INFO);
static const Event CHILD_CHANGED_HEALTH = MAKE_EVENT(7, SEVERITY::INFO);
static const Event CHILD_PROBLEMS = MAKE_EVENT(8, SEVERITY::LOW);
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, SEVERITY::LOW); //!< Assembly overwrites health information of children to keep satellite alive.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, SEVERITY::MEDIUM); //!< Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event RECOVERY_STEP = MAKE_EVENT(11, SEVERITY::MEDIUM); //!< Recovery is ongoing. Comes twice during recovery. P1: 0 for the first, 1 for the second event. P2: 0
static const Event RECOVERY_DONE = MAKE_EVENT(12, SEVERITY::MEDIUM); //!< Recovery was completed. Not necessarily successful. No parameters.
virtual ~HasHealthIF() {
}
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* 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
*/
virtual HasHealthIF::HealthState getHealth() = 0;
};
#endif /* HASHEALTHIF_H_ */

View File

@ -1,105 +1,105 @@
#include "../health/HealthHelper.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) :
objectId(objectId), owner(owner) {
}
HealthHelper::~HealthHelper() {
}
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
switch (message->getCommand()) {
case HealthMessage::HEALTH_SET:
handleSetHealthCommand(message);
return HasReturnvaluesIF::RETURN_OK;
case HealthMessage::HEALTH_ANNOUNCE: {
eventSender->forwardEvent(HasHealthIF::HEALTH_INFO, getHealth(),
getHealth());
}
return HasReturnvaluesIF::RETURN_OK;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
HasHealthIF::HealthState HealthHelper::getHealth() {
return healthTable->getHealth(objectId);
}
ReturnValue_t HealthHelper::initialize(MessageQueueId_t parentQueue) {
setParentQueue(parentQueue);
return initialize();
}
void HealthHelper::setParentQueue(MessageQueueId_t parentQueue) {
this->parentQueue = parentQueue;
}
ReturnValue_t HealthHelper::initialize() {
healthTable = objectManager->get<HealthTableIF>(objects::HEALTH_TABLE);
eventSender = objectManager->get<EventReportingProxyIF>(objectId);
if (healthTable == nullptr) {
sif::error << "HealthHelper::initialize: Health table object needs"
"to be created in factory." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if(eventSender == nullptr) {
sif::error << "HealthHelper::initialize: Owner has to implement "
"ReportingProxyIF." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ReturnValue_t result = healthTable->registerObject(objectId,
HasHealthIF::HEALTHY);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
void HealthHelper::setHealth(HasHealthIF::HealthState health) {
HasHealthIF::HealthState oldHealth = getHealth();
eventSender->forwardEvent(HasHealthIF::HEALTH_INFO, health, oldHealth);
if (health != oldHealth) {
healthTable->setHealth(objectId, health);
informParent(health, oldHealth);
}
}
void HealthHelper::informParent(HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth) {
if (parentQueue == MessageQueueMessageIF::NO_QUEUE) {
return;
}
CommandMessage information;
HealthMessage::setHealthMessage(&information, HealthMessage::HEALTH_INFO,
health, oldHealth);
if (MessageQueueSenderIF::sendMessage(parentQueue, &information,
owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "HealthHelper::informParent: sending health reply failed."
<< std::endl;
}
}
void HealthHelper::handleSetHealthCommand(CommandMessage* command) {
ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command));
if (command->getSender() == MessageQueueMessageIF::NO_QUEUE) {
return;
}
CommandMessage reply;
if (result == HasReturnvaluesIF::RETURN_OK) {
HealthMessage::setHealthMessage(&reply,
HealthMessage::REPLY_HEALTH_SET);
} else {
reply.setReplyRejected(result, command->getCommand());
}
if (MessageQueueSenderIF::sendMessage(command->getSender(), &reply,
owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "HealthHelper::handleHealthCommand: sending health "
"reply failed." << std::endl;
}
}
#include "../health/HealthHelper.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
HealthHelper::HealthHelper(HasHealthIF* owner, object_id_t objectId) :
objectId(objectId), owner(owner) {
}
HealthHelper::~HealthHelper() {
}
ReturnValue_t HealthHelper::handleHealthCommand(CommandMessage* message) {
switch (message->getCommand()) {
case HealthMessage::HEALTH_SET:
handleSetHealthCommand(message);
return HasReturnvaluesIF::RETURN_OK;
case HealthMessage::HEALTH_ANNOUNCE: {
eventSender->forwardEvent(HasHealthIF::HEALTH_INFO, getHealth(),
getHealth());
}
return HasReturnvaluesIF::RETURN_OK;
default:
return HasReturnvaluesIF::RETURN_FAILED;
}
}
HasHealthIF::HealthState HealthHelper::getHealth() {
return healthTable->getHealth(objectId);
}
ReturnValue_t HealthHelper::initialize(MessageQueueId_t parentQueue) {
setParentQueue(parentQueue);
return initialize();
}
void HealthHelper::setParentQueue(MessageQueueId_t parentQueue) {
this->parentQueue = parentQueue;
}
ReturnValue_t HealthHelper::initialize() {
healthTable = objectManager->get<HealthTableIF>(objects::HEALTH_TABLE);
eventSender = objectManager->get<EventReportingProxyIF>(objectId);
if (healthTable == nullptr) {
sif::error << "HealthHelper::initialize: Health table object needs"
"to be created in factory." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
if(eventSender == nullptr) {
sif::error << "HealthHelper::initialize: Owner has to implement "
"ReportingProxyIF." << std::endl;
return ObjectManagerIF::CHILD_INIT_FAILED;
}
ReturnValue_t result = healthTable->registerObject(objectId,
HasHealthIF::HEALTHY);
if (result != HasReturnvaluesIF::RETURN_OK) {
return result;
}
return HasReturnvaluesIF::RETURN_OK;
}
void HealthHelper::setHealth(HasHealthIF::HealthState health) {
HasHealthIF::HealthState oldHealth = getHealth();
eventSender->forwardEvent(HasHealthIF::HEALTH_INFO, health, oldHealth);
if (health != oldHealth) {
healthTable->setHealth(objectId, health);
informParent(health, oldHealth);
}
}
void HealthHelper::informParent(HasHealthIF::HealthState health,
HasHealthIF::HealthState oldHealth) {
if (parentQueue == MessageQueueMessageIF::NO_QUEUE) {
return;
}
CommandMessage information;
HealthMessage::setHealthMessage(&information, HealthMessage::HEALTH_INFO,
health, oldHealth);
if (MessageQueueSenderIF::sendMessage(parentQueue, &information,
owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "HealthHelper::informParent: sending health reply failed."
<< std::endl;
}
}
void HealthHelper::handleSetHealthCommand(CommandMessage* command) {
ReturnValue_t result = owner->setHealth(HealthMessage::getHealth(command));
if (command->getSender() == MessageQueueMessageIF::NO_QUEUE) {
return;
}
CommandMessage reply;
if (result == HasReturnvaluesIF::RETURN_OK) {
HealthMessage::setHealthMessage(&reply,
HealthMessage::REPLY_HEALTH_SET);
} else {
reply.setReplyRejected(result, command->getCommand());
}
if (MessageQueueSenderIF::sendMessage(command->getSender(), &reply,
owner->getCommandQueue()) != HasReturnvaluesIF::RETURN_OK) {
sif::debug << "HealthHelper::handleHealthCommand: sending health "
"reply failed." << std::endl;
}
}

View File

@ -1,121 +1,121 @@
#ifndef FRAMEWORK_HEALTH_HEALTHHELPER_H_
#define FRAMEWORK_HEALTH_HEALTHHELPER_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
*
* 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
* changes, not for all @c HEALTH_SET commands received.
*
* It does NOT handle @c HEALTH_INFO messages
*/
class HealthHelper {
public:
/**
* ctor
*
* @param owner
* @param objectId the object Id to use when communication with the HealthTable
*/
HealthHelper(HasHealthIF* owner, object_id_t objectId);
virtual ~HealthHelper();
/**
* Pointer to the Health Table
*
* only valid after initialize() has been called
*/
HealthTableIF *healthTable = nullptr;
/**
* Proxy to forward events.
*/
EventReportingProxyIF* eventSender = nullptr;
/**
* Try to handle the message.
*
* This function handles @c HEALTH_SET and @c HEALTH_READ commands.
* it updates the Health Table and generates a reply to the sender.
*
* @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)
*/
ReturnValue_t handleHealthCommand(CommandMessage *message);
/**
* set the Health State
*
* The parent will be informed, if the Health changes
*
* @param health
*/
void setHealth(HasHealthIF::HealthState health);
/**
* get Health State
*
* @return Health State of the object
*/
HasHealthIF::HealthState getHealth();
/**
* @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
* @return
* -@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 );
ReturnValue_t initialize();
private:
/**
* the object id to use when communicating with the Health Table
*/
object_id_t objectId;
/**
* The Queue of the parent
*/
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
/**
* The one using the healthHelper.
*/
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
* @param oldHealth information of the previous health state.
*/
void informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth);
void handleSetHealthCommand(CommandMessage *message);
};
#endif /* HEALTHHELPER_H_ */
#ifndef FRAMEWORK_HEALTH_HEALTHHELPER_H_
#define FRAMEWORK_HEALTH_HEALTHHELPER_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
*
* 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
* changes, not for all @c HEALTH_SET commands received.
*
* It does NOT handle @c HEALTH_INFO messages
*/
class HealthHelper {
public:
/**
* ctor
*
* @param owner
* @param objectId the object Id to use when communication with the HealthTable
*/
HealthHelper(HasHealthIF* owner, object_id_t objectId);
virtual ~HealthHelper();
/**
* Pointer to the Health Table
*
* only valid after initialize() has been called
*/
HealthTableIF *healthTable = nullptr;
/**
* Proxy to forward events.
*/
EventReportingProxyIF* eventSender = nullptr;
/**
* Try to handle the message.
*
* This function handles @c HEALTH_SET and @c HEALTH_READ commands.
* it updates the Health Table and generates a reply to the sender.
*
* @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)
*/
ReturnValue_t handleHealthCommand(CommandMessage *message);
/**
* set the Health State
*
* The parent will be informed, if the Health changes
*
* @param health
*/
void setHealth(HasHealthIF::HealthState health);
/**
* get Health State
*
* @return Health State of the object
*/
HasHealthIF::HealthState getHealth();
/**
* @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
* @return
* -@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 );
ReturnValue_t initialize();
private:
/**
* the object id to use when communicating with the Health Table
*/
object_id_t objectId;
/**
* The Queue of the parent
*/
MessageQueueId_t parentQueue = MessageQueueIF::NO_QUEUE;
/**
* The one using the healthHelper.
*/
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
* @param oldHealth information of the previous health state.
*/
void informParent(HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth);
void handleSetHealthCommand(CommandMessage *message);
};
#endif /* HEALTHHELPER_H_ */

View File

@ -1,28 +1,28 @@
#include "../health/HealthMessage.h"
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) {
message->setCommand(command);
message->setParameter(health);
message->setParameter2(oldHealth);
}
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command) {
message->setCommand(command);
}
HasHealthIF::HealthState HealthMessage::getHealth(const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter();
}
void HealthMessage::clear(CommandMessage* message) {
message->setCommand(CommandMessage::CMD_NONE);
}
HealthMessage::HealthMessage() {
}
HasHealthIF::HealthState HealthMessage::getOldHealth(
const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter2();
}
#include "../health/HealthMessage.h"
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command,
HasHealthIF::HealthState health, HasHealthIF::HealthState oldHealth) {
message->setCommand(command);
message->setParameter(health);
message->setParameter2(oldHealth);
}
void HealthMessage::setHealthMessage(CommandMessage* message, Command_t command) {
message->setCommand(command);
}
HasHealthIF::HealthState HealthMessage::getHealth(const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter();
}
void HealthMessage::clear(CommandMessage* message) {
message->setCommand(CommandMessage::CMD_NONE);
}
HealthMessage::HealthMessage() {
}
HasHealthIF::HealthState HealthMessage::getOldHealth(
const CommandMessage* message) {
return (HasHealthIF::HealthState) message->getParameter2();
}

View File

@ -1,30 +1,30 @@
#ifndef HEALTHMESSAGE_H_
#define HEALTHMESSAGE_H_
#include "../health/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_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);
static void setHealthMessage(CommandMessage *message, Command_t command);
static HasHealthIF::HealthState getHealth(const CommandMessage *message);
static HasHealthIF::HealthState getOldHealth(const CommandMessage *message);
static void clear(CommandMessage *message);
private:
HealthMessage();
};
#endif /* HEALTHMESSAGE_H_ */
#ifndef HEALTHMESSAGE_H_
#define HEALTHMESSAGE_H_
#include "../health/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_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);
static void setHealthMessage(CommandMessage *message, Command_t command);
static HasHealthIF::HealthState getHealth(const CommandMessage *message);
static HasHealthIF::HealthState getOldHealth(const CommandMessage *message);
static void clear(CommandMessage *message);
private:
HealthMessage();
};
#endif /* HEALTHMESSAGE_H_ */

View File

@ -1,100 +1,100 @@
#include "../health/HealthTable.h"
#include "../serialize/SerializeAdapter.h"
#include "../ipc/MutexFactory.h"
HealthTable::HealthTable(object_id_t objectid) :
SystemObject(objectid) {
mutex = MutexFactory::instance()->createMutex();;
mapIterator = healthMap.begin();
}
HealthTable::~HealthTable() {
MutexFactory::instance()->deleteMutex(mutex);
}
ReturnValue_t HealthTable::registerObject(object_id_t object,
HasHealthIF::HealthState initilialState) {
if (healthMap.count(object) != 0) {
return HasReturnvaluesIF::RETURN_FAILED;
}
healthMap.insert(
std::pair<object_id_t, HasHealthIF::HealthState>(object,
initilialState));
return HasReturnvaluesIF::RETURN_OK;
}
void HealthTable::setHealth(object_id_t object,
HasHealthIF::HealthState newState) {
mutex->lockMutex(MutexIF::BLOCKING);
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);
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);
HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) {
exits = true;
}
mutex->unlockMutex();
return exits;
}
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
mutex->lockMutex(MutexIF::BLOCKING);
size_t size = 0;
uint16_t count = healthMap.size();
ReturnValue_t result = 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,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
uint8_t health = iter->second;
result = SerializeAdapter::serialize(&health, &pointer, &size,
maxSize, SerializeIF::Endianness::BIG);
}
mutex->unlockMutex();
}
ReturnValue_t HealthTable::iterate(
std::pair<object_id_t, HasHealthIF::HealthState> *value, bool reset) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
mutex->lockMutex(MutexIF::BLOCKING);
if (reset) {
mapIterator = healthMap.begin();
}
if (mapIterator == healthMap.end()) {
result = HasReturnvaluesIF::RETURN_FAILED;
}
*value = *mapIterator;
mapIterator++;
mutex->unlockMutex();
return result;
}
#include "../health/HealthTable.h"
#include "../serialize/SerializeAdapter.h"
#include "../ipc/MutexFactory.h"
HealthTable::HealthTable(object_id_t objectid) :
SystemObject(objectid) {
mutex = MutexFactory::instance()->createMutex();;
mapIterator = healthMap.begin();
}
HealthTable::~HealthTable() {
MutexFactory::instance()->deleteMutex(mutex);
}
ReturnValue_t HealthTable::registerObject(object_id_t object,
HasHealthIF::HealthState initilialState) {
if (healthMap.count(object) != 0) {
return HasReturnvaluesIF::RETURN_FAILED;
}
healthMap.insert(
std::pair<object_id_t, HasHealthIF::HealthState>(object,
initilialState));
return HasReturnvaluesIF::RETURN_OK;
}
void HealthTable::setHealth(object_id_t object,
HasHealthIF::HealthState newState) {
mutex->lockMutex(MutexIF::BLOCKING);
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);
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);
HealthMap::iterator iter = healthMap.find(object);
if (iter != healthMap.end()) {
exits = true;
}
mutex->unlockMutex();
return exits;
}
void HealthTable::printAll(uint8_t* pointer, size_t maxSize) {
mutex->lockMutex(MutexIF::BLOCKING);
size_t size = 0;
uint16_t count = healthMap.size();
ReturnValue_t result = 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,
&pointer, &size, maxSize, SerializeIF::Endianness::BIG);
uint8_t health = iter->second;
result = SerializeAdapter::serialize(&health, &pointer, &size,
maxSize, SerializeIF::Endianness::BIG);
}
mutex->unlockMutex();
}
ReturnValue_t HealthTable::iterate(
std::pair<object_id_t, HasHealthIF::HealthState> *value, bool reset) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
mutex->lockMutex(MutexIF::BLOCKING);
if (reset) {
mapIterator = healthMap.begin();
}
if (mapIterator == healthMap.end()) {
result = HasReturnvaluesIF::RETURN_FAILED;
}
*value = *mapIterator;
mapIterator++;
mutex->unlockMutex();
return result;
}

View File

@ -1,35 +1,35 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLE_H_
#define FRAMEWORK_HEALTH_HEALTHTABLE_H_
#include "../health/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);
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);
protected:
MutexIF* mutex;
HealthMap healthMap;
HealthMap::iterator mapIterator;
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false);
};
#endif /* HEALTHTABLE_H_ */
#ifndef FRAMEWORK_HEALTH_HEALTHTABLE_H_
#define FRAMEWORK_HEALTH_HEALTHTABLE_H_
#include "../health/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);
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);
protected:
MutexIF* mutex;
HealthMap healthMap;
HealthMap::iterator mapIterator;
virtual ReturnValue_t iterate(std::pair<object_id_t,HasHealthIF::HealthState> *value, bool reset = false);
};
#endif /* HEALTHTABLE_H_ */

View File

@ -1,28 +1,28 @@
#ifndef FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#define FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#include "../health/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 ReturnValue_t registerObject(object_id_t object,
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
virtual uint32_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;
};
#endif /* FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ */
#ifndef FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#define FRAMEWORK_HEALTH_HEALTHTABLEIF_H_
#include "../health/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 ReturnValue_t registerObject(object_id_t object,
HasHealthIF::HealthState initilialState = HasHealthIF::HEALTHY) = 0;
virtual uint32_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;
};
#endif /* FRAMEWORK_HEALTH_HEALTHTABLEIF_H_ */

View File

@ -1,52 +1,52 @@
#ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
#define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
#include "../health/HasHealthIF.h"
#include "../objectmanager/ObjectManagerIF.h"
class ManagesHealthIF {
public:
virtual ~ManagesHealthIF() {
}
virtual bool hasHealth(object_id_t object) = 0;
virtual void setHealth(object_id_t object,
HasHealthIF::HealthState newState) = 0;
virtual HasHealthIF::HealthState getHealth(object_id_t) = 0;
virtual bool isHealthy(object_id_t object) {
return (getHealth(object) == HasHealthIF::HEALTHY);
}
virtual bool isHealthy(HasHealthIF::HealthState health) {
return (health == HasHealthIF::HEALTHY);
}
virtual bool isFaulty(object_id_t object) {
HasHealthIF::HealthState health = getHealth(object);
return isFaulty(health);
}
virtual bool isPermanentFaulty(object_id_t object) {
HasHealthIF::HealthState health = getHealth(object);
return isPermanentFaulty(health);
}
virtual bool isPermanentFaulty(HasHealthIF::HealthState health) {
return (health == HasHealthIF::PERMANENT_FAULTY);
}
static bool isFaulty(HasHealthIF::HealthState health) {
return ((health == HasHealthIF::FAULTY)
|| (health == HasHealthIF::PERMANENT_FAULTY)
|| (health == HasHealthIF::NEEDS_RECOVERY));
}
virtual bool isCommandable(object_id_t object) {
return (getHealth(object) != HasHealthIF::EXTERNAL_CONTROL);
}
virtual bool isCommandable(HasHealthIF::HealthState health) {
return (health != HasHealthIF::EXTERNAL_CONTROL);
}
};
#endif /* FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ */
#ifndef FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
#define FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_
#include "../health/HasHealthIF.h"
#include "../objectmanager/ObjectManagerIF.h"
class ManagesHealthIF {
public:
virtual ~ManagesHealthIF() {
}
virtual bool hasHealth(object_id_t object) = 0;
virtual void setHealth(object_id_t object,
HasHealthIF::HealthState newState) = 0;
virtual HasHealthIF::HealthState getHealth(object_id_t) = 0;
virtual bool isHealthy(object_id_t object) {
return (getHealth(object) == HasHealthIF::HEALTHY);
}
virtual bool isHealthy(HasHealthIF::HealthState health) {
return (health == HasHealthIF::HEALTHY);
}
virtual bool isFaulty(object_id_t object) {
HasHealthIF::HealthState health = getHealth(object);
return isFaulty(health);
}
virtual bool isPermanentFaulty(object_id_t object) {
HasHealthIF::HealthState health = getHealth(object);
return isPermanentFaulty(health);
}
virtual bool isPermanentFaulty(HasHealthIF::HealthState health) {
return (health == HasHealthIF::PERMANENT_FAULTY);
}
static bool isFaulty(HasHealthIF::HealthState health) {
return ((health == HasHealthIF::FAULTY)
|| (health == HasHealthIF::PERMANENT_FAULTY)
|| (health == HasHealthIF::NEEDS_RECOVERY));
}
virtual bool isCommandable(object_id_t object) {
return (getHealth(object) != HasHealthIF::EXTERNAL_CONTROL);
}
virtual bool isCommandable(HasHealthIF::HealthState health) {
return (health != HasHealthIF::EXTERNAL_CONTROL);
}
};
#endif /* FRAMEWORK_HEALTH_MANAGESHEALTHIF_H_ */

View File

@ -1,11 +1,11 @@
#ifndef FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_
#define FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_
#include "../ipc/MessageQueueMessageIF.h"
class AcceptsHkPacketsIF {
public:
virtual~ AcceptsHkPacketsIF() {};
virtual MessageQueueId_t getHkQueue() const = 0;
};
#endif /* FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ */
#ifndef FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_
#define FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_
#include "../ipc/MessageQueueMessageIF.h"
class AcceptsHkPacketsIF {
public:
virtual~ AcceptsHkPacketsIF() {};
virtual MessageQueueId_t getHkQueue() const = 0;
};
#endif /* FRAMEWORK_HOUSEKEEPING_ACCEPTSHKPACKETSIF_H_ */

View File

@ -1,125 +1,125 @@
#include "../datapoolglob/GlobalDataSet.h"
#include "InternalErrorReporter.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) :
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId),
tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0),
storeHits(0) {
mutex = MutexFactory::instance()->createMutex();
}
InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
GlobDataSet mySet;
gp_uint32_t queueHitsInPool(queuePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t tmHitsInPool(tmPoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t storeHitsInPool(storePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits();
queueHitsInPool.value += newQueueHits;
tmHitsInPool.value += newTmHits;
storeHitsInPool.value += newStoreHits;
mySet.commit(PoolVariableIF::VALID);
return HasReturnvaluesIF::RETURN_OK;
}
void InternalErrorReporter::queueMessageNotSent() {
incrementQueueHits();
}
void InternalErrorReporter::lostTm() {
incrementTmHits();
}
uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = queueHits;
queueHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = queueHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(MutexIF::BLOCKING);
queueHits++;
mutex->unlockMutex();
}
uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = tmHits;
tmHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = tmHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(MutexIF::BLOCKING);
tmHits++;
mutex->unlockMutex();
}
void InternalErrorReporter::storeFull() {
incrementStoreHits();
}
uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = storeHits;
storeHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = storeHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(MutexIF::BLOCKING);
storeHits++;
mutex->unlockMutex();
}
#include "../datapoolglob/GlobalDataSet.h"
#include "InternalErrorReporter.h"
#include "../datapoolglob/GlobalPoolVariable.h"
#include "../ipc/MutexFactory.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId,
uint32_t queuePoolId, uint32_t tmPoolId, uint32_t storePoolId) :
SystemObject(setObjectId), mutex(NULL), queuePoolId(queuePoolId),
tmPoolId(tmPoolId),storePoolId(storePoolId), queueHits(0), tmHits(0),
storeHits(0) {
mutex = MutexFactory::instance()->createMutex();
}
InternalErrorReporter::~InternalErrorReporter() {
MutexFactory::instance()->deleteMutex(mutex);
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
GlobDataSet mySet;
gp_uint32_t queueHitsInPool(queuePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t tmHitsInPool(tmPoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
gp_uint32_t storeHitsInPool(storePoolId, &mySet,
PoolVariableIF::VAR_READ_WRITE);
mySet.read();
uint32_t newQueueHits = getAndResetQueueHits();
uint32_t newTmHits = getAndResetTmHits();
uint32_t newStoreHits = getAndResetStoreHits();
queueHitsInPool.value += newQueueHits;
tmHitsInPool.value += newTmHits;
storeHitsInPool.value += newStoreHits;
mySet.commit(PoolVariableIF::VALID);
return HasReturnvaluesIF::RETURN_OK;
}
void InternalErrorReporter::queueMessageNotSent() {
incrementQueueHits();
}
void InternalErrorReporter::lostTm() {
incrementTmHits();
}
uint32_t InternalErrorReporter::getAndResetQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = queueHits;
queueHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getQueueHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = queueHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementQueueHits() {
mutex->lockMutex(MutexIF::BLOCKING);
queueHits++;
mutex->unlockMutex();
}
uint32_t InternalErrorReporter::getAndResetTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = tmHits;
tmHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getTmHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = tmHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementTmHits() {
mutex->lockMutex(MutexIF::BLOCKING);
tmHits++;
mutex->unlockMutex();
}
void InternalErrorReporter::storeFull() {
incrementStoreHits();
}
uint32_t InternalErrorReporter::getAndResetStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = storeHits;
storeHits = 0;
mutex->unlockMutex();
return value;
}
uint32_t InternalErrorReporter::getStoreHits() {
uint32_t value;
mutex->lockMutex(MutexIF::BLOCKING);
value = storeHits;
mutex->unlockMutex();
return value;
}
void InternalErrorReporter::incrementStoreHits() {
mutex->lockMutex(MutexIF::BLOCKING);
storeHits++;
mutex->unlockMutex();
}

View File

@ -1,50 +1,50 @@
#ifndef INTERNALERRORREPORTER_H_
#define INTERNALERRORREPORTER_H_
#include "InternalErrorReporterIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h"
class InternalErrorReporter: public SystemObject,
public ExecutableObjectIF,
public InternalErrorReporterIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId,
uint32_t tmPoolId, uint32_t storePoolId);
virtual ~InternalErrorReporter();
virtual ReturnValue_t performOperation(uint8_t opCode);
virtual void queueMessageNotSent();
virtual void lostTm();
virtual void storeFull();
protected:
MutexIF* mutex;
uint32_t queuePoolId;
uint32_t tmPoolId;
uint32_t storePoolId;
uint32_t queueHits;
uint32_t tmHits;
uint32_t storeHits;
uint32_t getAndResetQueueHits();
uint32_t getQueueHits();
void incrementQueueHits();
uint32_t getAndResetTmHits();
uint32_t getTmHits();
void incrementTmHits();
uint32_t getAndResetStoreHits();
uint32_t getStoreHits();
void incrementStoreHits();
};
#endif /* INTERNALERRORREPORTER_H_ */
#ifndef INTERNALERRORREPORTER_H_
#define INTERNALERRORREPORTER_H_
#include "InternalErrorReporterIF.h"
#include "../tasks/ExecutableObjectIF.h"
#include "../objectmanager/SystemObject.h"
#include "../ipc/MutexIF.h"
class InternalErrorReporter: public SystemObject,
public ExecutableObjectIF,
public InternalErrorReporterIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t queuePoolId,
uint32_t tmPoolId, uint32_t storePoolId);
virtual ~InternalErrorReporter();
virtual ReturnValue_t performOperation(uint8_t opCode);
virtual void queueMessageNotSent();
virtual void lostTm();
virtual void storeFull();
protected:
MutexIF* mutex;
uint32_t queuePoolId;
uint32_t tmPoolId;
uint32_t storePoolId;
uint32_t queueHits;
uint32_t tmHits;
uint32_t storeHits;
uint32_t getAndResetQueueHits();
uint32_t getQueueHits();
void incrementQueueHits();
uint32_t getAndResetTmHits();
uint32_t getTmHits();
void incrementTmHits();
uint32_t getAndResetStoreHits();
uint32_t getStoreHits();
void incrementStoreHits();
};
#endif /* INTERNALERRORREPORTER_H_ */

View File

@ -1,111 +1,111 @@
#include "CommandMessage.h"
#include "CommandMessageCleaner.h"
#include <cstring>
CommandMessage::CommandMessage() {
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(CMD_NONE);
}
CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
uint32_t parameter2) {
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(command);
setParameter(parameter1);
setParameter2(parameter2);
}
Command_t CommandMessage::getCommand() const {
Command_t command;
std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t));
return command;
}
void CommandMessage::setCommand(Command_t command) {
std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t));
}
uint8_t CommandMessage::getMessageType() const {
// first byte of command ID.
return getCommand() >> 8 & 0xff;
}
uint32_t CommandMessage::getParameter() const {
uint32_t parameter1;
std::memcpy(&parameter1, this->getData(), sizeof(parameter1));
return parameter1;
}
void CommandMessage::setParameter(uint32_t parameter1) {
std::memcpy(this->getData(), &parameter1, sizeof(parameter1));
}
uint32_t CommandMessage::getParameter2() const {
uint32_t parameter2;
std::memcpy(&parameter2, this->getData() + sizeof(uint32_t),
sizeof(parameter2));
return parameter2;
}
void CommandMessage::setParameter2(uint32_t parameter2) {
std::memcpy(this->getData() + sizeof(uint32_t), &parameter2,
sizeof(parameter2));
}
uint32_t CommandMessage::getParameter3() const {
uint32_t parameter3;
std::memcpy(&parameter3, this->getData() + 2 * sizeof(uint32_t),
sizeof(parameter3));
return parameter3;
}
void CommandMessage::setParameter3(uint32_t parameter3) {
std::memcpy(this->getData() + 2 * sizeof(uint32_t), &parameter3,
sizeof(parameter3));
}
size_t CommandMessage::getMinimumMessageSize() const {
return MINIMUM_COMMAND_MESSAGE_SIZE;
}
void CommandMessage::clearCommandMessage() {
clear();
}
void CommandMessage::clear() {
CommandMessageCleaner::clearCommandMessage(this);
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
}
void CommandMessage::setToUnknownCommand() {
Command_t initialCommand = getCommand();
this->clear();
setReplyRejected(UNKNOWN_COMMAND, initialCommand);
}
void CommandMessage::setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) {
setCommand(REPLY_REJECTED);
setParameter(reason);
setParameter2(initialCommand);
}
ReturnValue_t CommandMessage::getReplyRejectedReason(
Command_t *initialCommand) const {
ReturnValue_t reason = getParameter();
if(initialCommand != nullptr) {
*initialCommand = getParameter2();
}
return reason;
}
uint8_t* CommandMessage::getData() {
return MessageQueueMessage::getData() + sizeof(Command_t);
}
const uint8_t* CommandMessage::getData() const {
return MessageQueueMessage::getData() + sizeof(Command_t);
}
#include "CommandMessage.h"
#include "CommandMessageCleaner.h"
#include <cstring>
CommandMessage::CommandMessage() {
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(CMD_NONE);
}
CommandMessage::CommandMessage(Command_t command, uint32_t parameter1,
uint32_t parameter2) {
MessageQueueMessage::setMessageSize(DEFAULT_COMMAND_MESSAGE_SIZE);
setCommand(command);
setParameter(parameter1);
setParameter2(parameter2);
}
Command_t CommandMessage::getCommand() const {
Command_t command;
std::memcpy(&command, MessageQueueMessage::getData(), sizeof(Command_t));
return command;
}
void CommandMessage::setCommand(Command_t command) {
std::memcpy(MessageQueueMessage::getData(), &command, sizeof(Command_t));
}
uint8_t CommandMessage::getMessageType() const {
// first byte of command ID.
return getCommand() >> 8 & 0xff;
}
uint32_t CommandMessage::getParameter() const {
uint32_t parameter1;
std::memcpy(&parameter1, this->getData(), sizeof(parameter1));
return parameter1;
}
void CommandMessage::setParameter(uint32_t parameter1) {
std::memcpy(this->getData(), &parameter1, sizeof(parameter1));
}
uint32_t CommandMessage::getParameter2() const {
uint32_t parameter2;
std::memcpy(&parameter2, this->getData() + sizeof(uint32_t),
sizeof(parameter2));
return parameter2;
}
void CommandMessage::setParameter2(uint32_t parameter2) {
std::memcpy(this->getData() + sizeof(uint32_t), &parameter2,
sizeof(parameter2));
}
uint32_t CommandMessage::getParameter3() const {
uint32_t parameter3;
std::memcpy(&parameter3, this->getData() + 2 * sizeof(uint32_t),
sizeof(parameter3));
return parameter3;
}
void CommandMessage::setParameter3(uint32_t parameter3) {
std::memcpy(this->getData() + 2 * sizeof(uint32_t), &parameter3,
sizeof(parameter3));
}
size_t CommandMessage::getMinimumMessageSize() const {
return MINIMUM_COMMAND_MESSAGE_SIZE;
}
void CommandMessage::clearCommandMessage() {
clear();
}
void CommandMessage::clear() {
CommandMessageCleaner::clearCommandMessage(this);
}
bool CommandMessage::isClearedCommandMessage() {
return getCommand() == CMD_NONE;
}
void CommandMessage::setToUnknownCommand() {
Command_t initialCommand = getCommand();
this->clear();
setReplyRejected(UNKNOWN_COMMAND, initialCommand);
}
void CommandMessage::setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) {
setCommand(REPLY_REJECTED);
setParameter(reason);
setParameter2(initialCommand);
}
ReturnValue_t CommandMessage::getReplyRejectedReason(
Command_t *initialCommand) const {
ReturnValue_t reason = getParameter();
if(initialCommand != nullptr) {
*initialCommand = getParameter2();
}
return reason;
}
uint8_t* CommandMessage::getData() {
return MessageQueueMessage::getData() + sizeof(Command_t);
}
const uint8_t* CommandMessage::getData() const {
return MessageQueueMessage::getData() + sizeof(Command_t);
}

View File

@ -1,129 +1,129 @@
#ifndef FSFW_IPC_COMMANDMESSAGE_H_
#define FSFW_IPC_COMMANDMESSAGE_H_
#include "CommandMessageIF.h"
#include "MessageQueueMessage.h"
#include "FwMessageTypes.h"
/**
* @brief Default command message used to pass command messages between tasks.
* Primary message type for IPC. Contains sender, 2-byte command ID
* field, and 2 4-byte parameters.
* @details
* It operates on an external memory which is contained inside a
* class implementing MessageQueueMessageIF by taking its address.
* This allows for a more flexible designs of message implementations.
* The pointer can be passed to different message implementations without
* the need of unnecessary copying.
*
* The command message is based of the generic MessageQueueMessage which
* currently has an internal message size of 28 bytes.
* @author Bastian Baetz
*/
class CommandMessage: public MessageQueueMessage, public CommandMessageIF {
public:
/**
* Default size can accomodate 2 4-byte parameters.
*/
static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE =
CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t);
/**
* @brief Default Constructor, does not initialize anything.
* @details
* This constructor should be used when receiving a Message, as the
* content is filled by the MessageQueue.
*/
CommandMessage();
/**
* This constructor creates a new message with all message content
* initialized
*
* @param command The DeviceHandlerCommand_t that will be sent
* @param parameter1 The first parameter
* @param parameter2 The second parameter
*/
CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2);
/**
* @brief Default Destructor
*/
virtual ~CommandMessage() {}
/**
* Read the DeviceHandlerCommand_t that is stored in the message,
* usually used after receiving.
*
* @return the Command stored in the Message
*/
virtual Command_t getCommand() const override;
/**
* Set the command type of the message. Default implementation also
* sets the message type, which will be the first byte of the command ID.
* @param the Command to be sent
*/
virtual void setCommand(Command_t command);
virtual uint8_t* getData() override;
virtual const uint8_t* getData() const override;
/**
* Get the first parameter of the message
* @return the first Parameter of the message
*/
uint32_t getParameter() const;
/**
* Set the first parameter of the message
* @param the first parameter of the message
*/
void setParameter(uint32_t parameter1);
uint32_t getParameter2() const;
void setParameter2(uint32_t parameter2);
uint32_t getParameter3() const;
void setParameter3(uint32_t parameter3);
/**
* check if a message was cleared
*
* @return if the command is CMD_NONE
*/
bool isClearedCommandMessage();
/**
* Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND.
* Is needed quite often, so we better code it once only.
*/
void setToUnknownCommand() override;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) override;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const override;
virtual void clear() override;
void clearCommandMessage();
/**
* Extract message ID, which is the first byte of the command ID for the
* default implementation.
* @return
*/
virtual uint8_t getMessageType() const override;
/** MessageQueueMessageIF functions used for minimum size check. */
size_t getMinimumMessageSize() const override;
};
#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */
#ifndef FSFW_IPC_COMMANDMESSAGE_H_
#define FSFW_IPC_COMMANDMESSAGE_H_
#include "CommandMessageIF.h"
#include "MessageQueueMessage.h"
#include "FwMessageTypes.h"
/**
* @brief Default command message used to pass command messages between tasks.
* Primary message type for IPC. Contains sender, 2-byte command ID
* field, and 2 4-byte parameters.
* @details
* It operates on an external memory which is contained inside a
* class implementing MessageQueueMessageIF by taking its address.
* This allows for a more flexible designs of message implementations.
* The pointer can be passed to different message implementations without
* the need of unnecessary copying.
*
* The command message is based of the generic MessageQueueMessage which
* currently has an internal message size of 28 bytes.
* @author Bastian Baetz
*/
class CommandMessage: public MessageQueueMessage, public CommandMessageIF {
public:
/**
* Default size can accomodate 2 4-byte parameters.
*/
static constexpr size_t DEFAULT_COMMAND_MESSAGE_SIZE =
CommandMessageIF::MINIMUM_COMMAND_MESSAGE_SIZE + sizeof(uint32_t);
/**
* @brief Default Constructor, does not initialize anything.
* @details
* This constructor should be used when receiving a Message, as the
* content is filled by the MessageQueue.
*/
CommandMessage();
/**
* This constructor creates a new message with all message content
* initialized
*
* @param command The DeviceHandlerCommand_t that will be sent
* @param parameter1 The first parameter
* @param parameter2 The second parameter
*/
CommandMessage(Command_t command, uint32_t parameter1, uint32_t parameter2);
/**
* @brief Default Destructor
*/
virtual ~CommandMessage() {}
/**
* Read the DeviceHandlerCommand_t that is stored in the message,
* usually used after receiving.
*
* @return the Command stored in the Message
*/
virtual Command_t getCommand() const override;
/**
* Set the command type of the message. Default implementation also
* sets the message type, which will be the first byte of the command ID.
* @param the Command to be sent
*/
virtual void setCommand(Command_t command);
virtual uint8_t* getData() override;
virtual const uint8_t* getData() const override;
/**
* Get the first parameter of the message
* @return the first Parameter of the message
*/
uint32_t getParameter() const;
/**
* Set the first parameter of the message
* @param the first parameter of the message
*/
void setParameter(uint32_t parameter1);
uint32_t getParameter2() const;
void setParameter2(uint32_t parameter2);
uint32_t getParameter3() const;
void setParameter3(uint32_t parameter3);
/**
* check if a message was cleared
*
* @return if the command is CMD_NONE
*/
bool isClearedCommandMessage();
/**
* Sets the command to REPLY_REJECTED with parameter UNKNOWN_COMMAND.
* Is needed quite often, so we better code it once only.
*/
void setToUnknownCommand() override;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) override;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const override;
virtual void clear() override;
void clearCommandMessage();
/**
* Extract message ID, which is the first byte of the command ID for the
* default implementation.
* @return
*/
virtual uint8_t getMessageType() const override;
/** MessageQueueMessageIF functions used for minimum size check. */
size_t getMinimumMessageSize() const override;
};
#endif /* FSFW_IPC_COMMANDMESSAGE_H_ */

View File

@ -1,45 +1,45 @@
#include "../ipc/CommandMessageCleaner.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
switch(message->getMessageType()){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(message);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(message);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(message);
break;
case messagetypes::ACTION:
ActionMessage::clear(message);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(message);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(message);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(message);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(message);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(message);
break;
default:
messagetypes::clearMissionMessage(message);
break;
}
}
#include "../ipc/CommandMessageCleaner.h"
#include "../devicehandlers/DeviceHandlerMessage.h"
#include "../health/HealthMessage.h"
#include "../memory/MemoryMessage.h"
#include "../modes/ModeMessage.h"
#include "../monitoring/MonitoringMessage.h"
#include "../subsystem/modes/ModeSequenceMessage.h"
#include "../tmstorage/TmStoreMessage.h"
#include "../parameters/ParameterMessage.h"
void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
switch(message->getMessageType()){
case messagetypes::MODE_COMMAND:
ModeMessage::clear(message);
break;
case messagetypes::HEALTH_COMMAND:
HealthMessage::clear(message);
break;
case messagetypes::MODE_SEQUENCE:
ModeSequenceMessage::clear(message);
break;
case messagetypes::ACTION:
ActionMessage::clear(message);
break;
case messagetypes::DEVICE_HANDLER_COMMAND:
DeviceHandlerMessage::clear(message);
break;
case messagetypes::MEMORY:
MemoryMessage::clear(message);
break;
case messagetypes::MONITORING:
MonitoringMessage::clear(message);
break;
case messagetypes::TM_STORE:
TmStoreMessage::clear(message);
break;
case messagetypes::PARAMETER:
ParameterMessage::clear(message);
break;
default:
messagetypes::clearMissionMessage(message);
break;
}
}

View File

@ -1,16 +1,16 @@
#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#include "../ipc/CommandMessage.h"
namespace messagetypes {
// Implemented in config.
void clearMissionMessage(CommandMessage* message);
}
class CommandMessageCleaner {
public:
static void clearCommandMessage(CommandMessage* message);
};
#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */
#ifndef FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#define FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_
#include "../ipc/CommandMessage.h"
namespace messagetypes {
// Implemented in config.
void clearMissionMessage(CommandMessage* message);
}
class CommandMessageCleaner {
public:
static void clearCommandMessage(CommandMessage* message);
};
#endif /* FRAMEWORK_IPC_COMMANDMESSAGECLEANER_H_ */

View File

@ -1,73 +1,73 @@
#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_
#define FSFW_IPC_COMMANDMESSAGEIF_H_
#include "MessageQueueMessageIF.h"
#include "FwMessageTypes.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef uint16_t Command_t;
class CommandMessageIF {
public:
/**
* Header consists of sender ID and command ID.
*/
static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE +
sizeof(Command_t);
/**
* This minimum size is derived from the interface requirement to be able
* to set a rejected reply, which contains a returnvalue and the initial
* command.
*/
static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE =
CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) +
sizeof(Command_t);
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
//! Used internally, shall be ignored
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 );
//! Reply indicating that the current command was rejected,
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 );
virtual ~CommandMessageIF() {};
/**
* A command message shall have a uint16_t command ID field.
* @return
*/
virtual Command_t getCommand() const = 0;
/**
* A command message shall have a uint8_t message type ID field.
* @return
*/
virtual uint8_t getMessageType() const = 0;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
virtual void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) = 0;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
virtual ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const = 0;
virtual void setToUnknownCommand() = 0;
virtual void clear() = 0;
};
#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */
#ifndef FSFW_IPC_COMMANDMESSAGEIF_H_
#define FSFW_IPC_COMMANDMESSAGEIF_H_
#include "MessageQueueMessageIF.h"
#include "FwMessageTypes.h"
#include "../returnvalues/HasReturnvaluesIF.h"
#define MAKE_COMMAND_ID( number ) ((MESSAGE_ID << 8) + (number))
typedef uint16_t Command_t;
class CommandMessageIF {
public:
/**
* Header consists of sender ID and command ID.
*/
static constexpr size_t HEADER_SIZE = MessageQueueMessageIF::HEADER_SIZE +
sizeof(Command_t);
/**
* This minimum size is derived from the interface requirement to be able
* to set a rejected reply, which contains a returnvalue and the initial
* command.
*/
static constexpr size_t MINIMUM_COMMAND_MESSAGE_SIZE =
CommandMessageIF::HEADER_SIZE + sizeof(ReturnValue_t) +
sizeof(Command_t);
static const uint8_t INTERFACE_ID = CLASS_ID::COMMAND_MESSAGE;
static const ReturnValue_t UNKNOWN_COMMAND = MAKE_RETURN_CODE(0x01);
static const uint8_t MESSAGE_ID = messagetypes::COMMAND;
//! Used internally, shall be ignored
static const Command_t CMD_NONE = MAKE_COMMAND_ID( 0 );
static const Command_t REPLY_COMMAND_OK = MAKE_COMMAND_ID( 1 );
//! Reply indicating that the current command was rejected,
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID( 2 );
virtual ~CommandMessageIF() {};
/**
* A command message shall have a uint16_t command ID field.
* @return
*/
virtual Command_t getCommand() const = 0;
/**
* A command message shall have a uint8_t message type ID field.
* @return
*/
virtual uint8_t getMessageType() const = 0;
/**
* A command message can be rejected and needs to offer a function
* to set a rejected reply
* @param reason
* @param initialCommand
*/
virtual void setReplyRejected(ReturnValue_t reason,
Command_t initialCommand) = 0;
/**
* Corrensonding getter function.
* @param initialCommand
* @return
*/
virtual ReturnValue_t getReplyRejectedReason(
Command_t* initialCommand = nullptr) const = 0;
virtual void setToUnknownCommand() = 0;
virtual void clear() = 0;
};
#endif /* FSFW_IPC_COMMANDMESSAGEIF_H_ */

View File

@ -1,171 +1,171 @@
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls
// semaphores are being implemented, which makes this idea even more iteresting.
/**
* @defgroup message_queue Message Queue
* @brief Message Queue related software components
*/
#include "../ipc/MessageQueueMessage.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class MessageQueueIF {
public:
static const MessageQueueId_t NO_QUEUE = MessageQueueMessageIF::NO_QUEUE; //!< Ugly hack.
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
//! No new messages on the queue
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
//! No space left for more messages
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
//! Returned if a reply method was called without partner
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
//! Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() {}
/**
* @brief This operation sends a message to the last communication partner.
* @details
* This operation simplifies answering an incoming message by using the
* stored lastParnter information as destination. If there was no message
* received yet (i.e. lastPartner is zero), an error code is returned.
* @param message
* A pointer to a previously created message, which is sent.
* @return
* -@c RETURN_OK if ok
* -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found.
*/
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/**
* @brief This function reads available messages from the message queue
* and returns the sender.
* @details
* It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id.
* @param message
* A pointer to a message in which the received data is stored.
* @param receivedFrom
* A pointer to a queue id in which the sender's id is stored.
*/
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) = 0;
/**
* @brief This function reads available messages from the message queue.
* @details
* If data is available it is stored in the passed message pointer.
* The message's original content is overwritten and the sendFrom
* information is stored in theblastPartner attribute. Else, the lastPartner
* information remains untouched, the message's content is cleared and the
* function returns immediately.
* @param message
* A pointer to a message in which the received data is stored.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::EMPTY if queue is empty
*/
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
virtual ReturnValue_t flush(uint32_t* count) = 0;
/**
* @brief This method returns the message queue
* id of the last communication partner.
*/
virtual MessageQueueId_t getLastPartner() const = 0;
/**
* @brief This method returns the message queue
* id of this class's message queue.
*/
virtual MessageQueueId_t getId() const = 0;
/**
* @brief With the sendMessage call, a queue message
* is sent to a receiving queue.
* @details
* This method takes the message provided, adds the sentFrom information
* and passes it on to the destination provided with an operating system
* call. The OS's returnvalue is returned.
* @param sendTo
* This parameter specifies the message queue id to send the message to.
* @param message
* This is a pointer to a previously created message, which is sent.
* @param sentFrom
* The sentFrom information can be set to inject the sender's queue id
* into the message. This variable is set to zero by default.
* @param ignoreFault
* If set to true, the internal software fault counter is not incremented
* if queue is full (if implemented).
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false ) = 0;
/**
* @brief This operation sends a message to the given destination.
* @details
* It directly uses the sendMessage call of the MessageQueueSender parent,
* but passes its queue id as "sentFrom" parameter.
* @param sendTo
* This parameter specifies the message queue id of the destination
* message queue.
* @param message
* A pointer to a previously created message, which is sent.
* @param ignoreFault
* If set to true, the internal software fault counter is not incremented
* if queue is full.
*/
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) = 0;
/**
* @brief The sendToDefaultFrom method sends a queue message
* to the default destination.
* @details
* In all other aspects, it works identical to the sendMessage method.
* @param message
* This is a pointer to a previously created message, which is sent.
* @param sentFrom
* The sentFrom information can be set to inject the sender's queue id
* into the message. This variable is set to zero by default.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
/**
* @brief This operation sends a message to the default destination.
* @details
* As in the sendMessage method, this function uses the sendToDefault
* call of the Implementation class and adds its queue id as
* "sentFrom" information.
* @param message A pointer to a previously created message, which is sent.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0;
/**
* @brief This method is a simple setter for the default destination.
*/
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0;
/**
* @brief This method is a simple getter for the default destination.
*/
virtual MessageQueueId_t getDefaultDestination() const = 0;
virtual bool isDefaultDestinationSet() const = 0;
};
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */
#ifndef FSFW_IPC_MESSAGEQUEUEIF_H_
#define FSFW_IPC_MESSAGEQUEUEIF_H_
// COULDDO: We could support blocking calls
// semaphores are being implemented, which makes this idea even more iteresting.
/**
* @defgroup message_queue Message Queue
* @brief Message Queue related software components
*/
#include "../ipc/MessageQueueMessage.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../returnvalues/HasReturnvaluesIF.h"
class MessageQueueIF {
public:
static const MessageQueueId_t NO_QUEUE = MessageQueueMessageIF::NO_QUEUE; //!< Ugly hack.
static const uint8_t INTERFACE_ID = CLASS_ID::MESSAGE_QUEUE_IF;
//! No new messages on the queue
static const ReturnValue_t EMPTY = MAKE_RETURN_CODE(1);
//! No space left for more messages
static const ReturnValue_t FULL = MAKE_RETURN_CODE(2);
//! Returned if a reply method was called without partner
static const ReturnValue_t NO_REPLY_PARTNER = MAKE_RETURN_CODE(3);
//! Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINVATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() {}
/**
* @brief This operation sends a message to the last communication partner.
* @details
* This operation simplifies answering an incoming message by using the
* stored lastParnter information as destination. If there was no message
* received yet (i.e. lastPartner is zero), an error code is returned.
* @param message
* A pointer to a previously created message, which is sent.
* @return
* -@c RETURN_OK if ok
* -@c NO_REPLY_PARTNER Should return NO_REPLY_PARTNER if partner was found.
*/
virtual ReturnValue_t reply(MessageQueueMessageIF* message) = 0;
/**
* @brief This function reads available messages from the message queue
* and returns the sender.
* @details
* It works identically to the other receiveMessage call, but in addition
* returns the sender's queue id.
* @param message
* A pointer to a message in which the received data is stored.
* @param receivedFrom
* A pointer to a queue id in which the sender's id is stored.
*/
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t *receivedFrom) = 0;
/**
* @brief This function reads available messages from the message queue.
* @details
* If data is available it is stored in the passed message pointer.
* The message's original content is overwritten and the sendFrom
* information is stored in theblastPartner attribute. Else, the lastPartner
* information remains untouched, the message's content is cleared and the
* function returns immediately.
* @param message
* A pointer to a message in which the received data is stored.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::EMPTY if queue is empty
*/
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
/**
* Deletes all pending messages in the queue.
* @param count The number of flushed messages.
* @return RETURN_OK on success.
*/
virtual ReturnValue_t flush(uint32_t* count) = 0;
/**
* @brief This method returns the message queue
* id of the last communication partner.
*/
virtual MessageQueueId_t getLastPartner() const = 0;
/**
* @brief This method returns the message queue
* id of this class's message queue.
*/
virtual MessageQueueId_t getId() const = 0;
/**
* @brief With the sendMessage call, a queue message
* is sent to a receiving queue.
* @details
* This method takes the message provided, adds the sentFrom information
* and passes it on to the destination provided with an operating system
* call. The OS's returnvalue is returned.
* @param sendTo
* This parameter specifies the message queue id to send the message to.
* @param message
* This is a pointer to a previously created message, which is sent.
* @param sentFrom
* The sentFrom information can be set to inject the sender's queue id
* into the message. This variable is set to zero by default.
* @param ignoreFault
* If set to true, the internal software fault counter is not incremented
* if queue is full (if implemented).
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendMessageFrom( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false ) = 0;
/**
* @brief This operation sends a message to the given destination.
* @details
* It directly uses the sendMessage call of the MessageQueueSender parent,
* but passes its queue id as "sentFrom" parameter.
* @param sendTo
* This parameter specifies the message queue id of the destination
* message queue.
* @param message
* A pointer to a previously created message, which is sent.
* @param ignoreFault
* If set to true, the internal software fault counter is not incremented
* if queue is full.
*/
virtual ReturnValue_t sendMessage( MessageQueueId_t sendTo,
MessageQueueMessageIF* message, bool ignoreFault = false ) = 0;
/**
* @brief The sendToDefaultFrom method sends a queue message
* to the default destination.
* @details
* In all other aspects, it works identical to the sendMessage method.
* @param message
* This is a pointer to a previously created message, which is sent.
* @param sentFrom
* The sentFrom information can be set to inject the sender's queue id
* into the message. This variable is set to zero by default.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendToDefaultFrom( MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false ) = 0;
/**
* @brief This operation sends a message to the default destination.
* @details
* As in the sendMessage method, this function uses the sendToDefault
* call of the Implementation class and adds its queue id as
* "sentFrom" information.
* @param message A pointer to a previously created message, which is sent.
* @return -@c RETURN_OK on success
* -@c MessageQueueIF::FULL if queue is full
*/
virtual ReturnValue_t sendToDefault( MessageQueueMessageIF* message ) = 0;
/**
* @brief This method is a simple setter for the default destination.
*/
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) = 0;
/**
* @brief This method is a simple getter for the default destination.
*/
virtual MessageQueueId_t getDefaultDestination() const = 0;
virtual bool isDefaultDestinationSet() const = 0;
};
#endif /* FSFW_IPC_MESSAGEQUEUEIF_H_ */

View File

@ -1,84 +1,84 @@
#include "MessageQueueMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
MessageQueueMessage::MessageQueueMessage() :
messageSize(getMinimumMessageSize()) {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
this->messageSize = this->HEADER_SIZE + size;
}
else {
sif::warning << "MessageQueueMessage: Passed size larger than maximum"
"allowed size! Setting content to 0" << std::endl;
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
}
}
MessageQueueMessage::~MessageQueueMessage() {
}
const uint8_t* MessageQueueMessage::getBuffer() const {
return this->internalBuffer;
}
uint8_t* MessageQueueMessage::getBuffer() {
return this->internalBuffer;
}
const uint8_t* MessageQueueMessage::getData() const {
return this->internalBuffer + this->HEADER_SIZE;
}
uint8_t* MessageQueueMessage::getData() {
return this->internalBuffer + this->HEADER_SIZE;
}
MessageQueueId_t MessageQueueMessage::getSender() const {
MessageQueueId_t temp_id;
memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t));
return temp_id;
}
void MessageQueueMessage::setSender(MessageQueueId_t setId) {
memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t));
}
void MessageQueueMessage::print(bool printWholeMessage) {
sif::debug << "MessageQueueMessage content: " << std::endl;
if(printWholeMessage) {
arrayprinter::print(getData(), getMaximumMessageSize());
}
else {
arrayprinter::print(getData(), getMessageSize());
}
}
void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE);
}
size_t MessageQueueMessage::getMessageSize() const {
return this->messageSize;
}
void MessageQueueMessage::setMessageSize(size_t messageSize) {
this->messageSize = messageSize;
}
size_t MessageQueueMessage::getMinimumMessageSize() const {
return this->MIN_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE;
}
#include "MessageQueueMessage.h"
#include "../serviceinterface/ServiceInterfaceStream.h"
#include "../globalfunctions/arrayprinter.h"
#include <cstring>
MessageQueueMessage::MessageQueueMessage() :
messageSize(getMinimumMessageSize()) {
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size) :
messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
this->messageSize = this->HEADER_SIZE + size;
}
else {
sif::warning << "MessageQueueMessage: Passed size larger than maximum"
"allowed size! Setting content to 0" << std::endl;
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = this->HEADER_SIZE;
}
}
MessageQueueMessage::~MessageQueueMessage() {
}
const uint8_t* MessageQueueMessage::getBuffer() const {
return this->internalBuffer;
}
uint8_t* MessageQueueMessage::getBuffer() {
return this->internalBuffer;
}
const uint8_t* MessageQueueMessage::getData() const {
return this->internalBuffer + this->HEADER_SIZE;
}
uint8_t* MessageQueueMessage::getData() {
return this->internalBuffer + this->HEADER_SIZE;
}
MessageQueueId_t MessageQueueMessage::getSender() const {
MessageQueueId_t temp_id;
memcpy(&temp_id, this->internalBuffer, sizeof(MessageQueueId_t));
return temp_id;
}
void MessageQueueMessage::setSender(MessageQueueId_t setId) {
memcpy(this->internalBuffer, &setId, sizeof(MessageQueueId_t));
}
void MessageQueueMessage::print(bool printWholeMessage) {
sif::debug << "MessageQueueMessage content: " << std::endl;
if(printWholeMessage) {
arrayprinter::print(getData(), getMaximumMessageSize());
}
else {
arrayprinter::print(getData(), getMessageSize());
}
}
void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, this->MAX_MESSAGE_SIZE);
}
size_t MessageQueueMessage::getMessageSize() const {
return this->messageSize;
}
void MessageQueueMessage::setMessageSize(size_t messageSize) {
this->messageSize = messageSize;
}
size_t MessageQueueMessage::getMinimumMessageSize() const {
return this->MIN_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumMessageSize() const {
return this->MAX_MESSAGE_SIZE;
}

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