Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr_other_introspection
This commit is contained in:
commit
b08d127e11
3
.gitignore
vendored
3
.gitignore
vendored
@ -10,5 +10,8 @@
|
|||||||
.settings
|
.settings
|
||||||
.metadata
|
.metadata
|
||||||
|
|
||||||
|
# VSCode
|
||||||
|
.vscode
|
||||||
|
|
||||||
/build*
|
/build*
|
||||||
/cmake-build*
|
/cmake-build*
|
||||||
|
@ -15,6 +15,7 @@ add_subdirectory(globalfunctions)
|
|||||||
add_subdirectory(health)
|
add_subdirectory(health)
|
||||||
add_subdirectory(housekeeping)
|
add_subdirectory(housekeeping)
|
||||||
add_subdirectory(internalerror)
|
add_subdirectory(internalerror)
|
||||||
|
add_subdirectory(introspection)
|
||||||
add_subdirectory(ipc)
|
add_subdirectory(ipc)
|
||||||
add_subdirectory(memory)
|
add_subdirectory(memory)
|
||||||
add_subdirectory(modes)
|
add_subdirectory(modes)
|
||||||
|
62
src/fsfw/action/Action.cpp
Normal file
62
src/fsfw/action/Action.cpp
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#include "Action.h"
|
||||||
|
|
||||||
|
#include <fsfw/serialize/SerializeAdapter.h>
|
||||||
|
|
||||||
|
#undef Action
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
Action::Action() {}
|
||||||
|
|
||||||
|
void Action::setEnum(EnumIF *theEnum) {
|
||||||
|
id = theEnum->getValue();
|
||||||
|
name = theEnum->getDescription();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *Action::getName() { return name; }
|
||||||
|
#else
|
||||||
|
Action::Action(ActionId_t id) : id(id) {}
|
||||||
|
#endif
|
||||||
|
ActionId_t Action::getId() { return id; }
|
||||||
|
|
||||||
|
void Action::registerParameter(ParameterIF *parameter) { parameterList.push_back(parameter); }
|
||||||
|
|
||||||
|
std::vector<ParameterIF *> const *Action::getParameters() const { return ¶meterList; }
|
||||||
|
|
||||||
|
size_t Action::getSerializedSize() const {
|
||||||
|
size_t size = SerializeAdapter::getSerializedSize(&id);
|
||||||
|
for (auto parameter : *getParameters()) {
|
||||||
|
size += parameter->getSerializedSize();
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Action::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const {
|
||||||
|
ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
for (auto parameter : *getParameters()) {
|
||||||
|
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t Action::deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
|
Endianness streamEndianness) {
|
||||||
|
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;/* TODO not needed as must have been read before to find this action = SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}*/
|
||||||
|
for (auto parameter : *getParameters()) {
|
||||||
|
result = parameter->deSerialize(buffer, size, streamEndianness);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
47
src/fsfw/action/Action.h
Normal file
47
src/fsfw/action/Action.h
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <fsfw/serialize/SerializeIF.h>
|
||||||
|
#include "ActionMessage.h"
|
||||||
|
#include "ParameterIF.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
#include "../introspection/Enum.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Action: public SerializeIF {
|
||||||
|
public:
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
Action();
|
||||||
|
void setEnum(EnumIF* id);
|
||||||
|
const char *getName();
|
||||||
|
#else
|
||||||
|
Action(ActionId_t id);
|
||||||
|
#endif
|
||||||
|
ActionId_t getId();
|
||||||
|
|
||||||
|
virtual ReturnValue_t handle() = 0;
|
||||||
|
|
||||||
|
void registerParameter(ParameterIF *parameter);
|
||||||
|
|
||||||
|
std::vector<ParameterIF *> const *getParameters() const;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActionId_t id;
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
const char *name;
|
||||||
|
#endif
|
||||||
|
std::vector<ParameterIF *> parameterList;
|
||||||
|
};
|
@ -57,6 +57,8 @@ void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t co
|
|||||||
|
|
||||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||||
store_address_t dataAddress) {
|
store_address_t dataAddress) {
|
||||||
const uint8_t* dataPtr = NULL;
|
const uint8_t* dataPtr = NULL;
|
||||||
@ -66,9 +68,29 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
|
|||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
auto actionIter = actionMap.find(actionId);
|
||||||
|
if (actionIter == actionMap.end()){
|
||||||
|
puts("end");
|
||||||
|
CommandMessage reply;
|
||||||
|
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Action* action = actionIter->second;
|
||||||
|
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||||
|
if ((result != HasReturnvaluesIF::RETURN_OK) || (size != 0)){ //TODO write unittest for second condition
|
||||||
|
printf("serialze %i, %x\n", size, result);
|
||||||
|
CommandMessage reply;
|
||||||
|
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result = action->handle();
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||||
CommandMessage reply;
|
CommandMessage reply;
|
||||||
@ -163,3 +185,11 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ActionHelper::registerAction(Action* action) {
|
||||||
|
//TODO error handling
|
||||||
|
ActionId_t id = action->getId();
|
||||||
|
actionMap.emplace(id, action);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<ActionId_t, Action*> const* ActionHelper::getActionMap() { return &actionMap; }
|
@ -1,9 +1,11 @@
|
|||||||
#ifndef FSFW_ACTION_ACTIONHELPER_H_
|
#ifndef FSFW_ACTION_ACTIONHELPER_H_
|
||||||
#define FSFW_ACTION_ACTIONHELPER_H_
|
#define FSFW_ACTION_ACTIONHELPER_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include "../ipc/MessageQueueIF.h"
|
#include "../ipc/MessageQueueIF.h"
|
||||||
#include "../serialize/SerializeIF.h"
|
#include "../serialize/SerializeIF.h"
|
||||||
#include "ActionMessage.h"
|
#include "ActionMessage.h"
|
||||||
|
#include "Action.h"
|
||||||
/**
|
/**
|
||||||
* @brief Action Helper is a helper class which handles action messages
|
* @brief Action Helper is a helper class which handles action messages
|
||||||
*
|
*
|
||||||
@ -98,6 +100,10 @@ class ActionHelper {
|
|||||||
*/
|
*/
|
||||||
void setQueueToUse(MessageQueueIF* queue);
|
void setQueueToUse(MessageQueueIF* queue);
|
||||||
|
|
||||||
|
void registerAction(Action* action);
|
||||||
|
|
||||||
|
std::map<ActionId_t, Action*> const* getActionMap();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
//! Increase of value of this per step
|
//! Increase of value of this per step
|
||||||
static const uint8_t STEP_OFFSET = 1;
|
static const uint8_t STEP_OFFSET = 1;
|
||||||
@ -108,6 +114,8 @@ class ActionHelper {
|
|||||||
MessageQueueIF* queueToUse;
|
MessageQueueIF* queueToUse;
|
||||||
//! Pointer to an IPC Store, initialized during construction or
|
//! Pointer to an IPC Store, initialized during construction or
|
||||||
StorageManagerIF* ipcStore = nullptr;
|
StorageManagerIF* ipcStore = nullptr;
|
||||||
|
//! Map of all implemented Actions
|
||||||
|
std::map<ActionId_t, Action*> actionMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function called by handleActionMessage
|
* Internal function called by handleActionMessage
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
target_sources(
|
target_sources(
|
||||||
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
|
${LIB_FSFW_NAME} PRIVATE Action.cpp ActionHelper.cpp ActionMessage.cpp
|
||||||
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
CommandActionHelper.cpp SimpleActionHelper.cpp)
|
||||||
|
@ -44,8 +44,11 @@ class HasActionsIF {
|
|||||||
/**
|
/**
|
||||||
* Function to get the MessageQueueId_t of the implementing object
|
* Function to get the MessageQueueId_t of the implementing object
|
||||||
* @return MessageQueueId_t of the object
|
* @return MessageQueueId_t of the object
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
virtual MessageQueueId_t getCommandQueue() const = 0;
|
virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||||
|
|
||||||
|
virtual ActionHelper* getActionHelper() = 0;
|
||||||
/**
|
/**
|
||||||
* Execute or initialize the execution of a certain function.
|
* Execute or initialize the execution of a certain function.
|
||||||
* The ActionHelpers will execute this function and behave differently
|
* The ActionHelpers will execute this function and behave differently
|
||||||
@ -55,8 +58,7 @@ class HasActionsIF {
|
|||||||
* -@c EXECUTION_FINISHED Finish reply will be generated
|
* -@c EXECUTION_FINISHED Finish reply will be generated
|
||||||
* -@c Not RETURN_OK Step failure reply will be generated
|
* -@c Not RETURN_OK Step failure reply will be generated
|
||||||
*/
|
*/
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
virtual ReturnValue_t executeAction(Action* action, MessageQueueId_t commandedBy) = 0;
|
||||||
const uint8_t* data, size_t size) = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */
|
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */
|
||||||
|
40
src/fsfw/action/MinMaxParameter.h
Normal file
40
src/fsfw/action/MinMaxParameter.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Parameter.h"
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class MinMaxParameter : public Parameter<T> {
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
private:
|
||||||
|
MinMaxParameter(Action *owner, const char *name, T min, T max)
|
||||||
|
: Parameter<T>(owner, name), min(min), max(max) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MinMaxParameter createMinMaxParameter(Action *owner, const char *name, T min, T max) {
|
||||||
|
return MinMaxParameter(owner, name, min, max);
|
||||||
|
}
|
||||||
|
virtual double getMinFloating() override { return static_cast<double>(min); }
|
||||||
|
virtual int64_t getMinSigned() override { return static_cast<int64_t>(min); }
|
||||||
|
|
||||||
|
virtual double getMaxFloating() override { return static_cast<double>(max); }
|
||||||
|
virtual int64_t getMaxSigned() override { return static_cast<int64_t>(max); }
|
||||||
|
|
||||||
|
#else
|
||||||
|
private:
|
||||||
|
MinMaxParameter(Action *owner, T min, T max) : Parameter<T>(owner), min(min), max(max) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
static MinMaxParameter createMinMaxParameter(Action *owner, T min, T max) {
|
||||||
|
return MinMaxParameter(owner, min, max);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
private:
|
||||||
|
T min;
|
||||||
|
T max;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p2, p3, p4)
|
||||||
|
#else
|
||||||
|
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p3, p4)
|
||||||
|
#endif
|
117
src/fsfw/action/Parameter.h
Normal file
117
src/fsfw/action/Parameter.h
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
#include <fsfw/introspection/Types.h>
|
||||||
|
#include <fsfw/introspection/TypesHelper.h>
|
||||||
|
#include "ParameterIF.h"
|
||||||
|
// TODO: ifdef introspection stuff
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
class Parameter : public ParameterIF {
|
||||||
|
protected:
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
Parameter(Action *owner, const char *name)
|
||||||
|
: name(name)
|
||||||
|
#else
|
||||||
|
Parameter(Action *owner)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
owner->registerParameter(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
static Parameter createParameter(Action *owner, const char *name) {
|
||||||
|
return Parameter(owner, name);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static Parameter createParameter(Action *owner) { return Parameter(owner); }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool isValid() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::isValid(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T(){
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
Types::ParameterType getType() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getType<T>();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
T value;
|
||||||
|
|
||||||
|
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
Endianness streamEndianness) const override {
|
||||||
|
return SerializeAdapter::serialize(&value, buffer, size, maxSize, streamEndianness);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSerializedSize() const override { return SerializeAdapter::getSerializedSize(&value); }
|
||||||
|
|
||||||
|
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
|
Endianness streamEndianness) override {
|
||||||
|
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
double getFloating() override { return (double)value; }
|
||||||
|
int64_t getSigned() override { return (int64_t)value; }
|
||||||
|
|
||||||
|
bool setFloating(double value) override {
|
||||||
|
if (getType() != Types::FLOATING) {
|
||||||
|
puts("fups");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->value = T(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setSigned(int64_t value) override {
|
||||||
|
if ((getType() != Types::SIGNED) && (getType() != Types::ENUM)) {
|
||||||
|
puts("sups");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this->value = T(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMinFloating() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMin<T>();
|
||||||
|
}
|
||||||
|
int64_t getMinSigned() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMin<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMaxFloating() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMax<T>();
|
||||||
|
}
|
||||||
|
int64_t getMaxSigned() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::template getMax<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<int64_t> getEnumValues() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::getEnumValues(&value);
|
||||||
|
}
|
||||||
|
const char *const *getEnumDescriptions() override {
|
||||||
|
return enumHelper<std::is_base_of<EnumIF, T>::value>::getEnumDescriptions(&value);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *getName() override { return name; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char *name;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
#define createParameter(p1, p2) createParameter(p1, p2)
|
||||||
|
#else
|
||||||
|
#define createParameter(p1, p2) createParameter(p1)
|
||||||
|
#endif
|
45
src/fsfw/action/ParameterIF.h
Normal file
45
src/fsfw/action/ParameterIF.h
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/serialize/SerializeIF.h>
|
||||||
|
#include <fsfw/introspection/Types.h>
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
#include <vector>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class ParameterIF : public SerializeIF {
|
||||||
|
public:
|
||||||
|
virtual bool isValid() = 0;
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
virtual const char *getName() = 0;
|
||||||
|
|
||||||
|
virtual Types::ParameterType getType() = 0;
|
||||||
|
|
||||||
|
virtual double getFloating() = 0;
|
||||||
|
virtual int64_t getSigned() = 0;
|
||||||
|
|
||||||
|
virtual bool setFloating(double value) = 0;
|
||||||
|
virtual bool setSigned(int64_t value) = 0;
|
||||||
|
|
||||||
|
virtual double getMinFloating() = 0;
|
||||||
|
virtual int64_t getMinSigned() = 0;
|
||||||
|
|
||||||
|
virtual double getMaxFloating() = 0;
|
||||||
|
virtual int64_t getMaxSigned() = 0;
|
||||||
|
|
||||||
|
virtual std::vector<int64_t> getEnumValues() = 0;
|
||||||
|
virtual const char *const * getEnumDescriptions() = 0;
|
||||||
|
|
||||||
|
// ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||||
|
// Endianness streamEndianness) const override = 0;
|
||||||
|
|
||||||
|
// size_t getSerializedSize() const override = 0;
|
||||||
|
|
||||||
|
// ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||||
|
// Endianness streamEndianness) override = 0;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
@ -44,11 +44,27 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId
|
|||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||||
queueToUse->sendMessage(commandedBy, &reply);
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
lastCommander = commandedBy;
|
auto actionIter = actionMap.find(actionId);
|
||||||
lastAction = actionId;
|
if (actionIter == actionMap.end()){
|
||||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
CommandMessage reply;
|
||||||
|
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Action* action = actionIter->second;
|
||||||
|
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||||
|
if (result != HasReturnvaluesIF::RETURN_OK){
|
||||||
|
CommandMessage reply;
|
||||||
|
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
|
||||||
|
queueToUse->sendMessage(commandedBy, &reply);
|
||||||
|
ipcStore->deleteData(dataAddress);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
result = action->handle();
|
||||||
ipcStore->deleteData(dataAddress);
|
ipcStore->deleteData(dataAddress);
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case HasReturnvaluesIF::RETURN_OK:
|
case HasReturnvaluesIF::RETURN_OK:
|
||||||
|
23
src/fsfw/action/TemplateAction.h
Normal file
23
src/fsfw/action/TemplateAction.h
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Action.h"
|
||||||
|
|
||||||
|
template <class owner, class action, class ActionEnum>
|
||||||
|
class TemplateAction : public Action {
|
||||||
|
public:
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
TemplateAction(owner *myOwner, ActionEnum id) : Action(), myOwner(myOwner) {
|
||||||
|
Action::setEnum(&id);
|
||||||
|
myOwner->getActionHelper()->registerAction(this);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
TemplateAction(owner *myOwner, ActionEnum id) : Action((uint32_t) id), myOwner(myOwner) {
|
||||||
|
myOwner->getActionHelper()->registerAction(this);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ReturnValue_t handle() override { return myOwner->handleAction(dynamic_cast<action *>(this)); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
owner *myOwner;
|
||||||
|
};
|
@ -8,9 +8,7 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t
|
|||||||
|
|
||||||
ExtendedControllerBase::~ExtendedControllerBase() {}
|
ExtendedControllerBase::~ExtendedControllerBase() {}
|
||||||
|
|
||||||
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
|
ReturnValue_t ExtendedControllerBase::executeAction(Action *action, MessageQueueId_t commandedBy) {
|
||||||
MessageQueueId_t commandedBy,
|
|
||||||
const uint8_t *data, size_t size) {
|
|
||||||
/* Needs to be overriden and implemented by child class. */
|
/* Needs to be overriden and implemented by child class. */
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
@ -50,8 +50,7 @@ class ExtendedControllerBase : public ControllerBase,
|
|||||||
void handleQueue() override;
|
void handleQueue() override;
|
||||||
|
|
||||||
/* HasActionsIF overrides */
|
/* HasActionsIF overrides */
|
||||||
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
virtual ReturnValue_t executeAction(Action* actionId, MessageQueueId_t commandedBy) override;
|
||||||
const uint8_t* data, size_t size) override;
|
|
||||||
|
|
||||||
/* HasLocalDatapoolIF overrides */
|
/* HasLocalDatapoolIF overrides */
|
||||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||||
|
@ -1316,19 +1316,18 @@ void DeviceHandlerBase::handleDeviceTM(SerializeIF* dataSet, DeviceCommandId_t r
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t DeviceHandlerBase::executeAction(Action *action, MessageQueueId_t commandedBy) {
|
||||||
const uint8_t* data, size_t size) {
|
|
||||||
ReturnValue_t result = acceptExternalDeviceCommands();
|
ReturnValue_t result = acceptExternalDeviceCommands();
|
||||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
|
DeviceCommandMap::iterator iter = deviceCommandMap.find(action->getId());
|
||||||
if (iter == deviceCommandMap.end()) {
|
if (iter == deviceCommandMap.end()) {
|
||||||
result = COMMAND_NOT_SUPPORTED;
|
result = COMMAND_NOT_SUPPORTED;
|
||||||
} else if (iter->second.isExecuting) {
|
} else if (iter->second.isExecuting) {
|
||||||
result = COMMAND_ALREADY_SENT;
|
result = COMMAND_ALREADY_SENT;
|
||||||
} else {
|
} else {
|
||||||
result = buildCommandFromCommand(actionId, data, size);
|
result = action->handle();
|
||||||
}
|
}
|
||||||
if (result == RETURN_OK) {
|
if (result == RETURN_OK) {
|
||||||
iter->second.sendReplyTo = commandedBy;
|
iter->second.sendReplyTo = commandedBy;
|
||||||
|
@ -204,9 +204,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||||||
*/
|
*/
|
||||||
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
virtual void setParentQueue(MessageQueueId_t parentQueueId);
|
||||||
|
|
||||||
/** @brief Implementation required for HasActionIF */
|
/** @brief Implementation required for HasActionIF */
|
||||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ReturnValue_t executeAction(Action *action, MessageQueueId_t commandedBy) override;
|
||||||
const uint8_t *data, size_t size) override;
|
|
||||||
|
|
||||||
Mode_t getTransitionSourceMode() const;
|
Mode_t getTransitionSourceMode() const;
|
||||||
Submode_t getTransitionSourceSubMode() const;
|
Submode_t getTransitionSourceSubMode() const;
|
||||||
|
1
src/fsfw/introspection/CMakeLists.txt
Normal file
1
src/fsfw/introspection/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
target_sources(${LIB_FSFW_NAME} PRIVATE ParameterTypeSelector.cpp)
|
48
src/fsfw/introspection/ClasslessEnum.h
Normal file
48
src/fsfw/introspection/ClasslessEnum.h
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
// TODO ifdef EnumIF, consistent naming of functions arrays and macros (probably enum values and
|
||||||
|
// descriptions)
|
||||||
|
|
||||||
|
#include "EnumIF.h"
|
||||||
|
#include "EnumCommon.h"
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
#define FSFW_CLASSLESS_ENUM(name, type, elements) \
|
||||||
|
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||||
|
\
|
||||||
|
class name : public EnumIF { \
|
||||||
|
public: \
|
||||||
|
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||||
|
name(type value) : value(value) {} \
|
||||||
|
name() : value(-1) {} \
|
||||||
|
name(const name &other) : value(other.value) {} \
|
||||||
|
int64_t getValue() const override { return value; } \
|
||||||
|
operator type() { return value; } \
|
||||||
|
name &operator=(name other) { \
|
||||||
|
value = other.value; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
name &operator=(type value) { \
|
||||||
|
this->value = value; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
CREATE_KEY_ARRAY(elements, type) \
|
||||||
|
VALUE_CHECK(type) \
|
||||||
|
GET_INDEX() \
|
||||||
|
CREATE_DESCRIPTION_ARRAY(elements) \
|
||||||
|
GET_DESCRIPTION_FUNC() \
|
||||||
|
private: \
|
||||||
|
type value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define FSFW_CLASSLESS_ENUM(name, type, elements) \
|
||||||
|
enum name : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) };
|
||||||
|
|
||||||
|
#endif
|
64
src/fsfw/introspection/Enum.h
Normal file
64
src/fsfw/introspection/Enum.h
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <fsfw/returnvalues/HasReturnvaluesIF.h>
|
||||||
|
#include <fsfw/serialize/SerializeAdapter.h>
|
||||||
|
|
||||||
|
#include <boost/preprocessor.hpp>
|
||||||
|
|
||||||
|
// TODO ifdef EnumIF, consistent naming of functions arrays and macros (probably enum values and
|
||||||
|
// descriptions)
|
||||||
|
|
||||||
|
#include "EnumIF.h"
|
||||||
|
#include "EnumCommon.h"
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
#define FSFW_ENUM(name, type, elements) \
|
||||||
|
class name : public EnumIF, public SerializeIF { \
|
||||||
|
public: \
|
||||||
|
enum : type { BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) }; \
|
||||||
|
name(type value) : value(value) {} \
|
||||||
|
name() : value(-1) {} \
|
||||||
|
name(const name &other) : value(other.value) {} \
|
||||||
|
int64_t getValue() const override { return value; } \
|
||||||
|
operator type() { return value; } \
|
||||||
|
name &operator=(name other) { \
|
||||||
|
value = other.value; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
name &operator=(type value) { \
|
||||||
|
this->value = value; \
|
||||||
|
return *this; \
|
||||||
|
} \
|
||||||
|
CREATE_KEY_ARRAY(elements, type) \
|
||||||
|
VALUE_CHECK(type) \
|
||||||
|
GET_INDEX() \
|
||||||
|
CREATE_DESCRIPTION_ARRAY(elements) \
|
||||||
|
GET_DESCRIPTION_FUNC() \
|
||||||
|
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); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
private: \
|
||||||
|
type value; \
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define FSFW_ENUM(name, type, elements) \
|
||||||
|
enum class name : type { \
|
||||||
|
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(CLEAN_ENUM_ITEM, "", elements)) \
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
62
src/fsfw/introspection/EnumCommon.h
Normal file
62
src/fsfw/introspection/EnumCommon.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#define CLEAN_ENUM_ITEM(r, data, element) \
|
||||||
|
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), \
|
||||||
|
(BOOST_PP_TUPLE_ELEM(0, element) = BOOST_PP_TUPLE_ELEM(1, element)), \
|
||||||
|
(BOOST_PP_TUPLE_ELEM(0, element)))
|
||||||
|
|
||||||
|
#if defined FSFW_ENUM_VALUE_CHECKS || defined FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
|
||||||
|
#define GET_KEY(r, data, element) (BOOST_PP_TUPLE_ELEM(0, element))
|
||||||
|
#define GET_DESCRIPTION(r, data, element) \
|
||||||
|
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), (BOOST_PP_TUPLE_ELEM(2, element)), \
|
||||||
|
(BOOST_PP_TUPLE_ELEM(1, element)))
|
||||||
|
|
||||||
|
#define CREATE_KEY_ARRAY(enum_elements, type) \
|
||||||
|
/*was static constexpr, but clang won't compile that*/ \
|
||||||
|
int64_t elements[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))] = { \
|
||||||
|
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))}; \
|
||||||
|
const int64_t *getElements() const override { return elements; } \
|
||||||
|
size_t getSize() const override { \
|
||||||
|
return BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements)); \
|
||||||
|
}
|
||||||
|
#define VALUE_CHECK(type) \
|
||||||
|
bool isValid() const override { \
|
||||||
|
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
|
||||||
|
if (value == elements[i]) { \
|
||||||
|
return true; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
#define CREATE_DESCRIPTION_ARRAY(elements) \
|
||||||
|
/*was static constexpr, but clang won't compile that*/ \
|
||||||
|
const char \
|
||||||
|
*descriptions[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))] = { \
|
||||||
|
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))}; \
|
||||||
|
const char *const *getDescriptions() const override { return descriptions; }
|
||||||
|
#define GET_INDEX() \
|
||||||
|
size_t getIndex(int64_t value) const override { \
|
||||||
|
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
|
||||||
|
if (value == elements[i]) { \
|
||||||
|
return i; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
return -1; \
|
||||||
|
}
|
||||||
|
#define GET_DESCRIPTION_FUNC() \
|
||||||
|
const char *getDescription() const override { \
|
||||||
|
if (getIndex(value) == static_cast<size_t>(-1)) { \
|
||||||
|
return nullptr; \
|
||||||
|
} else { \
|
||||||
|
return descriptions[getIndex(value)]; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#define GET_INDEX()
|
||||||
|
#define CREATE_DESCRIPTION_ARRAY(elements)
|
||||||
|
#define GET_DESCRIPTION_FUNC()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
15
src/fsfw/introspection/EnumIF.h
Normal file
15
src/fsfw/introspection/EnumIF.h
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
class EnumIF {
|
||||||
|
public:
|
||||||
|
virtual int64_t getValue() const = 0;
|
||||||
|
virtual bool isValid() const = 0;
|
||||||
|
virtual size_t getSize() const = 0;
|
||||||
|
virtual size_t getIndex(int64_t value) const = 0;
|
||||||
|
virtual const int64_t *getElements() const = 0;
|
||||||
|
virtual const char *const *getDescriptions() const = 0;
|
||||||
|
virtual const char *getDescription() const = 0;
|
||||||
|
};
|
56
src/fsfw/introspection/ParameterTypeSelector.cpp
Normal file
56
src/fsfw/introspection/ParameterTypeSelector.cpp
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "ParameterTypeSelector.h"
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType() {
|
||||||
|
return Types::UNSUPPORTED;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<uint8_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<int8_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<uint16_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<int16_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<uint32_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<int32_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
// template <>
|
||||||
|
// Types::ParameterType ParameterTypeSelector::getType<uint64_t>() {
|
||||||
|
// return Types::UNSIGNED;
|
||||||
|
// }
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<int64_t>() {
|
||||||
|
return Types::SIGNED;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<float>() {
|
||||||
|
return Types::FLOATING;
|
||||||
|
}
|
||||||
|
template <>
|
||||||
|
Types::ParameterType ParameterTypeSelector::getType<double>() {
|
||||||
|
return Types::FLOATING;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
13
src/fsfw/introspection/ParameterTypeSelector.h
Normal file
13
src/fsfw/introspection/ParameterTypeSelector.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Types.h"
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
|
||||||
|
class ParameterTypeSelector {
|
||||||
|
public:
|
||||||
|
template <typename T>
|
||||||
|
static Types::ParameterType getType();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
8
src/fsfw/introspection/Types.h
Normal file
8
src/fsfw/introspection/Types.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
//maybe call them MIB types as these are the ones exposed to the MIB?
|
||||||
|
// Note: some DBs (Postgress, Mongo) only support signed 64bit integers. To have a common denominator, all integers are int64_t.
|
||||||
|
// As such, ther is no unsigned Type, as there can not be a uint64_t and uint32_t completely fits into int64_t
|
||||||
|
namespace Types {
|
||||||
|
enum ParameterType { SIGNED, FLOATING, ENUM, UNSUPPORTED };
|
||||||
|
} // namespace Types
|
74
src/fsfw/introspection/TypesHelper.h
Normal file
74
src/fsfw/introspection/TypesHelper.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "Enum.h"
|
||||||
|
#include "Types.h"
|
||||||
|
#include "ParameterTypeSelector.h"
|
||||||
|
|
||||||
|
template <bool>
|
||||||
|
class enumHelper;
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class enumHelper<true> {
|
||||||
|
public:
|
||||||
|
static bool isValid(EnumIF *anEnum) { return anEnum->isValid(); }
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
template <typename T>
|
||||||
|
static Types::ParameterType getType() {
|
||||||
|
return Types::ENUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T getMin() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T getMax() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<int64_t> getEnumValues() { return std::vector<int64_t>(); }
|
||||||
|
|
||||||
|
static std::vector<int64_t> getEnumValues(EnumIF *anEnum) {
|
||||||
|
std::vector<int64_t> vector;
|
||||||
|
for (size_t i = 0; i < anEnum->getSize(); i++) {
|
||||||
|
vector.push_back(anEnum->getElements()[i]);
|
||||||
|
}
|
||||||
|
return vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *const *getEnumDescriptions(EnumIF *anEnum) {
|
||||||
|
return anEnum->getDescriptions();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
class enumHelper<false> {
|
||||||
|
public:
|
||||||
|
static bool isValid(void *) { return true; }
|
||||||
|
|
||||||
|
#ifdef FSFW_INTROSPECTION
|
||||||
|
template <typename T>
|
||||||
|
static Types::ParameterType getType() {
|
||||||
|
return ParameterTypeSelector::getType<T>();
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static T getMin() {
|
||||||
|
return std::numeric_limits<T>::lowest();
|
||||||
|
}
|
||||||
|
template <typename T>
|
||||||
|
static T getMax() {
|
||||||
|
return std::numeric_limits<T>::max();
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<int64_t> getEnumValues(void *) { return std::vector<int64_t>(); }
|
||||||
|
|
||||||
|
static const char *const *getEnumDescriptions(void *) { return nullptr; }
|
||||||
|
#endif
|
||||||
|
};
|
@ -9,37 +9,35 @@
|
|||||||
#include "fsfw_tests/unit/mocks/MessageQueueMockBase.h"
|
#include "fsfw_tests/unit/mocks/MessageQueueMockBase.h"
|
||||||
|
|
||||||
TEST_CASE("Action Helper", "[ActionHelper]") {
|
TEST_CASE("Action Helper", "[ActionHelper]") {
|
||||||
ActionHelperOwnerMockBase testDhMock;
|
|
||||||
MessageQueueMockBase testMqMock;
|
MessageQueueMockBase testMqMock;
|
||||||
ActionHelper actionHelper = ActionHelper(&testDhMock, dynamic_cast<MessageQueueIF*>(&testMqMock));
|
ActionHelperOwnerMockBase testDhMock(&testMqMock);
|
||||||
CommandMessage actionMessage;
|
CommandMessage actionMessage;
|
||||||
ActionId_t testActionId = 777;
|
ActionId_t testActionId = (ActionId_t) TestActions::TEST_ACTION;
|
||||||
std::array<uint8_t, 3> testParams{1, 2, 3};
|
std::array<uint8_t, 3> testParams{1, 2, 3};
|
||||||
store_address_t paramAddress;
|
store_address_t paramAddress;
|
||||||
StorageManagerIF* ipcStore = tglob::getIpcStoreHandle();
|
StorageManagerIF* ipcStore = tglob::getIpcStoreHandle();
|
||||||
REQUIRE(ipcStore != nullptr);
|
REQUIRE(ipcStore != nullptr);
|
||||||
ipcStore->addData(¶mAddress, testParams.data(), 3);
|
ipcStore->addData(¶mAddress, testParams.data(), 3);
|
||||||
REQUIRE(actionHelper.initialize() == retval::CATCH_OK);
|
REQUIRE(testDhMock.getActionHelper()->initialize() == retval::CATCH_OK);
|
||||||
|
|
||||||
SECTION("Simple tests") {
|
SECTION("Simple tests") {
|
||||||
ActionMessage::setCommand(&actionMessage, testActionId, paramAddress);
|
ActionMessage::setCommand(&actionMessage, testActionId, paramAddress);
|
||||||
CHECK(not testDhMock.executeActionCalled);
|
CHECK(not testDhMock.executeActionCalled);
|
||||||
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
||||||
CHECK(testDhMock.executeActionCalled);
|
CHECK(testDhMock.executeActionCalled);
|
||||||
// No message is sent if everything is alright.
|
// No message is sent if everything is alright.
|
||||||
CHECK(not testMqMock.wasMessageSent());
|
CHECK(not testMqMock.wasMessageSent());
|
||||||
store_address_t invalidAddress;
|
store_address_t invalidAddress;
|
||||||
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
|
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
|
||||||
actionHelper.handleActionMessage(&actionMessage);
|
testDhMock.getActionHelper()->handleActionMessage(&actionMessage);
|
||||||
CHECK(testMqMock.wasMessageSent());
|
CHECK(testMqMock.wasMessageSent());
|
||||||
const uint8_t* ptr = nullptr;
|
const uint8_t* ptr = nullptr;
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
|
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
|
||||||
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
|
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
|
||||||
REQUIRE(ptr == nullptr);
|
REQUIRE(ptr == nullptr);
|
||||||
REQUIRE(size == 0);
|
testDhMock.getBuffer(&ptr);
|
||||||
testDhMock.getBuffer(&ptr, &size);
|
|
||||||
REQUIRE(size == 3);
|
|
||||||
for (uint8_t i = 0; i < 3; i++) {
|
for (uint8_t i = 0; i < 3; i++) {
|
||||||
REQUIRE(ptr[i] == (i + 1));
|
REQUIRE(ptr[i] == (i + 1));
|
||||||
}
|
}
|
||||||
@ -48,12 +46,12 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
|
|||||||
|
|
||||||
SECTION("Handle failures") {
|
SECTION("Handle failures") {
|
||||||
actionMessage.setCommand(1234);
|
actionMessage.setCommand(1234);
|
||||||
REQUIRE(actionHelper.handleActionMessage(&actionMessage) ==
|
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) ==
|
||||||
static_cast<uint32_t>(CommandMessage::UNKNOWN_COMMAND));
|
static_cast<uint32_t>(CommandMessage::UNKNOWN_COMMAND));
|
||||||
CHECK(not testMqMock.wasMessageSent());
|
CHECK(not testMqMock.wasMessageSent());
|
||||||
uint16_t step = 5;
|
uint16_t step = 5;
|
||||||
ReturnValue_t status = 0x1234;
|
ReturnValue_t status = 0x1234;
|
||||||
actionHelper.step(step, testMqMock.getId(), testActionId, status);
|
testDhMock.getActionHelper()->step(step, testMqMock.getId(), testActionId, status);
|
||||||
step += 1;
|
step += 1;
|
||||||
CHECK(testMqMock.wasMessageSent());
|
CHECK(testMqMock.wasMessageSent());
|
||||||
CommandMessage testMessage;
|
CommandMessage testMessage;
|
||||||
@ -69,7 +67,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
|
|||||||
SECTION("Handle finish") {
|
SECTION("Handle finish") {
|
||||||
CHECK(not testMqMock.wasMessageSent());
|
CHECK(not testMqMock.wasMessageSent());
|
||||||
ReturnValue_t status = 0x9876;
|
ReturnValue_t status = 0x9876;
|
||||||
actionHelper.finish(false, testMqMock.getId(), testActionId, status);
|
testDhMock.getActionHelper()->finish(false, testMqMock.getId(), testActionId, status);
|
||||||
CHECK(testMqMock.wasMessageSent());
|
CHECK(testMqMock.wasMessageSent());
|
||||||
CommandMessage testMessage;
|
CommandMessage testMessage;
|
||||||
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
||||||
@ -85,14 +83,14 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
|
|||||||
REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == retval::CATCH_OK);
|
REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == retval::CATCH_OK);
|
||||||
ActionMessage::setCommand(&actionMessage, testActionId, toLongParamAddress);
|
ActionMessage::setCommand(&actionMessage, testActionId, toLongParamAddress);
|
||||||
CHECK(not testDhMock.executeActionCalled);
|
CHECK(not testDhMock.executeActionCalled);
|
||||||
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
||||||
REQUIRE(ipcStore->getData(toLongParamAddress).first ==
|
REQUIRE(ipcStore->getData(toLongParamAddress).first ==
|
||||||
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
|
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
|
||||||
CommandMessage testMessage;
|
CommandMessage testMessage;
|
||||||
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
||||||
static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
|
static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
|
||||||
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
|
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
|
||||||
REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE);
|
REQUIRE(ActionMessage::getReturnCode(&testMessage) == HasActionsIF::INVALID_PARAMETERS);
|
||||||
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
|
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
|
||||||
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
|
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
|
||||||
}
|
}
|
||||||
@ -100,7 +98,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
|
|||||||
SECTION("Missing IPC Data") {
|
SECTION("Missing IPC Data") {
|
||||||
ActionMessage::setCommand(&actionMessage, testActionId, StorageManagerIF::INVALID_ADDRESS);
|
ActionMessage::setCommand(&actionMessage, testActionId, StorageManagerIF::INVALID_ADDRESS);
|
||||||
CHECK(not testDhMock.executeActionCalled);
|
CHECK(not testDhMock.executeActionCalled);
|
||||||
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == retval::CATCH_OK);
|
||||||
CommandMessage testMessage;
|
CommandMessage testMessage;
|
||||||
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
REQUIRE(testMqMock.receiveMessage(&testMessage) ==
|
||||||
static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
|
static_cast<uint32_t>(HasReturnvaluesIF::RETURN_OK));
|
||||||
|
@ -2,12 +2,27 @@
|
|||||||
#define UNITTEST_HOSTED_TESTACTIONHELPER_H_
|
#define UNITTEST_HOSTED_TESTACTIONHELPER_H_
|
||||||
|
|
||||||
#include <fsfw/action/HasActionsIF.h>
|
#include <fsfw/action/HasActionsIF.h>
|
||||||
|
#include <fsfw/action/Parameter.h>
|
||||||
|
#include <fsfw/action/TemplateAction.h>
|
||||||
|
#include <fsfw/introspection/Enum.h>
|
||||||
#include <fsfw/ipc/MessageQueueIF.h>
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#include "fsfw_tests/unit/CatchDefinitions.h"
|
#include "fsfw_tests/unit/CatchDefinitions.h"
|
||||||
|
|
||||||
|
class ActionHelperOwnerMockBase;
|
||||||
|
|
||||||
|
FSFW_ENUM(TestActions, ActionId_t, ((TEST_ACTION, "Test Action")))
|
||||||
|
|
||||||
|
class TestAction : public TemplateAction < ActionHelperOwnerMockBase, TestAction, TestActions> {
|
||||||
|
public:
|
||||||
|
TestAction(ActionHelperOwnerMockBase* owner) : TemplateAction(owner, TestActions::TEST_ACTION) {}
|
||||||
|
Parameter<uint8_t> p1 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
|
||||||
|
Parameter<uint8_t> p2 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
|
||||||
|
Parameter<uint8_t> p3 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
|
||||||
|
};
|
||||||
|
|
||||||
class ActionHelperOwnerMockBase : public HasActionsIF {
|
class ActionHelperOwnerMockBase : public HasActionsIF {
|
||||||
public:
|
public:
|
||||||
bool getCommandQueueCalled = false;
|
bool getCommandQueueCalled = false;
|
||||||
@ -16,16 +31,26 @@ class ActionHelperOwnerMockBase : public HasActionsIF {
|
|||||||
uint8_t buffer[MAX_SIZE] = {0, 0, 0};
|
uint8_t buffer[MAX_SIZE] = {0, 0, 0};
|
||||||
size_t size = 0;
|
size_t size = 0;
|
||||||
|
|
||||||
|
ActionHelperOwnerMockBase(MessageQueueIF* useThisQueue) : actionHelper(this, useThisQueue) {}
|
||||||
|
|
||||||
MessageQueueId_t getCommandQueue() const override { return tconst::testQueueId; }
|
MessageQueueId_t getCommandQueue() const override { return tconst::testQueueId; }
|
||||||
|
|
||||||
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
|
ActionHelper* getActionHelper() override { return &actionHelper; }
|
||||||
const uint8_t* data, size_t size) override {
|
|
||||||
|
ReturnValue_t executeAction(Action* action, MessageQueueId_t commandedBy) override {
|
||||||
executeActionCalled = true;
|
executeActionCalled = true;
|
||||||
if (size > MAX_SIZE) {
|
if (size > MAX_SIZE) {
|
||||||
return 0xAFFE;
|
return 0xAFFE;
|
||||||
}
|
}
|
||||||
this->size = size;
|
this->size = size;
|
||||||
memcpy(buffer, data, size);
|
return action->handle();
|
||||||
|
}
|
||||||
|
|
||||||
|
ReturnValue_t handleAction(TestAction *action){
|
||||||
|
executeActionCalled = true;
|
||||||
|
buffer[0] = action->p1;
|
||||||
|
buffer[1] = action->p2;
|
||||||
|
buffer[2] = action->p3;
|
||||||
return HasReturnvaluesIF::RETURN_OK;
|
return HasReturnvaluesIF::RETURN_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,14 +61,15 @@ class ActionHelperOwnerMockBase : public HasActionsIF {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void getBuffer(const uint8_t** ptr, size_t* size) {
|
void getBuffer(const uint8_t** ptr) {
|
||||||
if (size != nullptr) {
|
|
||||||
*size = this->size;
|
|
||||||
}
|
|
||||||
if (ptr != nullptr) {
|
if (ptr != nullptr) {
|
||||||
*ptr = buffer;
|
*ptr = buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
ActionHelper actionHelper;
|
||||||
|
TestAction testAction = TestAction(this);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */
|
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */
|
||||||
|
Loading…
Reference in New Issue
Block a user