Merge branch 'source/develop' into mueller/master
This commit is contained in:
commit
4154c06825
@ -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 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.
|
||||
-
|
||||
|
||||
### PUS Parameter Service 20
|
||||
|
||||
Added PUS parameter service 20 (only custom subservices available).
|
@ -1,7 +1,7 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
PRIVATE
|
||||
ActionHelper.cpp
|
||||
ActionMessage.cpp
|
||||
CommandActionHelper.cpp
|
||||
SimpleActionHelper.cpp
|
||||
)
|
@ -1,5 +1,5 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
PRIVATE
|
||||
SharedRingBuffer.cpp
|
||||
SimpleRingBuffer.cpp
|
||||
)
|
@ -1,4 +1,4 @@
|
||||
target_sources(${LIB_FSFW_NAME}
|
||||
PRIVATE
|
||||
ControllerBase.cpp
|
||||
target_sources(${LIB_FSFW_NAME} PRIVATE
|
||||
ControllerBase.cpp
|
||||
ExtendedControllerBase.cpp
|
||||
)
|
@ -8,6 +8,9 @@ ExtendedControllerBase::ExtendedControllerBase(object_id_t objectId,
|
||||
actionHelper(this, commandQueue) {
|
||||
}
|
||||
|
||||
ExtendedControllerBase::~ExtendedControllerBase() {
|
||||
}
|
||||
|
||||
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.
|
||||
|
@ -22,13 +22,14 @@ class ExtendedControllerBase: public ControllerBase,
|
||||
public:
|
||||
ExtendedControllerBase(object_id_t objectId, object_id_t parentId,
|
||||
size_t commandQueueDepth = 3);
|
||||
virtual ~ExtendedControllerBase();
|
||||
|
||||
/** SystemObjectIF overrides */
|
||||
/* SystemObjectIF overrides */
|
||||
virtual ReturnValue_t initialize() override;
|
||||
|
||||
virtual MessageQueueId_t getCommandQueue() const override;
|
||||
|
||||
/** ExecutableObjectIF overrides */
|
||||
/* ExecutableObjectIF overrides */
|
||||
virtual ReturnValue_t performOperation(uint8_t opCode) override;
|
||||
virtual ReturnValue_t initializeAfterTaskCreation() override;
|
||||
|
||||
@ -49,15 +50,15 @@ protected:
|
||||
*/
|
||||
virtual void performControlOperation() = 0;
|
||||
|
||||
/** Handle the four messages mentioned above */
|
||||
/* Handle the four messages mentioned above */
|
||||
void handleQueue() override;
|
||||
|
||||
/** HasActionsIF overrides */
|
||||
/* HasActionsIF overrides */
|
||||
virtual ReturnValue_t executeAction(ActionId_t actionId,
|
||||
MessageQueueId_t commandedBy, const uint8_t* data,
|
||||
size_t size) override;
|
||||
|
||||
/** HasLocalDatapoolIF overrides */
|
||||
/* HasLocalDatapoolIF overrides */
|
||||
virtual LocalDataPoolManager* getHkManagerHandle() override;
|
||||
virtual object_id_t getObjectId() const override;
|
||||
virtual ReturnValue_t initializeLocalDataPool(
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "PoolDataSetBase.h"
|
||||
#include "../serviceinterface/ServiceInterfaceStream.h"
|
||||
#include <cstring>
|
||||
|
||||
PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount):
|
||||
|
@ -39,8 +39,12 @@ public:
|
||||
* supply a pointer to this dataset to PoolVariable
|
||||
* initializations to register pool variables.
|
||||
*/
|
||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
|
||||
const size_t maxFillCount);
|
||||
PoolDataSetBase(PoolVariableIF** registeredVariablesArray, const size_t maxFillCount);
|
||||
|
||||
/* Forbidden for now */
|
||||
PoolDataSetBase(const PoolDataSetBase& otherSet) = delete;
|
||||
const PoolDataSetBase& operator=(const PoolDataSetBase& otherSet) = delete;
|
||||
|
||||
virtual~ PoolDataSetBase();
|
||||
|
||||
/**
|
||||
@ -63,8 +67,7 @@ public:
|
||||
* - @c SET_WAS_ALREADY_READ if read() is called twice without calling
|
||||
* commit() in between
|
||||
*/
|
||||
virtual ReturnValue_t read(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
virtual ReturnValue_t read(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
/**
|
||||
* @brief The commit call initializes writing back the registered variables.
|
||||
@ -84,8 +87,7 @@ public:
|
||||
* - @c COMMITING_WITHOUT_READING if set was not read yet and
|
||||
* contains non write-only variables
|
||||
*/
|
||||
virtual ReturnValue_t commit(
|
||||
MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
virtual ReturnValue_t commit(MutexIF::TimeoutType timeoutType = MutexIF::TimeoutType::WAITING,
|
||||
uint32_t lockTimeout = 20) override;
|
||||
|
||||
/**
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
* @param storeId If a snapshot was requested, data will be located inside
|
||||
* 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) {
|
||||
return;
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ ReturnValue_t LocalDataPoolManager::performHkOperation() {
|
||||
switch(receiver.reportingType) {
|
||||
case(ReportingType::PERIODIC): {
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
// Periodic packets shall only be generated from datasets.
|
||||
/* Periodic packets shall only be generated from datasets */
|
||||
continue;
|
||||
}
|
||||
performPeriodicHkGeneration(receiver);
|
||||
@ -156,19 +156,17 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
if(receiver.dataType == DataType::LOCAL_POOL_VARIABLE) {
|
||||
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId);
|
||||
//LocalPoolObjectBase* poolObj = owner->getPoolObjectHandle(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.
|
||||
/* Prepare and send update notification. */
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateNotificationVariableCommand(¬ification,
|
||||
receiver.dataId.localPoolId);
|
||||
ReturnValue_t result = hkQueue->sendMessage(
|
||||
receiver.destinationQueue, ¬ification);
|
||||
gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId));
|
||||
ReturnValue_t result = hkQueue->sendMessage(receiver.destinationQueue, ¬ification);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
status = result;
|
||||
}
|
||||
@ -185,10 +183,10 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
return DATASET_NOT_FOUND;
|
||||
}
|
||||
if(dataSet->hasChanged()) {
|
||||
// prepare and send update notification
|
||||
/* Prepare and send update notification */
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateNotificationSetCommand(
|
||||
¬ification, receiver.dataId.sid);
|
||||
HousekeepingMessage::setUpdateNotificationSetCommand(¬ification,
|
||||
receiver.dataId.sid);
|
||||
ReturnValue_t result = hkQueue->sendMessage(
|
||||
receiver.destinationQueue, ¬ification);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@ -198,8 +196,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
}
|
||||
}
|
||||
if(toReset != nullptr) {
|
||||
handleChangeResetLogic(receiver.dataType,
|
||||
receiver.dataId, toReset);
|
||||
handleChangeResetLogic(receiver.dataType, receiver.dataId, toReset);
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
@ -207,7 +204,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationUpdate(HkReceiver& receive
|
||||
ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
HkReceiver& receiver, ReturnValue_t& status) {
|
||||
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) {
|
||||
LocalPoolObjectBase* poolObj = HasLocalDpIFManagerAttorney::getPoolObjectHandle(owner,
|
||||
receiver.dataId.localPoolId);
|
||||
@ -221,14 +218,14 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
// prepare and send update snapshot.
|
||||
/* 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));
|
||||
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);
|
||||
@ -238,7 +235,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
|
||||
CommandMessage notification;
|
||||
HousekeepingMessage::setUpdateSnapshotVariableCommand(¬ification,
|
||||
receiver.dataId.localPoolId, storeId);
|
||||
gp_id_t(owner->getObjectId(), receiver.dataId.localPoolId), storeId);
|
||||
result = hkQueue->sendMessage(receiver.destinationQueue,
|
||||
¬ification);
|
||||
if (result != HasReturnvaluesIF::RETURN_OK) {
|
||||
@ -259,7 +256,7 @@ ReturnValue_t LocalDataPoolManager::handleNotificationSnapshot(
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
// prepare and send update snapshot.
|
||||
/* Prepare and send update snapshot */
|
||||
timeval now;
|
||||
Clock::getClock_timeval(&now);
|
||||
CCSDSTime::CDS_short cds;
|
||||
@ -309,7 +306,7 @@ ReturnValue_t LocalDataPoolManager::addUpdateToStore(
|
||||
void LocalDataPoolManager::handleChangeResetLogic(
|
||||
DataType type, DataId dataId, MarkChangedIF* toReset) {
|
||||
if(hkUpdateResetList == nullptr) {
|
||||
// config error!
|
||||
/* Config error */
|
||||
return;
|
||||
}
|
||||
HkUpdateResetList& listRef = *hkUpdateResetList;
|
||||
@ -326,16 +323,16 @@ void LocalDataPoolManager::handleChangeResetLogic(
|
||||
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) {
|
||||
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) {
|
||||
toReset->setChanged(false);
|
||||
changeInfo.currentUpdateCounter = 0;
|
||||
}
|
||||
// Not all recipiens have been notified yet, decrement.
|
||||
/* Not all recipiens have been notified yet, decrement */
|
||||
else {
|
||||
changeInfo.currentUpdateCounter--;
|
||||
}
|
||||
@ -371,7 +368,6 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
|
||||
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
|
||||
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
if(dataSet != nullptr) {
|
||||
LocalPoolDataSetAttorney::setReportingEnabled(*dataSet, enableReporting);
|
||||
LocalPoolDataSetAttorney::setDiagnostic(*dataSet, isDiagnostics);
|
||||
@ -557,15 +553,14 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
|
||||
dataSet, true);
|
||||
}
|
||||
|
||||
// Notification handling.
|
||||
/* Notification handling */
|
||||
case(HousekeepingMessage::UPDATE_NOTIFICATION_SET): {
|
||||
owner->handleChangedDataset(sid);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_NOTIFICATION_VARIABLE): {
|
||||
lp_id_t locPoolId = HousekeepingMessage::
|
||||
getUpdateNotificationVariableCommand(message);
|
||||
owner->handleChangedPoolVariable(locPoolId);
|
||||
gp_id_t globPoolId = HousekeepingMessage::getUpdateNotificationVariableCommand(message);
|
||||
owner->handleChangedPoolVariable(globPoolId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_SNAPSHOT_SET): {
|
||||
@ -576,9 +571,9 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
|
||||
}
|
||||
case(HousekeepingMessage::UPDATE_SNAPSHOT_VARIABLE): {
|
||||
store_address_t storeId;
|
||||
lp_id_t localPoolId = HousekeepingMessage::
|
||||
getUpdateSnapshotVariableCommand(message, &storeId);
|
||||
owner->handleChangedPoolVariable(localPoolId, storeId);
|
||||
gp_id_t globPoolId = HousekeepingMessage::getUpdateSnapshotVariableCommand(message,
|
||||
&storeId);
|
||||
owner->handleChangedPoolVariable(globPoolId, storeId);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
@ -693,7 +688,6 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
|
||||
|
||||
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
sid_t sid = receiver.dataId.sid;
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if(dataSet == nullptr) {
|
||||
printWarningOrError(sif::OutputTypes::OUT_WARNING,
|
||||
@ -710,24 +704,23 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
LocalPoolDataSetAttorney::getPeriodicHelper(*dataSet);
|
||||
|
||||
if(periodicHelper == nullptr) {
|
||||
// Configuration error.
|
||||
/* Configuration error */
|
||||
return;
|
||||
}
|
||||
|
||||
if(periodicHelper->checkOpNecessary()) {
|
||||
if(not periodicHelper->checkOpNecessary()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReturnValue_t result = generateHousekeepingPacket(
|
||||
sid, dataSet, true);
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// configuration error
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "LocalDataPoolManager::performHkOperation: "
|
||||
<< "HK generation failed." << std::endl;
|
||||
sif::warning << "LocalDataPoolManager::performHkOperation: HK generation failed." <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: "
|
||||
"HK generation failed.\n");
|
||||
sif::printWarning("LocalDataPoolManager::performHkOperation: HK generation failed.\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@ -735,7 +728,6 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
|
||||
bool enable, bool isDiagnostics) {
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
if((LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and not isDiagnostics) or
|
||||
(not LocalPoolDataSetAttorney::isDiagnostics(*dataSet) and isDiagnostics)) {
|
||||
@ -753,7 +745,6 @@ ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
|
||||
|
||||
ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
|
||||
float newCollectionInterval, bool isDiagnostics) {
|
||||
//LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
|
||||
LocalPoolDataSetBase* dataSet = HasLocalDpIFManagerAttorney::getDataSetHandle(owner, sid);
|
||||
bool targetIsDiagnostics = LocalPoolDataSetAttorney::isDiagnostics(*dataSet);
|
||||
if((targetIsDiagnostics and not isDiagnostics) or
|
||||
@ -848,7 +839,6 @@ MutexIF* LocalDataPoolManager::getLocalPoolMutex() {
|
||||
|
||||
object_id_t LocalDataPoolManager::getCreatorObjectId() const {
|
||||
return owner->getObjectId();
|
||||
//return owner->getObjectId();
|
||||
}
|
||||
|
||||
void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
@ -883,26 +873,30 @@ void LocalDataPoolManager::printWarningOrError(sif::OutputTypes outputType,
|
||||
}
|
||||
|
||||
if(outputType == sif::OutputTypes::OUT_WARNING) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
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::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printWarning("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
functionName, owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
}
|
||||
else if(outputType == sif::OutputTypes::OUT_ERROR) {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
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::dec << std::setfill(' ') << std::endl;
|
||||
#else
|
||||
sif::printError("LocalDataPoolManager::%s: Object ID 0x%08x | %s\n",
|
||||
functionName, owner->getObjectId(), errorPrint);
|
||||
#endif
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
|
||||
AccessPoolManagerIF* accessor = HasLocalDpIFUserAttorney::getAccessorHandle(hkOwner);
|
||||
if(accessor != nullptr) {
|
||||
mutexIfSingleDataCreator = accessor->getLocalPoolMutex();
|
||||
poolManager = accessor->getPoolManagerHandle();
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,9 +67,19 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(
|
||||
|
||||
|
||||
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(
|
||||
@ -83,7 +94,7 @@ ReturnValue_t LocalPoolDataSetBase::lockDataPool(
|
||||
ReturnValue_t LocalPoolDataSetBase::serializeWithValidityBuffer(uint8_t **buffer,
|
||||
size_t *size, size_t maxSize,
|
||||
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 validityMask[validityMaskSize];
|
||||
uint8_t validBufferIndex = 0;
|
||||
|
@ -97,12 +97,18 @@ public:
|
||||
* @brief The destructor automatically manages writing the valid
|
||||
* information of variables.
|
||||
* @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.
|
||||
* For each, the valid flag in the data pool is set to "invalid".
|
||||
*/
|
||||
~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);
|
||||
|
||||
sid_t getSid() const;
|
||||
@ -153,6 +159,7 @@ public:
|
||||
bool hasChanged() const override;
|
||||
|
||||
object_id_t getCreatorObjectId();
|
||||
|
||||
protected:
|
||||
sid_t sid;
|
||||
//! This mutex is used if the data is created by one object only.
|
||||
|
@ -20,12 +20,10 @@ class LocalPoolObjectBase: public PoolVariableIF,
|
||||
public HasReturnvaluesIF,
|
||||
public MarkChangedIF {
|
||||
public:
|
||||
LocalPoolObjectBase(lp_id_t poolId,
|
||||
HasLocalDataPoolIF* hkOwner, DataSetIF* dataSet,
|
||||
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,
|
||||
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);
|
||||
|
@ -38,24 +38,22 @@ public:
|
||||
bool isDiagnostics,
|
||||
object_id_t packetDestination) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* @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.
|
||||
* @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 subscribeForSetUpdateMessages(const uint32_t setId,
|
||||
object_id_t destinationObject,
|
||||
MessageQueueId_t targetQueueId,
|
||||
object_id_t destinationObject, MessageQueueId_t targetQueueId,
|
||||
bool generateSnapshot) = 0;
|
||||
|
||||
/**
|
||||
@ -64,12 +62,12 @@ public:
|
||||
* @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.
|
||||
* @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 subscribeForVariableUpdateMessages(
|
||||
|
@ -435,8 +435,7 @@ ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t DeviceHandlerBase::insertInCommandMap(
|
||||
DeviceCommandId_t deviceCommand) {
|
||||
ReturnValue_t DeviceHandlerBase::insertInCommandMap(DeviceCommandId_t deviceCommand) {
|
||||
DeviceCommandInfo info;
|
||||
info.expectedReplies = 0;
|
||||
info.isExecuting = false;
|
||||
@ -701,13 +700,11 @@ void DeviceHandlerBase::parseReply(const uint8_t* receivedData,
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED;
|
||||
DeviceCommandId_t foundId = DeviceHandlerIF::NO_COMMAND_ID;
|
||||
size_t foundLen = 0;
|
||||
// The loop may not execute more often than the number of received bytes
|
||||
// (worst case). This approach avoids infinite loops due to buggy
|
||||
// scanForReply routines.
|
||||
/* The loop may not execute more often than the number of received bytes
|
||||
(worst case). This approach avoids infinite loops due to buggy scanForReply routines. */
|
||||
uint32_t remainingLength = receivedDataLen;
|
||||
for (uint32_t count = 0; count < receivedDataLen; count++) {
|
||||
result = scanForReply(receivedData, remainingLength, &foundId,
|
||||
&foundLen);
|
||||
result = scanForReply(receivedData, remainingLength, &foundId, &foundLen);
|
||||
switch (result) {
|
||||
case RETURN_OK:
|
||||
handleReply(receivedData, foundId, foundLen);
|
||||
@ -790,9 +787,9 @@ void DeviceHandlerBase::handleReply(const uint8_t* receivedData,
|
||||
replyToReply(iter, result);
|
||||
}
|
||||
else {
|
||||
// Other completion failure messages are created by timeout.
|
||||
// Powering down the device might take some time during which periodic
|
||||
// replies may still come in.
|
||||
/* Other completion failure messages are created by timeout.
|
||||
Powering down the device might take some time during which periodic
|
||||
replies may still come in. */
|
||||
if (mode != _MODE_WAIT_OFF) {
|
||||
triggerEvent(DEVICE_UNREQUESTED_REPLY, foundId);
|
||||
}
|
||||
|
@ -125,8 +125,10 @@ sid_t HousekeepingMessage::getSid(const CommandMessage* message) {
|
||||
return sid;
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setSid(CommandMessage *message, sid_t sid) {
|
||||
std::memcpy(message->getData(), &sid.raw, sizeof(sid.raw));
|
||||
gp_id_t HousekeepingMessage::getGpid(const CommandMessage* message) {
|
||||
gp_id_t globalPoolId;
|
||||
std::memcpy(&globalPoolId.raw, message->getData(), sizeof(globalPoolId.raw));
|
||||
return globalPoolId;
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setHkStuctureReportReply(CommandMessage *reply,
|
||||
@ -169,9 +171,9 @@ void HousekeepingMessage::setUpdateNotificationSetCommand(
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setUpdateNotificationVariableCommand(
|
||||
CommandMessage *command, lp_id_t localPoolId) {
|
||||
CommandMessage *command, gp_id_t globalPoolId) {
|
||||
command->setCommand(UPDATE_NOTIFICATION_VARIABLE);
|
||||
command->setParameter(localPoolId);
|
||||
setGpid(command, globalPoolId);
|
||||
}
|
||||
|
||||
void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||
@ -182,9 +184,9 @@ void HousekeepingMessage::setUpdateSnapshotSetCommand(CommandMessage *command,
|
||||
}
|
||||
|
||||
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->setParameter(localPoolId);
|
||||
setGpid(command, globalPoolId);
|
||||
command->setParameter3(storeId.raw);
|
||||
}
|
||||
|
||||
@ -193,9 +195,9 @@ sid_t HousekeepingMessage::getUpdateNotificationSetCommand(
|
||||
return getSid(command);
|
||||
}
|
||||
|
||||
lp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
|
||||
gp_id_t HousekeepingMessage::getUpdateNotificationVariableCommand(
|
||||
const CommandMessage *command) {
|
||||
return command->getParameter();
|
||||
return getGpid(command);
|
||||
}
|
||||
|
||||
sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
|
||||
@ -206,10 +208,18 @@ sid_t HousekeepingMessage::getUpdateSnapshotSetCommand(
|
||||
return getSid(command);
|
||||
}
|
||||
|
||||
lp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(
|
||||
gp_id_t HousekeepingMessage::getUpdateSnapshotVariableCommand(
|
||||
const CommandMessage *command, store_address_t *storeId) {
|
||||
if(storeId != nullptr) {
|
||||
*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));
|
||||
}
|
||||
|
@ -75,6 +75,7 @@ public:
|
||||
//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);
|
||||
|
||||
/* Housekeeping Interface Messages */
|
||||
|
||||
@ -123,26 +124,27 @@ public:
|
||||
static void setUpdateNotificationSetCommand(CommandMessage* command,
|
||||
sid_t sid);
|
||||
static void setUpdateNotificationVariableCommand(CommandMessage* command,
|
||||
lp_id_t localPoolId);
|
||||
gp_id_t globalPoolId);
|
||||
|
||||
static void setUpdateSnapshotSetCommand(CommandMessage* command, sid_t sid,
|
||||
store_address_t storeId);
|
||||
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 lp_id_t getUpdateNotificationVariableCommand(
|
||||
static gp_id_t getUpdateNotificationVariableCommand(
|
||||
const CommandMessage* command);
|
||||
|
||||
static sid_t getUpdateSnapshotSetCommand(const CommandMessage* command,
|
||||
store_address_t* storeId);
|
||||
static lp_id_t getUpdateSnapshotVariableCommand(const CommandMessage* command,
|
||||
static gp_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);
|
||||
};
|
||||
|
||||
|
||||
|
@ -18,17 +18,19 @@ QueueMapManager* QueueMapManager::instance() {
|
||||
|
||||
ReturnValue_t QueueMapManager::addMessageQueue(
|
||||
MessageQueueIF* queueToInsert, MessageQueueId_t* id) {
|
||||
// Not thread-safe, but it is assumed all message queues are created
|
||||
// at software initialization now. If this is to be made thread-safe in
|
||||
// the future, it propably would be sufficient to lock the increment
|
||||
// operation here
|
||||
/* Not thread-safe, but it is assumed all message queues are created at software initialization
|
||||
now. If this is to be made thread-safe in the future, it propably would be sufficient to lock
|
||||
the increment operation here. */
|
||||
uint32_t currentId = queueCounter++;
|
||||
auto returnPair = queueMap.emplace(currentId, queueToInsert);
|
||||
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
|
||||
sif::error << "QueueMapManager: This ID is already inside the map!"
|
||||
<< std::endl;
|
||||
sif::error << "QueueMapManager::addMessageQueue This ID is already "
|
||||
"inside the map!" << std::endl;
|
||||
#else
|
||||
sif::printError("QueueMapManager::addMessageQueue This ID is already "
|
||||
"inside the map!\n");
|
||||
#endif
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
@ -47,8 +49,11 @@ MessageQueueIF* QueueMapManager::getMessageQueue(
|
||||
}
|
||||
else {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "QueueMapManager::getQueueHandle: The ID " <<
|
||||
messageQueueId << " does not exists in the map" << std::endl;
|
||||
sif::warning << "QueueMapManager::getQueueHandle: The ID " << messageQueueId <<
|
||||
" 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
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ public:
|
||||
private:
|
||||
//! External instantiation is forbidden.
|
||||
QueueMapManager();
|
||||
uint32_t queueCounter = 1;
|
||||
uint32_t queueCounter = 0;
|
||||
MutexIF* mapLock;
|
||||
QueueMap queueMap;
|
||||
static QueueMapManager* mqManagerInstance;
|
||||
|
@ -4,199 +4,199 @@
|
||||
|
||||
|
||||
Service3Housekeeping::Service3Housekeeping(object_id_t objectId, uint16_t apid,
|
||||
uint8_t serviceId):
|
||||
CommandingServiceBase(objectId, apid, serviceId,
|
||||
NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {}
|
||||
uint8_t serviceId):
|
||||
CommandingServiceBase(objectId, apid, serviceId,
|
||||
NUM_OF_PARALLEL_COMMANDS, COMMAND_TIMEOUT_SECONDS) {}
|
||||
|
||||
Service3Housekeeping::~Service3Housekeeping() {}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::isValidSubservice(uint8_t subservice) {
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES :
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
// Telemetry or invalid subservice.
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
default:
|
||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||
}
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES :
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
// Telemetry or invalid subservice.
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
default:
|
||||
return AcceptsTelecommandsIF::INVALID_SUBSERVICE;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::getMessageQueueAndObject(uint8_t subservice,
|
||||
const uint8_t *tcData, size_t tcDataLen,
|
||||
MessageQueueId_t *id, object_id_t *objectId) {
|
||||
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
|
||||
if(result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||
const uint8_t *tcData, size_t tcDataLen,
|
||||
MessageQueueId_t *id, object_id_t *objectId) {
|
||||
ReturnValue_t result = checkAndAcquireTargetID(objectId,tcData,tcDataLen);
|
||||
if(result != RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return checkInterfaceAndAcquireMessageQueue(id,objectId);
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::checkAndAcquireTargetID(
|
||||
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
object_id_t* objectIdToSet, const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(SerializeAdapter::deSerialize(objectIdToSet, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG) != HasReturnvaluesIF::RETURN_OK) {
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::checkInterfaceAndAcquireMessageQueue(
|
||||
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
||||
// check HasLocalDataPoolIF property of target
|
||||
HasLocalDataPoolIF* possibleTarget =
|
||||
objectManager->get<HasLocalDataPoolIF>(*objectId);
|
||||
if(possibleTarget == nullptr){
|
||||
return CommandingServiceBase::INVALID_OBJECT;
|
||||
}
|
||||
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
MessageQueueId_t* messageQueueToSet, object_id_t* objectId) {
|
||||
// check HasLocalDataPoolIF property of target
|
||||
HasLocalDataPoolIF* possibleTarget =
|
||||
objectManager->get<HasLocalDataPoolIF>(*objectId);
|
||||
if(possibleTarget == nullptr){
|
||||
return CommandingServiceBase::INVALID_OBJECT;
|
||||
}
|
||||
*messageQueueToSet = possibleTarget->getCommandQueue();
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareCommand(CommandMessage* message,
|
||||
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) {
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, false, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, true, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
false, tcData, tcDataLen);
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
true, tcData, tcDataLen);
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
// Those are telemetry packets.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
default:
|
||||
// should never happen, subservice was already checked.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
uint8_t subservice, const uint8_t *tcData, size_t tcDataLen,
|
||||
uint32_t *state, object_id_t objectId) {
|
||||
switch(static_cast<Subservice>(subservice)) {
|
||||
case Subservice::ENABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_HK_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::ENABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, true, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::DISABLE_PERIODIC_DIAGNOSTICS_REPORT_GENERATION:
|
||||
return prepareReportingTogglingCommand(message, objectId, false, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::REPORT_HK_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, false, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::REPORT_DIAGNOSTICS_REPORT_STRUCTURES:
|
||||
return prepareStructureReportingCommand(message, objectId, true, tcData,
|
||||
tcDataLen);
|
||||
case Subservice::GENERATE_ONE_PARAMETER_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, false,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::GENERATE_ONE_DIAGNOSTICS_REPORT:
|
||||
return prepareOneShotReportCommand(message, objectId, true,
|
||||
tcData, tcDataLen);
|
||||
case Subservice::MODIFY_PARAMETER_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
false, tcData, tcDataLen);
|
||||
case Subservice::MODIFY_DIAGNOSTICS_REPORT_COLLECTION_INTERVAL:
|
||||
return prepareCollectionIntervalModificationCommand(message, objectId,
|
||||
true, tcData, tcDataLen);
|
||||
case Subservice::HK_DEFINITIONS_REPORT:
|
||||
case Subservice::DIAGNOSTICS_DEFINITION_REPORT:
|
||||
case Subservice::HK_REPORT:
|
||||
case Subservice::DIAGNOSTICS_REPORT:
|
||||
// Those are telemetry packets.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
default:
|
||||
// should never happen, subservice was already checked.
|
||||
return HasReturnvaluesIF::RETURN_FAILED;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareReportingTogglingCommand(
|
||||
CommandMessage *command, object_id_t objectId,
|
||||
bool enableReporting, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
CommandMessage *command, object_id_t objectId,
|
||||
bool enableReporting, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setToggleReportingCommand(command, targetSid,
|
||||
enableReporting, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setToggleReportingCommand(command, targetSid,
|
||||
enableReporting, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareStructureReportingCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t* tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setStructureReportingCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setStructureReportingCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareOneShotReportCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t)) {
|
||||
// TC data should consist of object ID and set ID.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setOneShotReportCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
HousekeepingMessage::setOneShotReportCommand(command, targetSid,
|
||||
isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::prepareCollectionIntervalModificationCommand(
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t) + sizeof(float)) {
|
||||
// SID plus the size of the new collection intervL.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
CommandMessage *command, object_id_t objectId, bool isDiagnostics,
|
||||
const uint8_t *tcData, size_t tcDataLen) {
|
||||
if(tcDataLen < sizeof(sid_t) + sizeof(float)) {
|
||||
// SID plus the size of the new collection intervL.
|
||||
return CommandingServiceBase::INVALID_TC;
|
||||
}
|
||||
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
float newCollectionInterval = 0;
|
||||
SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
HousekeepingMessage::setCollectionIntervalModificationCommand(command,
|
||||
targetSid, newCollectionInterval, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
sid_t targetSid = buildSid(objectId, &tcData, &tcDataLen);
|
||||
float newCollectionInterval = 0;
|
||||
SerializeAdapter::deSerialize(&newCollectionInterval, &tcData, &tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
HousekeepingMessage::setCollectionIntervalModificationCommand(command,
|
||||
targetSid, newCollectionInterval, isDiagnostics);
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
|
||||
ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
|
||||
Command_t previousCommand, uint32_t *state,
|
||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||
bool *isStep) {
|
||||
Command_t command = reply->getCommand();
|
||||
switch(command) {
|
||||
Command_t previousCommand, uint32_t *state,
|
||||
CommandMessage* optionalNextCommand, object_id_t objectId,
|
||||
bool *isStep) {
|
||||
Command_t command = reply->getCommand();
|
||||
switch(command) {
|
||||
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
ReturnValue_t result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
return result;
|
||||
}
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_DEFINITIONS_REPORT): {
|
||||
return generateHkReply(reply, static_cast<uint8_t>(
|
||||
@ -209,93 +209,110 @@ ReturnValue_t Service3Housekeeping::handleReply(const CommandMessage* reply,
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REQUEST_FAILURE): {
|
||||
failureParameter1 = objectId;
|
||||
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
|
||||
HousekeepingMessage::getHkRequestFailureReply(reply,&error);
|
||||
failureParameter2 = error;
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
case(HousekeepingMessage::HK_REQUEST_FAILURE): {
|
||||
failureParameter1 = objectId;
|
||||
ReturnValue_t error = HasReturnvaluesIF::RETURN_FAILED;
|
||||
HousekeepingMessage::getHkRequestFailureReply(reply,&error);
|
||||
failureParameter2 = error;
|
||||
return CommandingServiceBase::EXECUTION_COMPLETE;
|
||||
}
|
||||
|
||||
default:
|
||||
default:
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Service3Housekeeping::handleReply: Invalid reply with "
|
||||
<< "reply command " << command << "!" << std::endl;
|
||||
sif::warning << "Service3Housekeeping::handleReply: Invalid reply with "
|
||||
<< "reply command " << command << "!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("Service3Housekeeping::handleReply: Invalid reply with "
|
||||
"reply command %hu!\n", command);
|
||||
#endif
|
||||
return CommandingServiceBase::INVALID_REPLY;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
return CommandingServiceBase::INVALID_REPLY;
|
||||
}
|
||||
return HasReturnvaluesIF::RETURN_OK;
|
||||
}
|
||||
|
||||
void Service3Housekeeping::handleUnrequestedReply(
|
||||
CommandMessage* reply) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
Command_t command = reply->getCommand();
|
||||
CommandMessage* reply) {
|
||||
ReturnValue_t result = HasReturnvaluesIF::RETURN_OK;
|
||||
Command_t command = reply->getCommand();
|
||||
|
||||
switch(command) {
|
||||
switch(command) {
|
||||
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
break;
|
||||
}
|
||||
case(HousekeepingMessage::DIAGNOSTICS_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::DIAGNOSTICS_REPORT));
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
break;
|
||||
}
|
||||
case(HousekeepingMessage::HK_REPORT): {
|
||||
result = generateHkReply(reply,
|
||||
static_cast<uint8_t>(Subservice::HK_REPORT));
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
case(HousekeepingMessage::HK_REQUEST_SUCCESS): {
|
||||
break;
|
||||
}
|
||||
|
||||
case(HousekeepingMessage::HK_REQUEST_FAILURE): {
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::error << "Service3Housekeeping::handleUnrequestedReply: Invalid "
|
||||
<< "reply with " << "reply command " << command << "!"
|
||||
<< std::endl;
|
||||
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Invalid reply with reply "
|
||||
"command " << command << "!" << std::endl;
|
||||
#else
|
||||
sif::printWarning("Service3Housekeeping::handleUnrequestedReply: Invalid reply with "
|
||||
"reply command %hu!\n", command);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
// Configuration error
|
||||
if(result != HasReturnvaluesIF::RETURN_OK) {
|
||||
/* Configuration error */
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::debug << "Service3Housekeeping::handleUnrequestedReply:"
|
||||
<< "Could not generate reply!" << std::endl;
|
||||
sif::warning << "Service3Housekeeping::handleUnrequestedReply: Could not generate reply!" <<
|
||||
std::endl;
|
||||
#else
|
||||
sif::printWarning("Service3Housekeeping::handleUnrequestedReply: "
|
||||
"Could not generate reply!\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MessageQueueId_t Service3Housekeeping::getHkQueue() const {
|
||||
return commandQueue->getId();
|
||||
return commandQueue->getId();
|
||||
}
|
||||
|
||||
ReturnValue_t Service3Housekeeping::generateHkReply(
|
||||
const CommandMessage* hkMessage, uint8_t subserviceId) {
|
||||
store_address_t storeId;
|
||||
const CommandMessage* hkMessage, uint8_t subserviceId) {
|
||||
store_address_t storeId;
|
||||
|
||||
sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId);
|
||||
auto resultPair = IPCStore->getData(storeId);
|
||||
if(resultPair.first != HasReturnvaluesIF::RETURN_OK) {
|
||||
return resultPair.first;
|
||||
}
|
||||
sid_t sid = HousekeepingMessage::getHkDataReply(hkMessage, &storeId);
|
||||
auto resultPair = IPCStore->getData(storeId);
|
||||
if(resultPair.first != HasReturnvaluesIF::RETURN_OK) {
|
||||
return resultPair.first;
|
||||
}
|
||||
|
||||
HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size());
|
||||
return sendTmPacket(static_cast<uint8_t>(subserviceId),
|
||||
hkPacket.hkData, hkPacket.hkSize, nullptr, 0);
|
||||
HkPacket hkPacket(sid, resultPair.second.data(), resultPair.second.size());
|
||||
return sendTmPacket(static_cast<uint8_t>(subserviceId),
|
||||
hkPacket.hkData, hkPacket.hkSize, nullptr, 0);
|
||||
}
|
||||
|
||||
sid_t Service3Housekeeping::buildSid(object_id_t objectId,
|
||||
const uint8_t** tcData, size_t* tcDataLen) {
|
||||
sid_t targetSid;
|
||||
targetSid.objectId = objectId;
|
||||
// skip deserialization of object ID, was already done.
|
||||
*tcData += sizeof(object_id_t);
|
||||
*tcDataLen -= sizeof(object_id_t);
|
||||
// size check is expected to be performed beforehand!
|
||||
SerializeAdapter::deSerialize(&targetSid.ownerSetId, tcData, tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
return targetSid;
|
||||
const uint8_t** tcData, size_t* tcDataLen) {
|
||||
sid_t targetSid;
|
||||
targetSid.objectId = objectId;
|
||||
// skip deserialization of object ID, was already done.
|
||||
*tcData += sizeof(object_id_t);
|
||||
*tcDataLen -= sizeof(object_id_t);
|
||||
// size check is expected to be performed beforehand!
|
||||
SerializeAdapter::deSerialize(&targetSid.ownerSetId, tcData, tcDataLen,
|
||||
SerializeIF::Endianness::BIG);
|
||||
return targetSid;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "../ipc/QueueFactory.h"
|
||||
#include "../tmtcpacket/pus/TcPacketStored.h"
|
||||
#include "../tmtcpacket/pus/TmPacketStored.h"
|
||||
#include "../serviceinterface/ServiceInterface.h"
|
||||
|
||||
object_id_t CommandingServiceBase::defaultPacketSource = objects::NO_OBJECT;
|
||||
object_id_t CommandingServiceBase::defaultPacketDestination = objects::NO_OBJECT;
|
||||
@ -104,9 +105,27 @@ ReturnValue_t CommandingServiceBase::initialize() {
|
||||
void CommandingServiceBase::handleCommandQueue() {
|
||||
CommandMessage reply;
|
||||
ReturnValue_t result = RETURN_FAILED;
|
||||
for (result = commandQueue->receiveMessage(&reply); result == RETURN_OK;
|
||||
result = commandQueue->receiveMessage(&reply)) {
|
||||
handleCommandMessage(&reply);
|
||||
while(true) {
|
||||
result = commandQueue->receiveMessage(&reply);
|
||||
if (result == HasReturnvaluesIF::RETURN_OK) {
|
||||
handleCommandMessage(&reply);
|
||||
continue;
|
||||
}
|
||||
else if(result == MessageQueueIF::EMPTY) {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
#if FSFW_VERBOSE_LEVEL >= 1
|
||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||
sif::warning << "CommandingServiceBase::handleCommandQueue: Receiving message failed"
|
||||
"with code" << result << std::endl;
|
||||
#else
|
||||
sif::printWarning("CommandingServiceBase::handleCommandQueue: Receiving message "
|
||||
"failed with code %d\n", result);
|
||||
#endif /* FSFW_CPP_OSTREAM_ENABLED == 1 */
|
||||
#endif /* FSFW_VERBOSE_LEVEL >= 1 */
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user