Refactor and clean up HK and Local Pool Modules

This commit is contained in:
Robin Müller 2024-11-15 10:56:43 +01:00
parent 21d5800bfa
commit bb95797073
206 changed files with 3530 additions and 4961 deletions

View File

@ -34,6 +34,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## Changed
- Complete refactoring of HK subsystem. Replaced local data pool manager by periodic HK
helper. The shared pool and the periodic HK generation are now distinct concepts.
- Improved File System Abstraction to be more in line with normal filesystems.
- CFDP implementation was improved, has now even less dependencies on other FSFW components
and allows one inserted packet per state machine call.

View File

@ -8,7 +8,8 @@ GyroHandlerL3GD20H::GyroHandlerL3GD20H(object_id_t objectId, object_id_t deviceC
CookieIF *comCookie, uint32_t transitionDelayMs)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
transitionDelayMs(transitionDelayMs),
dataset(this) {}
sharedPool(DeviceHandlerBase::getObjectId()),
dataset(sharedPool) {}
GyroHandlerL3GD20H::~GyroHandlerL3GD20H() {}
@ -210,27 +211,27 @@ ReturnValue_t GyroHandlerL3GD20H::interpretDeviceReply(DeviceCommandId_t id,
if (readSet.getReadResult() == returnvalue::OK) {
if (std::abs(angVelocX) < this->absLimitX) {
dataset.angVelocX = angVelocX;
dataset.angVelocX.setValid(true);
// dataset.angVelocX.setValid(true);
} else {
dataset.angVelocX.setValid(false);
// dataset.angVelocX.setValid(false);
}
if (std::abs(angVelocY) < this->absLimitY) {
dataset.angVelocY = angVelocY;
dataset.angVelocY.setValid(true);
// dataset.angVelocY.setValid(true);
} else {
dataset.angVelocY.setValid(false);
// dataset.angVelocY.setValid(false);
}
if (std::abs(angVelocZ) < this->absLimitZ) {
dataset.angVelocZ = angVelocZ;
dataset.angVelocZ.setValid(true);
// dataset.angVelocZ.setValid(true);
} else {
dataset.angVelocZ.setValid(false);
// dataset.angVelocZ.setValid(false);
}
dataset.temperature = temperature;
dataset.temperature.setValid(true);
// dataset.temperature.setValid(true);
}
break;
}
@ -246,16 +247,19 @@ uint32_t GyroHandlerL3GD20H::getTransitionDelayMs(Mode_t from, Mode_t to) {
void GyroHandlerL3GD20H::setToGoToNormalMode(bool enable) { this->goNormalModeImmediately = true; }
// TODO
/*
ReturnValue_t GyroHandlerL3GD20H::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
PeriodicHkGenerationHelper &hkGenHelper) {
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_X, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Y, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::ANG_VELOC_Z, new PoolEntry<float>({0.0}));
localDataPoolMap.emplace(l3gd20h::TEMPERATURE, new PoolEntry<float>({0.0}));
poolManager.subscribeForRegularPeriodicPacket(
hkGenHelper.enableRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(dataset.getSid(), false, 10.0));
return returnvalue::OK;
}
*/
void GyroHandlerL3GD20H::fillCommandAndReplyMap() {
insertInCommandAndReplyMap(l3gd20h::READ_REGS, 1, &dataset);

View File

@ -1,9 +1,9 @@
#ifndef MISSION_DEVICES_GYROL3GD20HANDLER_H_
#define MISSION_DEVICES_GYROL3GD20HANDLER_H_
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <fsfw/globalfunctions/PeriodicOperationDivider.h>
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
#include "gyroL3gHelpers.h"
/**
* @brief Device Handler for the L3GD20H gyroscope sensor
@ -51,11 +51,12 @@ class GyroHandlerL3GD20H : public DeviceHandlerBase {
void fillCommandAndReplyMap() override;
void modeChanged() override;
virtual uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
// ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
// PeriodicHkGenerationHelper &hkGenHelper) override;
private:
uint32_t transitionDelayMs = 0;
localpool::SharedPool sharedPool;
GyroPrimaryDataset dataset;
float absLimitX = l3gd20h::RANGE_DPS_00;

View File

@ -0,0 +1,13 @@
#include "HasLocalDpIFManagerAttorney.h"
#include "fsfw/datapool/LocalPoolObjectBase.h"
#include "fsfw/housekeeping/GeneratesPeriodicHkIF.h"
LocalPoolObjectBase* HasLocalDpIFManagerAttorney::getPoolObjectHandle(
PeriodicHkGenerationIF* clientIF, dp::lp_id_t localPoolId) {
return clientIF->getPoolObjectHandle(localPoolId);
}
object_id_t HasLocalDpIFManagerAttorney::getObjectId(PeriodicHkGenerationIF* clientIF) {
return clientIF->getObjectId();
}

View File

@ -0,0 +1,17 @@
#pragma once
#include <fsfw/housekeeping/PeriodicHkHelper.h>
#include "fsfw/datapool/definitions.h"
class PeriodicHkGenerationIF;
class LocalPoolDataSetBase;
class LocalPoolObjectBase;
class HasLocalDpIFManagerAttorney {
static LocalPoolObjectBase* getPoolObjectHandle(PeriodicHkGenerationIF* clientIF,
dp::id_t localPoolId);
static object_id_t getObjectId(PeriodicHkGenerationIF* clientIF);
friend class hk::PeriodicHelper;
};

View File

@ -0,0 +1 @@
#include "HasLocalDpIFUserAttorney.h"

View File

@ -1,12 +1,12 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDPIFUSERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDPIFUSERATTORNEY_H_
class HasLocalDataPoolIF;
class PeriodicHkGenerationIF;
class AccessPoolManagerIF;
class HasLocalDpIFUserAttorney {
private:
static AccessPoolManagerIF* getAccessorHandle(HasLocalDataPoolIF* clientIF);
// static AccessPoolManagerIF* getAccessorHandle(PeriodicHkGenerationIF* clientIF);
friend class LocalPoolObjectBase;
friend class LocalPoolDataSetBase;

View File

@ -273,7 +273,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
if (readHelper.getReadResult() == returnvalue::OK) {
if (std::abs(mgmX) > absLimitX or std::abs(mgmY) > absLimitY or
std::abs(mgmZ) > absLimitZ) {
dataset.fieldStrengths.setValid(false);
dataset.setIsValid = false;
}
if (std::abs(mgmX) < absLimitX) {
dataset.fieldStrengths[0] = mgmX;
@ -286,7 +286,7 @@ ReturnValue_t MgmLIS3MDLHandler::interpretDeviceReply(DeviceCommandId_t id, cons
if (std::abs(mgmZ) < absLimitZ) {
dataset.fieldStrengths[2] = mgmZ;
}
dataset.fieldStrengths.setValid(true);
dataset.setIsValid = true;
}
break;
}
@ -415,13 +415,15 @@ uint32_t MgmLIS3MDLHandler::getTransitionDelayMs(Mode_t from, Mode_t to) { retur
void MgmLIS3MDLHandler::modeChanged(void) { internalState = InternalState::STATE_NONE; }
/*
ReturnValue_t MgmLIS3MDLHandler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
PeriodicHkGenerationHelper &poolManager) {
localDataPoolMap.emplace(mgmLis3::FIELD_STRENGTHS, &mgmXYZ);
localDataPoolMap.emplace(mgmLis3::TEMPERATURE_CELCIUS, &temperature);
poolManager.subscribeForRegularPeriodicPacket({dataset.getSid(), false, 10.0});
poolManager.setPeriodicFrequency(dataset.getSid(), 10'000);
return returnvalue::OK;
}
*/
void MgmLIS3MDLHandler::setAbsoluteLimits(float xLimit, float yLimit, float zLimit) {
this->absLimitX = xLimit;

View File

@ -1,7 +1,7 @@
#ifndef MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#define MISSION_DEVICES_MGMLIS3MDLHANDLER_H_
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmLis3Helpers.h>
#include "mgmLis3Helpers.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
@ -63,8 +63,8 @@ class MgmLIS3MDLHandler : public DeviceHandlerBase {
virtual ReturnValue_t interpretDeviceReply(DeviceCommandId_t id, const uint8_t *packet) override;
void fillCommandAndReplyMap() override;
void modeChanged(void) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
// ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
// PeriodicHkGenerationHelper &poolManager) override;
private:
mgmLis3::MgmPrimaryDataset dataset;

View File

@ -9,7 +9,7 @@
MgmRM3100Handler::MgmRM3100Handler(object_id_t objectId, object_id_t deviceCommunication,
CookieIF *comCookie, uint32_t transitionDelay)
: DeviceHandlerBase(objectId, deviceCommunication, comCookie),
primaryDataset(this),
primaryDataset(sharedPool),
transitionDelay(transitionDelay) {}
MgmRM3100Handler::~MgmRM3100Handler() {}
@ -307,12 +307,15 @@ void MgmRM3100Handler::fillCommandAndReplyMap() {
void MgmRM3100Handler::modeChanged() { internalState = InternalState::NONE; }
// TODO: Fix
/*
ReturnValue_t MgmRM3100Handler::initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) {
PeriodicHkGenerationHelper &poolManager) {
localDataPoolMap.emplace(mgmRm3100::FIELD_STRENGTHS, &mgmXYZ);
poolManager.subscribeForRegularPeriodicPacket({primaryDataset.getSid(), false, 10.0});
poolManager.setPeriodicFrequency(primaryDataset.getSid(), 10'000);
return returnvalue::OK;
}
*/
uint32_t MgmRM3100Handler::getTransitionDelayMs(Mode_t from, Mode_t to) {
return this->transitionDelay;
@ -356,7 +359,7 @@ ReturnValue_t MgmRM3100Handler::handleDataReadout(const uint8_t *packet) {
primaryDataset.fieldStrengths[0] = fieldStrengthX;
primaryDataset.fieldStrengths[1] = fieldStrengthY;
primaryDataset.fieldStrengths[2] = fieldStrengthZ;
primaryDataset.setValidity(true, true);
primaryDataset.valid = true;
}
return returnvalue::OK;
}

View File

@ -1,7 +1,7 @@
#ifndef MISSION_DEVICES_MGMRM3100HANDLER_H_
#define MISSION_DEVICES_MGMRM3100HANDLER_H_
#include <fsfw_hal/devicehandlers/devicedefinitions/mgmRm3100Helpers.h>
#include "mgmRm3100Helpers.h"
#include "fsfw/devicehandlers/DeviceHandlerBase.h"
#include "fsfw/globalfunctions/PeriodicOperationDivider.h"
@ -52,8 +52,8 @@ class MgmRM3100Handler : public DeviceHandlerBase {
void fillCommandAndReplyMap() override;
void modeChanged(void) override;
virtual uint32_t getTransitionDelayMs(Mode_t from, Mode_t to) override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
// ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
// PeriodicHkGenerationHelper &poolManager) override;
private:
enum class InternalState {

View File

@ -0,0 +1,46 @@
#ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#include <fsfw/timemanager/clockDefinitions.h>
#include <optional>
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "localPoolDefinitions.h"
namespace subdp {
struct ParamsBase {
ParamsBase(sid_t sid, bool enableReporting, dur_millis_t collectionIntervalMs)
: sid(sid), enableReporting(enableReporting), collectionIntervalMs(collectionIntervalMs) {}
[[nodiscard]] bool isDiagnostics() const { return diagnostics; }
sid_t sid;
bool enableReporting;
dur_millis_t collectionIntervalMs;
MessageQueueId_t receiver = MessageQueueIF::NO_QUEUE;
protected:
bool diagnostics;
};
struct RegularHkPeriodicParams : public ParamsBase {
RegularHkPeriodicParams(sid_t sid, bool enableReporting, dur_millis_t collectionIntervalMs)
: ParamsBase(sid, enableReporting, collectionIntervalMs) {}
};
struct RegularHkUpdateParams : public ParamsBase {
RegularHkUpdateParams(sid_t sid, bool enableReporting) : ParamsBase(sid, enableReporting, 0) {}
};
struct DiagnosticsHkUpdateParams : public ParamsBase {
DiagnosticsHkUpdateParams(sid_t sid, bool enableReporting)
: ParamsBase(sid, enableReporting, 0) {}
};
} // namespace subdp
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */

View File

@ -1,21 +1,23 @@
#include "fsfw/datapoollocal/SharedLocalDataSet.h"
#include "fsfw/datapool/SharedLocalDataset.h"
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid, const size_t maxSize)
: SystemObject(objectId), LocalPoolDataSetBase(sid, nullptr, maxSize), poolVarVector(maxSize) {
SharedLocalDataset::SharedLocalDataset(object_id_t objectId, structure_id_t sid, const size_t maxSize)
: SystemObject(objectId), SharedDatasetBase(sid, nullptr, maxSize), poolVarVector(maxSize) {
this->setContainer(poolVarVector.data());
datasetLock = MutexFactory::instance()->createMutex();
}
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, HasLocalDataPoolIF *owner,
SharedLocalDataset::SharedLocalDataset(object_id_t objectId, localpool::SharedPool& sharedPool,
uint32_t setId, const size_t maxSize)
: SystemObject(objectId),
LocalPoolDataSetBase(owner, setId, nullptr, maxSize),
SharedDatasetBase(sharedPool, setId, nullptr, maxSize),
poolVarVector(maxSize) {
this->setContainer(poolVarVector.data());
datasetLock = MutexFactory::instance()->createMutex();
}
ReturnValue_t SharedLocalDataSet::lockDataset(MutexIF::TimeoutType timeoutType,
SharedLocalDataset::~SharedLocalDataset() { MutexFactory::instance()->deleteMutex(datasetLock); }
ReturnValue_t SharedLocalDataset::lockDataset(MutexIF::TimeoutType timeoutType,
dur_millis_t mutexTimeout) {
if (datasetLock != nullptr) {
return datasetLock->lockMutex(timeoutType, mutexTimeout);
@ -23,9 +25,7 @@ ReturnValue_t SharedLocalDataSet::lockDataset(MutexIF::TimeoutType timeoutType,
return returnvalue::FAILED;
}
SharedLocalDataSet::~SharedLocalDataSet() { MutexFactory::instance()->deleteMutex(datasetLock); }
ReturnValue_t SharedLocalDataSet::unlockDataset() {
ReturnValue_t SharedLocalDataset::unlockDataset() {
if (datasetLock != nullptr) {
return datasetLock->unlockMutex();
}

View File

@ -0,0 +1,37 @@
#pragma once
#include <vector>
#include "fsfw/datapool/SharedDataSetIF.h"
#include "fsfw/objectmanager/SystemObject.h"
#include "SharedSetBase.h"
#include "SharedPool.h"
namespace datapool {
/**
* This local dataset variation can be used if the dataset is used concurrently across
* multiple threads. It provides a lock in addition to all other functionalities provided
* by the LocalPoolDataSetBase class.
*
* The user is completely responsible for locking and unlocking the dataset when using the
* shared dataset.
*/
class SharedLocalDataset : public SystemObject, public SharedSetBase, public SharedDataSetIF {
public:
SharedLocalDataset(object_id_t objectId, SharedPool& sharedPool, uint32_t setId,
size_t maxSize);
SharedLocalDataset(object_id_t objectId, sid_t sid, size_t maxSize);
~SharedLocalDataset() override;
ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
dur_millis_t mutexTimeout = 20) override;
ReturnValue_t unlockDataset() override;
private:
MutexIF* datasetLock = nullptr;
std::vector<PoolVariableIF*> poolVarVector;
};
}

View File

@ -1,4 +1,4 @@
#include <fsfw_hal/devicehandlers/devicedefinitions/gyroL3gHelpers.h>
#include "gyroL3gHelpers.h"
float l3gd20h::ctrlReg4ToSensitivity(uint8_t reg) {
bool fsH = reg & l3gd20h::SET_FS_1;

View File

@ -1,8 +1,8 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_GYROL3GD20DEFINITIONS_H_
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include <cstdint>
@ -124,8 +124,8 @@ class GyroPrimaryDataset : public StaticLocalDataSet<5> {
setAllVariablesReadOnly();
}
/** Constructor for the data creator */
GyroPrimaryDataset(HasLocalDataPoolIF* hkOwner)
: StaticLocalDataSet(hkOwner, l3gd20h::GYRO_DATASET_ID) {}
GyroPrimaryDataset(localpool::SharedPool& sharedPool)
: StaticLocalDataSet(sharedPool, l3gd20h::GYRO_DATASET_ID) {}
/* Angular velocities in degrees per second (DPS) */
lp_var_t<float> angVelocX = lp_var_t<float>(sid.objectId, l3gd20h::ANG_VELOC_X, this);

View File

@ -1,9 +1,9 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_MGMLIS3HANDLERDEFS_H_
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include <cstdint>
@ -169,11 +169,12 @@ static const uint8_t CTRL_REG5_DEFAULT = 0;
static const uint32_t MGM_DATA_SET_ID = READ_CONFIG_AND_DATA;
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS, TEMPERATURE_CELCIUS };
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS = 0, TEMPERATURE_CELCIUS = 1, SET_IS_VALID = 2 };
class MgmPrimaryDataset : public StaticLocalDataSet<4> {
public:
MgmPrimaryDataset(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MGM_DATA_SET_ID) {}
MgmPrimaryDataset(localpool::SharedPool& sharedPool)
: StaticLocalDataSet(sharedPool, MGM_DATA_SET_ID) {}
MgmPrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATA_SET_ID)) {}
@ -182,6 +183,7 @@ class MgmPrimaryDataset : public StaticLocalDataSet<4> {
*/
lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this);
lp_var_t<float> temperature = lp_var_t<float>(sid.objectId, TEMPERATURE_CELCIUS, this);
lp_var_t<uint8_t> setIsValid = lp_var_t<uint8_t>(sid.objectId, SET_IS_VALID, this);
};
} // namespace mgmLis3

View File

@ -1,13 +1,13 @@
#ifndef MISSION_DEVICES_DEVICEDEFINITIONS_MGMHANDLERRM3100DEFINITIONS_H_
#define MISSION_DEVICES_DEVICEDEFINITIONS_MGMHANDLERRM3100DEFINITIONS_H_
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/devicehandlers/DeviceHandlerIF.h>
#include <fsfw/serialize/SerialLinkedListAdapter.h>
#include <cstdint>
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
namespace mgmRm3100 {
/* Actually 10, we round up a little bit */
@ -101,11 +101,12 @@ class CycleCountCommand : public SerialLinkedListAdapter<SerializeIF> {
static constexpr uint32_t MGM_DATASET_ID = READ_DATA;
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS };
enum MgmPoolIds : lp_id_t { FIELD_STRENGTHS = 0, VALID = 1 };
class Rm3100PrimaryDataset : public StaticLocalDataSet<3> {
public:
Rm3100PrimaryDataset(HasLocalDataPoolIF* hkOwner) : StaticLocalDataSet(hkOwner, MGM_DATASET_ID) {}
Rm3100PrimaryDataset(localpool::SharedPool& sharedPool)
: StaticLocalDataSet(sharedPool, MGM_DATASET_ID) {}
Rm3100PrimaryDataset(object_id_t mgmId) : StaticLocalDataSet(sid_t(mgmId, MGM_DATASET_ID)) {}
@ -113,6 +114,7 @@ class Rm3100PrimaryDataset : public StaticLocalDataSet<3> {
* Field strenghts in uT
*/
lp_vec_t<float, 3> fieldStrengths = lp_vec_t<float, 3>(sid.objectId, FIELD_STRENGTHS, this);
lp_var_t<uint8_t> valid = lp_var_t<uint8_t>(sid.objectId, VALID, this);
};
} // namespace mgmRm3100

View File

@ -7,7 +7,6 @@ add_subdirectory(cfdp)
add_subdirectory(container)
add_subdirectory(controller)
add_subdirectory(datapool)
add_subdirectory(datapoollocal)
add_subdirectory(devicehandlers)
add_subdirectory(events)
add_subdirectory(fdir)

View File

@ -2,7 +2,7 @@
ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth)
: ControllerBase(objectId, commandQueueDepth),
poolManager(this, commandQueue),
hkHelper(this, commandQueue),
actionHelper(this, commandQueue) {}
ExtendedControllerBase::~ExtendedControllerBase() = default;
@ -10,22 +10,18 @@ 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. */
// Needs to be overriden and implemented by child class.
return returnvalue::OK;
}
object_id_t ExtendedControllerBase::getObjectId() const { return SystemObject::getObjectId(); }
uint32_t ExtendedControllerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
ReturnValue_t ExtendedControllerBase::handleCommandMessage(CommandMessage *message) {
ReturnValue_t result = actionHelper.handleActionMessage(message);
if (result == returnvalue::OK) {
return result;
}
return poolManager.handleHousekeepingMessage(message);
return hkHelper.handleHousekeepingMessage(message);
}
void ExtendedControllerBase::handleQueue() {
@ -48,7 +44,7 @@ void ExtendedControllerBase::handleQueue() {
continue;
}
result = poolManager.handleHousekeepingMessage(&command);
result = hkHelper.handleHousekeepingMessage(&command);
if (result == returnvalue::OK) {
continue;
}
@ -72,22 +68,18 @@ ReturnValue_t ExtendedControllerBase::initialize() {
return result;
}
return poolManager.initialize(commandQueue);
}
ReturnValue_t ExtendedControllerBase::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
return hkHelper.initialize(commandQueue);
}
ReturnValue_t ExtendedControllerBase::performOperation(uint8_t opCode) {
handleQueue();
performControlOperation(opCode);
/* We do this after performing control operation because variables will be set changed
in this function. */
poolManager.performHkOperation();
// We do this after performing control operation because variables will be set changed
// in this function.
hkHelper.performHkOperation();
return returnvalue::OK;
}
MessageQueueId_t ExtendedControllerBase::getCommandQueue() const { return commandQueue->getId(); }
LocalDataPoolManager *ExtendedControllerBase::getHkManagerHandle() { return &poolManager; }
datapool::SharedPool *ExtendedControllerBase::getOptionalSharedPool() { return nullptr; }

View File

@ -1,10 +1,11 @@
#ifndef FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#define FSFW_CONTROLLER_EXTENDEDCONTROLLERBASE_H_
#include <fsfw/housekeeping/GeneratesPeriodicHkIF.h>
#include "ControllerBase.h"
#include "fsfw/action.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/housekeeping/PeriodicHkHelper.h"
/**
* @brief Extends the basic ControllerBase with commonly used components
@ -15,9 +16,9 @@
*/
class ExtendedControllerBase : public ControllerBase,
public HasActionsIF,
public HasLocalDataPoolIF {
public hk::GeneratesPeriodicHkIF {
public:
ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
explicit ExtendedControllerBase(object_id_t objectId, size_t commandQueueDepth = 3);
~ExtendedControllerBase() override;
/* SystemObjectIF overrides */
@ -27,12 +28,18 @@ class ExtendedControllerBase : public ControllerBase,
/* ExecutableObjectIF overrides */
ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
protected:
LocalDataPoolManager poolManager;
hk::PeriodicHelper hkHelper;
ActionHelper actionHelper;
// Periodic HK methods, default method assumes that no shared pool is required.
virtual datapool::SharedPool* getOptionalSharedPool() override;
// Periodic HK abstract methods.
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) = 0;
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) = 0;
/**
* Implemented by child class. Handle all command messages which are
* not health, mode, action or housekeeping messages.
@ -49,18 +56,12 @@ class ExtendedControllerBase : public ControllerBase,
// Handle the four messages mentioned above
void handleQueue() override;
/* HasActionsIF overrides */
// HasActionsIF overrides
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override;
/* HasLocalDatapoolIF overrides */
LocalDataPoolManager* getHkManagerHandle() override;
// HasLocalDatapoolIF overrides
[[nodiscard]] object_id_t getObjectId() const override;
[[nodiscard]] uint32_t getPeriodicOperationFrequency() const override;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override = 0;
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
// Mode abstract functions
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,

11
src/fsfw/datapool.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
#define FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_
// Collected related headers
#include "fsfw/datapool/LocalPoolVector.h"
#include "fsfw/datapool/PoolVariable.h"
#include "fsfw/datapool/SharedPool.h"
#include "fsfw/datapool/SharedSet.h"
#include "fsfw/datapool/StaticSharedSet.h"
#endif /* FSFW_DATAPOOLLOCAL_DATAPOOLLOCAL_H_ */

View File

@ -1 +1,6 @@
target_sources(${LIB_FSFW_NAME} PRIVATE PoolDataSetBase.cpp PoolEntry.cpp)
target_sources(
${LIB_FSFW_NAME}
PRIVATE PoolDataSetBase.cpp PoolEntry.cpp SharedPool.cpp SharedSet.cpp
SharedSetBase.cpp LocalPoolObjectBase.cpp)
add_subdirectory(internal)

View File

@ -1,36 +1,25 @@
#include "fsfw/datapoollocal/LocalPoolObjectBase.h"
#include "fsfw/datapool/LocalPoolObjectBase.h"
#include "fsfw/datapoollocal/AccessLocalPoolF.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/housekeeping/PeriodicHkHelper.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "internal/HasLocalDpIFUserAttorney.h"
LocalPoolObjectBase::LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner,
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
: localPoolId(poolId), readWriteMode(setReadWriteMode) {
using namespace dp;
PoolObjectBase::PoolObjectBase(SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: localPoolId(poolId), readWriteMode(setReadWriteMode), sharedPool(&sharedPool) {
if (poolId == PoolVariableIF::NO_PARAMETER) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolVar<T>::LocalPoolVar: 0 passed as pool ID, "
<< "which is the NO_PARAMETER value!" << std::endl;
#endif
}
if (hkOwner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVar<T>::LocalPoolVar: The supplied pool "
<< "owner is a invalid!" << std::endl;
#endif
return;
}
AccessPoolManagerIF* poolManAccessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
hkManager = poolManAccessor->getPoolManagerHandle();
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet,
PoolObjectBase::PoolObjectBase(object_id_t poolOwner, id_t poolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: localPoolId(poolId), readWriteMode(setReadWriteMode) {
if (poolId == PoolVariableIF::NO_PARAMETER) {
@ -44,7 +33,7 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
"which is the NO_PARAMETER value!\n");
#endif
}
HasLocalDataPoolIF* hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(poolOwner);
auto* hkOwner = ObjectManager::instance()->get<hk::GeneratesPeriodicHkIF>(poolOwner);
if (hkOwner == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolVariable: The supplied pool owner 0x" << std::hex << poolOwner
@ -58,37 +47,25 @@ LocalPoolObjectBase::LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId,
#endif
return;
}
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if (accessor != nullptr) {
hkManager = accessor->getPoolManagerHandle();
}
sharedPool = hkOwner->getOptionalSharedPool();
if (dataSet != nullptr) {
dataSet->registerVariable(this);
}
}
pool_rwm_t LocalPoolObjectBase::getReadWriteMode() const { return readWriteMode; }
pool_rwm_t PoolObjectBase ::getReadWriteMode() const { return readWriteMode; }
bool LocalPoolObjectBase::isValid() const { return valid; }
id_t PoolObjectBase ::getDataPoolId() const { return localPoolId; }
void LocalPoolObjectBase::setValid(bool valid) { this->valid = valid; }
void PoolObjectBase::setDataPoolId(id_t poolId) { this->localPoolId = poolId; }
lp_id_t LocalPoolObjectBase::getDataPoolId() const { return localPoolId; }
void LocalPoolObjectBase::setDataPoolId(lp_id_t poolId) { this->localPoolId = poolId; }
void LocalPoolObjectBase::setChanged(bool changed) { this->changed = changed; }
bool LocalPoolObjectBase::hasChanged() const { return changed; }
void LocalPoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) {
void PoolObjectBase::setReadWriteMode(pool_rwm_t newReadWriteMode) {
this->readWriteMode = newReadWriteMode;
}
void LocalPoolObjectBase::reportReadCommitError(const char* variableType, ReturnValue_t error,
bool read, object_id_t objectId, lp_id_t lpId) {
void PoolObjectBase::reportReadCommitError(const char* variableType, ReturnValue_t error, bool read,
object_id_t objectId, id_t lpId) {
#if FSFW_DISABLE_PRINTOUT == 0
const char* variablePrintout = variableType;
if (variablePrintout == nullptr) {
@ -102,9 +79,9 @@ void LocalPoolObjectBase::reportReadCommitError(const char* variableType, Return
}
const char* errMsg = nullptr;
if (error == localpool::POOL_ENTRY_NOT_FOUND) {
if (error == POOL_ENTRY_NOT_FOUND) {
errMsg = "Pool entry not found";
} else if (error == localpool::POOL_ENTRY_TYPE_CONFLICT) {
} else if (error == POOL_ENTRY_TYPE_CONFLICT) {
errMsg = "Pool entry type conflict";
} else if (error == PoolVariableIF::INVALID_READ_WRITE_MODE) {
errMsg = "Pool variable wrong read-write mode";

View File

@ -0,0 +1,50 @@
#pragma once
#include "SharedPool.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/datapool/definitions.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/returnvalues/returnvalue.h"
class DataSetIF;
namespace datapool {
/**
* @brief This class serves as a non-template base for pool objects like pool variables
* or pool vectors.
*/
class PoolObjectBase : public PoolVariableIF {
public:
PoolObjectBase(dp::SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode);
PoolObjectBase(object_id_t poolOwner, dp::id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
void setReadWriteMode(pool_rwm_t newReadWriteMode) override;
[[nodiscard]] pool_rwm_t getReadWriteMode() const override;
[[nodiscard]] dp::id_t getDataPoolId() const override;
void setDataPoolId(dp::id_t poolId);
protected:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t localPoolId = PoolVariableIF::NO_PARAMETER;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE;
//! @brief Pointer to the class which manages the HK pool.
dp::SharedPool* sharedPool = nullptr;
void reportReadCommitError(const char* variableType, ReturnValue_t error, bool read,
object_id_t objectId, dp::id_t lpId);
};
} // namespace datapool

View File

@ -1,14 +1,15 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#pragma once
#include <fsfw/ipc/MutexGuard.h>
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h"
#include "../datapool/PoolVariableIF.h"
#include "../datapoollocal/LocalDataPoolManager.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterface.h"
#include "LocalPoolObjectBase.h"
#include "internal/LocalDpManagerAttorney.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolEntry.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
namespace datapool {
/**
* @brief This is the access class for array-type data pool entries.
@ -24,16 +25,16 @@
* @tparam T
* This template parameter specifies the data type of an array entry. Currently,
* all plain data types are supported, but in principle any type is possible.
* @tparam vector_size
* @tparam N
* This template parameter specifies the vector size of this entry. Using a
* template parameter for this is not perfect, but avoids
* dynamic memory allocation.
* @ingroup data_pool
*/
template <typename T, uint16_t vectorSize>
class LocalPoolVector : public LocalPoolObjectBase {
template <typename T, size_t N>
class PoolVector : public PoolObjectBase {
public:
LocalPoolVector() = delete;
PoolVector() = delete;
/**
* This constructor is used by the data creators to have pool variable
* instances which can also be stored in datasets.
@ -47,8 +48,9 @@ class LocalPoolVector : public LocalPoolObjectBase {
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
*/
LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
PoolVector(SharedPool& sharedPool, id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE)
: PoolObjectBase(sharedPool, poolId, dataSet, setReadWriteMode) {}
/**
* This constructor is used by data users like controllers to have
@ -57,15 +59,15 @@ class LocalPoolVector : public LocalPoolObjectBase {
* It does not fetch the current value from the data pool. This is performed
* by the read() operation (which is not thread-safe).
* Datasets can be used to access local pool entires in a thread-safe way.
* @param poolOwner Owner of the shared pool.
* @param poolId ID of the local pool entry.
* @param hkOwner Pointer of the owner. This will generally be the calling
* class itself which passes "this".
* @param setReadWriteMode Specify the read-write mode of the pool variable.
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
*/
LocalPoolVector(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
PoolVector(object_id_t poolOwner, id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE)
: PoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
/**
* Variation which takes the unique global identifier of a local pool
* vector.
@ -73,8 +75,10 @@ class LocalPoolVector : public LocalPoolObjectBase {
* @param dataSet
* @param setReadWriteMode
*/
LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
PoolVector(g_id_t globalPoolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE)
: PoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, setReadWriteMode) {
}
/**
* @brief This is the local copy of the data pool entry.
@ -82,27 +86,80 @@ class LocalPoolVector : public LocalPoolObjectBase {
* The user can work on this attribute just like he would on a local
* array of this type.
*/
T value[vectorSize] = {};
T value[N] = {};
/**
* @brief The classes destructor is empty.
* @details If commit() was not called, the local value is
* discarded and not written back to the data pool.
*/
~LocalPoolVector() {};
~PoolVector() override {};
/**
* @brief The operation returns the number of array entries
* in this variable.
*/
uint8_t getSize() { return vectorSize; }
size_t getSize() { return N; }
T& operator[](size_t i);
const T& operator[](size_t i) const;
T& operator[](size_t i) {
if (i < N) {
return value[i];
}
// If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PoolVector: Invalid index. Setting or returning"
" last value!"
<< std::endl;
#else
sif::printWarning(
"PoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif
return value[N - 1];
}
const T& operator[](size_t i) const {
if (i < N) {
return value[i];
}
// If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "PoolVector: Invalid index. Setting or returning"
" last value!"
<< std::endl;
#else
sif::printWarning(
"PoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif
return value[N - 1];
}
ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
SerializeIF::Endianness streamEndiannes) const override;
size_t getSerializedSize() const override;
SerializeIF::Endianness streamEndianness) const override {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t i = 0; i < N; i++) {
result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
break;
}
}
return result;
}
[[nodiscard]] size_t getSerializedSize() const override {
return N * SerializeAdapter::getSerializedSize(value);
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
SerializeIF::Endianness streamEndianness) override {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t i = 0; i < N; i++) {
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness);
if (result != returnvalue::OK) {
break;
}
}
return result;
}
/**
* @brief This is a call to read the array's values
@ -118,7 +175,10 @@ class LocalPoolVector : public LocalPoolObjectBase {
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
uint32_t timeoutMs = 20) override {
MutexGuard mg(sharedPool->getPoolMutex(), timeoutType, timeoutMs);
return readWithoutLock();
}
/**
* @brief The commit call copies the array values back to the data pool.
@ -129,15 +189,11 @@ class LocalPoolVector : public LocalPoolObjectBase {
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief This commit call also sets the validity of the pool entry.
* @details
*/
ReturnValue_t commit(bool valid, MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
ReturnValue_t commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) override {
MutexGuard mg(sharedPool->getPoolMutex(), timeoutType, timeoutMs);
return commitWithoutLock();
}
ReturnValue_t commit() { return commit(MutexIF::TimeoutType::WAITING, 20); }
protected:
/**
@ -148,7 +204,22 @@ class LocalPoolVector : public LocalPoolObjectBase {
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
ReturnValue_t readWithoutLock() override {
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
memset(this->value, 0, N * sizeof(T));
if (result != returnvalue::OK) {
return result;
}
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
return returnvalue::OK;
}
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
@ -157,19 +228,36 @@ class LocalPoolVector : public LocalPoolObjectBase {
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
ReturnValue_t commitWithoutLock() override {
if (readWriteMode == pool_rwm_t::VAR_READ) {
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
if (result != returnvalue::OK) {
return result;
}
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
return returnvalue::OK;
}
private:
#if FSFW_CPP_OSTREAM_ENABLED == 1
// std::ostream is the type for object std::cout
template <typename U, uint16_t otherSize>
friend std::ostream& operator<<(std::ostream& out, const LocalPoolVector<U, otherSize>& var);
std::ostream& operator<<(std::ostream& out, const PoolVector<T, N>& var) {
out << "Vector: [";
for (int i = 0; i < N; i++) {
out << var.value[i];
if (i < N - 1) {
out << ", ";
}
}
out << "]";
return out;
}
#endif
};
#include "LocalPoolVector.tpp"
template <typename T, size_t N>
using vec_t = PoolVector<T, N>;
template <typename T, uint16_t vectorSize>
using lp_vec_t = LocalPoolVector<T, vectorSize>;
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_ */
} // namespace datapool

View File

View File

@ -82,19 +82,19 @@ 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. */
// 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. */
// 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 */
// The readWithoutLock function is protected, so we use the attorney here
result = ReadCommitIFAttorney::readWithoutLock(registeredVariables[count]);
}

View File

@ -1,11 +1,14 @@
#ifndef FSFW_DATAPOOL_POOLDATASETBASE_H_
#define FSFW_DATAPOOL_POOLDATASETBASE_H_
#pragma once
#include "PoolDataSetIF.h"
#include "PoolVariableIF.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/serialize/SerializeIF.h"
namespace datapool {
class SharedSetBase;
}
/**
* @brief The DataSetBase class manages a set of locally checked out variables.
* @details
@ -30,6 +33,8 @@
* @ingroup data_pool
*/
class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
friend class datapool::SharedSetBase;
public:
/**
* @brief Creates an empty dataset. Use registerVariable or
@ -99,23 +104,22 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
* thread-safety. Default implementation is empty
* @return Always returns -@c returnvalue::OK
*/
virtual ReturnValue_t lockDataPool(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
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;
ReturnValue_t unlockDataPool() override;
virtual uint16_t getFillCount() const override;
[[nodiscard]] uint16_t getFillCount() const override;
/* SerializeIF implementations */
virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize,
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,
[[nodiscard]] size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
@ -169,5 +173,3 @@ class PoolDataSetBase : public PoolDataSetIF, public SerializeIF {
ReturnValue_t handleUnreadDatasetCommit(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING, uint32_t timeoutMs = 20);
};
#endif /* FSFW_DATAPOOL_POOLDATASETBASE_H_ */

View File

@ -10,7 +10,7 @@
*/
class PoolDataSetIF : virtual public DataSetIF, virtual public ReadCommitIF {
public:
virtual ~PoolDataSetIF() {};
~PoolDataSetIF() override = default;
/**
* @brief Most underlying data structures will have a pool like structure
@ -18,17 +18,13 @@ class PoolDataSetIF : virtual public DataSetIF, virtual public ReadCommitIF {
* thread-safety
* @return Lock operation result
*/
virtual ReturnValue_t lockDataPool(
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) = 0;
virtual ReturnValue_t lockDataPool(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) = 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_ */

View File

@ -52,16 +52,6 @@ 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;

View File

@ -104,16 +104,7 @@ class PoolEntry : public PoolEntryIF {
* @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.

View File

@ -39,14 +39,7 @@ class PoolEntryIF {
* @brief This operation returns a the address pointer casted to void*.
*/
virtual void* getRawData() = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual void setValid(bool isValid) = 0;
/**
* @brief This method allows to set the valid information of the pool entry.
*/
virtual bool getValid() = 0;
/**
* @brief This is a debug method that prints all values and the valid
* information to the screen. It prints all array entries in a row.

View File

@ -0,0 +1,348 @@
#pragma once
#include <fsfw/datapool/internal/SharedPoolAttorney.h>
#include "FSFWConfig.h"
#include "LocalPoolObjectBase.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/serialize/SerializeAdapter.h"
namespace datapool {
/**
* @brief Local Pool Variable class which is used to access the local pools.
* @details
* This class is not stored in the map. Instead, it is used to access
* the pool entries by using a pointer to the map storing the pool
* entries. It can also be used to organize these pool entries into data sets.
*
* @tparam T The template parameter sets the type of the variable. Currently,
* all plain data types are supported, but in principle any type is possible.
* @ingroup data_pool
*/
template <typename T>
class PoolVariable : public PoolObjectBase {
public:
//! Default ctor is forbidden.
PoolVariable() = delete;
/**
* This constructor is used by the data creators to have pool variable
* instances which can also be stored in datasets.
*
* It does not fetch the current value from the data pool, which
* has to be done by calling the read() operation.
* Datasets can be used to access multiple local pool entries in an
* efficient way. A pointer to a dataset can be passed to register
* the pool variable in that dataset directly.
* @param poolId ID of the local pool entry.
* @param hkOwner Pointer of the owner. This will generally be the calling
* class itself which passes "this".
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*/
PoolVariable(SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/**
* This constructor is used by data users like controllers to have
* access to the local pool variables of data creators by supplying
* the respective creator object ID.
*
* It does not fetch the current value from the data pool, which
* has to be done by calling the read() operation.
* Datasets can be used to access multiple local pool entries in an
* efficient way. A pointer to a dataset can be passed to register
* the pool variable in that dataset directly.
* @param poolId ID of the local pool entry.
* @param hkOwner object ID of the pool owner.
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*
*/
PoolVariable(object_id_t poolOwner, dp::id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/**
* Variation which takes the global unique identifier of a pool variable.
* @param globalPoolId
* @param dataSet
* @param setReadWriteMode
*/
PoolVariable(g_id_t globalPoolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
virtual ~PoolVariable() {};
T get() const;
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a simple local variable.
*/
T value = 0;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the data pool and copies all array values and the valid
* information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*
*/
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the local valid flag is written back as well.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
PoolVariable<T>& operator=(const T& newValue);
PoolVariable<T>& operator=(const PoolVariable<T>& newPoolVariable);
//! Explicit type conversion operator. Allows casting the class to
//! its template type to perform operations on value.
explicit operator T() const;
bool operator==(const PoolVariable<T>& other) const;
bool operator==(const T& other) const;
bool operator!=(const PoolVariable<T>& other) const;
bool operator!=(const T& other) const;
bool operator<(const PoolVariable<T>& other) const;
bool operator<(const T& other) const;
bool operator>(const PoolVariable<T>& other) const;
bool operator>(const T& other) const;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
#if FSFW_CPP_OSTREAM_ENABLED == 1
// std::ostream is the type for object std::cout
template <typename U>
friend std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<U>& var);
#endif
};
template <typename T>
PoolVariable<T>::PoolVariable(SharedPool& sharedPool, dp::id_t poolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: PoolObjectBase(sharedPool, poolId, dataSet, setReadWriteMode) {}
template <typename T>
PoolVariable<T>::PoolVariable(object_id_t poolOwner, dp::id_t poolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: PoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
template <typename T>
PoolVariable<T>::PoolVariable(g_id_t globalPoolId, DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
: PoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet, setReadWriteMode) {}
template <typename T>
ReturnValue_t PoolVariable<T>::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
if (sharedPool == nullptr) {
return readWithoutLock();
}
MutexIF* mutex = sharedPool->getPoolMutex();
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
return result;
}
result = readWithoutLock();
mutex->unlockMutex();
return result;
}
template <typename T>
inline ReturnValue_t PoolVariable<T>::readWithoutLock() {
if (sharedPool == nullptr) {
return PoolVariableIF::INVALID_SHARED_POOL;
}
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
if (ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
result != returnvalue::OK) {
return result;
}
this->value = *(poolEntry->getDataPtr());
return returnvalue::OK;
}
template <typename T>
inline ReturnValue_t PoolVariable<T>::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
if (sharedPool == nullptr) {
return commitWithoutLock();
}
MutexIF* mutex = sharedPool->getPoolMutex();
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
return result;
}
result = commitWithoutLock();
mutex->unlockMutex();
return result;
}
template <typename T>
ReturnValue_t PoolVariable<T>::commitWithoutLock() {
if (readWriteMode == pool_rwm_t::VAR_READ) {
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result = sharedPool->fetchPoolEntry(localPoolId, &poolEntry);
if (result != returnvalue::OK) {
return result;
}
*(poolEntry->getDataPtr()) = this->value;
return returnvalue::OK;
}
template <typename T>
ReturnValue_t PoolVariable<T>::serialize(uint8_t** buffer, size_t* size, const size_t max_size,
SerializeIF::Endianness streamEndianness) const {
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
}
template <typename T>
size_t PoolVariable<T>::getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
template <typename T>
ReturnValue_t PoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
}
template <typename T>
T PoolVariable<T>::get() const {
return value;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
template <typename T>
inline std::ostream& operator<<(std::ostream& out, const PoolVariable<T>& var) {
out << var.value;
return out;
}
#endif
template <typename T>
PoolVariable<T>::operator T() const {
return value;
}
template <typename T>
PoolVariable<T>& PoolVariable<T>::operator=(const T& newValue) {
value = newValue;
return *this;
}
template <typename T>
PoolVariable<T>& PoolVariable<T>::operator=(const PoolVariable<T>& newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
template <typename T>
bool PoolVariable<T>::operator==(const PoolVariable<T>& other) const {
return this->value == other.value;
}
template <typename T>
bool PoolVariable<T>::operator==(const T& other) const {
return this->value == other;
}
template <typename T>
bool PoolVariable<T>::operator!=(const PoolVariable& other) const {
return not(*this == other);
}
template <typename T>
bool PoolVariable<T>::operator!=(const T& other) const {
return not(*this == other);
}
template <typename T>
bool PoolVariable<T>::operator<(const PoolVariable<T>& other) const {
return this->value < other.value;
}
template <typename T>
bool PoolVariable<T>::operator<(const T& other) const {
return this->value < other;
}
template <typename T>
bool PoolVariable<T>::operator>(const PoolVariable<T>& other) const {
return not(*this < other);
}
template <typename T>
bool PoolVariable<T>::operator>(const T& other) const {
return not(*this < other);
}
template <class T>
using var_t = PoolVariable<T>;
using bool_t = PoolVariable<uint8_t>;
using u8_t = PoolVariable<uint8_t>;
using u16_t = PoolVariable<uint16_t>;
using u32_t = PoolVariable<uint32_t>;
using u64_t = PoolVariable<uint64_t>;
using i8_t = PoolVariable<int8_t>;
using i16_t = PoolVariable<int16_t>;
using i32_t = PoolVariable<int32_t>;
using i64_t = PoolVariable<int64_t>;
using f32_t = PoolVariable<float>;
using f64_t = PoolVariable<double>;
} // namespace datapool

View File

@ -0,0 +1 @@
#pragma once

View File

@ -23,6 +23,7 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
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 ReturnValue_t INVALID_SHARED_POOL = MAKE_RETURN_CODE(0xA2);
static constexpr bool VALID = 1;
static constexpr bool INVALID = 0;
@ -46,15 +47,6 @@ class PoolVariableIF : public SerializeIF, public ReadCommitIF {
* @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;

View File

@ -0,0 +1,36 @@
#include "SharedPool.h"
#include "FSFWConfig.h"
#include "fsfw/ipc/MutexFactory.h"
#include "fsfw/serviceinterface.h"
using namespace dp;
SharedPool::SharedPool(object_id_t ownerId) : ownerId(ownerId) {
mutex = MutexFactory::instance()->createMutex();
if (mutex == nullptr) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "localpool::Manager: Mutex creation failed" << std::endl;
#else
sif::printError("localpool::Manager: Mutex creation failed");
#endif
}
}
SharedPool::~SharedPool() { MutexFactory::instance()->deleteMutex(mutex); }
object_id_t SharedPool::getOwnerId() const { return ownerId; }
void SharedPool::addPoolEntry(id_t poolId, PoolEntryIF* entry) {
localPoolMap.emplace(poolId, entry);
}
MutexIF* SharedPool::getPoolMutex() { return mutex; }
ReturnValue_t SharedPool::printPoolEntry(id_t localPoolId) {
auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) {
return POOL_ENTRY_NOT_FOUND;
}
poolIter->second->print();
return returnvalue::OK;
}

View File

@ -0,0 +1,62 @@
#pragma once
#include "fsfw/datapool/PoolEntry.h"
#include "fsfw/datapool/definitions.h"
#include "fsfw/ipc/MutexIF.h"
namespace datapool {
class SharedPool {
public:
explicit SharedPool(object_id_t ownerId);
~SharedPool();
[[nodiscard]] object_id_t getOwnerId() const;
/**
* Read a variable by supplying its local pool ID and assign the pool
* entry to the supplied PoolEntry pointer. The type of the pool entry
* is deduced automatically. This call is not thread-safe!
* For now, only classes designated by the LocalDpManagerAttorney may use this function.
* @tparam T Type of the pool entry
* @param localPoolId Pool ID of the variable to read
* @param poolVar [out] Corresponding pool entry will be assigned to the
* supplied pointer.
* @return
*/
template <class T>
ReturnValue_t fetchPoolEntry(id_t localPoolId, PoolEntry<T>** poolEntry);
ReturnValue_t printPoolEntry(id_t localPoolId);
void addPoolEntry(id_t poolId, PoolEntryIF* entry);
MutexIF* getPoolMutex();
private:
object_id_t ownerId;
// Core data structure for the actual pool data
DataPool localPoolMap{};
// Every housekeeping data manager has a mutex to protect access
// to it's data pool.
MutexIF* mutex = nullptr;
};
template <class T>
inline ReturnValue_t datapool::SharedPool::fetchPoolEntry(id_t localPoolId,
PoolEntry<T>** poolEntry) {
if (poolEntry == nullptr) {
return returnvalue::FAILED;
}
auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) {
return POOL_ENTRY_NOT_FOUND;
}
*poolEntry = dynamic_cast<PoolEntry<T>*>(poolIter->second);
if (*poolEntry == nullptr) {
return POOL_ENTRY_TYPE_CONFLICT;
}
return returnvalue::OK;
}
} // namespace datapool

View File

@ -0,0 +1,16 @@
#include "SharedSet.h"
using namespace dp;
SharedSet::SharedSet(dp::SharedPool& sharedPool, uint32_t setId, const size_t maxNumberOfVariables)
: SharedSetBase(sharedPool, setId, nullptr, maxNumberOfVariables),
poolVarList(maxNumberOfVariables) {
this->setContainer(poolVarList.data());
}
SharedSet::SharedSet(dp::structure_id_t sid, const size_t maxNumberOfVariables)
: SharedSetBase(sid, nullptr, maxNumberOfVariables), poolVarList(maxNumberOfVariables) {
this->setContainer(poolVarList.data());
}
SharedSet::~SharedSet() = default;

View File

@ -1,10 +1,11 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALDATASET_H_
#define FSFW_DATAPOOLLOCAL_LOCALDATASET_H_
#pragma once
#include <vector>
#include "LocalPoolDataSetBase.h"
#include "SharedPool.h"
#include "SharedSetBase.h"
namespace datapool {
/**
* @brief This dataset type can be used to group related pool variables if the number of
* variables should not be fixed.
@ -18,20 +19,20 @@
* @tparam capacity Capacity of the static dataset, which is usually known
* beforehand.
*/
class LocalDataSet : public LocalPoolDataSetBase {
class SharedSet : public SharedSetBase {
public:
LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId, const size_t maxSize);
SharedSet(SharedPool& sharedPool, uint32_t setId, size_t maxSize);
LocalDataSet(sid_t sid, const size_t maxSize);
SharedSet(sid_t sid, size_t maxSize);
virtual ~LocalDataSet();
~SharedSet() override;
//! Copying forbidden for now.
LocalDataSet(const LocalDataSet&) = delete;
LocalDataSet& operator=(const LocalDataSet&) = delete;
SharedSet(const SharedSet&) = delete;
SharedSet& operator=(const SharedSet&) = delete;
private:
std::vector<PoolVariableIF*> poolVarList;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALDATASET_H_ */
} // namespace datapool

View File

@ -0,0 +1,153 @@
#include "SharedSetBase.h"
#include <fsfw/housekeeping/GeneratesPeriodicHkIF.h>
#include <cmath>
#include "fsfw/datapool.h"
#include "fsfw/globalfunctions/bitutility.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
using namespace datapool;
SharedSetBase::SharedSetBase(SharedPool &sharedPool, uint32_t setId,
PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables)
: base(registeredVariablesArray, maxNumberOfVariables), sharedPool(&sharedPool) {
mutexIfSingleDataCreator = sharedPool.getPoolMutex();
this->sid.objectId = sharedPool.getOwnerId();
this->sid.ownerSetId = setId;
}
SharedSetBase::SharedSetBase(structure_id_t sid, PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables)
: base(registeredVariablesArray, maxNumberOfVariables) {
auto *hkOwner = ObjectManager::instance()->get<hk::GeneratesPeriodicHkIF>(sid.objectId);
if (hkOwner != nullptr) {
sharedPool = hkOwner->getOptionalSharedPool();
if (sharedPool != nullptr) {
mutexIfSingleDataCreator = sharedPool->getPoolMutex();
}
}
this->sid = sid;
}
SharedSetBase::SharedSetBase(PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables, bool protectEveryReadCommitCall)
: base(registeredVariablesArray, maxNumberOfVariables) {
base.setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
}
SharedSetBase::~SharedSetBase() {
// In case set was read but not comitted, we commit all variables with an invalid state
if (base.state == PoolDataSetBase::States::STATE_SET_WAS_READ) {
for (uint16_t count = 0; count < base.getFillCount(); count++) {
if (base.registeredVariables[count] != nullptr) {
base.registeredVariables[count]->commit(MutexIF::TimeoutType::WAITING, 20);
}
}
}
}
ReturnValue_t SharedSetBase::lockDataPool(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
if (mutexIfSingleDataCreator != nullptr) {
return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs);
}
return returnvalue::OK;
}
ReturnValue_t SharedSetBase::unlockDataPool() {
if (mutexIfSingleDataCreator != nullptr) {
return mutexIfSingleDataCreator->unlockMutex();
}
return returnvalue::OK;
}
ReturnValue_t SharedSetBase::serializeLocalPoolIds(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
/* Serialize fill count as uint8_t */
auto fillCount = this->getFillCount();
for (uint16_t count = 0; count < fillCount; count++) {
id_t currentPoolId = base.registeredVariables[count]->getDataPoolId();
auto result =
SerializeAdapter::serialize(&currentPoolId, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: " << "Serialization error!"
<< std::endl;
#else
sif::printWarning(
"LocalPoolDataSetBase::serializeLocalPoolIds: "
"Serialization error!\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return result;
}
}
return returnvalue::OK;
}
size_t SharedSetBase::getLocalPoolIdsSerializedSize() const {
return base.getFillCount() * sizeof(id_t);
}
size_t SharedSetBase::getSerializedSize() const { return base.getSerializedSize(); }
ReturnValue_t SharedSetBase::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
return base.deSerialize(buffer, size, streamEndianness);
}
ReturnValue_t SharedSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
return base.serialize(buffer, size, maxSize, streamEndianness);
}
[[nodiscard]] ReturnValue_t SharedSetBase::serialize(
uint8_t *buffer, size_t &serLen, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
return SerializeIF::serialize(buffer, serLen, maxSize, streamEndianness);
}
void SharedSetBase::setReportingEnabled(bool reportingEnabled) {
this->reportingEnabled = reportingEnabled;
}
bool SharedSetBase::getReportingEnabled() const { return reportingEnabled; }
structure_id_t SharedSetBase::getStructureId() const { return sid; }
object_id_t SharedSetBase::getCreatorObjectId() {
if (sharedPool != nullptr) {
return sharedPool->getOwnerId();
}
return objects::NO_OBJECT;
}
void SharedSetBase::setAllVariablesReadOnly() {
for (size_t idx = 0; idx < this->getFillCount(); idx++) {
base.registeredVariables[idx]->setReadWriteMode(pool_rwm_t::VAR_READ);
}
}
void SharedSetBase::printSet() { return; }
ReturnValue_t SharedSetBase::read(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
return base.read(timeoutType, timeoutMs);
}
ReturnValue_t SharedSetBase::commit(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs) {
return base.commit(timeoutType, timeoutMs);
}
uint16_t SharedSetBase::getFillCount() const { return base.getFillCount(); }
ReturnValue_t SharedSetBase::registerVariable(PoolVariableIF *variable) {
return base.registerVariable(variable);
}
void SharedSetBase::setContainer(PoolVariableIF **variablesContainer) {
return base.setContainer(variablesContainer);
}
PoolVariableIF **SharedSetBase::getContainer() const { return base.getContainer(); }

View File

@ -1,17 +1,16 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#pragma once
#include <vector>
#include "MarkChangedIF.h"
#include "SharedPool.h"
#include "definitions.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolDataSetBase.h"
#include "localPoolDefinitions.h"
class LocalDataPoolManager;
class HasLocalDataPoolIF;
class PeriodicHkGenerationHelper;
class PeriodicHkGenerationIF;
class PeriodicHousekeepingHelper;
namespace datapool {
/**
* @brief The LocalDataSet class manages a set of locally checked out
* variables for local data pools
@ -40,9 +39,8 @@ class PeriodicHousekeepingHelper;
*
* @ingroup data_pool
*/
class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
friend class LocalPoolDataSetAttorney;
friend class PeriodicHousekeepingHelper;
class SharedSetBase : public SerializeIF, public PoolDataSetIF {
// friend class PeriodicHousekeepingHelper;
public:
/**
@ -51,9 +49,8 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* This constructor also initializes the components required for
* periodic handling.
*/
LocalPoolDataSetBase(HasLocalDataPoolIF* hkOwner, uint32_t setId,
PoolVariableIF** registeredVariablesArray, const size_t maxNumberOfVariables,
bool periodicHandling = true);
SharedSetBase(SharedPool& sharedPool, uint32_t setId, PoolVariableIF** registeredVariablesArray,
size_t maxNumberOfVariables);
/**
* @brief Constructor for users of the local pool data, which need
@ -66,8 +63,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* @param registeredVariablesArray
* @param maxNumberOfVariables
*/
LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables);
SharedSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray, size_t maxNumberOfVariables);
/**
* @brief Simple constructor, if the dataset is not the owner by
@ -87,7 +83,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* multiple creators, this flag can be set to protect all read and
* commit calls separately.
*/
LocalPoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxNumberOfVariables,
SharedSetBase(PoolVariableIF** registeredVariablesArray, size_t maxNumberOfVariables,
bool protectEveryReadCommitCall = true);
/**
@ -98,13 +94,13 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* the destructor parses all variables that are still registered to the set.
* For each, the valid flag in the data pool is set to "invalid".
*/
~LocalPoolDataSetBase();
~SharedSetBase() override;
/* The copy constructor and assingment constructor are forbidden for now.
The use-cases are limited and the first step would be to implement them properly for the
base class */
LocalPoolDataSetBase(const LocalPoolDataSetBase& otherSet) = delete;
const LocalPoolDataSetBase& operator=(const LocalPoolDataSetBase& otherSet) = delete;
SharedSetBase(const SharedSetBase& otherSet) = delete;
const SharedSetBase& operator=(const SharedSetBase& otherSet) = delete;
/**
* Helper functions used to set all currently contained variables to read-only.
@ -112,56 +108,27 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* by data consumers to prevent accidentally changing pool data.
*/
void setAllVariablesReadOnly();
void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const;
[[nodiscard]] ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override;
/** SerializeIF overrides */
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
[[nodiscard]] ReturnValue_t serialize(uint8_t* buffer, size_t& serLen, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
size_t getSerializedSize() const override;
Endianness streamEndianness) override;
[[nodiscard]] dp::sid_t getStructureId() const;
[[nodiscard]] size_t getSerializedSize() const override;
/**
* Special version of the serilization function which appends a
* validity buffer at the end. Each bit of this validity buffer
* denotes whether the container data set entries are valid from left
* to right, MSB first. (length = ceil(N/8), N = number of pool variables)
* @param buffer
* @param size
* @param maxSize
* @param bigEndian
* @param withValidityBuffer
* @return
*/
ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const;
ReturnValue_t deSerializeWithValidityBuffer(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness);
ReturnValue_t serializeLocalPoolIds(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness,
bool serializeFillCount = true) const;
uint8_t getLocalPoolIdsSerializedSize(bool serializeFillCount = true) const;
/**
* Set the dataset valid or invalid. These calls are mutex protected.
* @param setEntriesRecursively
* If this is true, all contained datasets will also be set recursively.
*/
void setValidity(bool valid, bool setEntriesRecursively);
bool isValid() const override;
/**
* These calls are mutex protected.
* @param changed
*/
void setChanged(bool changed) override;
bool hasChanged() const override;
SerializeIF::Endianness streamEndianness) const;
[[nodiscard]] size_t getLocalPoolIdsSerializedSize() const;
object_id_t getCreatorObjectId();
bool getReportingEnabled() const;
[[nodiscard]] bool getReportingEnabled() const;
void setReportingEnabled(bool enabled);
/**
@ -170,14 +137,27 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
* returns 0.0
* @return
*/
float getCollectionInterval() const;
[[nodiscard]] float getCollectionInterval() const;
/**
* @brief Can be overwritten by a specific implementation of a dataset to print the set.
*/
virtual void printSet();
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
dur_millis_t timeoutMs = 0) override;
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::BLOCKING,
dur_millis_t timeoutMs = 0) override;
uint16_t getFillCount() const override;
ReturnValue_t registerVariable(PoolVariableIF* variable) override;
void setContainer(PoolVariableIF** variablesContainer);
PoolVariableIF** getContainer() const;
protected:
PoolDataSetBase base;
sid_t sid;
//! This mutex is used if the data is created by one object only.
MutexIF* mutexIfSingleDataCreator = nullptr;
@ -195,21 +175,6 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
*/
bool valid = false;
/**
* Can be used to mark the dataset as changed, which is used
* by the LocalDataPoolManager to send out update messages.
*/
bool changed = false;
/**
* Specify whether the validity buffer is serialized too when serializing
* or deserializing the packet. Each bit of the validity buffer will
* contain the validity state of the pool variables from left to right.
* The size of validity buffer thus will be ceil(N / 8) with N = number of
* pool variables.
*/
bool withValidityBuffer = true;
/**
* @brief This is a small helper function to facilitate locking
* the global data pool.
@ -226,8 +191,7 @@ class LocalPoolDataSetBase : public PoolDataSetBase, public MarkChangedIF {
*/
ReturnValue_t unlockDataPool() override;
PeriodicHousekeepingHelper* periodicHelper = nullptr;
LocalDataPoolManager* poolManager = nullptr;
dp::SharedPool* sharedPool = nullptr;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ */
} // namespace datapool

View File

@ -1,13 +1,10 @@
#ifndef FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#define FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_
#pragma once
#include <array>
#include "../objectmanager/SystemObjectIF.h"
#include "LocalPoolDataSetBase.h"
#include "LocalPoolVariable.h"
#include "LocalPoolVector.h"
#include "SharedSetBase.h"
namespace datapool {
/**
* @brief This dataset type can be used to group related pool variables if the number of
* variables is fixed.
@ -18,30 +15,29 @@
*
* It is recommended to read the documentation of the LocalPoolDataSetBase
* class for more information on how this class works and how to use it.
* @tparam capacity Capacity of the static dataset, which is usually known
* @tparam NUM_VARIABLES Capacity of the static dataset, which is usually known
* beforehand.
*/
template <uint8_t NUM_VARIABLES>
class StaticLocalDataSet : public LocalPoolDataSetBase {
template <size_t NUM_VARIABLES>
class StaticSharedSet : public datapool::SharedSetBase {
public:
/**
* Constructor used by data owner and creator like device handlers.
* This constructor also initialized the components required for
* periodic handling.
* @param hkOwner
* @param sharedPool Shared pool this dataset will read from or write to.
* @param setId
*/
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId)
: LocalPoolDataSetBase(hkOwner, setId, nullptr, NUM_VARIABLES) {
StaticSharedSet(SharedPool& sharedPool, const uint32_t setId)
: SharedSetBase(sharedPool, setId, nullptr, NUM_VARIABLES) {
this->setContainer(poolVarList.data());
}
/**
* Constructor used by data users like controllers.
* @param hkOwner
* @param setId
* @param sid
*/
StaticLocalDataSet(sid_t sid) : LocalPoolDataSetBase(sid, nullptr, NUM_VARIABLES) {
explicit StaticSharedSet(const structure_id_t sid) : SharedSetBase(sid, nullptr, NUM_VARIABLES) {
this->setContainer(poolVarList.data());
}
@ -49,4 +45,4 @@ class StaticLocalDataSet : public LocalPoolDataSetBase {
std::array<PoolVariableIF*, NUM_VARIABLES> poolVarList = {};
};
#endif /* FSFW_DATAPOOLLOCAL_STATICLOCALDATASET_H_ */
} // namespace datapool

View File

@ -1,5 +1,4 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_
#pragma once
#include <cstdint>
#include <map>
@ -8,44 +7,44 @@
#include "../objectmanager/SystemObjectIF.h"
#include "../objectmanager/frameworkObjects.h"
namespace datapool {
/**
* @brief Type definition for local pool entries.
*/
using lp_id_t = uint32_t;
using id_t = uint32_t;
namespace localpool {
static constexpr uint32_t INVALID_LPID = -1;
static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF;
static constexpr uint8_t INTERFACE_ID = CLASS_ID::DATAPOOL_IF;
static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x00);
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x01);
/** This is the core data structure of the local data pools. Users should insert all desired
pool variables, using the std::map interface. */
using DataPool = std::map<lp_id_t, PoolEntryIF*>;
using DataPoolMapIter = DataPool::iterator;
} // namespace localpool
using DataPool = std::map<id_t, PoolEntryIF*>;
/**
* Used as a unique identifier for data sets. Consists of 4 byte object ID and 4 byte set ID.
*/
union sid_t {
union structure_id_t {
static constexpr size_t SIZE = sizeof(object_id_t) + sizeof(uint32_t);
static constexpr uint64_t INVALID_SID = -1;
static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
static constexpr uint32_t INVALID_SET_ID = -1;
sid_t() : raw(INVALID_SID) {}
constexpr structure_id_t() : raw(INVALID_SID) {}
sid_t(object_id_t objectId, uint32_t setId) : objectId(objectId), ownerSetId(setId) {}
constexpr structure_id_t(object_id_t objectId, uint32_t setId)
: objectId(objectId), ownerSetId(setId) {}
struct {
object_id_t objectId;
/**
* A generic 32 bit ID to identify unique HK packets for a single
* object. For example, the DeviceCommandId_t is used for
* DeviceHandlers
* A generic 32 bit ID to identify unique HK set packets for a single
* object.
*/
uint32_t ownerSetId;
};
@ -54,39 +53,41 @@ union sid_t {
*/
uint64_t raw;
bool notSet() const { return raw == INVALID_SID; }
[[nodiscard]] bool notSet() const { return raw == INVALID_SID; }
bool operator==(const sid_t& other) const { return raw == other.raw; }
bool operator==(const structure_id_t& other) const { return raw == other.raw; }
bool operator!=(const sid_t& other) const { return not(raw == other.raw); }
bool operator!=(const structure_id_t& other) const { return not(raw == other.raw); }
};
using sid_t = structure_id_t;
/**
* Used as a global unique identifier for local pool variables. Consists of 4 byte object ID
* and 4 byte local pool ID.
*/
union gp_id_t {
union g_id_t {
static constexpr uint64_t INVALID_GPID = -1;
static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
gp_id_t() : raw(INVALID_GPID) {}
g_id_t() : raw(INVALID_GPID) {}
gp_id_t(object_id_t objectId, lp_id_t localPoolId)
: objectId(objectId), localPoolId(localPoolId) {}
g_id_t(object_id_t objectId, id_t localPoolId) : objectId(objectId), localPoolId(localPoolId) {}
struct {
object_id_t objectId;
lp_id_t localPoolId;
id_t localPoolId;
};
uint64_t raw;
bool notSet() const { return raw == INVALID_GPID; }
bool operator==(const gp_id_t& other) const { return raw == other.raw; }
bool operator==(const g_id_t& other) const { return raw == other.raw; }
bool operator!=(const gp_id_t& other) const { return not(raw == other.raw); }
bool operator!=(const g_id_t& other) const { return not(raw == other.raw); }
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDEFINITIONS_H_ */
} // namespace datapool
namespace dp = datapool;

View File

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

View File

@ -0,0 +1,11 @@
#pragma once
#include "fsfw/datapool/SharedSetBase.h"
class LocalPoolDataSetAttorney {
static void setReportingEnabled(SharedDatasetBase& set, bool enabled) {
set.setReportingEnabled(enabled);
}
static bool getReportingEnabled(SharedDatasetBase& set) { return set.getReportingEnabled(); }
};

View File

@ -1,8 +1,8 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_
#pragma once
#include "../LocalDataPoolManager.h"
#include "fsfw/datapool/SharedPool.h"
namespace datapool {
/**
* @brief This is a helper class implements the Attorney-Client idiom for access to
* LocalDataPoolManager internals
@ -13,15 +13,15 @@
* an explicit subset of the pool manager private/protected functions.
* See: https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Friendship_and_the_Attorney-Client
*/
class LocalDpManagerAttorney {
class SharedPoolAttorney {
private:
template <typename T>
static ReturnValue_t fetchPoolEntry(LocalDataPoolManager& manager, lp_id_t localPoolId,
static ReturnValue_t fetchPoolEntry(SharedPool& manager, dp::id_t localPoolId,
PoolEntry<T>** poolEntry) {
return manager.fetchPoolEntry(localPoolId, poolEntry);
}
static MutexIF* getMutexHandle(LocalDataPoolManager& manager) { return manager.getMutexHandle(); }
static MutexIF* getMutexHandle(SharedPool& manager) { return manager.getPoolMutex(); }
template <typename T>
friend class LocalPoolVariable;
@ -29,4 +29,4 @@ class LocalDpManagerAttorney {
friend class LocalPoolVector;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALDPMANAGERATTORNEY_H_ */
} // namespace datapool

View File

@ -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_ */

View File

@ -1,26 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_
#define FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_
class LocalDataPoolManager;
class MutexIF;
/**
* @brief Accessor class which can be used by classes which like to use the pool manager.
*/
class AccessPoolManagerIF {
public:
virtual ~AccessPoolManagerIF() {};
virtual MutexIF* getLocalPoolMutex() = 0;
/**
* Can be used to get a handle to the local data pool manager.
* This function is protected because it should only be used by the
* class imlementing the interface.
*/
virtual LocalDataPoolManager* getPoolManagerHandle() = 0;
protected:
};
#endif /* FSFW_DATAPOOLLOCAL_ACCESSLOCALPOOLF_H_ */

View File

@ -1,6 +0,0 @@
target_sources(
${LIB_FSFW_NAME}
PRIVATE LocalDataPoolManager.cpp LocalDataSet.cpp LocalPoolDataSetBase.cpp
LocalPoolObjectBase.cpp SharedLocalDataSet.cpp)
add_subdirectory(internal)

View File

@ -1,181 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_
#include <map>
#include "LocalDataPoolManager.h"
#include "fsfw/datapool/PoolEntryIF.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/ipc/MessageQueueSenderIF.h"
#include "fsfw/serviceinterface.h"
#include "localPoolDefinitions.h"
class AccessPoolManagerIF;
class ProvidesDataPoolSubscriptionIF;
class LocalPoolDataSetBase;
class LocalPoolObjectBase;
/**
* @brief This interface is implemented by classes which posses a local data pool (not
* the managing class). It defines the relationship between the local data pool owner and the
* LocalDataPoolManager.
* @details
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
* contains the actual pool data structure and exposes the public interface for it.
*
* The local data pool can be accessed using helper classes by using the
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
*
* All software objects which want to use the local pool of another object shall also use this
* interface, for example to get a handle to the subscription interface. The interface
* can be retrieved using the object manager, provided the target object is a SystemObject.
* For example, the following line of code can be used to retrieve the interface
*
* HasLocalDataPoolIF* poolIF = ObjectManager::instance()->
* get<HasLocalDataPoolIF>(objects::SOME_OBJECT);
* if(poolIF != nullptr) {
* doSomething()
* }
*/
class HasLocalDataPoolIF {
friend class HasLocalDpIFManagerAttorney;
friend class HasLocalDpIFUserAttorney;
public:
virtual ~HasLocalDataPoolIF() {};
static constexpr uint32_t INVALID_LPID = localpool::INVALID_LPID;
virtual object_id_t getObjectId() const = 0;
/** Command queue for housekeeping messages. */
virtual MessageQueueId_t getCommandQueue() const = 0;
/**
* Is used by pool owner to initialize the pool map once
* The manager instance shall also be passed to this function.
* It can be used to subscribe for periodic packets for for updates.
*/
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) = 0;
/**
* Returns the minimum sampling frequency in milliseconds, which will
* usually be the period the pool owner performs its periodic operation.
* @return
*/
virtual dur_millis_t getPeriodicOperationFrequency() const = 0;
/**
* @brief This function will be called by the manager if an update
* notification is received.
* @details HasLocalDataPoolIF
* Can be overriden by the child class to handle changed datasets.
* @param sid SID of the updated set
* @param storeId If a snapshot was requested, data will be located inside
* the IPC store with this store ID.
* @param clearMessage If this is set to true, the pool manager will take care of
* clearing the store automatically
*/
virtual void handleChangedDataset(sid_t sid, store_address_t storeId = store_address_t::invalid(),
bool* clearMessage = nullptr) {
if (clearMessage != nullptr) {
*clearMessage = true;
}
}
/**
* @brief This function will be called by the manager if an update
* notification is received.
* @details
* Can be overriden by the child class to handle changed pool variables.
* @param gpid GPID of the updated variable.
* @param storeId If a snapshot was requested, data will be located inside
* the IPC store with this store ID.
* @param clearMessage Relevant for snapshots. If the boolean this points to is set to true,
* the pool manager will take care of clearing the store automatically
* after the callback.
*/
virtual void handleChangedPoolVariable(gp_id_t gpid,
store_address_t storeId = store_address_t::invalid(),
bool* clearMessage = nullptr) {
if (clearMessage != nullptr) {
*clearMessage = true;
}
}
/**
* These function can be implemented by pool owner, if they are required
* and used by the housekeeping message interface.
* */
virtual ReturnValue_t addDataSet(sid_t sid) { return returnvalue::FAILED; };
virtual ReturnValue_t removeDataSet(sid_t sid) { return returnvalue::FAILED; };
virtual ReturnValue_t changeCollectionInterval(sid_t sid, float newIntervalSeconds) {
return returnvalue::FAILED;
};
/**
* This function can be used by data pool consumers to retrieve a handle
* which allows subscriptions to dataset and variable updates in form of messages.
* The consumers can then read the most recent variable value by calling read with
* an own pool variable or set instance or using the deserialized snapshot data.
* Returns the HK manager casted to the required interface by default.
* @return
*/
virtual ProvidesDataPoolSubscriptionIF* getSubscriptionInterface() {
return getHkManagerHandle();
}
protected:
/**
* Every class implementing this interface should have a local data pool manager. This
* function will return a reference to the manager.
* @return
*/
virtual LocalDataPoolManager* getHkManagerHandle() = 0;
/**
* Accessor handle required for internal handling. Not intended for users and therefore
* declared protected. Users should instead use pool variables, sets or the subscription
* interface to access pool entries. Returns the HK manager casted to a different interface
* by default.
* @return
*/
virtual AccessPoolManagerIF* getAccessorHandle() { return getHkManagerHandle(); }
/**
* This function is used by the pool manager to get a valid dataset
* from a SID. This function is protected to prevent users from
* using raw data set pointers which could not be thread-safe. Users
* should use the #ProvidesDataPoolSubscriptionIF.
* @param sid Corresponding structure ID
* @return
*/
virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0;
/**
* Similar to the function above, but used to get a local pool variable
* handle. This is only needed for update notifications, so it is not
* defined as abstract. This function is protected to prevent users from
* using raw pool variable pointers which could not be thread-safe.
* Users should use the #ProvidesDataPoolSubscriptionIF.
* @param localPoolId
* @return
*/
virtual LocalPoolObjectBase* getPoolObjectHandle(lp_id_t localPoolId) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "HasLocalDataPoolIF::getPoolObjectHandle: Not overriden. "
"Returning nullptr!"
<< std::endl;
#else
sif::printWarning(
"HasLocalDataPoolIF::getPoolObjectHandle: "
"Not overriden. Returning nullptr!\n");
#endif
return nullptr;
}
};
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDATAPOOLIF_H_ */

View File

@ -1,817 +0,0 @@
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include <cmath>
#include "fsfw/datapoollocal.h"
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/housekeeping/HousekeepingSetPacket.h"
#include "fsfw/housekeeping/HousekeepingSnapshot.h"
#include "fsfw/ipc/MutexFactory.h"
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/timemanager/CCSDSTime.h"
#include "internal/HasLocalDpIFManagerAttorney.h"
#include "internal/LocalPoolDataSetAttorney.h"
// TODO: Get rid of this. This should be a constructor argument, not something hardcoded in any way
object_id_t LocalDataPoolManager::defaultHkDestination = objects::PUS_SERVICE_3_HOUSEKEEPING;
LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
bool appendValidityBuffer)
: appendValidityBuffer(appendValidityBuffer) {
if (owner == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", returnvalue::FAILED,
"Invalid supplied owner");
return;
}
this->owner = owner;
mutex = MutexFactory::instance()->createMutex();
if (mutex == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "LocalDataPoolManager", returnvalue::FAILED,
"Could not create mutex");
}
hkQueue = queueToUse;
}
LocalDataPoolManager::~LocalDataPoolManager() {
if (mutex != nullptr) {
MutexFactory::instance()->deleteMutex(mutex);
}
}
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
if (queueToUse == nullptr) {
/* Error, all destinations invalid */
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID);
}
hkQueue = queueToUse;
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore == nullptr) {
/* Error, all destinations invalid */
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", returnvalue::FAILED,
"Could not set IPC store.");
return returnvalue::FAILED;
}
if (defaultHkDestination != objects::NO_OBJECT) {
auto* hkPacketReceiver =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(defaultHkDestination);
if (hkPacketReceiver != nullptr) {
hkDestinationId = hkPacketReceiver->getHkQueue();
} else {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
}
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation() {
return initializeHousekeepingPoolEntriesOnce();
}
ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
if (not mapInitialized) {
ReturnValue_t result = owner->initializeLocalDataPool(localPoolMap, *this);
if (result == returnvalue::OK) {
mapInitialized = true;
}
return result;
}
printWarningOrError(sif::OutputTypes::OUT_WARNING, "initializeHousekeepingPoolEntriesOnce",
returnvalue::FAILED, "The map should only be initialized once");
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::performHkOperation() {
ReturnValue_t status = returnvalue::OK;
for (auto& receiver : hkReceivers) {
switch (receiver.reportingType) {
case (ReportingType::PERIODIC): {
if (receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
/* Periodic packets shall only be generated from datasets */
continue;
}
performPeriodicHkGeneration(receiver);
break;
}
case (ReportingType::UPDATE_HK): {
handleHkUpdate(receiver, status);
break;
}
case (ReportingType::UPDATE_NOTIFICATION): {
handleNotificationUpdate(receiver, status);
break;
}
case (ReportingType::UPDATE_SNAPSHOT): {
handleNotificationSnapshot(receiver, status);
break;
}
default:
// This should never happen.
return returnvalue::FAILED;
}
}
resetHkUpdateResetHelper();
return status;
}
ReturnValue_t LocalDataPoolManager::handleHkUpdate(HkReceiver& receiver, ReturnValue_t& status) {
if (receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
/* Update packets shall only be generated from datasets. */
return returnvalue::FAILED;
}
LocalPoolDataSetBase* dataSet =
HasLocalDpIFManagerAttorney::getDataSetHandle(owner, receiver.dataId.sid);
if (dataSet == nullptr) {
return DATASET_NOT_FOUND;
}
if (dataSet->hasChanged()) {
/* Prepare and send update notification */
ReturnValue_t result = generateHousekeepingPacket(receiver.dataId.sid, dataSet, true);
if (result != returnvalue::OK) {
status = result;
}
}
handleChangeResetLogic(receiver.dataType, receiver.dataId, dataSet);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receiver,
ReturnValue_t& status) {
MarkChangedIF* toReset = nullptr;
if (receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj =
HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, receiver.dataId.localPoolId);
if (poolObj == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleNotificationUpdate",
POOLOBJECT_NOT_FOUND);
return POOLOBJECT_NOT_FOUND;
}
if (poolObj->hasChanged()) {
/* Prepare and send update notification. */
CommandMessage notification;
HousekeepingMessage::setUpdateNotificationVariableCommand(
&notification, gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId));
ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, &notification);
if (result != returnvalue::OK) {
status = result;
}
toReset = poolObj;
}
} else {
LocalPoolDataSetBase* dataSet =
HasLocalDpIFManagerAttorney::getDataSetHandle(owner, receiver.dataId.sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleNotificationUpdate",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
if (dataSet->hasChanged()) {
/* Prepare and send update notification */
CommandMessage notification;
HousekeepingMessage::setUpdateNotificationSetCommand(&notification, receiver.dataId.sid);
ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, &notification);
if (result != returnvalue::OK) {
status = result;
}
toReset = dataSet;
}
}
if (toReset != nullptr) {
handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset);
}
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(HkReceiver& receiver,
ReturnValue_t& status) {
MarkChangedIF* toReset = nullptr;
/* Check whether data has changed and send messages in case it has */
if (receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj =
HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, receiver.dataId.localPoolId);
if (poolObj == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleNotificationSnapshot",
POOLOBJECT_NOT_FOUND);
return POOLOBJECT_NOT_FOUND;
}
if (not poolObj->hasChanged()) {
return returnvalue::OK;
}
/* Prepare and send update snapshot */
timeval now{};
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{};
CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, receiver.dataId.localPoolId));
store_address_t storeId;
ReturnValue_t result = addUpdateToStore(updatePacket, storeId);
if (result != returnvalue::OK) {
return result;
}
CommandMessage notification;
HousekeepingMessage::setUpdateSnapshotVariableCommand(
&notification, gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId), storeId);
result = hkQueue->sendMessage(receiver.destinationQueue, &notification);
if (result != returnvalue::OK) {
status = result;
}
toReset = poolObj;
} else {
LocalPoolDataSetBase* dataSet =
HasLocalDpIFManagerAttorney::getDataSetHandle(owner, receiver.dataId.sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleNotificationSnapshot",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
if (not dataSet->hasChanged()) {
return returnvalue::OK;
}
/* Prepare and send update snapshot */
timeval now{};
Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds{};
CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket(
reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
HasLocalDpIFManagerAttorney::getDataSetHandle(owner, receiver.dataId.sid));
store_address_t storeId;
ReturnValue_t result = addUpdateToStore(updatePacket, storeId);
if (result != returnvalue::OK) {
return result;
}
CommandMessage notification;
HousekeepingMessage::setUpdateSnapshotSetCommand(&notification, receiver.dataId.sid, storeId);
result = hkQueue->sendMessage(receiver.destinationQueue, &notification);
if (result != returnvalue::OK) {
status = result;
}
toReset = dataSet;
}
if (toReset != nullptr) {
handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset);
}
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::addUpdateToStore(HousekeepingSnapshot& updatePacket,
store_address_t& storeId) {
size_t updatePacketSize = updatePacket.getSerializedSize();
uint8_t* storePtr = nullptr;
ReturnValue_t result =
ipcStore->getFreeElement(&storeId, updatePacket.getSerializedSize(), &storePtr);
if (result != returnvalue::OK) {
return result;
}
size_t serializedSize = 0;
result = updatePacket.serialize(&storePtr, &serializedSize, updatePacketSize,
SerializeIF::Endianness::MACHINE);
return result;
;
}
void LocalDataPoolManager::handleChangeResetLogic(DataType type, DataId dataId,
MarkChangedIF* toReset) {
for (auto& changeInfo : hkUpdateResetList) {
if (changeInfo.dataType != type) {
continue;
}
if ((changeInfo.dataType == DataType::DATA_SET) and (changeInfo.dataId.sid != dataId.sid)) {
continue;
}
if ((changeInfo.dataType == DataType::LOCAL_POOL_VARIABLE) and
(changeInfo.dataId.localPoolId != dataId.localPoolId)) {
continue;
}
/* Only one update recipient, we can reset changes status immediately */
if (changeInfo.updateCounter <= 1) {
toReset->setChanged(false);
}
/* All recipients have been notified, reset the changed flag */
else if (changeInfo.currentUpdateCounter <= 1) {
toReset->setChanged(false);
changeInfo.currentUpdateCounter = 0;
}
/* Not all recipiens have been notified yet, decrement */
else {
changeInfo.currentUpdateCounter--;
}
return;
}
}
void LocalDataPoolManager::resetHkUpdateResetHelper() {
for (auto& changeInfo : hkUpdateResetList) {
changeInfo.currentUpdateCounter = changeInfo.updateCounter;
}
}
ReturnValue_t LocalDataPoolManager::subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams params) {
return subscribeForPeriodicPacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams params) {
return subscribeForPeriodicPacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(subdp::ParamsBase& params) {
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = params.sid;
hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.dataType = DataType::DATA_SET;
if (params.receiver == MessageQueueIF::NO_QUEUE) {
hkReceiver.destinationQueue = hkDestinationId;
} else {
hkReceiver.destinationQueue = params.receiver;
}
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, params.enableReporting);
LocalPoolDataSetAttorney::initializePeriodicHelper(*dataSet, params.collectionInterval,
owner->getPeriodicOperationFrequency());
}
hkReceivers.push_back(hkReceiver);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::subscribeForRegularUpdatePacket(
subdp::RegularHkUpdateParams params) {
return subscribeForUpdatePacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForDiagUpdatePacket(
subdp::DiagnosticsHkUpdateParams params) {
return subscribeForUpdatePacket(params);
}
ReturnValue_t LocalDataPoolManager::subscribeForUpdatePacket(subdp::ParamsBase& params) {
struct HkReceiver hkReceiver;
hkReceiver.dataId.sid = params.sid;
hkReceiver.reportingType = ReportingType::UPDATE_HK;
hkReceiver.dataType = DataType::DATA_SET;
if (params.receiver == MessageQueueIF::NO_QUEUE) {
hkReceiver.destinationQueue = hkDestinationId;
} else {
hkReceiver.destinationQueue = params.receiver;
}
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, params.sid);
if (dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, true);
}
hkReceivers.push_back(hkReceiver);
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::subscribeForSetUpdateMessage(const uint32_t setId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) {
struct HkReceiver hkReceiver;
hkReceiver.dataType = DataType::DATA_SET;
hkReceiver.dataId.sid = sid_t(owner->getObjectId(), setId);
hkReceiver.destinationQueue = targetQueueId;
hkReceiver.objectId = destinationObject;
if (generateSnapshot) {
hkReceiver.reportingType = ReportingType::UPDATE_SNAPSHOT;
} else {
hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION;
}
hkReceivers.push_back(hkReceiver);
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::subscribeForVariableUpdateMessage(
const lp_id_t localPoolId, object_id_t destinationObject, MessageQueueId_t targetQueueId,
bool generateSnapshot) {
struct HkReceiver hkReceiver;
hkReceiver.dataType = DataType::LOCAL_POOL_VARIABLE;
hkReceiver.dataId.localPoolId = localPoolId;
hkReceiver.destinationQueue = targetQueueId;
hkReceiver.objectId = destinationObject;
if (generateSnapshot) {
hkReceiver.reportingType = ReportingType::UPDATE_SNAPSHOT;
} else {
hkReceiver.reportingType = ReportingType::UPDATE_NOTIFICATION;
}
hkReceivers.push_back(hkReceiver);
handleHkUpdateResetListInsertion(hkReceiver.dataType, hkReceiver.dataId);
return returnvalue::OK;
}
void LocalDataPoolManager::handleHkUpdateResetListInsertion(DataType dataType, DataId dataId) {
for (auto& updateResetStruct : hkUpdateResetList) {
if (dataType == DataType::DATA_SET) {
if (updateResetStruct.dataId.sid == dataId.sid) {
updateResetStruct.updateCounter++;
updateResetStruct.currentUpdateCounter++;
return;
}
} else {
if (updateResetStruct.dataId.localPoolId == dataId.localPoolId) {
updateResetStruct.updateCounter++;
updateResetStruct.currentUpdateCounter++;
return;
}
}
}
HkUpdateResetHelper hkUpdateResetHelper;
hkUpdateResetHelper.currentUpdateCounter = 1;
hkUpdateResetHelper.updateCounter = 1;
hkUpdateResetHelper.dataType = dataType;
if (dataType == DataType::DATA_SET) {
hkUpdateResetHelper.dataId.sid = dataId.sid;
} else {
hkUpdateResetHelper.dataId.localPoolId = dataId.localPoolId;
}
hkUpdateResetList.push_back(hkUpdateResetHelper);
}
ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(CommandMessage* message) {
Command_t command = message->getCommand();
sid_t sid = HousekeepingMessage::getSid(message);
ReturnValue_t result = returnvalue::OK;
switch (command) {
// Houskeeping interface handling.
case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, true);
break;
}
case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, false);
break;
}
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
result = generateSetStructurePacket(sid);
if (result == returnvalue::OK) {
return result;
}
break;
}
case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
float newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, &newCollIntvl);
result = changeCollectionInterval(sid, newCollIntvl);
break;
}
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), dataSet, true);
}
/* Notification handling */
case (HousekeepingMessage::UPDATE_NOTIFICATION_SET): {
owner->handleChangedDataset(sid);
return returnvalue::OK;
}
case (HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): {
gp_id_t globPoolId = HousekeepingMessage::getUpdateNotificationVariableCommand(message);
owner->handleChangedPoolVariable(globPoolId);
return returnvalue::OK;
}
case (HousekeepingMessage::UPDATE_SNAPSHOT_SET): {
store_address_t storeId;
HousekeepingMessage::getUpdateSnapshotSetCommand(message, &storeId);
bool clearMessage = true;
owner->handleChangedDataset(sid, storeId, &clearMessage);
if (clearMessage) {
message->clear();
}
return returnvalue::OK;
}
case (HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): {
store_address_t storeId;
gp_id_t globPoolId = HousekeepingMessage::getUpdateSnapshotVariableCommand(message, &storeId);
bool clearMessage = true;
owner->handleChangedPoolVariable(globPoolId, storeId, &clearMessage);
if (clearMessage) {
message->clear();
}
return returnvalue::OK;
}
default:
return CommandMessageIF::UNKNOWN_COMMAND;
}
CommandMessage reply;
if (result != returnvalue::OK) {
if (result == WRONG_HK_PACKET_TYPE) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
WRONG_HK_PACKET_TYPE);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
}
hkQueue->sendMessage(hkDestinationId, &reply);
return result;
}
ReturnValue_t LocalDataPoolManager::printPoolEntry(lp_id_t localPoolId) {
auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "printPoolEntry",
localpool::POOL_ENTRY_NOT_FOUND);
return localpool::POOL_ENTRY_NOT_FOUND;
}
poolIter->second->print();
return returnvalue::OK;
}
MutexIF* LocalDataPoolManager::getMutexHandle() { return mutex; }
HasLocalDataPoolIF* LocalDataPoolManager::getOwner() { return owner; }
ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination) {
if (dataSet == nullptr) {
/* Configuration error. */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
store_address_t storeId;
HousekeepingPacketDownlink hkPacket(sid, dataSet);
size_t serializedSize = 0;
ReturnValue_t result =
serializeHkPacketIntoStore(hkPacket, storeId, forDownlink, &serializedSize);
if (result != returnvalue::OK or serializedSize == 0) {
return result;
}
/* Now we set a HK message and send it the HK packet destination. */
CommandMessage hkMessage;
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
if (hkQueue == nullptr) {
/* Error, no queue available to send packet with. */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
if (destination == MessageQueueIF::NO_QUEUE) {
if (hkDestinationId == MessageQueueIF::NO_QUEUE) {
/* Error, all destinations invalid */
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
destination = hkDestinationId;
}
return hkQueue->sendMessage(destination, &hkMessage);
}
ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(HousekeepingPacketDownlink& hkPacket,
store_address_t& storeId,
bool forDownlink,
size_t* serializedSize) {
uint8_t* dataPtr = nullptr;
const size_t maxSize = hkPacket.getSerializedSize();
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &dataPtr);
if (result != returnvalue::OK) {
return result;
}
if (forDownlink) {
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::BIG);
}
return hkPacket.serialize(&dataPtr, serializedSize, maxSize, SerializeIF::Endianness::MACHINE);
}
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid;
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "performPeriodicHkGeneration",
DATASET_NOT_FOUND);
return;
}
if (not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet)) {
return;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
if (periodicHelper == nullptr) {
/* Configuration error */
return;
}
if (not periodicHelper->checkOpNecessary()) {
return;
}
ReturnValue_t result = generateHousekeepingPacket(sid, dataSet, true);
if (result != returnvalue::OK) {
/* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed."
<< std::endl;
#else
sif::printWarning("LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
#endif
}
}
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, bool enable) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
if ((LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and enable) or
(not LocalPoolDataSetAttorney::getReportingEnabled(*dataSet) and not enable)) {
return returnvalue::OK;
}
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enable);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval) {
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "changeCollectionInterval",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
PeriodicHousekeepingHelper* periodicHelper =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
if (periodicHelper == nullptr) {
/* Configuration error, set might not have a corresponding pool manager */
return PERIODIC_HELPER_INVALID;
}
periodicHelper->changeCollectionInterval(newCollectionInterval);
return returnvalue::OK;
}
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) {
/* Get and check dataset first. */
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if (dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "performPeriodicHkGeneration",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
bool valid = dataSet->isValid();
bool reportingEnabled = LocalPoolDataSetAttorney::getReportingEnabled(*dataSet);
float collectionInterval =
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet)->getCollectionIntervalInSeconds();
// Generate set packet which can be serialized.
HousekeepingSetPacket setPacket(sid, reportingEnabled, valid, collectionInterval, dataSet);
size_t expectedSize = setPacket.getSerializedSize();
uint8_t* storePtr = nullptr;
store_address_t storeId;
ReturnValue_t result = ipcStore->getFreeElement(&storeId, expectedSize, &storePtr);
if (result != returnvalue::OK) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "generateSetStructurePacket",
returnvalue::FAILED, "Could not get free element from IPC store.");
return result;
}
// Serialize set packet into store.
size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::BIG);
if (result != returnvalue::OK) {
ipcStore->deleteData(storeId);
return result;
}
if (expectedSize != size) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
returnvalue::FAILED, "Expected size is not equal to serialized size");
}
// Send structure reporting reply.
CommandMessage reply;
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
result = hkQueue->reply(&reply);
if (result != returnvalue::OK) {
ipcStore->deleteData(storeId);
}
return result;
}
void LocalDataPoolManager::clearReceiversList() {
/* Clear the vector completely and releases allocated memory. */
HkReceivers().swap(hkReceivers);
/* Also clear the reset helper if it exists */
HkUpdateResetList().swap(hkUpdateResetList);
}
MutexIF* LocalDataPoolManager::getLocalPoolMutex() { return this->mutex; }
object_id_t LocalDataPoolManager::getCreatorObjectId() const { return owner->getObjectId(); }
void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
const char* functionName, ReturnValue_t error,
const char* errorPrint) {
#if FSFW_VERBOSE_LEVEL >= 1
if (errorPrint == nullptr) {
if (error == DATASET_NOT_FOUND) {
errorPrint = "Dataset not found";
} else if (error == POOLOBJECT_NOT_FOUND) {
errorPrint = "Pool Object not found";
} else if (error == WRONG_HK_PACKET_TYPE) {
errorPrint = "Wrong Packet Type";
} else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
} else {
errorPrint = "Generic error";
}
} else if (error == QUEUE_OR_DESTINATION_INVALID) {
errorPrint = "Queue or destination not set";
} else if (error == localpool::POOL_ENTRY_TYPE_CONFLICT) {
errorPrint = "Pool entry type conflict";
} else if (error == localpool::POOL_ENTRY_NOT_FOUND) {
errorPrint = "Pool entry not found";
} else {
errorPrint = "Unknown error";
}
}
object_id_t objectId = 0xffffffff;
if (owner != nullptr) {
objectId = owner->getObjectId();
}
if (outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID 0x" << std::setw(8)
<< std::setfill('0') << std::hex << objectId << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", functionName, objectId,
errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} else if (outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName << ": Object ID 0x" << std::setw(8)
<< std::setfill('0') << std::hex << objectId << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", functionName, objectId,
errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
#endif /* #if FSFW_VERBOSE_LEVEL >= 1 */
}
LocalDataPoolManager* LocalDataPoolManager::getPoolManagerHandle() { return this; }
void LocalDataPoolManager::setHkDestinationId(MessageQueueId_t hkDestId) {
hkDestinationId = hkDestId;
}

View File

@ -1,380 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#define FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_
#include <map>
#include <vector>
#include "AccessLocalPoolF.h"
#include "ProvidesDataPoolSubscriptionIF.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/PoolEntry.h"
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/housekeeping/HousekeepingPacketDownlink.h"
#include "fsfw/housekeeping/PeriodicHousekeepingHelper.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MutexGuard.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
namespace Factory {
void setStaticFrameworkObjectIds();
}
class LocalPoolDataSetBase;
class HousekeepingSnapshot;
class HasLocalDataPoolIF;
class LocalDataPool;
/**
* @brief This class is the managing instance for the local data pool.
* @details
* The actual data pool structure is a member of this class. Any class which
* has a local data pool shall have this manager class as a member and implement
* the HasLocalDataPoolIF.
*
* The manager offers some adaption points and functions which can be used
* by the owning class to simplify data handling significantly.
*
* Please ensure that both initialize and initializeAfterTaskCreation are
* called at some point by the owning class in the respective functions of the
* same name!
*
* Users of the data pool use the helper classes LocalDataSet,
* LocalPoolVariable and LocalPoolVector to access pool entries in
* a thread-safe and efficient way.
*
* The local data pools employ a blackboard logic: Only the most recent
* value is stored. The helper classes offer a read() and commit() interface
* through the PoolVariableIF which is used to read and update values.
* Each pool entry has a valid state too.
* @author R. Mueller
*/
class LocalDataPoolManager : public ProvidesDataPoolSubscriptionIF, public AccessPoolManagerIF {
friend void(Factory::setStaticFrameworkObjectIds)();
//! Some classes using the pool manager directly need to access class internals of the
//! manager. The attorney provides granular control of access to these internals.
friend class LocalDpManagerAttorney;
public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t WRONG_HK_PACKET_TYPE = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t REPORTING_STATUS_UNCHANGED = MAKE_RETURN_CODE(2);
static constexpr ReturnValue_t PERIODIC_HELPER_INVALID = MAKE_RETURN_CODE(3);
static constexpr ReturnValue_t POOLOBJECT_NOT_FOUND = MAKE_RETURN_CODE(4);
static constexpr ReturnValue_t DATASET_NOT_FOUND = MAKE_RETURN_CODE(5);
/**
* This constructor is used by a class which wants to implement
* a personal local data pool. The queueToUse can be supplied if it
* is already known.
*
* initialize() has to be called in any case before using the object!
* @param owner
* @param queueToUse
* @param appendValidityBuffer Specify whether a buffer containing the
* validity state is generated when serializing or deserializing packets.
*/
LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse,
bool appendValidityBuffer = true);
~LocalDataPoolManager() override;
void setHkDestinationId(MessageQueueId_t hkDestId);
/**
* Assigns the queue to use. Make sure to call this in the #initialize
* function of the owner.
* @param queueToUse
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
* @return
*/
ReturnValue_t initialize(MessageQueueIF* queueToUse);
/**
* Initializes the map by calling the map initialization function and
* setting the periodic factor for non-diagnostic packets.
* Don't forget to call this in the #initializeAfterTaskCreation call of
* the owner, otherwise the map will be invalid!
* @param nonDiagInvlFactor
* @return
*/
ReturnValue_t initializeAfterTaskCreation();
/**
* @brief This should be called in the periodic handler of the owner.
* @details
* This in generally called in the #performOperation function of the owner.
* It performs all the periodic functionalities of the data pool manager,
* for example generating periodic HK packets.
* Marked virtual as an adaption point for custom data pool managers.
* @return
*/
virtual ReturnValue_t performHkOperation();
/**
* @brief Subscribe for a notification message which will be sent
* if a dataset has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param setId Set ID of the set to receive update messages from.
* @param destinationObject
* @param targetQueueId
* @param generateSnapshot If this is set to true, a copy of the current
* data with a timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent.
* @return
*/
ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
/**
* @brief Subscribe for an notification message which will be sent if a
* pool variable has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param localPoolId Pool ID of the pool variable
* @param destinationObject
* @param targetQueueId
* @param generateSnapshot If this is set to true, a copy of the current
* data with a timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent.
* @return
*/
ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) override;
/**
* @brief The manager is also able to handle housekeeping messages.
* @details
* This most commonly is used to handle messages for the housekeeping
* interface, but the manager is also able to handle update notifications
* and calls a special function which can be overriden by a child class
* to handle data set or pool variable updates. This is relevant
* for classes like controllers which have their own local datapool
* but pull their data from other local datapools.
* @param message
* @return
*/
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
/**
* Generate a housekeeping packet with a given SID.
* @param sid
* @return
*/
ReturnValue_t generateHousekeepingPacket(sid_t sid, LocalPoolDataSetBase* dataSet,
bool forDownlink,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t changeCollectionInterval(sid_t sid, float newCollectionInterval);
HasLocalDataPoolIF* getOwner();
ReturnValue_t printPoolEntry(lp_id_t localPoolId);
/**
* Different types of housekeeping reporting are possible.
* 1. PERIODIC:
* HK packets are generated in fixed intervals and sent to
* destination. Fromat will be raw.
* 2. UPDATE_NOTIFICATION:
* Notification will be sent out if HK data has changed.
* 3. UPDATE_SNAPSHOT:
* HK packets are only generated if explicitely requested.
* Propably not necessary, just use multiple local data sets or
* shared datasets.
*/
enum class ReportingType : uint8_t {
//! Periodic generation of HK packets.
PERIODIC,
//! Housekeeping packet will be generated if values have changed.
UPDATE_HK,
//! Update notification will be sent out as message.
UPDATE_NOTIFICATION,
//! Notification will be sent out as message and a snapshot of the
//! current data will be generated.
UPDATE_SNAPSHOT,
};
/** Different data types are possible in the HK receiver map. For example, updates can be
requested for full datasets or for single pool variables. Periodic reporting is only possible
for data sets. */
enum class DataType : uint8_t { LOCAL_POOL_VARIABLE, DATA_SET };
/* Copying forbidden */
LocalDataPoolManager(const LocalDataPoolManager&) = delete;
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
/**
* This function can be used to clear the receivers list. This is
* intended for test functions and not for regular operations, because
* the insertion operations allocate dynamically.
*/
void clearReceiversList();
[[nodiscard]] object_id_t getCreatorObjectId() const;
/**
* Get the pointer to the mutex. Can be used to lock the data pool
* externally. Use with care and don't forget to unlock locked mutexes!
* For now, only friend classes can accss this function.
* @return
*/
MutexIF* getMutexHandle();
LocalDataPoolManager* getPoolManagerHandle() override;
ReturnValue_t subscribeForRegularPeriodicPacket(subdp::RegularHkPeriodicParams params) override;
ReturnValue_t subscribeForDiagPeriodicPacket(subdp::DiagnosticsHkPeriodicParams params) override;
ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) override;
ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) override;
protected:
ReturnValue_t subscribeForPeriodicPacket(subdp::ParamsBase& params);
ReturnValue_t subscribeForUpdatePacket(subdp::ParamsBase& params);
/** Core data structure for the actual pool data */
localpool::DataPool localPoolMap;
/** Every housekeeping data manager has a mutex to protect access
to it's data pool. */
MutexIF* mutex = nullptr;
/** The class which actually owns the manager (and its datapool). */
HasLocalDataPoolIF* owner = nullptr;
uint8_t nonDiagnosticIntervalFactor = 0;
/** Default receiver for periodic HK packets */
static object_id_t defaultHkDestination;
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
union DataId {
DataId() : sid() {};
sid_t sid;
lp_id_t localPoolId;
};
/** The data pool manager will keep an internal map of HK receivers. */
struct HkReceiver {
/** Object ID of receiver */
object_id_t objectId = objects::NO_OBJECT;
DataType dataType = DataType::DATA_SET;
DataId dataId;
ReportingType reportingType = ReportingType::PERIODIC;
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
};
/** This vector will contain the list of HK receivers. */
using HkReceivers = std::vector<struct HkReceiver>;
HkReceivers hkReceivers;
struct HkUpdateResetHelper {
DataType dataType = DataType::DATA_SET;
DataId dataId;
uint8_t updateCounter;
uint8_t currentUpdateCounter;
};
using HkUpdateResetList = std::vector<struct HkUpdateResetHelper>;
/** This list is used to manage creating multiple update packets and only resetting
the update flag if all of them were created. */
HkUpdateResetList hkUpdateResetList = HkUpdateResetList();
/** This is the map holding the actual data. Should only be initialized
* once ! */
bool mapInitialized = false;
/** This specifies whether a validity buffer is appended at the end
* of generated housekeeping packets. */
bool appendValidityBuffer = true;
/**
* @brief Queue used for communication, for example commands.
* Is also used to send messages. Can be set either in the constructor
* or in the initialize() function.
*/
MessageQueueIF* hkQueue = nullptr;
/** Global IPC store is used to store all packets. */
StorageManagerIF* ipcStore = nullptr;
/**
* Read a variable by supplying its local pool ID and assign the pool
* entry to the supplied PoolEntry pointer. The type of the pool entry
* is deduced automatically. This call is not thread-safe!
* For now, only classes designated by the LocalDpManagerAttorney may use this function.
* @tparam T Type of the pool entry
* @param localPoolId Pool ID of the variable to read
* @param poolVar [out] Corresponding pool entry will be assigned to the
* supplied pointer.
* @return
*/
template <class T>
ReturnValue_t fetchPoolEntry(lp_id_t localPoolId, PoolEntry<T>** poolEntry);
/**
* This function is used to fill the local data pool map with pool
* entries. It should only be called once by the pool owner.
* @param localDataPoolMap
* @return
*/
ReturnValue_t initializeHousekeepingPoolEntriesOnce();
MutexIF* getLocalPoolMutex() override;
ReturnValue_t serializeHkPacketIntoStore(HousekeepingPacketDownlink& hkPacket,
store_address_t& storeId, bool forDownlink,
size_t* serializedSize);
void performPeriodicHkGeneration(HkReceiver& hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable);
ReturnValue_t generateSetStructurePacket(sid_t sid);
void handleHkUpdateResetListInsertion(DataType dataType, DataId dataId);
void handleChangeResetLogic(DataType type, DataId dataId, MarkChangedIF* toReset);
void resetHkUpdateResetHelper();
ReturnValue_t handleHkUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
ReturnValue_t handleNotificationUpdate(HkReceiver& hkReceiver, ReturnValue_t& status);
ReturnValue_t handleNotificationSnapshot(HkReceiver& hkReceiver, ReturnValue_t& status);
ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket, store_address_t& storeId);
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char* errorPrint = nullptr);
};
template <class T>
inline ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId,
PoolEntry<T>** poolEntry) {
if (poolEntry == nullptr) {
return returnvalue::FAILED;
}
auto poolIter = localPoolMap.find(localPoolId);
if (poolIter == localPoolMap.end()) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
localpool::POOL_ENTRY_NOT_FOUND);
return localpool::POOL_ENTRY_NOT_FOUND;
}
*poolEntry = dynamic_cast<PoolEntry<T>*>(poolIter->second);
if (*poolEntry == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "fetchPoolEntry",
localpool::POOL_ENTRY_TYPE_CONFLICT);
return localpool::POOL_ENTRY_TYPE_CONFLICT;
}
return returnvalue::OK;
}
#endif /* FSFW_DATAPOOLLOCAL_LOCALDATAPOOLMANAGER_H_ */

View File

@ -1,21 +0,0 @@
#include "fsfw/datapoollocal/LocalDataSet.h"
#include <cmath>
#include <cstring>
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/serialize/SerializeAdapter.h"
LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, uint32_t setId,
const size_t maxNumberOfVariables)
: LocalPoolDataSetBase(hkOwner, setId, nullptr, maxNumberOfVariables),
poolVarList(maxNumberOfVariables) {
this->setContainer(poolVarList.data());
}
LocalDataSet::LocalDataSet(sid_t sid, const size_t maxNumberOfVariables)
: LocalPoolDataSetBase(sid, nullptr, maxNumberOfVariables), poolVarList(maxNumberOfVariables) {
this->setContainer(poolVarList.data());
}
LocalDataSet::~LocalDataSet() {}

View File

@ -1,291 +0,0 @@
#include <cmath>
#include <cstring>
#include "fsfw/datapoollocal.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/globalfunctions/bitutility.h"
#include "fsfw/housekeeping/PeriodicHousekeepingHelper.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/serialize/SerializeAdapter.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "internal/HasLocalDpIFUserAttorney.h"
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, uint32_t setId,
PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables, bool periodicHandling)
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
if (hkOwner == nullptr) {
// Configuration error.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
#else
sif::printError(
"LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
"invalid!\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return;
}
AccessPoolManagerIF *accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if (accessor != nullptr) {
poolManager = accessor->getPoolManagerHandle();
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
}
this->sid.objectId = hkOwner->getObjectId();
this->sid.ownerSetId = setId;
/* Data creators get a periodic helper for periodic HK data generation. */
if (periodicHandling) {
periodicHelper = new PeriodicHousekeepingHelper(this);
}
}
LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid, PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables)
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
HasLocalDataPoolIF *hkOwner = ObjectManager::instance()->get<HasLocalDataPoolIF>(sid.objectId);
if (hkOwner != nullptr) {
AccessPoolManagerIF *accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if (accessor != nullptr) {
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
poolManager = accessor->getPoolManagerHandle();
}
}
this->sid = sid;
}
LocalPoolDataSetBase::LocalPoolDataSetBase(PoolVariableIF **registeredVariablesArray,
const size_t maxNumberOfVariables,
bool protectEveryReadCommitCall)
: PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
this->setReadCommitProtectionBehaviour(protectEveryReadCommitCall);
}
LocalPoolDataSetBase::~LocalPoolDataSetBase() {
/* We only delete objects which were created in the class constructor */
if (periodicHelper != nullptr) {
delete periodicHelper;
}
/* In case set was read but not comitted, we commit all variables with an invalid state */
if (state == States::STATE_SET_WAS_READ) {
for (uint16_t count = 0; count < fillCount; count++) {
if (registeredVariables[count] != nullptr) {
registeredVariables[count]->setValid(false);
registeredVariables[count]->commit(MutexIF::TimeoutType::WAITING, 20);
}
}
}
}
ReturnValue_t LocalPoolDataSetBase::lockDataPool(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
if (mutexIfSingleDataCreator != nullptr) {
return mutexIfSingleDataCreator->lockMutex(timeoutType, timeoutMs);
}
return returnvalue::OK;
}
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(
uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = returnvalue::OK;
const uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
uint8_t *validityPtr = nullptr;
#if defined(_MSC_VER) || defined(__clang__)
// Use a std::vector here because MSVC will (rightly) not create a fixed size array
// with a non constant size specifier. The Apple compiler (LLVM) will not accept
// the initialization of a variable sized array
std::vector<uint8_t> validityMask(validityMaskSize, 0);
validityPtr = validityMask.data();
#else
uint8_t validityMask[validityMaskSize] = {};
validityPtr = validityMask;
#endif
uint8_t validBufferIndex = 0;
uint8_t validBufferIndexBit = 0;
for (uint16_t count = 0; count < fillCount; count++) {
if (registeredVariables[count]->isValid()) {
/* Set bit at correct position */
bitutil::set(validityPtr + validBufferIndex, validBufferIndexBit);
}
if (validBufferIndexBit == 7) {
validBufferIndex++;
validBufferIndexBit = 0;
} else {
validBufferIndexBit++;
}
result = registeredVariables[count]->serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
}
if (*size + validityMaskSize > maxSize) {
return SerializeIF::BUFFER_TOO_SHORT;
}
// copy validity buffer to end
std::memcpy(*buffer, validityPtr, validityMaskSize);
*size += validityMaskSize;
return result;
}
ReturnValue_t LocalPoolDataSetBase::deSerializeWithValidityBuffer(
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;
}
}
if (*size < std::ceil(static_cast<float>(fillCount) / 8.0)) {
return SerializeIF::STREAM_TOO_SHORT;
}
uint8_t validBufferIndex = 0;
uint8_t validBufferIndexBit = 0;
for (uint16_t count = 0; count < fillCount; count++) {
// set validity buffer here.
bool nextVarValid = false;
bitutil::get(*buffer + validBufferIndex, validBufferIndexBit, nextVarValid);
registeredVariables[count]->setValid(nextVarValid);
if (validBufferIndexBit == 7) {
validBufferIndex++;
validBufferIndexBit = 0;
} else {
validBufferIndexBit++;
}
}
return result;
}
ReturnValue_t LocalPoolDataSetBase::unlockDataPool() {
if (mutexIfSingleDataCreator != nullptr) {
return mutexIfSingleDataCreator->unlockMutex();
}
return returnvalue::OK;
}
ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t **buffer, size_t *size,
size_t maxSize,
SerializeIF::Endianness streamEndianness,
bool serializeFillCount) const {
/* Serialize fill count as uint8_t */
uint8_t fillCount = this->fillCount;
if (serializeFillCount) {
SerializeAdapter::serialize(&fillCount, buffer, size, maxSize, streamEndianness);
}
for (uint16_t count = 0; count < fillCount; count++) {
lp_id_t currentPoolId = registeredVariables[count]->getDataPoolId();
auto result =
SerializeAdapter::serialize(&currentPoolId, buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolDataSetBase::serializeLocalPoolIds: "
<< "Serialization error!" << std::endl;
#else
sif::printWarning(
"LocalPoolDataSetBase::serializeLocalPoolIds: "
"Serialization error!\n\r");
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
return result;
}
}
return returnvalue::OK;
}
uint8_t LocalPoolDataSetBase::getLocalPoolIdsSerializedSize(bool serializeFillCount) const {
if (serializeFillCount) {
return fillCount * sizeof(lp_id_t) + sizeof(uint8_t);
} else {
return fillCount * sizeof(lp_id_t);
}
}
size_t LocalPoolDataSetBase::getSerializedSize() const {
if (withValidityBuffer) {
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount) / 8.0);
return validityMaskSize + PoolDataSetBase::getSerializedSize();
} else {
return PoolDataSetBase::getSerializedSize();
}
}
void LocalPoolDataSetBase::setValidityBufferGeneration(bool withValidityBuffer) {
this->withValidityBuffer = withValidityBuffer;
}
ReturnValue_t LocalPoolDataSetBase::deSerialize(const uint8_t **buffer, size_t *size,
SerializeIF::Endianness streamEndianness) {
if (withValidityBuffer) {
return this->deSerializeWithValidityBuffer(buffer, size, streamEndianness);
} else {
return PoolDataSetBase::deSerialize(buffer, size, streamEndianness);
}
}
ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
if (withValidityBuffer) {
return this->serializeWithValidityBuffer(buffer, size, maxSize, streamEndianness);
} else {
return PoolDataSetBase::serialize(buffer, size, maxSize, streamEndianness);
}
}
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
this->reportingEnabled = reportingEnabled;
}
bool LocalPoolDataSetBase::getReportingEnabled() const { return reportingEnabled; }
void LocalPoolDataSetBase::initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval);
}
void LocalPoolDataSetBase::setChanged(bool changed) { this->changed = changed; }
bool LocalPoolDataSetBase::hasChanged() const { return changed; }
sid_t LocalPoolDataSetBase::getSid() const { return sid; }
bool LocalPoolDataSetBase::isValid() const { return this->valid; }
void LocalPoolDataSetBase::setValidity(bool valid, bool setEntriesRecursively) {
if (setEntriesRecursively) {
for (size_t idx = 0; idx < this->getFillCount(); idx++) {
registeredVariables[idx]->setValid(valid);
}
}
this->valid = valid;
}
object_id_t LocalPoolDataSetBase::getCreatorObjectId() {
if (poolManager != nullptr) {
return poolManager->getCreatorObjectId();
}
return objects::NO_OBJECT;
}
void LocalPoolDataSetBase::setAllVariablesReadOnly() {
for (size_t idx = 0; idx < this->getFillCount(); idx++) {
registeredVariables[idx]->setReadWriteMode(pool_rwm_t::VAR_READ);
}
}
float LocalPoolDataSetBase::getCollectionInterval() const {
if (periodicHelper != nullptr) {
return periodicHelper->getCollectionIntervalInSeconds();
} else {
return 0.0;
}
}
void LocalPoolDataSetBase::printSet() { return; }

View File

@ -1,68 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_
#include "MarkChangedIF.h"
#include "fsfw/datapool/PoolVariableIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "localPoolDefinitions.h"
class LocalDataPoolManager;
class DataSetIF;
class HasLocalDataPoolIF;
/**
* @brief This class serves as a non-template base for pool objects like pool variables
* or pool vectors.
*/
class LocalPoolObjectBase : public PoolVariableIF, public MarkChangedIF {
public:
LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode);
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
void setReadWriteMode(pool_rwm_t newReadWriteMode) override;
pool_rwm_t getReadWriteMode() const override;
bool isValid() const override;
void setValid(bool valid) override;
void setChanged(bool changed) override;
bool hasChanged() const override;
lp_id_t getDataPoolId() const override;
void setDataPoolId(lp_id_t poolId);
protected:
/**
* @brief To access the correct data pool entry on read and commit calls,
* the data pool id is stored.
*/
uint32_t localPoolId = PoolVariableIF::NO_PARAMETER;
/**
* @brief The valid information as it was stored in the data pool
* is copied to this attribute.
*/
bool valid = false;
/**
* @brief A local pool variable can be marked as changed.
*/
bool changed = false;
/**
* @brief The information whether the class is read-write or
* read-only is stored here.
*/
ReadWriteMode_t readWriteMode = pool_rwm_t::VAR_READ_WRITE;
//! @brief Pointer to the class which manages the HK pool.
LocalDataPoolManager* hkManager = nullptr;
void reportReadCommitError(const char* variableType, ReturnValue_t error, bool read,
object_id_t objectId, lp_id_t lpId);
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLOBJECTBASE_H_ */

View File

@ -1,197 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#include "../datapool/DataSetIF.h"
#include "../datapool/PoolVariableIF.h"
#include "../objectmanager/ObjectManagerIF.h"
#include "../serialize/SerializeAdapter.h"
#include "../serviceinterface/ServiceInterface.h"
#include "AccessLocalPoolF.h"
#include "HasLocalDataPoolIF.h"
#include "LocalDataPoolManager.h"
#include "LocalPoolObjectBase.h"
#include "internal/LocalDpManagerAttorney.h"
/**
* @brief Local Pool Variable class which is used to access the local pools.
* @details
* This class is not stored in the map. Instead, it is used to access
* the pool entries by using a pointer to the map storing the pool
* entries. It can also be used to organize these pool entries into data sets.
*
* @tparam T The template parameter sets the type of the variable. Currently,
* all plain data types are supported, but in principle any type is possible.
* @ingroup data_pool
*/
template <typename T>
class LocalPoolVariable : public LocalPoolObjectBase {
public:
//! Default ctor is forbidden.
LocalPoolVariable() = delete;
/**
* This constructor is used by the data creators to have pool variable
* instances which can also be stored in datasets.
*
* It does not fetch the current value from the data pool, which
* has to be done by calling the read() operation.
* Datasets can be used to access multiple local pool entries in an
* efficient way. A pointer to a dataset can be passed to register
* the pool variable in that dataset directly.
* @param poolId ID of the local pool entry.
* @param hkOwner Pointer of the owner. This will generally be the calling
* class itself which passes "this".
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*/
LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/**
* This constructor is used by data users like controllers to have
* access to the local pool variables of data creators by supplying
* the respective creator object ID.
*
* It does not fetch the current value from the data pool, which
* has to be done by calling the read() operation.
* Datasets can be used to access multiple local pool entries in an
* efficient way. A pointer to a dataset can be passed to register
* the pool variable in that dataset directly.
* @param poolId ID of the local pool entry.
* @param hkOwner object ID of the pool owner.
* @param dataSet The data set in which the variable shall register itself.
* If nullptr, the variable is not registered.
* @param setReadWriteMode Specify the read-write mode of the pool variable.
*
*/
LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
/**
* Variation which takes the global unique identifier of a pool variable.
* @param globalPoolId
* @param dataSet
* @param setReadWriteMode
*/
LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
virtual ~LocalPoolVariable() {};
/**
* @brief This is the local copy of the data pool entry.
* @details The user can work on this attribute
* just like he would on a simple local variable.
*/
T value = 0;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override;
size_t getSerializedSize() const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) override;
/**
* @brief This is a call to read the array's values
* from the global data pool.
* @details
* When executed, this operation tries to fetch the pool entry with matching
* data pool id from the data pool and copies all array values and the valid
* information to its local attributes.
* In case of a failure (wrong type, size or pool id not found), the
* variable is set to zero and invalid.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*
*/
ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief The commit call copies the array values back to the data pool.
* @details
* It checks type and size, as well as if the variable is writable. If so,
* the value is copied and the local valid flag is written back as well.
* The read call is protected with a lock.
* It is recommended to use DataSets to read and commit multiple variables
* at once to avoid the overhead of unnecessary lock und unlock operations.
*/
ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20) override;
/**
* @brief This commit function can be used to set the pool variable valid
* as well.
* @param setValid
* @param timeoutType
* @param timeoutMs
* @return
*/
ReturnValue_t commit(bool setValid,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t timeoutMs = 20);
LocalPoolVariable<T>& operator=(const T& newValue);
LocalPoolVariable<T>& operator=(const LocalPoolVariable<T>& newPoolVariable);
//! Explicit type conversion operator. Allows casting the class to
//! its template type to perform operations on value.
explicit operator T() const;
bool operator==(const LocalPoolVariable<T>& other) const;
bool operator==(const T& other) const;
bool operator!=(const LocalPoolVariable<T>& other) const;
bool operator!=(const T& other) const;
bool operator<(const LocalPoolVariable<T>& other) const;
bool operator<(const T& other) const;
bool operator>(const LocalPoolVariable<T>& other) const;
bool operator>(const T& other) const;
protected:
/**
* @brief Like #read, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t readWithoutLock() override;
/**
* @brief Like #commit, but without a lock protection of the global pool.
* @details
* The operation does NOT provide any mutual exclusive protection by itself.
* This can be used if the lock is handled externally to avoid the overhead
* of consecutive lock und unlock operations.
* Declared protected to discourage free public usage.
*/
ReturnValue_t commitWithoutLock() override;
#if FSFW_CPP_OSTREAM_ENABLED == 1
// std::ostream is the type for object std::cout
template <typename U>
friend std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<U>& var);
#endif
};
#include "LocalPoolVariable.tpp"
template <class T>
using lp_var_t = LocalPoolVariable<T>;
using lp_bool_t = LocalPoolVariable<uint8_t>;
using lp_uint8_t = LocalPoolVariable<uint8_t>;
using lp_uint16_t = LocalPoolVariable<uint16_t>;
using lp_uint32_t = LocalPoolVariable<uint32_t>;
using lp_uint64_t = LocalPoolVariable<uint64_t>;
using lp_int8_t = LocalPoolVariable<int8_t>;
using lp_int16_t = LocalPoolVariable<int16_t>;
using lp_int32_t = LocalPoolVariable<int32_t>;
using lp_int64_t = LocalPoolVariable<int64_t>;
using lp_float_t = LocalPoolVariable<float>;
using lp_double_t = LocalPoolVariable<double>;
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_ */

View File

@ -1,193 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_H_
#error Include LocalPoolVariable.h before LocalPoolVariable.tpp!
#endif
template <typename T>
inline LocalPoolVariable<T>::LocalPoolVariable(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
template <typename T>
inline LocalPoolVariable<T>::LocalPoolVariable(object_id_t poolOwner, lp_id_t poolId,
DataSetIF* dataSet, pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
template <typename T>
inline LocalPoolVariable<T>::LocalPoolVariable(gp_id_t globalPoolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
setReadWriteMode) {}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::read(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
if (hkManager == nullptr) {
return readWithoutLock();
}
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
return result;
}
result = readWithoutLock();
mutex->unlockMutex();
return result;
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::readWithoutLock() {
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
targetObjectId, localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result =
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
if (result != returnvalue::OK) {
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
return result;
}
this->value = *(poolEntry->getDataPtr());
this->valid = poolEntry->getValid();
return returnvalue::OK;
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::commit(bool setValid, MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
this->setValid(setValid);
return commit(timeoutType, timeoutMs);
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::commit(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
if (hkManager == nullptr) {
return commitWithoutLock();
}
MutexIF* mutex = LocalDpManagerAttorney::getMutexHandle(*hkManager);
ReturnValue_t result = mutex->lockMutex(timeoutType, timeoutMs);
if (result != returnvalue::OK) {
return result;
}
result = commitWithoutLock();
mutex->unlockMutex();
return result;
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::commitWithoutLock() {
if (readWriteMode == pool_rwm_t::VAR_READ) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
targetObjectId, localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result =
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
if (result != returnvalue::OK) {
object_id_t ownerObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVariable", result, false, ownerObjectId, localPoolId);
return result;
}
*(poolEntry->getDataPtr()) = this->value;
poolEntry->setValid(this->valid);
return returnvalue::OK;
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::serialize(
uint8_t** buffer, size_t* size, const size_t max_size,
SerializeIF::Endianness streamEndianness) const {
return SerializeAdapter::serialize(&value, buffer, size, max_size, streamEndianness);
}
template <typename T>
inline size_t LocalPoolVariable<T>::getSerializedSize() const {
return SerializeAdapter::getSerializedSize(&value);
}
template <typename T>
inline ReturnValue_t LocalPoolVariable<T>::deSerialize(const uint8_t** buffer, size_t* size,
SerializeIF::Endianness streamEndianness) {
return SerializeAdapter::deSerialize(&value, buffer, size, streamEndianness);
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
template <typename T>
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVariable<T>& var) {
out << var.value;
return out;
}
#endif
template <typename T>
inline LocalPoolVariable<T>::operator T() const {
return value;
}
template <typename T>
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(const T& newValue) {
value = newValue;
return *this;
}
template <typename T>
inline LocalPoolVariable<T>& LocalPoolVariable<T>::operator=(
const LocalPoolVariable<T>& newPoolVariable) {
value = newPoolVariable.value;
return *this;
}
template <typename T>
inline bool LocalPoolVariable<T>::operator==(const LocalPoolVariable<T>& other) const {
return this->value == other.value;
}
template <typename T>
inline bool LocalPoolVariable<T>::operator==(const T& other) const {
return this->value == other;
}
template <typename T>
inline bool LocalPoolVariable<T>::operator!=(const LocalPoolVariable<T>& other) const {
return not(*this == other);
}
template <typename T>
inline bool LocalPoolVariable<T>::operator!=(const T& other) const {
return not(*this == other);
}
template <typename T>
inline bool LocalPoolVariable<T>::operator<(const LocalPoolVariable<T>& other) const {
return this->value < other.value;
}
template <typename T>
inline bool LocalPoolVariable<T>::operator<(const T& other) const {
return this->value < other;
}
template <typename T>
inline bool LocalPoolVariable<T>::operator>(const LocalPoolVariable<T>& other) const {
return not(*this < other);
}
template <typename T>
inline bool LocalPoolVariable<T>::operator>(const T& other) const {
return not(*this < other);
}
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVARIABLE_TPP_ */

View File

@ -1,177 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_H_
#error Include LocalPoolVector.h before LocalPoolVector.tpp!
#endif
template <typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(HasLocalDataPoolIF* hkOwner, lp_id_t poolId,
DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(poolId, hkOwner, dataSet, setReadWriteMode) {}
template <typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(object_id_t poolOwner, lp_id_t poolId,
DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(poolOwner, poolId, dataSet, setReadWriteMode) {}
template <typename T, uint16_t vectorSize>
inline LocalPoolVector<T, vectorSize>::LocalPoolVector(gp_id_t globalPoolId, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode)
: LocalPoolObjectBase(globalPoolId.objectId, globalPoolId.localPoolId, dataSet,
setReadWriteMode) {}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::read(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
return readWithoutLock();
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::readWithoutLock() {
if (readWriteMode == pool_rwm_t::VAR_WRITE) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, true,
targetObjectId, localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result =
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
memset(this->value, 0, vectorSize * sizeof(T));
if (result != returnvalue::OK) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", result, true, targetObjectId, localPoolId);
return result;
}
std::memcpy(this->value, poolEntry->getDataPtr(), poolEntry->getByteSize());
this->valid = poolEntry->getValid();
return returnvalue::OK;
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(bool valid,
MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
this->setValid(valid);
return commit(timeoutType, timeoutMs);
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commit(MutexIF::TimeoutType timeoutType,
uint32_t timeoutMs) {
MutexGuard(LocalDpManagerAttorney::getMutexHandle(*hkManager), timeoutType, timeoutMs);
return commitWithoutLock();
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::commitWithoutLock() {
if (readWriteMode == pool_rwm_t::VAR_READ) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", PoolVariableIF::INVALID_READ_WRITE_MODE, false,
targetObjectId, localPoolId);
return PoolVariableIF::INVALID_READ_WRITE_MODE;
}
PoolEntry<T>* poolEntry = nullptr;
ReturnValue_t result =
LocalDpManagerAttorney::fetchPoolEntry(*hkManager, localPoolId, &poolEntry);
if (result != returnvalue::OK) {
object_id_t targetObjectId = hkManager->getCreatorObjectId();
reportReadCommitError("LocalPoolVector", result, false, targetObjectId, localPoolId);
return result;
}
std::memcpy(poolEntry->getDataPtr(), this->value, poolEntry->getByteSize());
poolEntry->setValid(this->valid);
return returnvalue::OK;
}
template <typename T, uint16_t vectorSize>
inline T& LocalPoolVector<T, vectorSize>::operator[](size_t i) {
if (i < vectorSize) {
return value[i];
}
// If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
" last value!"
<< std::endl;
#else
sif::printWarning(
"LocalPoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif
return value[vectorSize - 1];
}
template <typename T, uint16_t vectorSize>
inline const T& LocalPoolVector<T, vectorSize>::operator[](size_t i) const {
if (i < vectorSize) {
return value[i];
}
// If this happens, I have to set some value. I consider this
// a configuration error, but I wont exit here.
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalPoolVector: Invalid index. Setting or returning"
" last value!"
<< std::endl;
#else
sif::printWarning(
"LocalPoolVector: Invalid index. Setting or returning"
" last value!\n");
#endif
return value[vectorSize - 1];
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::serialize(
uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t i = 0; i < vectorSize; i++) {
result = SerializeAdapter::serialize(&(value[i]), buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
break;
}
}
return result;
}
template <typename T, uint16_t vectorSize>
inline size_t LocalPoolVector<T, vectorSize>::getSerializedSize() const {
return vectorSize * SerializeAdapter::getSerializedSize(value);
}
template <typename T, uint16_t vectorSize>
inline ReturnValue_t LocalPoolVector<T, vectorSize>::deSerialize(
const uint8_t** buffer, size_t* size, SerializeIF::Endianness streamEndianness) {
ReturnValue_t result = returnvalue::FAILED;
for (uint16_t i = 0; i < vectorSize; i++) {
result = SerializeAdapter::deSerialize(&(value[i]), buffer, size, streamEndianness);
if (result != returnvalue::OK) {
break;
}
}
return result;
}
#if FSFW_CPP_OSTREAM_ENABLED == 1
template <typename T, uint16_t vectorSize>
inline std::ostream& operator<<(std::ostream& out, const LocalPoolVector<T, vectorSize>& var) {
out << "Vector: [";
for (int i = 0; i < vectorSize; i++) {
out << var.value[i];
if (i < vectorSize - 1) {
out << ", ";
}
}
out << "]";
return out;
}
#endif
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLVECTOR_TPP_ */

View File

@ -1,152 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#define FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/messageQueueDefinitions.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "localPoolDefinitions.h"
namespace subdp {
struct ParamsBase {
ParamsBase(sid_t sid, bool enableReporting, float collectionInterval, bool diagnostics)
: sid(sid),
enableReporting(enableReporting),
collectionInterval(collectionInterval),
diagnostics(diagnostics) {}
[[nodiscard]] bool isDiagnostics() const { return diagnostics; }
sid_t sid;
bool enableReporting;
float collectionInterval;
MessageQueueId_t receiver = MessageQueueIF::NO_QUEUE;
protected:
bool diagnostics;
};
struct RegularHkPeriodicParams : public ParamsBase {
RegularHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval)
: ParamsBase(sid, enableReporting, collectionInterval, false) {}
};
struct DiagnosticsHkPeriodicParams : public ParamsBase {
DiagnosticsHkPeriodicParams(sid_t sid, bool enableReporting, float collectionInterval)
: ParamsBase(sid, enableReporting, collectionInterval, true) {}
};
struct RegularHkUpdateParams : public ParamsBase {
RegularHkUpdateParams(sid_t sid, bool enableReporting)
: ParamsBase(sid, enableReporting, 0.0, false) {}
};
struct DiagnosticsHkUpdateParams : public ParamsBase {
DiagnosticsHkUpdateParams(sid_t sid, bool enableReporting)
: ParamsBase(sid, enableReporting, 0.0, true) {}
};
} // namespace subdp
class ProvidesDataPoolSubscriptionIF {
public:
virtual ~ProvidesDataPoolSubscriptionIF() = default;
/**
* @brief Subscribe for the generation of periodic packets. Used for regular HK packets
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
virtual ReturnValue_t subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams params) = 0;
/**
* @brief Subscribe for the generation of periodic packets. Used for diagnostic packets
* @details
* This subscription mechanism will generally be used by the data creator
* to generate housekeeping packets which are downlinked directly.
* @return
*/
virtual ReturnValue_t subscribeForDiagPeriodicPacket(
subdp::DiagnosticsHkPeriodicParams params) = 0;
[[deprecated(
"Please use the new API which takes all arguments as one wrapper "
"struct")]] virtual ReturnValue_t
subscribeForPeriodicPacket(sid_t sid, bool enableReporting, float collectionInterval,
bool isDiagnostics,
object_id_t packetDestination = objects::NO_OBJECT) {
if (isDiagnostics) {
subdp::DiagnosticsHkPeriodicParams params(sid, enableReporting, collectionInterval);
return subscribeForDiagPeriodicPacket(params);
} else {
subdp::RegularHkPeriodicParams params(sid, enableReporting, collectionInterval);
return subscribeForRegularPeriodicPacket(params);
}
}
/**
* @brief Subscribe for the generation of packets if the dataset
* is marked as changed.
* @details
* This subscription mechanism will generally be used by the data creator.
* @param sid
* @param isDiagnostics
* @param packetDestination
* @return
*/
virtual ReturnValue_t subscribeForRegularUpdatePacket(subdp::RegularHkUpdateParams params) = 0;
virtual ReturnValue_t subscribeForDiagUpdatePacket(subdp::DiagnosticsHkUpdateParams params) = 0;
[[deprecated(
"Please use the new API which takes all arguments as one wrapper "
"struct")]] virtual ReturnValue_t
subscribeForUpdatePacket(sid_t sid, bool reportingEnabled, bool isDiagnostics,
object_id_t packetDestination = objects::NO_OBJECT) {
if (isDiagnostics) {
subdp::DiagnosticsHkUpdateParams params(sid, reportingEnabled);
return subscribeForDiagUpdatePacket(params);
} else {
subdp::RegularHkUpdateParams params(sid, reportingEnabled);
return subscribeForRegularUpdatePacket(params);
}
}
/**
* @brief Subscribe for a notification message which will be sent
* if a dataset has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param setId Set ID of the set to receive update messages from.
* @param destinationObject Object ID of the receiver.
* @param targetQueueId Receiver queue ID
* @param generateSnapshot If this is set to true, a copy of the current data with a
* timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForSetUpdateMessage(uint32_t setId, object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;
/**
* @brief Subscribe for an notification message which will be sent if a
* pool variable has changed.
* @details
* This subscription mechanism will generally be used internally by
* other software components.
* @param localPoolId Pool ID of the pool variable
* @param destinationObject Object ID of the receiver
* @param targetQueueId Receiver queue ID
* @param generateSnapshot If this is set to true, a copy of the current data with a
* timestamp will be generated and sent via message. Otherwise,
* only an notification message is sent.
* @return
*/
virtual ReturnValue_t subscribeForVariableUpdateMessage(lp_id_t localPoolId,
object_id_t destinationObject,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0;
};
#endif /* FSFW_DATAPOOLLOCAL_PROVIDESDATAPOOLSUBSCRIPTION_H_ */

View File

@ -1,37 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#define FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_
#include <vector>
#include "../datapool/SharedDataSetIF.h"
#include "../objectmanager/SystemObject.h"
#include "LocalPoolDataSetBase.h"
/**
* This local dataset variation can be used if the dataset is used concurrently across
* multiple threads. It provides a lock in addition to all other functionalities provided
* by the LocalPoolDataSetBase class.
*
* The user is completely responsible for lockingand unlocking the dataset when using the
* shared dataset.
*/
class SharedLocalDataSet : public SystemObject,
public LocalPoolDataSetBase,
public SharedDataSetIF {
public:
SharedLocalDataSet(object_id_t objectId, HasLocalDataPoolIF* owner, uint32_t setId,
const size_t maxSize);
SharedLocalDataSet(object_id_t objectId, sid_t sid, const size_t maxSize);
virtual ~SharedLocalDataSet();
ReturnValue_t lockDataset(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
dur_millis_t mutexTimeout = 20) override;
ReturnValue_t unlockDataset() override;
private:
MutexIF* datasetLock = nullptr;
std::vector<PoolVariableIF*> poolVarVector;
};
#endif /* FSFW_DATAPOOLLOCAL_SHAREDLOCALDATASET_H_ */

View File

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

View File

@ -1,19 +0,0 @@
#include "HasLocalDpIFManagerAttorney.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
#include "fsfw/datapoollocal/LocalPoolObjectBase.h"
LocalPoolDataSetBase* HasLocalDpIFManagerAttorney::getDataSetHandle(HasLocalDataPoolIF* clientIF,
sid_t sid) {
return clientIF->getDataSetHandle(sid);
}
LocalPoolObjectBase* HasLocalDpIFManagerAttorney::getPoolObjectHandle(HasLocalDataPoolIF* clientIF,
lp_id_t localPoolId) {
return clientIF->getPoolObjectHandle(localPoolId);
}
object_id_t HasLocalDpIFManagerAttorney::getObjectId(HasLocalDataPoolIF* clientIF) {
return clientIF->getObjectId();
}

View File

@ -1,21 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_
#include "fsfw/datapoollocal/localPoolDefinitions.h"
class HasLocalDataPoolIF;
class LocalPoolDataSetBase;
class LocalPoolObjectBase;
class HasLocalDpIFManagerAttorney {
static LocalPoolDataSetBase* getDataSetHandle(HasLocalDataPoolIF* clientIF, sid_t sid);
static LocalPoolObjectBase* getPoolObjectHandle(HasLocalDataPoolIF* clientIF,
lp_id_t localPoolId);
static object_id_t getObjectId(HasLocalDataPoolIF* clientIF);
friend class LocalDataPoolManager;
};
#endif /* FSFW_DATAPOOLLOCAL_HASLOCALDPIFMANAGERATTORNEY_H_ */

View File

@ -1,8 +0,0 @@
#include "HasLocalDpIFUserAttorney.h"
#include "fsfw/datapoollocal/AccessLocalPoolF.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
AccessPoolManagerIF* HasLocalDpIFUserAttorney::getAccessorHandle(HasLocalDataPoolIF* clientIF) {
return clientIF->getAccessorHandle();
}

View File

@ -1,26 +0,0 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
class LocalPoolDataSetAttorney {
private:
static void initializePeriodicHelper(LocalPoolDataSetBase& set, float collectionInterval,
uint32_t minimumPeriodicIntervalMs) {
set.initializePeriodicHelper(collectionInterval, minimumPeriodicIntervalMs);
}
static void setReportingEnabled(LocalPoolDataSetBase& set, bool enabled) {
set.setReportingEnabled(enabled);
}
static bool getReportingEnabled(LocalPoolDataSetBase& set) { return set.getReportingEnabled(); }
static PeriodicHousekeepingHelper* getPeriodicHelper(LocalPoolDataSetBase& set) {
return set.periodicHelper;
}
friend class LocalDataPoolManager;
};
#endif /* FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETATTORNEY_H_ */

View File

@ -1,11 +1,10 @@
#include "DeviceHandlerBase.h"
#include "fsfw/datapool/PoolReadGuard.h"
#include "fsfw/datapoollocal/LocalPoolVariable.h"
#include "fsfw/datapool/PoolVariable.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"
@ -28,11 +27,12 @@ DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, object_id_t device
storedRawData(StorageManagerIF::INVALID_ADDRESS),
deviceCommunicationId(deviceCommunication),
comCookie(comCookie),
sharedPool(DeviceHandlerBase::getObjectId()),
healthHelper(this, setObjectId),
modeHelper(this),
parameterHelper(this),
actionHelper(this, nullptr),
poolManager(this, nullptr),
hkHelper(this, nullptr),
childTransitionFailure(returnvalue::OK),
fdirInstance(fdirInstance),
defaultFDIRUsed(fdirInstance == nullptr),
@ -111,7 +111,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) {
doGetRead();
/* This will be performed after datasets have been updated by the
custom device implementation. */
poolManager.performHkOperation();
hkHelper.performHkOperation();
break;
default:
break;
@ -152,8 +152,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
}
if (rawDataReceiverId != objects::NO_OBJECT) {
AcceptsDeviceResponsesIF* rawReceiver =
ObjectManager::instance()->get<AcceptsDeviceResponsesIF>(rawDataReceiverId);
auto* rawReceiver = ObjectManager::instance()->get<AcceptsDeviceResponsesIF>(rawDataReceiverId);
if (rawReceiver == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize",
@ -214,7 +213,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result;
}
result = poolManager.initialize(commandQueue);
result = hkHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
@ -226,7 +225,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
// Set temperature target state to NON_OP.
if (pg.getReadResult() == returnvalue::OK) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
thermalSet->heaterRequest.setValid(true);
// thermalSet->heaterRequest.setValid(true);
}
}
@ -288,7 +287,7 @@ void DeviceHandlerBase::readCommandQueue() {
return;
}
result = poolManager.handleHousekeepingMessage(&command);
result = hkHelper.handleHousekeepingMessage(&command);
if (result == returnvalue::OK) {
return;
}
@ -413,7 +412,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, dp::SharedSetBase* replyDataSet,
size_t replyLen, bool periodic, bool hasDifferentReplyId, DeviceCommandId_t replyId,
Countdown* countdown) {
// No need to check, as we may try to insert multiple times.
@ -428,7 +427,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles,
LocalPoolDataSetBase* dataSet, size_t replyLen,
dp::SharedSetBase* dataSet, size_t replyLen,
bool periodic, Countdown* countdown) {
DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles;
@ -529,7 +528,7 @@ ReturnValue_t DeviceHandlerBase::updatePeriodicReply(bool enable, DeviceCommandI
}
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
LocalPoolDataSetBase* dataSet) {
dp::SharedSetBase* dataSet) {
auto replyIter = deviceReplyMap.find(replyId);
if (replyIter == deviceReplyMap.end()) {
return returnvalue::FAILED;
@ -593,7 +592,7 @@ void DeviceHandlerBase::setMode(Mode_t newMode, uint8_t newSubmode) {
if (thermalSet->heaterRequest.value != ThermalComponentIF::STATE_REQUEST_IGNORE) {
thermalSet->heaterRequest.value = ThermalComponentIF::STATE_REQUEST_NON_OPERATIONAL;
}
thermalSet->heaterRequest.setValid(true);
// thermalSet->heaterRequest.setValid(true);
}
}
/* TODO: This will probably be done by the LocalDataPoolManager now */
@ -1468,8 +1467,9 @@ Submode_t DeviceHandlerBase::getInitialSubmode() { return SUBMODE_NONE; }
void DeviceHandlerBase::performOperationHook() {}
/*
ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) {
PeriodicHkGenerationHelper& poolManager) {
if (thermalStateCfg.has_value()) {
localDataPoolMap.emplace(thermalStateCfg.value().thermalStatePoolId,
new PoolEntry<DeviceHandlerIF::dh_thermal_state_t>());
@ -1478,6 +1478,7 @@ ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(localpool::DataPool& lo
}
return returnvalue::OK;
}
*/
ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
// In this function, the task handle should be valid if the task
@ -1485,7 +1486,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
if (executingTask != nullptr) {
pstIntervalMs = executingTask->getPeriodMs();
}
this->poolManager.initializeAfterTaskCreation();
// this->poolManager.initializeAfterTaskCreation();
if (thermalStateCfg.has_value()) {
ThermalStateCfg& cfg = thermalStateCfg.value();
@ -1497,20 +1498,11 @@ 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; }
// dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { return pstIntervalMs; }
DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
if (cookieInfo.pendingCommand != deviceCommandMap.end()) {
@ -1519,17 +1511,6 @@ DeviceCommandId_t DeviceHandlerBase::getPendingCommand() const {
return DeviceHandlerIF::NO_COMMAND_ID;
}
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);
}
}
}
}
void DeviceHandlerBase::printWarningOrError(sif::OutputTypes errorType, const char* functionName,
ReturnValue_t errorCode, const char* errorPrint) {
if (errorPrint == nullptr) {
@ -1570,8 +1551,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()) {
@ -1628,3 +1607,7 @@ ReturnValue_t DeviceHandlerBase::finishAction(bool success, DeviceCommandId_t ac
actionHelper.finish(success, commandIter->second.sendReplyTo, action, result);
return returnvalue::OK;
}
void DeviceHandlerBase::setNormalDatapoolEntriesInvalid() { return; }
hk::PeriodicHelper& DeviceHandlerBase::getHkHelper() { return hkHelper; }

View File

@ -1,5 +1,6 @@
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_
#pragma once
#include <fsfw/housekeeping/PeriodicHkHelper.h>
#include <map>
#include <optional>
@ -10,9 +11,6 @@
#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/health/HealthHelper.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/modes/HasModesIF.h"
@ -20,7 +18,6 @@
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/power/PowerSwitchIF.h"
#include "fsfw/returnvalues/returnvalue.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
#include "fsfw/serviceinterface/serviceInterfaceDefintions.h"
#include "fsfw/subsystem/ModeTreeConnectionIF.h"
#include "fsfw/tasks/ExecutableObjectIF.h"
@ -88,7 +85,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
public ModeTreeChildIF,
public ModeTreeConnectionIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
public hk::GeneratesPeriodicHkIF {
friend void(Factory::setStaticFrameworkObjectIds)();
public:
@ -96,7 +93,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* The constructor passes the objectId to the SystemObject().
*
* @param setObjectId the ObjectId to pass to the SystemObject() Constructor
* @param deviceCommuncation Communcation Interface object which is used
* @param deviceCommunication Communication Interface object which is used
* to implement communication functions
* @param comCookie This object will be passed to the communication inter-
* face and can contain user-defined information about the communication.
@ -109,6 +106,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
void setCustomFdir(FailureIsolationBase *fdir);
void setPowerSwitcher(PowerSwitchIF *switcher);
hk::PeriodicHelper &getHkHelper();
/**
* extending the modes of DeviceHandler IF for internal state machine
*/
@ -230,7 +229,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
ReturnValue_t initializeAfterTaskCreation() override;
/** Destructor. */
virtual ~DeviceHandlerBase();
~DeviceHandlerBase() override;
/**
* Implementation of ExecutableObjectIF function
@ -238,7 +237,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param task_ Pointer to the taskIF of this task
*/
virtual void setTaskIF(PeriodicTaskIF *task_) override;
virtual MessageQueueId_t getCommandQueue(void) const override;
virtual MessageQueueId_t getCommandQueue() const override;
/** Explicit interface implementation of getObjectId */
virtual object_id_t getObjectId() const override;
@ -506,7 +505,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* - @c returnvalue::FAILED else.
*/
ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
LocalPoolDataSetBase *replyDataSet = nullptr,
dp::SharedSetBase *replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false,
DeviceCommandId_t replyId = 0,
@ -527,7 +526,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,
dp::SharedSetBase *dataSet = nullptr, size_t replyLen = 0,
bool periodic = false, Countdown *countdown = nullptr);
/**
@ -580,7 +579,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @details
* Used by the local data pool manager.
*/
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, LocalPoolDataSetBase *dataset);
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, dp::SharedSetBase *dataset);
/**
* Get the time needed to transit from modeFrom to modeTo.
@ -607,8 +606,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* @param localDataPoolMap
* @return
*/
virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
LocalDataPoolManager &poolManager) override;
// virtual ReturnValue_t initializeLocalDataPool(localpool::DataPool &localDataPoolMap,
// PeriodicHkGenerationHelper &poolManager) override;
/**
* @brief Set all datapool variables that are update periodically in
* normal mode invalid
@ -619,15 +618,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
* 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;
/* HasModesIF overrides */
virtual void startTransition(Mode_t mode, Submode_t submode) override;
@ -797,6 +787,8 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/** Cookie used for communication */
CookieIF *comCookie;
dp::SharedPool sharedPool;
/* Health helper for HasHealthIF */
HealthHelper healthHelper;
/* Mode helper for HasModesIF */
@ -806,7 +798,7 @@ class DeviceHandlerBase : public DeviceHandlerIF,
/* Action helper for HasActionsIF */
ActionHelper actionHelper;
/* Housekeeping Manager */
LocalDataPoolManager poolManager;
hk::PeriodicHelper hkHelper;
/**
* @brief Information about commands
@ -854,7 +846,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;
dp::SharedSetBase *dataSet = nullptr;
//! 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
@ -1006,12 +998,6 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
virtual void doOnActivity();
/**
* Required for HasLocalDataPoolIF, return a handle to the local pool manager.
* @return
*/
LocalDataPoolManager *getHkManagerHandle() override;
const HasHealthIF *getOptHealthIF() const override;
const HasModesIF &getModeIF() const override;
@ -1403,8 +1389,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);
@ -1425,5 +1409,3 @@ class DeviceHandlerBase : public DeviceHandlerIF,
*/
void disableCommandsAndReplies();
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */

View File

@ -2,11 +2,11 @@
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERIF_H_
#include "../action/HasActionsIF.h"
#include "../datapoollocal/localPoolDefinitions.h"
#include "../events/Event.h"
#include "../ipc/MessageQueueSenderIF.h"
#include "../modes/HasModesIF.h"
#include "DeviceHandlerMessage.h"
#include "fsfw/datapool/definitions.h"
/**
* This is used to uniquely identify commands that are sent to a device
@ -120,10 +120,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 = dp::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 dp::id_t DEFAULT_THERMAL_STATE_POOL_ID = dp::INVALID_LPID - 2;
static constexpr dp::id_t DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID = dp::INVALID_LPID - 1;
/**
* Default Destructor
@ -138,8 +138,8 @@ class DeviceHandlerIF {
};
struct ThermalStateCfg {
lp_id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID;
lp_id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID;
dp::id_t thermalStatePoolId = DeviceHandlerIF::DEFAULT_THERMAL_STATE_POOL_ID;
dp::id_t thermalRequestPoolId = DeviceHandlerIF::DEFAULT_THERMAL_HEATING_REQUEST_POOL_ID;
uint32_t thermalSetId = DeviceHandlerIF::DEFAULT_THERMAL_SET_ID;
};

View File

@ -1,27 +1,29 @@
#ifndef FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_
#define FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_
#include "../datapoollocal/LocalPoolVariable.h"
#include "../datapoollocal/StaticLocalDataSet.h"
#include "DeviceHandlerIF.h"
#include <fsfw/datapool/StaticSharedSet.h>
#include <fsfw/housekeeping/GeneratesPeriodicHkIF.h>
class DeviceHandlerThermalSet : public StaticLocalDataSet<2> {
#include "DeviceHandlerIF.h"
#include "fsfw/datapool/PoolVariable.h"
class DeviceHandlerThermalSet : public dp::StaticSharedSet<2> {
public:
DeviceHandlerThermalSet(HasLocalDataPoolIF* hkOwner, ThermalStateCfg cfg)
DeviceHandlerThermalSet(hk::GeneratesPeriodicHkIF* hkOwner, ThermalStateCfg cfg)
: DeviceHandlerThermalSet(hkOwner->getObjectId(), cfg) {}
DeviceHandlerThermalSet(object_id_t deviceHandler, ThermalStateCfg cfg)
: StaticLocalDataSet(sid_t(deviceHandler, cfg.thermalSetId)),
: StaticSharedSet(dp::structure_id_t(deviceHandler, cfg.thermalSetId)),
thermalStatePoolId(cfg.thermalStatePoolId),
heaterRequestPoolId(cfg.thermalRequestPoolId) {}
const lp_id_t thermalStatePoolId;
const lp_id_t heaterRequestPoolId;
const dp::id_t thermalStatePoolId;
const dp::id_t heaterRequestPoolId;
lp_var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
lp_var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
lp_var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
lp_var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
dp::var_t<DeviceHandlerIF::dh_thermal_state_t> thermalState =
dp::var_t<DeviceHandlerIF::dh_thermal_state_t>(sid.objectId, thermalStatePoolId, this);
dp::var_t<DeviceHandlerIF::dh_heater_request_t> heaterRequest =
dp::var_t<DeviceHandlerIF::dh_heater_request_t>(sid.objectId, heaterRequestPoolId, this);
};
#endif /* FSFW_DEVICEHANDLERS_DEVICEHANDLERTHERMALSET_H_ */

View File

@ -8,12 +8,12 @@ FreshDeviceHandlerBase::FreshDeviceHandlerBase(DhbConfig config)
: SystemObject(config.objectId),
actionHelper(this, nullptr),
modeHelper(this),
healthHelper(this, getObjectId()),
healthHelper(this, FreshDeviceHandlerBase::getObjectId()),
paramHelper(this),
poolManager(this, nullptr),
hkHelper(this, nullptr),
fdirInstance(config.fdirInstance),
defaultFdirParent(config.defaultFdirParent) {
auto mqArgs = MqArgs(config.objectId, static_cast<void*>(this));
auto mqArgs = MqArgs(config.objectId, this);
messageQueue = QueueFactory::instance()->createMessageQueue(
config.msgQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
@ -33,7 +33,7 @@ ReturnValue_t FreshDeviceHandlerBase::performOperation(uint8_t opCode) {
handleQueue();
fdirInstance->checkForFailures();
performDeviceOperation(opCode);
poolManager.performHkOperation();
hkHelper.performHkOperation();
return returnvalue::OK;
}
@ -43,7 +43,6 @@ ReturnValue_t FreshDeviceHandlerBase::performDeviceOperationPreQueueHandling(uin
void FreshDeviceHandlerBase::startTransition(Mode_t mode_, Submode_t submode_) {
triggerEvent(CHANGING_MODE, mode_, submode_);
// Complete mode transition immediately by default.
setMode(mode_, submode_);
}
@ -97,7 +96,7 @@ ReturnValue_t FreshDeviceHandlerBase::handleQueue() {
continue;
}
result = poolManager.handleHousekeepingMessage(&command);
result = hkHelper.handleHousekeepingMessage(&command);
if (result == returnvalue::OK) {
continue;
}
@ -127,17 +126,6 @@ ReturnValue_t FreshDeviceHandlerBase::connectModeTreeParent(HasModeTreeChildrenI
// Executable Overrides.
void FreshDeviceHandlerBase::setTaskIF(PeriodicTaskIF* task_) { executingTask = task_; }
// Pool Manager overrides.
LocalDataPoolManager* FreshDeviceHandlerBase::getHkManagerHandle() { return &poolManager; }
[[nodiscard]] uint32_t FreshDeviceHandlerBase::getPeriodicOperationFrequency() const {
return this->executingTask->getPeriodMs();
}
ReturnValue_t FreshDeviceHandlerBase::initializeAfterTaskCreation() {
return poolManager.initializeAfterTaskCreation();
}
ReturnValue_t FreshDeviceHandlerBase::setHealth(HasHealthIF::HealthState health) {
// Assembly should handle commanding to OFF.
healthHelper.setHealth(health);
@ -174,7 +162,7 @@ ReturnValue_t FreshDeviceHandlerBase::initialize() {
return result;
}
result = poolManager.initialize(messageQueue);
result = hkHelper.initialize(messageQueue);
if (result != returnvalue::OK) {
return result;
}
@ -201,3 +189,5 @@ ReturnValue_t FreshDeviceHandlerBase::getParameter(uint8_t domainId, uint8_t uni
}
return INVALID_DOMAIN_ID;
}
datapool::SharedPool* FreshDeviceHandlerBase::getOptionalSharedPool() { return nullptr; }

View File

@ -1,12 +1,13 @@
#pragma once
#include <fsfw/housekeeping/PeriodicHkHelper.h>
#include "fsfw/action.h"
#include "fsfw/datapoollocal/HasLocalDataPoolIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/devicehandlers/DeviceHandlerIF.h"
#include "fsfw/fdir/FailureIsolationBase.h"
#include "fsfw/health/HasHealthIF.h"
#include "fsfw/health/HealthHelper.h"
#include "fsfw/housekeeping/GeneratesPeriodicHkIF.h"
#include "fsfw/modes/HasModesIF.h"
#include "fsfw/objectmanager.h"
#include "fsfw/parameters/ParameterHelper.h"
@ -34,7 +35,7 @@ class FreshDeviceHandlerBase : public SystemObject,
public ModeTreeConnectionIF,
public HasActionsIF,
public ReceivesParameterMessagesIF,
public HasLocalDataPoolIF {
public hk::GeneratesPeriodicHkIF {
public:
explicit FreshDeviceHandlerBase(DhbConfig config);
~FreshDeviceHandlerBase() override;
@ -56,16 +57,12 @@ class FreshDeviceHandlerBase : public SystemObject,
ReturnValue_t connectModeTreeParent(HasModeTreeChildrenIF& parent) override;
ModeTreeChildIF& getModeTreeChildIF() override;
[[nodiscard]] uint32_t getPeriodicOperationFrequency() const override;
protected:
// Pool Manager overrides.
LocalDataPoolManager* getHkManagerHandle() override;
ActionHelper actionHelper;
ModeHelper modeHelper;
HealthHelper healthHelper;
ParameterHelper paramHelper;
LocalDataPoolManager poolManager;
hk::PeriodicHelper hkHelper;
bool hasCustomFdir = false;
FailureIsolationBase* fdirInstance;
@ -107,6 +104,13 @@ class FreshDeviceHandlerBase : public SystemObject,
// System Object overrides.
ReturnValue_t initialize() override;
// Default implementation assumes that no optional shared pool is required.
virtual datapool::SharedPool* getOptionalSharedPool();
// Implemented by child, required for periodic HK.
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) = 0;
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) = 0;
/**
* Implemented by child class. Handle all command messages which are
* not health, mode, action or housekeeping messages.
@ -115,11 +119,6 @@ class FreshDeviceHandlerBase : public SystemObject,
*/
virtual ReturnValue_t handleCommandMessage(CommandMessage* message) = 0;
// HK manager abstract functions.
LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override = 0;
ReturnValue_t initializeLocalDataPool(localpool::DataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) override = 0;
// Mode abstract functions
ReturnValue_t checkModeCommand(Mode_t mode, Submode_t submode,
uint32_t* msToReachTheMode) override = 0;
@ -129,8 +128,7 @@ class FreshDeviceHandlerBase : public SystemObject,
ReturnValue_t executeAction(ActionId_t actionId, MessageQueueId_t commandedBy,
const uint8_t* data, size_t size) override = 0;
// Executable overrides.
virtual ReturnValue_t performOperation(uint8_t opCode) override;
ReturnValue_t initializeAfterTaskCreation() override;
ReturnValue_t performOperation(uint8_t opCode) override;
/**
* This calls the FDIR instance event trigger function.

View File

@ -1,2 +1,2 @@
target_sources(${LIB_FSFW_NAME} PRIVATE HousekeepingMessage.cpp
PeriodicHousekeepingHelper.cpp)
PeriodicHkHelper.cpp)

View File

@ -0,0 +1,65 @@
#pragma once
#include <fsfw/datapool/SharedPool.h>
#include <vector>
#include "definitions.h"
#include "fsfw/datapool/definitions.h"
namespace hk {
/**
* @brief This interface is implemented by classes which posses a local data pool (not
* the managing class). It defines the relationship between the local data pool owner and the
* LocalDataPoolManager.
* @details
* Any class implementing this interface shall also have a LocalDataPoolManager member class which
* contains the actual pool data structure and exposes the public interface for it.
*
* The local data pool can be accessed using helper classes by using the
* LocalPoolVariable, LocalPoolVector or LocalDataSet classes. Every local pool variable can
* be uniquely identified by a global pool ID (gp_id_t) and every dataset tied
* to a pool manager can be uniqely identified by a global structure ID (sid_t).
*
* All software objects which want to use the local pool of another object shall also use this
* interface, for example to get a handle to the subscription interface. The interface
* can be retrieved using the object manager, provided the target object is a SystemObject.
* For example, the following line of code can be used to retrieve the interface
*
* HasLocalDataPoolIF* poolIF = ObjectManager::instance()->
* get<HasLocalDataPoolIF>(objects::SOME_OBJECT);
* if(poolIF != nullptr) {
* doSomething()
* }
*/
class GeneratesPeriodicHkIF {
friend class PeriodicHelper;
public:
[[nodiscard]] virtual object_id_t getObjectId() const = 0;
/** Command queue for housekeeping messages. */
[[nodiscard]] virtual MessageQueueId_t getCommandQueue() const = 0;
virtual datapool::SharedPool* getOptionalSharedPool() = 0;
protected:
virtual ~GeneratesPeriodicHkIF() = default;
static constexpr uint32_t INVALID_LPID = dp::INVALID_LPID;
virtual ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) = 0;
virtual ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setList) = 0;
/**
* These function can be implemented by pool owner, if they are required
* and used by the housekeeping message interface.
* */
virtual ReturnValue_t addDataSet(dp::sid_t sid) { return returnvalue::FAILED; };
virtual ReturnValue_t removeDataSet(dp::sid_t sid) { return returnvalue::FAILED; };
virtual ReturnValue_t changeCollectionInterval(dp::sid_t sid, float newIntervalSeconds) {
return returnvalue::FAILED;
};
};
} // namespace hk

View File

@ -1,12 +1,14 @@
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include <fsfw/timemanager/clockDefinitions.h>
#include <cstring>
#include "fsfw/objectmanager/ObjectManager.h"
HousekeepingMessage::~HousekeepingMessage() {}
void HousekeepingMessage::setHkReportReply(CommandMessage *message, sid_t sid,
void HousekeepingMessage::setHkReportReply(CommandMessage *message, dp::structure_id_t sid,
store_address_t storeId) {
message->setCommand(HK_REPORT);
message->setMessageSize(HK_MESSAGE_SIZE);
@ -14,15 +16,15 @@ void HousekeepingMessage::setHkReportReply(CommandMessage *message, sid_t sid,
message->setParameter3(storeId.raw);
}
sid_t HousekeepingMessage::getHkDataReply(const CommandMessage *message,
dp::structure_id_t HousekeepingMessage::getHkDataReply(const CommandMessage *message,
store_address_t *storeIdToSet) {
if (storeIdToSet != nullptr) {
*storeIdToSet = message->getParameter3();
}
return getSid(message);
return getStructureId(message);
}
void HousekeepingMessage::setToggleReportingCommand(CommandMessage *message, sid_t sid,
void HousekeepingMessage::setToggleReportingCommand(CommandMessage *message, dp::structure_id_t sid,
bool enableReporting) {
if (enableReporting) {
message->setCommand(ENABLE_PERIODIC_HK_REPORT_GENERATION);
@ -33,74 +35,72 @@ void HousekeepingMessage::setToggleReportingCommand(CommandMessage *message, sid
setSid(message, sid);
}
void HousekeepingMessage::setStructureReportingCommand(CommandMessage *command, sid_t sid) {
void HousekeepingMessage::setStructureReportingCommand(CommandMessage *command,
dp::structure_id_t sid) {
command->setCommand(REPORT_HK_REPORT_STRUCTURES);
setSid(command, sid);
}
void HousekeepingMessage::setOneShotReportCommand(CommandMessage *command, sid_t sid) {
void HousekeepingMessage::setOneShotReportCommand(CommandMessage *command, dp::structure_id_t sid) {
command->setCommand(GENERATE_ONE_PARAMETER_REPORT);
setSid(command, sid);
}
void HousekeepingMessage::setCollectionIntervalModificationCommand(CommandMessage *command,
sid_t sid,
float collectionInterval) {
void HousekeepingMessage::setCollectionIntervalModificationCommand(
CommandMessage *command, dp::structure_id_t sid, dur_millis_t collectionIntervalMs) {
command->setCommand(MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL);
/* Raw storage of the float in the message. Do not use setParameter3, does
implicit conversion to integer type! */
std::memcpy(command->getData() + 2 * sizeof(uint32_t), &collectionInterval,
sizeof(collectionInterval));
std::memcpy(command->getData() + 2 * sizeof(uint32_t), &collectionIntervalMs,
sizeof(collectionIntervalMs));
setSid(command, sid);
}
sid_t HousekeepingMessage::getCollectionIntervalModificationCommand(const CommandMessage *command,
float *newCollectionInterval) {
if (newCollectionInterval != nullptr) {
std::memcpy(newCollectionInterval, command->getData() + 2 * sizeof(uint32_t),
sizeof(*newCollectionInterval));
}
dp::structure_id_t HousekeepingMessage::getCollectionIntervalModificationCommand(
const CommandMessage *command, dur_millis_t &newCollectionIntervalMs) {
std::memcpy(&newCollectionIntervalMs, command->getData() + 2 * sizeof(uint32_t),
sizeof(newCollectionIntervalMs));
return getSid(command);
return getStructureId(command);
}
void HousekeepingMessage::setHkRequestSuccessReply(CommandMessage *reply, sid_t sid) {
void HousekeepingMessage::setHkRequestSuccessReply(CommandMessage *reply, dp::structure_id_t sid) {
setSid(reply, sid);
reply->setCommand(HK_REQUEST_SUCCESS);
}
void HousekeepingMessage::setHkRequestFailureReply(CommandMessage *reply, sid_t sid,
void HousekeepingMessage::setHkRequestFailureReply(CommandMessage *reply, dp::structure_id_t sid,
ReturnValue_t error) {
setSid(reply, sid);
reply->setCommand(HK_REQUEST_FAILURE);
reply->setParameter3(error);
}
sid_t HousekeepingMessage::getHkRequestFailureReply(const CommandMessage *reply,
dp::structure_id_t HousekeepingMessage::getHkRequestFailureReply(const CommandMessage *reply,
ReturnValue_t *error) {
if (error != nullptr) {
*error = reply->getParameter3();
}
return getSid(reply);
return getStructureId(reply);
}
sid_t HousekeepingMessage::getSid(const CommandMessage *message) {
sid_t sid;
dp::structure_id_t HousekeepingMessage::getStructureId(const CommandMessage *message) {
dp::structure_id_t sid;
std::memcpy(&sid.raw, message->getData(), sizeof(sid.raw));
return sid;
}
gp_id_t HousekeepingMessage::getGpid(const CommandMessage *message) {
gp_id_t globalPoolId;
dp::g_id_t HousekeepingMessage::getGpid(const CommandMessage *message) {
dp::g_id_t globalPoolId;
std::memcpy(&globalPoolId.raw, message->getData(), sizeof(globalPoolId.raw));
return globalPoolId;
}
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply, sid_t sid,
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply, dp::structure_id_t sid,
store_address_t storeId) {
reply->setCommand(HK_DEFINITIONS_REPORT);
setSid(reply, sid);
@ -111,13 +111,10 @@ void HousekeepingMessage::clear(CommandMessage *message) {
switch (message->getCommand()) {
case (HK_REPORT):
case (DIAGNOSTICS_REPORT):
case (HK_DEFINITIONS_REPORT):
case (UPDATE_SNAPSHOT_SET):
case (UPDATE_SNAPSHOT_VARIABLE): {
case (HK_DEFINITIONS_REPORT): {
store_address_t storeId;
getHkDataReply(message, &storeId);
StorageManagerIF *ipcStore =
ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
auto *ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore != nullptr) {
ipcStore->deleteData(storeId);
}
@ -126,49 +123,25 @@ void HousekeepingMessage::clear(CommandMessage *message) {
message->setCommand(CommandMessage::CMD_NONE);
}
void HousekeepingMessage::setUpdateNotificationSetCommand(CommandMessage *command, sid_t sid) {
command->setCommand(UPDATE_NOTIFICATION_SET);
setSid(command, sid);
dp::structure_id_t HousekeepingMessage::getUpdateNotificationSetCommand(
const CommandMessage *command) {
return getStructureId(command);
}
void HousekeepingMessage::setUpdateNotificationVariableCommand(CommandMessage *command,
gp_id_t globalPoolId) {
command->setCommand(UPDATE_NOTIFICATION_VARIABLE);
setGpid(command, globalPoolId);
}
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command, sid_t sid,
store_address_t storeId) {
command->setCommand(UPDATE_SNAPSHOT_SET);
setSid(command, sid);
command->setParameter3(storeId.raw);
}
void HousekeepingMessage::setUpdateSnapshotVariableCommand(CommandMessage *command,
gp_id_t globalPoolId,
store_address_t storeId) {
command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
setGpid(command, globalPoolId);
command->setParameter3(storeId.raw);
}
sid_t HousekeepingMessage::getUpdateNotificationSetCommand(const CommandMessage *command) {
return getSid(command);
}
gp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(const CommandMessage *command) {
dp::g_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
const CommandMessage *command) {
return getGpid(command);
}
sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(const CommandMessage *command,
dp::structure_id_t HousekeepingMessage::getUpdateSnapshotSetCommand(const CommandMessage *command,
store_address_t *storeId) {
if (storeId != nullptr) {
*storeId = command->getParameter3();
}
return getSid(command);
return getStructureId(command);
}
gp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(const CommandMessage *command,
dp::g_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(const CommandMessage *command,
store_address_t *storeId) {
if (storeId != nullptr) {
*storeId = command->getParameter3();
@ -176,10 +149,10 @@ gp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(const CommandMessa
return getGpid(command);
}
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
void HousekeepingMessage::setSid(CommandMessage *message, dp::structure_id_t sid) {
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
}
void HousekeepingMessage::setGpid(CommandMessage *message, gp_id_t globalPoolId) {
void HousekeepingMessage::setGpid(CommandMessage *message, dp::g_id_t globalPoolId) {
std::memcpy(message->getData(), &globalPoolId.raw, sizeof(globalPoolId.raw));
}

View File

@ -1,7 +1,9 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_
#include "fsfw/datapoollocal/localPoolDefinitions.h"
#include <fsfw/timemanager/clockDefinitions.h>
#include "fsfw/datapool/definitions.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/FwMessageTypes.h"
#include "fsfw/objectmanager/frameworkObjects.h"
@ -16,7 +18,7 @@
class HousekeepingMessage {
public:
static constexpr size_t HK_MESSAGE_SIZE =
CommandMessageIF::HEADER_SIZE + sizeof(sid_t) + sizeof(uint32_t);
CommandMessageIF::HEADER_SIZE + sizeof(dp::structure_id_t) + sizeof(uint32_t);
/**
* Concrete instance is not used, instead this class operates on
@ -44,33 +46,35 @@ class HousekeepingMessage {
static constexpr Command_t HK_REQUEST_SUCCESS = MAKE_COMMAND_ID(128);
static constexpr Command_t HK_REQUEST_FAILURE = MAKE_COMMAND_ID(129);
static constexpr Command_t UPDATE_NOTIFICATION_SET = MAKE_COMMAND_ID(130);
static constexpr Command_t UPDATE_NOTIFICATION_VARIABLE = MAKE_COMMAND_ID(131);
// static constexpr Command_t UPDATE_NOTIFICATION_SET = MAKE_COMMAND_ID(130);
// static constexpr Command_t UPDATE_NOTIFICATION_VARIABLE = MAKE_COMMAND_ID(131);
static constexpr Command_t UPDATE_SNAPSHOT_SET = MAKE_COMMAND_ID(132);
static constexpr Command_t UPDATE_SNAPSHOT_VARIABLE = MAKE_COMMAND_ID(133);
// static constexpr Command_t UPDATE_SNAPSHOT_SET = MAKE_COMMAND_ID(132);
// static constexpr Command_t UPDATE_SNAPSHOT_VARIABLE = MAKE_COMMAND_ID(133);
// static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(134);
static sid_t getSid(const CommandMessage* message);
static gp_id_t getGpid(const CommandMessage* message);
static dp::sid_t getStructureId(const CommandMessage* message);
static dp::g_id_t getGpid(const CommandMessage* message);
/* Housekeeping Interface Messages */
static void setToggleReportingCommand(CommandMessage* command, sid_t sid, bool enableReporting);
static void setStructureReportingCommand(CommandMessage* command, sid_t sid);
static void setOneShotReportCommand(CommandMessage* command, sid_t sid);
static void setCollectionIntervalModificationCommand(CommandMessage* command, sid_t sid,
float collectionInterval);
static void setToggleReportingCommand(CommandMessage* command, dp::sid_t sid,
bool enableReporting);
static void setStructureReportingCommand(CommandMessage* command, dp::sid_t sid);
static void setOneShotReportCommand(CommandMessage* command, dp::sid_t sid);
static void setCollectionIntervalModificationCommand(CommandMessage* command, dp::sid_t sid,
dur_millis_t collectionIntervalMs);
static void setHkReportReply(CommandMessage* reply, sid_t sid, store_address_t storeId);
static void setHkReportReply(CommandMessage* reply, dp::sid_t sid, store_address_t storeId);
static void setHkRequestSuccessReply(CommandMessage* reply, sid_t sid);
static void setHkRequestFailureReply(CommandMessage* reply, sid_t sid, ReturnValue_t error);
static void setHkRequestSuccessReply(CommandMessage* reply, dp::sid_t sid);
static void setHkRequestFailureReply(CommandMessage* reply, dp::sid_t sid, ReturnValue_t error);
static void setHkStuctureReportReply(CommandMessage* reply, sid_t sid, store_address_t storeId);
static void setHkStuctureReportReply(CommandMessage* reply, dp::sid_t sid,
store_address_t storeId);
static sid_t getHkRequestFailureReply(const CommandMessage* reply, ReturnValue_t* error);
static dp::sid_t getHkRequestFailureReply(const CommandMessage* reply, ReturnValue_t* error);
/**
* @brief Generic getter function for housekeeping data replies
@ -79,33 +83,35 @@ class HousekeepingMessage {
* regular HK packets. This getter function should be used for the
* command IDs 10, 12, 25 and 26.
*/
static sid_t getHkDataReply(const CommandMessage* message, store_address_t* storeIdToSet);
static sid_t getCollectionIntervalModificationCommand(const CommandMessage* command,
float* newCollectionInterval);
static dp::sid_t getHkDataReply(const CommandMessage* message, store_address_t* storeIdToSet);
static dp::sid_t getCollectionIntervalModificationCommand(const CommandMessage* command,
dur_millis_t& newCollectionInterval);
/* Update Notification Messages */
static void setUpdateNotificationSetCommand(CommandMessage* command, sid_t sid);
static void setUpdateNotificationVariableCommand(CommandMessage* command, gp_id_t globalPoolId);
static void setUpdateNotificationSetCommand(CommandMessage* command, dp::sid_t sid);
static void setUpdateNotificationVariableCommand(CommandMessage* command,
dp::g_id_t globalPoolId);
static void setUpdateSnapshotSetCommand(CommandMessage* command, sid_t sid,
static void setUpdateSnapshotSetCommand(CommandMessage* command, dp::sid_t sid,
store_address_t storeId);
static void setUpdateSnapshotVariableCommand(CommandMessage* command, gp_id_t globalPoolId,
static void setUpdateSnapshotVariableCommand(CommandMessage* command, dp::g_id_t globalPoolId,
store_address_t storeId);
static sid_t getUpdateNotificationSetCommand(const CommandMessage* command);
static gp_id_t getUpdateNotificationVariableCommand(const CommandMessage* command);
static dp::sid_t getUpdateNotificationSetCommand(const CommandMessage* command);
static dp::g_id_t getUpdateNotificationVariableCommand(const CommandMessage* command);
static sid_t getUpdateSnapshotSetCommand(const CommandMessage* command, store_address_t* storeId);
static gp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
static dp::sid_t getUpdateSnapshotSetCommand(const CommandMessage* command,
store_address_t* storeId);
static dp::g_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
store_address_t* storeId);
/** Utility */
static void clear(CommandMessage* message);
private:
static void setSid(CommandMessage* message, sid_t sid);
static void setGpid(CommandMessage* message, gp_id_t globalPoolId);
static void setSid(CommandMessage* message, dp::sid_t sid);
static void setGpid(CommandMessage* message, dp::g_id_t globalPoolId);
};
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGMESSAGE_H_ */

View File

@ -1,9 +1,9 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_
#pragma once
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "../storagemanager/StorageManagerIF.h"
#include <fsfw/serialize/SerialBufferAdapter.h>
#include "fsfw/datapool/SharedSetBase.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
/**
* @brief This class will be used to serialize general housekeeping packets
@ -18,8 +18,8 @@
*/
class HousekeepingPacketDownlink : public SerialLinkedListAdapter<SerializeIF> {
public:
HousekeepingPacketDownlink(sid_t sid, LocalPoolDataSetBase* dataSetPtr)
: sourceId(sid.objectId), setId(sid.ownerSetId), hkData(dataSetPtr) {
HousekeepingPacketDownlink(dp::sid_t sid, const uint8_t* hkData, size_t hkDataLen)
: sourceId(sid.objectId), setId(sid.ownerSetId), hkData(hkData, hkDataLen) {
setLinks();
}
@ -32,7 +32,5 @@ class HousekeepingPacketDownlink : public SerialLinkedListAdapter<SerializeIF> {
SerializeElement<object_id_t> sourceId;
SerializeElement<uint32_t> setId;
LinkedElement<SerializeIF> hkData;
SerializeElement<SerialBufferAdapter<uint32_t>> hkData;
};
#endif /* FRAMEWORK_HOUSEKEEPING_HOUSEKEEPINGPACKETDOWNLINK_H_ */

View File

@ -1,60 +1,28 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_
#pragma once
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../housekeeping/HousekeepingMessage.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
class HousekeepingSetPacket : public SerialLinkedListAdapter<SerializeIF> {
public:
HousekeepingSetPacket(sid_t sid, bool reportingEnabled, bool valid, float collectionInterval,
LocalPoolDataSetBase* dataSetPtr)
HousekeepingSetPacket(dp::sid_t sid, bool reportingEnabled, dur_millis_t collectionIntervalMs)
: objectId(sid.objectId),
setId(sid.ownerSetId),
reportingEnabled(reportingEnabled),
valid(valid),
collectionIntervalSeconds(collectionInterval),
dataSet(dataSetPtr) {
collectionIntervalMs(collectionIntervalMs) {
setLinks();
}
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
Endianness streamEndianness) const override {
ReturnValue_t result =
SerialLinkedListAdapter::serialize(buffer, size, maxSize, streamEndianness);
if (result != returnvalue::OK) {
return result;
}
return dataSet->serializeLocalPoolIds(buffer, size, maxSize, streamEndianness);
}
size_t getSerializedSize() const override {
size_t linkedSize = SerialLinkedListAdapter::getSerializedSize();
linkedSize += dataSet->getLocalPoolIdsSerializedSize();
return linkedSize;
}
ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size,
Endianness streamEndianness) override {
return returnvalue::OK;
}
private:
void setLinks() {
setStart(&objectId);
objectId.setNext(&setId);
setId.setNext(&reportingEnabled);
reportingEnabled.setNext(&valid);
valid.setNext(&collectionIntervalSeconds);
collectionIntervalSeconds.setEnd();
reportingEnabled.setNext(&collectionIntervalMs);
collectionIntervalMs.setEnd();
}
SerializeElement<object_id_t> objectId;
SerializeElement<uint32_t> setId;
SerializeElement<bool> reportingEnabled;
SerializeElement<bool> valid;
SerializeElement<float> collectionIntervalSeconds;
LocalPoolDataSetBase* dataSet;
SerializeElement<uint32_t> collectionIntervalMs;
};
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSETPACKET_H_ */

View File

@ -1,11 +1,10 @@
#ifndef FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
#define FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_
#pragma once
#include "../datapoollocal/LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalPoolObjectBase.h"
#include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialLinkedListAdapter.h"
#include "../timemanager/CCSDSTime.h"
#include "fsfw/datapool/LocalPoolObjectBase.h"
#include "fsfw/datapool/SharedSetBase.h"
#include "fsfw/serialize/SerialBufferAdapter.h"
#include "fsfw/serialize/SerialLinkedListAdapter.h"
#include "fsfw/timemanager/CCSDSTime.h"
/**
* @brief This helper class will be used to serialize and deserialize update housekeeping packets
@ -20,7 +19,7 @@ class HousekeepingSnapshot : public SerializeIF {
* @param dataSetPtr Pointer to the dataset instance to serialize or deserialize the
* data into
*/
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolDataSetBase* dataSetPtr)
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, SerializeIF* dataSetPtr)
: timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
timeStampSize(sizeof(CCSDSTime::CDS_short)),
updateData(dataSetPtr) {};
@ -31,27 +30,7 @@ class HousekeepingSnapshot : public SerializeIF {
* @param timeStampSize Size of the timestamp
* @param dataSetPtr Pointer to the dataset instance to deserialize the data into
*/
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolDataSetBase* dataSetPtr)
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr) {};
/**
* Update packet constructor for pool variables.
* @param timeStamp
* @param timeStampSize
* @param dataSetPtr
*/
HousekeepingSnapshot(CCSDSTime::CDS_short* cdsShort, LocalPoolObjectBase* dataSetPtr)
: timeStamp(reinterpret_cast<uint8_t*>(cdsShort)),
timeStampSize(sizeof(CCSDSTime::CDS_short)),
updateData(dataSetPtr) {};
/**
* Update packet constructor for pool variables.
* @param timeStamp
* @param timeStampSize
* @param dataSetPtr
*/
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, LocalPoolObjectBase* dataSetPtr)
HousekeepingSnapshot(uint8_t* timeStamp, size_t timeStampSize, SerializeIF* dataSetPtr)
: timeStamp(timeStamp), timeStampSize(timeStampSize), updateData(dataSetPtr) {};
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
@ -107,5 +86,3 @@ class HousekeepingSnapshot : public SerializeIF {
SerializeIF* updateData = nullptr;
};
#endif /* FSFW_HOUSEKEEPING_HOUSEKEEPINGSNAPSHOT_H_ */

View File

@ -0,0 +1,411 @@
#include "PeriodicHkHelper.h"
#include <cmath>
#include <functional>
#include <set>
#include "fsfw/housekeeping/AcceptsHkPacketsIF.h"
#include "fsfw/housekeeping/HousekeepingSetPacket.h"
#include "fsfw/housekeeping/HousekeepingSnapshot.h"
#include "fsfw/ipc/QueueFactory.h"
#include "fsfw/objectmanager/ObjectManager.h"
#include "fsfw/timemanager/CCSDSTime.h"
using namespace hk;
PeriodicHelper::PeriodicHelper(GeneratesPeriodicHkIF* owner, MessageQueueIF* queueToUse,
MessageQueueId_t hkDestQueue)
: hkDestinationId(hkDestQueue) {
if (owner == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "LocalDataPoolManager", returnvalue::FAILED,
"Invalid supplied owner");
return;
}
this->owner = owner;
hkQueue = queueToUse;
}
ReturnValue_t PeriodicHelper::initialize(MessageQueueIF* queueToUse) {
if (queueToUse != nullptr) {
hkQueue = queueToUse;
}
if (hkQueue == nullptr) {
// Error, all destinations invalid
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID);
}
ipcStore = ObjectManager::instance()->get<StorageManagerIF>(objects::IPC_STORE);
if (ipcStore == nullptr) {
// Error, all destinations invalid
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", returnvalue::FAILED,
"Could not set IPC store.");
return returnvalue::FAILED;
}
if (hkDestinationId == MessageQueueIF::NO_QUEUE) {
if (const auto* hkPacketReceiver =
ObjectManager::instance()->get<AcceptsHkPacketsIF>(objects::PUS_SERVICE_3_HOUSEKEEPING);
hkPacketReceiver != nullptr) {
hkDestinationId = hkPacketReceiver->getHkQueue();
} else {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "initialize", QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
}
owner->specifyHkDatasets(setList);
return returnvalue::OK;
}
ReturnValue_t PeriodicHelper::performHkOperation() {
timeval now{};
Clock::getClockMonotonic(&now);
for (auto& setSpec : setList) {
switch (setSpec.reportingType) {
case (ReportingType::PERIODIC): {
if (setSpec.dataType == DataType::LOCAL_POOL_VARIABLE) {
// Periodic packets shall only be generated from datasets
continue;
}
if (not setSpec.periodicCollectionEnabled) {
continue;
}
performPeriodicHkGeneration(setSpec, now);
break;
}
default:
// This should never happen.
return returnvalue::FAILED;
}
}
return returnvalue::OK;
}
ReturnValue_t PeriodicHelper::handleHousekeepingMessage(CommandMessage* message) {
Command_t command = message->getCommand();
dp::sid_t sid = HousekeepingMessage::getStructureId(message);
ReturnValue_t result = returnvalue::OK;
switch (command) {
// Houskeeping interface handling.
case (HousekeepingMessage::ENABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, true);
break;
}
case (HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): {
result = togglePeriodicGeneration(sid, false);
break;
}
case (HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): {
result = generateSetStructurePacket(sid);
if (result == returnvalue::OK) {
return result;
}
break;
}
case (HousekeepingMessage::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL): {
dur_millis_t newCollIntvl = 0;
HousekeepingMessage::getCollectionIntervalModificationCommand(message, newCollIntvl);
result = setCollectionInterval(sid, newCollIntvl);
break;
}
case (HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): {
return generateHousekeepingPacket(HousekeepingMessage::getStructureId(message));
}
default:
return CommandMessageIF::UNKNOWN_COMMAND;
}
CommandMessage reply;
if (result != returnvalue::OK) {
if (result == INVALID_HK_REQUEST) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "handleHousekeepingMessage",
INVALID_HK_REQUEST);
}
HousekeepingMessage::setHkRequestFailureReply(&reply, sid, result);
} else {
HousekeepingMessage::setHkRequestSuccessReply(&reply, sid);
}
hkQueue->sendMessage(hkDestinationId, &reply);
return result;
}
GeneratesPeriodicHkIF* PeriodicHelper::getOwner() const { return owner; }
ReturnValue_t PeriodicHelper::generateHousekeepingPacket(const dp::sid_t sid,
MessageQueueId_t destination) {
store_address_t storeId;
const auto optSetSpec = getMutSetSpecification(sid);
if (!optSetSpec.has_value()) {
return DATASET_NOT_FOUND;
}
const auto& setSpec = optSetSpec.value().get();
uint8_t* dataPtr = nullptr;
const size_t maxSize = setSpec.serializedSize + dp::structure_id_t::SIZE;
ReturnValue_t result = ipcStore->getFreeElement(&storeId, maxSize, &dataPtr);
if (result != returnvalue::OK) {
return result;
}
size_t serSize = 0;
result = SerializeAdapter::serialize(&sid.objectId, &dataPtr, &serSize, maxSize,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = SerializeAdapter::serialize(&sid.ownerSetId, &dataPtr, &serSize, maxSize,
SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
return result;
}
result = owner->serializeHkDataset(sid, dataPtr, maxSize - 8);
if (result != returnvalue::OK) {
return result;
}
// Now we set a HK message and send it the HK packet destination.
CommandMessage hkMessage;
HousekeepingMessage::setHkReportReply(&hkMessage, sid, storeId);
if (hkQueue == nullptr) {
// Error, no queue available to send packet with.
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
if (destination == MessageQueueIF::NO_QUEUE) {
if (hkDestinationId == MessageQueueIF::NO_QUEUE) {
// Error, all destinations invalid
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateHousekeepingPacket",
QUEUE_OR_DESTINATION_INVALID);
return QUEUE_OR_DESTINATION_INVALID;
}
destination = hkDestinationId;
}
return hkQueue->sendMessage(destination, &hkMessage);
}
void PeriodicHelper::performPeriodicHkGeneration(SetSpecification& setSpec, timeval& now) {
const dp::sid_t sid = setSpec.dataId.sid;
auto [tv_sec, tv_usec] = now - setSpec.lastGenerated;
if (const dur_millis_t diffMillis = tv_sec * 1000 + tv_usec / 1000;
diffMillis >= setSpec.collectionFrequency) {
const ReturnValue_t result = generateHousekeepingPacket(sid);
setSpec.lastGenerated = now;
if (result != returnvalue::OK) {
// Configuration error
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::performPeriodicHkOperation: HK generation failed."
<< std::endl;
#else
sif::printWarning(
"LocalDataPoolManager::performPeriodicHkOperation: HK generation failed.\n");
#endif
return;
}
}
}
ReturnValue_t PeriodicHelper::togglePeriodicGeneration(const dp::sid_t sid, const bool enable) {
const auto optSetSpec = getMutSetSpecification(sid);
if (!optSetSpec.has_value()) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "togglePeriodicGeneration",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
optSetSpec.value().get().periodicCollectionEnabled = enable;
return returnvalue::OK;
}
std::optional<std::reference_wrapper<SetSpecification>> PeriodicHelper::getMutSetSpecification(
dp::sid_t structureId) {
for (auto& receiver : setList) {
if (receiver.dataId.sid == structureId) {
return receiver;
}
}
return std::nullopt;
}
std::optional<std::reference_wrapper<const SetSpecification>> PeriodicHelper::getSetSpecification(
dp::sid_t structureId) const {
for (const auto& receiver : setList) {
if (receiver.dataId.sid == structureId) {
return receiver;
}
}
return std::nullopt;
}
ReturnValue_t PeriodicHelper::setCollectionInterval(dp::sid_t sid,
dur_millis_t newCollectionIntervalMs) {
bool wasUpdated = false;
for (auto& receiver : setList) {
if (receiver.dataId.sid == sid) {
receiver.collectionFrequency = newCollectionIntervalMs;
wasUpdated = true;
}
}
if (!wasUpdated) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "setCollectionInterval", DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
return returnvalue::OK;
}
ReturnValue_t PeriodicHelper::generateSetStructurePacket(dp::structure_id_t sid) {
// Get and check dataset first.
auto optSetSpec = getMutSetSpecification(sid);
if (!optSetSpec.has_value()) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "performPeriodicHkGeneration",
DATASET_NOT_FOUND);
return DATASET_NOT_FOUND;
}
auto& setSpec = optSetSpec.value().get();
uint8_t* storePtr = nullptr;
store_address_t storeId;
ReturnValue_t result = ipcStore->getFreeElement(&storeId, setSpec.serializedSize, &storePtr);
if (result != returnvalue::OK) {
printWarningOrError(sif::OutputTypes::OUT_ERROR, "generateSetStructurePacket",
returnvalue::FAILED, "Could not get free element from IPC store.");
return result;
}
dur_millis_t collectionInterval = 0;
HousekeepingSetPacket setPacket(sid, setSpec.periodicCollectionEnabled, collectionInterval);
if (result != returnvalue::OK) {
return result;
}
size_t expectedSize = setPacket.getSerializedSize();
// Serialize set packet into store.
size_t size = 0;
result = setPacket.serialize(&storePtr, &size, expectedSize, SerializeIF::Endianness::NETWORK);
if (result != returnvalue::OK) {
ipcStore->deleteData(storeId);
return result;
}
if (expectedSize != size) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, "generateSetStructurePacket",
returnvalue::FAILED, "Expected size is not equal to serialized size");
}
// Send structure reporting reply.
CommandMessage reply;
HousekeepingMessage::setHkStuctureReportReply(&reply, sid, storeId);
result = hkQueue->reply(&reply);
if (result != returnvalue::OK) {
ipcStore->deleteData(storeId);
}
return result;
}
ReturnValue_t PeriodicHelper::enablePeriodicPacket(const dp::structure_id_t structureId,
const std::optional<dur_millis_t> frequencyMs) {
// Get and check dataset first.
const auto optSetSpec = getMutSetSpecification(structureId);
if (!optSetSpec.has_value()) {
return DATASET_NOT_FOUND;
}
auto& setSpec = optSetSpec.value().get();
setSpec.periodicCollectionEnabled = true;
if (frequencyMs) {
setSpec.collectionFrequency = frequencyMs.value();
}
return returnvalue::OK;
}
ReturnValue_t PeriodicHelper::enablePeriodicPacket(const dp::structure_id_t structureId) {
return enablePeriodicPacket(structureId, std::nullopt);
}
ReturnValue_t PeriodicHelper::disablePeriodicPacket(const dp::structure_id_t structureId) {
// Get and check dataset first.
const auto optSetSpec = getMutSetSpecification(structureId);
if (!optSetSpec.has_value()) {
return DATASET_NOT_FOUND;
}
auto& setSpec = optSetSpec.value().get();
setSpec.periodicCollectionEnabled = false;
return returnvalue::OK;
}
ReturnValue_t PeriodicHelper::collectionEnabled(dp::sid_t structureId,
bool& collectionEnabled) const {
// Get and check dataset first.
const auto optSetSpec = getSetSpecification(structureId);
if (!optSetSpec.has_value()) {
return DATASET_NOT_FOUND;
}
auto& setSpec = optSetSpec.value().get();
collectionEnabled = setSpec.periodicCollectionEnabled;
return returnvalue::OK;
}
object_id_t PeriodicHelper::getCreatorObjectId() const { return owner->getObjectId(); }
void PeriodicHelper::printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t error, const char* errorPrint) {
#if FSFW_VERBOSE_LEVEL >= 1
if (errorPrint == nullptr) {
if (error == DATASET_NOT_FOUND) {
errorPrint = "Dataset not found";
} else if (error == INVALID_HK_REQUEST) {
errorPrint = "Invalid HK request";
} else if (error == returnvalue::FAILED) {
if (outputType == sif::OutputTypes::OUT_WARNING) {
errorPrint = "Generic Warning";
} else {
errorPrint = "Generic error";
}
} else if (error == QUEUE_OR_DESTINATION_INVALID) {
errorPrint = "Queue or destination not set";
} else if (error == dp::POOL_ENTRY_TYPE_CONFLICT) {
errorPrint = "Pool entry type conflict";
} else if (error == dp::POOL_ENTRY_NOT_FOUND) {
errorPrint = "Pool entry not found";
} else {
errorPrint = "Unknown error";
}
}
object_id_t objectId = 0xffffffff;
if (owner != nullptr) {
objectId = owner->getObjectId();
}
if (outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName << ": Object ID 0x" << std::setw(8)
<< std::setfill('0') << std::hex << objectId << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", functionName, objectId,
errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
} else if (outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName << ": Object ID 0x" << std::setw(8)
<< std::setfill('0') << std::hex << objectId << " | " << errorPrint << std::dec
<< std::setfill(' ') << std::endl;
#else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", functionName, objectId,
errorPrint);
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
}
#endif /* #if FSFW_VERBOSE_LEVEL >= 1 */
}
void PeriodicHelper::setHkDestinationId(const MessageQueueId_t hkDestId) {
hkDestinationId = hkDestId;
}
void PeriodicHelper::addSetSpecification(const SetSpecification& setSpec) {
setList.push_back(setSpec);
}

View File

@ -0,0 +1,193 @@
#pragma once
#include <map>
#include <optional>
#include <vector>
#include "GeneratesPeriodicHkIF.h"
#include "PeriodicHkHelperIF.h"
#include "definitions.h"
#include "fsfw/datapool/DataSetIF.h"
#include "fsfw/datapool/definitions.h"
#include "fsfw/housekeeping/HousekeepingMessage.h"
#include "fsfw/housekeeping/HousekeepingPacketDownlink.h"
#include "fsfw/ipc/CommandMessage.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/objectmanager/SystemObjectIF.h"
#include "fsfw/serviceinterface/ServiceInterface.h"
namespace hk {
/**
* @brief This class is the managing instance for the local data pool.
* @details
* The actual data pool structure is a member of this class. Any class which
* has a local data pool shall have this manager class as a member and implement
* the HasLocalDataPoolIF.
*
* The manager offers some adaption points and functions which can be used
* by the owning class to simplify data handling significantly.
*
* Please ensure that both initialize and initializeAfterTaskCreation are
* called at some point by the owning class in the respective functions of the
* same name!
*
* Users of the data pool use the helper classes LocalDataSet,
* LocalPoolVariable and LocalPoolVector to access pool entries in
* a thread-safe and efficient way.
*
* The local data pools employ a blackboard logic: Only the most recent
* value is stored. The helper classes offer a read() and commit() interface
* through the PoolVariableIF which is used to read and update values.
* Each pool entry has a valid state too.
* @author R. Mueller
*/
class PeriodicHelper : public PeriodicHelperIF {
//! Some classes using the pool manager directly need to access class internals of the
//! manager. The attorney provides granular control of access to these internals.
friend class SharedPoolAttorney;
public:
/**
* This constructor is used by a class which wants to implement
* a personal local data pool. The queueToUse can be supplied if it
* is already known.
*
* initialize() has to be called in any case before using the object!
* @param owner
* @param queueToUse
* validity state is generated when serializing or deserializing packets.
*/
PeriodicHelper(GeneratesPeriodicHkIF* owner, MessageQueueIF* queueToUse,
MessageQueueId_t hkDestQueue = MessageQueueIF::NO_QUEUE);
void setHkDestinationId(MessageQueueId_t hkDestId);
/**
* Assigns the queue to use. Make sure to call this in the #initialize
* function of the owner.
* @param queueToUse
*/
ReturnValue_t initialize(MessageQueueIF* queueToUse);
/**
* @brief This should be called in the periodic handler of the owner.
* @details
* This in generally called in the #performOperation function of the owner.
* It performs all the periodic functionalities of the data pool manager,
* for example generating periodic HK packets.
* Marked virtual as an adaption point for custom data pool managers.
* @return
*/
virtual ReturnValue_t performHkOperation();
/**
* @brief The manager is also able to handle housekeeping messages.
* @details
* This most commonly is used to handle messages for the housekeeping
* interface, but the manager is also able to handle update notifications
* and calls a special function which can be overriden by a child class
* to handle data set or pool variable updates. This is relevant
* for classes like controllers which have their own local datapool
* but pull their data from other local datapools.
* @param message
* @return
*/
virtual ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
/**
* Generate a housekeeping packet with a given SID.
* @param sid
* @return
*/
ReturnValue_t generateHousekeepingPacket(dp::sid_t sid,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
[[nodiscard]] GeneratesPeriodicHkIF* getOwner() const;
void addSetSpecification(const SetSpecification& setSpec);
ReturnValue_t printPoolEntry(dp::id_t localPoolId);
/* Copying forbidden */
PeriodicHelper(const PeriodicHkGenerationHelper&) = delete;
PeriodicHelper operator=(const PeriodicHkGenerationHelper&) = delete;
/**
* This function can be used to clear the receivers list. This is
* intended for test functions and not for regular operations, because
* the insertion operations allocate dynamically.
*/
// void clearReceiversList();
[[nodiscard]] object_id_t getCreatorObjectId() const;
/**
* Get the pointer to the mutex. Can be used to lock the data pool
* externally. Use with care and don't forget to unlock locked mutexes!
* For now, only friend classes can accss this function.
* @return
*/
MutexIF* getMutexHandle();
/**
* Set the periodic generation frequency without enabling the periodic generation of packets.
*/
ReturnValue_t enablePeriodicPacket(dp::sid_t structureId,
std::optional<dur_millis_t> frequencyMs) override;
ReturnValue_t enablePeriodicPacket(dp::sid_t structureId) override;
ReturnValue_t disablePeriodicPacket(dp::sid_t structureId) override;
ReturnValue_t collectionEnabled(dp::sid_t structureId, bool& collectionEnabled) const override;
ReturnValue_t setCollectionInterval(dp::sid_t structureId,
dur_millis_t newCollectionIntervalMs) override;
std::optional<std::reference_wrapper<SetSpecification>> getMutSetSpecification(
dp::sid_t structureId);
std::optional<std::reference_wrapper<const SetSpecification>> getSetSpecification(
dp::sid_t structureId) const;
protected:
std::optional<dur_millis_t> getCollectionFrequency(dp::sid_t structureId);
/** The class which actually owns the manager (and its datapool). */
hk::GeneratesPeriodicHkIF* owner = nullptr;
/** Default receiver for periodic HK packets */
MessageQueueId_t hkDestinationId = MessageQueueIF::NO_QUEUE;
/** This vector will contain the list of HK receivers. */
using SetList = std::vector<SetSpecification>;
SetList setList{};
/**
* @brief Queue used for communication, for example commands.
* Is also used to send messages. Can be set either in the constructor
* or in the initialize() function.
*/
MessageQueueIF* hkQueue = nullptr;
/** Global IPC store is used to store all packets. */
StorageManagerIF* ipcStore = nullptr;
ReturnValue_t serializeHkPacketIntoStore(HousekeepingPacketDownlink& hkPacket,
store_address_t& storeId, size_t* serializedSize);
void performPeriodicHkGeneration(SetSpecification& hkReceiver, timeval& now);
ReturnValue_t togglePeriodicGeneration(dp::sid_t sid, bool enable);
ReturnValue_t generateSetStructurePacket(dp::sid_t sid);
// void handleChangeResetLogic(periodicHk::DataType type, periodicHk::DataId dataId,
// MarkChangedIF* toReset);
// void resetHkUpdateResetHelper();
// ReturnValue_t addUpdateToStore(HousekeepingSnapshot& updatePacket, store_address_t& storeId);
void printWarningOrError(sif::OutputTypes outputType, const char* functionName,
ReturnValue_t errorCode = returnvalue::FAILED,
const char* errorPrint = nullptr);
};
} // namespace hk

View File

@ -0,0 +1,32 @@
#pragma once
#include <fsfw/timemanager/clockDefinitions.h>
#include "fsfw/datapool/definitions.h"
#include "fsfw/retval.h"
namespace hk {
class PeriodicHelperIF {
public:
virtual ~PeriodicHelperIF() = default;
/**
* Set the periodic generation frequency without enabling the periodic generation of packets.
*/
virtual ReturnValue_t setCollectionInterval(dp::sid_t structureId,
dur_millis_t newCollectionIntervalMs) = 0;
virtual ReturnValue_t enablePeriodicPacket(dp::sid_t structureId,
std::optional<dur_millis_t> frequencyMs) = 0;
/**
* @brief Enables periodic packet generation for a given structure, and
* keeps the previous configured collection interval.
*
* @param structureId
* @return ReturnValue_t
*/
virtual ReturnValue_t enablePeriodicPacket(dp::sid_t structureId) = 0;
virtual ReturnValue_t disablePeriodicPacket(dp::sid_t structureId) = 0;
virtual ReturnValue_t collectionEnabled(dp::sid_t structureId, bool& collectionEnabled) const = 0;
};
} // namespace hk

View File

@ -1,39 +0,0 @@
#include "fsfw/housekeeping/PeriodicHousekeepingHelper.h"
#include <cmath>
#include "fsfw/datapoollocal/LocalPoolDataSetBase.h"
#include "fsfw/serviceinterface.h"
PeriodicHousekeepingHelper::PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner)
: owner(owner) {}
void PeriodicHousekeepingHelper::initialize(float collectionInterval,
dur_millis_t minimumPeriodicInterval) {
this->minimumPeriodicInterval = minimumPeriodicInterval;
changeCollectionInterval(collectionInterval);
}
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() const {
return collectionInterval;
}
bool PeriodicHousekeepingHelper::checkOpNecessary() {
if (hkGenerationCd.hasTimedOut()) {
hkGenerationCd.resetTimer();
return true;
}
return false;
}
void PeriodicHousekeepingHelper::changeCollectionInterval(float newIntervalSeconds) {
uint32_t intervalMs = newIntervalSeconds * 1000;
if (newIntervalSeconds <= 0) {
intervalMs = minimumPeriodicInterval;
newIntervalSeconds = static_cast<float>(minimumPeriodicInterval) / 1000.0;
}
collectionInterval = newIntervalSeconds;
hkGenerationCd.setTimeout(intervalMs);
// We want an immediate HK packet at the start, so time out the generation CD immediately.
hkGenerationCd.timeOut();
}

View File

@ -1,29 +0,0 @@
#ifndef FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_
#define FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_
#include <cstdint>
#include "fsfw/timemanager/Clock.h"
#include "fsfw/timemanager/Countdown.h"
class LocalPoolDataSetBase;
class PeriodicHousekeepingHelper {
public:
PeriodicHousekeepingHelper(LocalPoolDataSetBase* owner);
void initialize(float collectionInterval, dur_millis_t minimumPeriodicInterval);
void changeCollectionInterval(float newInterval);
float getCollectionIntervalInSeconds() const;
bool checkOpNecessary();
private:
LocalPoolDataSetBase* owner = nullptr;
Countdown hkGenerationCd;
float collectionInterval = 0.0;
dur_millis_t minimumPeriodicInterval = 0;
};
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */

View File

@ -0,0 +1,86 @@
#pragma once
#include <fsfw/ipc/MessageQueueIF.h>
#include <fsfw/ipc/messageQueueDefinitions.h>
#include <fsfw/timemanager/clockDefinitions.h>
#include <cstdint>
#include <ctime>
#include "fsfw/datapool/definitions.h"
namespace hk {
static constexpr uint8_t INTERFACE_ID = CLASS_ID::PERIODIC_HK_IF;
static constexpr ReturnValue_t DATASET_NOT_FOUND = MAKE_RETURN_CODE(0);
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_INVALID = MAKE_RETURN_CODE(1);
static constexpr ReturnValue_t INVALID_HK_REQUEST = MAKE_RETURN_CODE(2);
/**
* Different types of housekeeping reporting are possible.
* 1. PERIODIC:
* HK packets are generated in fixed intervals and sent to
* destination. Fromat will be raw.
* 2. UPDATE_NOTIFICATION:
* Notification will be sent out if HK data has changed.
* 3. UPDATE_SNAPSHOT:
* HK packets are only generated if explicitely requested.
* Propably not necessary, just use multiple local data sets or
* shared datasets.
*/
enum class ReportingType : uint8_t {
//! Periodic generation of HK packets.
PERIODIC,
};
union DataId {
DataId() : sid() {}
static DataId forSetId(dp::structure_id_t sid) {
DataId d;
d.sid = sid;
return d;
}
dp::sid_t sid;
dp::id_t localPoolId;
};
/** Different data types are possible in the HK receiver map. For example, updates can be
requested for full datasets or for single pool variables. Periodic reporting is only possible
for data sets. */
enum class DataType : uint8_t { LOCAL_POOL_VARIABLE, DATA_SET };
struct SetSpecification {
friend class PeriodicHelper;
public:
SetSpecification(const dp::structure_id_t structureId, const size_t serializedSize,
const dur_millis_t collectionFrequency,
const MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE)
: dataId(DataId::forSetId(structureId)),
destinationQueue(destinationQueue),
serializedSize(serializedSize),
collectionFrequency(collectionFrequency) {};
// Object ID of receiver
object_id_t objectId = objects::NO_OBJECT;
DataType dataType = DataType::DATA_SET;
DataId dataId;
ReportingType reportingType = ReportingType::PERIODIC;
[[nodiscard]] size_t getSerializedSize() const { return serializedSize; }
[[nodiscard]] dur_millis_t getCollectionFrequency() const { return collectionFrequency; }
[[nodiscard]] bool collectionEnabled() const { return periodicCollectionEnabled; }
private:
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
bool periodicCollectionEnabled = false;
size_t serializedSize = 0;
dur_millis_t collectionFrequency = 0;
timeval lastGenerated{};
};
} // namespace hk

View File

@ -1,22 +1,24 @@
#ifndef FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#define FSFW_INTERNALERROR_INTERNALERRORDATASET_H_
#include <fsfw/datapoollocal/LocalPoolVariable.h>
#include <fsfw/datapoollocal/StaticLocalDataSet.h>
#include <fsfw/datapool/PoolVariable.h>
#include <fsfw/datapool/StaticSharedSet.h>
enum errorPoolIds { TM_HITS, QUEUE_HITS, STORE_HITS };
enum errorPoolIds { TM_HITS = 0, QUEUE_HITS = 1, STORE_HITS = 2, VALID = 3 };
class InternalErrorDataset : public StaticLocalDataSet<3 * sizeof(uint32_t)> {
class InternalErrorDataset : public dp::StaticSharedSet<4> {
public:
static constexpr uint8_t ERROR_SET_ID = 0;
InternalErrorDataset(HasLocalDataPoolIF* owner) : StaticLocalDataSet(owner, ERROR_SET_ID) {}
InternalErrorDataset(dp::SharedPool& sharedPool) : StaticSharedSet(sharedPool, ERROR_SET_ID) {}
InternalErrorDataset(object_id_t objectId) : StaticLocalDataSet(sid_t(objectId, ERROR_SET_ID)) {}
InternalErrorDataset(object_id_t objectId)
: StaticSharedSet(dp::structure_id_t(objectId, ERROR_SET_ID)) {}
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);
dp::var_t<uint32_t> tmHits = dp::var_t<uint32_t>(sid.objectId, TM_HITS, this);
dp::var_t<uint32_t> queueHits = dp::var_t<uint32_t>(sid.objectId, QUEUE_HITS, this);
dp::var_t<uint32_t> storeHits = dp::var_t<uint32_t>(sid.objectId, STORE_HITS, this);
dp::var_t<uint8_t> valid = dp::var_t<uint8_t>(sid.objectId, VALID, this);
};
#endif /* FSFW_INTERNALERROR_INTERNALERRORDATASET_H_ */

View File

@ -6,16 +6,18 @@
#include "fsfw/serviceinterface/ServiceInterface.h"
InternalErrorReporter::InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency)
bool enableSetByDefault,
dur_millis_t generationFrequency)
: SystemObject(setObjectId),
poolManager(this, commandQueue),
sharedPool(getObjectId()),
hkHelper(this, nullptr),
enableSetByDefault(enableSetByDefault),
generationFrequency(generationFrequency),
internalErrorSid(setObjectId, InternalErrorDataset::ERROR_SET_ID),
internalErrorDataset(this) {
internalErrorDataset(sharedPool) {
commandQueue = QueueFactory::instance()->createMessageQueue(messageQueueDepth);
mutex = MutexFactory::instance()->createMutex();
auto mqArgs = MqArgs(setObjectId, static_cast<void *>(this));
auto mqArgs = MqArgs(setObjectId, this);
commandQueue = QueueFactory::instance()->createMessageQueue(
messageQueueDepth, MessageQueueMessage::MAX_MESSAGE_SIZE, &mqArgs);
}
@ -29,11 +31,25 @@ void InternalErrorReporter::setDiagnosticPrintout(bool enable) {
this->diagnosticPrintout = enable;
}
ReturnValue_t InternalErrorReporter::initialize() {
ReturnValue_t result = hkHelper.initialize(commandQueue);
if (result != returnvalue::OK) {
return result;
}
sharedPool.addPoolEntry(errorPoolIds::STORE_HITS, &storeHitsEntry);
sharedPool.addPoolEntry(errorPoolIds::TM_HITS, &tmHitsEntry);
sharedPool.addPoolEntry(errorPoolIds::QUEUE_HITS, &queueHitsEntry);
sharedPool.addPoolEntry(errorPoolIds::VALID, &setIsValid);
internalErrorDataset.valid = false;
return SystemObject::initialize();
}
ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
CommandMessage message;
ReturnValue_t result = commandQueue->receiveMessage(&message);
if (result != MessageQueueIF::EMPTY) {
poolManager.handleHousekeepingMessage(&message);
hkHelper.handleHousekeepingMessage(&message);
}
uint32_t newQueueHits = getAndResetQueueHits();
@ -64,14 +80,11 @@ ReturnValue_t InternalErrorReporter::performOperation(uint8_t opCode) {
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);
}
internalErrorDataset.valid = true;
}
}
poolManager.performHkOperation();
hkHelper.performHkOperation();
return returnvalue::OK;
}
@ -132,42 +145,27 @@ 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.subscribeForRegularPeriodicPacket(
subdp::RegularHkPeriodicParams(internalErrorSid, enableSetByDefault, generationFrequency));
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; }
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; }
ReturnValue_t InternalErrorReporter::serializeHkDataset(dp::structure_id_t structureId,
uint8_t *buf, size_t maxSize) {
if (structureId == internalErrorDataset.getStructureId()) {
size_t serSize = 0;
return internalErrorDataset.serialize(buf, serSize, maxSize, SerializeIF::Endianness::NETWORK);
}
return returnvalue::FAILED;
}
ReturnValue_t InternalErrorReporter::specifyHkDatasets(
std::vector<hk::SetSpecification> &setSpecification) {
setSpecification.emplace_back(internalErrorDataset.getStructureId(),
internalErrorDataset.getSerializedSize(), generationFrequency);
return returnvalue::OK;
}
dp::SharedPool *InternalErrorReporter::getOptionalSharedPool() { return &sharedPool; }

View File

@ -1,8 +1,10 @@
#ifndef FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#define FSFW_INTERNALERROR_INTERNALERRORREPORTER_H_
#include <fsfw/housekeeping/PeriodicHkHelper.h>
#include "InternalErrorReporterIF.h"
#include "fsfw/datapoollocal/LocalDataPoolManager.h"
#include "fsfw/housekeeping/GeneratesPeriodicHkIF.h"
#include "fsfw/internalerror/InternalErrorDataset.h"
#include "fsfw/ipc/MutexIF.h"
#include "fsfw/objectmanager/SystemObject.h"
@ -19,10 +21,10 @@
class InternalErrorReporter : public SystemObject,
public ExecutableObjectIF,
public InternalErrorReporterIF,
public HasLocalDataPoolIF {
public hk::GeneratesPeriodicHkIF {
public:
InternalErrorReporter(object_id_t setObjectId, uint32_t messageQueueDepth,
bool enableSetByDefault, float generationFrequency);
bool enableSetByDefault, dur_millis_t generationFrequency);
/**
* Enable diagnostic printout. Please note that this feature will
@ -33,31 +35,32 @@ class InternalErrorReporter : public SystemObject,
void setMutexTimeout(MutexIF::TimeoutType timeoutType, uint32_t timeoutMs);
virtual ~InternalErrorReporter();
~InternalErrorReporter() override;
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;
[[nodiscard]] object_id_t getObjectId() const override;
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
virtual ReturnValue_t initialize() override;
virtual ReturnValue_t initializeAfterTaskCreation() override;
virtual ReturnValue_t performOperation(uint8_t opCode) override;
dp::SharedPool* getOptionalSharedPool() override;
virtual void queueMessageNotSent() override;
ReturnValue_t serializeHkDataset(dp::sid_t structureId, uint8_t* buf, size_t maxSize) override;
virtual void lostTm() override;
ReturnValue_t specifyHkDatasets(std::vector<hk::SetSpecification>& setSpecification) override;
virtual void storeFull() override;
ReturnValue_t initialize() override;
ReturnValue_t performOperation(uint8_t opCode) override;
virtual void setTaskIF(PeriodicTaskIF* task) override;
void queueMessageNotSent() override;
void lostTm() override;
void storeFull() override;
void setTaskIF(PeriodicTaskIF* task) override;
protected:
MessageQueueIF* commandQueue;
LocalDataPoolManager poolManager;
dp::SharedPool sharedPool;
hk::PeriodicHelper hkHelper;
PeriodicTaskIF* executingTask = nullptr;
@ -65,9 +68,9 @@ class InternalErrorReporter : public SystemObject,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING;
uint32_t timeoutMs = 20;
bool enableSetByDefault;
float generationFrequency;
dur_millis_t generationFrequency;
sid_t internalErrorSid;
dp::structure_id_t internalErrorSid;
InternalErrorDataset internalErrorDataset;
bool diagnosticPrintout = true;
@ -75,6 +78,7 @@ class InternalErrorReporter : public SystemObject,
uint32_t queueHits = 0;
uint32_t tmHits = 0;
uint32_t storeHits = 0;
PoolEntry<uint8_t> setIsValid = PoolEntry<uint8_t>();
PoolEntry<uint32_t> tmHitsEntry = PoolEntry<uint32_t>();
PoolEntry<uint32_t> storeHitsEntry = PoolEntry<uint32_t>();
PoolEntry<uint32_t> queueHitsEntry = PoolEntry<uint32_t>();

View File

@ -9,7 +9,7 @@
template <typename T>
class AbsLimitMonitor : public MonitorBase<T> {
public:
AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId, gp_id_t globalPoolId,
AbsLimitMonitor(object_id_t reporterId, uint8_t monitorId, dp::g_id_t globalPoolId,
uint16_t confirmationLimit, T limit,
Event violationEvent = MonitoringIF::VALUE_OUT_OF_RANGE,
bool aboveIsViolation = true)

View File

@ -13,7 +13,7 @@
template <typename T>
class LimitMonitor : public MonitorBase<T> {
public:
LimitMonitor(object_id_t reporterId, uint8_t monitorId, gp_id_t globalPoolId,
LimitMonitor(object_id_t reporterId, uint8_t monitorId, dp::g_id_t globalPoolId,
uint16_t confirmationLimit, T lowerLimit, T upperLimit,
Event belowLowEvent = MonitoringIF::VALUE_BELOW_LOW_LIMIT,
Event aboveHighEvent = MonitoringIF::VALUE_ABOVE_HIGH_LIMIT)

View File

@ -1,11 +1,11 @@
#ifndef FSFW_MONITORING_MONITORBASE_H_
#define FSFW_MONITORING_MONITORBASE_H_
#include "../datapoollocal/LocalPoolVariable.h"
#include "LimitViolationReporter.h"
#include "MonitorReporter.h"
#include "MonitoringIF.h"
#include "MonitoringMessageContent.h"
#include "fsfw/datapool/PoolVariable.h"
#include "monitoringConf.h"
/**
@ -22,7 +22,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, dp::g_id_t globalPoolId,
uint16_t confirmationLimit)
: MonitorReporter<T>(reporterId, monitorId, globalPoolId, confirmationLimit),
poolVariable(globalPoolId) {}
@ -59,14 +59,11 @@ class MonitorBase : public MonitorReporter<T> {
if (result != returnvalue::OK) {
return result;
}
if (not poolVariable.isValid()) {
return MonitoringIF::INVALID;
}
*sample = poolVariable.value;
return returnvalue::OK;
}
LocalPoolVariable<T> poolVariable;
dp::PoolVariable<T> poolVariable;
};
#endif /* FSFW_MONITORING_MONITORBASE_H_ */

View File

@ -1,12 +1,11 @@
#ifndef FSFW_MONITORING_MONITORREPORTER_H_
#define FSFW_MONITORING_MONITORREPORTER_H_
#pragma once
#include "../datapoollocal/localPoolDefinitions.h"
#include "../events/EventManagerIF.h"
#include "../parameters/HasParametersIF.h"
#include "LimitViolationReporter.h"
#include "MonitoringIF.h"
#include "MonitoringMessageContent.h"
#include "fsfw/datapool/definitions.h"
#include "monitoringConf.h"
template <typename T>
@ -17,7 +16,7 @@ class MonitorReporter : public HasParametersIF {
// TODO: Adapt to use SID instead of parameter ID.
MonitorReporter(object_id_t reportingId, uint8_t monitorId, gp_id_t globalPoolId,
MonitorReporter(object_id_t reportingId, uint8_t monitorId, dp::g_id_t globalPoolId,
uint16_t confirmationLimit)
: monitorId(monitorId),
globalPoolId(globalPoolId),
@ -84,7 +83,7 @@ class MonitorReporter : public HasParametersIF {
protected:
const uint8_t monitorId;
const gp_id_t globalPoolId;
const dp::g_id_t globalPoolId;
object_id_t reportingId;
ReturnValue_t oldState;
@ -162,5 +161,3 @@ class MonitorReporter : public HasParametersIF {
return returnvalue::OK;
}
};
#endif /* FSFW_MONITORING_MONITORREPORTER_H_ */

View File

@ -1,7 +1,5 @@
#ifndef FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
#define FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_
#pragma once
#include "../datapoollocal/localPoolDefinitions.h"
#include "../objectmanager/ObjectManager.h"
#include "../serialize/SerialBufferAdapter.h"
#include "../serialize/SerialFixedArrayListAdapter.h"
@ -11,6 +9,7 @@
#include "../timemanager/TimeWriterIF.h"
#include "HasMonitorsIF.h"
#include "MonitoringIF.h"
#include "fsfw/datapool/definitions.h"
#include "monitoringConf.h"
namespace Factory {
@ -29,7 +28,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
public:
SerializeElement<uint8_t> monitorId;
SerializeElement<uint32_t> parameterObjectId;
SerializeElement<lp_id_t> localPoolId;
SerializeElement<dp::id_t> localPoolId;
SerializeElement<T> parameterValue;
SerializeElement<T> limitValue;
SerializeElement<ReturnValue_t> oldState;
@ -50,7 +49,7 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
timeStamper(nullptr) {
setAllNext();
}
MonitoringReportContent(gp_id_t globalPoolId, T value, T limitValue, ReturnValue_t oldState,
MonitoringReportContent(dp::g_id_t globalPoolId, T value, T limitValue, ReturnValue_t oldState,
ReturnValue_t newState)
: SerialLinkedListAdapter<SerializeIF>(&parameterObjectId),
monitorId(0),
@ -94,5 +93,3 @@ class MonitoringReportContent : public SerialLinkedListAdapter<SerializeIF> {
};
template <typename T>
object_id_t MonitoringReportContent<T>::timeStamperId = 0;
#endif /* FSFW_MONITORING_MONITORINGMESSAGECONTENT_H_ */

View File

@ -54,9 +54,8 @@ ReturnValue_t Clock::getClockMonotonic(timeval* time) {
// generic is kind of awkward..
return returnvalue::FAILED;
#elif defined(PLATFORM_UNIX)
timespec timeMonotonic;
int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic);
if (status != 0) {
timespec timeMonotonic{};
if (const int status = clock_gettime(CLOCK_MONOTONIC_RAW, &timeMonotonic); status != 0) {
return returnvalue::FAILED;
}
time->tv_sec = timeMonotonic.tv_sec;

View File

@ -8,19 +8,16 @@
object_id_t Fuse::powerSwitchId = 0;
Fuse::Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
float maxCurrent, uint16_t confirmationCount)
Fuse::Fuse(object_id_t ownerId, object_id_t fuseObjectId, uint8_t fuseId,
dp::structure_id_t variableSet, VariableIds ids, float maxCurrent,
uint16_t confirmationCount)
: SystemObject(fuseObjectId),
oldFuseState(0),
fuseId(fuseId),
currentLimit(fuseObjectId, 1, ids.pidCurrent, confirmationCount, maxCurrent,
FUSE_CURRENT_HIGH),
powerMonitor(fuseObjectId, 2, ids.poolIdPower, confirmationCount),
set(variableSet),
voltage(ids.pidVoltage, &set),
current(ids.pidCurrent, &set),
state(ids.pidState, &set),
power(ids.poolIdPower, &set, PoolVariableIF::VAR_READ_WRITE),
set(ownerId),
parameterHelper(this),
healthHelper(this, fuseObjectId) {
commandQueue = QueueFactory::instance()->createMessageQueue();
@ -63,20 +60,20 @@ ReturnValue_t Fuse::check() {
set.read();
if (!healthHelper.healthTable->isHealthy(getObjectId())) {
setAllMonitorsToUnchecked();
set.setValidity(false, true);
set.setValid = false;
return set.commit();
}
ReturnValue_t result = returnvalue::OK;
checkFuseState();
calculateFusePower();
// Check if power is valid and if fuse state is off or invalid.
if (!power.isValid() || (state == 0) || !state.isValid()) {
if (!set.setValid.value || (set.state == 0)) {
result = powerMonitor.setToInvalid();
} else {
float lowLimit = 0.0;
float highLimit = RESIDUAL_POWER;
calculatePowerLimits(&lowLimit, &highLimit);
result = powerMonitor.checkPower(power.value, lowLimit, highLimit);
result = powerMonitor.checkPower(set.power.value, lowLimit, highLimit);
if (result == MonitoringIF::BELOW_LOW_LIMIT) {
reportEvents(POWER_BELOW_LOW_LIMIT);
} else if (result == MonitoringIF::ABOVE_HIGH_LIMIT) {
@ -122,13 +119,12 @@ uint8_t Fuse::getFuseId() const { return fuseId; }
void Fuse::calculateFusePower() {
ReturnValue_t result1 = currentLimit.check();
if (result1 != returnvalue::OK || !(voltage.isValid())) {
power.setValid(PoolVariableIF::INVALID);
return;
if (result1 != returnvalue::OK || !(set.setValid.value)) {
set.powerValid = false;
}
// Calculate fuse power.
power.value = current.value * voltage.value;
power.setValid(PoolVariableIF::VALID);
set.power = set.current.value * set.voltage.value;
set.powerValid = true;
}
ReturnValue_t Fuse::performOperation(uint8_t opCode) {
@ -173,21 +169,21 @@ void Fuse::checkCommandQueue() {
}
void Fuse::checkFuseState() {
if (!state.isValid()) {
if (!set.setValid.value) {
oldFuseState = 0;
return;
}
if (state == 0) {
if (set.state == 0) {
if (oldFuseState != 0) {
reportEvents(FUSE_WENT_OFF);
}
}
oldFuseState = state.value;
oldFuseState = set.state.value;
}
float Fuse::getPower() {
if (power.isValid()) {
return power.value;
if (set.powerValid.value) {
return set.power.value;
} else {
return 0.0;
}
@ -195,7 +191,8 @@ float Fuse::getPower() {
void Fuse::setDataPoolEntriesInvalid() {
set.read();
set.setValidity(false, true);
set.setValid = false;
set.powerValid = false;
set.commit();
}
@ -223,7 +220,7 @@ bool Fuse::areSwitchesOfComponentOn(DeviceList::iterator iter) {
return true;
}
bool Fuse::isPowerValid() { return power.isValid(); }
bool Fuse::isPowerValid() { return set.powerValid.value; }
ReturnValue_t Fuse::setHealth(HealthState health) {
healthHelper.setHealth(health);

View File

@ -3,17 +3,44 @@
#include <list>
#include "../datapoollocal/StaticLocalDataSet.h"
#include "../devicehandlers/HealthDevice.h"
#include "../monitoring/AbsLimitMonitor.h"
#include "../parameters/ParameterHelper.h"
#include "../returnvalues/returnvalue.h"
#include "PowerComponentIF.h"
#include "PowerSwitchIF.h"
#include "fsfw/datapool/StaticSharedSet.h"
#include "fsfw/devicehandlers/HealthDevice.h"
#include "fsfw/monitoring/AbsLimitMonitor.h"
#include "fsfw/parameters/ParameterHelper.h"
#include "fsfw/returnvalues/returnvalue.h"
namespace Factory {
void setStaticFrameworkObjectIds();
}
enum FusePoolId {
VOLTAGE = 0,
CURRENT = 1,
STATE = 2,
POWER = 3,
POWER_VALID = 4,
SET_VALID = 5
};
class FuseSet : public datapool::StaticSharedSet<6> {
public:
static constexpr uint8_t FUSE_SET_ID = 0;
FuseSet(dp::SharedPool &sharedPool) : StaticSharedSet(sharedPool, FUSE_SET_ID) {}
FuseSet(object_id_t objectId) : StaticSharedSet(dp::sid_t(objectId, FUSE_SET_ID)) {}
dp::f32_t voltage = dp::f32_t(sid.objectId, FusePoolId::VOLTAGE, this);
dp::f32_t current = dp::f32_t(sid.objectId, FusePoolId::CURRENT, this);
dp::u8_t state = dp::u8_t(sid.objectId, FusePoolId::STATE, this);
dp::f32_t power = dp::f32_t(sid.objectId, FusePoolId::POWER, this);
dp::u8_t powerValid = dp::u8_t(sid.objectId, FusePoolId::POWER_VALID, this);
dp::u8_t setValid = dp::u8_t(sid.objectId, FusePoolId::SET_VALID, this);
};
class Fuse : public SystemObject,
public HasHealthIF,
public ReceivesParameterMessagesIF,
@ -26,10 +53,10 @@ class Fuse : public SystemObject,
//!< Worst case is Fuse and one of two switches on. See PCDU ICD 1.9 p29 bottom
public:
struct VariableIds {
gp_id_t pidVoltage;
gp_id_t pidCurrent;
gp_id_t pidState;
gp_id_t poolIdPower;
dp::g_id_t pidVoltage;
dp::g_id_t pidCurrent;
dp::g_id_t pidState;
dp::g_id_t poolIdPower;
};
static const uint8_t SUBSYSTEM_ID = SUBSYSTEM_ID::POWER_SWITCH_IF;
@ -43,8 +70,8 @@ class Fuse : public SystemObject,
static const Event POWER_BELOW_LOW_LIMIT = MAKE_EVENT(5, severity::LOW);
typedef std::list<PowerComponentIF *> DeviceList;
Fuse(object_id_t fuseObjectId, uint8_t fuseId, sid_t variableSet, VariableIds ids,
float maxCurrent, uint16_t confirmationCount = 2);
Fuse(object_id_t ownerId, object_id_t fuseObjectId, uint8_t fuseId, dp::sid_t variableSet,
VariableIds ids, float maxCurrent, uint16_t confirmationCount = 2);
virtual ~Fuse();
void addDevice(PowerComponentIF *set);
float getPower();
@ -83,13 +110,8 @@ class Fuse : public SystemObject,
void sendTransitionEvent(float currentValue, ReturnValue_t state) {}
};
PowerMonitor powerMonitor;
StaticLocalDataSet<3> set;
lp_var_t<float> voltage;
lp_var_t<float> current;
lp_var_t<uint8_t> state;
lp_var_t<float> power;
FuseSet set;
MessageQueueIF *commandQueue = nullptr;
ParameterHelper parameterHelper;
HealthHelper healthHelper;

View File

@ -1,16 +1,15 @@
#include "fsfw/power/PowerSensor.h"
#include "definitions.h"
#include "fsfw/ipc/QueueFactory.h"
PowerSensor::PowerSensor(object_id_t objectId, sid_t setId, VariableIds ids, DefaultLimits limits,
SensorEvents events, uint16_t confirmationCount)
PowerSensor::PowerSensor(object_id_t objectId, dp::structure_id_t setId, VariableIds ids,
DefaultLimits limits, SensorEvents events, uint16_t confirmationCount)
: SystemObject(objectId),
parameterHelper(this),
healthHelper(this, objectId),
powerSensorSet(setId),
current(ids.pidCurrent, &powerSensorSet),
voltage(ids.pidVoltage, &powerSensorSet),
power(ids.poolIdPower, &powerSensorSet, PoolVariableIF::VAR_WRITE),
powerSensorSet(objectId),
// valid(ids.valid, &powerSensorSet),
currentLimit(objectId, MODULE_ID_CURRENT, ids.pidCurrent, confirmationCount,
limits.currentMin, limits.currentMax, events.currentLow, events.currentHigh),
voltageLimit(objectId, MODULE_ID_VOLTAGE, ids.pidVoltage, confirmationCount,
@ -24,10 +23,9 @@ ReturnValue_t PowerSensor::calculatePower() {
powerSensorSet.read();
ReturnValue_t result1 = returnvalue::FAILED;
ReturnValue_t result2 = returnvalue::FAILED;
if (healthHelper.healthTable->isHealthy(getObjectId()) && voltage.isValid() &&
current.isValid()) {
result1 = voltageLimit.doCheck(voltage.value);
result2 = currentLimit.doCheck(current.value);
if (healthHelper.healthTable->isHealthy(getObjectId()) && powerSensorSet.setIsValid.value) {
result1 = voltageLimit.doCheck(powerSensorSet.voltage.value);
result2 = currentLimit.doCheck(powerSensorSet.current.value);
} else {
voltageLimit.setToInvalid();
currentLimit.setToInvalid();
@ -35,10 +33,10 @@ ReturnValue_t PowerSensor::calculatePower() {
}
if (result1 != returnvalue::OK || result2 != returnvalue::OK) {
result1 = MonitoringIF::INVALID;
power.setValid(PoolVariableIF::INVALID);
powerSensorSet.setIsValid = false;
} else {
power.setValid(PoolVariableIF::VALID);
power.value = current.value * voltage.value;
powerSensorSet.setIsValid = true;
powerSensorSet.power = powerSensorSet.current.value * powerSensorSet.voltage.value;
}
powerSensorSet.commit();
return result1;
@ -92,13 +90,13 @@ void PowerSensor::checkCommandQueue() {
void PowerSensor::setDataPoolEntriesInvalid() {
powerSensorSet.read();
powerSensorSet.setValidity(false, true);
powerSensorSet.setIsValid = false;
powerSensorSet.commit();
}
float PowerSensor::getPower() {
if (power.isValid()) {
return power.value;
if (powerSensorSet.setIsValid.value) {
return powerSensorSet.power.value;
} else {
return 0.0;
}

View File

@ -1,7 +1,7 @@
#ifndef FSFW_POWER_POWERSENSOR_H_
#define FSFW_POWER_POWERSENSOR_H_
#include "fsfw/datapoollocal/StaticLocalDataSet.h"
#include "fsfw/datapool/StaticSharedSet.h"
#include "fsfw/devicehandlers/HealthDevice.h"
#include "fsfw/ipc/MessageQueueIF.h"
#include "fsfw/monitoring/LimitMonitor.h"
@ -10,6 +10,27 @@
class PowerController;
enum PowerSensorPoolId {
CURRENT = 0,
VOLTAGE = 1,
POWER = 2,
SET_VALID = 3
};
class PowerSensorSet : public dp::StaticSharedSet<6> {
public:
static constexpr uint8_t POWER_SENSOR_SET_ID = 0;
PowerSensorSet(dp::SharedPool &sharedPool) : StaticSharedSet(sharedPool, POWER_SENSOR_SET_ID) {}
PowerSensorSet(object_id_t objectId)
: StaticSharedSet(dp::sid_t(objectId, POWER_SENSOR_SET_ID)) {}
dp::f32_t current{sid.objectId, PowerSensorPoolId::CURRENT, this};
dp::f32_t voltage{sid.objectId, PowerSensorPoolId::VOLTAGE, this};
dp::f32_t power = {sid.objectId, PowerSensorPoolId::POWER, this};
dp::u8_t setIsValid{sid.objectId, PowerSensorPoolId::SET_VALID, this};
};
/**
* @brief Does magic.
*/
@ -18,9 +39,10 @@ class PowerSensor : public SystemObject, public ReceivesParameterMessagesIF, pub
public:
struct VariableIds {
gp_id_t pidCurrent;
gp_id_t pidVoltage;
gp_id_t poolIdPower;
dp::g_id_t pidCurrent;
dp::g_id_t pidVoltage;
dp::g_id_t poolIdPower;
dp::g_id_t valid;
};
struct DefaultLimits {
float currentMin;
@ -34,7 +56,7 @@ class PowerSensor : public SystemObject, public ReceivesParameterMessagesIF, pub
Event voltageLow;
Event voltageHigh;
};
PowerSensor(object_id_t objectId, sid_t sid, VariableIds setIds, DefaultLimits limits,
PowerSensor(object_id_t objectId, dp::sid_t sid, VariableIds setIds, DefaultLimits limits,
SensorEvents events, uint16_t confirmationCount = 0);
virtual ~PowerSensor();
ReturnValue_t calculatePower();
@ -53,16 +75,7 @@ class PowerSensor : public SystemObject, public ReceivesParameterMessagesIF, pub
MessageQueueIF *commandQueue = nullptr;
ParameterHelper parameterHelper;
HealthHelper healthHelper;
// GlobDataSet set;
StaticLocalDataSet<3> powerSensorSet;
// Variables in
lp_var_t<float> current;
lp_var_t<float> voltage;
// PIDReader<float> current;
// PIDReader<float> voltage;
// Variables out
lp_var_t<float> power;
// gp_float_t power;
PowerSensorSet powerSensorSet;
static const uint8_t MODULE_ID_CURRENT = 1;
static const uint8_t MODULE_ID_VOLTAGE = 2;

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