Compare commits
90 Commits
master
...
mohr/romeo
Author | SHA1 | Date | |
---|---|---|---|
9110fd2728 | |||
8b9a468893 | |||
7ebfcdda60 | |||
5c25a2777c | |||
7f80e91a91 | |||
732419e239 | |||
d328f3e190 | |||
4c0d9ae039 | |||
753d587b69 | |||
979a7b7d75 | |||
a30146a799 | |||
ae2823ba2d | |||
3a433915f1 | |||
d766469f1e | |||
33a2fb48e5 | |||
531d8c45e8 | |||
14a7dd885b | |||
50a4ec97ef | |||
de93bff561 | |||
ad4adc7cba | |||
6a76857f5f | |||
2044e1cde2 | |||
b56b54951b | |||
1fc50a1562 | |||
e831ba11d2 | |||
0da490481e | |||
146c3471d0 | |||
1816c3f623 | |||
d03d5aa74c | |||
26e97ddf89 | |||
be3a57a795 | |||
318a933b3b | |||
13b97abf0d | |||
e8480cf962 | |||
a5e6107001 | |||
f95c373076 | |||
e03731bcf8 | |||
9fe8579377 | |||
2714e588d7 | |||
e905288adc | |||
3805ea50a7 | |||
699bd694cd | |||
4518fec65c | |||
dac1aacab2 | |||
0042f92fdf | |||
656faf8169 | |||
f84431e965 | |||
0cec9ebb73 | |||
a440b7c394 | |||
bbfc1b2b34 | |||
025b379e8b | |||
c35a0a8541 | |||
0f81d5e458 | |||
e0a072859b | |||
b50f092939 | |||
2f90e12179 | |||
8b77fac099 | |||
47503824d7 | |||
5e3f5c4121 | |||
1f36c082ef | |||
aa84e93603 | |||
8f63a0e747 | |||
6fc8f756a7 | |||
067cb7d0f8 | |||
d98ed40e3d | |||
2c17af4ef8 | |||
110fb43b9c | |||
b057250bfb | |||
066dd0d397 | |||
f735c2e9d4 | |||
1c527c4946 | |||
4c0f67adf5 | |||
450ad1dad4 | |||
1dfb3323f7 | |||
f5adcd0625 | |||
bc593c938d | |||
3f8f17a66e | |||
3260a03544 | |||
3ffdc0d31f | |||
d367baa42c | |||
59f8dd1322 | |||
61b4e68f3d | |||
e34664d265 | |||
20eb232bf5 | |||
dd281f8a67 | |||
f9e9ff320f | |||
f56646d2c3 | |||
ef18377cef | |||
0c057c66b1 | |||
34c50ce3e2 |
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,5 +10,8 @@
|
|||
.settings
|
||||
.metadata
|
||||
|
||||
# VSCode
|
||||
.vscode
|
||||
|
||||
/build*
|
||||
/cmake-build*
|
||||
|
|
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -8,6 +8,42 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|||
|
||||
# [unreleased]
|
||||
|
||||
## Fixes
|
||||
|
||||
- Important bugfix in CFDP PDU header format: The entity length field and the transaction sequence
|
||||
number fields stored the actual length of the field instead of the length minus 1 like specified
|
||||
in the CFDP standard.
|
||||
- PUS Health Service: Size check for set health command.
|
||||
Perform operation completion for announce health command.
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/746
|
||||
- Linux OSAL `getUptime` fix: Check validity of `/proc/uptime` file before reading uptime.
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/745
|
||||
- Small tweak for version getter
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/744
|
||||
|
||||
## Added
|
||||
|
||||
- add CFDP subsystem ID
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/742
|
||||
|
||||
## Changed
|
||||
- Bump ETL version to 20.35.14
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/748
|
||||
- Renamed `PCDU_2` subsystem ID to `POWER_SWITCH_IF`.
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
|
||||
- Add new `PowerSwitchIF::SWITCH_UNKNOWN` returnvalue.
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/743
|
||||
- Assert that `FixedArrayList` is larger than 0 at compile time.
|
||||
https://egit.irs.uni-stuttgart.de/fsfw/fsfw/pulls/740
|
||||
|
||||
## Added
|
||||
|
||||
- `EventManager`: Add function to print all listeners.
|
||||
|
||||
## Changed
|
||||
|
||||
- `EventManager`: Queue depth is configurable now
|
||||
|
||||
# [v6.0.0] 2023-02-10
|
||||
|
||||
## Fixes
|
||||
|
|
|
@ -72,7 +72,7 @@ set(FSFW_ETL_LIB_MAJOR_VERSION
|
|||
20
|
||||
CACHE STRING "ETL library major version requirement")
|
||||
set(FSFW_ETL_LIB_VERSION
|
||||
${FSFW_ETL_LIB_MAJOR_VERSION}.28.0
|
||||
${FSFW_ETL_LIB_MAJOR_VERSION}.36.0
|
||||
CACHE STRING "ETL library exact version requirement")
|
||||
set(FSFW_ETL_LINK_TARGET etl::etl)
|
||||
|
||||
|
@ -80,7 +80,7 @@ set(FSFW_CATCH2_LIB_MAJOR_VERSION
|
|||
3
|
||||
CACHE STRING "Catch2 library major version requirement")
|
||||
set(FSFW_CATCH2_LIB_VERSION
|
||||
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.1.0
|
||||
v${FSFW_CATCH2_LIB_MAJOR_VERSION}.3.2
|
||||
CACHE STRING "Catch2 library exact version requirement")
|
||||
|
||||
# Keep this off by default for now. See PR:
|
||||
|
|
4
automation/Jenkinsfile
vendored
4
automation/Jenkinsfile
vendored
|
@ -97,7 +97,7 @@ pipeline {
|
|||
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/development'
|
||||
}
|
||||
}
|
||||
dir(BUILDDIR) {
|
||||
dir(BUILDDIR_LINUX) {
|
||||
sshagent(credentials: ['documentation-buildfix']) {
|
||||
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/development'
|
||||
}
|
||||
|
@ -116,7 +116,7 @@ pipeline {
|
|||
sh 'rsync -r --delete docs/sphinx/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/master'
|
||||
}
|
||||
}
|
||||
dir(BUILDDIR) {
|
||||
dir(BUILDDIR_LINUX) {
|
||||
sshagent(credentials: ['documentation-buildfix']) {
|
||||
sh 'rsync -r --delete fsfw-tests_coverage/* buildfix@documentation.irs.uni-stuttgart.de:/fsfw/coverage/master'
|
||||
}
|
||||
|
|
|
@ -8,4 +8,4 @@ if(FSFW_ADD_HAL)
|
|||
add_subdirectory(fsfw_hal)
|
||||
endif()
|
||||
|
||||
add_subdirectory(fsfw_tests)
|
||||
#add_subdirectory(fsfw_tests)
|
||||
|
|
|
@ -7,7 +7,7 @@ add_subdirectory(cfdp)
|
|||
add_subdirectory(container)
|
||||
add_subdirectory(controller)
|
||||
add_subdirectory(datapool)
|
||||
add_subdirectory(datapoollocal)
|
||||
#add_subdirectory(datapoollocal)
|
||||
add_subdirectory(devicehandlers)
|
||||
add_subdirectory(events)
|
||||
add_subdirectory(fdir)
|
||||
|
@ -15,20 +15,22 @@ add_subdirectory(globalfunctions)
|
|||
add_subdirectory(health)
|
||||
add_subdirectory(housekeeping)
|
||||
add_subdirectory(internalerror)
|
||||
add_subdirectory(introspection)
|
||||
add_subdirectory(ipc)
|
||||
add_subdirectory(memory)
|
||||
add_subdirectory(modes)
|
||||
add_subdirectory(objectmanager)
|
||||
add_subdirectory(parameters)
|
||||
add_subdirectory(power)
|
||||
#add_subdirectory(power)
|
||||
add_subdirectory(serialize)
|
||||
add_subdirectory(serviceinterface)
|
||||
add_subdirectory(storagemanager)
|
||||
add_subdirectory(subsystem)
|
||||
add_subdirectory(tasks)
|
||||
add_subdirectory(tcdistribution)
|
||||
add_subdirectory(thermal)
|
||||
#add_subdirectory(thermal)
|
||||
add_subdirectory(timemanager)
|
||||
add_subdirectory(tmtc)
|
||||
add_subdirectory(tmtcpacket)
|
||||
add_subdirectory(tmtcservices)
|
||||
add_subdirectory(filesystem)
|
||||
|
@ -36,7 +38,7 @@ add_subdirectory(filesystem)
|
|||
# Optional
|
||||
|
||||
if(FSFW_ADD_MONITORING)
|
||||
add_subdirectory(monitoring)
|
||||
#add_subdirectory(monitoring)
|
||||
endif()
|
||||
if(FSFW_ADD_PUS)
|
||||
add_subdirectory(pus)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#ifndef FSFW_INC_FSFW_ACTION_H_
|
||||
#define FSFW_INC_FSFW_ACTION_H_
|
||||
|
||||
#include "fsfw/action/Action.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/ActionMessage.h"
|
||||
#include "fsfw/action/CommandActionHelper.h"
|
||||
|
|
70
src/fsfw/action/Action.cpp
Normal file
70
src/fsfw/action/Action.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "Action.h"
|
||||
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
#include <fsfw/ipc/MessageQueueIF.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::clear() {
|
||||
tc = store_address_t();
|
||||
tcOffset = 0;
|
||||
commandedBy = MessageQueueIF::NO_QUEUE;
|
||||
}
|
||||
|
||||
void Action::registerParameter(ParameterIF *parameter) { parameterList.push_back(parameter); }
|
||||
|
||||
std::vector<ParameterIF *> const *Action::getParameters() const { return ¶meterList; }
|
||||
|
||||
size_t Action::getSerializedSize() const {
|
||||
size_t size = SerializeAdapter::getSerializedSize(&id);
|
||||
for (auto parameter : *getParameters()) {
|
||||
size += parameter->getSerializedSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
ReturnValue_t Action::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t result = SerializeAdapter::serialize(&id, buffer, size, maxSize, streamEndianness);
|
||||
if (result != 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 != returnvalue::OK) {
|
||||
return result;
|
||||
}*/
|
||||
for (auto parameter : *getParameters()) {
|
||||
result = parameter->deSerialize(buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
64
src/fsfw/action/Action.h
Normal file
64
src/fsfw/action/Action.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/introspection/HasTmTcParametersIF.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ActionMessage.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#include "../introspection/Enum.h"
|
||||
#endif
|
||||
|
||||
// TODO ActionId_t
|
||||
|
||||
class Action : public SerializeIF, public HasTmTcParametersIF {
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Action();
|
||||
void setEnum(EnumIF *id);
|
||||
const char *getName();
|
||||
#else
|
||||
Action(ActionId_t id);
|
||||
#endif
|
||||
|
||||
store_address_t getTc();
|
||||
size_t getTcOffset();
|
||||
|
||||
// if an action is triggered by a TC, this should be set to be able to handle replies
|
||||
// TODO make deleting it safe
|
||||
// TODO integrate with internal commands
|
||||
store_address_t tc;
|
||||
size_t tcOffset;
|
||||
MessageQueueId_t commandedBy;
|
||||
|
||||
ActionId_t getId();
|
||||
|
||||
|
||||
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] virtual ReturnValue_t handle() = 0;
|
||||
|
||||
void registerParameter(ParameterIF *parameter) override;
|
||||
|
||||
std::vector<ParameterIF *> const *getParameters() const override;
|
||||
|
||||
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;
|
||||
};
|
|
@ -1,3 +1,6 @@
|
|||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
#include <fsfw/tmtc/TmMessage.h>
|
||||
|
||||
#include "fsfw/action.h"
|
||||
#include "fsfw/ipc/MessageQueueSenderIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
@ -10,8 +13,8 @@ ActionHelper::~ActionHelper() = default;
|
|||
|
||||
ReturnValue_t ActionHelper::handleActionMessage(CommandMessage* command) {
|
||||
if (command->getCommand() == ActionMessage::EXECUTE_ACTION) {
|
||||
ActionId_t currentAction = ActionMessage::getActionId(command);
|
||||
prepareExecution(command->getSender(), currentAction, ActionMessage::getStoreId(command));
|
||||
prepareExecution(command->getSender(), ActionMessage::getOffset(command),
|
||||
ActionMessage::getStoreId(command));
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return CommandMessage::UNKNOWN_COMMAND;
|
||||
|
@ -23,6 +26,12 @@ ReturnValue_t ActionHelper::initialize(MessageQueueIF* queueToUse_) {
|
|||
if (ipcStore == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
tmManager = ObjectManager::instance()->get<TmManager>(objects::TM_MANAGER);
|
||||
if (tmManager == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
if (queueToUse_ != nullptr) {
|
||||
setQueueToUse(queueToUse_);
|
||||
}
|
||||
|
@ -57,28 +66,89 @@ void ActionHelper::finish(bool success, MessageQueueId_t reportTo, ActionId_t co
|
|||
|
||||
void ActionHelper::setQueueToUse(MessageQueueIF* queue) { queueToUse = queue; }
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
MessageQueueIF const* ActionHelper::getQueue() const { return queueToUse; }
|
||||
|
||||
void ActionHelper::prepareExecution(MessageQueueId_t commandedBy, size_t offset,
|
||||
store_address_t dataAddress) {
|
||||
const uint8_t* dataPtr = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
const uint8_t* tcData = nullptr;
|
||||
size_t tcDataSize = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &tcData, &tcDataSize);
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
|
||||
FsfwProtocolHeader header;
|
||||
|
||||
const uint8_t* dataPtr = tcData + offset;
|
||||
size_t size = tcDataSize - offset;
|
||||
|
||||
result = header.deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
|
||||
if (header.getInterface() != HasActionsIF::INTERFACE_ID or
|
||||
header.getFunction() != HasActionsIF::Functions::EXECUTE_ACTION) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
ActionId_t actionId;
|
||||
|
||||
result =
|
||||
SerializeAdapter::deSerialize(&actionId, &dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
auto actionIter = actionMap.find(actionId);
|
||||
if (actionIter == actionMap.end()) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
Action* action = actionIter->second;
|
||||
|
||||
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if ((result != returnvalue::OK) || (size != 0)) { // TODO write unittest for second condition
|
||||
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);
|
||||
|
||||
// TODO safetify dynamic cast
|
||||
result = tmManager->sendTmPacket(dynamic_cast<SystemObjectIF*>(owner)->getObjectId(), HasActionsIF::INTERFACE_ID,
|
||||
HasActionsIF::Functions::EXECUTION_IN_PROGRESS, action,
|
||||
dataAddress, offset);
|
||||
if (result != returnvalue::OK) {
|
||||
sif::error << "replying action failed " << std::hex << result << std::dec << std::endl;
|
||||
}
|
||||
|
||||
// ipcStore->deleteData(dataAddress);
|
||||
if (result == HasActionsIF::EXECUTION_FINISHED) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setCompletionReply(&reply, actionId, true, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
// queueToUse->sendMessage(commandedBy, &reply);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -163,3 +233,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; }
|
|
@ -1,9 +1,12 @@
|
|||
#ifndef FSFW_ACTION_ACTIONHELPER_H_
|
||||
#define FSFW_ACTION_ACTIONHELPER_H_
|
||||
|
||||
#include <fsfw/tmtc/TmManager.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 +101,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;
|
||||
|
@ -106,8 +119,11 @@ class ActionHelper {
|
|||
//! Queue to be used as response sender, has to be set in ctor or with
|
||||
//! setQueueToUse
|
||||
MessageQueueIF* queueToUse;
|
||||
TmManager* tmManager = nullptr;
|
||||
//! 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
|
||||
|
@ -115,7 +131,7 @@ class ActionHelper {
|
|||
* @param actionId ID of action to be done
|
||||
* @param dataAddress Address of additional data in IPC Store
|
||||
*/
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, size_t offset,
|
||||
store_address_t dataAddress);
|
||||
/**
|
||||
* @brief Default implementation is empty.
|
||||
|
|
|
@ -6,14 +6,14 @@ ActionMessage::ActionMessage() = default;
|
|||
|
||||
ActionMessage::~ActionMessage() = default;
|
||||
|
||||
void ActionMessage::setCommand(CommandMessage* message, ActionId_t fid,
|
||||
void ActionMessage::setCommand(CommandMessage* message, size_t offset,
|
||||
store_address_t parameters) {
|
||||
message->setCommand(EXECUTE_ACTION);
|
||||
message->setParameter(fid);
|
||||
message->setParameter(offset);
|
||||
message->setParameter2(parameters.raw);
|
||||
}
|
||||
|
||||
ActionId_t ActionMessage::getActionId(const CommandMessage* message) {
|
||||
size_t ActionMessage::getOffset(const CommandMessage* message) {
|
||||
return ActionId_t(message->getParameter());
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ class ActionMessage {
|
|||
static const Command_t COMPLETION_FAILED = MAKE_COMMAND_ID(6);
|
||||
|
||||
virtual ~ActionMessage();
|
||||
static void setCommand(CommandMessage* message, ActionId_t fid, store_address_t parameters);
|
||||
static void setCommand(CommandMessage* message, size_t offset, store_address_t parameters);
|
||||
|
||||
static ActionId_t getActionId(const CommandMessage* message);
|
||||
static size_t getOffset(const CommandMessage* message);
|
||||
static store_address_t getStoreId(const CommandMessage* message);
|
||||
|
||||
static void setStepReply(CommandMessage* message, ActionId_t fid, uint8_t step,
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -74,24 +74,24 @@ ReturnValue_t CommandActionHelper::handleReply(CommandMessage *reply) {
|
|||
switch (reply->getCommand()) {
|
||||
case ActionMessage::COMPLETION_SUCCESS:
|
||||
commandCount--;
|
||||
owner->completionSuccessfulReceived(ActionMessage::getActionId(reply));
|
||||
// owner->completionSuccessfulReceived(ActionMessage::getActionId(reply)); TODO
|
||||
return returnvalue::OK;
|
||||
case ActionMessage::COMPLETION_FAILED:
|
||||
commandCount--;
|
||||
owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
// owner->completionFailedReceived(ActionMessage::getActionId(reply),
|
||||
// ActionMessage::getReturnCode(reply));
|
||||
return returnvalue::OK;
|
||||
case ActionMessage::STEP_SUCCESS:
|
||||
owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
ActionMessage::getStep(reply));
|
||||
// owner->stepSuccessfulReceived(ActionMessage::getActionId(reply),
|
||||
// ActionMessage::getStep(reply));
|
||||
return returnvalue::OK;
|
||||
case ActionMessage::STEP_FAILED:
|
||||
commandCount--;
|
||||
owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
|
||||
ActionMessage::getReturnCode(reply));
|
||||
// owner->stepFailedReceived(ActionMessage::getActionId(reply), ActionMessage::getStep(reply),
|
||||
// ActionMessage::getReturnCode(reply));
|
||||
return returnvalue::OK;
|
||||
case ActionMessage::DATA_REPLY:
|
||||
extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
|
||||
// extractDataForOwner(ActionMessage::getActionId(reply), ActionMessage::getStoreId(reply));
|
||||
return returnvalue::OK;
|
||||
default:
|
||||
return returnvalue::FAILED;
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
#ifndef FSFW_ACTION_HASACTIONSIF_H_
|
||||
#define FSFW_ACTION_HASACTIONSIF_H_
|
||||
|
||||
#include "Action.h"
|
||||
#include "ActionHelper.h"
|
||||
#include "ActionMessage.h"
|
||||
#include "SimpleActionHelper.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/returnvalues/returnvalue.h"
|
||||
#include <fsfw/tmtc/FsfwProtocolHeader.h>
|
||||
|
||||
/**
|
||||
* @brief
|
||||
|
@ -40,12 +42,18 @@ class HasActionsIF {
|
|||
static const ReturnValue_t INVALID_PARAMETERS = MAKE_RETURN_CODE(2);
|
||||
static const ReturnValue_t EXECUTION_FINISHED = MAKE_RETURN_CODE(3);
|
||||
static const ReturnValue_t INVALID_ACTION_ID = MAKE_RETURN_CODE(4);
|
||||
|
||||
enum Functions : FsfwProtocolHeader::FunctionType_t { EXECUTE_ACTION, EXECUTION_IN_PROGRESS };
|
||||
|
||||
virtual ~HasActionsIF() = default;
|
||||
/**
|
||||
* Function to get the MessageQueueId_t of the implementing object
|
||||
* @return MessageQueueId_t of the object
|
||||
*
|
||||
*/
|
||||
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
|
||||
|
||||
virtual ActionHelper* getActionHelper() = 0;
|
||||
/**
|
||||
* Execute or initialize the execution of a certain function.
|
||||
* The ActionHelpers will execute this function and behave differently
|
||||
|
@ -55,8 +63,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_ */
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
#include "fsfw/action.h"
|
||||
#include <fsfw/serialize/SerializeAdapter.h>
|
||||
|
||||
|
||||
SimpleActionHelper::SimpleActionHelper(HasActionsIF* setOwner, MessageQueueIF* useThisQueue)
|
||||
: ActionHelper(setOwner, useThisQueue), isExecuting(false) {}
|
||||
|
@ -30,25 +32,57 @@ void SimpleActionHelper::resetHelper() {
|
|||
lastCommander = 0;
|
||||
}
|
||||
|
||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress) {
|
||||
void SimpleActionHelper::prepareExecution(MessageQueueId_t commandedBy, size_t offset,
|
||||
store_address_t dataAddress) {
|
||||
CommandMessage reply;
|
||||
if (isExecuting) {
|
||||
ipcStore->deleteData(dataAddress);
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::IS_BUSY);
|
||||
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, HasActionsIF::IS_BUSY);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
}
|
||||
const uint8_t* dataPtr = nullptr;
|
||||
size_t size = 0;
|
||||
ReturnValue_t result = ipcStore->getData(dataAddress, &dataPtr, &size);
|
||||
if (result != returnvalue::OK) {
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
ActionMessage::setStepReply(&reply, 0 /*TODO*/, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
lastCommander = commandedBy;
|
||||
lastAction = actionId;
|
||||
result = owner->executeAction(actionId, commandedBy, dataPtr, size);
|
||||
|
||||
|
||||
dataPtr += offset;
|
||||
size -=offset;
|
||||
|
||||
ActionId_t actionId;
|
||||
|
||||
result = SerializeAdapter::deSerialize(&actionId, &dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if (result != returnvalue::OK) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, result);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
|
||||
auto actionIter = actionMap.find(actionId);
|
||||
if (actionIter == actionMap.end()){
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_ACTION_ID);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
Action* action = actionIter->second;
|
||||
result = action->deSerialize(&dataPtr, &size, SerializeIF::Endianness::NETWORK);
|
||||
if ((result != returnvalue::OK) or (size != 0)) {
|
||||
CommandMessage reply;
|
||||
ActionMessage::setStepReply(&reply, actionId, 0, HasActionsIF::INVALID_PARAMETERS);
|
||||
queueToUse->sendMessage(commandedBy, &reply);
|
||||
ipcStore->deleteData(dataAddress);
|
||||
return;
|
||||
}
|
||||
result = action->handle();
|
||||
ipcStore->deleteData(dataAddress);
|
||||
switch (result) {
|
||||
case returnvalue::OK:
|
||||
|
|
|
@ -17,8 +17,8 @@ class SimpleActionHelper : public ActionHelper {
|
|||
ReturnValue_t reportData(SerializeIF* data);
|
||||
|
||||
protected:
|
||||
void prepareExecution(MessageQueueId_t commandedBy, ActionId_t actionId,
|
||||
store_address_t dataAddress) override;
|
||||
virtual void prepareExecution(MessageQueueId_t commandedBy, size_t offset,
|
||||
store_address_t dataAddress) override;
|
||||
void resetHelper() override;
|
||||
|
||||
private:
|
||||
|
|
29
src/fsfw/action/TemplateAction.h
Normal file
29
src/fsfw/action/TemplateAction.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
#pragma once
|
||||
|
||||
#include "Action.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
template <class owner_class, class action_type, class ActionEnum>
|
||||
class TemplateAction : public Action {
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
TemplateAction(owner_class *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_class *myOwner, ActionEnum id) : Action((uint32_t)id), myOwner(myOwner) {
|
||||
myOwner->getActionHelper()->registerAction(this);
|
||||
}
|
||||
#endif
|
||||
|
||||
ReturnValue_t handle() override { return myOwner->handleAction(dynamic_cast<action_type *>(this)); }
|
||||
|
||||
private:
|
||||
owner_class *myOwner;
|
||||
};
|
|
@ -51,8 +51,9 @@ class VarLenField : public SerializeIF {
|
|||
return os;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
|
||||
// compiler
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@ ReturnValue_t HeaderCreator::serialize(uint8_t **buffer, size_t *size, size_t ma
|
|||
*buffer += 1;
|
||||
**buffer = pduDataFieldLen & 0x00ff;
|
||||
*buffer += 1;
|
||||
**buffer = segmentationCtrl << 7 | pduConf.sourceId.getWidth() << 4 | segmentMetadataFlag << 3 |
|
||||
pduConf.seqNum.getWidth();
|
||||
**buffer = segmentationCtrl << 7 | ((pduConf.sourceId.getWidth() - 1) << 4) |
|
||||
segmentMetadataFlag << 3 | (pduConf.seqNum.getWidth() - 1);
|
||||
*buffer += 1;
|
||||
*size += 4;
|
||||
ReturnValue_t result = pduConf.sourceId.serialize(buffer, size, maxSize, streamEndianness);
|
||||
|
|
|
@ -78,11 +78,11 @@ cfdp::SegmentationControl PduHeaderReader::getSegmentationControl() const {
|
|||
}
|
||||
|
||||
cfdp::WidthInBytes PduHeaderReader::getLenEntityIds() const {
|
||||
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte >> 4) & 0x07);
|
||||
return static_cast<cfdp::WidthInBytes>(((pointers.fixedHeader->fourthByte >> 4) & 0b111) + 1);
|
||||
}
|
||||
|
||||
cfdp::WidthInBytes PduHeaderReader::getLenSeqNum() const {
|
||||
return static_cast<cfdp::WidthInBytes>(pointers.fixedHeader->fourthByte & 0x07);
|
||||
return static_cast<cfdp::WidthInBytes>((pointers.fixedHeader->fourthByte & 0b111) + 1);
|
||||
}
|
||||
|
||||
cfdp::SegmentMetadataFlag PduHeaderReader::getSegmentMetadataFlag() const {
|
||||
|
|
|
@ -23,6 +23,8 @@ class EntityIdTlv : public TlvIF {
|
|||
*/
|
||||
ReturnValue_t deSerialize(cfdp::Tlv& tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
||||
// the compiler
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@ class FilestoreRequestTlv : public cfdp::FilestoreTlvBase {
|
|||
*/
|
||||
ReturnValue_t deSerialize(cfdp::Tlv &tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize; // we overloaded above, so this is needed to uncofuse the
|
||||
// compiler
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
|
|
@ -29,6 +29,8 @@ class FilestoreResponseTlv : public cfdp::FilestoreTlvBase {
|
|||
*/
|
||||
ReturnValue_t deSerialize(const cfdp::Tlv& tlv, Endianness endianness);
|
||||
|
||||
using SerializeIF::deSerialize; // we overloaded this function, so this is needed to unconfuse
|
||||
// the compiler
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ template <typename T, size_t MAX_SIZE, typename count_t = uint8_t>
|
|||
class FixedArrayList : public ArrayList<T, count_t> {
|
||||
static_assert(MAX_SIZE <= std::numeric_limits<count_t>::max(),
|
||||
"count_t is not large enough to hold MAX_SIZE");
|
||||
static_assert(MAX_SIZE > 0, "MAX_SIZE is 0");
|
||||
|
||||
private:
|
||||
T data[MAX_SIZE];
|
||||
|
|
|
@ -155,8 +155,8 @@ class FixedMap : public SerializeIF {
|
|||
|
||||
uint32_t maxSize() const { return theMap.maxSize(); }
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const override {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::serialize(&this->_size, buffer, size, maxSize, streamEndianness);
|
||||
uint32_t i = 0;
|
||||
|
@ -170,7 +170,7 @@ class FixedMap : public SerializeIF {
|
|||
return result;
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
size_t getSerializedSize() const override {
|
||||
uint32_t printSize = sizeof(_size);
|
||||
uint32_t i = 0;
|
||||
|
||||
|
@ -182,8 +182,8 @@ class FixedMap : public SerializeIF {
|
|||
return printSize;
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) override {
|
||||
ReturnValue_t result =
|
||||
SerializeAdapter::deSerialize(&this->_size, buffer, size, streamEndianness);
|
||||
if (this->_size > theMap.maxSize()) {
|
||||
|
|
|
@ -1,2 +1 @@
|
|||
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE ControllerBase.cpp)
|
||||
|
|
|
@ -12,7 +12,10 @@ ControllerBase::ControllerBase(object_id_t setObjectId, object_id_t parentId,
|
|||
mode(MODE_OFF),
|
||||
submode(SUBMODE_NONE),
|
||||
modeHelper(this),
|
||||
healthHelper(this, setObjectId) {
|
||||
healthHelper(this, setObjectId),
|
||||
actionHelper(this, commandQueue),
|
||||
datapoolHelper(this),
|
||||
housekeepingHelper(this) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(commandQueueDepth);
|
||||
}
|
||||
|
||||
|
@ -45,6 +48,21 @@ ReturnValue_t ControllerBase::initialize() {
|
|||
return result;
|
||||
}
|
||||
|
||||
result = actionHelper.initialize(commandQueue);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = housekeepingHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
result = datapoolHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -64,6 +82,12 @@ void ControllerBase::handleQueue() {
|
|||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = actionHelper.handleActionMessage(&command);
|
||||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
}
|
||||
|
||||
result = handleCommandMessage(&command);
|
||||
if (result == returnvalue::OK) {
|
||||
continue;
|
||||
|
@ -99,6 +123,15 @@ ReturnValue_t ControllerBase::performOperation(uint8_t opCode) {
|
|||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
const ModeHelper* ControllerBase::getModeHelper() const { return &modeHelper; }
|
||||
|
||||
ActionHelper* ControllerBase::getActionHelper() { return &actionHelper; }
|
||||
|
||||
ReturnValue_t ControllerBase::executeAction(Action* action) { return action->handle(); }
|
||||
|
||||
DatapoolHelper* ControllerBase::getDatapoolHelper() { return &datapoolHelper; }
|
||||
HousekeepingHelper* ControllerBase::getHousekeepingHelper() { return &housekeepingHelper; }
|
||||
|
||||
void ControllerBase::modeChanged(Mode_t mode_, Submode_t submode_) {}
|
||||
|
||||
ReturnValue_t ControllerBase::setHealth(HealthState health) {
|
||||
|
|
|
@ -1,13 +1,15 @@
|
|||
#ifndef FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
#define FSFW_CONTROLLER_CONTROLLERBASE_H_
|
||||
|
||||
#include "fsfw/health/HasHealthIF.h"
|
||||
#include "fsfw/health/HealthHelper.h"
|
||||
#include "fsfw/modes/HasModesIF.h"
|
||||
#include "fsfw/modes/ModeHelper.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
#include "fsfw/tasks/ExecutableObjectIF.h"
|
||||
#include "fsfw/tasks/PeriodicTaskIF.h"
|
||||
#include <fsfw/health/HasHealthIF.h>
|
||||
#include <fsfw/health/HealthHelper.h>
|
||||
#include <fsfw/introspection/ClasslessEnum.h>
|
||||
#include <fsfw/modes/HasModesIF.h>
|
||||
#include <fsfw/action/HasActionsIF.h>
|
||||
#include <fsfw/datapool/HasDatapoolIF.h>
|
||||
#include <fsfw/objectmanager/SystemObject.h>
|
||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||
#include <fsfw/tasks/PeriodicTaskIF.h>
|
||||
|
||||
/**
|
||||
* @brief Generic base class for controller classes
|
||||
|
@ -17,10 +19,14 @@
|
|||
*/
|
||||
class ControllerBase : public HasModesIF,
|
||||
public HasHealthIF,
|
||||
public HasDatapoolIF,
|
||||
public HasActionsIF,
|
||||
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 +45,17 @@ class ControllerBase : public HasModesIF,
|
|||
void setTaskIF(PeriodicTaskIF *task) override;
|
||||
ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
/** HasModeIF overrides */
|
||||
const ModeHelper *getModeHelper() const override;
|
||||
|
||||
/** HasActionsIF override */
|
||||
ActionHelper* getActionHelper() override;
|
||||
ReturnValue_t executeAction(Action* action) override;
|
||||
|
||||
/** HasDatapoolIF overrides */
|
||||
DatapoolHelper* getDatapoolHelper() override;
|
||||
HousekeepingHelper* getHousekeepingHelper() override;
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Implemented by child class. Handle command messages which are not
|
||||
|
@ -68,6 +85,12 @@ class ControllerBase : public HasModesIF,
|
|||
|
||||
HealthHelper healthHelper;
|
||||
|
||||
ActionHelper actionHelper;
|
||||
|
||||
DatapoolHelper datapoolHelper;
|
||||
|
||||
HousekeepingHelper housekeepingHelper;
|
||||
|
||||
/**
|
||||
* Pointer to the task which executes this component,
|
||||
* is invalid before setTaskIF was called.
|
||||
|
|
|
@ -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(); }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -1 +1 @@
|
|||
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE Dataset.cpp DatapoolHelper.cpp)
|
||||
|
|
20
src/fsfw/datapool/DatapoolHelper.cpp
Normal file
20
src/fsfw/datapool/DatapoolHelper.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "DatapoolHelper.h"
|
||||
|
||||
DatapoolHelper::DatapoolHelper(HasDatapoolIF* owner) : HousekeepingHelper(owner) {}
|
||||
|
||||
ReturnValue_t DatapoolHelper::initialize() {
|
||||
return HousekeepingHelper::initialize();
|
||||
}
|
||||
|
||||
const Dataset* DatapoolHelper::getDataSet(HousekeepingSetId_t id) {
|
||||
auto iter = dataSets.find(id);
|
||||
if (iter == dataSets.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void DatapoolHelper::registerSet(Dataset* set) {
|
||||
auto id = set->getId();
|
||||
dataSets.emplace(id, set);
|
||||
}
|
28
src/fsfw/datapool/DatapoolHelper.h
Normal file
28
src/fsfw/datapool/DatapoolHelper.h
Normal file
|
@ -0,0 +1,28 @@
|
|||
#pragma once
|
||||
|
||||
#include "Dataset.h"
|
||||
#include "HasDatapoolIF.h"
|
||||
|
||||
#include <fsfw/housekeeping/HousekeepingHelper.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
|
||||
class DatapoolHelper : public HousekeepingHelper {
|
||||
public:
|
||||
DatapoolHelper(HasDatapoolIF *owner);
|
||||
~DatapoolHelper() = default;
|
||||
|
||||
const Dataset* getDataSet(HousekeepingSetId_t id);
|
||||
|
||||
const std::map<HousekeepingSetId_t, Dataset*>* getDatasets() const {
|
||||
return &dataSets;
|
||||
}
|
||||
|
||||
void registerSet(Dataset* set);
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
private:
|
||||
std::map<HousekeepingSetId_t, Dataset*> dataSets;
|
||||
};
|
141
src/fsfw/datapool/Dataset.cpp
Normal file
141
src/fsfw/datapool/Dataset.cpp
Normal file
|
@ -0,0 +1,141 @@
|
|||
#include "Dataset.h"
|
||||
|
||||
#include <fsfw/ipc/MutexFactory.h>
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
|
||||
//TODO for non allocated: detect if initialized, and if not, call it
|
||||
|
||||
#include "HasDatapoolIF.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Dataset::Dataset(HasDatapoolIF* owner, const EnumIF &id, bool allowUserCommit)
|
||||
: HousekeepingSet(owner, id), allocated(true), allowUserCommit(allowUserCommit) {
|
||||
this->owner.pointer = owner;
|
||||
owner->getDatapoolHelper()->registerSet(this);
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
Dataset::Dataset(uint32_t owner_id, const EnumIF &id)
|
||||
: HousekeepingSet(nullptr, id), allocated(false), allowUserCommit(false) {
|
||||
this->owner.id = owner_id;
|
||||
}
|
||||
#else
|
||||
Dataset::Dataset(HasDatapoolIF* owner, HousekeepingSetId_t id, bool allowUserCommit)
|
||||
: HousekeepingSet(owner, id), allocated(true), allowUserCommit(allowUserCommit) {
|
||||
this->owner.pointer = owner;
|
||||
owner->getDatapoolHelper()->registerSet(this);
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
Dataset::Dataset(uint32_t owner_id, HousekeepingSetId_t id) : HousekeepingSet(nullptr, id) {
|
||||
this->owner.id = owner_id;
|
||||
}
|
||||
#endif
|
||||
|
||||
Dataset::~Dataset() { MutexFactory::instance()->deleteMutex(mutex); }
|
||||
|
||||
void Dataset::commit() {
|
||||
if ((!allocated) && (!allowUserCommit)) {
|
||||
return;
|
||||
}
|
||||
|
||||
lock();
|
||||
for (auto variable : variables) {
|
||||
variable->commit();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
void Dataset::commit(bool valid) {
|
||||
if ((!allocated) && (!allowUserCommit)) {
|
||||
return;
|
||||
}
|
||||
setAllValid(valid);
|
||||
commit();
|
||||
}
|
||||
|
||||
void Dataset::setAllValid(bool valid) {
|
||||
if ((!allocated) && (!allowUserCommit)) {
|
||||
return;
|
||||
}
|
||||
for (auto variable : variables) {
|
||||
variable->setValid(valid);
|
||||
}
|
||||
}
|
||||
|
||||
void Dataset::read() {
|
||||
lock();
|
||||
for (auto variable : variables) {
|
||||
variable->read();
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
bool Dataset::hasChanged() {
|
||||
bool changed = hasChangedNoRead();
|
||||
read();
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool Dataset::hasChangedOrOlderThan(uint32_t seconds) {
|
||||
bool changed = hasChanged();
|
||||
// TODO time
|
||||
read();
|
||||
return changed;
|
||||
}
|
||||
|
||||
const std::vector<DatasetEntryIF*>* Dataset::getVariables() const { return &variables; }
|
||||
|
||||
ReturnValue_t Dataset::initialize() {
|
||||
if (allocated) {
|
||||
// nothing to do
|
||||
return returnvalue::OK;
|
||||
}
|
||||
HasDatapoolIF* actualOwner = ObjectManager::instance()->get<HasDatapoolIF>(owner.id);
|
||||
if (actualOwner == nullptr) {
|
||||
puts("owner type");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
const Dataset* theOtherSet = actualOwner->getDatapoolHelper()->getDataSet(this->id);
|
||||
if (theOtherSet == nullptr) {
|
||||
puts("no set");
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
if (theOtherSet->variables.size() != variables.size()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
this->mutex = theOtherSet->mutex;
|
||||
this->allowUserCommit = theOtherSet->allowUserCommit;
|
||||
|
||||
for (size_t i = 0; i < variables.size(); i++) {
|
||||
variables[i]->connect(theOtherSet->variables[i]);
|
||||
}
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
// operator[]
|
||||
|
||||
|
||||
bool Dataset::registerEntry(DatasetEntryIF* entry) {
|
||||
variables.push_back(entry);
|
||||
return allocated;
|
||||
}
|
||||
|
||||
void Dataset::lock() { mutex->lockMutex(MutexIF::TimeoutType::BLOCKING); }
|
||||
|
||||
void Dataset::unlock() { mutex->unlockMutex(); }
|
||||
|
||||
bool Dataset::hasChangedNoRead() {
|
||||
bool changed = false;
|
||||
for (auto variable : variables) {
|
||||
if (variable->changed()) {
|
||||
changed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return changed;
|
||||
}
|
183
src/fsfw/datapool/Dataset.h
Normal file
183
src/fsfw/datapool/Dataset.h
Normal file
|
@ -0,0 +1,183 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/housekeeping/HousekeepingSet.h>
|
||||
#include <fsfw/introspection/Enum.h>
|
||||
#include <fsfw/ipc/MutexIF.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/storagemanager/storeAddress.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "DatasetEntryIF.h"
|
||||
|
||||
// TODO ring inclusion
|
||||
// #include "HasDatapoolIF.h"
|
||||
class HasDatapoolIF;
|
||||
|
||||
// TODO allow user commit and reporting TM
|
||||
|
||||
/**
|
||||
* This class has a dual use
|
||||
*
|
||||
* 1) It is used as an IPC method:
|
||||
* It implements a shared memory which can be written and read by different parties
|
||||
*
|
||||
* 2) It is used to define data that is to be downlinked, either periodically or
|
||||
* triggered by an (abstract, not in the sense of fsfw/events) event occuring, ie
|
||||
* data was received from an external source and should be shared with ground.
|
||||
*
|
||||
* Generating a downlinked report is coupled to commiting, as without a commit there is no
|
||||
* change in information to be reported.
|
||||
*
|
||||
* Nominally, the decision to report is done by the set itself, depending on its settings.
|
||||
* If a report is to be forced regardless of these settings, the commitAndReport() functions
|
||||
* are provided which will always generate a report.
|
||||
*
|
||||
* Periodic reports are not tied to a specific tc and are reported as "unrequested". When forcing
|
||||
* a report, optionally a tc can be provided which (logically) triggered the report.
|
||||
*
|
||||
* And, as life is complicated, there is a third set of commits: commitAndReportIfRequested(). Same
|
||||
* as before, but this time, a report is only generated, if the store_address_t is valid. These are
|
||||
* used if at the place where the commit is called, it is not known if there is a request (cf DHB
|
||||
* interpretDeviceReply)
|
||||
*/
|
||||
|
||||
class Dataset : public HousekeepingSet {
|
||||
protected:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Dataset(HasDatapoolIF* owner, const EnumIF &id, bool allowUserCommit);
|
||||
Dataset(uint32_t owner_id, const EnumIF &id);
|
||||
#else
|
||||
Dataset(HasDatapoolIF* owner, HousekeepingSetId_t id, bool allowUserCommit);
|
||||
Dataset(uint32_t owner_id, HousekeepingSetId_t id);
|
||||
#endif
|
||||
public:
|
||||
~Dataset() override;
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
*
|
||||
*/
|
||||
void commit();
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commit(bool valid);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet
|
||||
*
|
||||
*/
|
||||
void commitAndReport();
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReport(bool valid);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
*/
|
||||
void commitAndReport(store_address_t tc, size_t tc_offset);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReport(bool valid, store_address_t tc, size_t tc_offset);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc, if tc is valid
|
||||
*
|
||||
*/
|
||||
void commitAndReportIfRequested(store_address_t tc, size_t tc_offset);
|
||||
|
||||
/**
|
||||
* Copy content of local copies into actual variable
|
||||
* Force sending of TM packet, in reference to tc, if tc is valid
|
||||
*
|
||||
* calls setValid(valid) before committing
|
||||
*
|
||||
*/
|
||||
void commitAndReportIfRequested(bool valid, store_address_t tc, size_t tc_offset);
|
||||
|
||||
/**
|
||||
* set all contained variables to #valid
|
||||
*
|
||||
*/
|
||||
void setAllValid(bool valid);
|
||||
|
||||
/**
|
||||
* Copy content of actual variables into local copies
|
||||
*
|
||||
*
|
||||
*/
|
||||
void read();
|
||||
|
||||
/**
|
||||
* returns true if local copies and actual variables differ
|
||||
*
|
||||
* implicitely calls read()
|
||||
*/
|
||||
bool hasChanged();
|
||||
|
||||
/**
|
||||
* returns true if local copies and actual variables differ
|
||||
* or time since last time true has been returned is greater than
|
||||
* supplied time
|
||||
*
|
||||
* implicitely calls read()
|
||||
*
|
||||
*/
|
||||
bool hasChangedOrOlderThan(uint32_t seconds);
|
||||
|
||||
/**
|
||||
* get List of contained Valiables
|
||||
*/
|
||||
virtual const std::vector<DatasetEntryIF*>* getVariables() const;
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
// operator[]
|
||||
|
||||
bool registerEntry(DatasetEntryIF*);
|
||||
|
||||
protected:
|
||||
|
||||
bool allocated;
|
||||
bool allowUserCommit;
|
||||
union {
|
||||
object_id_t id;
|
||||
HasDatapoolIF* pointer;
|
||||
} owner;
|
||||
MutexIF* mutex;
|
||||
|
||||
std::vector<DatasetEntryIF*> variables;
|
||||
|
||||
/**
|
||||
* lock the mutex of the set
|
||||
*/
|
||||
void lock();
|
||||
|
||||
/**
|
||||
* unlock the mutex of the set
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
bool hasChangedNoRead();
|
||||
};
|
87
src/fsfw/datapool/DatasetEntry.h
Normal file
87
src/fsfw/datapool/DatasetEntry.h
Normal file
|
@ -0,0 +1,87 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/introspection/Parameter.h>
|
||||
#include <fsfw/introspection/Types.h>
|
||||
#include <fsfw/introspection/TypesHelper.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Dataset.h"
|
||||
#include "DatasetEntryIF.h"
|
||||
// TODO: ifdef introspection stuff
|
||||
|
||||
template <typename T>
|
||||
class DatasetEntry : public Parameter<T>, public DatasetEntryIF {
|
||||
protected:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
DatasetEntry(Dataset *owner, const char *name)
|
||||
: Parameter<T>(owner, name)
|
||||
#else
|
||||
DatasetEntry(Dataset *owner)
|
||||
: Parameter<T>(owner)
|
||||
#endif
|
||||
{
|
||||
allocated = owner->registerEntry(this);
|
||||
if (!allocated) {
|
||||
return;
|
||||
}
|
||||
storedValue = new T();
|
||||
storedValid = new bool;
|
||||
}
|
||||
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
static DatasetEntry createDatasetEntry(Dataset *owner, const char *name) {
|
||||
return DatasetEntry(owner, name);
|
||||
}
|
||||
#else
|
||||
static DatasetEntry createDatasetEntry(Dataset *owner) { return DatasetEntry(owner); }
|
||||
#endif
|
||||
|
||||
~DatasetEntry() {
|
||||
if (allocated) {
|
||||
delete storedValue;
|
||||
delete storedValid;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void setValid(bool isValid) { valid = isValid; }
|
||||
|
||||
virtual bool getValid() { return valid; }
|
||||
|
||||
//T value; //TODO can this be private?
|
||||
|
||||
protected:
|
||||
virtual void commit() {
|
||||
*storedValue = Parameter<T>::value;
|
||||
*storedValid = valid;
|
||||
}
|
||||
virtual void read() {
|
||||
Parameter<T>::value = *storedValue;
|
||||
valid = *storedValid;
|
||||
}
|
||||
|
||||
virtual void connect(DatasetEntryIF *entry) {
|
||||
DatasetEntry<T> *theOther = dynamic_cast<DatasetEntry<T> *>(entry);
|
||||
if (theOther == nullptr) {
|
||||
// Configuration error
|
||||
return;
|
||||
}
|
||||
this->storedValue = theOther->storedValue;
|
||||
this->storedValid = theOther->storedValid;
|
||||
}
|
||||
|
||||
virtual bool changed() { return ((Parameter<T>::value != *storedValue) || (valid != *storedValid)); }
|
||||
|
||||
private:
|
||||
|
||||
T *storedValue;
|
||||
bool *storedValid;
|
||||
bool valid;
|
||||
bool allocated;
|
||||
};
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#define createDatasetEntry(p1, p2) createDatasetEntry(p1, p2)
|
||||
#else
|
||||
#define createDatasetEntry(p1, p2) createDatasetEntry(p1)
|
||||
#endif
|
39
src/fsfw/datapool/DatasetEntryIF.h
Normal file
39
src/fsfw/datapool/DatasetEntryIF.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLENTRYIF_H_
|
||||
#define FSFW_DATAPOOL_POOLENTRYIF_H_
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <fsfw/introspection/Types.h>
|
||||
|
||||
class DatasetEntryIF {
|
||||
friend class Dataset;
|
||||
|
||||
public:
|
||||
|
||||
virtual ~DatasetEntryIF() {}
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual void setValid(bool isValid) = 0;
|
||||
/**
|
||||
* @brief This method allows to set the valid information of the pool entry.
|
||||
*/
|
||||
virtual bool getValid() = 0;
|
||||
|
||||
|
||||
protected:
|
||||
virtual void commit() = 0;
|
||||
virtual void read() = 0;
|
||||
virtual void connect(DatasetEntryIF* entry) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* returns if value and actual value is different
|
||||
*/
|
||||
virtual bool changed() = 0;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLENTRYIF_H_ */
|
13
src/fsfw/datapool/HasDatapoolIF.h
Normal file
13
src/fsfw/datapool/HasDatapoolIF.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
//TODO ring
|
||||
class DatapoolHelper;
|
||||
#include "DatapoolHelper.h"
|
||||
|
||||
#include <fsfw/housekeeping/GeneratesHousekeepingIF.h>
|
||||
|
||||
class HasDatapoolIF: public GeneratesHousekeepingIF {
|
||||
public:
|
||||
virtual ~HasDatapoolIF() = default;
|
||||
virtual DatapoolHelper* getDatapoolHelper() = 0;
|
||||
};
|
|
@ -1,217 +0,0 @@
|
|||
#include "fsfw/datapool/PoolDataSetBase.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/datapool/ReadCommitIFAttorney.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount)
|
||||
: registeredVariables(registeredVariablesArray), maxFillCount(maxFillCount) {}
|
||||
|
||||
PoolDataSetBase::~PoolDataSetBase() {}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::registerVariable(PoolVariableIF* variable) {
|
||||
if (registeredVariables == nullptr) {
|
||||
/* Underlying container invalid */
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
if (state != States::STATE_SET_UNINITIALISED) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: Call made in wrong position." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: Call made in wrong position.");
|
||||
#endif
|
||||
return DataSetIF::DATA_SET_UNINITIALISED;
|
||||
}
|
||||
if (variable == nullptr) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: Pool variable is nullptr." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: Pool variable is nullptr.\n");
|
||||
#endif
|
||||
return DataSetIF::POOL_VAR_NULL;
|
||||
}
|
||||
if (fillCount >= maxFillCount) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::registerVariable: DataSet is full." << std::endl;
|
||||
#else
|
||||
sif::printError("DataSet::registerVariable: DataSet is full.\n");
|
||||
#endif
|
||||
return DataSetIF::DATA_SET_FULL;
|
||||
}
|
||||
registeredVariables[fillCount] = variable;
|
||||
fillCount++;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
ReturnValue_t error = result;
|
||||
if (state == States::STATE_SET_UNINITIALISED) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = readVariable(count);
|
||||
if (result != returnvalue::OK) {
|
||||
error = result;
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_WAS_READ;
|
||||
unlockDataPool();
|
||||
} else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||
"commit member datasets!"
|
||||
<< std::endl;
|
||||
#else
|
||||
sif::printWarning(
|
||||
"PoolDataSetBase::read: Call made in wrong position. Don't forget to "
|
||||
"commit member datasets!\n");
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
result = SET_WAS_ALREADY_READ;
|
||||
}
|
||||
|
||||
if (error != returnvalue::OK) {
|
||||
result = error;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
uint16_t PoolDataSetBase::getFillCount() const { return fillCount; }
|
||||
|
||||
ReturnValue_t PoolDataSetBase::readVariable(uint16_t count) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
if (registeredVariables[count] == nullptr) {
|
||||
/* Configuration error. */
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
|
||||
/* These checks are often performed by the respective variable implementation too, but I guess
|
||||
a double check does not hurt. */
|
||||
if (registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_WRITE and
|
||||
registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
|
||||
if (protectEveryReadCommitCall) {
|
||||
result =
|
||||
registeredVariables[count]->read(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
|
||||
} else {
|
||||
/* The readWithoutLock function is protected, so we use the attorney here */
|
||||
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
|
||||
if (result != returnvalue::OK) {
|
||||
result = INVALID_PARAMETER_DEFINITION;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t lockTimeout) {
|
||||
if (state == States::STATE_SET_WAS_READ) {
|
||||
handleAlreadyReadDatasetCommit(timeoutType, lockTimeout);
|
||||
return returnvalue::OK;
|
||||
} else {
|
||||
return handleUnreadDatasetCommit(timeoutType, lockTimeout);
|
||||
}
|
||||
}
|
||||
|
||||
void PoolDataSetBase::handleAlreadyReadDatasetCommit(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if ((registeredVariables[count]->getReadWriteMode() != PoolVariableIF::VAR_READ) and
|
||||
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||
if (protectEveryReadCommitCall) {
|
||||
registeredVariables[count]->commit(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
|
||||
} else {
|
||||
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::handleUnreadDatasetCommit(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
lockDataPool(timeoutType, lockTimeout);
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
if ((registeredVariables[count]->getReadWriteMode() == PoolVariableIF::VAR_WRITE) and
|
||||
(registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER)) {
|
||||
if (protectEveryReadCommitCall) {
|
||||
result =
|
||||
registeredVariables[count]->commit(timeoutTypeForSingleVars, mutexTimeoutForSingleVars);
|
||||
} else {
|
||||
/* The commitWithoutLock function is protected, so we use the attorney here */
|
||||
ReadCommitIFAttorney::commitWithoutLock(registeredVariables[count]);
|
||||
}
|
||||
|
||||
} else if (registeredVariables[count]->getDataPoolId() != PoolVariableIF::NO_PARAMETER) {
|
||||
if (result != COMMITING_WITHOUT_READING) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "DataSet::commit(): commit-without-read call made "
|
||||
"with non write-only variable."
|
||||
<< std::endl;
|
||||
#endif
|
||||
result = COMMITING_WITHOUT_READING;
|
||||
}
|
||||
}
|
||||
}
|
||||
state = States::STATE_SET_UNINITIALISED;
|
||||
unlockDataPool();
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
|
||||
uint32_t lockTimeout) {
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::unlockDataPool() { return returnvalue::OK; }
|
||||
|
||||
ReturnValue_t PoolDataSetBase::serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const {
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
ReturnValue_t PoolDataSetBase::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) {
|
||||
ReturnValue_t result = returnvalue::FAILED;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
result = registeredVariables[count]->deSerialize(buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t PoolDataSetBase::getSerializedSize() const {
|
||||
uint32_t size = 0;
|
||||
for (uint16_t count = 0; count < fillCount; count++) {
|
||||
size += registeredVariables[count]->getSerializedSize();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
void PoolDataSetBase::setContainer(PoolVariableIF** variablesContainer) {
|
||||
this->registeredVariables = variablesContainer;
|
||||
}
|
||||
|
||||
PoolVariableIF** PoolDataSetBase::getContainer() const { return registeredVariables; }
|
||||
|
||||
void PoolDataSetBase::setReadCommitProtectionBehaviour(bool protectEveryReadCommit,
|
||||
MutexIF::TimeoutType timeoutType,
|
||||
uint32_t mutexTimeout) {
|
||||
this->protectEveryReadCommitCall = protectEveryReadCommit;
|
||||
this->timeoutTypeForSingleVars = timeoutType;
|
||||
this->mutexTimeoutForSingleVars = mutexTimeout;
|
||||
}
|
|
@ -1,173 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLDATASETBASE_H_
|
||||
#define FSFW_DATAPOOL_POOLDATASETBASE_H_
|
||||
|
||||
#include "PoolDataSetIF.h"
|
||||
#include "PoolVariableIF.h"
|
||||
#include "fsfw/ipc/MutexIF.h"
|
||||
#include "fsfw/serialize/SerializeIF.h"
|
||||
|
||||
/**
|
||||
* @brief The DataSetBase class manages a set of locally checked out variables.
|
||||
* @details
|
||||
* This class manages a list, where a set of local variables (or pool variables)
|
||||
* are registered. They are checked-out (i.e. their values are looked
|
||||
* up and copied) with the read call. After the user finishes working with the
|
||||
* pool variables, he can write back all variable values to the pool with
|
||||
* the commit call. The data set manages locking and freeing the data pool,
|
||||
* to ensure that all values are read and written back at once.
|
||||
*
|
||||
* An internal state manages usage of this class. Variables may only be
|
||||
* registered before the read call is made, and the commit call only
|
||||
* after the read call.
|
||||
*
|
||||
* If pool variables are writable and not committed until destruction
|
||||
* of the set, the DataSet class automatically sets the valid flag in the
|
||||
* data pool to invalid (without) changing the variable's value.
|
||||
*
|
||||
* The base class lockDataPool und unlockDataPool implementation are empty
|
||||
* and should be implemented to protect the underlying pool type.
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
|
||||
public:
|
||||
/**
|
||||
* @brief Creates an empty dataset. Use registerVariable or
|
||||
* supply a pointer to this dataset to PoolVariable
|
||||
* initializations to register pool variables.
|
||||
*/
|
||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, size_t maxFillCount);
|
||||
|
||||
/* Forbidden for now */
|
||||
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
|
||||
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
|
||||
|
||||
~PoolDataSetBase() override;
|
||||
|
||||
/**
|
||||
* @brief The read call initializes reading out all registered variables.
|
||||
* It is mandatory to call commit after every read call!
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls all read()
|
||||
* functions of the registered pool variables (which read out their values
|
||||
* from the data pool) which are not write-only.
|
||||
* In case of an error (e.g. a wrong data type, or an invalid data pool id),
|
||||
* the operation is aborted and @c INVALID_PARAMETER_DEFINITION returned.
|
||||
*
|
||||
* The data pool is locked during the whole read operation and
|
||||
* freed afterwards. It is mandatory to call commit after a read call,
|
||||
* even if the read operation is not successful!
|
||||
* @return
|
||||
* - @c returnvalue::OK if all variables were read successfully.
|
||||
* - @c INVALID_PARAMETER_DEFINITION if a pool entry does not exist or there
|
||||
* is a type conflict.
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
* @details
|
||||
* It iterates through the list of registered variables and calls the
|
||||
* commit() method of the remaining registered variables (which write back
|
||||
* their values to the pool).
|
||||
*
|
||||
* The data pool is locked during the whole commit operation and
|
||||
* freed afterwards. The state changes to "was committed" after this operation.
|
||||
*
|
||||
* If the set does contain at least one variable which is not write-only
|
||||
* commit() can only be called after read(). If the set only contains
|
||||
* variables which are write only, commit() can be called without a
|
||||
* preceding read() call. Every read call must be followed by a commit call!
|
||||
* @return - @c returnvalue::OK if all variables were read successfully.
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
|
||||
/**
|
||||
* Register the passed pool variable instance into the data set.
|
||||
* @param variable
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t registerVariable(PoolVariableIF* variable) override;
|
||||
|
||||
/**
|
||||
* Provides the means to lock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c returnvalue::OK
|
||||
*/
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) override;
|
||||
/**
|
||||
* Provides the means to unlock the underlying data structure to ensure
|
||||
* thread-safety. Default implementation is empty
|
||||
* @return Always returns -@c returnvalue::OK
|
||||
*/
|
||||
virtual ReturnValue_t unlockDataPool() override;
|
||||
|
||||
virtual uint16_t getFillCount() const override;
|
||||
|
||||
/* SerializeIF implementations */
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
|
||||
SerializeIF::Endianness streamEndianness) const override;
|
||||
virtual size_t getSerializedSize() const override;
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override;
|
||||
|
||||
/**
|
||||
* Can be used to individually protect every read and commit call.
|
||||
* @param protectEveryReadCommit
|
||||
* @param mutexTimeout
|
||||
*/
|
||||
void setReadCommitProtectionBehaviour(
|
||||
bool protectEveryReadCommit, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t mutexTimeout = 20);
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @brief The fill_count attribute ensures that the variables
|
||||
* register in the correct array position and that the maximum
|
||||
* number of variables is not exceeded.
|
||||
*/
|
||||
uint16_t fillCount = 0;
|
||||
/**
|
||||
* States of the seet.
|
||||
*/
|
||||
enum class States {
|
||||
STATE_SET_UNINITIALISED, //!< DATA_SET_UNINITIALISED
|
||||
STATE_SET_WAS_READ //!< DATA_SET_WAS_READ
|
||||
};
|
||||
/**
|
||||
* @brief state manages the internal state of the data set,
|
||||
* which is important e.g. for the behavior on destruction.
|
||||
*/
|
||||
States state = States::STATE_SET_UNINITIALISED;
|
||||
|
||||
/**
|
||||
* @brief This array represents all pool variables registered in this set.
|
||||
* Child classes can use a static or dynamic container to create
|
||||
* an array of registered variables and assign the first entry here.
|
||||
*/
|
||||
PoolVariableIF** registeredVariables = nullptr;
|
||||
const size_t maxFillCount = 0;
|
||||
|
||||
void setContainer(PoolVariableIF** variablesContainer);
|
||||
PoolVariableIF** getContainer() const;
|
||||
|
||||
private:
|
||||
bool protectEveryReadCommitCall = false;
|
||||
MutexIF::TimeoutType timeoutTypeForSingleVars = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t mutexTimeoutForSingleVars = 20;
|
||||
|
||||
ReturnValue_t readVariable(uint16_t count);
|
||||
void handleAlreadyReadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20);
|
||||
ReturnValue_t handleUnreadDatasetCommit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20);
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */
|
|
@ -1,34 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLDATASETIF_H_
|
||||
#define FSFW_DATAPOOL_POOLDATASETIF_H_
|
||||
|
||||
#include "DataSetIF.h"
|
||||
#include "ReadCommitIF.h"
|
||||
|
||||
/**
|
||||
* @brief Extendes the DataSetIF by adding abstract functions to lock
|
||||
* and unlock a data pool and read/commit semantics.
|
||||
*/
|
||||
class PoolDataSetIF : virtual public DataSetIF, virtual public ReadCommitIF {
|
||||
public:
|
||||
virtual ~PoolDataSetIF(){};
|
||||
|
||||
/**
|
||||
* @brief Most underlying data structures will have a pool like structure
|
||||
* and will require a lock and unlock mechanism to ensure
|
||||
* thread-safety
|
||||
* @return Lock operation result
|
||||
*/
|
||||
virtual ReturnValue_t lockDataPool(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t timeoutMs = 20) = 0;
|
||||
|
||||
/**
|
||||
* @brief Unlock call corresponding to the lock call.
|
||||
* @return Unlock operation result
|
||||
*/
|
||||
virtual ReturnValue_t unlockDataPool() = 0;
|
||||
|
||||
virtual bool isValid() const = 0;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLDATASETIF_H_ */
|
|
@ -1,102 +0,0 @@
|
|||
#include "fsfw/datapool/PoolEntry.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstring>
|
||||
|
||||
#include "fsfw/globalfunctions/arrayprinter.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(uint8_t len, bool setValid) : length(len), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
std::memset(this->address, 0, this->getByteSize());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(std::initializer_list<T> initValues, bool setValid)
|
||||
: length(static_cast<uint8_t>(initValues.size())), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
if (initValues.size() > 0) {
|
||||
std::copy(initValues.begin(), initValues.end(), this->address);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
PoolEntry<T>::PoolEntry(const T* initValue, uint8_t setLength, bool setValid)
|
||||
: length(setLength), valid(setValid) {
|
||||
this->address = new T[this->length]();
|
||||
if (initValue != nullptr) {
|
||||
std::memcpy(this->address, initValue, this->getByteSize());
|
||||
}
|
||||
}
|
||||
|
||||
// As the data pool is global, this dtor is only be called on program exit.
|
||||
// Warning! Never copy pool entries!
|
||||
template <typename T>
|
||||
PoolEntry<T>::~PoolEntry() {
|
||||
delete[] this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint16_t PoolEntry<T>::getByteSize() {
|
||||
return (sizeof(T) * this->length);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
uint8_t PoolEntry<T>::getSize() {
|
||||
return this->length;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void* PoolEntry<T>::getRawData() {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::setValid(bool isValid) {
|
||||
this->valid = isValid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool PoolEntry<T>::getValid() {
|
||||
return valid;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void PoolEntry<T>::print() {
|
||||
const char* validString = nullptr;
|
||||
if (valid) {
|
||||
validString = "Valid";
|
||||
} else {
|
||||
validString = "Invalid";
|
||||
}
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "PoolEntry information." << std::endl;
|
||||
sif::info << "PoolEntry validity: " << validString << std::endl;
|
||||
#else
|
||||
sif::printInfo("PoolEntry information.\n");
|
||||
sif::printInfo("PoolEntry validity: %s\n", validString);
|
||||
#endif
|
||||
arrayprinter::print(reinterpret_cast<uint8_t*>(address), getByteSize());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T* PoolEntry<T>::getDataPtr() {
|
||||
return this->address;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
Type PoolEntry<T>::getType() {
|
||||
return PodTypeConversion<T>::type;
|
||||
}
|
||||
|
||||
template class PoolEntry<uint8_t>;
|
||||
template class PoolEntry<uint16_t>;
|
||||
template class PoolEntry<uint32_t>;
|
||||
template class PoolEntry<uint64_t>;
|
||||
template class PoolEntry<int8_t>;
|
||||
template class PoolEntry<int16_t>;
|
||||
template class PoolEntry<int32_t>;
|
||||
template class PoolEntry<int64_t>;
|
||||
template class PoolEntry<float>;
|
||||
template class PoolEntry<double>;
|
|
@ -1,140 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLENTRY_H_
|
||||
#define FSFW_DATAPOOL_POOLENTRY_H_
|
||||
|
||||
#include <cstddef>
|
||||
#include <initializer_list>
|
||||
#include <type_traits>
|
||||
|
||||
#include "PoolEntryIF.h"
|
||||
|
||||
/**
|
||||
* @brief This is a small helper class that defines a single data pool entry.
|
||||
* @details
|
||||
* The helper is used to store all information together with the data as a
|
||||
* single data pool entry. The content's type is defined by the template
|
||||
* argument.
|
||||
*
|
||||
* It is prepared for use with plain old data types, but may be
|
||||
* extended to complex types if necessary. It can be initialized with a
|
||||
* certain value, size and validity flag.
|
||||
*
|
||||
* It holds a pointer to the real data and offers methods to access this data
|
||||
* and to acquire additional information (such as validity and array/byte size).
|
||||
* It is NOT intended to be used outside DataPool implementations as it performs
|
||||
* dynamic memory allocation.
|
||||
*
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
template <typename T>
|
||||
class PoolEntry : public PoolEntryIF {
|
||||
public:
|
||||
static_assert(not std::is_same<T, bool>::value,
|
||||
"Do not use boolean for the PoolEntry type, use uint8_t "
|
||||
"instead! The ECSS standard defines a boolean as a one bit "
|
||||
"field. Therefore it is preferred to store a boolean as an "
|
||||
"uint8_t");
|
||||
|
||||
PoolEntry(uint8_t len = 1, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential initialization values are copied to that space.
|
||||
* @details
|
||||
* Not passing any arguments will initialize an non-array pool entry
|
||||
* with an initial invalid state and the value 0.
|
||||
* Please note that if an initializer list is passed, the length of the
|
||||
* initializer list needs to be correct for vector entries because
|
||||
* required allocated space will be deduced from the initializer list length
|
||||
* and the pool entry type.
|
||||
* @param initValue
|
||||
* Initializer list with values to initialize with, for example {0, 0} to
|
||||
* initialize the a pool entry of a vector with two entries to 0.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(std::initializer_list<T> initValue, bool setValid = false);
|
||||
|
||||
/**
|
||||
* @brief In the classe's constructor, space is allocated on the heap and
|
||||
* potential init values are copied to that space.
|
||||
* @param initValue
|
||||
* A pointer to the single value or array that holds the init value.
|
||||
* With the default value (nullptr), the entry is initalized with all 0.
|
||||
* @param setLength
|
||||
* Defines the array length of this entry.
|
||||
* @param setValid
|
||||
* Sets the initialization flag. It is invalid by default.
|
||||
*/
|
||||
PoolEntry(const T* initValue, uint8_t setLength = 1, bool setValid = false);
|
||||
|
||||
//! Explicitely deleted copy ctor, copying is not allowed.
|
||||
PoolEntry(const PoolEntry&) = delete;
|
||||
//! Explicitely deleted copy assignment, copying is not allowed.
|
||||
PoolEntry& operator=(const PoolEntry&) = delete;
|
||||
|
||||
/**
|
||||
* @brief The allocated memory for the variable is freed
|
||||
* in the destructor.
|
||||
* @details
|
||||
* As the data pool is global, this dtor is only called on program exit.
|
||||
* PoolEntries shall never be copied, as a copy might delete the variable
|
||||
* on the heap.
|
||||
*/
|
||||
~PoolEntry();
|
||||
|
||||
/**
|
||||
* Return typed pointer to start of data.
|
||||
* @return
|
||||
*/
|
||||
T* getDataPtr();
|
||||
|
||||
/**
|
||||
* @brief getSize returns the array size of the entry.
|
||||
* @details
|
||||
* For non-array pool entries return type size, for vector entries
|
||||
* return type size times the number of entries.
|
||||
*/
|
||||
uint8_t getSize();
|
||||
/**
|
||||
* @brief This operation returns the size in bytes.
|
||||
* @details The size is calculated by sizeof(type) * array_size.
|
||||
*/
|
||||
uint16_t getByteSize();
|
||||
/**
|
||||
* @brief This operation returns a the address pointer casted to void*.
|
||||
*/
|
||||
void* getRawData();
|
||||
/**
|
||||
* @brief This method allows to set the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
void setValid(bool isValid);
|
||||
/**
|
||||
* @brief This method allows to get the valid information
|
||||
* of the pool entry.
|
||||
*/
|
||||
bool getValid();
|
||||
/**
|
||||
* @brief This is a debug method that prints all values and the valid
|
||||
* information to the screen. It prints all array entries in a row.
|
||||
*/
|
||||
void print();
|
||||
Type getType();
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief This attribute stores the length information.
|
||||
*/
|
||||
uint8_t length;
|
||||
/**
|
||||
* @brief Here, the validity information for a variable is stored.
|
||||
* Every entry (single variable or vector) has one valid flag.
|
||||
*/
|
||||
uint8_t valid;
|
||||
/**
|
||||
* @brief This is the address pointing to the allocated memory.
|
||||
*/
|
||||
T* address;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLENTRY_H_ */
|
|
@ -1,28 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLVARLIST_H_
|
||||
#define FSFW_DATAPOOL_POOLVARLIST_H_
|
||||
|
||||
#include "../datapool/PoolVariableIF.h"
|
||||
#include "../datapoolglob/GlobalPoolVariable.h"
|
||||
template <class T, uint8_t n_var>
|
||||
class PoolVarList {
|
||||
private:
|
||||
GlobPoolVar<T> variables[n_var];
|
||||
|
||||
public:
|
||||
PoolVarList(const uint32_t set_id[n_var], DataSetIF* dataSet,
|
||||
PoolVariableIF::ReadWriteMode_t setReadWriteMode) {
|
||||
// I really should have a look at the new init list c++ syntax.
|
||||
if (dataSet == NULL) {
|
||||
return;
|
||||
}
|
||||
for (uint8_t count = 0; count < n_var; count++) {
|
||||
variables[count].dataPoolId = set_id[count];
|
||||
variables[count].readWriteMode = setReadWriteMode;
|
||||
dataSet->registerVariable(&variables[count]);
|
||||
}
|
||||
}
|
||||
|
||||
GlobPoolVar<T>& operator[](int i) { return variables[i]; }
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLVARLIST_H_ */
|
|
@ -1,62 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||
#define FSFW_DATAPOOL_POOLVARIABLEIF_H_
|
||||
|
||||
#include "../returnvalues/returnvalue.h"
|
||||
#include "../serialize/SerializeIF.h"
|
||||
#include "ReadCommitIF.h"
|
||||
|
||||
/**
|
||||
* @brief This interface is used to control data pool
|
||||
* variable representations.
|
||||
* @details
|
||||
* To securely handle data pool variables, all pool entries are locally
|
||||
* managed by data pool variable access classes, which are called pool
|
||||
* variables. To ensure a common state of a set of variables needed in a
|
||||
* function, these local pool variables again are managed by other classes,
|
||||
* like the DataSet classes. This interface provides unified access to
|
||||
* local pool variables for such manager classes.
|
||||
* @author Bastian Baetz
|
||||
* @ingroup data_pool
|
||||
*/
|
||||
class PoolVariableIF : public SerializeIF, public ReadCommitIF {
|
||||
public:
|
||||
static constexpr uint8_t INTERFACE_ID = CLASS_ID::POOL_VARIABLE_IF;
|
||||
static constexpr ReturnValue_t INVALID_READ_WRITE_MODE = MAKE_RETURN_CODE(0xA0);
|
||||
static constexpr ReturnValue_t INVALID_POOL_ENTRY = MAKE_RETURN_CODE(0xA1);
|
||||
|
||||
static constexpr bool VALID = 1;
|
||||
static constexpr bool INVALID = 0;
|
||||
static constexpr uint32_t NO_PARAMETER = 0xffffffff;
|
||||
|
||||
enum ReadWriteMode_t { VAR_READ, VAR_WRITE, VAR_READ_WRITE };
|
||||
|
||||
/**
|
||||
* @brief This is an empty virtual destructor,
|
||||
* as it is proposed for C++ interfaces.
|
||||
*/
|
||||
virtual ~PoolVariableIF() {}
|
||||
/**
|
||||
* @brief This method returns if the variable is write-only,
|
||||
* read-write or read-only.
|
||||
*/
|
||||
virtual ReadWriteMode_t getReadWriteMode() const = 0;
|
||||
virtual void setReadWriteMode(ReadWriteMode_t newMode) = 0;
|
||||
|
||||
/**
|
||||
* @brief This operation shall return the data pool id of the variable.
|
||||
*/
|
||||
virtual uint32_t getDataPoolId() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the
|
||||
* variable is returned.
|
||||
*/
|
||||
virtual bool isValid() const = 0;
|
||||
/**
|
||||
* @brief With this call, the valid information of the variable is set.
|
||||
*/
|
||||
virtual void setValid(bool validity) = 0;
|
||||
};
|
||||
|
||||
using pool_rwm_t = PoolVariableIF::ReadWriteMode_t;
|
||||
|
||||
#endif /* FSFW_DATAPOOL_POOLVARIABLEIF_H_ */
|
|
@ -1,27 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_READCOMMITIF_H_
|
||||
#define FSFW_DATAPOOL_READCOMMITIF_H_
|
||||
|
||||
#include "../ipc/MutexIF.h"
|
||||
#include "../returnvalues/returnvalue.h"
|
||||
|
||||
/**
|
||||
* @brief Common interface for all software objects which employ read-commit
|
||||
* semantics.
|
||||
*/
|
||||
class ReadCommitIF {
|
||||
friend class ReadCommitIFAttorney;
|
||||
|
||||
public:
|
||||
virtual ~ReadCommitIF() {}
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 0;
|
||||
|
||||
protected:
|
||||
/* Optional and protected because this is interesting for classes grouping members with commit
|
||||
and read semantics where the lock is only necessary once. */
|
||||
virtual ReturnValue_t readWithoutLock() { return read(MutexIF::TimeoutType::WAITING, 20); }
|
||||
|
||||
virtual ReturnValue_t commitWithoutLock() { return commit(MutexIF::TimeoutType::WAITING, 20); }
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_READCOMMITIF_H_ */
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||
#define FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_
|
||||
|
||||
#include <fsfw/datapool/ReadCommitIF.h>
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
|
||||
/**
|
||||
* @brief This class determines which members are allowed to access protected members
|
||||
* of the ReadCommitIF.
|
||||
*/
|
||||
class ReadCommitIFAttorney {
|
||||
private:
|
||||
static ReturnValue_t readWithoutLock(ReadCommitIF* readCommitIF) {
|
||||
if (readCommitIF == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return readCommitIF->readWithoutLock();
|
||||
}
|
||||
|
||||
static ReturnValue_t commitWithoutLock(ReadCommitIF* readCommitIF) {
|
||||
if (readCommitIF == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return readCommitIF->commitWithoutLock();
|
||||
}
|
||||
|
||||
friend class PoolDataSetBase;
|
||||
};
|
||||
|
||||
#endif /* FSFW_DATAPOOL_READCOMMITIFATTORNEY_H_ */
|
|
@ -1,16 +0,0 @@
|
|||
#ifndef FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
#define FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_
|
||||
|
||||
#include "PoolDataSetIF.h"
|
||||
|
||||
class SharedDataSetIF {
|
||||
public:
|
||||
virtual ~SharedDataSetIF(){};
|
||||
|
||||
private:
|
||||
virtual ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType,
|
||||
dur_millis_t mutexTimeout) = 0;
|
||||
virtual ReturnValue_t unlockDataset() = 0;
|
||||
};
|
||||
|
||||
#endif /* FRAMEWORK_DATAPOOL_SHAREDDATASETIF_H_ */
|
|
@ -1,11 +0,0 @@
|
|||
#ifndef FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||
#define FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
|
||||
|
||||
/* Collected related headers */
|
||||
#include "fsfw/datapoollocal/LocalDataSet.h"
|
||||
#include "fsfw/datapoollocal/LocalPoolVariable.h"
|
||||
#include "fsfw/datapoollocal/LocalPoolVector.h"
|
||||
#include "fsfw/datapoollocal/SharedLocalDataSet.h"
|
||||
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
|
||||
|
||||
#endif /* FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_ */
|
|
@ -12,7 +12,7 @@ ChildHandlerBase::ChildHandlerBase(object_id_t setObjectId, object_id_t deviceCo
|
|||
parentId(parent),
|
||||
childHandlerFdir(setObjectId) {
|
||||
this->setHkDestination(hkDestination);
|
||||
this->setThermalStateRequestPoolIds(thermalStatePoolId, thermalRequestPoolId);
|
||||
this->setThermalStateRequestPoolIds(); //TODO
|
||||
}
|
||||
|
||||
ChildHandlerBase::~ChildHandlerBase() {}
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
|
||||
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#include "fsfw/datapoollocal/LocalPoolVariable.h"
|
||||
#include "DeviceHandlerBase.h"
|
||||
#include "fsfw/devicehandlers/AcceptsDeviceResponsesIF.h"
|
||||
#include "fsfw/devicehandlers/DeviceTmReportingWrapper.h"
|
||||
#include "fsfw/globalfunctions/CRC.h"
|
||||
#include "fsfw/housekeeping/HousekeepingMessage.h"
|
||||
#include "fsfw/ipc/MessageQueueMessage.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
|
@ -33,7 +31,7 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
|
|||
modeHelper(this),
|
||||
parameterHelper(this),
|
||||
actionHelper(this, nullptr),
|
||||
poolManager(this, nullptr),
|
||||
datapoolHelper(this),
|
||||
childTransitionFailure(returnvalue::OK),
|
||||
fdirInstance(fdirInstance),
|
||||
defaultFDIRUsed(fdirInstance == nullptr),
|
||||
|
@ -59,12 +57,7 @@ void DeviceHandlerBase::setHkDestination(object_id_t hkDestination) {
|
|||
this->hkDestination = hkDestination;
|
||||
}
|
||||
|
||||
void DeviceHandlerBase::setThermalStateRequestPoolIds(lp_id_t thermalStatePoolId,
|
||||
lp_id_t heaterRequestPoolId,
|
||||
uint32_t thermalSetId) {
|
||||
thermalSet =
|
||||
new DeviceHandlerThermalSet(this, thermalSetId, thermalStatePoolId, heaterRequestPoolId);
|
||||
}
|
||||
void DeviceHandlerBase::setThermalStateRequestPoolIds() {}
|
||||
|
||||
DeviceHandlerBase::~DeviceHandlerBase() {
|
||||
if (comCookie != nullptr) {
|
||||
|
@ -115,9 +108,6 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
|
|||
break;
|
||||
case CommunicationAction::GET_READ:
|
||||
doGetRead();
|
||||
/* This will be performed after datasets have been updated by the
|
||||
custom device implementation. */
|
||||
poolManager.performHkOperation();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -206,6 +196,10 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = datapoolHelper.initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
result = fdirInstance->initialize();
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
|
@ -216,22 +210,22 @@ ReturnValue_t DeviceHandlerBase::initialize() {
|
|||
return result;
|
||||
}
|
||||
|
||||
result = poolManager.initialize(commandQueue);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
// result = poolManager.initialize(commandQueue);
|
||||
// if (result != returnvalue::OK) {
|
||||
// return result;
|
||||
// }
|
||||
|
||||
fillCommandAndReplyMap();
|
||||
|
||||
if (thermalSet != nullptr) {
|
||||
// Set temperature target state to NON_OP.
|
||||
result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
thermalSet->heaterRequest.setValid(true);
|
||||
thermalSet->commit();
|
||||
}
|
||||
}
|
||||
// if (thermalSet != nullptr) { //TODO
|
||||
// // Set temperature target state to NON_OP.
|
||||
// result = thermalSet->read();
|
||||
// if (result == returnvalue::OK) {
|
||||
// thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
// thermalSet->heaterRequest.setValid(true);
|
||||
// thermalSet->commit();
|
||||
// }
|
||||
// }
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
@ -291,10 +285,10 @@ void DeviceHandlerBase::readCommandQueue() {
|
|||
return;
|
||||
}
|
||||
|
||||
result = poolManager.handleHousekeepingMessage(&command);
|
||||
if (result == returnvalue::OK) {
|
||||
return;
|
||||
}
|
||||
// result = poolManager.handleHousekeepingMessage(&command); //TODO
|
||||
// if (result == returnvalue::OK) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
result = handleDeviceHandlerMessage(&command);
|
||||
if (result == returnvalue::OK) {
|
||||
|
@ -421,7 +415,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode, Submode_t s
|
|||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, LocalPoolDataSetBase* replyDataSet,
|
||||
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, void* replyDataSet /*TODO*/,
|
||||
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
|
||||
Countdown* countdown) {
|
||||
// No need to check, as we may try to insert multiple times.
|
||||
|
@ -436,14 +430,14 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
|
|||
|
||||
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||
uint16_t maxDelayCycles,
|
||||
LocalPoolDataSetBase* dataSet, size_t replyLen,
|
||||
void* dataSet/*TODO*/, size_t replyLen,
|
||||
bool periodic, Countdown* countdown) {
|
||||
DeviceReplyInfo info;
|
||||
info.maxDelayCycles = maxDelayCycles;
|
||||
info.periodic = periodic;
|
||||
info.delayCycles = 0;
|
||||
info.replyLen = replyLen;
|
||||
info.dataSet = dataSet;
|
||||
//info.dataSet = dataSet;
|
||||
info.command = deviceCommandMap.end();
|
||||
info.countdown = countdown;
|
||||
auto resultPair = deviceReplyMap.emplace(replyId, info);
|
||||
|
@ -536,15 +530,15 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
|
|||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
|
||||
LocalPoolDataSetBase* dataSet) {
|
||||
auto replyIter = deviceReplyMap.find(replyId);
|
||||
if (replyIter == deviceReplyMap.end()) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
replyIter->second.dataSet = dataSet;
|
||||
return returnvalue::OK;
|
||||
}
|
||||
// ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
|
||||
// void* dataSet/*TODO*/) {
|
||||
// auto replyIter = deviceReplyMap.find(replyId);
|
||||
// if (replyIter == deviceReplyMap.end()) {
|
||||
// return returnvalue::FAILED;
|
||||
// }
|
||||
// replyIter->second.dataSet = dataSet;
|
||||
// return returnvalue::OK;
|
||||
// }
|
||||
|
||||
void DeviceHandlerBase::callChildStatemachine() {
|
||||
if (mode == _MODE_START_UP) {
|
||||
|
@ -580,15 +574,15 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
|
|||
}
|
||||
Clock::getUptime(&timeoutStart);
|
||||
|
||||
if (mode == MODE_OFF and thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
}
|
||||
thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
|
||||
}
|
||||
}
|
||||
// if (mode == MODE_OFF and thermalSet != nullptr) { //TODO
|
||||
// ReturnValue_t result = thermalSet->read();
|
||||
// if (result == returnvalue::OK) {
|
||||
// if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
// thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
|
||||
// }
|
||||
// thermalSet->heaterRequest.commit(PoolVariableIF::VALID);
|
||||
// }
|
||||
// }
|
||||
/* TODO: This will probably be done by the LocalDataPoolManager now */
|
||||
// changeHK(mode, submode, true);
|
||||
}
|
||||
|
@ -1077,14 +1071,14 @@ ReturnValue_t DeviceHandlerBase::checkModeCommand(Mode_t commandedMode, Submode_
|
|||
}
|
||||
|
||||
if ((commandedMode == MODE_ON) && (mode == MODE_OFF) and (thermalSet != nullptr)) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
|
||||
(not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
|
||||
triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
|
||||
return NON_OP_TEMPERATURE;
|
||||
}
|
||||
}
|
||||
// ReturnValue_t result = thermalSet->read(); //TODO
|
||||
// if (result == returnvalue::OK) {
|
||||
// if ((thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) and
|
||||
// (not ThermalComponentIF::isOperational(thermalSet->thermalState.value))) {
|
||||
// triggerEvent(ThermalComponentIF::TEMP_NOT_IN_OP_RANGE, thermalSet->thermalState.value);
|
||||
// return NON_OP_TEMPERATURE;
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
return isModeCombinationValid(commandedMode, commandedSubmode);
|
||||
|
@ -1136,15 +1130,15 @@ void DeviceHandlerBase::handleTransitionToOnMode(Mode_t commandedMode, Submode_t
|
|||
// need to call it twice
|
||||
childTransitionDelay = getTransitionDelayMs(_MODE_START_UP, MODE_ON);
|
||||
triggerEvent(CHANGING_MODE, commandedMode, commandedSubmode);
|
||||
if (thermalSet != nullptr) {
|
||||
ReturnValue_t result = thermalSet->read();
|
||||
if (result == returnvalue::OK) {
|
||||
if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||
thermalSet->commit();
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (thermalSet != nullptr) { //TODO
|
||||
// ReturnValue_t result = thermalSet->read();
|
||||
// if (result == returnvalue::OK) {
|
||||
// if (thermalSet->heaterRequest != ThermalComponentIF::STATE_REQUEST_IGNORE) {
|
||||
// thermalSet->heaterRequest = ThermalComponentIF::STATE_REQUEST_OPERATIONAL;
|
||||
// thermalSet->commit();
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
} else {
|
||||
setTransition(MODE_ON, commandedSubmode);
|
||||
}
|
||||
|
@ -1314,22 +1308,23 @@ 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);
|
||||
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 {
|
||||
iter->second.sendReplyTo = commandedBy;
|
||||
result = buildCommandFromCommand(actionId, data, size);
|
||||
result = action->handle();
|
||||
}
|
||||
if (result == returnvalue::OK) {
|
||||
iter->second.sendReplyTo = action->commandedBy;
|
||||
iter->second.isExecuting = true;
|
||||
cookieInfo.pendingCommand = iter;
|
||||
cookieInfo.state = COOKIE_WRITE_READY;
|
||||
|
@ -1459,24 +1454,12 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker, object_id_t obje
|
|||
|
||||
void DeviceHandlerBase::performOperationHook() {}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) {
|
||||
if (thermalSet != nullptr) {
|
||||
localDataPoolMap.emplace(thermalSet->thermalStatePoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>);
|
||||
localDataPoolMap.emplace(thermalSet->heaterRequestPoolId,
|
||||
new PoolEntry<DeviceHandlerIF::dh_heater_request_t>);
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
||||
// In this function, the task handle should be valid if the task
|
||||
// was implemented correctly. We still check to be 1000 % sure :-)
|
||||
if (executingTask != nullptr) {
|
||||
pstIntervalMs = executingTask->getPeriodMs();
|
||||
}
|
||||
this->poolManager.initializeAfterTaskCreation();
|
||||
|
||||
if (setStartupImmediately) {
|
||||
startTransition(MODE_ON, SUBMODE_NONE);
|
||||
|
@ -1484,21 +1467,10 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
|
|||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
|
||||
auto iter = deviceReplyMap.find(sid.ownerSetId);
|
||||
if (iter != deviceReplyMap.end()) {
|
||||
return iter->second.dataSet;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
object_id_t DeviceHandlerBase::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
void DeviceHandlerBase::setStartUpImmediately() { this->setStartupImmediately = true; }
|
||||
|
||||
dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { return pstIntervalMs; }
|
||||
|
||||
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
|
||||
if (cookieInfo.pendingCommand != deviceCommandMap.end()) {
|
||||
return cookieInfo.pendingCommand->first;
|
||||
|
@ -1507,16 +1479,19 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
|
|||
}
|
||||
|
||||
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() {
|
||||
for (const auto& reply : deviceReplyMap) {
|
||||
if (reply.second.dataSet != nullptr) {
|
||||
PoolReadGuard pg(reply.second.dataSet);
|
||||
if (pg.getReadResult() == returnvalue::OK) {
|
||||
reply.second.dataSet->setValidity(false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (const auto& reply : deviceReplyMap) {
|
||||
// if (reply.second.dataSet != nullptr) {
|
||||
// PoolReadGuard pg(reply.second.dataSet);
|
||||
// if (pg.getReadResult() == returnvalue::OK) {
|
||||
// reply.second.dataSet->setValidity(false, true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
||||
DatapoolHelper* DeviceHandlerBase::getDatapoolHelper() { return &datapoolHelper; }
|
||||
HousekeepingHelper* DeviceHandlerBase::getHousekeepingHelper() { return &datapoolHelper; }
|
||||
|
||||
void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const char* functionName,
|
||||
ReturnValue_t errorCode, const char* errorPrint) {
|
||||
if (errorPrint == nullptr) {
|
||||
|
@ -1557,8 +1532,6 @@ void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const ch
|
|||
}
|
||||
}
|
||||
|
||||
LocalDataPoolManager* DeviceHandlerBase::getHkManagerHandle() { return &poolManager; }
|
||||
|
||||
MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyId) const {
|
||||
auto commandIter = deviceCommandMap.find(replyId);
|
||||
if (commandIter == deviceCommandMap.end()) {
|
||||
|
@ -1566,3 +1539,5 @@ MessageQueueId_t DeviceHandlerBase::getCommanderQueueId(DeviceCommandId_t replyI
|
|||
}
|
||||
return commandIter->second.sendReplyTo;
|
||||
}
|
||||
|
||||
ModeHelper const* DeviceHandlerBase::getModeHelper() const { return &modeHelper; }
|
||||
|
|
|
@ -6,12 +6,11 @@
|
|||
#include "DeviceCommunicationIF.h"
|
||||
#include "DeviceHandlerFailureIsolation.h"
|
||||
#include "DeviceHandlerIF.h"
|
||||
#include "DeviceHandlerThermalSet.h"
|
||||
#include "fsfw/action/ActionHelper.h"
|
||||
#include "fsfw/action/HasActionsIF.h"
|
||||
#include "fsfw/datapool/PoolVariableIF.h"
|
||||
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
|
||||
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
// #include "fsfw/datapool/PoolVariableIF.h"
|
||||
#include "fsfw/datapool/HasDatapoolIF.h"
|
||||
// #include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
#include "fsfw/health/HealthHelper.h"
|
||||
#include "fsfw/ipc/MessageQueueIF.h"
|
||||
#include "fsfw/modes/HasModesIF.h"
|
||||
|
@ -84,7 +83,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
public HasHealthIF,
|
||||
public HasActionsIF,
|
||||
public ReceivesParameterMessagesIF,
|
||||
public HasLocalDataPoolIF {
|
||||
public HasDatapoolIF {
|
||||
friend void(Factory::setStaticFrameworkObjectIds)();
|
||||
|
||||
public:
|
||||
|
@ -113,10 +112,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* @param thermalStatePoolId
|
||||
* @param thermalRequestPoolId
|
||||
*/
|
||||
void setThermalStateRequestPoolIds(
|
||||
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID,
|
||||
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID,
|
||||
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID);
|
||||
void setThermalStateRequestPoolIds(); // TODO
|
||||
/**
|
||||
* @brief Helper function to ease device handler development.
|
||||
* This will instruct the transition to MODE_ON immediately
|
||||
|
@ -200,13 +196,14 @@ 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;
|
||||
HealthState getHealth();
|
||||
ReturnValue_t setHealth(HealthState health);
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint8_t uniqueId,
|
||||
|
@ -310,35 +307,10 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* - Anything else triggers an even with the returnvalue as a parameter
|
||||
*/
|
||||
virtual ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t *id) = 0;
|
||||
/**
|
||||
* @brief Build a device command packet from data supplied by a direct
|
||||
* command (PUS Service 8)
|
||||
* @details
|
||||
* This will be called if an functional command via PUS Service 8 is received and is
|
||||
* the primary interface for functional command instead of #executeAction for users. The
|
||||
* supplied ActionId_t action ID will be converted to a DeviceCommandId_t command ID after
|
||||
* an internal check whether the action ID is a key in the device command map.
|
||||
*
|
||||
* #rawPacket and #rawPacketLen should be set by this method to the packet to be sent.
|
||||
* The existence of the command in the command map and the command size check against 0 are
|
||||
* done by the base class.
|
||||
*
|
||||
* @param deviceCommand The command to build, already checked against deviceCommandMap
|
||||
* @param commandData Pointer to the data from the direct command
|
||||
* @param commandDataLen Length of commandData
|
||||
* @return
|
||||
* - @c returnvalue::OK to send command after #rawPacket and #rawPacketLen
|
||||
* have been set.
|
||||
* - @c HasActionsIF::EXECUTION_COMPLETE to generate a finish reply immediately. This can
|
||||
* be used if no reply is expected
|
||||
* - Anything else triggers an event with the return code as a parameter as well as a
|
||||
* step reply failed with the return code
|
||||
*/
|
||||
virtual ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
|
||||
const uint8_t *commandData,
|
||||
size_t commandDataLen) = 0;
|
||||
|
||||
/* Reply handling */
|
||||
// TODO add way to say, not enough data in buffer, try again later
|
||||
// ComIF needs to decide if buffer will be appended or overwritten
|
||||
/**
|
||||
* @brief Scans a buffer for a valid reply.
|
||||
* @details
|
||||
|
@ -454,7 +426,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* - @c returnvalue::FAILED else.
|
||||
*/
|
||||
ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
||||
LocalPoolDataSetBase *replyDataSet = nullptr,
|
||||
void *replyDataSet = nullptr,
|
||||
size_t replyLen = 0, bool periodic = false,
|
||||
bool hasDifferentReplyId = false,
|
||||
DeviceCommandId_t replyId = 0,
|
||||
|
@ -475,7 +447,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* - @c returnvalue::FAILED else.
|
||||
*/
|
||||
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
|
||||
LocalPoolDataSetBase *dataSet = nullptr, size_t replyLen = 0,
|
||||
void *dataSet = nullptr, size_t replyLen = 0,
|
||||
bool periodic = false, Countdown *countdown = nullptr);
|
||||
|
||||
/**
|
||||
|
@ -523,12 +495,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
*/
|
||||
ReturnValue_t updateReplyMapEntry(DeviceCommandId_t deviceReply, uint16_t delayCycles,
|
||||
uint16_t maxDelayCycles, bool periodic = false);
|
||||
/**
|
||||
* @brief Can be used to set the dataset corresponding to a reply ID manually.
|
||||
* @details
|
||||
* Used by the local data pool manager.
|
||||
*/
|
||||
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, LocalPoolDataSetBase *dataset);
|
||||
|
||||
/**
|
||||
* Get the time needed to transit from modeFrom to modeTo.
|
||||
|
@ -548,15 +514,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
*/
|
||||
virtual uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) = 0;
|
||||
|
||||
/* Functions used by the local data pool manager */
|
||||
/**
|
||||
* This function is used to initialize the local housekeeping pool
|
||||
* entries. The default implementation leaves the pool empty.
|
||||
* @param localDataPoolMap
|
||||
* @return
|
||||
*/
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) override;
|
||||
|
||||
/**
|
||||
* @brief Set all datapool variables that are update periodically in
|
||||
* normal mode invalid
|
||||
|
@ -566,16 +524,11 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* variables inside the dataset to invalid. The user can override this
|
||||
* method optionally.
|
||||
*/
|
||||
virtual void setNormalDatapoolEntriesInvalid();
|
||||
/**
|
||||
* @brief Get the dataset handle for a given SID.
|
||||
* @details
|
||||
* The default implementation will use the deviceCommandMap to look for the corresponding
|
||||
* dataset handle. The user can override this function if this is not desired.
|
||||
* @param sid
|
||||
* @return
|
||||
*/
|
||||
virtual LocalPoolDataSetBase *getDataSetHandle(sid_t sid) override;
|
||||
virtual void setNormalDatapoolEntriesInvalid(); //TODO
|
||||
|
||||
DatapoolHelper* getDatapoolHelper() override;
|
||||
HousekeepingHelper* getHousekeepingHelper() override;
|
||||
|
||||
|
||||
/* HasModesIF overrides */
|
||||
virtual void startTransition(Mode_t mode, Submode_t submode) override;
|
||||
|
@ -745,7 +698,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
/* Action helper for HasActionsIF */
|
||||
ActionHelper actionHelper;
|
||||
/* Housekeeping Manager */
|
||||
LocalDataPoolManager poolManager;
|
||||
DatapoolHelper datapoolHelper;
|
||||
|
||||
/**
|
||||
* @brief Information about commands
|
||||
|
@ -786,7 +739,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
//! The dataset used to access housekeeping data related to the
|
||||
//! respective device reply. Will point to a dataset held by
|
||||
//! the child handler (if one is specified)
|
||||
LocalPoolDataSetBase *dataSet = nullptr;
|
||||
// LocalPoolDataSetBase *dataSet = nullptr; TODO
|
||||
//! The command that expects this reply.
|
||||
DeviceCommandMap::iterator command;
|
||||
//! Instead of using delayCycles to specify the maximum time to wait for the device reply, it
|
||||
|
@ -818,7 +771,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
//! and to send replies.
|
||||
MessageQueueIF *commandQueue = nullptr;
|
||||
|
||||
DeviceHandlerThermalSet *thermalSet = nullptr;
|
||||
void *thermalSet = nullptr; //TODO
|
||||
|
||||
/**
|
||||
* Optional Error code. Can be set in doStartUp(), doShutDown() and
|
||||
|
@ -935,12 +888,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
*/
|
||||
virtual void doOnActivity();
|
||||
|
||||
/**
|
||||
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
|
||||
* @return
|
||||
*/
|
||||
LocalDataPoolManager *getHkManagerHandle() override;
|
||||
|
||||
/**
|
||||
* Returns the delay cycle count of a reply.
|
||||
* A count != 0 indicates that the command is already executed.
|
||||
|
@ -1032,7 +979,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
* by #switches are on
|
||||
* - @c PowerSwitchIF::SWITCH_OFF one of the switches specified by
|
||||
* #switches are off
|
||||
* - @c PowerSwitchIF::returnvalue::FAILED if an error occured
|
||||
* - @c returnvalue::FAILED if an error occured
|
||||
*/
|
||||
ReturnValue_t getStateOfSwitches();
|
||||
|
||||
|
@ -1307,8 +1254,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
|
|||
|
||||
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
|
||||
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
|
||||
void parseReply(const uint8_t *receivedData, size_t receivedDataLen);
|
||||
|
||||
void handleTransitionToOnMode(Mode_t commandedMode, Submode_t commandedSubmode);
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include "fsfw/health/HealthTableIF.h"
|
||||
#include "fsfw/modes/HasModesIF.h"
|
||||
#include "fsfw/objectmanager/ObjectManager.h"
|
||||
#include "fsfw/power/Fuse.h"
|
||||
//#include "fsfw/power/Fuse.h"
|
||||
#include <fsfw/power/PowerSwitchIF.h>
|
||||
#include "fsfw/serviceinterface/ServiceInterfaceStream.h"
|
||||
#include "fsfw/thermal/ThermalComponentIF.h"
|
||||
|
||||
|
@ -77,16 +78,16 @@ ReturnValue_t DeviceHandlerFailureIsolation::eventReceived(EventMessage* event)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case Fuse::FUSE_WENT_OFF:
|
||||
// Not so good, because PCDU reacted.
|
||||
case Fuse::POWER_ABOVE_HIGH_LIMIT:
|
||||
// Better, because software detected over-current.
|
||||
setFaulty(event->getEvent());
|
||||
break;
|
||||
case Fuse::POWER_BELOW_LOW_LIMIT:
|
||||
// Device might got stuck during boot, retry.
|
||||
handleRecovery(event->getEvent());
|
||||
break;
|
||||
// case Fuse::FUSE_WENT_OFF:
|
||||
// // Not so good, because PCDU reacted.
|
||||
// case Fuse::POWER_ABOVE_HIGH_LIMIT:
|
||||
// // Better, because software detected over-current.
|
||||
// setFaulty(event->getEvent());
|
||||
// break;
|
||||
// case Fuse::POWER_BELOW_LOW_LIMIT:
|
||||
// // Device might got stuck during boot, retry.
|
||||
// handleRecovery(event->getEvent());
|
||||
// break;
|
||||
//****Thermal*****
|
||||
case ThermalComponentIF::COMPONENT_TEMP_LOW:
|
||||
case ThermalComponentIF::COMPONENT_TEMP_HIGH:
|
||||
|
|
|
@ -2,8 +2,8 @@
|
|||
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
|
||||
|
||||
#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 +37,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
|
||||
*/
|
||||
FSFW_CLASSLESS_ENUM(
|
||||
DeviceHandlerMode, Mode_t,
|
||||
//! The device is powered and ready to perform operations. In this mode, no
|
||||
//! commands are sent by the device handler itself, but direct commands can be
|
||||
//! commanded and will be executed/forwarded to the device
|
||||
//! This is an alias of MODE_ON to have the FSFW_ENUM complete for introspection
|
||||
((DEVICEHANDLER_MODE_ON, HasModesIF::MODE_ON, "On"))
|
||||
//! The device is powered off. The only command accepted in this
|
||||
//! mode is a mode change to on.
|
||||
//! This is an alias of MODE_OFF to have the FSFW_ENUM complete for introspection
|
||||
((DEVICEHANDLER_MODE_OFF, HasModesIF::MODE_OFF, "Off"))
|
||||
//! The device is powered on and the device handler periodically sends
|
||||
//! commands. The commands to be sent are selected by the handler
|
||||
//! according to the submode.
|
||||
((MODE_NORMAL, 2, "Normal"))
|
||||
//! The device is powered on and ready to perform operations. In this mode,
|
||||
//! raw commands can be sent. The device handler will send all replies
|
||||
//! received from the command back to the commanding object as raw TM
|
||||
((MODE_RAW, 3, "Raw"))
|
||||
//! The device is shut down but the switch could not be turned off, so the
|
||||
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
|
||||
//! can be commanded, which tries to switch off the device again.
|
||||
((MODE_ERROR_ON, 4, "Error")))
|
||||
|
||||
// MODE_ON = 0, //!< The device is powered and ready to perform operations. In this mode, no
|
||||
// commands are sent by the device handler itself, but direct commands van be commanded and will
|
||||
// be interpreted MODE_OFF = 1, //!< The device is powered off. The only command accepted in this
|
||||
// mode is a mode change to on.
|
||||
//! The device is powered on and the device handler periodically sends
|
||||
//! commands. The commands to be sent are selected by the handler
|
||||
//! according to the submode.
|
||||
static const Mode_t MODE_NORMAL = 2;
|
||||
//! The device is powered on and ready to perform operations. In this mode,
|
||||
//! raw commands can be sent. The device handler will send all replies
|
||||
//! received from the command back to the commanding object.
|
||||
static const Mode_t MODE_RAW = 3;
|
||||
//! The device is shut down but the switch could not be turned off, so the
|
||||
//! device still is powered. In this mode, only a mode change to @c MODE_OFF
|
||||
//! can be commanded, which tries to switch off the device again.
|
||||
static const Mode_t MODE_ERROR_ON = 4;
|
||||
//! This is a transitional state which can not be commanded. The device
|
||||
//! handler performs all commands to get the device in a state ready to
|
||||
//! perform commands. When this is completed, the mode changes to @c MODE_ON.
|
||||
|
@ -162,10 +169,10 @@ class DeviceHandlerIF {
|
|||
NOTHING //!< Do nothing.
|
||||
};
|
||||
|
||||
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = sid_t::INVALID_SET_ID - 1;
|
||||
static constexpr uint32_t DEFAULT_THERMAL_SET_ID = 0; // TODO sid_t::INVALID_SET_ID - 1;
|
||||
|
||||
static constexpr lp_id_t DEFAULT_THERMAL_STATE_POOL_ID = localpool::INVALID_LPID - 2;
|
||||
static constexpr lp_id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID = localpool::INVALID_LPID - 1;
|
||||
static constexpr int DEFAULT_THERMAL_STATE_POOL_ID = 0; // TODOlocalpool::INVALID_LPID - 2;
|
||||
static constexpr int DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID = 0; // TODOlocalpool::INVALID_LPID - 1;
|
||||
|
||||
/**
|
||||
* Default Destructor
|
||||
|
|
|
@ -15,11 +15,12 @@ const LocalPool::LocalPoolConfig EventManager::poolConfig = {
|
|||
{fsfwconfig::FSFW_EVENTMGMT_EVENTIDMATCHERS, sizeof(EventIdRangeMatcher)},
|
||||
{fsfwconfig::FSFW_EVENTMGMR_RANGEMATCHERS, sizeof(ReporterRangeMatcher)}};
|
||||
|
||||
EventManager::EventManager(object_id_t setObjectId)
|
||||
EventManager::EventManager(object_id_t setObjectId, uint32_t eventQueueDepth)
|
||||
: SystemObject(setObjectId), factoryBackend(0, poolConfig, false, true) {
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(MAX_EVENTS_PER_CYCLE,
|
||||
EventMessage::EVENT_MESSAGE_SIZE);
|
||||
auto mqArgs = MqArgs(setObjectId, static_cast<void*>(this));
|
||||
eventReportQueue = QueueFactory::instance()->createMessageQueue(
|
||||
eventQueueDepth, EventMessage::EVENT_MESSAGE_SIZE, &mqArgs);
|
||||
}
|
||||
|
||||
EventManager::~EventManager() {
|
||||
|
@ -38,6 +39,16 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
|||
if (result == returnvalue::OK) {
|
||||
#if FSFW_OBJ_EVENT_TRANSLATION == 1
|
||||
printEvent(&message);
|
||||
#else
|
||||
//TODO
|
||||
sif::debug << "EventManager: ";
|
||||
sif::debug << "0x" << std::hex << std::setw(8) << std::setfill('0') << message.getReporter()
|
||||
<< std::setfill(' ') << std::dec;
|
||||
sif::debug << " reported event with ID " << message.getEventId() << std::endl;
|
||||
sif::debug << std::hex << "P1 Hex: 0x"
|
||||
<< message.getParameter1() << " | P1 Dec: " << std::dec << message.getParameter1()
|
||||
<< std::hex << " | P2 Hex: 0x" << message.getParameter2()
|
||||
<< " | P2 Dec: " << std::dec << message.getParameter2() << std::endl;
|
||||
#endif
|
||||
notifyListeners(&message);
|
||||
}
|
||||
|
@ -47,9 +58,20 @@ ReturnValue_t EventManager::performOperation(uint8_t opCode) {
|
|||
|
||||
void EventManager::notifyListeners(EventMessage* message) {
|
||||
lockMutex();
|
||||
for (auto iter = listenerList.begin(); iter != listenerList.end(); ++iter) {
|
||||
if (iter->second.match(message)) {
|
||||
MessageQueueSenderIF::sendMessage(iter->first, message, message->getSender());
|
||||
for (auto& listener : listenerList) {
|
||||
if (listener.second.match(message)) {
|
||||
ReturnValue_t result =
|
||||
MessageQueueSenderIF::sendMessage(listener.first, message, message->getSender());
|
||||
if (result != returnvalue::OK) {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << std::hex << "EventManager::notifyListeners: MSG to 0x" << std::setfill('0')
|
||||
<< std::setw(8) << listener.first << " failed with result 0x" << std::setw(4)
|
||||
<< result << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printError("Sending message to listener 0x%08x failed with result %04x\n",
|
||||
listener.first, result);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
unlockMutex();
|
||||
|
@ -200,4 +222,19 @@ void EventManager::printUtility(sif::OutputTypes printType, EventMessage* messag
|
|||
}
|
||||
}
|
||||
|
||||
void EventManager::printListeners() {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::info << "Event manager listener MQ IDs:" << std::setfill('0') << std::hex << std::endl;
|
||||
for (auto& listener : listenerList) {
|
||||
sif::info << "0x" << std::setw(8) << listener.first << std::endl;
|
||||
}
|
||||
sif::info << std::dec << std::setfill(' ');
|
||||
#else
|
||||
sif::printInfo("Event manager listener MQ IDs:\n");
|
||||
for (auto& listener : listenerList) {
|
||||
sif::printInfo("0x%08x\n", listener.first);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* FSFW_OBJ_EVENT_TRANSLATION == 1 */
|
||||
|
|
|
@ -21,9 +21,7 @@ extern const char* translateEvents(Event event);
|
|||
|
||||
class EventManager : public EventManagerIF, public ExecutableObjectIF, public SystemObject {
|
||||
public:
|
||||
static const uint16_t MAX_EVENTS_PER_CYCLE = 80;
|
||||
|
||||
EventManager(object_id_t setObjectId);
|
||||
EventManager(object_id_t setObjectId, uint32_t eventQueueDepth);
|
||||
virtual ~EventManager();
|
||||
|
||||
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
|
||||
|
@ -44,6 +42,7 @@ class EventManager : public EventManagerIF, public ExecutableObjectIF, public Sy
|
|||
object_id_t reporterFrom = 0, object_id_t reporterTo = 0,
|
||||
bool reporterInverted = false);
|
||||
ReturnValue_t performOperation(uint8_t opCode);
|
||||
void printListeners();
|
||||
|
||||
protected:
|
||||
MessageQueueIF* eventReportQueue = nullptr;
|
||||
|
|
|
@ -10,7 +10,7 @@ enum : uint8_t {
|
|||
CDH = 28,
|
||||
TCS_1 = 59,
|
||||
PCDU_1 = 42,
|
||||
PCDU_2 = 43,
|
||||
POWER_SWITCH_IF = 43,
|
||||
HEATER = 50,
|
||||
T_SENSORS = 52,
|
||||
FDIR = 70,
|
||||
|
@ -33,6 +33,7 @@ enum : uint8_t {
|
|||
PUS_SERVICE_23 = 103,
|
||||
MGM_LIS3MDL = 106,
|
||||
MGM_RM3100 = 107,
|
||||
CFDP = 108,
|
||||
|
||||
FW_SUBSYSTEM_ID_RANGE
|
||||
};
|
||||
|
|
|
@ -44,13 +44,13 @@ class Type : public SerializeIF {
|
|||
|
||||
static ActualType_t getActualType(uint8_t ptc, uint8_t pfc);
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
ReturnValue_t serialize(uint8_t **buffer, size_t *size, size_t maxSize,
|
||||
Endianness streamEndianness) const override;
|
||||
|
||||
virtual size_t getSerializedSize() const override;
|
||||
size_t getSerializedSize() const override;
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
ReturnValue_t deSerialize(const uint8_t **buffer, size_t *size,
|
||||
Endianness streamEndianness) override;
|
||||
|
||||
private:
|
||||
ActualType_t actualType;
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
|
||||
PeriodicHousekeepingHelper.cpp)
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingHelper.cpp
|
||||
HousekeepingSet.cpp )
|
||||
|
|
16
src/fsfw/housekeeping/GeneratesHousekeepingIF.h
Normal file
16
src/fsfw/housekeeping/GeneratesHousekeepingIF.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/tmtc/FsfwProtocolHeader.h>
|
||||
|
||||
#include "HousekeepingHelper.h"
|
||||
|
||||
class GeneratesHousekeepingIF {
|
||||
public:
|
||||
static const uint8_t INTERFACE_ID = CLASS_ID::GENERATES_HOUSEKEEPING;
|
||||
|
||||
enum Functions : FsfwProtocolHeader::FunctionType_t { REPORT };
|
||||
|
||||
virtual ~GeneratesHousekeepingIF() = default;
|
||||
|
||||
virtual HousekeepingHelper* getHousekeepingHelper() = 0;
|
||||
};
|
46
src/fsfw/housekeeping/HousekeepingHelper.cpp
Normal file
46
src/fsfw/housekeeping/HousekeepingHelper.cpp
Normal file
|
@ -0,0 +1,46 @@
|
|||
#include "HousekeepingHelper.h"
|
||||
|
||||
#include <fsfw/objectmanager/ObjectManager.h>
|
||||
|
||||
#include "GeneratesHousekeepingIF.h"
|
||||
|
||||
HousekeepingHelper::HousekeepingHelper(GeneratesHousekeepingIF* owner) : owner(owner) {}
|
||||
|
||||
ReturnValue_t HousekeepingHelper::initialize() {
|
||||
tmManager = ObjectManager::instance()->get<TmManager>(objects::TM_MANAGER);
|
||||
if (tmManager == nullptr) {
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
const HousekeepingSet* HousekeepingHelper::getHousekeepingSet(HousekeepingSetId_t id) {
|
||||
auto iter = housekeepingSets.find(id);
|
||||
if (iter == housekeepingSets.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return iter->second;
|
||||
}
|
||||
|
||||
void HousekeepingHelper::registerSet(HousekeepingSet* set) {
|
||||
auto id = set->getId();
|
||||
housekeepingSets.emplace(id, set);
|
||||
}
|
||||
|
||||
ReturnValue_t HousekeepingHelper::reportHousekeeping(HousekeepingSet* set, const Action* action) {
|
||||
SystemObjectIF* ownerAsObject = dynamic_cast<SystemObjectIF*>(owner);
|
||||
if (ownerAsObject == nullptr) {
|
||||
sif::error << "Duuuuuuuude, what the hell?" << std::endl;
|
||||
return returnvalue::FAILED;
|
||||
}
|
||||
store_address_t tc;
|
||||
size_t tcOffset = 0;
|
||||
if (action != nullptr) {
|
||||
tc = action->tc;
|
||||
tcOffset = action->tcOffset;
|
||||
}
|
||||
|
||||
return tmManager->sendTmPacket(ownerAsObject->getObjectId(),
|
||||
GeneratesHousekeepingIF::INTERFACE_ID,
|
||||
GeneratesHousekeepingIF::Functions::REPORT, set, tc, tcOffset);
|
||||
}
|
36
src/fsfw/housekeeping/HousekeepingHelper.h
Normal file
36
src/fsfw/housekeeping/HousekeepingHelper.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/returnvalue.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include <fsfw/tmtc/TmManager.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
#include "HousekeepingSet.h"
|
||||
|
||||
class HousekeepingHelper {
|
||||
friend class HousekeepingSet;
|
||||
|
||||
public:
|
||||
HousekeepingHelper(GeneratesHousekeepingIF* owner);
|
||||
~HousekeepingHelper() = default;
|
||||
|
||||
const HousekeepingSet* getHousekeepingSet(HousekeepingSetId_t id);
|
||||
|
||||
const std::map<HousekeepingSetId_t, HousekeepingSet*>* getHousekeepingSets() const {
|
||||
return &housekeepingSets;
|
||||
}
|
||||
|
||||
ReturnValue_t initialize();
|
||||
|
||||
protected:
|
||||
GeneratesHousekeepingIF* owner;
|
||||
TmManager* tmManager = nullptr;
|
||||
|
||||
void registerSet(HousekeepingSet* set);
|
||||
|
||||
ReturnValue_t reportHousekeeping(HousekeepingSet* set, const Action* action = nullptr);
|
||||
|
||||
private:
|
||||
std::map<HousekeepingSetId_t, HousekeepingSet*> housekeepingSets;
|
||||
};
|
146
src/fsfw/housekeeping/HousekeepingSet.cpp
Normal file
146
src/fsfw/housekeeping/HousekeepingSet.cpp
Normal file
|
@ -0,0 +1,146 @@
|
|||
#include "HousekeepingSet.h"
|
||||
|
||||
#include <fsfw/datapool/DatasetEntryIF.h>
|
||||
|
||||
#include "GeneratesHousekeepingIF.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
HousekeepingSet::HousekeepingSet(GeneratesHousekeepingIF* owner, const EnumIF &id) {
|
||||
if (owner != nullptr) {
|
||||
helper = owner->getHousekeepingHelper();
|
||||
helper->registerSet(this);
|
||||
}
|
||||
this->id = id.getValue();
|
||||
description = id.getDescription();
|
||||
}
|
||||
|
||||
const char* HousekeepingSet::getDescription() const { return description; }
|
||||
#else
|
||||
HousekeepingSet::HousekeepingSet(GeneratesHousekeepingIF* owner, HousekeepingSetId_t id) : id(id) {
|
||||
if (owner != nullptr) {
|
||||
helper = owner->getHousekeepingHelper();
|
||||
helper->registerSet(this);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
HousekeepingSet::~HousekeepingSet() {}
|
||||
|
||||
void HousekeepingSet::report(const Action* action) {
|
||||
if (helper != nullptr) {
|
||||
helper->reportHousekeeping(this, action);
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t HousekeepingSet::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 : parameterList) {
|
||||
result = parameter->serialize(buffer, size, maxSize, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Fill valid flags
|
||||
size_t index = 0;
|
||||
for (auto parameter : parameterList) {
|
||||
size_t byteIndex = index / 8;
|
||||
size_t bitIndex = index % 8;
|
||||
if (*size + byteIndex > maxSize) { // TODO audition me
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the parameter is a datasetParameter which knows its validity
|
||||
* If not, just set to valid
|
||||
*/
|
||||
DatasetEntryIF* dataSetParameter = dynamic_cast<DatasetEntryIF*>(parameter);
|
||||
if (dataSetParameter != nullptr) {
|
||||
if (dataSetParameter->getValid()) {
|
||||
(*buffer)[byteIndex] |= (1 << bitIndex);
|
||||
} else {
|
||||
(*buffer)[byteIndex] &= ~(1 << bitIndex);
|
||||
}
|
||||
} else {
|
||||
(*buffer)[byteIndex] |= (1 << bitIndex);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
*size += (parameterList.size() - 1) / 8 + 1;
|
||||
if (*size > maxSize) {
|
||||
// how did we end up here
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
*buffer += (parameterList.size() - 1) / 8 + 1;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
size_t HousekeepingSet::getSerializedSize() const {
|
||||
size_t size = SerializeAdapter::getSerializedSize(&id);
|
||||
for (auto parameter : parameterList) {
|
||||
size += parameter->getSerializedSize();
|
||||
}
|
||||
const size_t validBytes = (parameterList.size() - 1) / 8 + 1;
|
||||
size += validBytes;
|
||||
return size;
|
||||
}
|
||||
|
||||
ReturnValue_t HousekeepingSet::deSerialize(const uint8_t** buffer, size_t* size,
|
||||
Endianness streamEndianness) {
|
||||
ReturnValue_t result = returnvalue::OK;
|
||||
|
||||
/**
|
||||
* When deserializing, the id needs to be deserialized first, to find the correct class to
|
||||
* deserialize with. Consequentely, it is assumed, that the pointer was already advanced
|
||||
*
|
||||
* SerializeAdapter::deSerialize(&id, buffer, size, streamEndianness); if (result !=
|
||||
*/
|
||||
for (auto parameter : *getParameters()) {
|
||||
result = parameter->deSerialize(buffer, size, streamEndianness);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// read valid flags
|
||||
size_t index = 0;
|
||||
for (auto parameter : parameterList) {
|
||||
size_t byteIndex = index / 8;
|
||||
size_t bitIndex = index % 8;
|
||||
if (byteIndex > *size) { // TODO audition me
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* check if the parameter is a datasetParameter which knows its validity
|
||||
* If not, just set to valid
|
||||
*/
|
||||
DatasetEntryIF* dataSetParameter = dynamic_cast<DatasetEntryIF*>(parameter);
|
||||
if (dataSetParameter != nullptr) {
|
||||
bool valid = ((*buffer)[byteIndex] & (1 << bitIndex)) != 0;
|
||||
dataSetParameter->setValid(valid);
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
if (*size < (parameterList.size() - 1) / 8 + 1) {
|
||||
// how did we end up here
|
||||
return SerializeIF::BUFFER_TOO_SHORT;
|
||||
}
|
||||
*size -= (parameterList.size() - 1) / 8 + 1;
|
||||
*buffer += (parameterList.size() - 1) / 8 + 1;
|
||||
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
void HousekeepingSet::registerParameter(ParameterIF* parameter) {
|
||||
parameterList.push_back(parameter);
|
||||
}
|
||||
|
||||
std::vector<ParameterIF*> const* HousekeepingSet::getParameters() const { return ¶meterList; }
|
54
src/fsfw/housekeeping/HousekeepingSet.h
Normal file
54
src/fsfw/housekeeping/HousekeepingSet.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/action/Action.h>
|
||||
#include <fsfw/introspection/Enum.h>
|
||||
#include <fsfw/introspection/HasTmTcParametersIF.h>
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class HousekeepingHelper;
|
||||
class GeneratesHousekeepingIF;
|
||||
|
||||
using HousekeepingSetId_t = uint32_t;
|
||||
|
||||
class HousekeepingSet : public HasTmTcParametersIF, public SerializeIF {
|
||||
friend class ParameterIF;
|
||||
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
HousekeepingSet(GeneratesHousekeepingIF* owner, const EnumIF &id);
|
||||
#else
|
||||
HousekeepingSet(GeneratesHousekeepingIF* owner, HousekeepingSetId_t id);
|
||||
#endif
|
||||
|
||||
virtual ~HousekeepingSet();
|
||||
|
||||
HousekeepingSetId_t getId() const { return id; }
|
||||
|
||||
virtual void report(const Action* action = nullptr);
|
||||
|
||||
std::vector<ParameterIF*> const* getParameters() const override;
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
const char* getDescription() const;
|
||||
#endif
|
||||
|
||||
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;
|
||||
|
||||
protected:
|
||||
HousekeepingHelper* helper = nullptr;
|
||||
HousekeepingSetId_t id;
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
const char* description;
|
||||
#endif
|
||||
std::vector<ParameterIF*> parameterList;
|
||||
|
||||
void registerParameter(ParameterIF* parameter) override;
|
||||
};
|
|
@ -54,8 +54,8 @@ class HousekeepingSnapshot : public SerializeIF {
|
|||
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolObjectBase* dataSetPtr)
|
||||
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr){};
|
||||
|
||||
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
|
||||
Endianness streamEndianness) const {
|
||||
if (timeStamp != nullptr) {
|
||||
/* Endianness will always be MACHINE, so we can simply use memcpy
|
||||
here. */
|
||||
|
@ -70,15 +70,15 @@ class HousekeepingSnapshot : public SerializeIF {
|
|||
return updateData->serialize(buffer, size, maxSize, streamEndianness);
|
||||
}
|
||||
|
||||
virtual size_t getSerializedSize() const {
|
||||
size_t getSerializedSize() const {
|
||||
if (updateData == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
return timeStampSize + updateData->getSerializedSize();
|
||||
}
|
||||
|
||||
virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override {
|
||||
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
|
||||
SerializeIF::Endianness streamEndianness) override {
|
||||
if (*size < timeStampSize) {
|
||||
return SerializeIF::STREAM_TOO_SHORT;
|
||||
}
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
|
||||
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
|
||||
|
||||
#include <fsfw/datapoollocal/LocalPoolVariable.h>
|
||||
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
|
||||
#include <cstdint>
|
||||
#include <fsfw/objectmanager/SystemObjectIF.h>
|
||||
|
||||
enum errorPoolIds { TM_HITS, QUEUE_HITS, STORE_HITS };
|
||||
|
||||
class InternalErrorDataset : public StaticLocalDataSet<3 * sizeof(uint32_t)> {
|
||||
class InternalErrorDataset {
|
||||
public:
|
||||
static constexpr uint8_t ERROR_SET_ID = 0;
|
||||
|
||||
InternalErrorDataset(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, ERROR_SET_ID) {}
|
||||
InternalErrorDataset(void* owner) {}
|
||||
|
||||
InternalErrorDataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, ERROR_SET_ID)) {}
|
||||
InternalErrorDataset(object_id_t objectId) {}
|
||||
|
||||
lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(sid.objectId, TM_HITS, this);
|
||||
lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(sid.objectId, QUEUE_HITS, this);
|
||||
lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(sid.objectId, STORE_HITS, this);
|
||||
// lp_var_t<uint32_t> tmHits = lp_var_t<uint32_t>(sid.objectId, TM_HITS, this);
|
||||
// lp_var_t<uint32_t> queueHits = lp_var_t<uint32_t>(sid.objectId, QUEUE_HITS, this);
|
||||
// lp_var_t<uint32_t> storeHits = lp_var_t<uint32_t>(sid.objectId, STORE_HITS, this);
|
||||
};
|
||||
|
||||
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */
|
||||
|
|
|
@ -1,22 +1,17 @@
|
|||
#include "fsfw/internalerror/InternalErrorReporter.h"
|
||||
|
||||
#include "fsfw/datapool/PoolReadGuard.h"
|
||||
#include "fsfw/ipc/MutexFactory.h"
|
||||
#include "fsfw/ipc/QueueFactory.h"
|
||||
#include "fsfw/serviceinterface/ServiceInterface.h"
|
||||
|
||||
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth)
|
||||
: SystemObject(setObjectId),
|
||||
poolManager(this, commandQueue),
|
||||
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
|
||||
internalErrorDataset(this) {
|
||||
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
|
||||
mutex = MutexFactory::instance()->createMutex();
|
||||
}
|
||||
|
||||
InternalErrorReporter::~InternalErrorReporter() {
|
||||
MutexFactory::instance()->deleteMutex(mutex);
|
||||
QueueFactory::instance()->deleteMessageQueue(commandQueue);
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
||||
|
@ -24,12 +19,6 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
|
|||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
||||
CommandMessage message;
|
||||
ReturnValue_t result = commandQueue->receiveMessage(&message);
|
||||
if (result != MessageQueueIF::EMPTY) {
|
||||
poolManager.handleHousekeepingMessage(&message);
|
||||
}
|
||||
|
||||
uint32_t newQueueHits = getAndResetQueueHits();
|
||||
uint32_t newTmHits = getAndResetTmHits();
|
||||
uint32_t newStoreHits = getAndResetStoreHits();
|
||||
|
@ -53,20 +42,19 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
|
|||
}
|
||||
#endif
|
||||
|
||||
{
|
||||
PoolReadGuard readGuard(&internalErrorDataset);
|
||||
if (readGuard.getReadResult() == returnvalue::OK) {
|
||||
internalErrorDataset.queueHits.value += newQueueHits;
|
||||
internalErrorDataset.storeHits.value += newStoreHits;
|
||||
internalErrorDataset.tmHits.value += newTmHits;
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
|
||||
internalErrorDataset.setChanged(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
// {
|
||||
// PoolReadGuard readGuard(&internalErrorDataset);
|
||||
// if (readGuard.getReadResult() == returnvalue::OK) {
|
||||
// internalErrorDataset.queueHits.value += newQueueHits;
|
||||
// internalErrorDataset.storeHits.value += newStoreHits;
|
||||
// internalErrorDataset.tmHits.value += newTmHits;
|
||||
// internalErrorDataset.setValidity(true, true);
|
||||
// if ((newQueueHits != 0) or (newStoreHits != 0) or (newTmHits != 0)) {
|
||||
// internalErrorDataset.setChanged(true);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
poolManager.performHkOperation();
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
|
@ -123,47 +111,15 @@ void InternalErrorReporter::incrementStoreHits() {
|
|||
|
||||
object_id_t InternalErrorReporter::getObjectId() const { return SystemObject::getObjectId(); }
|
||||
|
||||
MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
|
||||
return this->commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
|
||||
LocalDataPoolManager &poolManager) {
|
||||
localDataPoolMap.emplace(errorPoolIds::TM_HITS, &tmHitsEntry);
|
||||
localDataPoolMap.emplace(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
|
||||
localDataPoolMap.emplace(errorPoolIds::STORE_HITS, &storeHitsEntry);
|
||||
poolManager.subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams(
|
||||
internalErrorSid, false,
|
||||
static_cast<float>(getPeriodicOperationFrequency()) / static_cast<float>(1000.0)));
|
||||
internalErrorDataset.setValidity(true, true);
|
||||
return returnvalue::OK;
|
||||
}
|
||||
|
||||
dur_millis_t InternalErrorReporter::getPeriodicOperationFrequency() const {
|
||||
return this->executingTask->getPeriodMs();
|
||||
}
|
||||
|
||||
LocalPoolDataSetBase *InternalErrorReporter::getDataSetHandle(sid_t sid) {
|
||||
return &internalErrorDataset;
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setTaskIF(PeriodicTaskIF *task) { this->executingTask = task; }
|
||||
// MessageQueueId_t InternalErrorReporter::getCommandQueue() const {
|
||||
// return this->commandQueue->getId();
|
||||
// }
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initialize() {
|
||||
ReturnValue_t result = poolManager.initialize(commandQueue);
|
||||
if (result != returnvalue::OK) {
|
||||
return result;
|
||||
}
|
||||
return SystemObject::initialize();
|
||||
}
|
||||
|
||||
ReturnValue_t InternalErrorReporter::initializeAfterTaskCreation() {
|
||||
return poolManager.initializeAfterTaskCreation();
|
||||
}
|
||||
|
||||
void InternalErrorReporter::setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
|
||||
this->timeoutType = timeoutType;
|
||||
this->timeoutMs = timeoutMs;
|
||||
}
|
||||
|
||||
LocalDataPoolManager *InternalErrorReporter::getHkManagerHandle() { return &poolManager; }
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
|
||||
|
||||
#include "InternalErrorReporterIF.h"
|
||||
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
// #include "fsfw/datapoollocal/LocalDataPoolManager.h"
|
||||
#include "fsfw/internalerror/InternalErrorDataset.h"
|
||||
#include "fsfw/ipc/MutexIF.h"
|
||||
#include "fsfw/objectmanager/SystemObject.h"
|
||||
|
@ -18,8 +18,7 @@
|
|||
*/
|
||||
class InternalErrorReporter : public SystemObject,
|
||||
public ExecutableObjectIF,
|
||||
public InternalErrorReporterIF,
|
||||
public HasLocalDataPoolIF {
|
||||
public InternalErrorReporterIF {
|
||||
public:
|
||||
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth = 5);
|
||||
|
||||
|
@ -35,15 +34,10 @@ class InternalErrorReporter : public SystemObject,
|
|||
virtual ~InternalErrorReporter();
|
||||
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
|
||||
LocalDataPoolManager& poolManager) override;
|
||||
virtual dur_millis_t getPeriodicOperationFrequency() const override;
|
||||
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
|
||||
LocalDataPoolManager* getHkManagerHandle() override;
|
||||
//virtual MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
virtual ReturnValue_t initialize() override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
//virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
|
||||
virtual void queueMessageNotSent() override;
|
||||
|
@ -52,19 +46,13 @@ class InternalErrorReporter : public SystemObject,
|
|||
|
||||
virtual void storeFull() override;
|
||||
|
||||
virtual void setTaskIF(PeriodicTaskIF* task) override;
|
||||
|
||||
protected:
|
||||
MessageQueueIF* commandQueue;
|
||||
LocalDataPoolManager poolManager;
|
||||
|
||||
PeriodicTaskIF* executingTask = nullptr;
|
||||
// MessageQueueIF* commandQueue;
|
||||
|
||||
MutexIF* mutex = nullptr;
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
|
||||
uint32_t timeoutMs = 20;
|
||||
|
||||
sid_t internalErrorSid;
|
||||
InternalErrorDataset internalErrorDataset;
|
||||
|
||||
bool diagnosticPrintout = true;
|
||||
|
@ -72,9 +60,6 @@ class InternalErrorReporter : public SystemObject,
|
|||
uint32_t queueHits = 0;
|
||||
uint32_t tmHits = 0;
|
||||
uint32_t storeHits = 0;
|
||||
PoolEntry<uint32_t> tmHitsEntry = PoolEntry<uint32_t>();
|
||||
PoolEntry<uint32_t> storeHitsEntry = PoolEntry<uint32_t>();
|
||||
PoolEntry<uint32_t> queueHitsEntry = PoolEntry<uint32_t>();
|
||||
|
||||
uint32_t getAndResetQueueHits();
|
||||
void incrementQueueHits();
|
||||
|
|
1
src/fsfw/introspection/CMakeLists.txt
Normal file
1
src/fsfw/introspection/CMakeLists.txt
Normal file
|
@ -0,0 +1 @@
|
|||
target_sources(${LIB_FSFW_NAME} PRIVATE ParameterTypeSelector.cpp)
|
48
src/fsfw/introspection/ClasslessEnum.h
Normal file
48
src/fsfw/introspection/ClasslessEnum.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/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
|
64
src/fsfw/introspection/Enum.h
Normal file
64
src/fsfw/introspection/Enum.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/returnvalues/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
|
62
src/fsfw/introspection/EnumCommon.h
Normal file
62
src/fsfw/introspection/EnumCommon.h
Normal file
|
@ -0,0 +1,62 @@
|
|||
#define CLEAN_ENUM_ITEM(r, data, element) \
|
||||
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), \
|
||||
(BOOST_PP_TUPLE_ELEM(0, element) = BOOST_PP_TUPLE_ELEM(1, element)), \
|
||||
(BOOST_PP_TUPLE_ELEM(0, element)))
|
||||
|
||||
#if defined FSFW_ENUM_VALUE_CHECKS || defined FSFW_INTROSPECTION
|
||||
|
||||
|
||||
#define GET_KEY(r, data, element) (BOOST_PP_TUPLE_ELEM(0, element))
|
||||
#define GET_DESCRIPTION(r, data, element) \
|
||||
BOOST_PP_IF(BOOST_PP_SUB(BOOST_PP_TUPLE_SIZE(element), 2), (BOOST_PP_TUPLE_ELEM(2, element)), \
|
||||
(BOOST_PP_TUPLE_ELEM(1, element)))
|
||||
|
||||
#define CREATE_KEY_ARRAY(enum_elements, type) \
|
||||
/*was static constexpr, but clang won't compile that*/ \
|
||||
int64_t elements[BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))] = { \
|
||||
BOOST_PP_SEQ_ENUM(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements))}; \
|
||||
const int64_t *getElements() const override { return elements; } \
|
||||
size_t getSize() const override { \
|
||||
return BOOST_PP_SEQ_SIZE(BOOST_PP_SEQ_FOR_EACH(GET_KEY, "", enum_elements)); \
|
||||
}
|
||||
#define VALUE_CHECK(type) \
|
||||
bool isValueValid() 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
|
16
src/fsfw/introspection/EnumIF.h
Normal file
16
src/fsfw/introspection/EnumIF.h
Normal file
|
@ -0,0 +1,16 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
|
||||
class EnumIF {
|
||||
public:
|
||||
virtual ~EnumIF() {}
|
||||
virtual int64_t getValue() const = 0;
|
||||
virtual bool isValueValid() 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;
|
||||
};
|
13
src/fsfw/introspection/HasTmTcParametersIF.h
Normal file
13
src/fsfw/introspection/HasTmTcParametersIF.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "ParameterIF.h"
|
||||
|
||||
class HasTmTcParametersIF {
|
||||
public:
|
||||
virtual ~HasTmTcParametersIF() = default;
|
||||
|
||||
virtual void registerParameter(ParameterIF *parameter) = 0;
|
||||
virtual std::vector<ParameterIF *> const *getParameters() const = 0;
|
||||
};
|
40
src/fsfw/introspection/MinMaxParameter.h
Normal file
40
src/fsfw/introspection/MinMaxParameter.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
#pragma once
|
||||
|
||||
#include "Parameter.h"
|
||||
|
||||
template <typename T>
|
||||
class MinMaxParameter : public Parameter<T> {
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
private:
|
||||
MinMaxParameter(Action *owner, const char *name, T min, T max)
|
||||
: Parameter<T>(owner, name), min(min), max(max) {}
|
||||
|
||||
public:
|
||||
static MinMaxParameter createMinMaxParameter(Action *owner, const char *name, T min, T max) {
|
||||
return MinMaxParameter(owner, name, min, max);
|
||||
}
|
||||
virtual double getMinFloating() override { return static_cast<double>(min); }
|
||||
virtual int64_t getMinSigned() override { return static_cast<int64_t>(min); }
|
||||
|
||||
virtual double getMaxFloating() override { return static_cast<double>(max); }
|
||||
virtual int64_t getMaxSigned() override { return static_cast<int64_t>(max); }
|
||||
|
||||
#else
|
||||
private:
|
||||
MinMaxParameter(Action *owner, T min, T max) : Parameter<T>(owner), min(min), max(max) {}
|
||||
|
||||
public:
|
||||
static MinMaxParameter createMinMaxParameter(Action *owner, T min, T max) {
|
||||
return MinMaxParameter(owner, min, max);
|
||||
}
|
||||
#endif
|
||||
private:
|
||||
T min;
|
||||
T max;
|
||||
};
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p2, p3, p4)
|
||||
#else
|
||||
#define createMinMaxParameter(p1, p2, p3, p4) createMinMaxParameter(p1, p3, p4)
|
||||
#endif
|
117
src/fsfw/introspection/Parameter.h
Normal file
117
src/fsfw/introspection/Parameter.h
Normal file
|
@ -0,0 +1,117 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/introspection/Types.h>
|
||||
#include <fsfw/introspection/TypesHelper.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "HasTmTcParametersIF.h"
|
||||
#include "ParameterIF.h"
|
||||
// TODO: ifdef introspection stuff
|
||||
|
||||
template <typename T>
|
||||
class Parameter : public ParameterIF {
|
||||
protected:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
Parameter(HasTmTcParametersIF *owner, const char *name)
|
||||
: name(name)
|
||||
#else
|
||||
Parameter(HasTmTcParametersIF *owner)
|
||||
#endif
|
||||
{
|
||||
owner->registerParameter(this);
|
||||
}
|
||||
|
||||
public:
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
static Parameter createParameter(HasTmTcParametersIF *owner, const char *name) {
|
||||
return Parameter(owner, name);
|
||||
}
|
||||
#else
|
||||
static Parameter createParameter(HasTmTcParametersIF *owner) { return Parameter(owner); }
|
||||
#endif
|
||||
|
||||
bool isValueValid() override {
|
||||
return enumHelper<std::is_base_of<EnumIF, T>::value>::isValueValid(&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 {
|
||||
ReturnValue_t result = SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
|
||||
return result;
|
||||
}
|
||||
|
||||
#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
|
45
src/fsfw/introspection/ParameterIF.h
Normal file
45
src/fsfw/introspection/ParameterIF.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
#include <fsfw/serialize/SerializeIF.h>
|
||||
#include <fsfw/introspection/Types.h>
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
#include <vector>
|
||||
#endif
|
||||
|
||||
class ParameterIF : public SerializeIF {
|
||||
public:
|
||||
virtual bool isValueValid() = 0; //TODO change name to resolve confusion with valid flag
|
||||
#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
|
||||
};
|
56
src/fsfw/introspection/ParameterTypeSelector.cpp
Normal file
56
src/fsfw/introspection/ParameterTypeSelector.cpp
Normal file
|
@ -0,0 +1,56 @@
|
|||
#include "ParameterTypeSelector.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
template <typename T>
|
||||
Types::ParameterType ParameterTypeSelector::getType() {
|
||||
return Types::UNSUPPORTED;
|
||||
}
|
||||
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint8_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int8_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint16_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int16_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<uint32_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int32_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
// template <>
|
||||
// Types::ParameterType ParameterTypeSelector::getType<uint64_t>() {
|
||||
// return Types::UNSIGNED;
|
||||
// }
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<int64_t>() {
|
||||
return Types::SIGNED;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<float>() {
|
||||
return Types::FLOATING;
|
||||
}
|
||||
template <>
|
||||
Types::ParameterType ParameterTypeSelector::getType<double>() {
|
||||
return Types::FLOATING;
|
||||
}
|
||||
|
||||
#endif
|
13
src/fsfw/introspection/ParameterTypeSelector.h
Normal file
13
src/fsfw/introspection/ParameterTypeSelector.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef FSFW_INTROSPECTION
|
||||
|
||||
class ParameterTypeSelector {
|
||||
public:
|
||||
template <typename T>
|
||||
static Types::ParameterType getType();
|
||||
};
|
||||
|
||||
#endif
|
9
src/fsfw/introspection/Types.h
Normal file
9
src/fsfw/introspection/Types.h
Normal file
|
@ -0,0 +1,9 @@
|
|||
#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
|
||||
// Floating is IEEE double
|
||||
namespace Types {
|
||||
enum ParameterType { SIGNED, FLOATING, ENUM, UNSUPPORTED };
|
||||
} // namespace Types
|
74
src/fsfw/introspection/TypesHelper.h
Normal file
74
src/fsfw/introspection/TypesHelper.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
|
||||
#include "Enum.h"
|
||||
#include "Types.h"
|
||||
#include "ParameterTypeSelector.h"
|
||||
|
||||
template <bool>
|
||||
class enumHelper;
|
||||
|
||||
template <>
|
||||
class enumHelper<true> {
|
||||
public:
|
||||
static bool isValueValid(EnumIF *anEnum) { return anEnum->isValueValid(); }
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
//TODO needed?: 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 isValueValid(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
|
||||
};
|
|
@ -3,7 +3,7 @@
|
|||
#include "fsfw/devicehandlers/DeviceHandlerMessage.h"
|
||||
#include "fsfw/filesystem/GenericFileSystemMessage.h"
|
||||
#include "fsfw/health/HealthMessage.h"
|
||||
#include "fsfw/housekeeping/HousekeepingMessage.h"
|
||||
// #include "fsfw/housekeeping/HousekeepingMessage.h"
|
||||
#include "fsfw/memory/MemoryMessage.h"
|
||||
#include "fsfw/modes/ModeMessage.h"
|
||||
#include "fsfw/monitoring/MonitoringMessage.h"
|
||||
|
@ -33,9 +33,9 @@ void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
|
|||
case messagetypes::MEMORY:
|
||||
MemoryMessage::clear(message);
|
||||
break;
|
||||
case messagetypes::MONITORING:
|
||||
MonitoringMessage::clear(message);
|
||||
break;
|
||||
// case messagetypes::MONITORING: //TODO
|
||||
// MonitoringMessage::clear(message);
|
||||
// break;
|
||||
#ifdef FSFW_ADD_TMSTORAGE
|
||||
case messagetypes::TM_STORE:
|
||||
TmStoreMessage::clear(message);
|
||||
|
@ -44,9 +44,9 @@ void CommandMessageCleaner::clearCommandMessage(CommandMessage* message) {
|
|||
case messagetypes::PARAMETER:
|
||||
ParameterMessage::clear(message);
|
||||
break;
|
||||
case messagetypes::HOUSEKEEPING:
|
||||
HousekeepingMessage::clear(message);
|
||||
break;
|
||||
// case messagetypes::HOUSEKEEPING:
|
||||
// HousekeepingMessage::clear(message);
|
||||
// break;
|
||||
case messagetypes::FILE_SYSTEM_MESSAGE:
|
||||
GenericFileSystemMessage::clear(message);
|
||||
break;
|
||||
|
|
|
@ -17,6 +17,7 @@ enum FsfwMessageTypes {
|
|||
PARAMETER,
|
||||
FILE_SYSTEM_MESSAGE,
|
||||
HOUSEKEEPING,
|
||||
TELEMETRY,
|
||||
|
||||
FW_MESSAGES_COUNT,
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
@ -44,10 +46,14 @@ class HasModesIF {
|
|||
//!< interpreted
|
||||
static const Mode_t MODE_OFF = 0; //!< The device is powered off. The only command accepted in
|
||||
//!< this mode is a mode change to on.
|
||||
static const Submode_t SUBMODE_NONE = 0; //!< To avoid checks against magic number "0".
|
||||
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; //TODO do not think this is a good idea
|
||||
virtual void getMode(Mode_t *mode, Submode_t *submode) = 0;
|
||||
|
||||
protected:
|
||||
|
|
33
src/fsfw/modes/ModeDefinitionHelper.h
Normal file
33
src/fsfw/modes/ModeDefinitionHelper.h
Normal 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
|
||||
};
|
|
@ -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) ==
|
||||
// returnvalue::OK) {
|
||||
// submodeVector.push_back(std::pair<Submode_t, const char *>(submode->getElements()[i],
|
||||
// submode->getDescriptions()[i]));
|
||||
// }
|
||||
// }
|
||||
// modeDefinitionHelper.free();
|
||||
return submodeVector;
|
||||
}
|
||||
#endif
|
|
@ -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;
|
||||
|
|
|
@ -32,9 +32,9 @@ class AbsLimitMonitor : public MonitorBase<T> {
|
|||
return returnvalue::OK; // We're not out of range.
|
||||
}
|
||||
|
||||
virtual ReturnValue_t getParameter(uint8_t domainId, uint16_t parameterId,
|
||||
ParameterWrapper *parameterWrapper,
|
||||
const ParameterWrapper *newValues, uint16_t startAtIndex) {
|
||||
ReturnValue_t getParameter(uint8_t domainId, uint8_t parameterId,
|
||||
ParameterWrapper *parameterWrapper, const ParameterWrapper *newValues,
|
||||
uint16_t startAtIndex) override {
|
||||
ReturnValue_t result = this->MonitorBase<T>::getParameter(
|
||||
domainId, parameterId, parameterWrapper, newValues, startAtIndex);
|
||||
// We'll reuse the DOMAIN_ID of MonitorReporter,
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef FSFW_MONITORING_MONITORBASE_H_
|
||||
#define FSFW_MONITORING_MONITORBASE_H_
|
||||
|
||||
#include "../datapoollocal/LocalPoolVariable.h"
|
||||
#include "LimitViolationReporter.h"
|
||||
#include "MonitorReporter.h"
|
||||
#include "MonitoringIF.h"
|
||||
|
@ -22,7 +21,7 @@
|
|||
template <typename T>
|
||||
class MonitorBase : public MonitorReporter<T> {
|
||||
public:
|
||||
MonitorBase(object_id_t reporterId, uint8_t monitorId, gp_id_t globalPoolId,
|
||||
MonitorBase(object_id_t reporterId, uint8_t monitorId, /*gp_id_t globalPoolId TODO*/,
|
||||
uint16_t confirmationLimit)
|
||||
: MonitorReporter<T>(reporterId, monitorId, globalPoolId, confirmationLimit),
|
||||
poolVariable(globalPoolId) {}
|
||||
|
|
|
@ -13,6 +13,7 @@ class MonitoringMessage : public CommandMessage {
|
|||
static const Command_t LIMIT_VIOLATION_REPORT = MAKE_COMMAND_ID(10);
|
||||
virtual ~MonitoringMessage();
|
||||
static void setLimitViolationReport(CommandMessage* message, store_address_t storeId);
|
||||
using CommandMessage::clear;
|
||||
static void clear(CommandMessage* message);
|
||||
static store_address_t getStoreId(const CommandMessage* message);
|
||||
static void setTypicalMessage(CommandMessage* message, Command_t type, store_address_t storeId);
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
|
||||
#include "AccessLocalPoolF.h"
|
||||
#include "ProvidesDataPoolSubscriptionIF.h"
|
||||
#include "fsfw/datapool/DataSetIF.h"
|
||||
#include "fsfw/datapool/PoolEntry.h"
|
||||
#include "fsfw/datapoollocal/DataSetIF.h"
|
||||
#include "fsfw/datapoollocal/PoolEntry.h"
|
||||
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
|
||||
#include "fsfw/housekeeping/HousekeepingMessage.h"
|
||||
#include "fsfw/housekeeping/HousekeepingPacketDownlink.h"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user