Merge pull request 'Additional Update for Local Data Pools' (#367) from mueller/fsfw-update-2 into development

Reviewed-on: fsfw/fsfw#367
This commit is contained in:
Steffen Gaisser 2021-02-09 15:20:25 +01:00
commit 8a1f043b39
19 changed files with 2558 additions and 2521 deletions

View File

@ -81,4 +81,7 @@ now
For the fsfw, this can be done by checking the processor define FSFW_CPP_OSTREAM_ENABLED from FSFWConfig.h. For the fsfw, this can be done by checking the processor define FSFW_CPP_OSTREAM_ENABLED from FSFWConfig.h.
For mission code, developers need to replace sif:: calls by the printf counterparts, but only if the CPP stream are excluded. For mission code, developers need to replace sif:: calls by the printf counterparts, but only if the CPP stream are excluded.
If this is not the case, everything should work as usual. If this is not the case, everything should work as usual.
-
### PUS Parameter Service 20
Added PUS parameter service 20 (only custom subservices available).

View File

@ -1,4 +1,4 @@
target_sources(${LIB_FSFW_NAME} target_sources(${LIB_FSFW_NAME} PRIVATE
PRIVATE ControllerBase.cpp
ControllerBase.cpp ExtendedControllerBase.cpp
) )

View File

@ -8,6 +8,9 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
actionHelper(this, commandQueue) { actionHelper(this, commandQueue) {
} }
ExtendedControllerBase::~ExtendedControllerBase() {
}
ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId, ReturnValue_t ExtendedControllerBase::executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t *data, size_t size) { 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.

View File

@ -22,13 +22,14 @@ class ExtendedControllerBase: public ControllerBase,
public: public:
ExtendedControllerBase(object_id_t objectId, object_id_t parentId, ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
size_t commandQueueDepth = 3); size_t commandQueueDepth = 3);
virtual ~ExtendedControllerBase();
/** SystemObjectIF overrides */ /* SystemObjectIF overrides */
virtual ReturnValue_t initialize() override; virtual ReturnValue_t initialize() override;
virtual MessageQueueId_t getCommandQueue() const override; virtual MessageQueueId_t getCommandQueue() const override;
/** ExecutableObjectIF overrides */ /* ExecutableObjectIF overrides */
virtual ReturnValue_t performOperation(uint8_t opCode) override; virtual ReturnValue_t performOperation(uint8_t opCode) override;
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
@ -49,15 +50,15 @@ protected:
*/ */
virtual void performControlOperation() = 0; virtual void performControlOperation() = 0;
/** Handle the four messages mentioned above */ /* Handle the four messages mentioned above */
void handleQueue() override; void handleQueue() override;
/** HasActionsIF overrides */ /* HasActionsIF overrides */
virtual ReturnValue_t executeAction(ActionId_t actionId, virtual ReturnValue_t executeAction(ActionId_t actionId,
MessageQueueId_t commandedBy, const uint8_t* data, MessageQueueId_t commandedBy, const uint8_t* data,
size_t size) override; size_t size) override;
/** HasLocalDatapoolIF overrides */ /* HasLocalDatapoolIF overrides */
virtual LocalDataPoolManager* getHkManagerHandle() override; virtual LocalDataPoolManager* getHkManagerHandle() override;
virtual object_id_t getObjectId() const override; virtual object_id_t getObjectId() const override;
virtual ReturnValue_t initializeLocalDataPool( virtual ReturnValue_t initializeLocalDataPool(

View File

@ -1,5 +1,6 @@
#include "PoolDataSetBase.h" #include "PoolDataSetBase.h"
#include "../serviceinterface/ServiceInterfaceStream.h" #include "../serviceinterface/ServiceInterfaceStream.h"
#include <cstring>
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray, PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount): const size_t maxFillCount):

View File

@ -39,8 +39,12 @@ public:
* supply a pointer to this dataset to PoolVariable * supply a pointer to this dataset to PoolVariable
* initializations to register pool variables. * initializations to register pool variables.
*/ */
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, PoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxFillCount);
const size_t maxFillCount);
/* Forbidden for now */
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
virtual~ PoolDataSetBase(); virtual~ PoolDataSetBase();
/** /**
@ -63,8 +67,7 @@ public:
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling * - @c SET_WAS_ALREADY_READ if read() is called twice without calling
* commit() in between * commit() in between
*/ */
virtual ReturnValue_t read( virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**
* @brief The commit call initializes writing back the registered variables. * @brief The commit call initializes writing back the registered variables.
@ -84,8 +87,7 @@ public:
* - @c COMMITING_WITHOUT_READING if set was not read yet and * - @c COMMITING_WITHOUT_READING if set was not read yet and
* contains non write-only variables * contains non write-only variables
*/ */
virtual ReturnValue_t commit( virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
uint32_t lockTimeout = 20) override; uint32_t lockTimeout = 20) override;
/** /**

View File

@ -80,7 +80,7 @@ public:
* @param storeId If a snapshot was requested, data will be located inside * @param storeId If a snapshot was requested, data will be located inside
* the IPC store with this store ID. * the IPC store with this store ID.
*/ */
virtual void handleChangedPoolVariable(lp_id_t poolId, virtual void handleChangedPoolVariable(gp_id_t globPoolId,
store_address_t storeId = storeId::INVALID_STORE_ADDRESS) { store_address_t storeId = storeId::INVALID_STORE_ADDRESS) {
return; return;
} }

View File

@ -102,7 +102,7 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() {
switch(receiver.reportingType) { switch(receiver.reportingType) {
case(ReportingType::PERIODIC): { case(ReportingType::PERIODIC): {
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
// Periodic packets shall only be generated from datasets. /* Periodic packets shall only be generated from datasets */
continue; continue;
} }
performPeriodicHkGeneration(receiver); performPeriodicHkGeneration(receiver);
@ -156,19 +156,17 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId); receiver.dataId.localPoolId);
//LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle(receiver.dataId.localPoolId);
if(poolObj == nullptr) { if(poolObj == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, printWarningOrError(sif::OutputTypes::OUT_WARNING,
"handleNotificationUpdate", POOLOBJECT_NOT_FOUND); "handleNotificationUpdate", POOLOBJECT_NOT_FOUND);
return POOLOBJECT_NOT_FOUND; return POOLOBJECT_NOT_FOUND;
} }
if(poolObj->hasChanged()) { if(poolObj->hasChanged()) {
// prepare and send update notification. /* Prepare and send update notification. */
CommandMessage notification; CommandMessage notification;
HousekeepingMessage::setUpdateNotificationVariableCommand(&notification, HousekeepingMessage::setUpdateNotificationVariableCommand(&notification,
receiver.dataId.localPoolId); gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId));
ReturnValue_t result = hkQueue->sendMessage( ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, &notification);
receiver.destinationQueue, &notification);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
status = result; status = result;
} }
@ -185,10 +183,10 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
return DATASET_NOT_FOUND; return DATASET_NOT_FOUND;
} }
if(dataSet->hasChanged()) { if(dataSet->hasChanged()) {
// prepare and send update notification /* Prepare and send update notification */
CommandMessage notification; CommandMessage notification;
HousekeepingMessage::setUpdateNotificationSetCommand( HousekeepingMessage::setUpdateNotificationSetCommand(&notification,
&notification, receiver.dataId.sid); receiver.dataId.sid);
ReturnValue_t result = hkQueue->sendMessage( ReturnValue_t result = hkQueue->sendMessage(
receiver.destinationQueue, &notification); receiver.destinationQueue, &notification);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
@ -198,8 +196,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
} }
} }
if(toReset != nullptr) { if(toReset != nullptr) {
handleChangeResetLogic(receiver.dataType, handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset);
receiver.dataId, toReset);
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -207,7 +204,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot( ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
HkReceiver& receiver, ReturnValue_t& status) { HkReceiver& receiver, ReturnValue_t& status) {
MarkChangedIF* toReset = nullptr; MarkChangedIF* toReset = nullptr;
// check whether data has changed and send messages in case it has. /* Check whether data has changed and send messages in case it has */
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) { if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
receiver.dataId.localPoolId); receiver.dataId.localPoolId);
@ -221,14 +218,14 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
// prepare and send update snapshot. /* Prepare and send update snapshot */
timeval now; timeval now;
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
CCSDSTime::convertToCcsds(&cds, &now); CCSDSTime::convertToCcsds(&cds, &now);
HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds), HousekeepingSnapshot updatePacket(reinterpret_cast<uint8_t*>(&cds), sizeof(cds),
sizeof(cds), HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner, HasLocalDpIFManagerAttorney::getPoolObjectHandle(
receiver.dataId.localPoolId)); owner,receiver.dataId.localPoolId));
store_address_t storeId; store_address_t storeId;
ReturnValue_t result = addUpdateToStore(updatePacket, storeId); ReturnValue_t result = addUpdateToStore(updatePacket, storeId);
@ -238,7 +235,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
CommandMessage notification; CommandMessage notification;
HousekeepingMessage::setUpdateSnapshotVariableCommand(&notification, HousekeepingMessage::setUpdateSnapshotVariableCommand(&notification,
receiver.dataId.localPoolId, storeId); gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId), storeId);
result = hkQueue->sendMessage(receiver.destinationQueue, result = hkQueue->sendMessage(receiver.destinationQueue,
&notification); &notification);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
@ -259,7 +256,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
// prepare and send update snapshot. /* Prepare and send update snapshot */
timeval now; timeval now;
Clock::getClock_timeval(&now); Clock::getClock_timeval(&now);
CCSDSTime::CDS_short cds; CCSDSTime::CDS_short cds;
@ -309,7 +306,7 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(
void LocalDataPoolManager::handleChangeResetLogic( void LocalDataPoolManager::handleChangeResetLogic(
DataType type, DataId dataId, MarkChangedIF* toReset) { DataType type, DataId dataId, MarkChangedIF* toReset) {
if(hkUpdateResetList == nullptr) { if(hkUpdateResetList == nullptr) {
// config error! /* Config error */
return; return;
} }
HkUpdateResetList& listRef = *hkUpdateResetList; HkUpdateResetList& listRef = *hkUpdateResetList;
@ -326,16 +323,16 @@ void LocalDataPoolManager::handleChangeResetLogic(
continue; continue;
} }
// only one update recipient, we can reset changes status immediately. /* Only one update recipient, we can reset changes status immediately */
if(changeInfo.updateCounter <= 1) { if(changeInfo.updateCounter <= 1) {
toReset->setChanged(false); toReset->setChanged(false);
} }
// All recipients have been notified, reset the changed flag. /* All recipients have been notified, reset the changed flag */
if(changeInfo.currentUpdateCounter <= 1) { if(changeInfo.currentUpdateCounter <= 1) {
toReset->setChanged(false); toReset->setChanged(false);
changeInfo.currentUpdateCounter = 0; changeInfo.currentUpdateCounter = 0;
} }
// Not all recipiens have been notified yet, decrement. /* Not all recipiens have been notified yet, decrement */
else { else {
changeInfo.currentUpdateCounter--; changeInfo.currentUpdateCounter--;
} }
@ -371,7 +368,6 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
if(dataSet != nullptr) { if(dataSet != nullptr) {
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting); LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting);
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics); LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
@ -557,15 +553,14 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
dataSet, true); dataSet, true);
} }
// Notification handling. /* Notification handling */
case(HousekeepingMessage::UPDATE_NOTIFICATION_SET): { case(HousekeepingMessage::UPDATE_NOTIFICATION_SET): {
owner->handleChangedDataset(sid); owner->handleChangedDataset(sid);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
case(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): { case(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): {
lp_id_t locPoolId = HousekeepingMessage:: gp_id_t globPoolId = HousekeepingMessage::getUpdateNotificationVariableCommand(message);
getUpdateNotificationVariableCommand(message); owner->handleChangedPoolVariable(globPoolId);
owner->handleChangedPoolVariable(locPoolId);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
case(HousekeepingMessage::UPDATE_SNAPSHOT_SET): { case(HousekeepingMessage::UPDATE_SNAPSHOT_SET): {
@ -576,9 +571,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
} }
case(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): { case(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): {
store_address_t storeId; store_address_t storeId;
lp_id_t localPoolId = HousekeepingMessage:: gp_id_t globPoolId = HousekeepingMessage::getUpdateSnapshotVariableCommand(message,
getUpdateSnapshotVariableCommand(message, &storeId); &storeId);
owner->handleChangedPoolVariable(localPoolId, storeId); owner->handleChangedPoolVariable(globPoolId, storeId);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -693,7 +688,6 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) { void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
sid_t sid = receiver.dataId.sid; sid_t sid = receiver.dataId.sid;
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if(dataSet == nullptr) { if(dataSet == nullptr) {
printWarningOrError(sif::OutputTypes::OUT_WARNING, printWarningOrError(sif::OutputTypes::OUT_WARNING,
@ -710,24 +704,23 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet); LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
if(periodicHelper == nullptr) { if(periodicHelper == nullptr) {
// Configuration error. /* Configuration error */
return; return;
} }
if(periodicHelper->checkOpNecessary()) { if(not periodicHelper->checkOpNecessary()) {
return; return;
} }
ReturnValue_t result = generateHousekeepingPacket( ReturnValue_t result = generateHousekeepingPacket(
sid, dataSet, true); sid, dataSet, true);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// configuration error /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::performHkOperation: " sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." <<
<< "HK generation failed." << std::endl; std::endl;
#else #else
sif::printWarning("LocalDataPoolManager::performHkOperation: " sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
"HK generation failed.\n");
#endif #endif
} }
} }
@ -735,7 +728,6 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
bool enable, bool isDiagnostics) { bool enable, bool isDiagnostics) {
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
if((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or if((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) { (not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
@ -753,7 +745,6 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid, ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics) { float newCollectionInterval, bool isDiagnostics) {
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid); LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet); bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
if((targetIsDiagnostics and not isDiagnostics) or if((targetIsDiagnostics and not isDiagnostics) or
@ -848,7 +839,6 @@ MutexIF* LocalDataPoolManager::getLocalPoolMutex() {
object_id_t LocalDataPoolManager::getCreatorObjectId() const { object_id_t LocalDataPoolManager::getCreatorObjectId() const {
return owner->getObjectId(); return owner->getObjectId();
//return owner->getObjectId();
} }
void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType, void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
@ -883,26 +873,30 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
} }
if(outputType == sif::OutputTypes::OUT_WARNING) { if(outputType == sif::OutputTypes::OUT_WARNING) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "LocalDataPoolManager::" << functionName sif::warning << "LocalDataPoolManager::" << functionName
<< ": Object ID " << std::setw(8) << std::setfill('0') << ": Object ID 0x" << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint << std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl; << std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint); functionName, owner->getObjectId(), errorPrint);
#endif #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
} }
else if(outputType == sif::OutputTypes::OUT_ERROR) { else if(outputType == sif::OutputTypes::OUT_ERROR) {
#if FSFW_VERBOSE_LEVEL >= 1
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "LocalDataPoolManager::" << functionName sif::error << "LocalDataPoolManager::" << functionName
<< ": Object ID " << std::setw(8) << std::setfill('0') << ": Object ID 0x" << std::setw(8) << std::setfill('0')
<< std::hex << owner->getObjectId() << " | " << errorPrint << std::hex << owner->getObjectId() << " | " << errorPrint
<< std::dec << std::setfill(' ') << std::endl; << std::dec << std::setfill(' ') << std::endl;
#else #else
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n", sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
functionName, owner->getObjectId(), errorPrint); functionName, owner->getObjectId(), errorPrint);
#endif #endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
} }
} }

View File

@ -51,6 +51,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner); AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
if(accessor != nullptr) { if(accessor != nullptr) {
mutexIfSingleDataCreator = accessor->getLocalPoolMutex(); mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
poolManager = accessor->getPoolManagerHandle();
} }
} }
@ -66,9 +67,19 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(
LocalPoolDataSetBase::~LocalPoolDataSetBase() { LocalPoolDataSetBase::~LocalPoolDataSetBase() {
/* We only delete objects which were created in the class constructor */
if(periodicHelper != nullptr) { if(periodicHelper != nullptr) {
delete periodicHelper; 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( ReturnValue_t LocalPoolDataSetBase::lockDataPool(
@ -83,7 +94,7 @@ ReturnValue_t LocalPoolDataSetBase::lockDataPool(
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer, ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
size_t *size, size_t maxSize, size_t *size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const { SerializeIF::Endianness streamEndianness) const {
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0); uint8_t validityMaskSize = std::ceil(static_cast<float>(fillCount)/8.0);
uint8_t validityMask[validityMaskSize]; uint8_t validityMask[validityMaskSize];
uint8_t validBufferIndex = 0; uint8_t validBufferIndex = 0;

View File

@ -97,12 +97,18 @@ public:
* @brief The destructor automatically manages writing the valid * @brief The destructor automatically manages writing the valid
* information of variables. * information of variables.
* @details * @details
* In case the data set was read out, but not committed(indicated by state), * In case the data set was read out, but not committed (indicated by state),
* the destructor parses all variables that are still registered to the set. * 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". * For each, the valid flag in the data pool is set to "invalid".
*/ */
~LocalPoolDataSetBase(); ~LocalPoolDataSetBase();
/* 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;
void setValidityBufferGeneration(bool withValidityBuffer); void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const; sid_t getSid() const;
@ -153,6 +159,7 @@ public:
bool hasChanged() const override; bool hasChanged() const override;
object_id_t getCreatorObjectId(); object_id_t getCreatorObjectId();
protected: protected:
sid_t sid; sid_t sid;
//! This mutex is used if the data is created by one object only. //! This mutex is used if the data is created by one object only.

View File

@ -20,12 +20,10 @@ class LocalPoolObjectBase: public PoolVariableIF,
public HasReturnvaluesIF, public HasReturnvaluesIF,
public MarkChangedIF { public MarkChangedIF {
public: public:
LocalPoolObjectBase(lp_id_t poolId, LocalPoolObjectBase(lp_id_t poolId, HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
pool_rwm_t setReadWriteMode); pool_rwm_t setReadWriteMode);
LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, LocalPoolObjectBase(object_id_t poolOwner, lp_id_t poolId, DataSetIF* dataSet = nullptr,
DataSetIF* dataSet = nullptr,
pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE); pool_rwm_t setReadWriteMode = pool_rwm_t::VAR_READ_WRITE);
void setReadWriteMode(pool_rwm_t newReadWriteMode); void setReadWriteMode(pool_rwm_t newReadWriteMode);

View File

@ -38,24 +38,22 @@ public:
bool isDiagnostics, bool isDiagnostics,
object_id_t packetDestination) = 0; object_id_t packetDestination) = 0;
/** /**
* @brief Subscribe for a notification message which will be sent * @brief Subscribe for a notification message which will be sent
* if a dataset has changed. * if a dataset has changed.
* @details * @details
* This subscription mechanism will generally be used internally by * This subscription mechanism will generally be used internally by
* other software components. * other software components.
* @param setId Set ID of the set to receive update messages from. * @param setId Set ID of the set to receive update messages from.
* @param destinationObject * @param destinationObject Object ID of the receiver.
* @param targetQueueId * @param targetQueueId Receiver queue ID
* @param generateSnapshot If this is set to true, a copy of the current * @param generateSnapshot If this is set to true, a copy of the current data with a
* data with a timestamp will be generated and sent via message. * timestamp will be generated and sent via message.
* Otherwise, only an notification message is sent. * Otherwise, only an notification message is sent.
* @return * @return
*/ */
virtual ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId, virtual ReturnValue_t subscribeForSetUpdateMessages(const uint32_t setId,
object_id_t destinationObject, object_id_t destinationObject, MessageQueueId_t targetQueueId,
MessageQueueId_t targetQueueId,
bool generateSnapshot) = 0; bool generateSnapshot) = 0;
/** /**
@ -64,12 +62,12 @@ public:
* @details * @details
* This subscription mechanism will generally be used internally by * This subscription mechanism will generally be used internally by
* other software components. * other software components.
* @param localPoolId Pool ID of the pool variable * @param localPoolId Pool ID of the pool variable
* @param destinationObject * @param destinationObject Object ID of the receiver
* @param targetQueueId * @param targetQueueId Receiver queue ID
* @param generateSnapshot If this is set to true, a copy of the current * @param generateSnapshot If this is set to true, a copy of the current data with a
* data with a timestamp will be generated and sent via message. * timestamp will be generated and sent via message. Otherwise,
* Otherwise, only an notification message is sent. * only an notification message is sent.
* @return * @return
*/ */
virtual ReturnValue_t subscribeForVariableUpdateMessages( virtual ReturnValue_t subscribeForVariableUpdateMessages(

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -125,8 +125,10 @@ sid_t HousekeepingMessage::getSid(const CommandMessage* message) {
return sid; return sid;
} }
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) { gp_id_t HousekeepingMessage::getGpid(const CommandMessage* message) {
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw)); gp_id_t globalPoolId;
std::memcpy(&globalPoolId.raw, message->getData(), sizeof(globalPoolId.raw));
return globalPoolId;
} }
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply, void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply,
@ -169,9 +171,9 @@ void HousekeepingMessage::setUpdateNotificationSetCommand(
} }
void HousekeepingMessage::setUpdateNotificationVariableCommand( void HousekeepingMessage::setUpdateNotificationVariableCommand(
CommandMessage *command, lp_id_t localPoolId) { CommandMessage *command, gp_id_t globalPoolId) {
command->setCommand(UPDATE_NOTIFICATION_VARIABLE); command->setCommand(UPDATE_NOTIFICATION_VARIABLE);
command->setParameter(localPoolId); setGpid(command, globalPoolId);
} }
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command, void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
@ -182,9 +184,9 @@ void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
} }
void HousekeepingMessage::setUpdateSnapshotVariableCommand( void HousekeepingMessage::setUpdateSnapshotVariableCommand(
CommandMessage *command, lp_id_t localPoolId, store_address_t storeId) { CommandMessage *command, gp_id_t globalPoolId, store_address_t storeId) {
command->setCommand(UPDATE_SNAPSHOT_VARIABLE); command->setCommand(UPDATE_SNAPSHOT_VARIABLE);
command->setParameter(localPoolId); setGpid(command, globalPoolId);
command->setParameter3(storeId.raw); command->setParameter3(storeId.raw);
} }
@ -193,9 +195,9 @@ sid_t HousekeepingMessage::getUpdateNotificationSetCommand(
return getSid(command); return getSid(command);
} }
lp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand( gp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
const CommandMessage *command) { const CommandMessage *command) {
return command->getParameter(); return getGpid(command);
} }
sid_t HousekeepingMessage::getUpdateSnapshotSetCommand( sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
@ -206,10 +208,18 @@ sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
return getSid(command); return getSid(command);
} }
lp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand( gp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(
const CommandMessage *command, store_address_t *storeId) { const CommandMessage *command, store_address_t *storeId) {
if(storeId != nullptr) { if(storeId != nullptr) {
*storeId = command->getParameter3(); *storeId = command->getParameter3();
} }
return command->getParameter(); return getGpid(command);
}
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
}
void HousekeepingMessage::setGpid(CommandMessage *message, gp_id_t globalPoolId) {
std::memcpy(message->getData(), &globalPoolId.raw, sizeof(globalPoolId.raw));
} }

View File

@ -75,6 +75,7 @@ public:
//static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(134); //static constexpr Command_t UPDATE_HK_REPORT = MAKE_COMMAND_ID(134);
static sid_t getSid(const CommandMessage* message); static sid_t getSid(const CommandMessage* message);
static gp_id_t getGpid(const CommandMessage* message);
/* Housekeeping Interface Messages */ /* Housekeeping Interface Messages */
@ -123,26 +124,27 @@ public:
static void setUpdateNotificationSetCommand(CommandMessage* command, static void setUpdateNotificationSetCommand(CommandMessage* command,
sid_t sid); sid_t sid);
static void setUpdateNotificationVariableCommand(CommandMessage* command, static void setUpdateNotificationVariableCommand(CommandMessage* command,
lp_id_t localPoolId); gp_id_t globalPoolId);
static void setUpdateSnapshotSetCommand(CommandMessage* command, sid_t sid, static void setUpdateSnapshotSetCommand(CommandMessage* command, sid_t sid,
store_address_t storeId); store_address_t storeId);
static void setUpdateSnapshotVariableCommand(CommandMessage* command, static void setUpdateSnapshotVariableCommand(CommandMessage* command,
lp_id_t localPoolId, store_address_t storeId); gp_id_t globalPoolId, store_address_t storeId);
static sid_t getUpdateNotificationSetCommand(const CommandMessage* command); static sid_t getUpdateNotificationSetCommand(const CommandMessage* command);
static lp_id_t getUpdateNotificationVariableCommand( static gp_id_t getUpdateNotificationVariableCommand(
const CommandMessage* command); const CommandMessage* command);
static sid_t getUpdateSnapshotSetCommand(const CommandMessage* command, static sid_t getUpdateSnapshotSetCommand(const CommandMessage* command,
store_address_t* storeId); store_address_t* storeId);
static lp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command, static gp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
store_address_t* storeId); store_address_t* storeId);
/** Utility */ /** Utility */
static void clear(CommandMessage* message); static void clear(CommandMessage* message);
private: private:
static void setSid(CommandMessage* message, sid_t sid); static void setSid(CommandMessage* message, sid_t sid);
static void setGpid(CommandMessage* message, gp_id_t globalPoolId);
}; };

View File

@ -18,17 +18,19 @@ QueueMapManager* QueueMapManager::instance() {
ReturnValue_t QueueMapManager::addMessageQueue( ReturnValue_t QueueMapManager::addMessageQueue(
MessageQueueIF* queueToInsert, MessageQueueId_t* id) { MessageQueueIF* queueToInsert, MessageQueueId_t* id) {
// Not thread-safe, but it is assumed all message queues are created /* Not thread-safe, but it is assumed all message queues are created at software initialization
// at software initialization now. If this is to be made thread-safe in now. If this is to be made thread-safe in the future, it propably would be sufficient to lock
// the future, it propably would be sufficient to lock the increment the increment operation here. */
// operation here
uint32_t currentId = queueCounter++; uint32_t currentId = queueCounter++;
auto returnPair = queueMap.emplace(currentId, queueToInsert); auto returnPair = queueMap.emplace(currentId, queueToInsert);
if(not returnPair.second) { if(not returnPair.second) {
// this should never happen for the atomic variable. /* This should never happen for the atomic variable. */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "QueueMapManager: This ID is already inside the map!" sif::error << "QueueMapManager::addMessageQueue This ID is already "
<< std::endl; "inside the map!" << std::endl;
#else
sif::printError("QueueMapManager::addMessageQueue This ID is already "
"inside the map!\n");
#endif #endif
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
@ -47,8 +49,11 @@ MessageQueueIF* QueueMapManager::getMessageQueue(
} }
else { else {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::warning << "QueueMapManager::getQueueHandle: The ID " << sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId <<
messageQueueId << " does not exists in the map" << std::endl; " does not exists in the map!" << std::endl;
#else
sif::printWarning("QueueMapManager::getQueueHandle: The ID %d does not exist in the map!\n",
messageQueueId);
#endif #endif
return nullptr; return nullptr;
} }

View File

@ -36,7 +36,7 @@ public:
private: private:
//! External instantiation is forbidden. //! External instantiation is forbidden.
QueueMapManager(); QueueMapManager();
uint32_t queueCounter = 1; uint32_t queueCounter = 0;
MutexIF* mapLock; MutexIF* mapLock;
QueueMap queueMap; QueueMap queueMap;
static QueueMapManager* mqManagerInstance; static QueueMapManager* mqManagerInstance;

View File

@ -4,199 +4,199 @@
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid, Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid,
uint8_t serviceId): uint8_t serviceId):
CommandingServiceBase(objectId, apid, serviceId, CommandingServiceBase(objectId, apid, serviceId,
NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {} NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {}
Service3Housekeeping::~Service3Housekeeping() {} Service3Housekeeping::~Service3Housekeeping() {}
ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) { ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) {
switch(static_cast<Subservice>(subservice)) { switch(static_cast<Subservice>(subservice)) {
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION: case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION: case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
case Subservice::REPORT_HK_REPORT_STRUCTURES: case Subservice::REPORT_HK_REPORT_STRUCTURES:
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES : case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES :
case Subservice::GENERATE_ONE_PARAMETER_REPORT: case Subservice::GENERATE_ONE_PARAMETER_REPORT:
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT: case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL: case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL: case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
// Telemetry or invalid subservice. // Telemetry or invalid subservice.
case Subservice::HK_DEFINITIONS_REPORT: case Subservice::HK_DEFINITIONS_REPORT:
case Subservice::DIAGNOSTICS_DEFINITION_REPORT: case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
case Subservice::HK_REPORT: case Subservice::HK_REPORT:
case Subservice::DIAGNOSTICS_REPORT: case Subservice::DIAGNOSTICS_REPORT:
default: default:
return AcceptsTelecommandsIF::INVALID_SUBSERVICE; return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
} }
} }
ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice, ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice,
const uint8_t *tcData, size_t tcDataLen, const uint8_t *tcData, size_t tcDataLen,
MessageQueueId_t *id, object_id_t *objectId) { MessageQueueId_t *id, object_id_t *objectId) {
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen); ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
if(result != RETURN_OK) { if(result != RETURN_OK) {
return result; return result;
} }
return checkInterfaceAndAcquireMessageQueue(id,objectId); return checkInterfaceAndAcquireMessageQueue(id,objectId);
} }
ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID( ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID(
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) { object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen, if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) { SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue( ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue(
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) { MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
// check HasLocalDataPoolIF property of target // check HasLocalDataPoolIF property of target
HasLocalDataPoolIF* possibleTarget = HasLocalDataPoolIF* possibleTarget =
objectManager->get<HasLocalDataPoolIF>(*objectId); objectManager->get<HasLocalDataPoolIF>(*objectId);
if(possibleTarget == nullptr){ if(possibleTarget == nullptr){
return CommandingServiceBase::INVALID_OBJECT; return CommandingServiceBase::INVALID_OBJECT;
} }
*messageQueueToSet = possibleTarget->getCommandQueue(); *messageQueueToSet = possibleTarget->getCommandQueue();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message, ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message,
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen, uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
uint32_t *state, object_id_t objectId) { uint32_t *state, object_id_t objectId) {
switch(static_cast<Subservice>(subservice)) { switch(static_cast<Subservice>(subservice)) {
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION: case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
return prepareReportingTogglingCommand(message, objectId, true, false, return prepareReportingTogglingCommand(message, objectId, true, false,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION: case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
return prepareReportingTogglingCommand(message, objectId, false, false, return prepareReportingTogglingCommand(message, objectId, false, false,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
return prepareReportingTogglingCommand(message, objectId, true, true, return prepareReportingTogglingCommand(message, objectId, true, true,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION: case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
return prepareReportingTogglingCommand(message, objectId, false, true, return prepareReportingTogglingCommand(message, objectId, false, true,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::REPORT_HK_REPORT_STRUCTURES: case Subservice::REPORT_HK_REPORT_STRUCTURES:
return prepareStructureReportingCommand(message, objectId, false, tcData, return prepareStructureReportingCommand(message, objectId, false, tcData,
tcDataLen); tcDataLen);
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES: case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES:
return prepareStructureReportingCommand(message, objectId, true, tcData, return prepareStructureReportingCommand(message, objectId, true, tcData,
tcDataLen); tcDataLen);
case Subservice::GENERATE_ONE_PARAMETER_REPORT: case Subservice::GENERATE_ONE_PARAMETER_REPORT:
return prepareOneShotReportCommand(message, objectId, false, return prepareOneShotReportCommand(message, objectId, false,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT: case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
return prepareOneShotReportCommand(message, objectId, true, return prepareOneShotReportCommand(message, objectId, true,
tcData, tcDataLen); tcData, tcDataLen);
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL: case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
return prepareCollectionIntervalModificationCommand(message, objectId, return prepareCollectionIntervalModificationCommand(message, objectId,
false, tcData, tcDataLen); false, tcData, tcDataLen);
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL: case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
return prepareCollectionIntervalModificationCommand(message, objectId, return prepareCollectionIntervalModificationCommand(message, objectId,
true, tcData, tcDataLen); true, tcData, tcDataLen);
case Subservice::HK_DEFINITIONS_REPORT: case Subservice::HK_DEFINITIONS_REPORT:
case Subservice::DIAGNOSTICS_DEFINITION_REPORT: case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
case Subservice::HK_REPORT: case Subservice::HK_REPORT:
case Subservice::DIAGNOSTICS_REPORT: case Subservice::DIAGNOSTICS_REPORT:
// Those are telemetry packets. // Those are telemetry packets.
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
default: default:
// should never happen, subservice was already checked. // should never happen, subservice was already checked.
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand( ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand(
CommandMessage *command, object_id_t objectId, CommandMessage *command, object_id_t objectId,
bool enableReporting, bool isDiagnostics, bool enableReporting, bool isDiagnostics,
const uint8_t* tcData, size_t tcDataLen) { const uint8_t* tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(sid_t)) { if(tcDataLen < sizeof(sid_t)) {
// TC data should consist of object ID and set ID. // TC data should consist of object ID and set ID.
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
HousekeepingMessage::setToggleReportingCommand(command, targetSid, HousekeepingMessage::setToggleReportingCommand(command, targetSid,
enableReporting, isDiagnostics); enableReporting, isDiagnostics);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand( ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand(
CommandMessage *command, object_id_t objectId, bool isDiagnostics, CommandMessage *command, object_id_t objectId, bool isDiagnostics,
const uint8_t* tcData, size_t tcDataLen) { const uint8_t* tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(sid_t)) { if(tcDataLen < sizeof(sid_t)) {
// TC data should consist of object ID and set ID. // TC data should consist of object ID and set ID.
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
HousekeepingMessage::setStructureReportingCommand(command, targetSid, HousekeepingMessage::setStructureReportingCommand(command, targetSid,
isDiagnostics); isDiagnostics);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand( ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand(
CommandMessage *command, object_id_t objectId, bool isDiagnostics, CommandMessage *command, object_id_t objectId, bool isDiagnostics,
const uint8_t *tcData, size_t tcDataLen) { const uint8_t *tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(sid_t)) { if(tcDataLen < sizeof(sid_t)) {
// TC data should consist of object ID and set ID. // TC data should consist of object ID and set ID.
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
HousekeepingMessage::setOneShotReportCommand(command, targetSid, HousekeepingMessage::setOneShotReportCommand(command, targetSid,
isDiagnostics); isDiagnostics);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand( ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand(
CommandMessage *command, object_id_t objectId, bool isDiagnostics, CommandMessage *command, object_id_t objectId, bool isDiagnostics,
const uint8_t *tcData, size_t tcDataLen) { const uint8_t *tcData, size_t tcDataLen) {
if(tcDataLen < sizeof(sid_t) + sizeof(float)) { if(tcDataLen < sizeof(sid_t) + sizeof(float)) {
// SID plus the size of the new collection intervL. // SID plus the size of the new collection intervL.
return CommandingServiceBase::INVALID_TC; return CommandingServiceBase::INVALID_TC;
} }
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen); sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
float newCollectionInterval = 0; float newCollectionInterval = 0;
SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen, SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
HousekeepingMessage::setCollectionIntervalModificationCommand(command, HousekeepingMessage::setCollectionIntervalModificationCommand(command,
targetSid, newCollectionInterval, isDiagnostics); targetSid, newCollectionInterval, isDiagnostics);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply, ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
Command_t previousCommand, uint32_t *state, Command_t previousCommand, uint32_t *state,
CommandMessage* optionalNextCommand, object_id_t objectId, CommandMessage* optionalNextCommand, object_id_t objectId,
bool *isStep) { bool *isStep) {
Command_t command = reply->getCommand(); Command_t command = reply->getCommand();
switch(command) { switch(command) {
case(HousekeepingMessage::HK_REPORT): { case(HousekeepingMessage::HK_REPORT): {
ReturnValue_t result = generateHkReply(reply, ReturnValue_t result = generateHkReply(reply,
static_cast<uint8_t>(Subservice::HK_REPORT)); static_cast<uint8_t>(Subservice::HK_REPORT));
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
case(HousekeepingMessage::DIAGNOSTICS_REPORT): { case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
ReturnValue_t result = generateHkReply(reply, ReturnValue_t result = generateHkReply(reply,
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT)); static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
case(HousekeepingMessage::HK_DEFINITIONS_REPORT): { case(HousekeepingMessage::HK_DEFINITIONS_REPORT): {
return generateHkReply(reply, static_cast<uint8_t>( return generateHkReply(reply, static_cast<uint8_t>(
@ -209,93 +209,110 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
break; break;
} }
case(HousekeepingMessage::HK_REQUEST_SUCCESS): { case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
case(HousekeepingMessage::HK_REQUEST_FAILURE): { case(HousekeepingMessage::HK_REQUEST_FAILURE): {
failureParameter1 = objectId; failureParameter1 = objectId;
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED; ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
HousekeepingMessage::getHkRequestFailureReply(reply,&error); HousekeepingMessage::getHkRequestFailureReply(reply,&error);
failureParameter2 = error; failureParameter2 = error;
return CommandingServiceBase::EXECUTION_COMPLETE; return CommandingServiceBase::EXECUTION_COMPLETE;
} }
default: default:
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service3Housekeeping::handleReply: Invalid reply with " sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
<< "reply command " << command << "!" << std::endl; << "reply command " << command << "!" << std::endl;
#else
sif::printWarning("Service3Housekeeping::handleReply: Invalid reply with "
"reply command %hu!\n", command);
#endif #endif
return CommandingServiceBase::INVALID_REPLY; return CommandingServiceBase::INVALID_REPLY;
} }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void Service3Housekeeping::handleUnrequestedReply( void Service3Housekeeping::handleUnrequestedReply(
CommandMessage* reply) { CommandMessage* reply) {
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK; ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
Command_t command = reply->getCommand(); Command_t command = reply->getCommand();
switch(command) { switch(command) {
case(HousekeepingMessage::DIAGNOSTICS_REPORT): { case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
result = generateHkReply(reply, result = generateHkReply(reply,
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT)); static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
break; break;
} }
case(HousekeepingMessage::HK_REPORT): { case(HousekeepingMessage::HK_REPORT): {
result = generateHkReply(reply, result = generateHkReply(reply,
static_cast<uint8_t>(Subservice::HK_REPORT)); static_cast<uint8_t>(Subservice::HK_REPORT));
break; break;
} }
default: case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
break;
}
case(HousekeepingMessage::HK_REQUEST_FAILURE): {
break;
}
default: {
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::error << "Service3Housekeeping::handleUnrequestedReply: Invalid " sif::warning << "Service3Housekeeping::handleUnrequestedReply: Invalid reply with reply "
<< "reply with " << "reply command " << command << "!" "command " << command << "!" << std::endl;
<< std::endl; #else
sif::printWarning("Service3Housekeeping::handleUnrequestedReply: Invalid reply with "
"reply command %hu!\n", command);
#endif #endif
return; return;
} }
}
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// Configuration error /* Configuration error */
#if FSFW_CPP_OSTREAM_ENABLED == 1 #if FSFW_CPP_OSTREAM_ENABLED == 1
sif::debug << "Service3Housekeeping::handleUnrequestedReply:" sif::warning << "Service3Housekeeping::handleUnrequestedReply: Could not generate reply!" <<
<< "Could not generate reply!" << std::endl; std::endl;
#else
sif::printWarning("Service3Housekeeping::handleUnrequestedReply: "
"Could not generate reply!\n");
#endif #endif
} }
} }
MessageQueueId_t Service3Housekeeping::getHkQueue() const { MessageQueueId_t Service3Housekeeping::getHkQueue() const {
return commandQueue->getId(); return commandQueue->getId();
} }
ReturnValue_t Service3Housekeeping::generateHkReply( ReturnValue_t Service3Housekeeping::generateHkReply(
const CommandMessage* hkMessage, uint8_t subserviceId) { const CommandMessage* hkMessage, uint8_t subserviceId) {
store_address_t storeId; store_address_t storeId;
sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId); sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId);
auto resultPair = IPCStore->getData(storeId); auto resultPair = IPCStore->getData(storeId);
if(resultPair.first != HasReturnvaluesIF::RETURN_OK) { if(resultPair.first != HasReturnvaluesIF::RETURN_OK) {
return resultPair.first; return resultPair.first;
} }
HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size()); HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size());
return sendTmPacket(static_cast<uint8_t>(subserviceId), return sendTmPacket(static_cast<uint8_t>(subserviceId),
hkPacket.hkData, hkPacket.hkSize, nullptr, 0); hkPacket.hkData, hkPacket.hkSize, nullptr, 0);
} }
sid_t Service3Housekeeping::buildSid(object_id_t objectId, sid_t Service3Housekeeping::buildSid(object_id_t objectId,
const uint8_t** tcData, size_t* tcDataLen) { const uint8_t** tcData, size_t* tcDataLen) {
sid_t targetSid; sid_t targetSid;
targetSid.objectId = objectId; targetSid.objectId = objectId;
// skip deserialization of object ID, was already done. // skip deserialization of object ID, was already done.
*tcData += sizeof(object_id_t); *tcData += sizeof(object_id_t);
*tcDataLen -= sizeof(object_id_t); *tcDataLen -= sizeof(object_id_t);
// size check is expected to be performed beforehand! // size check is expected to be performed beforehand!
SerializeAdapter::deSerialize(&targetSid.ownerSetId, tcData, tcDataLen, SerializeAdapter::deSerialize(&targetSid.ownerSetId, tcData, tcDataLen,
SerializeIF::Endianness::BIG); SerializeIF::Endianness::BIG);
return targetSid; return targetSid;
} }