diff --git a/datapoollocal/HasLocalDataPoolIF.h b/datapoollocal/HasLocalDataPoolIF.h index 7727c3b4..1a026dd3 100644 --- a/datapoollocal/HasLocalDataPoolIF.h +++ b/datapoollocal/HasLocalDataPoolIF.h @@ -43,6 +43,8 @@ public: static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF; static constexpr lp_id_t NO_POOL_ID = 0xffffffff; + virtual object_id_t getObjectId() const = 0; + /** Command queue for housekeeping messages. */ virtual MessageQueueId_t getCommandQueue() const = 0; @@ -53,6 +55,13 @@ public: /** Can be used to get a handle to the local data pool manager. */ virtual LocalDataPoolManager* getHkManagerHandle() = 0; + /** + * Returns the minimum sampling frequency, which will usually be the + * period the pool owner performs its periodic operation- + * @return + */ + virtual dur_millis_t getPeriodicOperationFrequency() const = 0; + /** * This function is used by the pool manager to get a valid dataset * from a SID diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index ec413492..b852143e 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -6,6 +6,7 @@ #include #include +#include LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, MessageQueueIF* queueToUse, bool appendValidityBuffer): @@ -25,11 +26,12 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, sif::error << "LocalDataPoolManager::LocalDataPoolManager: " "Could not set IPC store." << std::endl; } + hkQueue = queueToUse; } ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse, - object_id_t hkDestination) { + object_id_t hkDestination, uint8_t nonDiagInvlFactor) { if(queueToUse == nullptr) { sif::error << "LocalDataPoolManager::initialize: Supplied queue " "invalid!" << std::endl; @@ -51,6 +53,10 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse, sif::warning << "Make sure it exists and the object impements " "AcceptsHkPacketsIF!" << std::endl; } + + setNonDiagnosticIntervalFactor(nonDiagInvlFactor); + diagnosticMinimumInterval = owner->getPeriodicOperationFrequency(); + regularMinimumInterval = diagnosticMinimumInterval * nonDiagnosticIntervalFactor; return initializeHousekeepingPoolEntriesOnce(); } @@ -182,7 +188,9 @@ ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid) { return result; } -void LocalDataPoolManager::setMinimalSamplingFrequency(float frequencySeconds) { +void LocalDataPoolManager::setNonDiagnosticIntervalFactor( + uint8_t nonDiagInvlFactor) { + this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; } ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( @@ -214,5 +222,63 @@ ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( } ReturnValue_t LocalDataPoolManager::performHkOperation() { + for(auto& hkReceiversIter: hkReceiversMap) { + HkReceiver* receiver = &hkReceiversIter.second; + switch(receiver->reportingType) { + case(ReportingType::PERIODIC): { + performPeriodicHkGeneration(receiver); + break; + } + case(ReportingType::ON_UPDATE): { + // check whether data has changed and send messages in case it has. + break; + } + default: + // This should never happen. + return HasReturnvaluesIF::RETURN_FAILED; + } + } return HasReturnvaluesIF::RETURN_OK; } + +void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) { + if(receiver->reportingEnabled) { + if(receiver->intervalCounter >= intervalSecondsToInterval( + receiver->isDiagnostics, + receiver->hkParameter.collectionInterval)) { + ReturnValue_t result = generateHousekeepingPacket( + receiver->dataSetSid, receiver->destinationQueue); + if(result != HasReturnvaluesIF::RETURN_OK) { + // configuration error + sif::debug << "LocalDataPoolManager::performHkOperation:" + << "0x" << std::setfill('0') << std::setw(8) + << owner->getObjectId() << " Error generating " + << "HK packet" << std::setfill(' ') << std::endl; + } + receiver->intervalCounter = 1; + } + else if(receiver->reportingEnabled){ + receiver->intervalCounter++; + } + } +} + +uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics, + float collectionIntervalSeconds) { + if(isDiagnostics) { + return std::ceil(collectionIntervalSeconds/diagnosticMinimumInterval); + } + else { + return std::ceil(collectionIntervalSeconds/regularMinimumInterval); + } +} + +float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics, + uint32_t collectionInterval) { + if(isDiagnostics) { + return static_cast(collectionInterval * diagnosticMinimumInterval); + } + else { + return static_cast(collectionInterval * regularMinimumInterval); + } +} diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index 6912f0bc..bcfee3f4 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -66,10 +66,22 @@ public: * Initializes the map by calling the map initialization function of the * owner and assigns the queue to use. * @param queueToUse + * @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc * @return */ ReturnValue_t initialize(MessageQueueIF* queueToUse, - object_id_t hkDestination); + object_id_t hkDestination, uint8_t nonDiagInvlFactor = 5); + + /** + * Non-Diagnostics packets usually have a lower minimum sampling frequency + * than diagnostic packets. + * A factor can be specified to determine the minimum sampling frequency + * for non-diagnostic packets. The minimum sampling frequency of the + * diagnostics packets,which is usually jusst the period of the + * performOperation calls, is multiplied with that factor. + * @param factor + */ + void setNonDiagnosticIntervalFactor(uint8_t nonDiagInvlFactor); /** * This should be called in the periodic handler of the owner. @@ -144,29 +156,36 @@ public: private: LocalDataPool localPoolMap; - /** Every housekeeping data manager has a mutex to protect access - * to it's data pool. */ + //! Every housekeeping data manager has a mutex to protect access + //! to it's data pool. MutexIF* mutex = nullptr; /** The class which actually owns the manager (and its datapool). */ HasLocalDataPoolIF* owner = nullptr; - /** - * The data pool manager will keep an internal map of HK receivers. - */ + uint8_t nonDiagnosticIntervalFactor = 0; + dur_millis_t regularMinimumInterval = 0; + dur_millis_t diagnosticMinimumInterval = 0; + + /** The data pool manager will keep an internal map of HK receivers. */ struct HkReceiver { - LocalPoolDataSetBase* dataSet = nullptr; + sid_t dataSetSid; + //LocalPoolDataSetBase* dataSet = nullptr; lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID; MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE; ReportingType reportingType = ReportingType::PERIODIC; - bool reportingStatus = true; + bool reportingEnabled = true; /** Different members of this union will be used depending on reporting * type */ - union hkParameter { + union HkParameter { /** This parameter will be used for the PERIODIC type */ dur_seconds_t collectionInterval = 0; /** This parameter will be used for the ON_UPDATE type */ bool hkDataChanged; }; + HkParameter hkParameter; + bool isDiagnostics; + //! General purpose counter which is used for periodic generation. + uint32_t intervalCounter; }; /** Using a multimap as the same object might request multiple datasets */ @@ -223,6 +242,13 @@ private: void setMinimalSamplingFrequency(float frequencySeconds); ReturnValue_t serializeHkPacketIntoStore(store_address_t* storeId, LocalPoolDataSetBase* dataSet); + + uint32_t intervalSecondsToInterval(bool isDiagnostics, + float collectionIntervalSeconds); + float intervalToIntervalSeconds(bool isDiagnostics, + uint32_t collectionInterval); + + void performPeriodicHkGeneration(HkReceiver* hkReceiver); }; diff --git a/devicehandlers/DeviceHandlerBase.cpp b/devicehandlers/DeviceHandlerBase.cpp index a4346afb..cbbecb70 100644 --- a/devicehandlers/DeviceHandlerBase.cpp +++ b/devicehandlers/DeviceHandlerBase.cpp @@ -82,6 +82,7 @@ ReturnValue_t DeviceHandlerBase::performOperation(uint8_t counter) { decrementDeviceReplyMap(); fdirInstance->checkForFailures(); hkSwitcher.performOperation(); + hkManager.performHkOperation(); performOperationHook(); } if (mode == MODE_OFF) { @@ -1395,3 +1396,11 @@ DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) { return nullptr; } } + +object_id_t DeviceHandlerBase::getObjectId() const { + return SystemObject::getObjectId(); +} + +dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { + return pstIntervalMs; +} diff --git a/devicehandlers/DeviceHandlerBase.h b/devicehandlers/DeviceHandlerBase.h index 632db5e0..302829ea 100644 --- a/devicehandlers/DeviceHandlerBase.h +++ b/devicehandlers/DeviceHandlerBase.h @@ -493,7 +493,11 @@ protected: * performOperation(). Default implementation is empty. */ virtual void performOperationHook(); + public: + /** Explicit interface implementation of getObjectId */ + virtual object_id_t getObjectId() const override; + /** * @param parentQueueId */ @@ -653,8 +657,6 @@ protected: //! respective device reply. Will point to a dataset held by //! the child handler (if one is specified) DataSetIF* dataSet = nullptr; - float collectionInterval = 0.0; - uint32_t intervalCounter = 0; //! The command that expects this reply. DeviceCommandMap::iterator command; }; @@ -1201,6 +1203,8 @@ private: void parseReply(const uint8_t* receivedData, size_t receivedDataLen); + + virtual dur_millis_t getPeriodicOperationFrequency() const override; }; #endif /* FRAMEWORK_DEVICEHANDLERS_DEVICEHANDLERBASE_H_ */ diff --git a/objectmanager/SystemObject.h b/objectmanager/SystemObject.h index 6a1b35b6..47e53a7f 100644 --- a/objectmanager/SystemObject.h +++ b/objectmanager/SystemObject.h @@ -51,8 +51,8 @@ public: * @brief On destruction, the object removes itself from the list. */ virtual ~SystemObject(); - object_id_t getObjectId() const; - virtual ReturnValue_t initialize(); + object_id_t getObjectId() const override; + virtual ReturnValue_t initialize() override; virtual ReturnValue_t checkObjectConnections(); virtual void forwardEvent(Event event, uint32_t parameter1 = 0, uint32_t parameter2 = 0) const;