Compare commits

..

2 Commits

Author SHA1 Message Date
5ff28ff562 remove newline 2022-08-30 16:04:20 +02:00
fcdb90ff0a Merge branch 'mueller/data-wrapper' into mueller/dhb-handle-device-tm 2022-08-30 16:03:15 +02:00
386 changed files with 5406 additions and 9273 deletions

3
.gitignore vendored
View File

@ -10,8 +10,5 @@
.settings
.metadata
# VSCode
.vscode
/build*
/cmake-build*

View File

@ -10,6 +10,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
# [v6.0.0]
## Changes
- Removed `HasReturnvaluesIF` class in favor of `returnvalue` namespace with `OK` and `FAILED`
constants.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/659
## Added
- DHB TM handler `handleDeviceTM` renamed to `handleDeviceTm` and now takes
@ -23,16 +29,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Add new `UnsignedByteField` class
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/660
## Changes
- Removed `HasReturnvaluesIF` class in favor of `returnvalue` namespace with `OK` and `FAILED`
constants.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/659
- Overhaul of the TMTC stack, including various changes and improvements
for other modules
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/655
which also includes a migration guide
# [v5.0.0] 25.07.2022
## Changes
@ -166,6 +162,7 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
- https://gitlab.kitware.com/cmake/cmake/-/issues/21696
Easiest solution for now: Keep this option OFF by default.
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/616
- Linux HAL: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1
- Dedicated Version class and constant `fsfw::FSFW_VERSION` containing version information
inside `fsfw/version.h`
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/559
@ -180,17 +177,6 @@ https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/593
PR: https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/590
- `Subsystem`: New API to add table and sequence entries
## HAL
- SPI: Cache the SPI device in the communication interface. Architecturally, this makes a
lot more sense because each ComIF should be responsible for one SPI bus.
- SPI: Move the empty transfer to update the line polarity to separate function. This means
it is not automatically called when calling the setter function for SPI speed and mode.
The user should call this function after locking the CS mutex if multiple SPI devices with
differing speeds and modes are attached to one bus.
- SPI: Getter functions for SPI speed and mode.
- I2C: Add wiretapping option for I2C. Enabled with `FSFW_HAL_I2C_WIRETAPPING` defined to 1.
## Fixed
- TCP TMTC Server: `MutexGuard` was not created properly in

View File

@ -80,7 +80,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
3
CACHE STRING "Catch2 library major version requirement")
set(FSFW_CATCH2_LIB_VERSION
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.0.0-preview5
CACHE STRING "Catch2 library exact version requirement")
# Keep this off by default for now. See PR:
@ -195,7 +195,7 @@ message(
)
# Check whether the user has already installed ETL first
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} CONFIG QUIET)
find_package(${FSFW_ETL_LIB_NAME} ${FSFW_ETL_LIB_MAJOR_VERSION} QUIET)
# Not installed, so use FetchContent to download and provide etl
if(NOT ${FSFW_ETL_LIB_NAME}_FOUND)
message(
@ -360,8 +360,7 @@ if(NOT FSFW_CONFIG_PATH)
if(NOT FSFW_BUILD_DOCS)
message(
WARNING
"${MSG_PREFIX} Flight Software Framework configuration path FSFW_CONFIG_PATH not set"
)
"${MSG_PREFIX} Flight Software Framework configuration path not set")
message(
WARNING
"${MSG_PREFIX} Setting default configuration from ${DEF_CONF_PATH} ..")

View File

@ -175,7 +175,7 @@ cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..
Then you can generate the documentation using
```sh
cmake --build . -- Sphinx -j
cmake --build . -j
```
You can find the generated documentation inside the `docs/sphinx` folder inside the build

View File

@ -5,21 +5,16 @@ RUN apt-get --yes upgrade
#tzdata is a dependency, won't install otherwise
ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping python3 pip doxygen graphviz
RUN python3 -m pip install sphinx breathe
RUN apt-get --yes install gcc g++ cmake make lcov git valgrind nano iputils-ping
RUN git clone https://github.com/catchorg/Catch2.git && \
cd Catch2 && \
git checkout v3.1.0 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install
cd Catch2 && \
git checkout v3.0.0-preview5 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install
RUN git clone https://github.com/ETLCPP/etl.git && \
cd etl && \
git checkout 20.28.0 && \
cmake -B build . && \
cmake --install build/
#ssh needs a valid user to work
RUN adduser --uid 114 jenkins
cd etl && \
git checkout 20.28.0 && \
cmake -B build . && \
cmake --install build/

View File

@ -1,13 +1,9 @@
pipeline {
environment {
BUILDDIR = 'cmake-build-tests'
DOCDDIR = 'cmake-build-documentation'
BUILDDIR = 'build-tests'
}
agent {
docker {
image 'fsfw-ci:d5'
args '--network host'
}
docker { image 'fsfw-ci:d3'}
}
stages {
stage('Clean') {
@ -43,47 +39,5 @@ pipeline {
}
}
}
stage('Documentation') {
when {
branch 'development'
}
steps {
dir(DOCDDIR) {
sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
sh 'make Sphinx'
sshagent(credentials: ['documentation-buildfix']) {
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/development/*'
sh 'scp -o StrictHostKeyChecking=no -r docs/sphinx/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/development'
}
}
dir(BUILDDIR) {
sshagent(credentials: ['documentation-buildfix']) {
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/coverage/development/*'
sh 'scp -o StrictHostKeyChecking=no -r fsfw-tests_coverage/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/coverage/development'
}
}
}
}
stage('Master Documentation') {
when {
branch 'master'
}
steps {
dir(DOCDDIR) {
sh 'cmake -DFSFW_BUILD_DOCS=ON -DFSFW_OSAL=host ..'
sh 'make Sphinx'
sshagent(credentials: ['documentation-buildfix']) {
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/master/*'
sh 'scp -o StrictHostKeyChecking=no -r docs/sphinx/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/master'
}
}
dir(BUILDDIR) {
sshagent(credentials: ['documentation-buildfix']) {
sh 'ssh -o StrictHostKeyChecking=no buildfix@documentation.intra.irs.uni-stuttgart.de rm -rf /mnt/data/www/html/fsfw/coverage/master/*'
sh 'scp -o StrictHostKeyChecking=no -r fsfw-tests_coverage/* buildfix@documentation.intra.irs.uni-stuttgart.de:/mnt/data/www/html/fsfw/coverage/master'
}
}
}
}
}
}

View File

@ -4,10 +4,6 @@
#include <cstddef>
#include <cstdint>
// It is assumed the user has a subsystem and class ID list in some user header files.
// #include "events/subsystemIdRanges.h"
// #include "returnvalues/classIds.h"
//! Used to determine whether C++ ostreams are used which can increase
//! the binary size significantly. If this is disabled,
//! the C stdio functions can be used alternatively

View File

@ -35,8 +35,8 @@ void Factory::produceFsfwObjects(void) {
}
void Factory::setStaticFrameworkObjectIds() {
PusServiceBase::PUS_DISTRIBUTOR = objects::NO_OBJECT;
PusServiceBase::PACKET_DESTINATION = objects::NO_OBJECT;
PusServiceBase::packetSource = objects::NO_OBJECT;
PusServiceBase::packetDestination = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;

View File

@ -13,7 +13,7 @@ from shutil import which
from typing import List
UNITTEST_FOLDER_NAME = "cmake-build-tests"
UNITTEST_FOLDER_NAME = "build-tests"
DOCS_FOLDER_NAME = "build-docs"

View File

@ -15,7 +15,6 @@ add_subdirectory(globalfunctions)
add_subdirectory(health)
add_subdirectory(housekeeping)
add_subdirectory(internalerror)
add_subdirectory(introspection)
add_subdirectory(ipc)
add_subdirectory(memory)
add_subdirectory(modes)

View File

@ -1,62 +0,0 @@
#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 &parameterList; }
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 != returnvalue::OK) {
return result;
}
for (auto parameter : *getParameters()) {
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
return result;
}
ReturnValue_t Action::deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) {
ReturnValue_t result = returnvalue::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 != returnvalue::OK) {
return result;
}
}
return result;
}

View File

@ -1,50 +0,0 @@
#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();
MessageQueueId_t commandedBy;
[[nodiscard]] 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;
};

View File

@ -57,10 +57,6 @@ void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t co
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
MessageQueueIF const * ActionHelper::getQueue() const {
return queueToUse;
}
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
store_address_t dataAddress) {
const uint8_t* dataPtr = nullptr;
@ -70,29 +66,9 @@ void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t act
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
auto actionIter = actionMap.find(actionId);
if (actionIter == actionMap.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 != returnvalue::OK) or (size != 0)){
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
//TODO call action->check()
action->commandedBy = commandedBy;
result = owner->executeAction(action);
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
@ -187,11 +163,3 @@ ReturnValue_t ActionHelper::reportData(MessageQueueId_t reportTo, ActionId_t rep
}
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; }

View File

@ -1,13 +1,9 @@
#ifndef FSFW_ACTION_ACTIONHELPER_H_
#define FSFW_ACTION_ACTIONHELPER_H_
#include <map>
#include "Action.h"
#include "ActionMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* @brief Action Helper is a helper class which handles action messages
*
@ -102,16 +98,6 @@ class ActionHelper {
*/
void setQueueToUse(MessageQueueIF* queue);
/**
* Needed so templateAction can check if actionHelper was
* contructed already to aid in debuggig a nasty coding error.
*/
MessageQueueIF const * getQueue() const;
void registerAction(Action* action);
std::map<ActionId_t, Action*> const* getActionMap();
protected:
//! Increase of value of this per step
static const uint8_t STEP_OFFSET = 1;
@ -122,8 +108,6 @@ class ActionHelper {
MessageQueueIF* queueToUse;
//! Pointer to an IPC Store, initialized during construction or
StorageManagerIF* ipcStore = nullptr;
//! Map of all implemented Actions
std::map<ActionId_t, Action*> actionMap;
/**
* Internal function called by handleActionMessage

View File

@ -1,3 +1,3 @@
target_sources(
${LIB_FSFW_NAME} PRIVATE Action.cpp ActionHelper.cpp ActionMessage.cpp
${LIB_FSFW_NAME} PRIVATE ActionHelper.cpp ActionMessage.cpp
CommandActionHelper.cpp SimpleActionHelper.cpp)

View File

@ -16,8 +16,8 @@ class CommandActionHelper {
public:
explicit CommandActionHelper(CommandsActionsIF* owner);
virtual ~CommandActionHelper();
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId,
const uint8_t* data = nullptr, uint32_t size = 0);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, const uint8_t* data,
uint32_t size);
ReturnValue_t commandAction(object_id_t commandTo, ActionId_t actionId, SerializeIF* data);
ReturnValue_t initialize();
ReturnValue_t handleReply(CommandMessage* reply);

View File

@ -44,12 +44,8 @@ class HasActionsIF {
/**
* Function to get the MessageQueueId_t of the implementing object
* @return MessageQueueId_t of the object
*
*/
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
[[nodiscard]] virtual ActionHelper* getActionHelper() = 0;
/**
* Execute or initialize the execution of a certain function.
* The ActionHelpers will execute this function and behave differently
@ -59,7 +55,8 @@ class HasActionsIF {
* -@c EXECUTION_FINISHED Finish reply will be generated
* -@c Not returnvalue::OK Step failure reply will be generated
*/
virtual ReturnValue_t executeAction(Action* action) = 0;
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) = 0;
};
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */

View File

@ -1,40 +0,0 @@
#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

View File

@ -1,120 +0,0 @@
#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;
}
Parameter& operator =(const T& newValue){
value = newValue;
return *this;
}
#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) {
return false;
}
this->value = T(value);
return true;
}
bool setSigned(int64_t value) override {
if ((getType() != Types::SIGNED) && (getType() != Types::ENUM)) {
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

View File

@ -1,45 +0,0 @@
#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
};

View File

@ -44,27 +44,11 @@ void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId
if (result != returnvalue::OK) {
ActionMessage::setStepReply(&reply, actionId, 0, result);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
auto actionIter = actionMap.find(actionId);
if (actionIter == actionMap.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 != returnvalue::OK) or (size != 0)) {
CommandMessage reply;
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
queueToUse->sendMessage(commandedBy, &reply);
ipcStore->deleteData(dataAddress);
return;
}
result = action->handle();
lastCommander = commandedBy;
lastAction = actionId;
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
ipcStore->deleteData(dataAddress);
switch (result) {
case returnvalue::OK:

View File

@ -1,29 +0,0 @@
#pragma once
#include "Action.h"
#include "fsfw/serviceinterface/ServiceInterface.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);
if (myOwner->getActionHelper() == nullptr) {
sif::error
<< "TemplateAction::TemplateAction: Action instances need to be created (ie located) after the actionHelper instance."
<< "Program will segfault now..." << std::endl;
}
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;
};

View File

@ -1,25 +1,24 @@
#include "fsfw/cfdp/CfdpHandler.h"
#include "fsfw/cfdp/CFDPHandler.h"
#include "fsfw/cfdp/CfdpMessage.h"
#include "fsfw/cfdp/CFDPMessage.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/storagemanager/storeAddress.h"
#include "fsfw/tmtcservices/AcceptsTelemetryIF.h"
object_id_t CfdpHandler::packetSource = 0;
object_id_t CfdpHandler::packetDestination = 0;
object_id_t CFDPHandler::packetSource = 0;
object_id_t CFDPHandler::packetDestination = 0;
CfdpHandler::CfdpHandler(object_id_t setObjectId, CFDPDistributor* dist)
CFDPHandler::CFDPHandler(object_id_t setObjectId, CFDPDistributor* dist)
: SystemObject(setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
requestQueue = QueueFactory::instance()->createMessageQueue(
CFDP_HANDLER_MAX_RECEPTION, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
requestQueue = QueueFactory::instance()->createMessageQueue(CFDP_HANDLER_MAX_RECEPTION);
distributor = dist;
}
CfdpHandler::~CfdpHandler() = default;
CFDPHandler::~CFDPHandler() {}
ReturnValue_t CfdpHandler::initialize() {
ReturnValue_t CFDPHandler::initialize() {
ReturnValue_t result = SystemObject::initialize();
if (result != returnvalue::OK) {
return result;
@ -28,7 +27,7 @@ ReturnValue_t CfdpHandler::initialize() {
return returnvalue::OK;
}
ReturnValue_t CfdpHandler::handleRequest(store_address_t storeId) {
ReturnValue_t CFDPHandler::handleRequest(store_address_t storeId) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "CFDPHandler::handleRequest" << std::endl;
@ -42,17 +41,17 @@ ReturnValue_t CfdpHandler::handleRequest(store_address_t storeId) {
return returnvalue::OK;
}
ReturnValue_t CfdpHandler::performOperation(uint8_t opCode) {
ReturnValue_t CFDPHandler::performOperation(uint8_t opCode) {
ReturnValue_t status = returnvalue::OK;
CommandMessage currentMessage;
for (status = this->requestQueue->receiveMessage(&currentMessage); status == returnvalue::OK;
status = this->requestQueue->receiveMessage(&currentMessage)) {
store_address_t storeId = CfdpMessage::getStoreId(&currentMessage);
store_address_t storeId = CFDPMessage::getStoreId(&currentMessage);
this->handleRequest(storeId);
}
return returnvalue::OK;
}
uint16_t CfdpHandler::getIdentifier() { return 0; }
uint16_t CFDPHandler::getIdentifier() { return 0; }
MessageQueueId_t CfdpHandler::getRequestQueue() { return this->requestQueue->getId(); }
MessageQueueId_t CFDPHandler::getRequestQueue() { return this->requestQueue->getId(); }

View File

@ -12,15 +12,15 @@ namespace Factory {
void setStaticFrameworkObjectIds();
}
class CfdpHandler : public ExecutableObjectIF, public AcceptsTelecommandsIF, public SystemObject {
class CFDPHandler : public ExecutableObjectIF, public AcceptsTelecommandsIF, public SystemObject {
friend void(Factory::setStaticFrameworkObjectIds)();
public:
CfdpHandler(object_id_t setObjectId, CFDPDistributor* distributor);
CFDPHandler(object_id_t setObjectId, CFDPDistributor* distributor);
/**
* The destructor is empty.
*/
virtual ~CfdpHandler();
virtual ~CFDPHandler();
virtual ReturnValue_t handleRequest(store_address_t storeId);
@ -42,7 +42,7 @@ class CfdpHandler : public ExecutableObjectIF, public AcceptsTelecommandsIF, pub
* The current CFDP packet to be processed.
* It is deleted after handleRequest was executed.
*/
CfdpPacketStored currentPacket;
CFDPPacketStored currentPacket;
static object_id_t packetSource;

View File

@ -0,0 +1,17 @@
#include "CFDPMessage.h"
CFDPMessage::CFDPMessage() {}
CFDPMessage::~CFDPMessage() {}
void CFDPMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
message->setParameter(cfdpPacket.raw);
}
store_address_t CFDPMessage::getStoreId(const CommandMessage *message) {
store_address_t storeAddressCFDPPacket;
storeAddressCFDPPacket = message->getParameter();
return storeAddressCFDPPacket;
}
void CFDPMessage::clear(CommandMessage *message) {}

View File

@ -5,14 +5,14 @@
#include "fsfw/objectmanager/ObjectManagerIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
class CfdpMessage {
class CFDPMessage {
private:
CfdpMessage();
CFDPMessage();
public:
static const uint8_t MESSAGE_ID = messagetypes::CFDP;
virtual ~CfdpMessage();
virtual ~CFDPMessage();
static void setCommand(CommandMessage* message, store_address_t cfdpPacket);
static store_address_t getStoreId(const CommandMessage* message);

View File

@ -1,4 +1,4 @@
target_sources(${LIB_FSFW_NAME} PRIVATE CfdpHandler.cpp CfdpMessage.cpp)
target_sources(${LIB_FSFW_NAME} PRIVATE CFDPHandler.cpp CFDPMessage.cpp)
add_subdirectory(pdu)
add_subdirectory(tlv)

View File

@ -1,17 +0,0 @@
#include "CfdpMessage.h"
CfdpMessage::CfdpMessage() = default;
CfdpMessage::~CfdpMessage() = default;
void CfdpMessage::setCommand(CommandMessage *message, store_address_t cfdpPacket) {
message->setParameter(cfdpPacket.raw);
}
store_address_t CfdpMessage::getStoreId(const CommandMessage *message) {
store_address_t storeId;
storeId = static_cast<store_address_t>(message->getParameter());
return storeId;
}
void CfdpMessage::clear(CommandMessage *message) {}

View File

@ -21,7 +21,7 @@ cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
if (value == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setConstBuffer(value, otherSize);
this->value.setBuffer(value, otherSize);
return *this;
}
@ -70,7 +70,7 @@ ReturnValue_t cfdp::Lv::deSerialize(const uint8_t** buffer, size_t* size,
}
zeroLen = false;
// Zero-copy implementation
value.setConstBuffer(*buffer + 1, lengthField);
value.setBuffer(const_cast<uint8_t*>(*buffer + 1), lengthField);
*buffer += 1 + lengthField;
*size -= 1 + lengthField;
return returnvalue::OK;

View File

@ -75,7 +75,7 @@ ReturnValue_t cfdp::Tlv::deSerialize(const uint8_t **buffer, size_t *size,
}
zeroLen = false;
// Zero-copy implementation
value.setConstBuffer(*buffer + 1, lengthField);
value.setBuffer(const_cast<uint8_t *>(*buffer + 1), lengthField);
*buffer += 1 + lengthField;
*size -= 1 + lengthField;
return returnvalue::OK;
@ -96,7 +96,7 @@ void cfdp::Tlv::setValue(uint8_t *value, size_t len) {
if (len > 0) {
zeroLen = false;
}
this->value.setConstBuffer(value, len);
this->value.setBuffer(value, len);
}
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }

View File

@ -13,9 +13,7 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
submode(SUBMODE_NONE),
modeHelper(this),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
commandQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
}
ControllerBase::~ControllerBase() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }
@ -103,10 +101,6 @@ ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
const ModeHelper * ControllerBase::getModeHelper() const {
return &modeHelper;
}
ReturnValue_t ControllerBase::setHealth(HealthState health) {
switch (health) {
case HEALTHY:

View File

@ -3,7 +3,6 @@
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/introspection/ClasslessEnum.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/modes/ModeHelper.h"
#include "fsfw/objectmanager/SystemObject.h"
@ -21,9 +20,7 @@ class ControllerBase : public HasModesIF,
public ExecutableObjectIF,
public SystemObject {
public:
FSFW_CLASSLESS_ENUM(ControllerModes, Mode_t,
((CONTROLLER_MODE_ON, MODE_ON, "On"))((CONTROLLER_MODE_OFF, MODE_OFF,
"Off"))((MODE_NORMAL, 2, "Normal")))
static const Mode_t MODE_NORMAL = 2;
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override;
@ -42,9 +39,6 @@ class ControllerBase : public HasModesIF,
void setTaskIF(PeriodicTaskIF *task) override;
ReturnValue_t initializeAfterTaskCreation() override;
/** HasModeIF override */
const ModeHelper *getModeHelper() const override;
protected:
/**
* Implemented by child class. Handle command messages which are not

View File

@ -8,12 +8,11 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t
ExtendedControllerBase::~ExtendedControllerBase() = default;
ActionHelper *ExtendedControllerBase::getActionHelper() {
return &actionHelper;
}
ReturnValue_t ExtendedControllerBase::executeAction(Action *action) {
return action->handle();
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) {
/* Needs to be overriden and implemented by child class. */
return returnvalue::OK;
}
object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); }

View File

@ -29,10 +29,6 @@ class ExtendedControllerBase : public ControllerBase,
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
/* HasActionsIF overrides */
ActionHelper* getActionHelper() override;
ReturnValue_t executeAction(Action* actionId) override;
protected:
LocalDataPoolManager poolManager;
ActionHelper actionHelper;
@ -53,6 +49,10 @@ class ExtendedControllerBase : public ControllerBase,
/* Handle the four messages mentioned above */
void handleQueue() override;
/* HasActionsIF overrides */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
/* HasLocalDatapoolIF overrides */
LocalDataPoolManager* getHkManagerHandle() override;
[[nodiscard]] object_id_t getObjectId() const override;

View File

@ -6,7 +6,7 @@
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketReader.h"
#include "fsfw/tmtcpacket/SpacePacketBase.h"
#include "fsfw/tmtcservices/AcceptsTelecommandsIF.h"
#include "fsfw/tmtcservices/TmTcMessage.h"

View File

@ -79,7 +79,8 @@ class HasLocalDataPoolIF {
* @param clearMessage If this is set to true, the pool manager will take care of
* clearing the store automatically
*/
virtual void handleChangedDataset(sid_t sid, store_address_t storeId = store_address_t::invalid(),
virtual void handleChangedDataset(sid_t sid,
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
bool* clearMessage = nullptr) {
if (clearMessage != nullptr) {
*clearMessage = true;
@ -99,7 +100,7 @@ class HasLocalDataPoolIF {
* after the callback.
*/
virtual void handleChangedPoolVariable(gp_id_t gpid,
store_address_t storeId = store_address_t::invalid(),
store_address_t storeId = storeId::INVALID_STORE_ADDRESS,
bool* clearMessage = nullptr) {
if (clearMessage != nullptr) {
*clearMessage = true;

View File

@ -1,5 +1,6 @@
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include <array>
#include <cmath>
#include "fsfw/datapoollocal.h"
@ -14,7 +15,6 @@
#include "internal/HasLocalDpIFManagerAttorney.h"
#include "internal/LocalPoolDataSetAttorney.h"
// TODO: Get rid of this. This should be a constructor argument, not something hardcoded in any way
object_id_t LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING;
LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
@ -57,7 +57,7 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
}
if (defaultHkDestination != objects::NO_OBJECT) {
auto* hkPacketReceiver =
AcceptsHkPacketsIF* hkPacketReceiver =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(defaultHkDestination);
if (hkPacketReceiver != nullptr) {
hkDestinationId = hkPacketReceiver->getHkQueue();
@ -209,9 +209,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
}
/* Prepare and send update snapshot */
timeval now{};
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{};
CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
@ -245,9 +245,9 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& recei
}
/* Prepare and send update snapshot */
timeval now{};
timeval now;
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{};
CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
@ -291,7 +291,12 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updat
void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
MarkChangedIF* toReset) {
for (auto& changeInfo : hkUpdateResetList) {
if (hkUpdateResetList == nullptr) {
/* Config error */
return;
}
HkUpdateResetList& listRef = *hkUpdateResetList;
for (auto& changeInfo : listRef) {
if (changeInfo.dataType != type) {
continue;
}
@ -321,37 +326,38 @@ void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
}
void LocalDataPoolManager::resetHkUpdateResetHelper() {
for (auto& changeInfo : hkUpdateResetList) {
if (hkUpdateResetList == nullptr) {
return;
}
for (auto& changeInfo : *hkUpdateResetList) {
changeInfo.currentUpdateCounter = changeInfo.updateCounter;
}
}
ReturnValue_t LocalDataPoolManager::subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams params) {
return subscribeForPeriodicPacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams params) {
return subscribeForPeriodicPacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase& params) {
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = params.sid;
hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.dataType = DataType::DATA_SET;
if (params.receiver == MessageQueueIF::NO_QUEUE) {
hkReceiver.destinationQueue = hkDestinationId;
} else {
hkReceiver.destinationQueue = params.receiver;
ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
float collectionInterval,
bool isDiagnostics,
object_id_t packetDestination) {
AcceptsHkPacketsIF* hkReceiverObject =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
if (hkReceiverObject == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = sid;
hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval,
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, collectionInterval,
owner->getPeriodicOperationFrequency());
}
@ -359,30 +365,27 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::subscribeForRegularUpdatePacket(
subdp::RegularHkUpdateParams params) {
return subscribeForUpdatePacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForDiagUpdatePacket(
subdp::DiagnosticsHkUpdateParams params) {
return subscribeForUpdatePacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase& params) {
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = params.sid;
hkReceiver.reportingType = ReportingType::UPDATE_HK;
hkReceiver.dataType = DataType::DATA_SET;
if (params.receiver == MessageQueueIF::NO_QUEUE) {
hkReceiver.destinationQueue = hkDestinationId;
} else {
hkReceiver.destinationQueue = params.receiver;
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(sid_t sid, bool isDiagnostics,
bool reportingEnabled,
object_id_t packetDestination) {
AcceptsHkPacketsIF* hkReceiverObject =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(packetDestination);
if (hkReceiverObject == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "subscribeForPeriodicPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = sid;
hkReceiver.reportingType = ReportingType::UPDATE_HK;
hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, params.isDiagnostics());
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
}
hkReceivers.push_back(hkReceiver);
@ -433,7 +436,11 @@ ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessage(
}
void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, DataId dataId) {
for (auto& updateResetStruct : hkUpdateResetList) {
if (hkUpdateResetList == nullptr) {
hkUpdateResetList = new std::vector<struct HkUpdateResetHelper>();
}
for (auto& updateResetStruct : *hkUpdateResetList) {
if (dataType == DataType::DATA_SET) {
if (updateResetStruct.dataId.sid == dataId.sid) {
updateResetStruct.updateCounter++;
@ -457,7 +464,7 @@ void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, D
} else {
hkUpdateResetHelper.dataId.localPoolId = dataId.localPoolId;
}
hkUpdateResetList.push_back(hkUpdateResetHelper);
hkUpdateResetList->push_back(hkUpdateResetHelper);
}
ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* message) {
@ -570,10 +577,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* me
CommandMessage reply;
if (result != returnvalue::OK) {
if (result == WRONG_HK_PACKET_TYPE) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
WRONG_HK_PACKET_TYPE);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
@ -636,7 +639,6 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
/* Error, all destinations invalid */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
destination = hkDestinationId;
}
@ -813,7 +815,9 @@ void LocalDataPoolManager::clearReceiversList() {
/* Clear the vector completely and releases allocated memory. */
HkReceivers().swap(hkReceivers);
/* Also clear the reset helper if it exists */
HkUpdateResetList().swap(hkUpdateResetList);
if (hkUpdateResetList != nullptr) {
HkUpdateResetList().swap(*hkUpdateResetList);
}
}
MutexIF* LocalDataPoolManager::getLocalPoolMutex() { return this->mutex; }
@ -829,8 +833,6 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
errorPrint = "Dataset not found";
} else if (error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found";
} else if (error == WRONG_HK_PACKET_TYPE) {
errorPrint = "Wrong Packet Type";
} else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
@ -875,7 +877,3 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
}
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() { return this; }
void LocalDataPoolManager::setHkDestinationId(MessageQueueId_t hkDestId) {
hkDestinationId = hkDestId;
}

View File

@ -8,7 +8,6 @@
#include "ProvidesDataPoolSubscriptionIF.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolEntry.h"
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/housekeeping/HousekeepingPacketDownlink.h"
#include "fsfw/housekeeping/PeriodicHousekeepingHelper.h"
@ -81,9 +80,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
bool appendValidityBuffer = true);
~LocalDataPoolManager() override;
void setHkDestinationId(MessageQueueId_t hkDestId);
virtual ~LocalDataPoolManager();
/**
* Assigns the queue to use. Make sure to call this in the #initialize
@ -115,6 +112,31 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/
virtual ReturnValue_t performHkOperation();
/**
* @brief Subscribe for the generation of periodic packets.
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
ReturnValue_t subscribeForPeriodicPacket(
sid_t sid, bool enableReporting, float collectionInterval, bool isDiagnostics,
object_id_t packetDestination = defaultHkDestination) override;
/**
* @brief Subscribe for the generation of packets if the dataset
* is marked as changed.
* @details
* This subscription mechanism will generally be used by the data creator.
* @param sid
* @param isDiagnostics
* @param packetDestination
* @return
*/
ReturnValue_t subscribeForUpdatePacket(
sid_t sid, bool reportingEnabled, bool isDiagnostics,
object_id_t packetDestination = defaultHkDestination) override;
/**
* @brief Subscribe for a notification message which will be sent
* if a dataset has changed.
@ -129,7 +151,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* Otherwise, only an notification message is sent.
* @return
*/
ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject,
ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId, object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
@ -147,7 +169,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
* Otherwise, only an notification message is sent.
* @return
*/
ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId,
ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
@ -230,7 +252,7 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/
void clearReceiversList();
[[nodiscard]] object_id_t getCreatorObjectId() const;
object_id_t getCreatorObjectId() const;
/**
* Get the pointer to the mutex. Can be used to lock the data pool
@ -240,17 +262,9 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
*/
MutexIF* getMutexHandle();
LocalDataPoolManager* getPoolManagerHandle() override;
ReturnValue_t subscribeForRegularPeriodicPacket(subdp::RegularHkPeriodicParams params) override;
ReturnValue_t subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams params) override;
ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) override;
ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) override;
virtual LocalDataPoolManager* getPoolManagerHandle() override;
protected:
ReturnValue_t subscribeForPeriodicPacket(subdp::ParamsBase& params);
ReturnValue_t subscribeForUpdatePacket(subdp::ParamsBase& params);
/** Core data structure for the actual pool data */
localpool::DataPool localPoolMap;
/** Every housekeeping data manager has a mutex to protect access
@ -298,8 +312,8 @@ class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public Acces
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
/** This list is used to manage creating multiple update packets and only resetting
the update flag if all of them were created. */
HkUpdateResetList hkUpdateResetList = HkUpdateResetList();
the update flag if all of them were created. Will only be created when needed. */
HkUpdateResetList* hkUpdateResetList = nullptr;
/** This is the map holding the actual data. Should only be initialized
* once ! */

View File

@ -162,7 +162,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
object_id_t getCreatorObjectId();
bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/**
* Returns the current periodic HK generation interval this set
@ -190,6 +189,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* Used for periodic generation.
*/
bool reportingEnabled = false;
void setReportingEnabled(bool enabled);
void initializePeriodicHelper(float collectionInterval, dur_millis_t minimumPeriodicInterval,
uint8_t nonDiagIntervalFactor = 5);

View File

@ -1,90 +1,24 @@
#ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "../ipc/messageQueueDefinitions.h"
#include "../returnvalues/returnvalue.h"
#include "localPoolDefinitions.h"
namespace subdp {
struct ParamsBase {
ParamsBase(sid_t sid, bool enableReporting, float collectionInterval, bool diagnostics)
: sid(sid),
enableReporting(enableReporting),
collectionInterval(collectionInterval),
diagnostics(diagnostics) {}
[[nodiscard]] bool isDiagnostics() const { return diagnostics; }
sid_t sid;
bool enableReporting;
float collectionInterval;
MessageQueueId_t receiver = MessageQueueIF::NO_QUEUE;
protected:
bool diagnostics;
};
struct RegularHkPeriodicParams : public ParamsBase {
RegularHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval)
: ParamsBase(sid, enableReporting, collectionInterval, false) {}
};
struct DiagnosticsHkPeriodicParams : public ParamsBase {
DiagnosticsHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval)
: ParamsBase(sid, enableReporting, collectionInterval, true) {}
};
struct RegularHkUpdateParams : public ParamsBase {
RegularHkUpdateParams(sid_t sid, bool enableReporting)
: ParamsBase(sid, enableReporting, 0.0, false) {}
};
struct DiagnosticsHkUpdateParams : public ParamsBase {
DiagnosticsHkUpdateParams(sid_t sid, bool enableReporting)
: ParamsBase(sid, enableReporting, 0.0, true) {}
};
} // namespace subdp
class ProvidesDataPoolSubscriptionIF {
public:
virtual ~ProvidesDataPoolSubscriptionIF() = default;
virtual ~ProvidesDataPoolSubscriptionIF(){};
/**
* @brief Subscribe for the generation of periodic packets. Used for regular HK packets
* @brief Subscribe for the generation of periodic packets.
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
virtual ReturnValue_t subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams params) = 0;
/**
* @brief Subscribe for the generation of periodic packets. Used for diagnostic packets
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
virtual ReturnValue_t subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams params) = 0;
[[deprecated(
"Please use the new API which takes all arguments as one wrapper "
"struct")]] virtual ReturnValue_t
subscribeForPeriodicPacket(sid_t sid, bool enableReporting, float collectionInterval,
bool isDiagnostics,
object_id_t packetDestination = objects::NO_OBJECT) {
if (isDiagnostics) {
subdp::DiagnosticsHkPeriodicParams params(sid, enableReporting, collectionInterval);
return subscribeForDiagPeriodicPacket(params);
} else {
subdp::RegularHkPeriodicParams params(sid, enableReporting, collectionInterval);
return subscribeForRegularPeriodicPacket(params);
}
}
virtual ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
float collectionInterval, bool isDiagnostics,
object_id_t packetDestination) = 0;
/**
* @brief Subscribe for the generation of packets if the dataset
* is marked as changed.
@ -95,28 +29,9 @@ class ProvidesDataPoolSubscriptionIF {
* @param packetDestination
* @return
*/
virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0;
virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0;
// virtual ReturnValue_t
// subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics) {
// return subscribeForUpdatePacket(sid, reportingEnabled, isDiagnostics, objects::NO_OBJECT);
// }
[[deprecated(
"Please use the new API which takes all arguments as one wrapper "
"struct")]] virtual ReturnValue_t
subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics,
object_id_t packetDestination = objects::NO_OBJECT) {
if (isDiagnostics) {
subdp::DiagnosticsHkUpdateParams params(sid, reportingEnabled);
return subscribeForDiagUpdatePacket(params);
} else {
subdp::RegularHkUpdateParams params(sid, reportingEnabled);
return subscribeForRegularUpdatePacket(params);
}
}
virtual ReturnValue_t subscribeForUpdatePacket(sid_t sid, bool reportingEnabled,
bool isDiagnostics,
object_id_t packetDestination) = 0;
/**
* @brief Subscribe for a notification message which will be sent
* if a dataset has changed.
@ -131,7 +46,8 @@ class ProvidesDataPoolSubscriptionIF {
* Otherwise, only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject,
virtual ReturnValue_t subscribeForSetUpdateMessage(const uint32_t setId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;
/**
@ -148,7 +64,7 @@ class ProvidesDataPoolSubscriptionIF {
* only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId,
virtual ReturnValue_t subscribeForVariableUpdateMessage(const lp_id_t localPoolId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;

View File

@ -26,7 +26,11 @@ void AssemblyBase::performChildOperation() {
void AssemblyBase::startTransition(Mode_t mode, Submode_t submode) {
doStartTransition(mode, submode);
triggerModeHelperEvents(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) {
@ -73,10 +77,9 @@ bool AssemblyBase::handleChildrenChangedHealth() {
}
HealthState healthState = healthHelper.healthTable->getHealth(iter->first);
if (healthState == HasHealthIF::NEEDS_RECOVERY) {
triggerEvent(TRYING_RECOVERY, iter->first, 0);
triggerEvent(TRYING_RECOVERY);
recoveryState = RECOVERY_STARTED;
recoveringDevice = iter;
// The user needs to take care of commanding the children off in commandChildren
doStartTransition(targetMode, targetSubmode);
} else {
triggerEvent(CHILD_CHANGED_HEALTH);
@ -225,9 +228,6 @@ ReturnValue_t AssemblyBase::handleHealthReply(CommandMessage* message) {
bool AssemblyBase::checkAndHandleRecovery() {
switch (recoveryState) {
case RECOVERY_STARTED:
// The recovery was already start in #handleChildrenChangedHealth and we just need
// to wait for an off time period.
// TODO: make time period configurable
recoveryState = RECOVERY_WAIT;
recoveryOffTimer.resetTimer();
return true;
@ -266,11 +266,3 @@ void AssemblyBase::overwriteDeviceHealth(object_id_t objectId, HasHealthIF::Heal
modeHelper.setForced(true);
sendHealthCommand(childrenMap[objectId].commandQueue, EXTERNAL_CONTROL);
}
void AssemblyBase::triggerModeHelperEvents(Mode_t mode, Submode_t submode) {
if (modeHelper.isForced()) {
triggerEvent(FORCING_MODE, mode, submode);
} else {
triggerEvent(CHANGING_MODE, mode, submode);
}
}

View File

@ -12,8 +12,7 @@
* 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. However, it can also be used to
* manage the mode keeping and recovery of non-redundant devices
* 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.
@ -27,9 +26,11 @@
*
* Important:
*
* The implementation must call #registerChild for all commanded children during initialization.
* The implementation must call registerChild(object_id_t child)
* for all commanded children during initialization.
* The implementation must call the initialization function of the base class.
* (This will call the function in SubsystemBase)
*
*/
class AssemblyBase : public SubsystemBase {
public:
@ -46,10 +47,9 @@ class AssemblyBase : public SubsystemBase {
protected:
/**
* Command children to reach [mode,submode] combination. Can be done by setting
* #commandsOutstanding correctly, or using #executeTable. In case of an FDIR recovery,
* the user needs to ensure that the target devices are healthy. If a device is not healthy,
* a recovery might be on-going and the device needs to be commanded to off first.
* Command children to reach [mode,submode] combination
* Can be done by setting #commandsOutstanding correctly,
* or using executeTable()
* @param mode
* @param submode
* @return
@ -120,19 +120,8 @@ class AssemblyBase : public SubsystemBase {
virtual ReturnValue_t handleHealthReply(CommandMessage *message);
/**
* @brief Default periodic handler
* @details
* This is the default periodic handler which will be called by the SubsystemBase
* performOperation. It performs the child transitions or reacts to changed health/mode states
* of children objects
*/
virtual void performChildOperation() override;
virtual void performChildOperation();
/**
* This function handles changed mode or health states of children
* @return
*/
bool handleChildrenChanged();
/**
@ -145,37 +134,12 @@ class AssemblyBase : public SubsystemBase {
bool handleChildrenChangedHealth();
/**
* Core transition handler. The default implementation will only do something if
* #commandsOutstanding is smaller or equal to zero, which means that all mode commands
* from the #doPerformTransition call were executed successfully.
*
* Unless a second step was requested, the function will then use #checkChildrenState to
* determine whether the target mode was reached.
*
* There is some special handling for certain (internal) modes:
* - A second step is necessary. #commandChildren will be performed again
* - The device health was overwritten. #commandChildren will be called
* - A recovery is ongoing. #checkAndHandleRecovery will be called.
*/
virtual void handleChildrenTransition();
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode, uint32_t *msToReachTheMode);
/**
* Calls #doStartTransition and triggers an informative event as well that the mode will
* change
* @param mode
* @param submode
*/
virtual void startTransition(Mode_t mode, Submode_t submode);
/**
* This function starts the transition by setting the internal #targetSubmode and #targetMode
* variables and then calling the #commandChildren function.
* @param mode
* @param submode
*/
virtual void doStartTransition(Mode_t mode, Submode_t submode);
virtual bool isInTransition();
@ -196,7 +160,7 @@ class AssemblyBase : public SubsystemBase {
* Manages recovery of a device
* @return true if recovery is still ongoing, false else.
*/
virtual bool checkAndHandleRecovery();
bool checkAndHandleRecovery();
/**
* Helper method to overwrite health state of one of the children.
@ -204,8 +168,6 @@ class AssemblyBase : public SubsystemBase {
* @param objectId Must be a registered child.
*/
void overwriteDeviceHealth(object_id_t objectId, HasHealthIF::HealthState oldHealth);
void triggerModeHelperEvents(Mode_t mode, Submode_t submode);
};
#endif /* FSFW_DEVICEHANDLERS_ASSEMBLYBASE_H_ */

View File

@ -8,7 +8,6 @@
#include "fsfw/ipc/MessageQueueMessage.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/subsystem/SubsystemBase.h"
@ -40,9 +39,8 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
childTransitionDelay(5000),
transitionSourceMode(_MODE_POWER_DOWN),
transitionSourceSubMode(SUBMODE_NONE) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
cmdQueueSize, MessageQueueMessage::MAX_MESSAGE_SIZE);
insertInCommandMap(RAW_COMMAND_ID);
cookieInfo.state = COOKIE_UNUSED;
cookieInfo.pendingCommand = deviceCommandMap.end();
@ -50,6 +48,9 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
printWarningOrError(sif::OutputTypes::OUT_ERROR, "DeviceHandlerBase", returnvalue::FAILED,
"Invalid cookie");
}
if (this->fdirInstance == nullptr) {
this->fdirInstance = new DeviceHandlerFailureIsolation(setObjectId, defaultFdirParentId);
}
}
void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
@ -127,18 +128,6 @@ ReturnValue_t DeviceHandlerBase::initialize() {
if (result != returnvalue::OK) {
return result;
}
if (this->fdirInstance == nullptr) {
this->fdirInstance =
new DeviceHandlerFailureIsolation(this->getObjectId(), defaultFdirParentId);
}
if (this->parent != objects::NO_OBJECT) {
HasModesIF* modeIF = ObjectManager::instance()->get<HasModesIF>(this->parent);
HasHealthIF* healthIF = ObjectManager::instance()->get<HasHealthIF>(this->parent);
if (modeIF != nullptr and healthIF != nullptr) {
setParentQueue(modeIF->getCommandQueue());
}
}
communicationInterface =
ObjectManager::instance()->get<DeviceCommunicationIF>(deviceCommunicationId);
@ -374,12 +363,13 @@ void DeviceHandlerBase::doStateMachine() {
}
} break;
case _MODE_WAIT_OFF: {
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (powerSwitcher == nullptr) {
setMode(MODE_OFF);
break;
}
uint32_t currentUptime;
Clock::getUptime(&currentUptime);
if (currentUptime - timeoutStart >= powerSwitcher->getSwitchDelayMs()) {
triggerEvent(MODE_TRANSITION_FAILED, PowerSwitchIF::SWITCH_TIMEOUT, 0);
setMode(MODE_ERROR_ON);
@ -580,9 +570,6 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
mode = newMode;
modeChanged();
setNormalDatapoolEntriesInvalid();
if (newMode == MODE_OFF) {
disableCommandsAndReplies();
}
if (!isTransitionalMode()) {
modeHelper.modeChanged(newMode, newSubmode);
announceMode(false);
@ -1270,33 +1257,40 @@ ReturnValue_t DeviceHandlerBase::letChildHandleMessage(CommandMessage* message)
return returnvalue::FAILED;
}
void DeviceHandlerBase::handleDeviceTm(const uint8_t* rawData, size_t rawDataLen,
DeviceCommandId_t replyId, bool forceDirectTm) {
SerialBufferAdapter bufferWrapper(rawData, rawDataLen);
handleDeviceTm(bufferWrapper, replyId, forceDirectTm);
}
void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommandId_t replyId,
void DeviceHandlerBase::handleDeviceTm(util::DataWrapper dataWrapper, DeviceCommandId_t replyId,
bool forceDirectTm) {
if (dataWrapper.isNull()) {
return;
}
auto iter = deviceReplyMap.find(replyId);
if (iter == deviceReplyMap.end()) {
triggerEvent(DEVICE_UNKNOWN_REPLY, replyId);
return;
}
auto reportData = [&](MessageQueueId_t queueId) {
if (dataWrapper.type == util::DataTypes::SERIALIZABLE) {
return actionHelper.reportData(queueId, replyId, dataWrapper.dataUnion.serializable);
} else if (dataWrapper.type == util::DataTypes::RAW) {
return actionHelper.reportData(queueId, replyId, dataWrapper.dataUnion.raw.data,
dataWrapper.dataUnion.raw.len);
}
return returnvalue::FAILED;
};
// Regular replies to a command
if (iter->second.command != deviceCommandMap.end()) {
MessageQueueId_t queueId = iter->second.command->second.sendReplyTo;
// This may fail, but we'll ignore the fault.
if (queueId != NO_COMMANDER) {
// This may fail, but we'll ignore the fault.
actionHelper.reportData(queueId, replyId, const_cast<SerializeIF*>(&dataSet));
reportData(queueId);
}
// This check should make sure we get any TM but don't get anything doubled.
if (wiretappingMode == TM && (requestedRawTraffic != queueId)) {
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataWrapper);
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
}
@ -1305,13 +1299,12 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
// hiding of sender needed so the service will handle it as
// unexpected Data, no matter what state (progress or completed)
// it is in
actionHelper.reportData(defaultRawReceiver, replyId, const_cast<SerializeIF*>(&dataSet),
true);
reportData(defaultRawReceiver);
}
}
// Unrequested or aperiodic replies
else {
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataSet);
DeviceTmReportingWrapper wrapper(getObjectId(), replyId, dataWrapper);
if (wiretappingMode == TM) {
actionHelper.reportData(requestedRawTraffic, replyId, &wrapper);
}
@ -1324,23 +1317,22 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
}
}
ActionHelper* DeviceHandlerBase::getActionHelper() { return &actionHelper; }
ReturnValue_t DeviceHandlerBase::executeAction(Action* action) {
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ReturnValue_t result = acceptExternalDeviceCommands();
if (result != returnvalue::OK) {
return result;
}
DeviceCommandMap::iterator iter = deviceCommandMap.find(action->getId());
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
result = COMMAND_ALREADY_SENT;
} else {
iter->second.sendReplyTo = action->commandedBy;
result = action->handle();
result = buildCommandFromCommand(actionId, data, size);
}
if (result == returnvalue::OK) {
iter->second.sendReplyTo = commandedBy;
iter->second.isExecuting = true;
cookieInfo.pendingCommand = iter;
cookieInfo.state = COOKIE_WRITE_READY;
@ -1468,8 +1460,6 @@ void DeviceHandlerBase::setTaskIF(PeriodicTaskIF* task) { executingTask = task;
void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t objectId,
uint32_t parameter) {}
Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {}
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
@ -1492,7 +1482,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
this->poolManager.initializeAfterTaskCreation();
if (setStartupImmediately) {
startTransition(MODE_ON, getInitialSubmode());
startTransition(MODE_ON, SUBMODE_NONE);
}
return returnvalue::OK;
}
@ -1576,36 +1566,3 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
}
return commandIter->second.sendReplyTo;
}
void DeviceHandlerBase::setCustomFdir(FailureIsolationBase* fdir) { this->fdirInstance = fdir; }
void DeviceHandlerBase::setParent(object_id_t parent) { this->parent = parent; }
void DeviceHandlerBase::setPowerSwitcher(PowerSwitchIF* switcher) {
this->powerSwitcher = switcher;
}
void DeviceHandlerBase::disableCommandsAndReplies() {
for (auto& command : deviceCommandMap) {
if (command.second.isExecuting) {
command.second.isExecuting = false;
}
}
for (auto& reply : deviceReplyMap) {
if (!reply.second.periodic) {
if (reply.second.countdown != nullptr) {
reply.second.countdown->timeOut();
} else {
reply.second.delayCycles = 0;
}
reply.second.active = false;
}
}
}
ModeHelper const* DeviceHandlerBase::getModeHelper() const { return &modeHelper; }
ModeDefinitionHelper DeviceHandlerBase::getModeDefinitionHelper() {
return ModeDefinitionHelper::create<DeviceHandlerMode, DefaultSubmode>();
}

View File

@ -103,9 +103,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
DeviceHandlerBase(object_id_t setObjectId, object_id_t deviceCommunication, CookieIF *comCookie,
FailureIsolationBase *fdirInstance = nullptr, size_t cmdQueueSize = 20);
void setCustomFdir(FailureIsolationBase *fdir);
void setParent(object_id_t parent);
void setPowerSwitcher(PowerSwitchIF *switcher);
void setHkDestination(object_id_t hkDestination);
/**
@ -204,15 +201,13 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
/** @brief Implementations required for HasActionIF */
ActionHelper* getActionHelper() override;
ReturnValue_t executeAction(Action *action) override;
/** @brief Implementation required for HasActionIF */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) override;
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
void getMode(Mode_t *mode, Submode_t *submode) override;
ModeHelper const * getModeHelper() const override;
ModeDefinitionHelper getModeDefinitionHelper() override;
virtual void getMode(Mode_t *mode, Submode_t *submode);
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
@ -316,8 +311,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - Anything else triggers an even with the returnvalue as a parameter
*/
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) = 0;
//TODO Remove and update documentation
/**
* @brief Build a device command packet from data supplied by a direct
* command (PUS Service 8)
@ -344,7 +337,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {return returnvalue::FAILED;}
size_t commandDataLen) = 0;
/* Reply handling */
/**
@ -471,14 +464,14 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @brief This is a helper method to insert replies in the reply map.
* @param deviceCommand Identifier of the reply to add.
* @param maxDelayCycles The maximum number of delay cycles the reply waits
* until it times out.
* until it times out.
* @param periodic Indicates if the command is periodic (i.e. it is sent
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* by the device repeatedly without request) or not. Default is aperiodic (0).
* Please note that periodic replies are disabled by default. You can enable them with
* #updatePeriodicReply
* @param countdown Instead of using maxDelayCycles to timeout a device reply it is also possible
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* to provide a pointer to a Countdown object which will signal the timeout
* when expired
* @return - @c returnvalue::OK when the command was successfully inserted,
* - @c returnvalue::FAILED else.
*/
@ -663,12 +656,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
virtual void debugInterface(uint8_t positionTracker = 0, object_id_t objectId = 0,
uint32_t parameter = 0);
/**
* @brief Can be overwritten by a child to specify the initial submode when device has been set
* to startup immediately.
*/
virtual Submode_t getInitialSubmode();
protected:
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_BASE;
@ -787,18 +774,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* This is used to keep track of pending replies.
*/
struct DeviceReplyInfo {
//! For Command-Reply combinations:
//! The maximum number of cycles the handler should wait for a reply
//! to this command.
//!
//! Reply Only:
//! For periodic replies, this variable will be the number of delay cycles between the replies.
//! For the non-periodic variant, this variable is not used as there is no meaningful
//! definition for delay
uint16_t maxDelayCycles;
//! This variable will be set to #maxDelayCycles if a reply is expected.
//! For non-periodic replies without a command, this variable is unused.
//! A runtime value of 0 means there is no reply is currently expected.
//! The currently remaining cycles the handler should wait for a reply,
//! 0 means there is no reply expected
uint16_t delayCycles;
size_t replyLen = 0; //!< Expected size of the reply.
//! if this is !=0, the delayCycles will not be reset to 0 but to
@ -854,7 +834,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Pointer to the used FDIR instance. If not provided by child,
* default class is instantiated. */
FailureIsolationBase *fdirInstance;
object_id_t parent = objects::NO_OBJECT;
//! To correctly delete the default instance.
bool defaultFDIRUsed;
@ -1074,24 +1053,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
bool isAwaitingReply();
/**
* Wrapper function for @handleDeviceTm which wraps the raw buffer with @SerialBufferAdapter.
* For interpreted data, prefer the other function.
* @param rawData
* @param rawDataLen
* @param replyId
* @param forceDirectTm
*/
void handleDeviceTm(const uint8_t *rawData, size_t rawDataLen, DeviceCommandId_t replyId,
bool forceDirectTm = false);
/**
* Can be used to handle Service 8 data replies. This will also generate the TM wiretapping
* packets accordingly.
* @param dataSet
* @param replyId
* @param forceDirectTm
*/
void handleDeviceTm(const SerializeIF &dataSet, DeviceCommandId_t replyId,
void handleDeviceTm(util::DataWrapper dataWrapper, DeviceCommandId_t replyId,
bool forceDirectTm = false);
virtual ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
@ -1345,11 +1307,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
void printWarningOrError(sif::OutputTypes errorType, const char *functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char *errorPrint = nullptr);
/**
* @brief Disables all commands and replies when device is set to MODE_OFF
*/
void disableCommandsAndReplies();
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -29,7 +29,6 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
switch (event->getEvent()) {
case HasModesIF::MODE_TRANSITION_FAILED:
case HasModesIF::OBJECT_IN_INVALID_MODE:
case DeviceHandlerIF::DEVICE_WANTS_HARD_REBOOT:
// We'll try a recovery as long as defined in MAX_REBOOT.
// Might cause some AssemblyBase cycles, so keep number low.
handleRecovery(event->getEvent());

View File

@ -4,7 +4,6 @@
#include "../action/HasActionsIF.h"
#include "../datapoollocal/localPoolDefinitions.h"
#include "../events/Event.h"
#include "../introspection/ClasslessEnum.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../modes/HasModesIF.h"
#include "DeviceHandlerMessage.h"
@ -38,30 +37,23 @@ class DeviceHandlerIF {
* 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
*/
FSFW_CLASSLESS_ENUM(
DeviceHandlerMode, Mode_t,
//! The device is powered and ready to perform operations. In this mode, no
//! commands are sent by the device handler itself, but direct commands can be
//! commanded and will be executed/forwarded to the device
//! This is an alias of MODE_ON to have the FSFW_ENUM complete for introspection
((DEVICEHANDLER_MODE_ON, HasModesIF::MODE_ON, "On"))
//! The device is powered off. The only command accepted in this
//! mode is a mode change to on.
//! This is an alias of MODE_OFF to have the FSFW_ENUM complete for introspection
((DEVICEHANDLER_MODE_OFF, HasModesIF::MODE_OFF, "Off"))
//! 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.
((MODE_NORMAL, 2, "Normal"))
//! 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 as raw TM
((MODE_RAW, 3, "Raw"))
//! 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.
((MODE_ERROR_ON, 4, "Error")))
// 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.
@ -117,7 +109,6 @@ class DeviceHandlerIF {
static const Event INVALID_DEVICE_COMMAND = MAKE_EVENT(8, severity::LOW);
static const Event MONITORING_LIMIT_EXCEEDED = MAKE_EVENT(9, severity::LOW);
static const Event MONITORING_AMBIGUOUS = MAKE_EVENT(10, severity::HIGH);
static const Event DEVICE_WANTS_HARD_REBOOT = MAKE_EVENT(11, severity::HIGH);
static const uint8_t INTERFACE_ID = CLASS_ID::DEVICE_HANDLER_IF;

View File

@ -3,8 +3,8 @@
#include "fsfw/serialize/SerializeAdapter.h"
DeviceTmReportingWrapper::DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId,
const SerializeIF& data)
: objectId(objectId), actionId(actionId), data(data) {}
util::DataWrapper data)
: objectId(objectId), actionId(actionId), dataWrapper(data) {}
DeviceTmReportingWrapper::~DeviceTmReportingWrapper() = default;
@ -19,11 +19,24 @@ ReturnValue_t DeviceTmReportingWrapper::serialize(uint8_t** buffer, size_t* size
if (result != returnvalue::OK) {
return result;
}
return data.serialize(buffer, size, maxSize, streamEndianness);
if (dataWrapper.isNull()) {
return returnvalue::FAILED;
}
if (dataWrapper.type == util::DataTypes::SERIALIZABLE) {
return dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize, streamEndianness);
} else if (dataWrapper.type == util::DataTypes::RAW) {
if (*size + dataWrapper.dataUnion.raw.len > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
std::memcpy(*buffer, dataWrapper.dataUnion.raw.data, dataWrapper.dataUnion.raw.len);
*buffer += dataWrapper.dataUnion.raw.len;
*size += dataWrapper.dataUnion.raw.len;
}
return returnvalue::OK;
}
size_t DeviceTmReportingWrapper::getSerializedSize() const {
return sizeof(objectId) + sizeof(ActionId_t) + data.getSerializedSize();
return sizeof(objectId) + sizeof(ActionId_t) + dataWrapper.getLength();
}
ReturnValue_t DeviceTmReportingWrapper::deSerialize(const uint8_t** buffer, size_t* size,

View File

@ -8,7 +8,7 @@
class DeviceTmReportingWrapper : public SerializeIF {
public:
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, const SerializeIF& data);
DeviceTmReportingWrapper(object_id_t objectId, ActionId_t actionId, util::DataWrapper data);
~DeviceTmReportingWrapper() override;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
@ -19,7 +19,7 @@ class DeviceTmReportingWrapper : public SerializeIF {
private:
object_id_t objectId;
ActionId_t actionId;
const SerializeIF& data;
util::DataWrapper dataWrapper;
// Deserialization forbidden
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,

View File

@ -8,9 +8,7 @@ HealthDevice::HealthDevice(object_id_t setObjectId, MessageQueueId_t parentQueue
parentQueue(parentQueue),
commandQueue(),
healthHelper(this, setObjectId) {
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
3, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
commandQueue = QueueFactory::instance()->createMessageQueue(3);
}
HealthDevice::~HealthDevice() { QueueFactory::instance()->deleteMessageQueue(commandQueue); }

View File

@ -4,6 +4,8 @@
#include <stdint.h>
#include "fwSubsystemIdRanges.h"
// could be moved to more suitable location
#include <events/subsystemIdRanges.h>
using EventId_t = uint16_t;
using EventSeverity_t = uint8_t;

View File

@ -18,9 +18,8 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
EventManager::EventManager(object_id_t setObjectId)
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
eventReportQueue = QueueFactory::instance()->createMessageQueue(
MAX_EVENTS_PER_CYCLE, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
EventMessage::EVENT_MESSAGE_SIZE);
}
EventManager::~EventManager() {
@ -47,20 +46,9 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
void EventManager::notifyListeners(EventMessage* message) {
lockMutex();
for (auto& listener : listenerList) {
if (listener.second.match(message)) {
ReturnValue_t result =
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
<< result << std::setfill(' ') << std::endl;
#else
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
listener.first, result);
#endif
}
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
if (iter->second.match(message)) {
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
}
}
unlockMutex();
@ -206,19 +194,4 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
}
}
void EventManager::printListeners() {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
for (auto& listener : listenerList) {
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
}
sif::info << std::dec << std::setfill(' ');
#else
sif::printInfo("Event manager listener MQ IDs:\n");
for (auto& listener : listenerList) {
sif::printInfo("0x%08x\n", listener.first);
}
#endif
}
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */

View File

@ -43,7 +43,6 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
bool reporterInverted = false);
ReturnValue_t performOperation(uint8_t opCode);
void printListeners();
protected:
MessageQueueIF* eventReportQueue = nullptr;

View File

@ -9,9 +9,8 @@
FailureIsolationBase::FailureIsolationBase(object_id_t owner, object_id_t parent,
uint8_t messageDepth, uint8_t parameterDomainBase)
: ownerId(owner), faultTreeParent(parent), parameterDomainBase(parameterDomainBase) {
auto mqArgs = MqArgs(owner, static_cast<void*>(this));
eventQueue = QueueFactory::instance()->createMessageQueue(
messageDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
eventQueue =
QueueFactory::instance()->createMessageQueue(messageDepth, EventMessage::EVENT_MESSAGE_SIZE);
}
FailureIsolationBase::~FailureIsolationBase() {
@ -62,12 +61,11 @@ ReturnValue_t FailureIsolationBase::initialize() {
ObjectManager::instance()->get<ConfirmsFailuresIF>(faultTreeParent);
if (parentIF == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "FailureIsolationBase::intialize: Parent object "
<< "invalid" << std::endl;
sif::error << "Make sure it implements ConfirmsFailuresIF" << std::endl;
#else
sif::printError("FailureIsolationBase::intialize: Parent object invalid\n");
sif::printError("Make sure it implements ConfirmsFailuresIF\n");
sif::error << "FailureIsolationBase::intialize: Parent object"
<< "invalid." << std::endl;
#endif
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Make sure it implements ConfirmsFailuresIF." << std::endl;
#endif
return ObjectManagerIF::CHILD_INIT_FAILED;
return returnvalue::FAILED;

View File

@ -12,12 +12,13 @@
class FailureIsolationBase : public ConfirmsFailuresIF, public HasParametersIF {
public:
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::FDIR_1;
//! FDIR has an internal state, which changed from par2 (oldState) to par1 (newState).
static const Event FDIR_CHANGED_STATE = MAKE_EVENT(1, severity::INFO);
//! FDIR tries to restart device. Par1: event that caused recovery.
static const Event FDIR_STARTS_RECOVERY = MAKE_EVENT(2, severity::MEDIUM);
//! FDIR turns off device. Par1: event that caused recovery.
static const Event FDIR_TURNS_OFF_DEVICE = MAKE_EVENT(3, severity::MEDIUM);
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);

View File

@ -4,7 +4,6 @@ target_sources(
AsciiConverter.cpp
CRC.cpp
DleEncoder.cpp
DleParser.cpp
PeriodicOperationDivider.cpp
timevalOperations.cpp
Type.cpp

View File

@ -1,230 +0,0 @@
#include "DleParser.h"
#include <fsfw/serviceinterface/ServiceInterface.h>
#include <cstdio>
DleParser::DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf, UserHandler handler, void* args)
: decodeRingBuf(decodeRingBuf),
decoder(decoder),
encodedBuf(encodedBuf),
decodedBuf(decodedBuf),
handler(handler),
ctx(args) {
if (handler == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "DleParser::DleParser: Invalid user handler" << std::endl;
#else
sif::printError("DleParser::DleParser: Invalid user handler\n");
#endif
}
}
ReturnValue_t DleParser::passData(uint8_t* data, size_t len) {
if (data == nullptr or len == 0 or handler == nullptr) {
return returnvalue::FAILED;
}
size_t copyIntoRingBufFromHere = 0;
size_t copyAmount = len;
size_t startIdx = 0;
ReturnValue_t result = returnvalue::OK;
bool startFoundInThisPacket = false;
for (size_t idx = 0; idx < len; idx++) {
if (data[idx] == DleEncoder::STX_CHAR) {
if (not startFound and not startFoundInThisPacket) {
startIdx = idx;
copyIntoRingBufFromHere = idx;
copyAmount = len - idx;
} else {
// Maybe print warning, should not happen
decodeRingBuf.clear();
ErrorInfo info;
info.len = idx;
prepareErrorContext(ErrorTypes::CONSECUTIVE_STX_CHARS, info);
handler(ctx);
copyIntoRingBufFromHere = idx;
copyAmount = len - idx;
}
startFound = true;
startFoundInThisPacket = true;
} else if (data[idx] == DleEncoder::ETX_CHAR) {
if (startFoundInThisPacket) {
size_t readLen = 0;
size_t decodedLen = 0;
result = decoder.decode(data + startIdx, idx + 1 - startIdx, &readLen, decodedBuf.first,
decodedBuf.second, &decodedLen);
if (result == returnvalue::OK) {
ctx.setType(ContextType::PACKET_FOUND);
ctx.decodedPacket.first = decodedBuf.first;
ctx.decodedPacket.second = decodedLen;
this->handler(ctx);
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
} else {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
}
decodeRingBuf.clear();
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
} else if (startFound) {
// ETX found but STX was found in another mini packet. Reconstruct the full packet
// to decode it
result = decodeRingBuf.writeData(data, idx + 1);
if (result != returnvalue::OK) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
handler(ctx);
}
size_t fullEncodedLen = decodeRingBuf.getAvailableReadData();
if (fullEncodedLen > encodedBuf.second) {
ErrorInfo info;
info.len = fullEncodedLen;
prepareErrorContext(ErrorTypes::ENCODED_BUF_TOO_SMALL, info);
handler(ctx);
decodeRingBuf.clear();
} else {
size_t decodedLen = 0;
size_t readLen = 0;
decodeRingBuf.readData(encodedBuf.first, fullEncodedLen, true);
result = decoder.decode(encodedBuf.first, fullEncodedLen, &readLen, decodedBuf.first,
decodedBuf.second, &decodedLen);
if (result == returnvalue::OK) {
if (this->handler != nullptr) {
ctx.setType(ContextType::PACKET_FOUND);
ctx.decodedPacket.first = decodedBuf.first;
ctx.decodedPacket.second = decodedLen;
this->handler(ctx);
}
} else if (result == DleEncoder::STREAM_TOO_SHORT) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODING_BUF_TOO_SMALL, info);
handler(ctx);
} else {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::DECODE_ERROR, info);
handler(ctx);
}
decodeRingBuf.clear();
startFound = false;
startFoundInThisPacket = false;
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
}
} else {
// End data without preceeding STX
ErrorInfo info;
info.len = idx + 1;
prepareErrorContext(ErrorTypes::CONSECUTIVE_ETX_CHARS, info);
handler(ctx);
decodeRingBuf.clear();
if ((idx + 1) < len) {
copyIntoRingBufFromHere = idx + 1;
copyAmount = len - idx - 1;
} else {
copyAmount = 0;
}
}
startFoundInThisPacket = false;
startFound = false;
}
}
if (copyAmount > 0) {
result = decodeRingBuf.writeData(data + copyIntoRingBufFromHere, copyAmount);
if (result != returnvalue::OK) {
ErrorInfo info;
info.res = result;
prepareErrorContext(ErrorTypes::RING_BUF_ERROR, info);
handler(ctx);
}
}
return returnvalue::OK;
}
void DleParser::defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleFoundPacket: Detected DLE packet with " << len << " bytes"
<< std::endl;
#else
sif::printInfo("DleParserBase::handleFoundPacket: Detected DLE packet with %d bytes\n", len);
#endif
#endif
}
void DleParser::defaultErrorHandler(ErrorTypes err, ErrorInfo ctx) {
switch (err) {
case (ErrorTypes::NONE): {
errorPrinter("No error");
break;
}
case (ErrorTypes::DECODE_ERROR): {
errorPrinter("Decode Error");
break;
}
case (ErrorTypes::RING_BUF_ERROR): {
errorPrinter("Ring Buffer Error");
break;
}
case (ErrorTypes::ENCODED_BUF_TOO_SMALL):
case (ErrorTypes::DECODING_BUF_TOO_SMALL): {
char opt[64];
snprintf(opt, sizeof(opt), ": Too small for packet with length %zu", ctx.len);
if (err == ErrorTypes::ENCODED_BUF_TOO_SMALL) {
errorPrinter("Encoded buf too small", opt);
} else {
errorPrinter("Decoding buf too small", opt);
}
break;
}
case (ErrorTypes::CONSECUTIVE_STX_CHARS): {
errorPrinter("Consecutive STX chars detected");
break;
}
case (ErrorTypes::CONSECUTIVE_ETX_CHARS): {
errorPrinter("Consecutive ETX chars detected");
break;
}
}
}
void DleParser::errorPrinter(const char* str, const char* opt) {
if (opt == nullptr) {
opt = "";
}
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::info << "DleParserBase::handleParseError: " << str << opt << std::endl;
#else
sif::printInfo("DleParserBase::handleParseError: %s%s\n", str, opt);
#endif
#endif
}
void DleParser::prepareErrorContext(ErrorTypes err, ErrorInfo info) {
ctx.setType(ContextType::ERROR);
ctx.error.first = err;
ctx.error.second = info;
}
void DleParser::reset() {
startFound = false;
decodeRingBuf.clear();
}

View File

@ -1,124 +0,0 @@
#pragma once
#include <fsfw/container/SimpleRingBuffer.h>
#include <fsfw/globalfunctions/DleEncoder.h>
#include <fsfw/returnvalues/returnvalue.h>
#include <cstddef>
#include <utility>
/**
* @brief This base helper class can be used to extract DLE encoded packets from a data stream
* @details
* The core API of the parser takes received packets which can contains DLE packets. The parser
* can deal with DLE packets split across multiple packets. It does so by using a dedicated
* decoding ring buffer. The user can process received packets and detect errors by
* overriding two provided virtual methods. This also allows detecting multiple DLE packets
* inside one passed packet.
*/
class DleParser {
public:
using BufPair = std::pair<uint8_t*, size_t>;
enum class ContextType { PACKET_FOUND, ERROR };
enum class ErrorTypes {
NONE,
ENCODED_BUF_TOO_SMALL,
DECODING_BUF_TOO_SMALL,
DECODE_ERROR,
RING_BUF_ERROR,
CONSECUTIVE_STX_CHARS,
CONSECUTIVE_ETX_CHARS
};
union ErrorInfo {
size_t len;
ReturnValue_t res;
};
using ErrorPair = std::pair<ErrorTypes, ErrorInfo>;
struct Context {
public:
Context(void* args) : userArgs(args) { setType(ContextType::PACKET_FOUND); }
void setType(ContextType type) {
if (type == ContextType::PACKET_FOUND) {
error.first = ErrorTypes::NONE;
error.second.len = 0;
} else {
decodedPacket.first = nullptr;
decodedPacket.second = 0;
}
}
ContextType getType() const { return type; }
BufPair decodedPacket = {};
ErrorPair error;
void* userArgs;
private:
ContextType type;
};
using UserHandler = void (*)(const Context& ctx);
/**
* Base class constructor
* @param decodeRingBuf Ring buffer used to store multiple packets to allow detecting DLE packets
* split across multiple packets
* @param decoder Decoder instance
* @param encodedBuf Buffer used to store encoded packets. It has to be large enough to hold
* the largest expected encoded DLE packet size
* @param decodedBuf Buffer used to store decoded packets. It has to be large enough to hold the
* largest expected decoded DLE packet size
* @param handler Function which will be called on a found packet
* @param args Arbitrary user argument
*/
DleParser(SimpleRingBuffer& decodeRingBuf, DleEncoder& decoder, BufPair encodedBuf,
BufPair decodedBuf, UserHandler handler, void* args);
/**
* This function allows to pass new data into the parser. It then scans for DLE packets
* automatically and inserts (part of) the packet into a ring buffer if necessary.
* @param data
* @param len
* @return
*/
ReturnValue_t passData(uint8_t* data, size_t len);
/**
* Example found packet handler
* function call
* @param packet Decoded packet
* @param len Length of detected packet
*/
void defaultFoundPacketHandler(uint8_t* packet, size_t len, void* args);
/**
* Will be called if an error occured in the #passData call
* @param err
* @param ctx Context information depending on the error type
* - For buffer length errors, will be set to the detected packet length which is too large
* - For decode or ring buffer errors, will be set to the result returned from the failed call
*/
static void defaultErrorHandler(ErrorTypes err, ErrorInfo ctx);
static void errorPrinter(const char* str, const char* opt = nullptr);
void prepareErrorContext(ErrorTypes err, ErrorInfo ctx);
/**
* Resets the parser by resetting the internal states and clearing the decoding ring buffer
*/
void reset();
private:
SimpleRingBuffer& decodeRingBuf;
DleEncoder& decoder;
BufPair encodedBuf;
BufPair decodedBuf;
UserHandler handler = nullptr;
Context ctx;
bool startFound = false;
};

View File

@ -16,24 +16,26 @@ class HasHealthIF {
};
static const uint8_t INTERFACE_ID = CLASS_ID::HAS_HEALTH_IF;
static constexpr ReturnValue_t OBJECT_NOT_HEALTHY = returnvalue::makeCode(INTERFACE_ID, 1);
static constexpr ReturnValue_t INVALID_HEALTH_STATE = returnvalue::makeCode(INTERFACE_ID, 2);
static constexpr ReturnValue_t IS_EXTERNALLY_CONTROLLED = returnvalue::makeCode(INTERFACE_ID, 3);
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;
//! P1: New Health, P2: Old Health
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);
//! Assembly overwrites health information of children to keep satellite alive.
static const Event OVERWRITING_HEALTH = MAKE_EVENT(9, severity::LOW);
//! Someone starts a recovery of a component (typically power-cycle). No parameters.
static const Event TRYING_RECOVERY = MAKE_EVENT(10, 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_STEP = MAKE_EVENT(11, severity::MEDIUM);
//! Recovery was completed. Not necessarily successful. No parameters.
static const Event RECOVERY_DONE = MAKE_EVENT(12, severity::MEDIUM);
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;

View File

@ -9,8 +9,8 @@
class HealthTable : public HealthTableIF, public SystemObject {
public:
explicit HealthTable(object_id_t objectid);
~HealthTable() override;
HealthTable(object_id_t objectid);
virtual ~HealthTable();
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);

View File

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

View File

@ -7,13 +7,11 @@
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
: SystemObject(setObjectId),
commandQueue(QueueFactory::instance()->createMessageQueue(messageQueueDepth)),
poolManager(this, commandQueue),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
InternalErrorReporter::~InternalErrorReporter() { MutexFactory::instance()->deleteMutex(mutex); }
@ -38,14 +36,15 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
if ((newQueueHits > 0) or (newTmHits > 0) or (newStoreHits > 0)) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "InternalErrorReporter::performOperation: Errors "
<< "occured: Queue | TM | Store : " << newQueueHits << " | " << newTmHits << " | "
<< newStoreHits << std::endl;
<< "occured!" << std::endl;
sif::debug << "Queue errors: " << newQueueHits << std::endl;
sif::debug << "TM errors: " << newTmHits << std::endl;
sif::debug << "Store errors: " << newStoreHits << std::endl;
#else
sif::printDebug(
"InternalErrorReporter::performOperation: Errors occured: Queue | TM | Store: %lu | %lu "
"| %lu\n",
static_cast<unsigned int>(newQueueHits), static_cast<unsigned int>(newTmHits),
static_cast<unsigned int>(newStoreHits));
sif::printDebug("InternalErrorReporter::performOperation: Errors occured!\n");
sif::printDebug("Queue errors: %lu\n", static_cast<unsigned int>(newQueueHits));
sif::printDebug("TM errors: %lu\n", static_cast<unsigned int>(newTmHits));
sif::printDebug("Store errors: %lu\n", static_cast<unsigned int>(newStoreHits));
#endif
}
}
@ -127,12 +126,11 @@ MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
internalErrorSid, false,
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
localDataPoolMap.emplace(errorPoolIds::TM_HITS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, new PoolEntry<uint32_t>());
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, new PoolEntry<uint32_t>());
poolManager.subscribeForPeriodicPacket(internalErrorSid, false, getPeriodicOperationFrequency(),
true);
internalErrorDataset.setValidity(true, true);
return returnvalue::OK;
}

View File

@ -72,9 +72,6 @@ class InternalErrorReporter : public SystemObject,
uint32_t queueHits = 0;
uint32_t tmHits = 0;
uint32_t storeHits = 0;
PoolEntry<uint32_t> tmHitsEntry = PoolEntry<uint32_t>();
PoolEntry<uint32_t> storeHitsEntry = PoolEntry<uint32_t>();
PoolEntry<uint32_t> queueHitsEntry = PoolEntry<uint32_t>();
uint32_t getAndResetQueueHits();
void incrementQueueHits();

View File

@ -12,7 +12,7 @@
*/
class InternalErrorReporterIF {
public:
virtual ~InternalErrorReporterIF() = default;
virtual ~InternalErrorReporterIF() {}
/**
* @brief Function to be called if a message queue could not be sent.
* @details OSAL Implementations should call this function to indicate that

View File

@ -1 +0,0 @@
target_sources(${LIB_FSFW_NAME} PRIVATE ParameterTypeSelector.cpp)

View File

@ -1,48 +0,0 @@
#pragma once
#include <fsfw/returnvalues/returnvalue.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

View File

@ -1,64 +0,0 @@
#pragma once
#include <fsfw/returnvalues/returnvalue.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

View File

@ -1,62 +0,0 @@
#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

View File

@ -1,16 +0,0 @@
#pragma once
#include <cstddef>
#include <cstdint>
class EnumIF {
public:
virtual ~EnumIF() {}
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;
};

View File

@ -1,56 +0,0 @@
#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

View File

@ -1,13 +0,0 @@
#pragma once
#include "Types.h"
#ifdef FSFW_INTROSPECTION
class ParameterTypeSelector {
public:
template <typename T>
static Types::ParameterType getType();
};
#endif

View File

@ -1,8 +0,0 @@
#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, STRING, BYTEARRAY, UNSUPPORTED };
} // namespace Types

View File

@ -1,74 +0,0 @@
#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
};

View File

@ -34,7 +34,7 @@ class CommandMessageIF {
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,
//! Parameter 1 should contain the error code
//! par1 should contain the error code
static const Command_t REPLY_REJECTED = MAKE_COMMAND_ID(2);
virtual ~CommandMessageIF(){};

View File

@ -8,7 +8,7 @@ MessageQueueBase::MessageQueueBase(MessageQueueId_t id, MessageQueueId_t default
}
}
MessageQueueBase::~MessageQueueBase() = default;
MessageQueueBase::~MessageQueueBase() {}
ReturnValue_t MessageQueueBase::sendToDefault(MessageQueueMessageIF* message) {
return sendToDefaultFrom(message, this->getId(), false);

View File

@ -7,28 +7,28 @@
class MessageQueueBase : public MessageQueueIF {
public:
MessageQueueBase(MessageQueueId_t id, MessageQueueId_t defaultDest, MqArgs* mqArgs);
~MessageQueueBase() override;
virtual ~MessageQueueBase();
// Default implementations for MessageQueueIF where possible
[[nodiscard]] MessageQueueId_t getLastPartner() const override;
[[nodiscard]] MessageQueueId_t getId() const override;
MqArgs& getMqArgs() override;
void setDefaultDestination(MessageQueueId_t defaultDestination) override;
[[nodiscard]] MessageQueueId_t getDefaultDestination() const override;
[[nodiscard]] bool isDefaultDestinationSet() const override;
ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override;
ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
ReturnValue_t reply(MessageQueueMessageIF* message) override;
ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
virtual MessageQueueId_t getLastPartner() const override;
virtual MessageQueueId_t getId() const override;
virtual MqArgs& getMqArgs() override;
virtual void setDefaultDestination(MessageQueueId_t defaultDestination) override;
virtual MessageQueueId_t getDefaultDestination() const override;
virtual bool isDefaultDestinationSet() const override;
virtual ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
bool ignoreFault) override;
virtual ReturnValue_t sendToDefault(MessageQueueMessageIF* message) override;
virtual ReturnValue_t reply(MessageQueueMessageIF* message) override;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message,
MessageQueueId_t* receivedFrom) override;
virtual ReturnValue_t sendToDefaultFrom(MessageQueueMessageIF* message, MessageQueueId_t sentFrom,
bool ignoreFault = false) override;
// OSAL specific, forward the abstract function
ReturnValue_t receiveMessage(MessageQueueMessageIF* message) override = 0;
ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) override = 0;
virtual ReturnValue_t receiveMessage(MessageQueueMessageIF* message) = 0;
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault = false) = 0;
protected:
MessageQueueId_t id = MessageQueueIF::NO_QUEUE;

View File

@ -30,7 +30,7 @@ class MessageQueueIF {
//! [EXPORT] : [COMMENT] Returned if the target destination is invalid.
static constexpr ReturnValue_t DESTINATION_INVALID = MAKE_RETURN_CODE(4);
virtual ~MessageQueueIF() = default;
virtual ~MessageQueueIF() {}
/**
* @brief This operation sends a message to the last communication partner.
* @details
@ -82,11 +82,11 @@ class MessageQueueIF {
/**
* @brief This method returns the message queue ID of the last communication partner.
*/
[[nodiscard]] virtual MessageQueueId_t getLastPartner() const = 0;
virtual MessageQueueId_t getLastPartner() const = 0;
/**
* @brief This method returns the message queue ID of this class's message queue.
*/
[[nodiscard]] virtual MessageQueueId_t getId() const = 0;
virtual MessageQueueId_t getId() const = 0;
/**
* @brief With the sendMessage call, a queue message is sent to a receiving queue.
@ -159,9 +159,9 @@ class MessageQueueIF {
/**
* @brief This method is a simple getter for the default destination.
*/
[[nodiscard]] virtual MessageQueueId_t getDefaultDestination() const = 0;
virtual MessageQueueId_t getDefaultDestination() const = 0;
[[nodiscard]] virtual bool isDefaultDestinationSet() const = 0;
virtual bool isDefaultDestinationSet() const = 0;
virtual MqArgs& getMqArgs() = 0;
};

View File

@ -10,10 +10,10 @@ MessageQueueMessage::MessageQueueMessage() : messageSize(getMinimumMessageSize()
}
MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size)
: messageSize(MessageQueueMessage::HEADER_SIZE + size) {
if (size <= MessageQueueMessage::MAX_DATA_SIZE) {
std::memcpy(MessageQueueMessage::getData(), data, size);
this->messageSize = MessageQueueMessage::HEADER_SIZE + size;
: messageSize(this->HEADER_SIZE + size) {
if (size <= this->MAX_DATA_SIZE) {
memcpy(this->getData(), data, size);
this->messageSize = this->HEADER_SIZE + size;
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "MessageQueueMessage: Passed size larger than maximum"
@ -21,23 +21,21 @@ MessageQueueMessage::MessageQueueMessage(uint8_t* data, size_t size)
<< std::endl;
#endif
memset(this->internalBuffer, 0, sizeof(this->internalBuffer));
this->messageSize = MessageQueueMessage::HEADER_SIZE;
this->messageSize = this->HEADER_SIZE;
}
}
MessageQueueMessage::~MessageQueueMessage() = default;
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 + MessageQueueMessage::HEADER_SIZE;
return this->internalBuffer + this->HEADER_SIZE;
}
uint8_t* MessageQueueMessage::getData() {
return this->internalBuffer + MessageQueueMessage::HEADER_SIZE;
}
uint8_t* MessageQueueMessage::getData() { return this->internalBuffer + this->HEADER_SIZE; }
MessageQueueId_t MessageQueueMessage::getSender() const {
MessageQueueId_t temp_id;
@ -60,22 +58,14 @@ void MessageQueueMessage::print(bool printWholeMessage) {
}
}
void MessageQueueMessage::clear() {
memset(this->getBuffer(), 0, MessageQueueMessage::MAX_MESSAGE_SIZE);
}
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_; }
void MessageQueueMessage::setMessageSize(size_t messageSize) { this->messageSize = messageSize; }
size_t MessageQueueMessage::getMinimumMessageSize() const {
return MessageQueueMessage::MIN_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMinimumMessageSize() const { return this->MIN_MESSAGE_SIZE; }
size_t MessageQueueMessage::getMaximumMessageSize() const {
return MessageQueueMessage::MAX_MESSAGE_SIZE;
}
size_t MessageQueueMessage::getMaximumMessageSize() const { return this->MAX_MESSAGE_SIZE; }
size_t MessageQueueMessage::getMaximumDataSize() const {
return MessageQueueMessage::MAX_DATA_SIZE;
}
size_t MessageQueueMessage::getMaximumDataSize() const { return this->MAX_DATA_SIZE; }

View File

@ -25,30 +25,6 @@
*/
class MessageQueueMessage : public MessageQueueMessageIF {
public:
/**
* @brief This constant defines the maximum size of the data content,
* excluding the header.
* @details
* It may be changed if necessary, but in general should be kept
* as small as possible.
*/
static const size_t MAX_DATA_SIZE = 24;
/**
* @brief This constant defines the maximum total size in bytes
* of a sent message.
* @details
* It is the sum of the maximum data and the header size. Be aware that
* this constant is used to define the buffer sizes for every message
* queue in the system. So, a change here may have significant impact on
* the required resources.
*/
static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
/**
* @brief Defines the minimum size of a message where only the
* header is included
*/
static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE;
/**
* @brief The class is initialized empty with this constructor.
* @details
@ -74,12 +50,59 @@ class MessageQueueMessage : public MessageQueueMessageIF {
* @brief As no memory is allocated in this class,
* the destructor is empty.
*/
~MessageQueueMessage() override;
virtual ~MessageQueueMessage();
/**
* @brief The size information of each message is stored in
* this attribute.
* @details
* It is public to simplify usage and to allow for passing the size
* address as a pointer. Care must be taken when inheriting from this class,
* as every child class is responsible for managing the size information by
* itself. When using the class to receive a message, the size information
* is updated automatically.
*
* Please note that the minimum size is limited by the size of the header
* while the maximum size is limited by the maximum allowed message size.
*/
size_t messageSize;
/**
* @brief This constant defines the maximum size of the data content,
* excluding the header.
* @details
* It may be changed if necessary, but in general should be kept
* as small as possible.
*/
static const size_t MAX_DATA_SIZE = 24;
/**
* @brief This constant defines the maximum total size in bytes
* of a sent message.
* @details
* It is the sum of the maximum data and the header size. Be aware that
* this constant is used to define the buffer sizes for every message
* queue in the system. So, a change here may have significant impact on
* the required resources.
*/
static constexpr size_t MAX_MESSAGE_SIZE = MAX_DATA_SIZE + HEADER_SIZE;
/**
* @brief Defines the minimum size of a message where only the
* header is included
*/
static constexpr size_t MIN_MESSAGE_SIZE = HEADER_SIZE;
private:
/**
* @brief This is the internal buffer that contains the
* actual message data.
*/
uint8_t internalBuffer[MAX_MESSAGE_SIZE];
public:
/**
* @brief This method is used to get the complete data of the message.
*/
[[nodiscard]] const uint8_t* getBuffer() const override;
const uint8_t* getBuffer() const override;
/**
* @brief This method is used to get the complete data of the message.
*/
@ -89,7 +112,7 @@ class MessageQueueMessage : public MessageQueueMessageIF {
* @details
* It shall be used by child classes to add data at the right position.
*/
[[nodiscard]] const uint8_t* getData() const override;
const uint8_t* getData() const override;
/**
* @brief This method is used to fetch the data content of the message.
* @details
@ -100,7 +123,7 @@ class MessageQueueMessage : public MessageQueueMessageIF {
* @brief This method is used to extract the sender's message
* queue id information from a received message.
*/
[[nodiscard]] MessageQueueId_t getSender() const override;
MessageQueueId_t getSender() const override;
/**
* @brief With this method, the whole content
* and the message size is set to zero.
@ -115,40 +138,16 @@ class MessageQueueMessage : public MessageQueueMessageIF {
*/
void setSender(MessageQueueId_t setId) override;
[[nodiscard]] size_t getMessageSize() const override;
void setMessageSize(size_t messageSize) override;
[[nodiscard]] size_t getMinimumMessageSize() const override;
[[nodiscard]] size_t getMaximumMessageSize() const override;
[[nodiscard]] size_t getMaximumDataSize() const override;
virtual size_t getMessageSize() const override;
virtual void setMessageSize(size_t messageSize) override;
virtual size_t getMinimumMessageSize() const override;
virtual size_t getMaximumMessageSize() const override;
virtual size_t getMaximumDataSize() const override;
/**
* @brief This is a debug method that prints the content.
*/
void print(bool printWholeMessage);
/**
* TODO: This really should not be public. If it should be possible to pass size address as a
* pointer, add a getter function returning a const reference to the size
* @brief The size information of each message is stored in
* this attribute.
* @details
* It is public to simplify usage and to allow for passing the size
* address as a pointer. Care must be taken when inheriting from this class,
* as every child class is responsible for managing the size information by
* itself. When using the class to receive a message, the size information
* is updated automatically.
*
* Please note that the minimum size is limited by the size of the header
* while the maximum size is limited by the maximum allowed message size.
*/
size_t messageSize;
private:
/**
* @brief This is the internal buffer that contains the
* actual message data.
*/
uint8_t internalBuffer[MAX_MESSAGE_SIZE] = {};
};
#endif /* FSFW_IPC_MESSAGEQUEUEMESSAGE_H_ */

View File

@ -14,7 +14,7 @@ class MessageQueueMessageIF {
*/
static const size_t HEADER_SIZE = sizeof(MessageQueueId_t);
virtual ~MessageQueueMessageIF() = default;
virtual ~MessageQueueMessageIF(){};
/**
* @brief With this method, the whole content and the message
@ -29,7 +29,7 @@ class MessageQueueMessageIF {
* @brief Get read-only pointer to the complete data of the message.
* @return
*/
[[nodiscard]] virtual const uint8_t* getBuffer() const = 0;
virtual const uint8_t* getBuffer() const = 0;
/**
* @brief This method is used to get the complete data of the message.
@ -48,14 +48,14 @@ class MessageQueueMessageIF {
* @brief This method is used to extract the sender's message queue id
* information from a received message.
*/
[[nodiscard]] virtual MessageQueueId_t getSender() const = 0;
virtual MessageQueueId_t getSender() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
* It shall be used by child classes to add data at the right position.
*/
[[nodiscard]] virtual const uint8_t* getData() const = 0;
virtual const uint8_t* getData() const = 0;
/**
* @brief This method is used to fetch the data content of the message.
* @details
@ -67,28 +67,12 @@ class MessageQueueMessageIF {
* Get constant message size of current message implementation.
* @return
*/
[[nodiscard]] virtual size_t getMessageSize() const = 0;
virtual size_t getMessageSize() const = 0;
/**
* Sets the current message size of a given message
* @param messageSize
*/
virtual void setMessageSize(size_t messageSize) = 0;
/**
* Returns the smallest possible message size, including any headers
* @return
*/
[[nodiscard]] virtual size_t getMinimumMessageSize() const = 0;
/**
* Returns the largest possible message size, including any headers
* @return
*/
[[nodiscard]] virtual size_t getMaximumMessageSize() const = 0;
/**
* Returns the largest possible data size without any headers
* @return
*/
[[nodiscard]] virtual size_t getMaximumDataSize() const = 0;
virtual size_t getMinimumMessageSize() const = 0;
virtual size_t getMaximumMessageSize() const = 0;
virtual size_t getMaximumDataSize() const = 0;
};
#endif /* FRAMEWORK_IPC_MESSAGEQUEUEMESSAGEIF_H_ */

View File

@ -1,14 +1,14 @@
#ifndef FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#define FSFW_IPC_MESSAGEQUEUESENDERIF_H_
#include "../objectmanager/ObjectManagerIF.h"
#include "MessageQueueIF.h"
#include "MessageQueueMessageIF.h"
#include "fsfw/objectmanager/ObjectManagerIF.h"
class MessageQueueSenderIF {
public:
virtual ~MessageQueueSenderIF() = default;
MessageQueueSenderIF() = delete;
virtual ~MessageQueueSenderIF() {}
/**
* Allows sending messages without actually "owning" a message queue.
* Not sure whether this is actually a good idea.
@ -16,6 +16,9 @@ class MessageQueueSenderIF {
static ReturnValue_t sendMessage(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
MessageQueueId_t sentFrom = MessageQueueIF::NO_QUEUE,
bool ignoreFault = false);
private:
MessageQueueSenderIF() {}
};
#endif /* FSFW_IPC_MESSAGEQUEUESENDERIF_H_ */

View File

@ -4,9 +4,7 @@
#include <cstdint>
#include "../events/Event.h"
#include "../introspection/ClasslessEnum.h"
#include "../returnvalues/returnvalue.h"
#include "ModeDefinitionHelper.h"
#include "ModeHelper.h"
#include "ModeMessage.h"
@ -21,39 +19,35 @@ class HasModesIF {
static const ReturnValue_t INVALID_SUBMODE = MAKE_RETURN_CODE(0x04);
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::SYSTEM_MANAGER;
//! An object announces changing the mode. p1: target mode. p2: target submode
static const Event CHANGING_MODE = MAKE_EVENT(0, severity::INFO);
//! An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event MODE_INFO = MAKE_EVENT(1, severity::INFO);
static const Event CHANGING_MODE =
MAKE_EVENT(0, severity::INFO); //!< An object announces changing the mode. p1: target mode.
//!< p2: target submode
static const Event MODE_INFO = MAKE_EVENT(
1,
severity::INFO); //!< An Object announces its mode; parameter1 is mode, parameter2 is submode
static const Event FALLBACK_FAILED = MAKE_EVENT(2, severity::HIGH);
static const Event MODE_TRANSITION_FAILED = MAKE_EVENT(3, severity::LOW);
static const Event CANT_KEEP_MODE = MAKE_EVENT(4, severity::HIGH);
//! Indicates a bug or configuration failure: Object is in a mode it should never be in.
static const Event OBJECT_IN_INVALID_MODE = MAKE_EVENT(5, severity::LOW);
//! The mode is changed, but for some reason, the change is forced, i.e. EXTERNAL_CONTROL ignored.
//! p1: target mode. p2: target submode
static const Event FORCING_MODE = MAKE_EVENT(6, severity::MEDIUM);
//! A mode command was rejected by the called object. Par1: called object id, Par2: return code.
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
static const Event OBJECT_IN_INVALID_MODE =
MAKE_EVENT(5, severity::LOW); //!< Indicates a bug or configuration failure: Object is in a
//!< mode it should never be in.
static const Event FORCING_MODE = MAKE_EVENT(
6, severity::MEDIUM); //!< The mode is changed, but for some reason, the change is forced,
//!< i.e. EXTERNAL_CONTROL ignored. p1: target mode. p2: target submode
static const Event MODE_CMD_REJECTED =
MAKE_EVENT(7, severity::LOW); //!< A mode command was rejected by the called object. Par1:
//!< called object id, Par2: return code.
//! The device is powered and ready to perform operations. In this mode, no commands are
//! sent by the device handler itself, but direct commands can be commanded and will be
//! interpreted
static constexpr Mode_t MODE_ON = 1;
//! The device is powered off. The only command accepted in this mode is a mode change to on.
static constexpr Mode_t MODE_OFF = 0;
static constexpr Mode_t MODE_INVALID = -1;
static constexpr Mode_t MODE_UNDEFINED = -2;
FSFW_CLASSLESS_ENUM(DefaultSubmode, Submode_t,
((SUBMODE_NONE, 0,
"Default"))) //!< To avoid checks against magic number "0".
static const Mode_t MODE_ON =
1; //!< 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
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
//!< this mode is a mode change to on.
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
virtual ~HasModesIF() {}
virtual MessageQueueId_t getCommandQueue() const = 0;
virtual const ModeHelper * getModeHelper() const = 0;
virtual ModeDefinitionHelper getModeDefinitionHelper() = 0;
virtual void getMode(Mode_t *mode, Submode_t *submode) = 0;
protected:

View File

@ -1,33 +0,0 @@
#pragma once
#include <fsfw/introspection/EnumIF.h>
class ModeDefinitionHelper {
public:
#ifdef FSFW_INTROSPECTION
ModeDefinitionHelper(EnumIF *mode, EnumIF *submode) : mode(mode), submode(submode) {}
#else
ModeDefinitionHelper(void *mode, void *submode) {};
#endif
template <typename Mode, typename Submode>
static ModeDefinitionHelper create() {
#ifdef FSFW_INTROSPECTION
EnumIF *mode = new Mode();
EnumIF *submode = new Submode();
return ModeDefinitionHelper(mode, submode);
#else
return ModeDefinitionHelper(nullptr, nullptr);
#endif
}
void free() {
#ifdef FSFW_INTROSPECTION
delete mode;
delete submode;
#endif
}
#ifdef FSFW_INTROSPECTION
EnumIF *mode;
EnumIF *submode;
#endif
};

View File

@ -4,7 +4,7 @@
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
ModeHelper::ModeHelper(HasModesIF *owner)
ModeHelper::ModeHelper(HasModesIF* owner)
: commandedMode(HasModesIF::MODE_OFF),
commandedSubmode(HasModesIF::SUBMODE_NONE),
owner(owner),
@ -12,7 +12,7 @@ ModeHelper::ModeHelper(HasModesIF *owner)
ModeHelper::~ModeHelper() {}
ReturnValue_t ModeHelper::handleModeCommand(CommandMessage *command) {
ReturnValue_t ModeHelper::handleModeCommand(CommandMessage* command) {
CommandMessage reply;
Mode_t mode;
Submode_t submode;
@ -106,33 +106,3 @@ bool ModeHelper::isTimedOut() { return countdown.hasTimedOut(); }
bool ModeHelper::isForced() { return forced; }
void ModeHelper::setForced(bool forced) { this->forced = forced; }
#ifdef FSFW_INTROSPECTION
std::vector<std::pair<Mode_t, const char *>> ModeHelper::getModes() const {
std::vector<std::pair<Mode_t, const char *>> modeVector;
auto modeDefinitionHelper = owner->getModeDefinitionHelper();
EnumIF *mode = modeDefinitionHelper.mode;
for (size_t i = 0; i < mode->getSize(); i++) {
modeVector.push_back(
std::pair<Mode_t, const char *>(mode->getElements()[i], mode->getDescriptions()[i]));
}
modeDefinitionHelper.free();
return modeVector;
}
std::vector<std::pair<Submode_t, const char *>> ModeHelper::getSubmodes(Mode_t mode) const {
auto modeDefinitionHelper = owner->getModeDefinitionHelper();
EnumIF *submode = modeDefinitionHelper.submode;
std::vector<std::pair<Submode_t, const char *>> submodeVector;
for (size_t i = 0; i < submode->getSize(); i++) {
uint32_t ignored;
if (owner->checkModeCommand(mode, submode->getElements()[i], &ignored) ==
HasReturnvaluesIF::RETURN_OK) {
submodeVector.push_back(std::pair<Submode_t, const char *>(submode->getElements()[i],
submode->getDescriptions()[i]));
}
}
modeDefinitionHelper.free();
return submodeVector;
}
#endif

View File

@ -1,8 +1,6 @@
#ifndef FSFW_MODES_MODEHELPER_H_
#define FSFW_MODES_MODEHELPER_H_
#include <vector>
#include "ModeMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/returnvalues/returnvalue.h"
@ -41,12 +39,6 @@ class ModeHelper {
void setForced(bool forced);
#ifdef FSFW_INTROSPECTION
std::vector<std::pair<Mode_t, const char *>> getModes() const;
std::vector<std::pair<Submode_t, const char *>> getSubmodes(Mode_t mode) const;
#endif
protected:
HasModesIF *owner;
MessageQueueId_t parentQueueId = MessageQueueIF::NO_QUEUE;

View File

@ -8,7 +8,7 @@
#include "../serialize/SerialLinkedListAdapter.h"
#include "../serialize/SerializeElement.h"
#include "../serviceinterface/ServiceInterface.h"
#include "../timemanager/TimeWriterIF.h"
#include "../timemanager/TimeStamperIF.h"
#include "HasMonitorsIF.h"
#include "MonitoringIF.h"
#include "monitoringConf.h"
@ -34,9 +34,9 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
SerializeElement<T> limitValue;
SerializeElement<ReturnValue_t> oldState;
SerializeElement<ReturnValue_t> newState;
uint8_t rawTimestamp[TimeWriterIF::MAXIMUM_TIMESTAMP_LEN] = {};
uint8_t rawTimestamp[TimeStamperIF::MISSION_TIMESTAMP_SIZE] = {};
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
TimeWriterIF* timeStamper;
TimeStamperIF* timeStamper;
MonitoringReportContent()
: SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
monitorId(0),
@ -47,7 +47,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
oldState(0),
newState(0),
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
timeStamper(nullptr) {
timeStamper(NULL) {
setAllNext();
}
MonitoringReportContent(gp_id_t globalPoolId, T value, T limitValue, ReturnValue_t oldState,
@ -61,7 +61,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
oldState(oldState),
newState(newState),
timestampSerializer(rawTimestamp, sizeof(rawTimestamp)),
timeStamper(nullptr) {
timeStamper(NULL) {
setAllNext();
if (checkAndSetStamper()) {
timeStamper->addTimeStamp(rawTimestamp, sizeof(rawTimestamp));
@ -79,7 +79,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
}
bool checkAndSetStamper() {
if (timeStamper == nullptr) {
timeStamper = ObjectManager::instance()->get<TimeWriterIF>(timeStamperId);
timeStamper = ObjectManager::instance()->get<TimeStamperIF>(timeStamperId);
if (timeStamper == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MonitoringReportContent::checkAndSetStamper: "

View File

@ -21,7 +21,7 @@ void ObjectManager::setObjectFactoryFunction(produce_function_t objFactoryFunc,
this->factoryArgs = factoryArgs;
}
ObjectManager::ObjectManager() = default;
ObjectManager::ObjectManager() {}
ObjectManager::~ObjectManager() {
for (auto const& iter : objectList) {
@ -53,7 +53,7 @@ ReturnValue_t ObjectManager::insert(object_id_t id, SystemObjectIF* object) {
}
ReturnValue_t ObjectManager::remove(object_id_t id) {
if (this->getSystemObject(id) != nullptr) {
if (this->getSystemObject(id) != NULL) {
this->objectList.erase(id);
#if FSFW_CPP_OSTREAM_ENABLED == 1
// sif::debug << "ObjectManager::removeObject: Object " << std::hex
@ -78,7 +78,7 @@ SystemObjectIF* ObjectManager::getSystemObject(object_id_t id) {
}
}
void ObjectManager::produce() {
void ObjectManager::initialize() {
if (objectFactoryFunction == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectManager::initialize: Passed produceObjects "
@ -90,25 +90,18 @@ void ObjectManager::produce() {
return;
}
objectFactoryFunction(factoryArgs);
}
void ObjectManager::initialize() {
produce();
ReturnValue_t result = returnvalue::FAILED;
uint32_t errorCount = 0;
for (auto const& it : objectList) {
result = it.second->initialize();
if (result != returnvalue::OK) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1
object_id_t var = it.first;
sif::error << "ObjectManager::initialize: Object 0x" << std::hex << std::setw(8)
<< std::setfill('0') << it.first << " failed to initialize with code 0x" << result
<< std::dec << std::setfill(' ') << std::endl;
#else
sif::printError(
"ObjectManager::initialize: Object 0x%08x failed to initialize with code 0x%04x\n", var,
it.first);
#endif
<< std::setfill('0') << var
<< " failed to "
"initialize with code 0x"
<< result << std::dec << std::setfill(' ') << std::endl;
#endif
errorCount++;
}
@ -147,7 +140,3 @@ void ObjectManager::printList() {
}
#endif
}
const std::map<object_id_t, SystemObjectIF*> * ObjectManager::getObjectList(){
return &objectList;
}

View File

@ -38,13 +38,11 @@ class ObjectManager : public ObjectManagerIF {
/**
* @brief In the class's destructor, all objects in the list are deleted.
*/
~ObjectManager() override;
virtual ~ObjectManager();
ReturnValue_t insert(object_id_t id, SystemObjectIF* object) override;
ReturnValue_t remove(object_id_t id) override;
void initialize() override;
void produce() override;
void printList() override;
const std::map<object_id_t, SystemObjectIF*> * getObjectList() override;
protected:
SystemObjectIF* getSystemObject(object_id_t id) override;

View File

@ -1,8 +1,6 @@
#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#include <map>
#include "../returnvalues/returnvalue.h"
#include "../serviceinterface/ServiceInterface.h"
#include "SystemObjectIF.h"
@ -60,14 +58,12 @@ class ObjectManagerIF {
* @li returnvalue::OK in case the object was successfully removed
*/
virtual ReturnValue_t remove(object_id_t id) = 0;
virtual void produce() = 0;
virtual void initialize() = 0;
/**
* @brief This is a debug function, that prints the current content of the
* object list.
*/
virtual void printList() = 0;
virtual const std::map<object_id_t, SystemObjectIF*>* getObjectList() = 0;
};
#endif /* OBJECTMANAGERIF_H_ */

View File

@ -46,7 +46,7 @@ class SystemObjectIF : public EventReportingProxyIF {
* Therefore, a two-step initialization resolves this problem and prevents
* circular dependencies of not-fully initialized objects on start up.
* @return - @c returnvalue::OK in case the initialization was successful
* - @c returnvalue::FAILED otherwise
* - @c returnvalue::FAILED otherwise
*/
virtual ReturnValue_t initialize() = 0;
/**

View File

@ -33,7 +33,6 @@ enum framework_objects : object_id_t {
TC_STORE = 0x534f0100,
TM_STORE = 0x534f0200,
TIME_STAMPER = 0x53500010,
VERIFICATION_REPORTER = 0x53500020,
FSFW_OBJECTS_END = 0x53ffffff,
NO_OBJECT = 0xFFFFFFFF

View File

@ -16,9 +16,7 @@ elseif(FSFW_OSAL MATCHES "host")
else()
message(
WARNING
"${MSG_PREFIX} The FSFW_OSAL variable was not set. Assuming host OS..")
message(WARNING "The OS_FSFW variable was not set. Assuming host OS..")
# Not set. Assumuing this is a host build, try to determine host OS
if(WIN32)
add_subdirectory(host)

View File

@ -161,7 +161,7 @@ void TcpTmTcServer::handleServerOperation(socket_t& connSocket) {
while (true) {
ssize_t retval = recv(connSocket, reinterpret_cast<char*>(receptionBuffer.data()),
receptionBuffer.size(), tcpConfig.tcpFlags);
receptionBuffer.capacity(), tcpConfig.tcpFlags);
if (retval == 0) {
size_t availableReadData = ringBuffer.getAvailableReadData();
if (availableReadData > lastRingBufferSize) {
@ -335,27 +335,31 @@ ReturnValue_t TcpTmTcServer::handleTcRingBufferData(size_t availableReadData) {
}
ringBuffer.readData(receptionBuffer.data(), readAmount, true);
const uint8_t* bufPtr = receptionBuffer.data();
SpacePacketParser::FoundPacketInfo info;
if (spacePacketParser == nullptr) {
return returnvalue::FAILED;
}
spacePacketParser->reset();
while (spacePacketParser->getAmountRead() < readAmount) {
result = spacePacketParser->parseSpacePackets(&bufPtr, readAmount, info);
const uint8_t** bufPtrPtr = &bufPtr;
size_t startIdx = 0;
size_t foundSize = 0;
size_t readLen = 0;
while (readLen < readAmount) {
if (spacePacketParser == nullptr) {
return returnvalue::FAILED;
}
result =
spacePacketParser->parseSpacePackets(bufPtrPtr, readAmount, startIdx, foundSize, readLen);
switch (result) {
case (SpacePacketParser::NO_PACKET_FOUND):
case (SpacePacketParser::SPLIT_PACKET): {
break;
}
case (returnvalue::OK): {
result = handleTcReception(receptionBuffer.data() + info.startIdx, info.sizeFound);
result = handleTcReception(receptionBuffer.data() + startIdx, foundSize);
if (result != returnvalue::OK) {
status = result;
}
}
}
ringBuffer.deleteData(info.sizeFound);
ringBuffer.deleteData(foundSize);
lastRingBufferSize = ringBuffer.getAvailableReadData();
std::memset(receptionBuffer.data() + startIdx, 0, foundSize);
}
return status;
}

View File

@ -146,7 +146,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
struct tm time_tm {};
struct tm time_tm;
time_tm.tm_year = from->year - 1900;
time_tm.tm_mon = from->month - 1;

View File

@ -65,11 +65,11 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
// But I will still return a failure here.
return returnvalue::FAILED;
}
auto* targetQueue =
MessageQueue* targetQueue =
dynamic_cast<MessageQueue*>(QueueMapManager::instance()->getMessageQueue(sendTo));
if (targetQueue == nullptr) {
if (not ignoreFault) {
auto* internalErrorReporter =
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();
@ -84,7 +84,7 @@ ReturnValue_t MessageQueue::sendMessageFromMessageQueue(MessageQueueId_t sendTo,
message->getMaximumMessageSize());
} else {
if (not ignoreFault) {
auto* internalErrorReporter =
InternalErrorReporterIF* internalErrorReporter =
ObjectManager::instance()->get<InternalErrorReporterIF>(objects::INTERNAL_ERROR_REPORTER);
if (internalErrorReporter != nullptr) {
internalErrorReporter->queueMessageNotSent();

View File

@ -68,7 +68,7 @@ class MessageQueue : public MessageQueueBase {
* @details This is accomplished by using the delete call provided
* by the operating system.
*/
~MessageQueue() override;
virtual ~MessageQueue();
// Implement non-generic MessageQueueIF functions not handled by MessageQueueBase
virtual ReturnValue_t sendMessageFrom(MessageQueueId_t sendTo, MessageQueueMessageIF* message,
@ -111,6 +111,8 @@ class MessageQueue : public MessageQueueBase {
size_t messageDepth = 0;
MutexIF* queueLock;
MessageQueueId_t defaultDestination = MessageQueueIF::NO_QUEUE;
};
#endif /* FRAMEWORK_OSAL_HOST_MESSAGEQUEUE_H_ */

View File

@ -13,6 +13,7 @@ ReturnValue_t MessageQueueSenderIF::sendMessage(MessageQueueId_t sendTo,
MessageQueueMessageIF* message,
MessageQueueId_t sentFrom, bool ignoreFault) {
return MessageQueue::sendMessageFromMessageQueue(sendTo, message, sentFrom, ignoreFault);
return returnvalue::OK;
}
QueueFactory* QueueFactory::instance() {
@ -22,9 +23,9 @@ QueueFactory* QueueFactory::instance() {
return factoryInstance;
}
QueueFactory::QueueFactory() = default;
QueueFactory::QueueFactory() {}
QueueFactory::~QueueFactory() = default;
QueueFactory::~QueueFactory() {}
MessageQueueIF* QueueFactory::createMessageQueue(uint32_t messageDepth, size_t maxMessageSize,
MqArgs* args) {

View File

@ -54,7 +54,7 @@ MessageQueueIF* QueueMapManager::getMessageQueue(MessageQueueId_t messageQueueId
} else {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId
<< " does not exist in the map" << std::endl;
<< " does not exists in the map!" << std::endl;
#else
sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n",
messageQueueId);

View File

@ -2,22 +2,23 @@
#include <linux/sysinfo.h>
#include <sys/sysinfo.h>
#include <sys/time.h>
#include <time.h>
#include <unistd.h>
#include <ctime>
#include <fstream>
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
uint32_t Clock::getTicksPerSecond() {
uint32_t Clock::getTicksPerSecond(void) {
uint32_t ticks = sysconf(_SC_CLK_TCK);
return ticks;
}
ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
timespec timeUnix{};
timeval timeTimeval{};
timespec timeUnix;
timeval timeTimeval;
convertTimeOfDayToTimeval(time, &timeTimeval);
timeUnix.tv_sec = timeTimeval.tv_sec;
timeUnix.tv_nsec = (__syscall_slong_t)timeTimeval.tv_usec * 1000;
@ -31,7 +32,7 @@ ReturnValue_t Clock::setClock(const TimeOfDay_t* time) {
}
ReturnValue_t Clock::setClock(const timeval* time) {
timespec timeUnix{};
timespec timeUnix;
timeUnix.tv_sec = time->tv_sec;
timeUnix.tv_nsec = (__syscall_slong_t)time->tv_usec * 1000;
int status = clock_settime(CLOCK_REALTIME, &timeUnix);
@ -43,7 +44,7 @@ ReturnValue_t Clock::setClock(const timeval* time) {
}
ReturnValue_t Clock::getClock_timeval(timeval* time) {
timespec timeUnix{};
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
return returnvalue::FAILED;
@ -54,18 +55,18 @@ ReturnValue_t Clock::getClock_timeval(timeval* time) {
}
ReturnValue_t Clock::getClock_usecs(uint64_t* time) {
timeval timeVal{};
timeval timeVal;
ReturnValue_t result = getClock_timeval(&timeVal);
if (result != returnvalue::OK) {
return result;
}
*time = static_cast<uint64_t>(timeVal.tv_sec) * 1e6 + timeVal.tv_usec;
*time = (uint64_t)timeVal.tv_sec * 1e6 + timeVal.tv_usec;
return returnvalue::OK;
}
timeval Clock::getUptime() {
timeval uptime{};
timeval uptime;
auto result = getUptime(&uptime);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -98,7 +99,7 @@ ReturnValue_t Clock::getUptime(timeval* uptime) {
//}
ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
timeval uptime{};
timeval uptime;
ReturnValue_t result = getUptime(&uptime);
if (result != returnvalue::OK) {
return result;
@ -108,7 +109,7 @@ ReturnValue_t Clock::getUptime(uint32_t* uptimeMs) {
}
ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
timespec timeUnix{};
timespec timeUnix;
int status = clock_gettime(CLOCK_REALTIME, &timeUnix);
if (status != 0) {
// TODO errno
@ -121,7 +122,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
MutexGuard helper(timeMutex);
// gmtime writes its output in a global buffer which is not Thread Safe
// Therefore we have to use a Mutex here
struct std::tm* timeInfo;
struct tm* timeInfo;
timeInfo = gmtime(&timeUnix.tv_sec);
time->year = timeInfo->tm_year + 1900;
time->month = timeInfo->tm_mon + 1;
@ -135,7 +136,7 @@ ReturnValue_t Clock::getDateAndTime(TimeOfDay_t* time) {
}
ReturnValue_t Clock::convertTimeOfDayToTimeval(const TimeOfDay_t* from, timeval* to) {
std::tm fromTm{};
tm fromTm;
// Note: Fails for years before AD
fromTm.tm_year = from->year - 1900;
fromTm.tm_mon = from->month - 1;

View File

@ -66,8 +66,7 @@ class HasParametersIF {
* @param newValues
* @param startAtIndex Linear index, runs left to right, top to bottom for
* matrix indexes.
* @return returnvalue::OK if parameter is valid and a set function of the parameter wrapper was
* called.
* @return
*/
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueIdentifier,
ParameterWrapper *parameterWrapper,

View File

@ -44,7 +44,7 @@ store_address_t ParameterMessage::getParameterLoadCommand(const CommandMessage*
*pfc = packedParamSettings >> 16 & 0xff;
*rows = packedParamSettings >> 8 & 0xff;
*columns = packedParamSettings & 0xff;
return static_cast<store_address_t>(message->getParameter2());
return message->getParameter2();
}
void ParameterMessage::clear(CommandMessage* message) {

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