Compare commits

...

101 Commits

Author SHA1 Message Date
c42da5df86 fixed DHB unittest for new Actions 2022-09-14 17:04:17 +02:00
6c711415c1 bug found by unittest 2022-09-14 16:34:09 +02:00
253aa30263 fixing merge 2022-09-14 16:31:24 +02:00
eae7bfc935 Merge branch 'mohr/merge-upstream' into mohr/introspection 2022-09-14 16:23:23 +02:00
bd594123a2 Merge remote-tracking branch 'upstream/development' into mohr/merge-upstream 2022-09-14 12:54:15 +02:00
0ce568ad26 Merge pull request 'publish documentation for development and master branch' (#681) from mohr/documentation_ci into development
Reviewed-on: fsfw/fsfw#681
2022-09-14 11:22:35 +02:00
6970068d56 small fix in README 2022-09-13 18:19:35 +02:00
af282c7d3e reverting to only publish development 2022-09-13 18:17:56 +02:00
21a9d89fb3 pushing code coverage report to documentation server 2022-09-13 18:14:26 +02:00
3257935150 fixing scp yet again again 2022-09-13 18:06:16 +02:00
f34cf9095d fixing scp yet again 2022-09-13 18:02:38 +02:00
24ecf125a3 fixing scp command again 2022-09-13 17:55:12 +02:00
6451a16888 fixing scp command 2022-09-13 17:51:01 +02:00
fa5605c959 testing Jenkinsfile 2022-09-13 14:50:37 +02:00
8e835be55f testing Jenkinsfile 2022-09-13 14:46:12 +02:00
9bd600c488 testing Jenkinsfile 2022-09-13 14:32:10 +02:00
9c7248e78e typo in Dockerfile 2022-09-13 14:20:30 +02:00
ecf51b2913 testing Jenkinsfile 2022-09-13 14:09:08 +02:00
8bbde05413 add jenkins user in docker so that ssh will work 2022-09-13 14:08:04 +02:00
d79b5348d8 testing Jenkinsfile 2022-09-13 14:00:36 +02:00
92e3ab04f3 testing Jenkinsfile 2022-09-13 13:54:23 +02:00
003a6d00fa Documentation build tools in docker 2022-09-13 13:13:18 +02:00
9ee1896553 Merge pull request 'Refactor Local Pool API' (#667) from mueller/refactor-local-pool-api into development
Reviewed-on: fsfw/fsfw#667
2022-09-12 14:32:08 +02:00
a5b5523111 Merge pull request 'Refactor TMTC Stack, improve test framework' (#655) from mueller/refactor-tmtc-stack into development
Reviewed-on: fsfw/fsfw#655
2022-09-12 14:31:22 +02:00
62cd39e573 Merge pull request 'SerialBufferAdapter refactoring' (#677) from mueller/refactor-serial-buffer-adapter into development
Reviewed-on: fsfw/fsfw#677
2022-09-12 14:30:51 +02:00
278ed36db8 Merge pull request 'bump catch2 version' (#678) from mueller/bump-catch2 into development
Reviewed-on: fsfw/fsfw#678
2022-09-12 14:24:28 +02:00
aed30d54ef Merge pull request 'remove bsp specific code' (#679) from mueller/remove-bsp-specific-code into development
Reviewed-on: fsfw/fsfw#679
2022-09-12 14:23:48 +02:00
1126db2c8a Merge pull request 'remove user includes' (#675) from mueller/remove-user-includes into development
Reviewed-on: fsfw/fsfw#675
2022-09-12 14:15:18 +02:00
a64a04d7fe Merge branch 'development' into mueller/refactor-tmtc-stack 2022-09-12 14:14:49 +02:00
80467bf097 Merge pull request 'sif::buffer: if disabeld do not print' (#680) from mohr/enableDisable into development
Reviewed-on: fsfw/fsfw#680
2022-09-12 14:12:13 +02:00
6a6aa7fdd6 Merge branch 'development' into mohr/enableDisable 2022-09-12 14:11:38 +02:00
7e379d2159 Merge pull request 'provide a weak print char impl' (#674) from mueller/provide-weak-print-char into development
Reviewed-on: fsfw/fsfw#674
2022-09-12 14:10:31 +02:00
6ae709acc3 Merge branch 'development' into mueller/remove-user-includes 2022-09-12 14:07:09 +02:00
d52f335455 sif::buffer: if disabeld do not print 2022-09-08 11:47:40 +02:00
383bafe344 Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr/introspection 2022-09-08 11:42:27 +02:00
1c527c4946 copy paste fail #2 2022-09-08 11:41:32 +02:00
04b619a15c update header as well 2022-09-07 17:58:49 +02:00
282704e0fd remove bsp specific code 2022-09-07 17:54:04 +02:00
0e6e124eab small fixes 2022-09-07 10:54:49 +02:00
07ef9a0ec3 bump catch2 version 2022-09-06 15:47:04 +02:00
80464f2a81 Merge branch 'mueller/refactor-serial-buffer-adapter' into mueller/refactor-tmtc-stack 2022-09-05 16:38:58 +02:00
16688316a8 rename setBuffer to setConstBuffer 2022-09-05 16:31:56 +02:00
3583e30ee6 rename const buf setter 2022-09-05 16:27:20 +02:00
1e395dc402 set buffer expects const pointer now 2022-09-05 16:25:02 +02:00
f5421e9abd refactor tm helper 2022-09-05 16:10:06 +02:00
4c3f9feb93 explicit include 2022-09-05 16:06:24 +02:00
b7ed8ff390 Merge branch 'mueller/refactor-tmtc-stack' of https://egit.irs.uni-stuttgart.de/fsfw/fsfw into mueller/refactor-tmtc-stack 2022-09-05 16:02:41 +02:00
75dc7a405d del data wrapper 2022-09-05 16:02:32 +02:00
b7a1f79d5b update FSFWCnfig.h 2022-09-05 15:36:12 +02:00
f0b7a103d4 refactor ctors 2022-09-05 15:30:53 +02:00
ee93f4a4ca Merge branch 'development' into mueller/refactor-tmtc-stack 2022-09-05 14:46:51 +02:00
d64ad71529 Some improvements for time stamper API 2022-09-05 14:44:35 +02:00
26bc80964e Merge branch 'development' into mueller/provide-weak-print-char 2022-09-05 14:14:06 +02:00
eb03bf52a6 Merge pull request 'better warning for missing include paths' (#676) from mueller/better-missing-inc-path-warning into development
Reviewed-on: fsfw/fsfw#676
2022-09-05 14:13:19 +02:00
80355910ee better warning 2022-09-02 09:05:10 +02:00
04800df31e another user-level-include 2022-09-02 09:04:37 +02:00
1e85cdadfd remove user includes 2022-09-02 08:55:33 +02:00
ebc02673dd provide a weak print char impl 2022-09-02 08:50:39 +02:00
9202c6c17f Merge branch 'mueller/refactor-tmtc-stack' into mueller/refactor-local-pool-api 2022-09-01 17:51:50 +02:00
5f8c549993 Merge remote-tracking branch 'origin/development' into mueller/refactor-local-pool-api 2022-09-01 17:51:44 +02:00
04bff7a522 test fix 2022-09-01 17:51:09 +02:00
5c20cc804e Merge remote-tracking branch 'origin/development' into mueller/refactor-tmtc-stack 2022-09-01 17:48:40 +02:00
eb8e236cd4 Merge pull request 'Bugfix for Space Packet Parser' (#673) from eive/fsfw:mueller/fixes-tmtc-server-sp-parser into development
Reviewed-on: fsfw/fsfw#673
2022-09-01 14:12:16 +02:00
7dec45ccf2 Merge pull request 'Service 11 regression' (#670) from eive/fsfw:mueller/service-11-issues into development
Reviewed-on: fsfw/fsfw#670
2022-09-01 11:59:18 +02:00
2b01e86f9c one small additional precaution 2022-09-01 11:56:07 +02:00
60fd3d43c0 Merge pull request 'DHB TM handler alternative API raw buffer' (#671) from mueller/dhb-handle-device-tm-2 into development
Reviewed-on: fsfw/fsfw#671
2022-09-01 11:22:17 +02:00
67980cb592 Merge branch 'development' into mueller/fixes-tmtc-server-sp-parser 2022-09-01 11:21:02 +02:00
3010f2f925 Merge pull request 'DHB set action commander before buildCommandFromCommand' (#672) from eive/fsfw:mueller/dhb-set-action-commander-before-building-cmd into development
Reviewed-on: fsfw/fsfw#672
2022-09-01 11:18:32 +02:00
01651f0521 more simplfications 2022-09-01 10:52:48 +02:00
c7f300671f update header 2022-09-01 10:45:10 +02:00
7d3223d766 add comment blocks 2022-09-01 10:44:57 +02:00
7ae82a5cb4 do not cache previous recipient 2022-09-01 08:58:18 +02:00
28ecd0e5c6 bugfix for SP parser 2022-09-01 08:51:12 +02:00
7345c18b04 small fix which allows sending action reply immediately 2022-08-31 16:50:48 +02:00
64a7fde301 this is annoying 2022-08-30 15:19:01 +02:00
9131ca688b make two helper functions protected 2022-08-30 15:01:10 +02:00
c7e6f01f9b Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr/introspection 2022-08-26 15:52:14 +02:00
4c0f67adf5 missing implementation in subsystembase 2022-08-26 15:03:17 +02:00
450ad1dad4 ControllerBase Modes 2022-08-26 12:07:59 +02:00
1dfb3323f7 default getModehelper for ControllerBase 2022-08-26 11:53:46 +02:00
f5adcd0625 default getModehelper for subsystembase 2022-08-26 10:57:05 +02:00
bc593c938d some more mode introspection 2022-08-26 10:31:45 +02:00
8353964635 Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr/introspection 2022-08-25 22:41:25 +02:00
3f8f17a66e copy paste fail 2022-08-25 22:39:21 +02:00
3260a03544 forgot include 2022-08-25 22:37:41 +02:00
3ffdc0d31f Mode introspection 2022-08-25 22:33:33 +02:00
d367baa42c stupid idea 2022-08-24 18:47:25 +02:00
d634bdb775 Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr/introspection 2022-08-24 17:49:29 +02:00
59f8dd1322 preparing DHB::buildCommandFromCommand for retirement 2022-08-24 17:49:16 +02:00
61b4e68f3d parameter tuning 2022-08-24 17:19:45 +02:00
e34664d265 Adding error message to a coding error 2022-08-19 13:47:13 +02:00
20eb232bf5 added access to objectlist and a produce function to ObjectManager 2022-08-19 12:23:14 +02:00
31f59f915c Merge commit 'd9759581' into mohr/introspection 2022-08-18 12:20:20 +02:00
cfdbe0f6cb Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr/introspection 2022-07-28 16:32:24 +02:00
dd281f8a67 Controller base missing a function 2022-07-28 16:32:12 +02:00
f9e9ff320f Small fixes 2022-07-28 14:55:43 +02:00
f56646d2c3 changed action handling slightly 2022-07-20 16:59:42 +02:00
b08d127e11 Merge remote-tracking branch 'sidestream/mohr_introspection' into mohr_other_introspection 2022-07-14 15:59:22 +02:00
ef18377cef new Actions 2022-06-29 23:36:45 +02:00
0c057c66b1 added introspection 2022-06-28 18:56:52 +02:00
34c50ce3e2 ignore .vscode 2022-06-28 17:44:53 +02:00
89 changed files with 1337 additions and 484 deletions

3
.gitignore vendored
View File

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

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}.0.0-preview5
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
CACHE STRING "Catch2 library exact version requirement")
# Keep this off by default for now. See PR:
@ -360,7 +360,8 @@ if(NOT FSFW_CONFIG_PATH)
if(NOT FSFW_BUILD_DOCS)
message(
WARNING
"${MSG_PREFIX} Flight Software Framework configuration path not set")
"${MSG_PREFIX} Flight Software Framework configuration path FSFW_CONFIG_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 . -j
cmake --build . -- Sphinx -j
```
You can find the generated documentation inside the `docs/sphinx` folder inside the build

View File

@ -5,11 +5,13 @@ 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
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 git clone https://github.com/catchorg/Catch2.git && \
cd Catch2 && \
git checkout v3.0.0-preview5 && \
git checkout v3.1.0 && \
cmake -Bbuild -H. -DBUILD_TESTING=OFF && \
cmake --build build/ --target install
@ -18,3 +20,6 @@ RUN git clone https://github.com/ETLCPP/etl.git && \
git checkout 20.28.0 && \
cmake -B build . && \
cmake --install build/
#ssh needs a valid user to work
RUN adduser --uid 114 jenkins

View File

@ -1,9 +1,13 @@
pipeline {
environment {
BUILDDIR = 'cmake-build-tests'
DOCDDIR = 'cmake-build-documentation'
}
agent {
docker { image 'fsfw-ci:d3'}
docker {
image 'fsfw-ci:d5'
args '--network host'
}
}
stages {
stage('Clean') {
@ -39,5 +43,47 @@ 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,6 +4,10 @@
#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

@ -15,6 +15,7 @@ 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

@ -0,0 +1,62 @@
#include "Action.h"
#include <fsfw/serialize/SerializeAdapter.h>
#undef Action
#ifdef FSFW_INTROSPECTION
Action::Action() {}
void Action::setEnum(EnumIF *theEnum) {
id = theEnum->getValue();
name = theEnum->getDescription();
}
const char *Action::getName() { return name; }
#else
Action::Action(ActionId_t id) : id(id) {}
#endif
ActionId_t Action::getId() { return id; }
void Action::registerParameter(ParameterIF *parameter) { parameterList.push_back(parameter); }
std::vector<ParameterIF *> const *Action::getParameters() const { return &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;
}

50
src/fsfw/action/Action.h Normal file
View File

@ -0,0 +1,50 @@
#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,6 +57,10 @@ 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;
@ -66,9 +70,29 @@ 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;
}
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
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);
ipcStore->deleteData(dataAddress);
if (result == HasActionsIF::EXECUTION_FINISHED) {
CommandMessage reply;
@ -163,3 +187,11 @@ 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,9 +1,13 @@
#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
*
@ -98,6 +102,16 @@ 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;
@ -108,6 +122,8 @@ 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 ActionHelper.cpp ActionMessage.cpp
${LIB_FSFW_NAME} PRIVATE Action.cpp ActionHelper.cpp ActionMessage.cpp
CommandActionHelper.cpp SimpleActionHelper.cpp)

View File

@ -44,8 +44,12 @@ 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
@ -55,8 +59,7 @@ class HasActionsIF {
* -@c EXECUTION_FINISHED Finish reply will be generated
* -@c Not returnvalue::OK Step failure reply will be generated
*/
virtual ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) = 0;
virtual ReturnValue_t executeAction(Action* action) = 0;
};
#endif /* FSFW_ACTION_HASACTIONSIF_H_ */

View File

@ -0,0 +1,40 @@
#pragma once
#include "Parameter.h"
template <typename T>
class MinMaxParameter : public Parameter<T> {
#ifdef FSFW_INTROSPECTION
private:
MinMaxParameter(Action *owner, const char *name, T min, T max)
: Parameter<T>(owner, name), min(min), max(max) {}
public:
static MinMaxParameter createMinMaxParameter(Action *owner, const char *name, T min, T max) {
return MinMaxParameter(owner, name, min, max);
}
virtual double getMinFloating() override { return static_cast<double>(min); }
virtual int64_t getMinSigned() override { return static_cast<int64_t>(min); }
virtual double getMaxFloating() override { return static_cast<double>(max); }
virtual int64_t getMaxSigned() override { return static_cast<int64_t>(max); }
#else
private:
MinMaxParameter(Action *owner, T min, T max) : Parameter<T>(owner), min(min), max(max) {}
public:
static MinMaxParameter createMinMaxParameter(Action *owner, T min, T max) {
return MinMaxParameter(owner, min, max);
}
#endif
private:
T min;
T max;
};
#ifdef FSFW_INTROSPECTION
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p2, p3, p4)
#else
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p3, p4)
#endif

120
src/fsfw/action/Parameter.h Normal file
View File

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

@ -0,0 +1,45 @@
#pragma once
#include <fsfw/serialize/SerializeIF.h>
#include <fsfw/introspection/Types.h>
#ifdef FSFW_INTROSPECTION
#include <vector>
#endif
class ParameterIF : public SerializeIF {
public:
virtual bool isValid() = 0;
#ifdef FSFW_INTROSPECTION
virtual const char *getName() = 0;
virtual Types::ParameterType getType() = 0;
virtual double getFloating() = 0;
virtual int64_t getSigned() = 0;
virtual bool setFloating(double value) = 0;
virtual bool setSigned(int64_t value) = 0;
virtual double getMinFloating() = 0;
virtual int64_t getMinSigned() = 0;
virtual double getMaxFloating() = 0;
virtual int64_t getMaxSigned() = 0;
virtual std::vector<int64_t> getEnumValues() = 0;
virtual const char *const * getEnumDescriptions() = 0;
// ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
// Endianness streamEndianness) const override = 0;
// size_t getSerializedSize() const override = 0;
// ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
// Endianness streamEndianness) override = 0;
#endif
};

View File

@ -44,11 +44,27 @@ 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;
}
lastCommander = commandedBy;
lastAction = actionId;
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
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();
ipcStore->deleteData(dataAddress);
switch (result) {
case returnvalue::OK:

View File

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

@ -21,7 +21,7 @@ cfdp::Lv& cfdp::Lv::operator=(const Lv& other) {
if (value == nullptr or otherSize == 0) {
this->zeroLen = true;
}
this->value.setBuffer(value, otherSize);
this->value.setConstBuffer(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.setBuffer(const_cast<uint8_t*>(*buffer + 1), lengthField);
value.setConstBuffer(*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.setBuffer(const_cast<uint8_t *>(*buffer + 1), lengthField);
value.setConstBuffer(*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.setBuffer(value, len);
this->value.setConstBuffer(value, len);
}
uint8_t cfdp::Tlv::getLengthField() const { return this->value.getSerializedSize() - 1; }

View File

@ -103,6 +103,10 @@ 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,6 +3,7 @@
#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"
@ -20,7 +21,9 @@ class ControllerBase : public HasModesIF,
public ExecutableObjectIF,
public SystemObject {
public:
static const Mode_t MODE_NORMAL = 2;
FSFW_CLASSLESS_ENUM(ControllerModes, Mode_t,
((CONTROLLER_MODE_ON, MODE_ON, "On"))((CONTROLLER_MODE_OFF, MODE_OFF,
"Off"))((MODE_NORMAL, 2, "Normal")))
ControllerBase(object_id_t setObjectId, object_id_t parentId, size_t commandQueueDepth = 3);
~ControllerBase() override;
@ -39,6 +42,9 @@ 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,11 +8,12 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, object_id_t
ExtendedControllerBase::~ExtendedControllerBase() = default;
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;
ActionHelper *ExtendedControllerBase::getActionHelper() {
return &actionHelper;
}
ReturnValue_t ExtendedControllerBase::executeAction(Action *action) {
return action->handle();
}
object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); }

View File

@ -29,6 +29,10 @@ 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;
@ -49,10 +53,6 @@ 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

@ -1324,29 +1324,26 @@ void DeviceHandlerBase::handleDeviceTm(const SerializeIF& dataSet, DeviceCommand
}
}
ReturnValue_t DeviceHandlerBase::executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) {
ActionHelper* DeviceHandlerBase::getActionHelper() { return &actionHelper; }
ReturnValue_t DeviceHandlerBase::executeAction(Action* action) {
ReturnValue_t result = acceptExternalDeviceCommands();
if (result != returnvalue::OK) {
return result;
}
DeviceCommandMap::iterator iter = deviceCommandMap.find(actionId);
MessageQueueId_t prevRecipient = MessageQueueIF::NO_QUEUE;
DeviceCommandMap::iterator iter = deviceCommandMap.find(action->getId());
if (iter == deviceCommandMap.end()) {
result = COMMAND_NOT_SUPPORTED;
} else if (iter->second.isExecuting) {
result = COMMAND_ALREADY_SENT;
} else {
prevRecipient = iter->second.sendReplyTo;
iter->second.sendReplyTo = commandedBy;
result = buildCommandFromCommand(actionId, data, size);
iter->second.sendReplyTo = action->commandedBy;
result = action->handle();
}
if (result == returnvalue::OK) {
iter->second.isExecuting = true;
cookieInfo.pendingCommand = iter;
cookieInfo.state = COOKIE_WRITE_READY;
} else {
iter->second.sendReplyTo = prevRecipient;
}
return result;
}
@ -1605,3 +1602,10 @@ void DeviceHandlerBase::disableCommandsAndReplies() {
}
}
}
ModeHelper const* DeviceHandlerBase::getModeHelper() const { return &modeHelper; }
ModeDefinitionHelper DeviceHandlerBase::getModeDefinitionHelper() {
return ModeDefinitionHelper::create<DeviceHandlerMode, DefaultSubmode>();
}

View File

@ -204,13 +204,15 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual void setParentQueue(MessageQueueId_t parentQueueId);
/** @brief Implementation required for HasActionIF */
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t *data, size_t size) override;
/** @brief Implementations required for HasActionIF */
ActionHelper* getActionHelper() override;
ReturnValue_t executeAction(Action *action) override;
Mode_t getTransitionSourceMode() const;
Submode_t getTransitionSourceSubMode() const;
virtual void getMode(Mode_t *mode, Submode_t *submode);
void getMode(Mode_t *mode, Submode_t *submode) override;
ModeHelper const * getModeHelper() const override;
ModeDefinitionHelper getModeDefinitionHelper() override;
HealthState getHealth();
ReturnValue_t setHealth(HealthState health);
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
@ -314,6 +316,8 @@ 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)
@ -340,7 +344,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) = 0;
size_t commandDataLen) {return returnvalue::FAILED;}
/* Reply handling */
/**
@ -1070,8 +1074,23 @@ 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,
bool forceDirectTm = false);

View File

@ -4,6 +4,7 @@
#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"
@ -37,23 +38,30 @@ 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
*/
// 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.
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.
static const Mode_t MODE_NORMAL = 2;
((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.
static const Mode_t MODE_RAW = 3;
//! 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.
static const Mode_t MODE_ERROR_ON = 4;
((MODE_ERROR_ON, 4, "Error")))
//! 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.

View File

@ -4,8 +4,6 @@
#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

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

View File

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

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

@ -0,0 +1,62 @@
#define CLEAN_ENUM_ITEM(r, data, element) \
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), \
(BOOST_PP_TUPLE_ELEM(0, element) = BOOST_PP_TUPLE_ELEM(1, element)), \
(BOOST_PP_TUPLE_ELEM(0, element)))
#if defined FSFW_ENUM_VALUE_CHECKS || defined FSFW_INTROSPECTION
#define GET_KEY(r, data, element) (BOOST_PP_TUPLE_ELEM(0, element))
#define GET_DESCRIPTION(r, data, element) \
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), (BOOST_PP_TUPLE_ELEM(2, element)), \
(BOOST_PP_TUPLE_ELEM(1, element)))
#define CREATE_KEY_ARRAY(enum_elements, type) \
/*was static constexpr, but clang won't compile that*/ \
int64_t elements[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))] = { \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))}; \
const int64_t *getElements() const override { return elements; } \
size_t getSize() const override { \
return BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements)); \
}
#define VALUE_CHECK(type) \
bool isValid() const override { \
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
if (value == elements[i]) { \
return true; \
} \
} \
return false; \
}
#ifdef FSFW_INTROSPECTION
#define CREATE_DESCRIPTION_ARRAY(elements) \
/*was static constexpr, but clang won't compile that*/ \
const char \
*descriptions[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))] = { \
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_DESCRIPTION, "", elements))}; \
const char *const *getDescriptions() const override { return descriptions; }
#define GET_INDEX() \
size_t getIndex(int64_t value) const override { \
for (size_t i = 0; i < sizeof(elements) / sizeof(elements[0]); i++) { \
if (value == elements[i]) { \
return i; \
} \
} \
return -1; \
}
#define GET_DESCRIPTION_FUNC() \
const char *getDescription() const override { \
if (getIndex(value) == static_cast<size_t>(-1)) { \
return nullptr; \
} else { \
return descriptions[getIndex(value)]; \
} \
}
#else
#define GET_INDEX()
#define CREATE_DESCRIPTION_ARRAY(elements)
#define GET_DESCRIPTION_FUNC()
#endif
#endif

View File

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

@ -0,0 +1,56 @@
#include "ParameterTypeSelector.h"
#include <stdint.h>
#include "Types.h"
#ifdef FSFW_INTROSPECTION
template <typename T>
Types::ParameterType ParameterTypeSelector::getType() {
return Types::UNSUPPORTED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<uint8_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<int8_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<uint16_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<int16_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<uint32_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<int32_t>() {
return Types::SIGNED;
}
// template <>
// Types::ParameterType ParameterTypeSelector::getType<uint64_t>() {
// return Types::UNSIGNED;
// }
template <>
Types::ParameterType ParameterTypeSelector::getType<int64_t>() {
return Types::SIGNED;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<float>() {
return Types::FLOATING;
}
template <>
Types::ParameterType ParameterTypeSelector::getType<double>() {
return Types::FLOATING;
}
#endif

View File

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

View File

@ -0,0 +1,8 @@
#pragma once
//maybe call them MIB types as these are the ones exposed to the MIB?
// Note: some DBs (Postgress, Mongo) only support signed 64bit integers. To have a common denominator, all integers are int64_t.
// As such, ther is no unsigned Type, as there can not be a uint64_t and uint32_t completely fits into int64_t
namespace Types {
enum ParameterType { SIGNED, FLOATING, ENUM, STRING, BYTEARRAY, UNSUPPORTED };
} // namespace Types

View File

@ -0,0 +1,74 @@
#pragma once
#include <limits>
#include <vector>
#include "Enum.h"
#include "Types.h"
#include "ParameterTypeSelector.h"
template <bool>
class enumHelper;
template <>
class enumHelper<true> {
public:
static bool isValid(EnumIF *anEnum) { return anEnum->isValid(); }
#ifdef FSFW_INTROSPECTION
template <typename T>
static Types::ParameterType getType() {
return Types::ENUM;
}
template <typename T>
static T getMin() {
return 0;
}
template <typename T>
static T getMax() {
return 0;
}
static std::vector<int64_t> getEnumValues() { return std::vector<int64_t>(); }
static std::vector<int64_t> getEnumValues(EnumIF *anEnum) {
std::vector<int64_t> vector;
for (size_t i = 0; i < anEnum->getSize(); i++) {
vector.push_back(anEnum->getElements()[i]);
}
return vector;
}
static const char *const *getEnumDescriptions(EnumIF *anEnum) {
return anEnum->getDescriptions();
}
#endif
};
template <>
class enumHelper<false> {
public:
static bool isValid(void *) { return true; }
#ifdef FSFW_INTROSPECTION
template <typename T>
static Types::ParameterType getType() {
return ParameterTypeSelector::getType<T>();
}
template <typename T>
static T getMin() {
return std::numeric_limits<T>::lowest();
}
template <typename T>
static T getMax() {
return std::numeric_limits<T>::max();
}
static std::vector<int64_t> getEnumValues(void *) { return std::vector<int64_t>(); }
static const char *const *getEnumDescriptions(void *) { return nullptr; }
#endif
};

View File

@ -4,7 +4,9 @@
#include <cstdint>
#include "../events/Event.h"
#include "../introspection/ClasslessEnum.h"
#include "../returnvalues/returnvalue.h"
#include "ModeDefinitionHelper.h"
#include "ModeHelper.h"
#include "ModeMessage.h"
@ -35,7 +37,7 @@ class HasModesIF {
static const Event MODE_CMD_REJECTED = MAKE_EVENT(7, severity::LOW);
//! 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
//! 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.
@ -44,11 +46,14 @@ class HasModesIF {
static constexpr Mode_t MODE_INVALID = -1;
static constexpr Mode_t MODE_UNDEFINED = -2;
//! To avoid checks against magic number "0".
static const Submode_t SUBMODE_NONE = 0;
FSFW_CLASSLESS_ENUM(DefaultSubmode, Submode_t,
((SUBMODE_NONE, 0,
"Default"))) //!< 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

@ -0,0 +1,33 @@
#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,3 +106,33 @@ 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,6 +1,8 @@
#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"
@ -39,6 +41,12 @@ 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/TimeStamperIF.h"
#include "../timemanager/TimeWriterIF.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[TimeStamperIF::MAXIMUM_TIMESTAMP_LEN] = {};
uint8_t rawTimestamp[TimeWriterIF::MAXIMUM_TIMESTAMP_LEN] = {};
SerializeElement<SerialBufferAdapter<uint8_t>> timestampSerializer;
TimeStamperIF* timeStamper;
TimeWriterIF* timeStamper;
MonitoringReportContent()
: SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
monitorId(0),
@ -79,7 +79,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
}
bool checkAndSetStamper() {
if (timeStamper == nullptr) {
timeStamper = ObjectManager::instance()->get<TimeStamperIF>(timeStamperId);
timeStamper = ObjectManager::instance()->get<TimeWriterIF>(timeStamperId);
if (timeStamper == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "MonitoringReportContent::checkAndSetStamper: "

View File

@ -78,7 +78,7 @@ SystemObjectIF* ObjectManager::getSystemObject(object_id_t id) {
}
}
void ObjectManager::initialize() {
void ObjectManager::produce() {
if (objectFactoryFunction == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "ObjectManager::initialize: Passed produceObjects "
@ -90,6 +90,10 @@ void ObjectManager::initialize() {
return;
}
objectFactoryFunction(factoryArgs);
}
void ObjectManager::initialize() {
produce();
ReturnValue_t result = returnvalue::FAILED;
uint32_t errorCount = 0;
for (auto const& it : objectList) {
@ -143,3 +147,7 @@ void ObjectManager::printList() {
}
#endif
}
const std::map<object_id_t, SystemObjectIF*> * ObjectManager::getObjectList(){
return &objectList;
}

View File

@ -42,7 +42,9 @@ class ObjectManager : public ObjectManagerIF {
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,6 +1,8 @@
#ifndef FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#define FSFW_OBJECTMANAGER_OBJECTMANAGERIF_H_
#include <map>
#include "../returnvalues/returnvalue.h"
#include "../serviceinterface/ServiceInterface.h"
#include "SystemObjectIF.h"
@ -58,12 +60,14 @@ 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

@ -568,11 +568,13 @@ inline ReturnValue_t Service11TelecommandScheduling<MAX_NUM_TCS>::getMapFilterFr
return INVALID_TIME_WINDOW;
}
itBegin = telecommandMap.begin();
itEnd = telecommandMap.begin();
while (itBegin->first < fromTimestamp && itBegin != telecommandMap.end()) {
itBegin++;
}
// start looking for end beginning at begin
itEnd = itBegin;
while (itEnd->first <= toTimestamp && itEnd != telecommandMap.end()) {
itEnd++;
}

View File

@ -11,7 +11,7 @@ Service1TelecommandVerification::Service1TelecommandVerification(object_id_t obj
uint16_t apid, uint8_t serviceId,
object_id_t targetDestination,
uint16_t messageQueueDepth,
TimeStamperIF* timeStamper)
TimeWriterIF* timeStamper)
: SystemObject(objectId),
apid(apid),
serviceId(serviceId),
@ -134,7 +134,7 @@ ReturnValue_t Service1TelecommandVerification::initialize() {
storeHelper.setTmStore(*tmStore);
}
if (timeStamper == nullptr) {
timeStamper = ObjectManager::instance()->get<TimeStamperIF>(objects::TIME_STAMPER);
timeStamper = ObjectManager::instance()->get<TimeWriterIF>(objects::TIME_STAMPER);
if (timeStamper == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}

View File

@ -47,7 +47,7 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF,
Service1TelecommandVerification(object_id_t objectId, uint16_t apid, uint8_t serviceId,
object_id_t targetDestination, uint16_t messageQueueDepth,
TimeStamperIF* timeStamper = nullptr);
TimeWriterIF* timeStamper = nullptr);
~Service1TelecommandVerification() override;
/**
@ -87,7 +87,7 @@ class Service1TelecommandVerification : public AcceptsVerifyMessageIF,
TmStoreHelper storeHelper;
TmStoreAndSendWrapper tmHelper;
InternalErrorReporterIF* errReporter = nullptr;
TimeStamperIF* timeStamper = nullptr;
TimeWriterIF* timeStamper = nullptr;
StorageManagerIF* tmStore = nullptr;
MessageQueueIF* tmQueue = nullptr;

View File

@ -1,8 +1,6 @@
#ifndef FSFW_RETURNVALUES_RETURNVALUE_H_
#define FSFW_RETURNVALUES_RETURNVALUE_H_
#include <returnvalues/classIds.h>
#include <cstdint>
#include "FwClassIds.h"

View File

@ -21,7 +21,7 @@ SerialBufferAdapter<count_t>::SerialBufferAdapter(uint8_t* buffer, count_t buffe
bufferLength(bufferLength) {}
template <typename count_t>
SerialBufferAdapter<count_t>::~SerialBufferAdapter() {}
SerialBufferAdapter<count_t>::~SerialBufferAdapter() = default;
template <typename count_t>
ReturnValue_t SerialBufferAdapter<count_t>::serialize(uint8_t** buffer, size_t* size,
@ -119,10 +119,10 @@ const uint8_t* SerialBufferAdapter<count_t>::getConstBuffer() const {
}
template <typename count_t>
void SerialBufferAdapter<count_t>::setBuffer(uint8_t* buffer, count_t bufferLength) {
this->buffer = buffer;
this->constBuffer = buffer;
this->bufferLength = bufferLength;
void SerialBufferAdapter<count_t>::setConstBuffer(const uint8_t* buf, count_t bufLen) {
this->buffer = nullptr;
this->bufferLength = bufLen;
this->constBuffer = buf;
}
// forward Template declaration for linker

View File

@ -21,6 +21,7 @@
template <typename count_t>
class SerialBufferAdapter : public SerializeIF {
public:
SerialBufferAdapter() = default;
/**
* Constructor for constant uint8_t buffer. Length field can be serialized optionally.
* Type of length can be supplied as template type.
@ -40,12 +41,12 @@ class SerialBufferAdapter : public SerializeIF {
*/
SerialBufferAdapter(uint8_t* buffer, count_t bufferLength, bool serializeLength = false);
virtual ~SerialBufferAdapter();
~SerialBufferAdapter() override;
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
virtual size_t getSerializedSize() const override;
[[nodiscard]] size_t getSerializedSize() const override;
/**
* @brief This function deserializes a buffer into the member buffer.
@ -59,12 +60,12 @@ class SerialBufferAdapter : public SerializeIF {
* @param bigEndian
* @return
*/
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override;
uint8_t* getBuffer();
const uint8_t* getConstBuffer() const;
void setBuffer(uint8_t* buffer, count_t bufferLength);
[[nodiscard]] const uint8_t* getConstBuffer() const;
void setConstBuffer(const uint8_t* buf, count_t bufLen);
private:
bool serializeLength = false;

View File

@ -1,8 +1,8 @@
#include "fsfw/serviceinterface/ServiceInterfaceBuffer.h"
#include "ServiceInterfaceBuffer.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
#include <inttypes.h>
#include <cinttypes>
#include <cstring>
@ -16,8 +16,6 @@
// to be implemented by bsp
extern "C" void printChar(const char*, bool errStream);
#ifndef UT699
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addCrToPreamble,
bool buffered, bool errStream, uint16_t port)
: isActive(true),
@ -58,6 +56,9 @@ ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string setMessage, bool addC
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
if (not isActive) {
return;
}
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
@ -74,8 +75,6 @@ void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
}
}
#endif
int ServiceInterfaceBuffer::overflow(int c) {
if (not buffered and this->isActive) {
if (c != Traits::eof()) {
@ -169,89 +168,4 @@ void ServiceInterfaceBuffer::setAsciiColorPrefix(std::string colorPrefix) {
}
#endif
#ifdef UT699
#include "../osal/rtems/Interrupt.h"
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port) {
this->log_message = set_message;
this->isActive = true;
setp(buf, buf + BUF_SIZE);
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
length = sizeof(array);
}
memcpy(array, begin, length);
if (!Interrupt::isInterruptInProgress()) {
std::cout << array;
} else {
// Uncomment the following line if you need ISR debug output.
// printk(array);
}
}
#endif // UT699
#ifdef ML505
#include <bsp_flp/network/networkconfig.h>
ServiceInterfaceBuffer::ServiceInterfaceBuffer(std::string set_message, uint16_t port)
: isActive(true),
log_message(set_message),
udpSocket(0),
remoteAddressLength(sizeof(remoteAddress)) {
setp(buf, buf + BUF_SIZE);
memset((uint8_t*)&remoteAddress, 0, sizeof(remoteAddress));
remoteAddress.sin_family = AF_INET;
remoteAddress.sin_port = htons(port);
remoteAddress.sin_addr.s_addr = htonl(inet_addr("192.168.250.100"));
}
void ServiceInterfaceBuffer::putChars(char const* begin, char const* end) {
char array[BUF_SIZE];
uint32_t length = end - begin;
if (length > sizeof(array)) {
length = sizeof(array);
}
memcpy(array, begin, length);
if (udpSocket <= 0) {
initSocket();
}
if (udpSocket > 0) {
sendto(udpSocket, array, length, 0, (sockaddr*)&remoteAddress, sizeof(remoteAddress));
}
}
void ServiceInterfaceBuffer::initSocket() {
sockaddr_in address;
memset((uint8_t*)&address, 0, sizeof(address));
address.sin_family = AF_INET;
address.sin_port = htons(0);
address.sin_addr.s_addr = htonl(INADDR_ANY);
udpSocket = socket(PF_INET, SOCK_DGRAM, 0);
if (socket < 0) {
printf("Error opening socket!\n");
return;
}
timeval timeout = {0, 20};
if (setsockopt(udpSocket, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0) {
printf("Error setting SO_RCVTIMEO socket options!\n");
return;
}
if (setsockopt(udpSocket, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0) {
printf("Error setting SO_SNDTIMEO socket options!\n");
return;
}
if (bind(udpSocket, (sockaddr*)&address, sizeof(address)) < 0) {
printf("Error binding socket!\n");
}
}
#endif // ML505
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif

View File

@ -1,9 +1,8 @@
#ifndef FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
#define FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_
#include <FSFWConfig.h>
#include "../returnvalues/returnvalue.h"
#include "fsfw/FSFW.h"
#include "fsfw/returnvalues/returnvalue.h"
#if FSFW_CPP_OSTREAM_ENABLED == 1
@ -11,8 +10,6 @@
#include <iostream>
#include <sstream>
#ifndef UT699
/**
* @brief This is the underlying stream buffer which implements the
* streambuf class and overloads the overflow() and sync() methods
@ -77,85 +74,6 @@ class ServiceInterfaceBuffer : public std::streambuf {
bool crAdditionEnabled() const;
};
#endif
#ifdef UT699
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
friend class ServiceInterfaceStream;
public:
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
protected:
bool isActive;
// This is called when buffer becomes full. If
// buffer is not used, then this is called every
// time when characters are put to stream.
virtual int overflow(int c = Traits::eof());
// This function is called when stream is flushed,
// for example when std::endl is put to stream.
virtual int sync(void);
private:
// For additional message information
std::string log_message;
// For EOF detection
typedef std::char_traits<char> Traits;
// Work in buffer mode. It is also possible to work without buffer.
static size_t const BUF_SIZE = 128;
char buf[BUF_SIZE];
// In this function, the characters are parsed.
void putChars(char const* begin, char const* end);
};
#endif // UT699
#ifdef ML505
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <sys/socket.h>
#include <sys/types.h>
class ServiceInterfaceBuffer : public std::basic_streambuf<char, std::char_traits<char> > {
friend class ServiceInterfaceStream;
public:
ServiceInterfaceBuffer(std::string set_message, uint16_t port);
protected:
bool isActive;
// This is called when buffer becomes full. If
// buffer is not used, then this is called every
// time when characters are put to stream.
virtual int overflow(int c = Traits::eof());
// This function is called when stream is flushed,
// for example when std::endl is put to stream.
virtual int sync(void);
private:
// For additional message information
std::string log_message;
// For EOF detection
typedef std::char_traits<char> Traits;
// Work in buffer mode. It is also possible to work without buffer.
static size_t const BUF_SIZE = 128;
char buf[BUF_SIZE];
// In this function, the characters are parsed.
void putChars(char const* begin, char const* end);
int udpSocket;
sockaddr_in remoteAddress;
socklen_t remoteAddressLength;
void initSocket();
};
#endif // ML505
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FRAMEWORK_SERVICEINTERFACE_SERVICEINTERFACEBUFFER_H_ */

View File

@ -327,3 +327,7 @@ ReturnValue_t SubsystemBase::setHealth(HealthState health) {
HasHealthIF::HealthState SubsystemBase::getHealth() { return healthHelper.getHealth(); }
void SubsystemBase::modeChanged() {}
const ModeHelper * SubsystemBase::getModeHelper() const {
return &modeHelper;
}

View File

@ -40,7 +40,9 @@ class SubsystemBase : public SystemObject,
uint16_t commandQueueDepth = 8);
virtual ~SubsystemBase();
virtual MessageQueueId_t getCommandQueue() const override;
MessageQueueId_t getCommandQueue() const override;
const ModeHelper * getModeHelper() const override;
/**
* Function to register the child objects.
@ -55,13 +57,13 @@ class SubsystemBase : public SystemObject,
*/
ReturnValue_t registerChild(object_id_t objectId);
virtual ReturnValue_t initialize() override;
ReturnValue_t initialize() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t setHealth(HealthState health) override;
ReturnValue_t setHealth(HealthState health) override;
virtual HasHealthIF::HealthState getHealth() override;
HasHealthIF::HealthState getHealth() override;
protected:
struct ChildInfo {

View File

@ -6,11 +6,6 @@
CdsShortTimeStamper::CdsShortTimeStamper(object_id_t objectId) : SystemObject(objectId) {}
ReturnValue_t CdsShortTimeStamper::addTimeStamp(uint8_t *buffer, const uint8_t maxSize) {
size_t serLen = 0;
return serialize(&buffer, &serLen, maxSize, SerializeIF::Endianness::NETWORK);
}
ReturnValue_t CdsShortTimeStamper::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (*size + getSerializedSize() > maxSize) {
@ -33,15 +28,22 @@ size_t CdsShortTimeStamper::getSerializedSize() const { return getTimestampSize(
ReturnValue_t CdsShortTimeStamper::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
if (size == nullptr or buffer == nullptr) {
return returnvalue::FAILED;
}
ReturnValue_t CdsShortTimeStamper::readTimeStamp(const uint8_t *buffer, size_t maxSize) {
if (maxSize < getTimestampSize()) {
}
if (*size < getTimestampSize()) {
return SerializeIF::STREAM_TOO_SHORT;
}
size_t foundLen = 0;
return CCSDSTime::convertFromCcsds(&readTime, buffer, &foundLen, maxSize);
if (((**buffer >> 4) & 0b111) != CCSDSTime::TimeCodeIdentification::CDS) {
return BAD_TIMESTAMP;
}
auto res = CCSDSTime::convertFromCcsds(&readTime, *buffer, &foundLen, *size);
if (res == returnvalue::OK) {
*size -= getSerializedSize();
*buffer += getSerializedSize();
}
return res;
}
timeval &CdsShortTimeStamper::getTime() { return readTime; }

View File

@ -3,7 +3,7 @@
#include "CCSDSTime.h"
#include "TimeReaderIF.h"
#include "TimeStamperIF.h"
#include "TimeWriterIF.h"
#include "fsfw/objectmanager/SystemObject.h"
/**
@ -15,7 +15,7 @@
* overriding the #addTimeStamp function.
* @ingroup utility
*/
class CdsShortTimeStamper : public TimeStamperIF, public TimeReaderIF, public SystemObject {
class CdsShortTimeStamper : public TimeWriterIF, public TimeReaderIF, public SystemObject {
public:
static constexpr size_t TIMESTAMP_LEN = 7;
/**
@ -25,20 +25,11 @@ class CdsShortTimeStamper : public TimeStamperIF, public TimeReaderIF, public Sy
*/
explicit CdsShortTimeStamper(object_id_t objectId);
/**
* Adds a CCSDS CDC short 8 byte timestamp to the given buffer.
* This function can be overriden to use a custom timestamp.
* @param buffer
* @param maxSize
* @return
*/
ReturnValue_t addTimeStamp(uint8_t *buffer, uint8_t maxSize) override;
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
Endianness streamEndianness) const override;
[[nodiscard]] size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override;
ReturnValue_t readTimeStamp(const uint8_t *buffer, size_t maxSize) override;
timeval &getTime() override;
[[nodiscard]] size_t getTimestampSize() const override;

View File

@ -5,12 +5,28 @@
#include "TimeStampIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeIF.h"
class TimeReaderIF : public TimeStampIF {
class TimeReaderIF : public SerializeIF, public TimeStampIF {
public:
~TimeReaderIF() override = default;
virtual ReturnValue_t readTimeStamp(const uint8_t* buffer, size_t maxSize) = 0;
virtual timeval& getTime() = 0;
[[nodiscard]] size_t getSerializedSize() const override { return getTimestampSize(); }
ReturnValue_t readTimeStamp(const uint8_t* buf, size_t maxSize) {
size_t dummy = 0;
return deSerialize(buf, dummy, maxSize, SerializeIF::Endianness::NETWORK);
}
private:
/**
* Forbidden, use dedicated IF @TimeWriterIF
*/
[[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override {
return returnvalue::FAILED;
}
};
#endif // FSFW_TIMEMANAGER_TIMEREADERIF_H

View File

@ -1,23 +0,0 @@
#ifndef FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
#define FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
#include "TimeStampIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* A class implementing this IF provides facilities to add a time stamp to the
* buffer provided.
* Implementors need to ensure that calling the method is thread-safe, i.e.
* addTimeStamp may be called in parallel from a different context.
*/
class TimeStamperIF : public SerializeIF, public TimeStampIF {
public:
virtual ReturnValue_t addTimeStamp(uint8_t* buffer, uint8_t maxSize) = 0;
~TimeStamperIF() override = default;
size_t getTimestampSize() const override { return getSerializedSize(); }
protected:
};
#endif /* FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ */

View File

@ -0,0 +1,34 @@
#ifndef FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
#define FSFW_TIMEMANAGER_TIMESTAMPERIF_H_
#include "TimeStampIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serialize/SerializeIF.h"
/**
* A class implementing this IF provides facilities to add a time stamp to the
* buffer provided.
* Implementors need to ensure that calling the method is thread-safe, i.e.
* addTimeStamp may be called in parallel from a different context.
*/
class TimeWriterIF : public SerializeIF, public TimeStampIF {
public:
~TimeWriterIF() override = default;
[[nodiscard]] size_t getTimestampSize() const override { return getSerializedSize(); }
ReturnValue_t addTimeStamp(uint8_t *buf, size_t maxSize) {
size_t dummy = 0;
return serialize(buf, dummy, maxSize, SerializeIF::Endianness::NETWORK);
}
private:
/**
* Forbidden, use dedicated IF @TimeReaderIF
*/
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
Endianness streamEndianness) override {
return returnvalue::FAILED;
}
};
#endif /* FSFW_TIMEMANAGER_TIMESTAMPERIF_H_ */

View File

@ -7,7 +7,7 @@
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerializeElement.h"
#include "fsfw/timemanager/CCSDSTime.h"
#include "fsfw/timemanager/TimeStamperIF.h"
#include "fsfw/timemanager/TimeWriterIF.h"
#include "fsfw/tmtcpacket/pus/tm/PusTmMinimal.h"
#include "tmStorageConf.h"

View File

@ -7,6 +7,6 @@ class CustomUserDataIF {
public:
virtual ~CustomUserDataIF() = default;
virtual ReturnValue_t setRawUserData(const uint8_t* data, size_t len) = 0;
virtual ReturnValue_t setSerializableUserData(SerializeIF& serializable) = 0;
virtual ReturnValue_t setSerializableUserData(const SerializeIF& serializable) = 0;
};
#endif // FSFW_TMTCPACKET_CREATORDATAIF_H

View File

@ -14,7 +14,6 @@ PusTcCreator::PusTcCreator(SpacePacketParams spParams, PusTcParams pusParams)
ReturnValue_t PusTcCreator::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
const uint8_t *start = *buffer;
size_t userDataLen = pusParams.dataWrapper.getLength();
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
@ -37,17 +36,8 @@ ReturnValue_t PusTcCreator::serialize(uint8_t **buffer, size_t *size, size_t max
if (result != returnvalue::OK) {
return result;
}
if (pusParams.dataWrapper.type == util::DataTypes::RAW) {
const uint8_t *data = pusParams.dataWrapper.dataUnion.raw.data;
if (data != nullptr and userDataLen > 0) {
std::memcpy(*buffer, data, userDataLen);
*buffer += userDataLen;
*size += userDataLen;
}
} else if (pusParams.dataWrapper.type == util::DataTypes::SERIALIZABLE and
pusParams.dataWrapper.dataUnion.serializable != nullptr) {
result = pusParams.dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize,
streamEndianness);
if (pusParams.appData != nullptr) {
result = pusParams.appData->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
@ -58,8 +48,11 @@ ReturnValue_t PusTcCreator::serialize(uint8_t **buffer, size_t *size, size_t max
}
void PusTcCreator::updateSpLengthField() {
spCreator.setDataLen(ecss::PusTcDataFieldHeader::MIN_SIZE + pusParams.dataWrapper.getLength() +
1);
size_t len = ecss::PusTcDataFieldHeader::MIN_SIZE + 1;
if (pusParams.appData != nullptr) {
len += pusParams.appData->getSerializedSize();
}
spCreator.setDataLen(len);
}
size_t PusTcCreator::getSerializedSize() const { return spCreator.getFullPacketLen(); }
@ -91,14 +84,15 @@ SpacePacketParams &PusTcCreator::getSpParams() { return spCreator.getParams(); }
ReturnValue_t PusTcCreator::setRawUserData(const uint8_t *data, size_t len) {
// TODO: Check length field?
pusParams.dataWrapper.setRawData({data, len});
pusParams.bufAdapter.setConstBuffer(data, len);
pusParams.appData = &pusParams.bufAdapter;
updateSpLengthField();
return returnvalue::OK;
}
ReturnValue_t PusTcCreator::setSerializableUserData(SerializeIF &serializable) {
ReturnValue_t PusTcCreator::setSerializableUserData(const SerializeIF &serializable) {
// TODO: Check length field?
pusParams.dataWrapper.setSerializable(serializable);
pusParams.appData = &serializable;
updateSpLengthField();
return returnvalue::OK;
}

View File

@ -1,22 +1,30 @@
#ifndef FSFW_TMTCPACKET_TCPACKETDESERIALIZER_H
#define FSFW_TMTCPACKET_TCPACKETDESERIALIZER_H
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/tmtcpacket/RedirectableDataPointerIF.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketIF.h"
#include "fsfw/tmtcpacket/pus/CustomUserDataIF.h"
#include "fsfw/tmtcpacket/pus/defs.h"
#include "fsfw/tmtcpacket/pus/tc/PusTcIF.h"
#include "fsfw/util/dataWrapper.h"
struct PusTcParams {
PusTcParams(uint8_t service_, uint8_t subservice_) : service(service_), subservice(subservice_) {}
void setRawAppData(const uint8_t *data, size_t len) {
bufAdapter.setConstBuffer(data, len);
appData = &bufAdapter;
}
void setSerializableAppData(const SerializeIF &serializable) { appData = &serializable; }
uint8_t service;
uint8_t subservice;
uint8_t ackFlags = ecss::ACK_ALL;
uint16_t sourceId = 0;
util::DataWrapper dataWrapper{};
SerialBufferAdapter<uint8_t> bufAdapter;
const SerializeIF *appData = nullptr;
uint8_t pusVersion = ecss::PusVersion::PUS_C;
};
@ -52,7 +60,7 @@ class PusTcCreator : public PusTcIF, public SerializeIF, public CustomUserDataIF
[[nodiscard]] uint8_t getSubService() const override;
[[nodiscard]] uint16_t getSourceId() const override;
ReturnValue_t setRawUserData(const uint8_t *data, size_t len) override;
ReturnValue_t setSerializableUserData(SerializeIF &serializable) override;
ReturnValue_t setSerializableUserData(const SerializeIF &serializable) override;
// Load all big endian helpers into the class namespace
using SerializeIF::serializeBe;

View File

@ -3,7 +3,7 @@
#include <utility>
#include "fsfw/globalfunctions/CRC.h"
#include "fsfw/timemanager/TimeStamperIF.h"
#include "fsfw/timemanager/TimeWriterIF.h"
PusTmCreator::PusTmCreator(SpacePacketParams initSpParams, PusTmParams initPusParams)
: pusParams(initPusParams), spCreator(std::move(initSpParams)) {
@ -30,7 +30,7 @@ uint8_t PusTmCreator::getSubService() const { return pusParams.secHeader.subserv
PusTmParams& PusTmCreator::getParams() { return pusParams; }
void PusTmCreator::setTimeStamper(TimeStamperIF& timeStamper_) {
void PusTmCreator::setTimeStamper(TimeWriterIF& timeStamper_) {
pusParams.secHeader.timeStamper = &timeStamper_;
updateSpLengthField();
}
@ -51,7 +51,6 @@ ReturnValue_t PusTmCreator::serialize(uint8_t** buffer, size_t* size, size_t max
if (result != returnvalue::OK) {
return result;
}
size_t userDataLen = pusParams.dataWrapper.getLength();
**buffer =
((pusParams.secHeader.pusVersion << 4) & 0xF0) | (pusParams.secHeader.scTimeRefStatus & 0x0F);
*buffer += 1;
@ -77,15 +76,8 @@ ReturnValue_t PusTmCreator::serialize(uint8_t** buffer, size_t* size, size_t max
}
}
if (pusParams.dataWrapper.type == util::DataTypes::RAW and
pusParams.dataWrapper.dataUnion.raw.data != nullptr) {
std::memcpy(*buffer, pusParams.dataWrapper.dataUnion.raw.data, userDataLen);
*buffer += userDataLen;
*size += userDataLen;
} else if (pusParams.dataWrapper.type == util::DataTypes::SERIALIZABLE and
pusParams.dataWrapper.dataUnion.serializable != nullptr) {
result = pusParams.dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize,
streamEndianness);
if (pusParams.sourceData != nullptr) {
result = pusParams.sourceData->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
@ -106,13 +98,15 @@ ReturnValue_t PusTmCreator::deSerialize(const uint8_t** buffer, size_t* size,
return returnvalue::FAILED;
}
TimeStamperIF* PusTmCreator::getTimestamper() const { return pusParams.secHeader.timeStamper; }
TimeWriterIF* PusTmCreator::getTimestamper() const { return pusParams.secHeader.timeStamper; }
SpacePacketParams& PusTmCreator::getSpParams() { return spCreator.getParams(); }
void PusTmCreator::updateSpLengthField() {
size_t headerLen = PusTmIF::MIN_SEC_HEADER_LEN + pusParams.dataWrapper.getLength() +
sizeof(ecss::PusChecksumT) - 1;
size_t headerLen = PusTmIF::MIN_SEC_HEADER_LEN + sizeof(ecss::PusChecksumT) - 1;
if (pusParams.sourceData != nullptr) {
headerLen += pusParams.sourceData->getSerializedSize();
}
if (pusParams.secHeader.timeStamper != nullptr) {
headerLen += pusParams.secHeader.timeStamper->getSerializedSize();
}
@ -134,12 +128,17 @@ void PusTmCreator::setMessageTypeCounter(uint16_t messageTypeCounter) {
void PusTmCreator::setDestId(uint16_t destId) { pusParams.secHeader.destId = destId; }
ReturnValue_t PusTmCreator::setRawUserData(const uint8_t* data, size_t len) {
pusParams.dataWrapper.setRawData({data, len});
if (data == nullptr or len == 0) {
pusParams.sourceData = nullptr;
} else {
pusParams.adapter.setConstBuffer(data, len);
pusParams.sourceData = &pusParams.adapter;
}
updateSpLengthField();
return returnvalue::OK;
}
ReturnValue_t PusTmCreator::setSerializableUserData(SerializeIF& serializable) {
pusParams.dataWrapper.setSerializable(serializable);
ReturnValue_t PusTmCreator::setSerializableUserData(const SerializeIF& serializable) {
pusParams.sourceData = &serializable;
updateSpLengthField();
return returnvalue::OK;
}

View File

@ -2,18 +2,18 @@
#define FSFW_TMTCPACKET_TMPACKETCREATOR_H
#include "PusTmIF.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/tmtcpacket/ccsds/SpacePacketCreator.h"
#include "fsfw/tmtcpacket/pus/CustomUserDataIF.h"
#include "fsfw/util/dataWrapper.h"
struct PusTmSecHeader {
PusTmSecHeader() = default;
PusTmSecHeader(uint8_t service, uint8_t subservice, TimeStamperIF* timeStamper)
PusTmSecHeader(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper)
: service(service), subservice(subservice), timeStamper(timeStamper) {}
uint8_t service = 0;
uint8_t subservice = 0;
TimeStamperIF* timeStamper = nullptr;
TimeWriterIF* timeStamper = nullptr;
uint8_t pusVersion = ecss::PusVersion::PUS_C;
uint8_t scTimeRefStatus = 0;
uint16_t messageTypeCounter = 0;
@ -23,22 +23,28 @@ struct PusTmSecHeader {
struct PusTmParams {
PusTmParams() = default;
explicit PusTmParams(PusTmSecHeader secHeader) : secHeader(secHeader){};
PusTmParams(PusTmSecHeader secHeader, util::DataWrapper dataWrapper)
: secHeader(secHeader), dataWrapper(dataWrapper) {}
PusTmParams(uint8_t service, uint8_t subservice, TimeStamperIF* timeStamper)
PusTmParams(PusTmSecHeader secHeader, const SerializeIF& data)
: secHeader(secHeader), sourceData(&data) {}
PusTmParams(PusTmSecHeader secHeader, const uint8_t* data, size_t dataLen)
: secHeader(secHeader), adapter(data, dataLen), sourceData(&adapter) {}
PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper)
: secHeader(service, subservice, timeStamper) {}
PusTmParams(uint8_t service, uint8_t subservice, TimeStamperIF* timeStamper,
util::DataWrapper dataWrapper_)
PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper,
const SerializeIF& data_)
: PusTmParams(service, subservice, timeStamper) {
dataWrapper = dataWrapper_;
sourceData = &data_;
}
PusTmParams(uint8_t service, uint8_t subservice, TimeWriterIF* timeStamper, const uint8_t* data,
size_t dataLen)
: secHeader(service, subservice, timeStamper), adapter(data, dataLen), sourceData(&adapter) {}
PusTmSecHeader secHeader;
util::DataWrapper dataWrapper{};
SerialBufferAdapter<uint8_t> adapter;
const SerializeIF* sourceData = nullptr;
};
class TimeStamperIF;
class TimeWriterIF;
/**
* This class provides a high-level interface to create PUS TM packets and then @serialize
@ -56,7 +62,7 @@ class PusTmCreator : public SerializeIF, public PusTmIF, public CustomUserDataIF
PusTmCreator(SpacePacketParams initSpParams, PusTmParams initPusParams);
~PusTmCreator() override = default;
void setTimeStamper(TimeStamperIF& timeStamper);
void setTimeStamper(TimeWriterIF& timeStamper);
/**
* This function disables the CRC16 calculation on serialization. This is useful to avoid
* duplicate calculation if some lower level component needs to update fields like the sequence
@ -86,9 +92,9 @@ class PusTmCreator : public SerializeIF, public PusTmIF, public CustomUserDataIF
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
[[nodiscard]] size_t getSerializedSize() const override;
[[nodiscard]] TimeStamperIF* getTimestamper() const;
[[nodiscard]] TimeWriterIF* getTimestamper() const;
ReturnValue_t setRawUserData(const uint8_t* data, size_t len) override;
ReturnValue_t setSerializableUserData(SerializeIF& serializable) override;
ReturnValue_t setSerializableUserData(const SerializeIF& serializable) override;
// Load all big endian (network endian) helpers into scope
using SerializeIF::serializeBe;

View File

@ -4,7 +4,7 @@
#include <cstddef>
#include <cstdint>
#include "fsfw/timemanager/TimeStamperIF.h"
#include "fsfw/timemanager/TimeWriterIF.h"
#include "fsfw/tmtcpacket/pus/PusIF.h"
#include "fsfw/tmtcpacket/pus/defs.h"

View File

@ -106,7 +106,7 @@ ReturnValue_t CommandingServiceBase::initialize() {
// This avoids duplicate calculation of the CRC16
tmStoreHelper.disableCrcCalculation();
if (tmTimeStamper == nullptr) {
tmTimeStamper = ObjectManager::instance()->get<TimeStamperIF>(objects::TIME_STAMPER);
tmTimeStamper = ObjectManager::instance()->get<TimeWriterIF>(objects::TIME_STAMPER);
if (tmTimeStamper == nullptr) {
return ObjectManagerIF::CHILD_INIT_FAILED;
}

View File

@ -272,7 +272,7 @@ class CommandingServiceBase : public SystemObject,
MessageQueueIF* commandQueue = nullptr;
MessageQueueIF* requestQueue = nullptr;
TimeStamperIF* tmTimeStamper = nullptr;
TimeWriterIF* tmTimeStamper = nullptr;
VerificationReporterIF* verificationReporter;
InternalErrorReporterIF* errReporter = nullptr;

View File

@ -178,7 +178,7 @@ ReturnValue_t PusServiceBase::initializeTmStoreHelper(TmStoreHelper& tmStoreHelp
}
if (psbParams.timeStamper == nullptr) {
auto timerStamper = ObjectManager::instance()->get<TimeStamperIF>(objects::TIME_STAMPER);
auto timerStamper = ObjectManager::instance()->get<TimeWriterIF>(objects::TIME_STAMPER);
if (timerStamper != nullptr) {
tmStoreHelper.setTimeStamper(*timerStamper);
}

View File

@ -65,7 +65,7 @@ struct PsbParams {
* register itself at that object.
*/
PUSDistributorIF* pusDistributor = nullptr;
TimeStamperIF* timeStamper = nullptr;
TimeWriterIF* timeStamper = nullptr;
};
namespace Factory {

View File

@ -11,7 +11,7 @@ TmStoreHelper::TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore) :
}
TmStoreHelper::TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore,
TimeStamperIF& timeStamper)
TimeWriterIF& timeStamper)
: tmStore(&tmStore) {
creator.setApid(defaultApid);
creator.setTimeStamper(timeStamper);
@ -59,7 +59,7 @@ ReturnValue_t TmStoreHelper::addPacketToStore() {
SerializeIF::Endianness::NETWORK);
}
void TmStoreHelper::setTimeStamper(TimeStamperIF& timeStamper_) {
void TmStoreHelper::setTimeStamper(TimeWriterIF& timeStamper_) {
creator.setTimeStamper(timeStamper_);
}
@ -67,7 +67,7 @@ void TmStoreHelper::setApid(uint16_t apid) { creator.setApid(apid); }
PusTmCreator& TmStoreHelper::getCreatorRef() { return creator; }
TimeStamperIF* TmStoreHelper::getTimeStamper() const { return creator.getTimestamper(); }
TimeWriterIF* TmStoreHelper::getTimeStamper() const { return creator.getTimestamper(); }
uint16_t TmStoreHelper::getApid() const { return creator.getApid(); }

View File

@ -4,14 +4,14 @@
#include "fsfw/internalerror/InternalErrorReporterIF.h"
#include "fsfw/ipc/MessageQueueMessageIF.h"
#include "fsfw/storagemanager/StorageManagerIF.h"
#include "fsfw/timemanager/TimeStamperIF.h"
#include "fsfw/timemanager/TimeWriterIF.h"
#include "fsfw/tmtcpacket/pus/tm/PusTmCreator.h"
class TmStoreHelper {
public:
explicit TmStoreHelper(uint16_t defaultApid);
TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore);
TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore, TimeStamperIF& timeStamper);
TmStoreHelper(uint16_t defaultApid, StorageManagerIF& tmStore, TimeWriterIF& timeStamper);
void disableCrcCalculation();
[[nodiscard]] bool crcCalculationEnabled() const;
@ -20,8 +20,8 @@ class TmStoreHelper {
PusTmCreator& getCreatorRef();
void setTimeStamper(TimeStamperIF& timeStamper);
[[nodiscard]] TimeStamperIF* getTimeStamper() const;
void setTimeStamper(TimeWriterIF& timeStamper);
[[nodiscard]] TimeWriterIF* getTimeStamper() const;
[[nodiscard]] StorageManagerIF* getTmStore() const;
void setTmStore(StorageManagerIF& store);

View File

@ -10,48 +10,33 @@ namespace telemetry {
class DataWithObjectIdPrefix : public SerializeIF {
public:
DataWithObjectIdPrefix(object_id_t objectId, const uint8_t* srcData, size_t srcDataLen)
: objectId(objectId) {
dataWrapper.type = util::DataTypes::RAW;
dataWrapper.dataUnion.raw.data = srcData;
dataWrapper.dataUnion.raw.len = srcDataLen;
}
: objectId(objectId), bufAdapter(srcData, srcDataLen), userData(&bufAdapter) {}
DataWithObjectIdPrefix(object_id_t objectId, SerializeIF& serializable) : objectId(objectId) {
dataWrapper.type = util::DataTypes::SERIALIZABLE;
dataWrapper.dataUnion.serializable = &serializable;
}
DataWithObjectIdPrefix(object_id_t objectId, const SerializeIF& serializable)
: objectId(objectId), userData(&serializable) {}
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override {
if (*size + getSerializedSize() > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
if (dataWrapper.type != util::DataTypes::RAW) {
if ((dataWrapper.dataUnion.raw.data == nullptr) and (dataWrapper.dataUnion.raw.len > 0)) {
return returnvalue::FAILED;
}
} else if (dataWrapper.type == util::DataTypes::SERIALIZABLE) {
if (dataWrapper.dataUnion.serializable == nullptr) {
return returnvalue::FAILED;
}
}
ReturnValue_t result =
SerializeAdapter::serialize(&objectId, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
if (dataWrapper.type != util::DataTypes::RAW) {
std::memcpy(*buffer, dataWrapper.dataUnion.raw.data, dataWrapper.dataUnion.raw.len);
*buffer += dataWrapper.dataUnion.raw.len;
*size += dataWrapper.dataUnion.raw.len;
} else {
return dataWrapper.dataUnion.serializable->serialize(buffer, size, maxSize, streamEndianness);
if (userData != nullptr) {
return userData->serialize(buffer, size, maxSize, streamEndianness);
}
return returnvalue::OK;
}
[[nodiscard]] size_t getSerializedSize() const override {
return sizeof(objectId) + dataWrapper.getLength();
size_t len = 0;
if (userData != nullptr) {
len += userData->getSerializedSize();
}
return len;
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
@ -63,7 +48,8 @@ class DataWithObjectIdPrefix : public SerializeIF {
private:
object_id_t objectId;
util::DataWrapper dataWrapper{};
SerialBufferAdapter<uint8_t> bufAdapter;
const SerializeIF* userData = nullptr;
};
} // namespace telemetry

View File

@ -1 +1,3 @@
add_subdirectory(gpio)
target_sources(${LIB_FSFW_NAME} PRIVATE printChar.c)

View File

@ -0,0 +1,10 @@
#include <stdio.h>
#include <stdbool.h>
void __attribute__((weak)) printChar(const char* character, bool errStream) {
if (errStream) {
fprintf(stderr, "%c", *character);
} else {
printf("%c", *character);
}
}

View File

@ -2,7 +2,6 @@
#define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#include "devicedefinitions/MgmLIS3HandlerDefs.h"
#include "events/subsystemIdRanges.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"

View File

@ -18,6 +18,7 @@ add_subdirectory(power)
add_subdirectory(util)
add_subdirectory(container)
add_subdirectory(osal)
add_subdirectory(pus)
add_subdirectory(serialize)
add_subdirectory(datapoollocal)
add_subdirectory(storagemanager)

View File

@ -9,38 +9,35 @@
#include "mocks/MessageQueueMock.h"
TEST_CASE("Action Helper", "[ActionHelper]") {
ActionHelperOwnerMockBase testDhMock;
// TODO: Setting another number here breaks the test. Find out why
MessageQueueMock testMqMock(MessageQueueIF::NO_QUEUE);
ActionHelper actionHelper = ActionHelper(&testDhMock, dynamic_cast<MessageQueueIF*>(&testMqMock));
ActionHelperOwnerMockBase testDhMock(&testMqMock);
CommandMessage actionMessage;
ActionId_t testActionId = 777;
ActionId_t testActionId = (ActionId_t)TestActions::TEST_ACTION;
std::array<uint8_t, 3> testParams{1, 2, 3};
store_address_t paramAddress;
StorageManagerIF* ipcStore = tglob::getIpcStoreHandle();
REQUIRE(ipcStore != nullptr);
ipcStore->addData(&paramAddress, testParams.data(), 3);
REQUIRE(actionHelper.initialize() == returnvalue::OK);
REQUIRE(testDhMock.getActionHelper()->initialize() == returnvalue::OK);
SECTION("Simple tests") {
ActionMessage::setCommand(&actionMessage, testActionId, paramAddress);
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == returnvalue::OK);
CHECK(testDhMock.executeActionCalled);
// No message is sent if everything is alright.
CHECK(not testMqMock.wasMessageSent());
store_address_t invalidAddress;
ActionMessage::setCommand(&actionMessage, testActionId, invalidAddress);
actionHelper.handleActionMessage(&actionMessage);
testDhMock.getActionHelper()->handleActionMessage(&actionMessage);
CHECK(testMqMock.wasMessageSent());
const uint8_t* ptr = nullptr;
size_t size = 0;
REQUIRE(ipcStore->getData(paramAddress, &ptr, &size) ==
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
REQUIRE(ptr == nullptr);
REQUIRE(size == 0);
testDhMock.getBuffer(&ptr, &size);
REQUIRE(size == 3);
testDhMock.getBuffer(&ptr);
for (uint8_t i = 0; i < 3; i++) {
REQUIRE(ptr[i] == (i + 1));
}
@ -49,12 +46,12 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
SECTION("Handle failures") {
actionMessage.setCommand(1234);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) ==
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) ==
static_cast<uint32_t>(CommandMessage::UNKNOWN_COMMAND));
CHECK(not testMqMock.wasMessageSent());
uint16_t step = 5;
ReturnValue_t status = 0x1234;
actionHelper.step(step, testMqMock.getId(), testActionId, status);
testDhMock.getActionHelper()->step(step, testMqMock.getId(), testActionId, status);
step += 1;
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
@ -69,7 +66,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
SECTION("Handle finish") {
CHECK(not testMqMock.wasMessageSent());
ReturnValue_t status = 0x9876;
actionHelper.finish(false, testMqMock.getId(), testActionId, status);
testDhMock.getActionHelper()->finish(false, testMqMock.getId(), testActionId, status);
CHECK(testMqMock.wasMessageSent());
CommandMessage testMessage;
REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
@ -84,13 +81,13 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
REQUIRE(ipcStore->addData(&toLongParamAddress, toLongData.data(), 5) == returnvalue::OK);
ActionMessage::setCommand(&actionMessage, testActionId, toLongParamAddress);
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == returnvalue::OK);
REQUIRE(ipcStore->getData(toLongParamAddress).first ==
static_cast<uint32_t>(StorageManagerIF::DATA_DOES_NOT_EXIST));
CommandMessage testMessage;
REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));
REQUIRE(ActionMessage::getReturnCode(&testMessage) == 0xAFFE);
REQUIRE(ActionMessage::getReturnCode(&testMessage) == HasActionsIF::INVALID_PARAMETERS);
REQUIRE(ActionMessage::getStep(&testMessage) == 0);
REQUIRE(ActionMessage::getActionId(&testMessage) == testActionId);
}
@ -98,7 +95,7 @@ TEST_CASE("Action Helper", "[ActionHelper]") {
SECTION("Missing IPC Data") {
ActionMessage::setCommand(&actionMessage, testActionId, store_address_t::invalid());
CHECK(not testDhMock.executeActionCalled);
REQUIRE(actionHelper.handleActionMessage(&actionMessage) == returnvalue::OK);
REQUIRE(testDhMock.getActionHelper()->handleActionMessage(&actionMessage) == returnvalue::OK);
CommandMessage testMessage;
REQUIRE(testMqMock.getNextSentMessage(testMessage) == returnvalue::OK);
REQUIRE(testMessage.getCommand() == static_cast<uint32_t>(ActionMessage::STEP_FAILED));

View File

@ -2,12 +2,27 @@
#define UNITTEST_HOSTED_TESTACTIONHELPER_H_
#include <fsfw/action/HasActionsIF.h>
#include <fsfw/action/Parameter.h>
#include <fsfw/action/TemplateAction.h>
#include <fsfw/introspection/Enum.h>
#include <fsfw/ipc/MessageQueueIF.h>
#include <cstring>
#include "CatchDefinitions.h"
class ActionHelperOwnerMockBase;
FSFW_ENUM(TestActions, ActionId_t, ((TEST_ACTION, "Test Action")))
class TestAction : public TemplateAction < ActionHelperOwnerMockBase, TestAction, TestActions> {
public:
TestAction(ActionHelperOwnerMockBase* owner) : TemplateAction(owner, TestActions::TEST_ACTION) {}
Parameter<uint8_t> p1 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
Parameter<uint8_t> p2 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
Parameter<uint8_t> p3 = Parameter<uint8_t>::createParameter(this, "An uint8_t");
};
class ActionHelperOwnerMockBase : public HasActionsIF {
public:
bool getCommandQueueCalled = false;
@ -16,16 +31,26 @@ class ActionHelperOwnerMockBase : public HasActionsIF {
uint8_t buffer[MAX_SIZE] = {0, 0, 0};
size_t size = 0;
ActionHelperOwnerMockBase(MessageQueueIF* useThisQueue) : actionHelper(this, useThisQueue) {}
MessageQueueId_t getCommandQueue() const override { return tconst::testQueueId; }
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override {
ActionHelper* getActionHelper() override { return &actionHelper; }
ReturnValue_t executeAction(Action* action) override {
executeActionCalled = true;
if (size > MAX_SIZE) {
return 0xAFFE;
}
this->size = size;
memcpy(buffer, data, size);
return action->handle();
}
ReturnValue_t handleAction(TestAction *action){
executeActionCalled = true;
buffer[0] = action->p1;
buffer[1] = action->p2;
buffer[2] = action->p3;
return returnvalue::OK;
}
@ -36,14 +61,15 @@ class ActionHelperOwnerMockBase : public HasActionsIF {
}
}
void getBuffer(const uint8_t** ptr, size_t* size) {
if (size != nullptr) {
*size = this->size;
}
void getBuffer(const uint8_t** ptr) {
if (ptr != nullptr) {
*ptr = buffer;
}
}
private:
ActionHelper actionHelper;
TestAction testAction = TestAction(this);
};
#endif /* UNITTEST_TESTFW_NEWTESTS_TESTACTIONHELPER_H_ */

View File

@ -23,7 +23,7 @@ TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
SECTION("Commanding nominal") {
comIF.setTestCase(ComIFMock::TestCase::SIMPLE_COMMAND_NOMINAL);
result = deviceHandlerCommander.sendCommand(objects::DEVICE_HANDLER_MOCK,
DeviceHandlerMock::SIMPLE_COMMAND);
static_cast<uint32_t>(MockCommands::SIMPLE_COMMAND));
REQUIRE(result == returnvalue::OK);
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
@ -43,7 +43,7 @@ TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
// Set the timeout to 0 to immediately timeout the reply
deviceHandlerMock.changeSimpleCommandReplyCountdown(0);
result = deviceHandlerCommander.sendCommand(objects::DEVICE_HANDLER_MOCK,
DeviceHandlerMock::SIMPLE_COMMAND);
static_cast<uint32_t>(MockCommands::SIMPLE_COMMAND));
REQUIRE(result == returnvalue::OK);
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
@ -60,7 +60,7 @@ TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
SECTION("Periodic reply nominal") {
comIF.setTestCase(ComIFMock::TestCase::PERIODIC_REPLY_NOMINAL);
deviceHandlerMock.enablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY);
deviceHandlerMock.enablePeriodicReply(static_cast<uint32_t>(MockCommands::PERIODIC_REPLY));
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE);
@ -73,7 +73,7 @@ TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
comIF.setTestCase(ComIFMock::TestCase::MISSED_REPLY);
// Set the timeout to 0 to immediately timeout the reply
deviceHandlerMock.changePeriodicReplyCountdown(0);
deviceHandlerMock.enablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY);
deviceHandlerMock.enablePeriodicReply(static_cast<uint32_t>(MockCommands::PERIODIC_REPLY));
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE);
@ -82,7 +82,7 @@ TEST_CASE("Device Handler Base", "[DeviceHandlerBase]") {
uint32_t missedReplies = deviceFdirMock.getMissedReplyCount();
REQUIRE(missedReplies == 1);
// Test if disabling of periodic reply
deviceHandlerMock.disablePeriodicReply(DeviceHandlerMock::PERIODIC_REPLY);
deviceHandlerMock.disablePeriodicReply(static_cast<uint32_t>(MockCommands::PERIODIC_REPLY));
deviceHandlerMock.performOperation(DeviceHandlerIF::PERFORM_OPERATION);
deviceHandlerMock.performOperation(DeviceHandlerIF::SEND_WRITE);
deviceHandlerMock.performOperation(DeviceHandlerIF::GET_WRITE);

View File

@ -4,9 +4,9 @@
#include <array>
#include "fsfw/timemanager/TimeReaderIF.h"
#include "fsfw/timemanager/TimeStamperIF.h"
#include "fsfw/timemanager/TimeWriterIF.h"
class CdsShortTimestamperMock : public TimeStamperIF, public TimeReaderIF {
class CdsShortTimestamperMock : public TimeWriterIF, public TimeReaderIF {
public:
unsigned int serializeCallCount = 0;
unsigned int deserializeCallCount = 0;
@ -61,7 +61,6 @@ class CdsShortTimestamperMock : public TimeStamperIF, public TimeReaderIF {
}
[[nodiscard]] size_t getTimestampSize() const override { return getSerializedSize(); }
ReturnValue_t addTimeStamp(uint8_t *buffer, uint8_t maxSize) override { return 0; }
void reset() {
serializeCallCount = 0;
@ -75,9 +74,6 @@ class CdsShortTimestamperMock : public TimeStamperIF, public TimeReaderIF {
serFailRetval = returnvalue::FAILED;
}
ReturnValue_t readTimeStamp(const uint8_t *buffer, size_t maxSize) override {
return deSerialize(&buffer, &maxSize, SerializeIF::Endianness::NETWORK);
}
timeval &getTime() override { return dummyTime; }
private:

View File

@ -25,17 +25,13 @@ ReturnValue_t DeviceHandlerMock::buildTransitionDeviceCommand(DeviceCommandId_t
ReturnValue_t DeviceHandlerMock::buildCommandFromCommand(DeviceCommandId_t deviceCommand,
const uint8_t *commandData,
size_t commandDataLen) {
switch (deviceCommand) {
case SIMPLE_COMMAND: {
return returnvalue::OK;
}
ReturnValue_t DeviceHandlerMock::handleAction(MockAction *action) {
commandBuffer[0] = SIMPLE_COMMAND_DATA;
rawPacket = commandBuffer;
rawPacketLen = sizeof(SIMPLE_COMMAND_DATA);
break;
}
default:
WARN("DeviceHandlerMock::buildCommandFromCommand: Invalid device command");
break;
}
return returnvalue::OK;
}
@ -43,13 +39,13 @@ ReturnValue_t DeviceHandlerMock::scanForReply(const uint8_t *start, size_t len,
DeviceCommandId_t *foundId, size_t *foundLen) {
switch (*start) {
case SIMPLE_COMMAND_DATA: {
*foundId = SIMPLE_COMMAND;
*foundId = static_cast<uint32_t>(MockCommands::SIMPLE_COMMAND);
*foundLen = sizeof(SIMPLE_COMMAND_DATA);
return returnvalue::OK;
break;
}
case PERIODIC_REPLY_DATA: {
*foundId = PERIODIC_REPLY;
*foundId = static_cast<uint32_t>(MockCommands::PERIODIC_REPLY);
*foundLen = sizeof(PERIODIC_REPLY_DATA);
return returnvalue::OK;
break;
@ -62,8 +58,8 @@ ReturnValue_t DeviceHandlerMock::scanForReply(const uint8_t *start, size_t len,
ReturnValue_t DeviceHandlerMock::interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) {
switch (id) {
case SIMPLE_COMMAND:
case PERIODIC_REPLY: {
case static_cast<uint32_t>(MockCommands::SIMPLE_COMMAND):
case static_cast<uint32_t>(MockCommands::PERIODIC_REPLY): {
periodicReplyReceived = true;
break;
}
@ -74,10 +70,10 @@ ReturnValue_t DeviceHandlerMock::interpretDeviceReply(DeviceCommandId_t id, cons
}
void DeviceHandlerMock::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(SIMPLE_COMMAND, 0, nullptr, 0, false, false, 0,
&simpleCommandReplyTimeout);
insertInCommandAndReplyMap(PERIODIC_REPLY, 0, nullptr, 0, true, false, 0,
&periodicReplyCountdown);
insertInCommandAndReplyMap(static_cast<uint32_t>(MockCommands::SIMPLE_COMMAND), 0, nullptr, 0,
false, false, 0, &simpleCommandReplyTimeout);
insertInCommandAndReplyMap(static_cast<uint32_t>(MockCommands::PERIODIC_REPLY), 0, nullptr, 0,
true, false, 0, &periodicReplyCountdown);
}
uint32_t DeviceHandlerMock::getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) { return 500; }

View File

@ -2,11 +2,22 @@
#define TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/introspection/Enum.h>
#include <fsfw/action/TemplateAction.h>
FSFW_ENUM(MockCommands, ActionId_t, ((SIMPLE_COMMAND, 1, "Simple Command")) ((PERIODIC_REPLY, 2, "Periodic Reply")))
class DeviceHandlerMock;
class MockAction : public TemplateAction<DeviceHandlerMock, MockAction, MockCommands> {
public:
MockAction(DeviceHandlerMock *owner): TemplateAction(owner, MockCommands::SIMPLE_COMMAND) {
}
};
class DeviceHandlerMock : public DeviceHandlerBase {
public:
static const DeviceCommandId_t SIMPLE_COMMAND = 1;
static const DeviceCommandId_t PERIODIC_REPLY = 2;
static const uint8_t SIMPLE_COMMAND_DATA = 1;
static const uint8_t PERIODIC_REPLY_DATA = 2;
@ -21,6 +32,8 @@ class DeviceHandlerMock : public DeviceHandlerBase {
ReturnValue_t enablePeriodicReply(DeviceCommandId_t replyId);
ReturnValue_t disablePeriodicReply(DeviceCommandId_t replyId);
ReturnValue_t handleAction(MockAction * action);
protected:
void doStartUp() override;
void doShutDown() override;
@ -41,6 +54,8 @@ class DeviceHandlerMock : public DeviceHandlerBase {
uint8_t commandBuffer[1];
bool periodicReplyReceived = false;
MockAction mockAction = MockAction(this);
};
#endif /* TESTS_SRC_FSFW_TESTS_UNIT_DEVICEHANDLER_DEVICEHANDLERMOCK_H_ */

View File

@ -0,0 +1,3 @@
target_sources(${FSFW_TEST_TGT} PRIVATE
testService11.cpp
)

View File

@ -0,0 +1,14 @@
#include <fsfw/pus/Service11TelecommandScheduling.h>
#include <catch2/catch_test_macros.hpp>
#include "objects/systemObjectList.h"
#include "tmtc/apid.h"
#include "tmtc/pusIds.h"
TEST_CASE("PUS Service 11", "[pus-srvc11]") {
Service11TelecommandScheduling<13> pusService11(
{objects::PUS_SERVICE_11_TC_SCHEDULER, apid::DEFAULT_APID, pus::PUS_SERVICE_11}, nullptr);
// TODO test something...
}

View File

@ -64,7 +64,8 @@ TEST_CASE("Serial Buffer Adapter", "[single-file]") {
SECTION("Test set buffer function") {
SerialBufferAdapter<uint8_t> tv_serial_buffer_adapter_loc =
SerialBufferAdapter<uint8_t>((uint8_t*)nullptr, 0, true);
tv_serial_buffer_adapter_loc.setBuffer(test_serial_buffer.data(), test_serial_buffer.size());
tv_serial_buffer_adapter_loc.setConstBuffer(test_serial_buffer.data(),
test_serial_buffer.size());
serialized_size = 0;
arrayPtr = testArray.data();
SerializeAdapter::serialize(&test_value_bool, &arrayPtr, &serialized_size, testArray.size(),

View File

@ -71,7 +71,7 @@ TEST_CASE("PUS TC Creator", "[pus-tc-creator]") {
SECTION("Test with Application Data Raw") {
auto& params = creator.getPusParams();
std::array<uint8_t, 3> data{1, 2, 3};
params.dataWrapper.setRawData({data.data(), data.size()});
params.setRawAppData(data.data(), data.size());
// To get correct size information, the SP length field needs to be updated automatically
REQUIRE(creator.getSerializedSize() == 13);
creator.updateSpLengthField();

View File

@ -44,9 +44,7 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
REQUIRE(creator.getSubService() == 2);
REQUIRE(creator.getService() == 17);
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == util::DataTypes::RAW);
REQUIRE(params.dataWrapper.dataUnion.raw.data == nullptr);
REQUIRE(params.dataWrapper.dataUnion.raw.len == 0);
REQUIRE(params.sourceData == nullptr);
REQUIRE(tmHelper.sendCounter == 0);
REQUIRE(tmHelper.storeAndSendTmPacket() == returnvalue::OK);
REQUIRE(tmHelper.sendCounter == 1);
@ -65,9 +63,9 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
REQUIRE(tmHelper.prepareTmPacket(2, data.data(), data.size()) == returnvalue::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == util::DataTypes::RAW);
REQUIRE(params.dataWrapper.dataUnion.raw.data == data.data());
REQUIRE(params.dataWrapper.dataUnion.raw.len == data.size());
REQUIRE(params.sourceData != nullptr);
REQUIRE(params.sourceData->getSerializedSize() == data.size());
REQUIRE(params.adapter.getConstBuffer() == data.data());
}
SECTION("Serializable Helper") {
@ -75,8 +73,7 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
REQUIRE(tmHelper.prepareTmPacket(2, simpleSer) == returnvalue::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == util::DataTypes::SERIALIZABLE);
REQUIRE(params.dataWrapper.dataUnion.serializable == &simpleSer);
REQUIRE(params.sourceData == &simpleSer);
}
SECTION("Object ID prefix Helper") {
@ -86,8 +83,7 @@ TEST_CASE("TM Store And Send Helper", "[tm-store-send-helper]") {
REQUIRE(tmHelper.prepareTmPacket(2, dataWithObjId) == returnvalue::OK);
auto& creator = storeHelper.getCreatorRef();
auto& params = creator.getParams();
REQUIRE(params.dataWrapper.type == util::DataTypes::SERIALIZABLE);
REQUIRE(params.dataWrapper.dataUnion.serializable == &dataWithObjId);
REQUIRE(params.sourceData == &dataWithObjId);
}
// TODO: Error handling