hk stuff continued

This commit is contained in:
Robin Müller 2020-09-19 15:58:34 +02:00
parent 9ecbc8199e
commit 32c0140cc2
16 changed files with 235 additions and 208 deletions

View File

@ -140,7 +140,11 @@ public:
//SHOULDDO this should be implemented as non-member //SHOULDDO this should be implemented as non-member
bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const { bool operator!=(const typename ArrayList<T, count_t>::Iterator& other) const {
return !(*this == other); // POSSIBLY BUGGY ! Also this is really confusing. Why does
// the operator above use the value while this one
// dereferences itself?
//return not (value == other.value);
return !(*this == other);
} }
}; };

View File

@ -143,6 +143,15 @@ public:
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
bool empty() {
if(_size == 0) {
return true;
}
else {
return false;
}
}
bool full() { bool full() {
if(_size >= theMap.maxSize()) { if(_size >= theMap.maxSize()) {
return true; return true;

View File

@ -9,7 +9,8 @@
#include <map> #include <map>
class LocalDataPoolManager; class LocalDataPoolManager;
class DataSetIF; class LocalPoolDataSetBase;
/** /**
* @brief Type definition for local pool entries. * @brief Type definition for local pool entries.
*/ */
@ -76,7 +77,7 @@ public:
* @param sid Corresponding structure ID * @param sid Corresponding structure ID
* @return * @return
*/ */
virtual DataSetIF* getDataSetHandle(sid_t sid) = 0; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) = 0;
/* These function can be implemented by pool owner, as they are required /* These function can be implemented by pool owner, as they are required
* by the housekeeping message interface */ * by the housekeeping message interface */

View File

@ -56,9 +56,6 @@ ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation( ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(
uint8_t nonDiagInvlFactor) { uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor); setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
diagnosticMinimumInterval = owner->getPeriodicOperationFrequency();
regularMinimumInterval = diagnosticMinimumInterval *
nonDiagnosticIntervalFactor;
return initializeHousekeepingPoolEntriesOnce(); return initializeHousekeepingPoolEntriesOnce();
} }
@ -77,12 +74,12 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
} }
ReturnValue_t LocalDataPoolManager::performHkOperation() { ReturnValue_t LocalDataPoolManager::performHkOperation() {
for(auto& hkReceiversIter: hkReceiversMap) { for(auto& receiver: hkReceiversMap) {
HkReceiver* receiver = &hkReceiversIter.second; //HkReceiver* receiver = &hkReceiversIter.second;
switch(receiver->reportingType) { switch(receiver.reportingType) {
case(ReportingType::PERIODIC): { case(ReportingType::PERIODIC): {
if(receiver->dataId.dataSetSid.notSet()) { 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;
} }
@ -113,30 +110,19 @@ ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
} }
struct HkReceiver hkReceiver; struct HkReceiver hkReceiver;
hkReceiver.dataId.dataSetSid = sid; hkReceiver.dataId.sid = sid;
hkReceiver.reportingType = ReportingType::PERIODIC; hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue(); hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
if(not isDiagnostics) { LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
hkReceiver.hkParameter.collectionIntervalTicks =
intervalSecondsToInterval(isDiagnostics, collectionInterval *
nonDiagnosticIntervalFactor);
}
else {
hkReceiver.hkParameter.collectionIntervalTicks =
intervalSecondsToInterval(isDiagnostics, collectionInterval);
}
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid));
if(dataSet != nullptr) { if(dataSet != nullptr) {
dataSet->setReportingEnabled(enableReporting); dataSet->setReportingEnabled(enableReporting);
dataSet->setIsDiagnostic(isDiagnostics); dataSet->setDiagnostic(isDiagnostics);
dataSet->initializePeriodicHelper(collectionInterval,
owner->getPeriodicOperationFrequency(), isDiagnostics);
} }
hkReceiver.intervalCounter = 1; hkReceiversMap.push_back(hkReceiver);
hkReceiversMap.emplace(packetDestination, hkReceiver);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -153,7 +139,6 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
return togglePeriodicGeneration(sid, true, false); return togglePeriodicGeneration(sid, true, false);
case(HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION): case(HousekeepingMessage::DISABLE_PERIODIC_HK_REPORT_GENERATION):
return togglePeriodicGeneration(sid, false, false); return togglePeriodicGeneration(sid, false, false);
case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES): case(HousekeepingMessage::REPORT_DIAGNOSTICS_REPORT_STRUCTURES):
case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES): case(HousekeepingMessage::REPORT_HK_REPORT_STRUCTURES):
//return generateSetStructurePacket(sid, ); //return generateSetStructurePacket(sid, );
@ -174,14 +159,13 @@ ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT):
case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): { case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>( LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
owner->getDataSetHandle(sid));
if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT if(command == HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT
and dataSet->getIsDiagnostics()) { and dataSet->isDiagnostics()) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT else if(command == HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT
and not dataSet->getIsDiagnostics()) { and not dataSet->isDiagnostics()) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
return generateHousekeepingPacket(HousekeepingMessage::getSid(message), return generateHousekeepingPacket(HousekeepingMessage::getSid(message),
@ -234,7 +218,7 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
// and now we set a HK message and send it the HK packet destination. // and now we set a HK message and send it the HK packet destination.
CommandMessage hkMessage; CommandMessage hkMessage;
if(dataSet->getIsDiagnostics()) { if(dataSet->isDiagnostics()) {
HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId); HousekeepingMessage::setHkDiagnosticsReply(&hkMessage, sid, storeId);
} }
else { else {
@ -280,62 +264,40 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
this->nonDiagnosticIntervalFactor = nonDiagInvlFactor; this->nonDiagnosticIntervalFactor = nonDiagInvlFactor;
} }
void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) { void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver& receiver) {
if(receiver->intervalCounter >= sid_t sid = receiver.dataId.sid;
receiver->hkParameter.collectionIntervalTicks) { LocalPoolDataSetBase* dataSet = owner->getDataSetHandle(sid);
sid_t sid = receiver->dataId.dataSetSid; if(not dataSet->getReportingEnabled()) {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>( return;
owner->getDataSetHandle(sid)); }
if(not dataSet->getReportingEnabled()) {
return;
}
ReturnValue_t result = generateHousekeepingPacket( if(dataSet->periodicHelper == nullptr) {
sid, dataSet, true); // Configuration error.
if(result != HasReturnvaluesIF::RETURN_OK) { return;
// configuration error }
sif::debug << "LocalDataPoolManager::performHkOperation:"
<< "0x" << std::setfill('0') << std::setw(8) if(not dataSet->periodicHelper->checkOpNecessary()) {
<< owner->getObjectId() << " Error generating " return;
<< "HK packet" << std::setfill(' ') << std::endl; }
}
receiver->intervalCounter = 1; ReturnValue_t result = generateHousekeepingPacket(
} sid, dataSet, true);
else { if(result != HasReturnvaluesIF::RETURN_OK) {
receiver->intervalCounter++; // configuration error
} sif::debug << "LocalDataPoolManager::performHkOperation:"
<< "0x" << std::setfill('0') << std::setw(8)
<< owner->getObjectId() << " Error generating "
<< "HK packet" << std::setfill(' ') << std::endl;
}
} }
uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics,
float collectionIntervalSeconds) {
if(isDiagnostics) {
return std::ceil(collectionIntervalSeconds * 1000
/diagnosticMinimumInterval);
}
else {
return std::ceil(collectionIntervalSeconds * 1000
/regularMinimumInterval);
}
}
float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics,
uint32_t collectionInterval) {
if(isDiagnostics) {
return static_cast<float>(collectionInterval *
diagnosticMinimumInterval);
}
else {
return static_cast<float>(collectionInterval *
regularMinimumInterval);
}
}
ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid, ReturnValue_t LocalDataPoolManager::togglePeriodicGeneration(sid_t sid,
bool enable, bool isDiagnostics) { bool enable, bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>( LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid)); owner->getDataSetHandle(sid));
if((dataSet->getIsDiagnostics() and not isDiagnostics) or if((dataSet->isDiagnostics() and not isDiagnostics) or
(not dataSet->getIsDiagnostics() and isDiagnostics)) { (not dataSet->isDiagnostics() and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
} }
@ -352,7 +314,7 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics) { float newCollectionInterval, bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>( LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid)); owner->getDataSetHandle(sid));
bool targetIsDiagnostics = dataSet->getIsDiagnostics(); bool targetIsDiagnostics = dataSet->isDiagnostics();
if((targetIsDiagnostics and not isDiagnostics) or if((targetIsDiagnostics and not isDiagnostics) or
(not targetIsDiagnostics and isDiagnostics)) { (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE; return WRONG_HK_PACKET_TYPE;
@ -364,50 +326,49 @@ ReturnValue_t LocalDataPoolManager::changeCollectionInterval(sid_t sid,
} }
dataSet->periodicHelper->changeCollectionInterval(newCollectionInterval); dataSet->periodicHelper->changeCollectionInterval(newCollectionInterval);
// for(auto& receiver: hkReceiversMap) {
// if(receiver.second.reportingType != ReportingType::PERIODIC) {
// continue;
// }
//
// uint32_t newInterval = intervalSecondsToInterval(isDiagnostics,
// newCollectionInterval);
// receiver.second.hkParameter.collectionIntervalTicks = newInterval;
// }
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid, ReturnValue_t LocalDataPoolManager::generateSetStructurePacket(sid_t sid,
float collectionInterval, bool isDiagnostics) { bool isDiagnostics) {
LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>( LocalPoolDataSetBase* dataSet = dynamic_cast<LocalPoolDataSetBase*>(
owner->getDataSetHandle(sid)); owner->getDataSetHandle(sid));
if(dataSet == nullptr) { if(dataSet == nullptr) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket:" sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
" Set ID not found" << std::endl; " Set ID not found" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
bool valid = dataSet->isValid(); bool targetIsDiagnostics = dataSet->isDiagnostics();
bool targetIsDiagnostics = dataSet->getIsDiagnostics(); if((targetIsDiagnostics and not isDiagnostics) or
bool reportingEnabled = dataSet->getReportingEnabled(); (not targetIsDiagnostics and isDiagnostics)) {
return WRONG_HK_PACKET_TYPE;
}
size_t expectedSize = dataSet->getFillCount() * sizeof(lp_id_t); bool valid = dataSet->isValid();
uint8_t* storePtr = nullptr; bool reportingEnabled = dataSet->getReportingEnabled();
store_address_t storeId; float collectionInterval =
HousekeepingSetPacket setPacket = HousekeepingSetPacket(sid, reportingEnabled, dataSet->periodicHelper->getCollectionIntervalInSeconds();
valid, collectionInterval, dataSet);
ReturnValue_t result = ipcStore->getFreeElement(&storeId, HousekeepingSetPacket setPacket = HousekeepingSetPacket(sid,
expectedSize,&storePtr); reportingEnabled, valid, collectionInterval, dataSet);
if(result != HasReturnvaluesIF::RETURN_OK) { size_t expectedSize = setPacket.getSerializedSize();
sif::error << "HousekeepingManager::generateHousekeepingPacket: " uint8_t* storePtr = nullptr;
"Could not get free element from IPC store." << std::endl; store_address_t storeId;
return result; ReturnValue_t result = ipcStore->getFreeElement(&storeId,
} expectedSize,&storePtr);
size_t size = 0; if(result != HasReturnvaluesIF::RETURN_OK) {
result = dataSet->serializeLocalPoolIds(&storePtr, &size, sif::error << "HousekeepingManager::generateHousekeepingPacket: "
expectedSize, SerializeIF::Endianness::BIG); "Could not get free element from IPC store." << std::endl;
if(expectedSize != size) { return result;
sif::error << "HousekeepingManager::generateSetStructurePacket: " }
"Expected size is not equal to serialized size" << std::endl;
} size_t size = 0;
return result; result = setPacket.serialize(&storePtr, &size, expectedSize,
SerializeIF::Endianness::BIG);
if(expectedSize != size) {
sif::error << "HousekeepingManager::generateSetStructurePacket: "
"Expected size is not equal to serialized size" << std::endl;
}
return result;
} }

View File

@ -5,6 +5,7 @@
#include "../housekeeping/HousekeepingPacketDownlink.h" #include "../housekeeping/HousekeepingPacketDownlink.h"
#include "../housekeeping/HousekeepingMessage.h" #include "../housekeeping/HousekeepingMessage.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolEntry.h" #include "../datapool/PoolEntry.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
@ -131,16 +132,15 @@ public:
/** /**
* Different types of housekeeping reporting are possible. * Different types of housekeeping reporting are possible.
* 1. PERIODIC: HK packets are generated in fixed intervals and sent to * 1. PERIODIC:
* HK packets are generated in fixed intervals and sent to
* destination. Fromat will be raw. * destination. Fromat will be raw.
* 2. UPDATED: Notification will be sent out if HK data has changed. * 2. UPDATE_NOTIFICATION:
* Question: Send Raw data directly or just the message? * Notification will be sent out if HK data has changed.
* 3. REQUESTED: HK packets are only generated if explicitely requested. * 3. UPDATE_SNAPSHOT:
* HK packets are only generated if explicitely requested.
* Propably not necessary, just use multiple local data sets or * Propably not necessary, just use multiple local data sets or
* shared datasets. * shared datasets.
*
* Notifications should also be possible for single variables instead of
* full dataset updates.
*/ */
enum class ReportingType: uint8_t { enum class ReportingType: uint8_t {
//! Periodic generation of HK packets. //! Periodic generation of HK packets.
@ -152,6 +152,17 @@ public:
UPDATE_SNAPSHOT, UPDATE_SNAPSHOT,
}; };
/**
* Different data types are possible in the HK receiver map.
* For example, updates can be requested for full datasets or
* for single pool variables. Periodic reporting is only possible for
* data sets.
*/
enum class DataType: uint8_t {
LOCAL_POOL_VARIABLE,
DATA_SET
};
/* Copying forbidden */ /* Copying forbidden */
LocalDataPoolManager(const LocalDataPoolManager &) = delete; LocalDataPoolManager(const LocalDataPoolManager &) = delete;
LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete; LocalDataPoolManager operator=(const LocalDataPoolManager&) = delete;
@ -165,8 +176,6 @@ private:
HasLocalDataPoolIF* owner = nullptr; HasLocalDataPoolIF* owner = nullptr;
uint8_t nonDiagnosticIntervalFactor = 0; uint8_t nonDiagnosticIntervalFactor = 0;
dur_millis_t regularMinimumInterval = 0;
dur_millis_t diagnosticMinimumInterval = 0;
/** Default receiver for periodic HK packets */ /** Default receiver for periodic HK packets */
static object_id_t defaultHkDestination; static object_id_t defaultHkDestination;
@ -174,40 +183,25 @@ private:
/** The data pool manager will keep an internal map of HK receivers. */ /** The data pool manager will keep an internal map of HK receivers. */
struct HkReceiver { struct HkReceiver {
/** Different member of this union will be used depending on the /** Object ID of receiver */
type of data the receiver is interested in (full datasets or object_id_t objectId = objects::NO_OBJECT;
single data variables. */
DataType dataType = DataType::DATA_SET;
union DataId { union DataId {
DataId(): dataSetSid() {} DataId(): sid() {};
/** Will be initialized to INVALID_ADDRESS */ sid_t sid;
sid_t dataSetSid; lp_id_t localPoolId;
lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID;
}; };
DataId dataId; DataId dataId;
ReportingType reportingType = ReportingType::PERIODIC; ReportingType reportingType = ReportingType::PERIODIC;
// SHOULDDO: it would be nice to also have the object ID instead of
// a queue (or in addition).. but the FSFW is not ready for that yet.
// Also, an object can have multiple queues.
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE; MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
/** Different members of this union will be used depending on reporting
type */
union HkParameter {
/** This parameter will be used for the PERIODIC type */
uint32_t collectionIntervalTicks = 0;
/** This parameter will be used for the ON_UPDATE type */
bool hkDataChanged;
};
HkParameter hkParameter;
/** General purpose counter which is used for periodic generation. */
uint32_t intervalCounter;
}; };
/** Using a multimap as the same object might request multiple datasets */ /** This vector will contain the list of HK receivers. */
using HkReceiversMap = std::multimap<object_id_t, struct HkReceiver>; using HkReceivers = std::vector<struct HkReceiver>;
HkReceiversMap hkReceiversMap; HkReceivers hkReceiversMap;
/** This is the map holding the actual data. Should only be initialized /** This is the map holding the actual data. Should only be initialized
* once ! */ * once ! */
@ -252,18 +246,12 @@ private:
HousekeepingPacketDownlink& hkPacket, HousekeepingPacketDownlink& hkPacket,
store_address_t& storeId, bool forDownlink, size_t* serializedSize); store_address_t& storeId, bool forDownlink, size_t* serializedSize);
uint32_t intervalSecondsToInterval(bool isDiagnostics, void performPeriodicHkGeneration(HkReceiver& hkReceiver);
float collectionIntervalSeconds);
float intervalToIntervalSeconds(bool isDiagnostics,
uint32_t collectionInterval);
void performPeriodicHkGeneration(HkReceiver* hkReceiver);
ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable, ReturnValue_t togglePeriodicGeneration(sid_t sid, bool enable,
bool isDiagnostics); bool isDiagnostics);
ReturnValue_t changeCollectionInterval(sid_t sid, ReturnValue_t changeCollectionInterval(sid_t sid,
float newCollectionInterval, bool isDiagnostics); float newCollectionInterval, bool isDiagnostics);
ReturnValue_t generateSetStructurePacket(sid_t sid, ReturnValue_t generateSetStructurePacket(sid_t sid, bool isDiagnostics);
float collectionInterval, bool isDiagnostics);
}; };

View File

@ -1,5 +1,6 @@
#include "LocalPoolDataSetBase.h" #include "LocalPoolDataSetBase.h"
#include "../datapoollocal/LocalDataPoolManager.h" #include "../datapoollocal/LocalDataPoolManager.h"
#include "../housekeeping/PeriodicHousekeepingHelper.h"
#include "../serialize/SerializeAdapter.h" #include "../serialize/SerializeAdapter.h"
#include <cmath> #include <cmath>
@ -7,13 +8,14 @@
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
uint32_t setId, PoolVariableIF** registeredVariablesArray, uint32_t setId, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables): const size_t maxNumberOfVariables):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" // Configuration error.
<< std::endl; sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
return; << "invalid!" << std::endl;
} return;
}
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
this->sid.objectId = hkOwner->getObjectId(); this->sid.objectId = hkOwner->getObjectId();
this->sid.ownerSetId = setId; this->sid.ownerSetId = setId;
@ -29,8 +31,9 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>( HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
sid.objectId); sid.objectId);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" // Configuration error.
<< std::endl; sif::error << "LocalPoolDataSetBase::LocalPoolDataSetBase: Owner "
<< "invalid!" << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
@ -178,12 +181,12 @@ void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
*byte |= 1 << shiftNumber; *byte |= 1 << shiftNumber;
} }
void LocalPoolDataSetBase::setIsDiagnostic(bool isDiagnostics) { void LocalPoolDataSetBase::setDiagnostic(bool isDiagnostics) {
this->isDiagnostics = isDiagnostics; this->diagnostic = isDiagnostics;
} }
bool LocalPoolDataSetBase::getIsDiagnostics() const { bool LocalPoolDataSetBase::isDiagnostics() const {
return isDiagnostics; return diagnostic;
} }
void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) { void LocalPoolDataSetBase::setReportingEnabled(bool reportingEnabled) {
@ -194,6 +197,25 @@ bool LocalPoolDataSetBase::getReportingEnabled() const {
return reportingEnabled; return reportingEnabled;
} }
void LocalPoolDataSetBase::initializePeriodicHelper(
float collectionInterval, dur_millis_t minimumPeriodicInterval,
bool isDiagnostics, uint8_t nonDiagIntervalFactor) {
periodicHelper->initialize(collectionInterval, minimumPeriodicInterval,
isDiagnostics, nonDiagIntervalFactor);
}
void LocalPoolDataSetBase::setChanged(bool changed) {
this->changed = changed;
}
bool LocalPoolDataSetBase::isChanged() const {
return changed;
}
sid_t LocalPoolDataSetBase::getSid() const {
return sid;
}
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
uint8_t position) const { uint8_t position) const {
if(position > 7) { if(position > 7) {

View File

@ -1,7 +1,7 @@
#ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #ifndef FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_ #define FSFW_DATAPOOLLOCAL_LOCALPOOLDATASETBASE_H_
#include <fsfw/housekeeping/PeriodicHousekeepingHelper.h>
#include "HasLocalDataPoolIF.h" #include "HasLocalDataPoolIF.h"
#include "../datapool/DataSetIF.h" #include "../datapool/DataSetIF.h"
#include "../datapool/PoolDataSetBase.h" #include "../datapool/PoolDataSetBase.h"
@ -10,6 +10,7 @@
#include <vector> #include <vector>
class LocalDataPoolManager; class LocalDataPoolManager;
class PeriodicHousekeepingHelper;
/** /**
* @brief The LocalDataSet class manages a set of locally checked out * @brief The LocalDataSet class manages a set of locally checked out
@ -38,14 +39,16 @@ class LocalPoolDataSetBase: public PoolDataSetBase {
public: public:
/** /**
* @brief Constructor for the creator of local pool data. * @brief Constructor for the creator of local pool data.
* @details
* This constructor also initializes the components required for
* periodic handling.
*/ */
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
uint32_t setId, PoolVariableIF** registeredVariablesArray, uint32_t setId, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables); const size_t maxNumberOfVariables);
/** /**
* @brief Constructor for users of local pool data. The passed pool * @brief Constructor for users of local pool data.
* owner should implement the HasHkPoolParametersIF.
* @details * @details
* @param sid Unique identifier of dataset consisting of object ID and * @param sid Unique identifier of dataset consisting of object ID and
* set ID. * set ID.
@ -67,6 +70,8 @@ public:
void setValidityBufferGeneration(bool withValidityBuffer); void setValidityBufferGeneration(bool withValidityBuffer);
sid_t getSid() const;
ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize, ReturnValue_t serialize(uint8_t** buffer, size_t* size, size_t maxSize,
SerializeIF::Endianness streamEndianness) const override; SerializeIF::Endianness streamEndianness) const override;
ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size, ReturnValue_t deSerialize(const uint8_t** buffer, size_t *size,
@ -102,12 +107,15 @@ public:
void setValidity(bool valid, bool setEntriesRecursively); void setValidity(bool valid, bool setEntriesRecursively);
bool isValid() const override; bool isValid() const override;
void setChanged(bool changed);
bool isChanged() const;
protected: protected:
sid_t sid; sid_t sid;
bool isDiagnostics = false; bool diagnostic = false;
void setIsDiagnostic(bool diagnostics); void setDiagnostic(bool diagnostics);
bool getIsDiagnostics() const; bool isDiagnostics() const;
/** /**
* Used for periodic generation. * Used for periodic generation.
@ -116,12 +124,22 @@ protected:
void setReportingEnabled(bool enabled); void setReportingEnabled(bool enabled);
bool getReportingEnabled() const; bool getReportingEnabled() const;
void initializePeriodicHelper(float collectionInterval,
dur_millis_t minimumPeriodicInterval,
bool isDiagnostics, uint8_t nonDiagIntervalFactor = 5);
/** /**
* If the valid state of a dataset is always relevant to the whole * If the valid state of a dataset is always relevant to the whole
* data set we can use this flag. * data set we can use this flag.
*/ */
bool valid = false; bool valid = false;
/**
* Can be used to mark the dataset as changed, which is used
* by the LocalDataPoolManager to send out update messages.
*/
bool changed = false;
bool withValidityBuffer = true; bool withValidityBuffer = true;
/** /**
@ -147,7 +165,7 @@ protected:
*/ */
void bitSetter(uint8_t* byte, uint8_t position) const; void bitSetter(uint8_t* byte, uint8_t position) const;
bool bitGetter(const uint8_t* byte, uint8_t position) const; bool bitGetter(const uint8_t* byte, uint8_t position) const;
private:
PeriodicHousekeepingHelper* periodicHelper = nullptr; PeriodicHousekeepingHelper* periodicHelper = nullptr;
}; };

View File

@ -17,6 +17,24 @@
template <uint8_t NUM_VARIABLES> template <uint8_t NUM_VARIABLES>
class StaticLocalDataSet: public LocalPoolDataSetBase { class StaticLocalDataSet: public LocalPoolDataSetBase {
public: public:
/**
* Constructor used by data owner and creator like device handlers.
* This constructor also initialized the components required for
* periodic handling.
* @param hkOwner
* @param setId
*/
StaticLocalDataSet(HasLocalDataPoolIF* hkOwner,
uint32_t setId): LocalPoolDataSetBase(hkOwner, setId, nullptr,
NUM_VARIABLES) {
this->setContainer(poolVarList.data());
}
/**
* Constructor used by data users like controllers.
* @param hkOwner
* @param setId
*/
StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr, StaticLocalDataSet(sid_t sid): LocalPoolDataSetBase(sid, nullptr,
NUM_VARIABLES) { NUM_VARIABLES) {
this->setContainer(poolVarList.data()); this->setContainer(poolVarList.data());

View File

@ -391,7 +391,7 @@ ReturnValue_t DeviceHandlerBase::isModeCombinationValid(Mode_t mode,
ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap( ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles, DeviceCommandId_t deviceCommand, uint16_t maxDelayCycles,
PoolDataSetIF* replyDataSet, size_t replyLen, bool periodic, LocalPoolDataSetBase* replyDataSet, size_t replyLen, bool periodic,
bool hasDifferentReplyId, DeviceCommandId_t replyId) { bool hasDifferentReplyId, DeviceCommandId_t replyId) {
//No need to check, as we may try to insert multiple times. //No need to check, as we may try to insert multiple times.
insertInCommandMap(deviceCommand); insertInCommandMap(deviceCommand);
@ -405,7 +405,7 @@ ReturnValue_t DeviceHandlerBase::insertInCommandAndReplyMap(
} }
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, PoolDataSetIF* dataSet, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet,
size_t replyLen, bool periodic) { size_t replyLen, bool periodic) {
DeviceReplyInfo info; DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles; info.maxDelayCycles = maxDelayCycles;
@ -455,7 +455,7 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF *dataSet) { LocalPoolDataSetBase *dataSet) {
auto replyIter = deviceReplyMap.find(replyId); auto replyIter = deviceReplyMap.find(replyId);
if(replyIter == deviceReplyMap.end()) { if(replyIter == deviceReplyMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
@ -1396,7 +1396,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
DataSetIF* DeviceHandlerBase::getDataSetHandle(sid_t sid) { LocalPoolDataSetBase* DeviceHandlerBase::getDataSetHandle(sid_t sid) {
auto iter = deviceReplyMap.find(sid.ownerSetId); auto iter = deviceReplyMap.find(sid.ownerSetId);
if(iter != deviceReplyMap.end()) { if(iter != deviceReplyMap.end()) {
return iter->second.dataSet; return iter->second.dataSet;

View File

@ -389,7 +389,8 @@ protected:
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInCommandAndReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, PoolDataSetIF* replyDataSet = nullptr, uint16_t maxDelayCycles,
LocalPoolDataSetBase* replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false, size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
@ -404,7 +405,7 @@ protected:
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, PoolDataSetIF* dataSet = nullptr, uint16_t maxDelayCycles, LocalPoolDataSetBase* dataSet = nullptr,
size_t replyLen = 0, bool periodic = false); size_t replyLen = 0, bool periodic = false);
/** /**
@ -434,7 +435,7 @@ protected:
bool periodic = false); bool periodic = false);
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId, ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF* dataset); LocalPoolDataSetBase* dataset);
/** /**
* @brief Can be implemented by child handler to * @brief Can be implemented by child handler to
@ -663,7 +664,7 @@ protected:
//! The dataset used to access housekeeping data related to the //! The dataset used to access housekeeping data related to the
//! respective device reply. Will point to a dataset held by //! respective device reply. Will point to a dataset held by
//! the child handler (if one is specified) //! the child handler (if one is specified)
PoolDataSetIF* dataSet = nullptr; LocalPoolDataSetBase* dataSet;
//! The command that expects this reply. //! The command that expects this reply.
DeviceCommandMap::iterator command; DeviceCommandMap::iterator command;
}; };
@ -1198,7 +1199,7 @@ private:
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
virtual DataSetIF* getDataSetHandle(sid_t sid) override; virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;
virtual dur_millis_t getPeriodicOperationFrequency() const override; virtual dur_millis_t getPeriodicOperationFrequency() const override;

View File

@ -3,14 +3,15 @@
#include "../ipc/CommandMessage.h" #include "../ipc/CommandMessage.h"
#include "../ipc/FwMessageTypes.h" #include "../ipc/FwMessageTypes.h"
#include "../objectmanager/frameworkObjects.h"
#include "../objectmanager/SystemObjectIF.h" #include "../objectmanager/SystemObjectIF.h"
#include "../storagemanager/StorageManagerIF.h" #include "../storagemanager/StorageManagerIF.h"
#include <limits>
union sid_t { union sid_t {
static constexpr uint64_t INVALID_ADDRESS = static constexpr uint64_t INVALID_SID = -1;
std::numeric_limits<uint64_t>::max(); static constexpr uint32_t INVALID_SET_ID = -1;
sid_t(): raw(INVALID_ADDRESS) {} static constexpr uint32_t INVALID_OBJECT_ID = objects::NO_OBJECT;
sid_t(): raw(INVALID_SID) {}
sid_t(object_id_t objectId, uint32_t setId): sid_t(object_id_t objectId, uint32_t setId):
objectId(objectId), objectId(objectId),
@ -31,7 +32,7 @@ union sid_t {
uint64_t raw; uint64_t raw;
bool notSet() const { bool notSet() const {
return raw == INVALID_ADDRESS; return raw == INVALID_SID;
} }
bool operator==(const sid_t& other) const { bool operator==(const sid_t& other) const {

View File

@ -10,10 +10,11 @@ void PeriodicHousekeepingHelper::initialize(float collectionInterval,
dur_millis_t minimumPeriodicInterval, bool isDiagnostics, dur_millis_t minimumPeriodicInterval, bool isDiagnostics,
uint8_t nonDiagIntervalFactor) { uint8_t nonDiagIntervalFactor) {
this->minimumPeriodicInterval = minimumPeriodicInterval; this->minimumPeriodicInterval = minimumPeriodicInterval;
if(not owner->getIsDiagnostics()) { if(isDiagnostics) {
this->minimumPeriodicInterval = this->minimumPeriodicInterval * this->minimumPeriodicInterval = this->minimumPeriodicInterval *
nonDiagIntervalFactor; nonDiagIntervalFactor;
} }
collectionIntervalTicks = intervalSecondsToInterval(collectionInterval);
} }
float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() { float PeriodicHousekeepingHelper::getCollectionIntervalInSeconds() {

View File

@ -20,7 +20,6 @@ public:
private: private:
LocalPoolDataSetBase* owner = nullptr; LocalPoolDataSetBase* owner = nullptr;
uint32_t intervalSecondsToInterval(float collectionIntervalSeconds); uint32_t intervalSecondsToInterval(float collectionIntervalSeconds);
float intervalToIntervalSeconds(uint32_t collectionInterval); float intervalToIntervalSeconds(uint32_t collectionInterval);
@ -30,6 +29,4 @@ private:
}; };
#endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */ #endif /* FSFW_HOUSEKEEPING_PERIODICHOUSEKEEPINGHELPER_H_ */

View File

@ -6,7 +6,7 @@
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, 5) {}
Service3Housekeeping::~Service3Housekeeping() {} Service3Housekeeping::~Service3Housekeeping() {}

View File

@ -387,7 +387,7 @@ void CommandingServiceBase::acceptPacket(uint8_t reportId,
void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) { void CommandingServiceBase::checkAndExecuteFifo(CommandMapIter iter) {
store_address_t address; store_address_t address;
if (iter->second.fifo.retrieve(&address) != RETURN_OK) { if (iter->second.fifo.retrieve(&address) != RETURN_OK) {
commandMap.erase(&iter); commandMap.erase(iter->first);
} else { } else {
TcPacketStored newPacket(address); TcPacketStored newPacket(address);
startExecution(&newPacket, iter); startExecution(&newPacket, iter);
@ -411,8 +411,14 @@ void CommandingServiceBase::checkTimeout() {
uint32_t uptime; uint32_t uptime;
Clock::getUptime(&uptime); Clock::getUptime(&uptime);
CommandMapIter iter; CommandMapIter iter;
// TODO: BUG HERE! Problems with comparison operator of iterator.
for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) { for (iter = commandMap.begin(); iter != commandMap.end(); ++iter) {
if(commandMap.empty()) {
// intermediate solution.
break;
}
if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) { if ((iter->second.uptimeOfStart + (timeoutSeconds * 1000)) < uptime) {
sif::info << "test" << std::endl;
verificationReporter.sendFailureReport( verificationReporter.sendFailureReport(
TC_VERIFY::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags, TC_VERIFY::COMPLETION_FAILURE, iter->second.tcInfo.ackFlags,
iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl, iter->second.tcInfo.tcPacketId, iter->second.tcInfo.tcSequenceControl,

View File

@ -63,8 +63,8 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message); &message);
if (status != HasReturnvaluesIF::RETURN_OK) { if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error << "VerificationReporter::sendFailureReport Error writing " sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << status << std::dec << "to queue. Code: " << std::hex << "0x" << status << std::dec
<< std::endl; << std::endl;
} }
} }
@ -81,8 +81,8 @@ void VerificationReporter::sendFailureReport(uint8_t report_id,
ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue, ReturnValue_t status = MessageQueueSenderIF::sendMessage(acknowledgeQueue,
&message); &message);
if (status != HasReturnvaluesIF::RETURN_OK) { if (status != HasReturnvaluesIF::RETURN_OK) {
sif::error << "VerificationReporter::sendFailureReport Error writing " sif::error << "VerificationReporter::sendFailureReport: Error writing "
<< "to queue. Code: " << std::hex << status << std::dec << "to queue. Code: " << std::hex << "0x" << status << std::dec
<< std::endl; << std::endl;
} }
} }