Merge branch 'mueller/project/distribDatapool' into mueller/master

This commit is contained in:
Robin Müller 2020-08-27 14:23:14 +02:00
commit 790e0399b7
28 changed files with 306 additions and 245 deletions

View File

@ -5,9 +5,6 @@ PoolDataSetBase::PoolDataSetBase(PoolVariableIF** registeredVariablesArray,
const size_t maxFillCount): const size_t maxFillCount):
registeredVariables(registeredVariablesArray), registeredVariables(registeredVariablesArray),
maxFillCount(maxFillCount) { maxFillCount(maxFillCount) {
for (uint8_t count = 0; count < maxFillCount; count++) {
registeredVariables[count] = nullptr;
}
} }
PoolDataSetBase::~PoolDataSetBase() {} PoolDataSetBase::~PoolDataSetBase() {}

View File

@ -48,9 +48,14 @@ public:
/** Command queue for housekeeping messages. */ /** Command queue for housekeeping messages. */
virtual MessageQueueId_t getCommandQueue() const = 0; virtual MessageQueueId_t getCommandQueue() const = 0;
/** Is used by pool owner to initialize the pool map once */ /**
virtual ReturnValue_t initializePoolEntries( * Is used by pool owner to initialize the pool map once
LocalDataPool& localDataPoolMap) = 0; * The manager instance shall also be passed to this function.
* It can be used to subscribe for periodic packets for for updates.
*/
virtual ReturnValue_t initializeLocalDataPool(
LocalDataPool& localDataPoolMap,
LocalDataPoolManager& poolManager) = 0;
/** Can be used to get a handle to the local data pool manager. */ /** Can be used to get a handle to the local data pool manager. */
virtual LocalDataPoolManager* getHkManagerHandle() = 0; virtual LocalDataPoolManager* getHkManagerHandle() = 0;

View File

@ -8,6 +8,8 @@
#include <array> #include <array>
#include <cmath> #include <cmath>
object_id_t LocalDataPoolManager::defaultHkDestination = objects::NO_OBJECT;
LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner, LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner,
MessageQueueIF* queueToUse, bool appendValidityBuffer): MessageQueueIF* queueToUse, bool appendValidityBuffer):
appendValidityBuffer(appendValidityBuffer) { appendValidityBuffer(appendValidityBuffer) {
@ -28,48 +30,41 @@ LocalDataPoolManager::LocalDataPoolManager(HasLocalDataPoolIF* owner,
} }
hkQueue = queueToUse; hkQueue = queueToUse;
if(defaultHkDestination != objects::NO_OBJECT) {
AcceptsHkPacketsIF* hkPacketReceiver =
objectManager->get<AcceptsHkPacketsIF>(defaultHkDestination);
if(hkPacketReceiver != nullptr) {
defaultHkDestinationId = hkPacketReceiver->getHkQueue();
}
}
} }
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse, LocalDataPoolManager::~LocalDataPoolManager() {}
object_id_t hkDestination, uint8_t nonDiagInvlFactor) {
ReturnValue_t LocalDataPoolManager::initialize(MessageQueueIF* queueToUse) {
if(queueToUse == nullptr) { if(queueToUse == nullptr) {
sif::error << "LocalDataPoolManager::initialize: Supplied queue " sif::error << "LocalDataPoolManager::initialize: Supplied queue "
"invalid!" << std::endl; "invalid!" << std::endl;
} }
hkQueue = queueToUse; hkQueue = queueToUse;
if(hkDestination == objects::NO_OBJECT) { return HasReturnvaluesIF::RETURN_OK;
return initializeHousekeepingPoolEntriesOnce(); }
}
AcceptsHkPacketsIF* hkReceiver =
objectManager->get<AcceptsHkPacketsIF>(hkDestination);
if(hkReceiver != nullptr) {
setHkPacketDestination(hkReceiver->getHkQueue());
}
else {
sif::warning << "LocalDataPoolManager::initialize: Could not retrieve"
" queue ID from HK destination object ID. " << std::flush;
sif::warning << "Make sure it exists and the object impements "
"AcceptsHkPacketsIF!" << std::endl;
}
ReturnValue_t LocalDataPoolManager::initializeAfterTaskCreation(
uint8_t nonDiagInvlFactor) {
setNonDiagnosticIntervalFactor(nonDiagInvlFactor); setNonDiagnosticIntervalFactor(nonDiagInvlFactor);
diagnosticMinimumInterval = owner->getPeriodicOperationFrequency(); diagnosticMinimumInterval = owner->getPeriodicOperationFrequency();
regularMinimumInterval = diagnosticMinimumInterval * nonDiagnosticIntervalFactor; regularMinimumInterval = diagnosticMinimumInterval *
nonDiagnosticIntervalFactor;
return initializeHousekeepingPoolEntriesOnce(); return initializeHousekeepingPoolEntriesOnce();
} }
void LocalDataPoolManager::setHkPacketDestination(
MessageQueueId_t hkDestination) {
this->hkDestination = hkDestination;
}
LocalDataPoolManager::~LocalDataPoolManager() {}
ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
if(not mapInitialized) { if(not mapInitialized) {
ReturnValue_t result = owner->initializePoolEntries(localPoolMap); ReturnValue_t result = owner->initializeLocalDataPool(localPoolMap,
*this);
if(result == HasReturnvaluesIF::RETURN_OK) { if(result == HasReturnvaluesIF::RETURN_OK) {
mapInitialized = true; mapInitialized = true;
} }
@ -80,6 +75,67 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() {
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
ReturnValue_t LocalDataPoolManager::performHkOperation() {
for(auto& hkReceiversIter: hkReceiversMap) {
HkReceiver* receiver = &hkReceiversIter.second;
if(not receiver->reportingEnabled) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(receiver->reportingType) {
case(ReportingType::PERIODIC): {
if(receiver->dataId.dataSetSid.notSet()) {
// Periodic packets shall only be generated from datasets.
continue;
}
performPeriodicHkGeneration(receiver);
break;
}
case(ReportingType::UPDATE_SNAPSHOT): {
// 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;
}
ReturnValue_t LocalDataPoolManager::subscribeForPeriodicPacket(sid_t sid,
bool enableReporting, float collectionInterval, bool isDiagnostics,
object_id_t packetDestination) {
AcceptsHkPacketsIF* hkReceiverObject =
objectManager->get<AcceptsHkPacketsIF>(packetDestination);
if(hkReceiverObject == nullptr) {
sif::error << "LocalDataPoolManager::subscribeForPeriodicPacket:"
" Invalid receiver!"<< std::endl;
return HasReturnvaluesIF::RETURN_OK;
}
struct HkReceiver hkReceiver;
hkReceiver.dataId.dataSetSid = sid;
hkReceiver.reportingType = ReportingType::PERIODIC;
hkReceiver.destinationQueue = hkReceiverObject->getHkQueue();
hkReceiver.reportingEnabled = enableReporting;
if(not isDiagnostics) {
hkReceiver.hkParameter.collectionIntervalTicks =
intervalSecondsToInterval(isDiagnostics, collectionInterval *
nonDiagnosticIntervalFactor);
}
else {
hkReceiver.hkParameter.collectionIntervalTicks =
intervalSecondsToInterval(isDiagnostics, collectionInterval);
}
hkReceiver.isDiagnostics = isDiagnostics;
hkReceiver.intervalCounter = 1;
hkReceiversMap.emplace(packetDestination, hkReceiver);
return HasReturnvaluesIF::RETURN_OK;
}
ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage(
CommandMessage* message) { CommandMessage* message) {
Command_t command = message->getCommand(); Command_t command = message->getCommand();
@ -121,15 +177,15 @@ const HasLocalDataPoolIF* LocalDataPoolManager::getOwner() const {
} }
ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid, ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
float collectionInterval, MessageQueueId_t sendTo) { float collectionInterval, MessageQueueId_t destination) {
LocalPoolDataSetBase* dataSetToSerialize = dynamic_cast<LocalPoolDataSetBase*>( LocalPoolDataSetBase* dataSetToSerialize =
owner->getDataSetHandle(sid)); dynamic_cast<LocalPoolDataSetBase*>(owner->getDataSetHandle(sid));
if(dataSetToSerialize == nullptr) { if(dataSetToSerialize == nullptr) {
sif::warning << "HousekeepingManager::generateHousekeepingPacket:" sif::warning << "HousekeepingManager::generateHousekeepingPacket:"
" Set ID not found" << std::endl; " Set ID not found or dataset not assigned!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
sif::info << "hk gen called" << std::endl;
store_address_t storeId; store_address_t storeId;
HousekeepingPacketDownlink hkPacket(sid, collectionInterval, HousekeepingPacketDownlink hkPacket(sid, collectionInterval,
dataSetToSerialize->getFillCount(), dataSetToSerialize); dataSetToSerialize->getFillCount(), dataSetToSerialize);
@ -144,30 +200,23 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid,
if(hkQueue == nullptr) { if(hkQueue == nullptr) {
return QUEUE_OR_DESTINATION_NOT_SET; return QUEUE_OR_DESTINATION_NOT_SET;
} }
if(destination == MessageQueueIF::NO_QUEUE) {
if(sendTo != MessageQueueIF::NO_QUEUE) { if(defaultHkDestinationId == MessageQueueIF::NO_QUEUE) {
result = hkQueue->sendMessage(sendTo, &hkMessage); // error, all destinations invalid
} return HasReturnvaluesIF::RETURN_FAILED;
else {
if(hkDestination == MessageQueueIF::NO_QUEUE) {
sif::warning << "LocalDataPoolManager::generateHousekeepingPacket:"
" Destination is not set properly!" << std::endl;
return QUEUE_OR_DESTINATION_NOT_SET;
}
else {
result = hkQueue->sendMessage(hkDestination, &hkMessage);
} }
destination = defaultHkDestinationId;
} }
return result; return hkQueue->sendMessage(destination, &hkMessage);
} }
ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore(
HousekeepingPacketDownlink& hkPacket, HousekeepingPacketDownlink& hkPacket,
store_address_t *storeId) { store_address_t *storeId) {
uint8_t* dataPtr = nullptr; uint8_t* dataPtr = nullptr;
size_t serializedSize = hkPacket.getSerializedSize(); size_t serializedSize = 0;
const size_t maxSize = serializedSize; const size_t maxSize = hkPacket.getSerializedSize();
ReturnValue_t result = ipcStore->getFreeElement(storeId, ReturnValue_t result = ipcStore->getFreeElement(storeId,
serializedSize, &dataPtr); serializedSize, &dataPtr);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
@ -212,46 +261,17 @@ void LocalDataPoolManager::setNonDiagnosticIntervalFactor(
} }
ReturnValue_t LocalDataPoolManager::performHkOperation() {
for(auto& hkReceiversIter: hkReceiversMap) {
HkReceiver* receiver = &hkReceiversIter.second;
if(not receiver->reportingEnabled) {
return HasReturnvaluesIF::RETURN_OK;
}
switch(receiver->reportingType) {
case(ReportingType::PERIODIC): {
if(receiver->dataId.dataSetSid.notSet()) {
// Periodic packets shall only be generated from datasets.
continue;
}
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) { void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) {
if(receiver->intervalCounter >= intervalSecondsToInterval( if(receiver->intervalCounter >=
receiver->isDiagnostics, receiver->hkParameter.collectionIntervalTicks) {
receiver->hkParameter.collectionIntervalSeconds)) {
ReturnValue_t result = generateHousekeepingPacket( ReturnValue_t result = generateHousekeepingPacket(
receiver->dataId.dataSetSid, receiver->destinationQueue); receiver->dataId.dataSetSid);
if(result != HasReturnvaluesIF::RETURN_OK) { if(result != HasReturnvaluesIF::RETURN_OK) {
// configuration error // configuration error
sif::debug << "LocalDataPoolManager::performHkOperation:" sif::debug << "LocalDataPoolManager::performHkOperation:"
<< "0x" << std::setfill('0') << std::setw(8) << "0x" << std::setfill('0') << std::setw(8)
<< owner->getObjectId() << " Error generating " << owner->getObjectId() << " Error generating "
<< "HK packet" << std::setfill(' ') << std::endl; << "HK packet" << std::setfill(' ') << std::endl;
} }
receiver->intervalCounter = 1; receiver->intervalCounter = 1;
} }
@ -263,19 +283,23 @@ void LocalDataPoolManager::performPeriodicHkGeneration(HkReceiver* receiver) {
uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics, uint32_t LocalDataPoolManager::intervalSecondsToInterval(bool isDiagnostics,
float collectionIntervalSeconds) { float collectionIntervalSeconds) {
if(isDiagnostics) { if(isDiagnostics) {
return std::ceil(collectionIntervalSeconds/diagnosticMinimumInterval); return std::ceil(collectionIntervalSeconds * 1000
/diagnosticMinimumInterval);
} }
else { else {
return std::ceil(collectionIntervalSeconds/regularMinimumInterval); return std::ceil(collectionIntervalSeconds * 1000
/regularMinimumInterval);
} }
} }
float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics, float LocalDataPoolManager::intervalToIntervalSeconds(bool isDiagnostics,
uint32_t collectionInterval) { uint32_t collectionInterval) {
if(isDiagnostics) { if(isDiagnostics) {
return static_cast<float>(collectionInterval * diagnosticMinimumInterval); return static_cast<float>(collectionInterval *
diagnosticMinimumInterval);
} }
else { else {
return static_cast<float>(collectionInterval * regularMinimumInterval); return static_cast<float>(collectionInterval *
regularMinimumInterval);
} }
} }

View File

@ -15,8 +15,13 @@
#include <map> #include <map>
namespace Factory {
void setStaticFrameworkObjectIds();
}
class LocalDataSetBase; class LocalDataSetBase;
/** /**
* @brief This class is the managing instance for local data pool. * @brief This class is the managing instance for local data pool.
* @details * @details
@ -40,6 +45,7 @@ class LocalDataPoolManager {
template<typename T, uint16_t vecSize> template<typename T, uint16_t vecSize>
friend class LocalPoolVector; friend class LocalPoolVector;
friend class LocalPoolDataSetBase; friend class LocalPoolDataSetBase;
friend void (Factory::setStaticFrameworkObjectIds)();
public: public:
static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER;
@ -47,7 +53,6 @@ public:
static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1); static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1);
static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x2); static constexpr ReturnValue_t QUEUE_OR_DESTINATION_NOT_SET = MAKE_RETURN_CODE(0x2);
//static constexpr ReturnValue_t SET_NOT_FOUND = MAKE_RETURN_CODE(0x3);
/** /**
* This constructor is used by a class which wants to implement * This constructor is used by a class which wants to implement
@ -70,8 +75,16 @@ public:
* @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc * @param nonDiagInvlFactor See #setNonDiagnosticIntervalFactor doc
* @return * @return
*/ */
ReturnValue_t initialize(MessageQueueIF* queueToUse, ReturnValue_t initialize(MessageQueueIF* queueToUse);
object_id_t hkDestination, uint8_t nonDiagInvlFactor = 5);
ReturnValue_t initializeAfterTaskCreation(uint8_t nonDiagInvlFactor = 5);
/**
* @return
*/
ReturnValue_t subscribeForPeriodicPacket(sid_t sid, bool enableReporting,
float collectionInterval, bool isDiagnostics,
object_id_t packetDestination = defaultHkDestination);
/** /**
* Non-Diagnostics packets usually have a lower minimum sampling frequency * Non-Diagnostics packets usually have a lower minimum sampling frequency
@ -90,20 +103,15 @@ public:
* @return * @return
*/ */
ReturnValue_t performHkOperation(); ReturnValue_t performHkOperation();
/**
* This function is used to set the default HK packet destination.
* This destination will usually only be set once.
* @param hkDestination
*/
void setHkPacketDestination(MessageQueueId_t hkDestination);
/** /**
* Generate a housekeeping packet with a given SID. * Generate a housekeeping packet with a given SID.
* @param sid * @param sid
* @return * @return
*/ */
ReturnValue_t generateHousekeepingPacket(sid_t sid, float collectionInterval, ReturnValue_t generateHousekeepingPacket(sid_t sid,
MessageQueueId_t sendTo = MessageQueueIF::NO_QUEUE); float collectionInterval = 0,
MessageQueueId_t destination = MessageQueueIF::NO_QUEUE);
ReturnValue_t generateSetStructurePacket(sid_t sid); ReturnValue_t generateSetStructurePacket(sid_t sid);
ReturnValue_t handleHousekeepingMessage(CommandMessage* message); ReturnValue_t handleHousekeepingMessage(CommandMessage* message);
@ -134,11 +142,13 @@ public:
* full dataset updates. * full dataset updates.
*/ */
enum class ReportingType: uint8_t { enum class ReportingType: uint8_t {
// Periodic generation of HK packets. //! Periodic generation of HK packets.
PERIODIC, PERIODIC,
// Notification will be sent out as message. //! Update notification will be sent out as message.
// Data is accessed via shared data set or multiple local data sets. UPDATE_NOTIFICATION,
ON_UPDATE, //! Notification will be sent out as message and a snapshot of the
//! current data will be generated.
UPDATE_SNAPSHOT,
}; };
/* Copying forbidden */ /* Copying forbidden */
@ -157,26 +167,31 @@ private:
dur_millis_t regularMinimumInterval = 0; dur_millis_t regularMinimumInterval = 0;
dur_millis_t diagnosticMinimumInterval = 0; dur_millis_t diagnosticMinimumInterval = 0;
/** Default receiver for periodic HK packets */
static object_id_t defaultHkDestination;
MessageQueueId_t defaultHkDestinationId = MessageQueueIF::NO_QUEUE;
/** 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 /** Different member of this union will be used depending on the
type of data the receiver is interested in (full datasets or type of data the receiver is interested in (full datasets or
single data variables. */ single data variables. */
union DataId { union DataId {
DataId(): dataSetSid() {}
/** Will be initialized to INVALID_ADDRESS */ /** Will be initialized to INVALID_ADDRESS */
sid_t dataSetSid; sid_t dataSetSid;
lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID; lp_id_t localPoolId = HasLocalDataPoolIF::NO_POOL_ID;
}; };
DataId dataId; DataId dataId;
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
ReportingType reportingType = ReportingType::PERIODIC; ReportingType reportingType = ReportingType::PERIODIC;
MessageQueueId_t destinationQueue = MessageQueueIF::NO_QUEUE;
bool reportingEnabled = true; bool reportingEnabled = true;
/** Different members of this union will be used depending on reporting /** Different members of this union will be used depending on reporting
type */ type */
union HkParameter { union HkParameter {
/** This parameter will be used for the PERIODIC type */ /** This parameter will be used for the PERIODIC type */
float collectionIntervalSeconds = 0; uint32_t collectionIntervalTicks = 0;
/** This parameter will be used for the ON_UPDATE type */ /** This parameter will be used for the ON_UPDATE type */
bool hkDataChanged; bool hkDataChanged;
}; };
@ -205,13 +220,6 @@ private:
*/ */
MessageQueueIF* hkQueue = nullptr; MessageQueueIF* hkQueue = nullptr;
/**
* HK replies will always be a reply to the commander, but HK packet
* can be sent to another destination by specifying this message queue
* ID, for example to a dedicated housekeeping service implementation.
*/
MessageQueueId_t hkDestination = MessageQueueIF::NO_QUEUE;
/** Global IPC store is used to store all packets. */ /** Global IPC store is used to store all packets. */
StorageManagerIF* ipcStore = nullptr; StorageManagerIF* ipcStore = nullptr;
/** /**

View File

@ -5,32 +5,17 @@
#include <cmath> #include <cmath>
#include <cstring> #include <cstring>
LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, LocalDataSet::LocalDataSet(HasLocalDataPoolIF *hkOwner, uint32_t setId,
const size_t maxNumberOfVariables): const size_t maxNumberOfVariables):
LocalPoolDataSetBase(hkOwner,poolVarList.data(), maxNumberOfVariables) { LocalPoolDataSetBase(hkOwner, setId, nullptr, maxNumberOfVariables),
poolVarList.reserve(maxNumberOfVariables); poolVarList(maxNumberOfVariables) {
poolVarList.resize(maxNumberOfVariables); this->setContainer(poolVarList.data());
if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
<< std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
} }
LocalDataSet::LocalDataSet(object_id_t ownerId, LocalDataSet::LocalDataSet(sid_t sid, const size_t maxNumberOfVariables):
const size_t maxNumberOfVariables): LocalPoolDataSetBase(sid, nullptr, maxNumberOfVariables),
LocalPoolDataSetBase(ownerId, poolVarList.data(), maxNumberOfVariables) { poolVarList(maxNumberOfVariables) {
poolVarList.reserve(maxNumberOfVariables); this->setContainer(poolVarList.data());
poolVarList.resize(maxNumberOfVariables);
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
ownerId);
if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
<< std::endl;
return;
}
hkManager = hkOwner->getHkManagerHandle();
} }
LocalDataSet::~LocalDataSet() {} LocalDataSet::~LocalDataSet() {}

View File

@ -5,8 +5,9 @@
class LocalDataSet: public LocalPoolDataSetBase { class LocalDataSet: public LocalPoolDataSetBase {
public: public:
LocalDataSet(HasLocalDataPoolIF* hkOwner, const size_t maxSize); LocalDataSet(HasLocalDataPoolIF* hkOwner, uint32_t setId,
LocalDataSet(object_id_t owner, const size_t maxSize); const size_t maxSize);
LocalDataSet(sid_t sid, const size_t maxSize);
virtual~ LocalDataSet(); virtual~ LocalDataSet();
//! Copying forbidden for now. //! Copying forbidden for now.

View File

@ -6,7 +6,7 @@
#include <cstring> #include <cstring>
LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
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) {
@ -15,20 +15,23 @@ LocalPoolDataSetBase::LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
this->sid.objectId = hkOwner->getObjectId();
this->sid.ownerSetId = setId;
} }
LocalPoolDataSetBase::LocalPoolDataSetBase(object_id_t ownerId, LocalPoolDataSetBase::LocalPoolDataSetBase(sid_t sid,
PoolVariableIF** registeredVariablesArray, PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables): const size_t maxNumberOfVariables):
PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) { PoolDataSetBase(registeredVariablesArray, maxNumberOfVariables) {
HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>( HasLocalDataPoolIF* hkOwner = objectManager->get<HasLocalDataPoolIF>(
ownerId); sid.objectId);
if(hkOwner == nullptr) { if(hkOwner == nullptr) {
sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!"
<< std::endl; << std::endl;
return; return;
} }
hkManager = hkOwner->getHkManagerHandle(); hkManager = hkOwner->getHkManagerHandle();
this->sid = sid;
} }
LocalPoolDataSetBase::~LocalPoolDataSetBase() { LocalPoolDataSetBase::~LocalPoolDataSetBase() {
@ -123,14 +126,6 @@ ReturnValue_t LocalPoolDataSetBase::serializeLocalPoolIds(uint8_t** buffer,
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
if(position > 7) {
sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl;
return;
}
uint8_t shiftNumber = position + (7 - 2 * position);
*byte |= 1 << shiftNumber;
}
size_t LocalPoolDataSetBase::getSerializedSize() const { size_t LocalPoolDataSetBase::getSerializedSize() const {
if(withValidityBuffer) { if(withValidityBuffer) {
@ -170,9 +165,21 @@ ReturnValue_t LocalPoolDataSetBase::serialize(uint8_t **buffer, size_t *size,
} }
} }
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte, uint8_t position) const { void LocalPoolDataSetBase::bitSetter(uint8_t* byte, uint8_t position) const {
if(position > 7) { if(position > 7) {
sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl; sif::debug << "Pool Raw Access: Bit setting invalid position"
<< std::endl;
return;
}
uint8_t shiftNumber = position + (7 - 2 * position);
*byte |= 1 << shiftNumber;
}
bool LocalPoolDataSetBase::bitGetter(const uint8_t* byte,
uint8_t position) const {
if(position > 7) {
sif::debug << "Pool Raw Access: Bit setting invalid position"
<< std::endl;
return false; return false;
} }
uint8_t shiftNumber = position + (7 - 2 * position); uint8_t shiftNumber = position + (7 - 2 * position);

View File

@ -30,28 +30,25 @@ class LocalDataPoolManager;
* *
* @ingroup data_pool * @ingroup data_pool
*/ */
// todo: make withValidityBuffer a member
class LocalPoolDataSetBase: public PoolDataSetBase { class LocalPoolDataSetBase: public PoolDataSetBase {
public: public:
/** /**
* @brief Constructor for the creator of local pool data. * @brief Constructor for the creator of local pool data.
* The constructor simply sets the fill_count to zero and sets
* the state to "uninitialized".
*/ */
LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner, LocalPoolDataSetBase(HasLocalDataPoolIF *hkOwner,
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. The passed pool
* owner should implement the HasHkPoolParametersIF. * owner should implement the HasHkPoolParametersIF.
* The constructor simply sets the fill_count to zero and sets
* the state to "uninitialized".
* @details * @details
* * @param sid Unique identifier of dataset consisting of object ID and
* set ID.
* @param registeredVariablesArray
* @param maxNumberOfVariables
*/ */
LocalPoolDataSetBase(object_id_t ownerId, LocalPoolDataSetBase(sid_t sid, PoolVariableIF** registeredVariablesArray,
PoolVariableIF** registeredVariablesArray,
const size_t maxNumberOfVariables); const size_t maxNumberOfVariables);
/** /**
@ -96,6 +93,7 @@ public:
bool isValid() const override; bool isValid() const override;
protected: protected:
sid_t sid;
/** /**
* 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.

View File

@ -1,8 +1,8 @@
#include "SharedLocalDataSet.h" #include "SharedLocalDataSet.h"
SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, object_id_t owner, SharedLocalDataSet::SharedLocalDataSet(object_id_t objectId, sid_t sid,
const size_t maxSize): SystemObject(objectId), const size_t maxSize): SystemObject(objectId),
LocalPoolDataSetBase(owner, nullptr, maxSize) { LocalPoolDataSetBase(sid, nullptr, maxSize) {
this->setContainer(poolVarVector.data()); this->setContainer(poolVarVector.data());
datasetLock = MutexFactory::instance()->createMutex(); datasetLock = MutexFactory::instance()->createMutex();
} }

View File

@ -16,7 +16,7 @@ class SharedLocalDataSet: public SystemObject,
public LocalPoolDataSetBase, public LocalPoolDataSetBase,
public SharedDataSetIF { public SharedDataSetIF {
public: public:
SharedLocalDataSet(object_id_t objectId, object_id_t owner, SharedLocalDataSet(object_id_t objectId, sid_t sid,
const size_t maxSize); const size_t maxSize);
ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override; ReturnValue_t lockDataset(dur_millis_t mutexTimeout) override;
ReturnValue_t unlockDataset() override; ReturnValue_t unlockDataset() override;

View File

@ -16,8 +16,8 @@
template <uint8_t NUM_VARIABLES> template <uint8_t NUM_VARIABLES>
class StaticLocalDataSet: public LocalPoolDataSetBase { class StaticLocalDataSet: public LocalPoolDataSetBase {
public: public:
StaticLocalDataSet(object_id_t owner): StaticLocalDataSet(sid_t sid):
LocalPoolDataSetBase(owner, poolVarList.data(), NUM_VARIABLES) { LocalPoolDataSetBase(sid, poolVarList.data(), NUM_VARIABLES) {
} }
private: private:

View File

@ -19,7 +19,6 @@
object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::powerSwitcherId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::rawDataReceiverId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT; object_id_t DeviceHandlerBase::defaultFdirParentId = objects::NO_OBJECT;
object_id_t DeviceHandlerBase::defaultHkDestination = objects::NO_OBJECT;
DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId, DeviceHandlerBase::DeviceHandlerBase(object_id_t setObjectId,
object_id_t deviceCommunication, CookieIF * comCookie, object_id_t deviceCommunication, CookieIF * comCookie,
@ -194,11 +193,7 @@ ReturnValue_t DeviceHandlerBase::initialize() {
return result; return result;
} }
if(hkDestination == objects::NO_OBJECT) { result = hkManager.initialize(commandQueue);
hkDestination = defaultHkDestination;
}
result = hkManager.initialize(commandQueue, hkDestination);
if (result != HasReturnvaluesIF::RETURN_OK) { if (result != HasReturnvaluesIF::RETURN_OK) {
return result; return result;
} }
@ -396,24 +391,28 @@ 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,
size_t replyLen, bool periodic, bool hasDifferentReplyId, PoolDataSetIF* replyDataSet, size_t replyLen, bool periodic,
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);
if (hasDifferentReplyId) { if (hasDifferentReplyId) {
return insertInReplyMap(replyId, maxDelayCycles, replyLen, periodic); return insertInReplyMap(replyId, maxDelayCycles,
replyDataSet, replyLen, periodic);
} else { } else {
return insertInReplyMap(deviceCommand, maxDelayCycles, replyLen, periodic); return insertInReplyMap(deviceCommand, maxDelayCycles,
replyDataSet, replyLen, periodic);
} }
} }
ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId, ReturnValue_t DeviceHandlerBase::insertInReplyMap(DeviceCommandId_t replyId,
uint16_t maxDelayCycles, size_t replyLen, bool periodic) { uint16_t maxDelayCycles, PoolDataSetIF* dataSet,
size_t replyLen, bool periodic) {
DeviceReplyInfo info; DeviceReplyInfo info;
info.maxDelayCycles = maxDelayCycles; info.maxDelayCycles = maxDelayCycles;
info.periodic = periodic; info.periodic = periodic;
info.delayCycles = 0; info.delayCycles = 0;
info.replyLen = replyLen; info.replyLen = replyLen;
info.dataSet = dataSet;
info.command = deviceCommandMap.end(); info.command = deviceCommandMap.end();
auto resultPair = deviceReplyMap.emplace(replyId, info); auto resultPair = deviceReplyMap.emplace(replyId, info);
if (resultPair.second) { if (resultPair.second) {
@ -439,13 +438,12 @@ ReturnValue_t DeviceHandlerBase::insertInCommandMap(
ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply, ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceReply,
uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) { uint16_t delayCycles, uint16_t maxDelayCycles, bool periodic) {
std::map<DeviceCommandId_t, DeviceReplyInfo>::iterator iter = auto replyIter = deviceReplyMap.find(deviceReply);
deviceReplyMap.find(deviceReply); if (replyIter == deviceReplyMap.end()) {
if (iter == deviceReplyMap.end()) {
triggerEvent(INVALID_DEVICE_COMMAND, deviceReply); triggerEvent(INVALID_DEVICE_COMMAND, deviceReply);
return RETURN_FAILED; return RETURN_FAILED;
} else { } else {
DeviceReplyInfo *info = &(iter->second); DeviceReplyInfo *info = &(replyIter->second);
if (maxDelayCycles != 0) { if (maxDelayCycles != 0) {
info->maxDelayCycles = maxDelayCycles; info->maxDelayCycles = maxDelayCycles;
} }
@ -455,6 +453,17 @@ ReturnValue_t DeviceHandlerBase::updateReplyMapEntry(DeviceCommandId_t deviceRep
} }
} }
ReturnValue_t DeviceHandlerBase::setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF *dataSet) {
auto replyIter = deviceReplyMap.find(replyId);
if(replyIter == deviceReplyMap.end()) {
return HasReturnvaluesIF::RETURN_FAILED;
}
replyIter->second.dataSet = dataSet;
return HasReturnvaluesIF::RETURN_OK;
}
void DeviceHandlerBase::callChildStatemachine() { void DeviceHandlerBase::callChildStatemachine() {
if (mode == _MODE_START_UP) { if (mode == _MODE_START_UP) {
doStartUp(); doStartUp();
@ -1368,8 +1377,9 @@ void DeviceHandlerBase::debugInterface(uint8_t positionTracker,
void DeviceHandlerBase::performOperationHook() { void DeviceHandlerBase::performOperationHook() {
} }
ReturnValue_t DeviceHandlerBase::initializePoolEntries( ReturnValue_t DeviceHandlerBase::initializeLocalDataPool(
LocalDataPool &localDataPoolMap) { LocalDataPool &localDataPoolMap,
LocalDataPoolManager& poolManager) {
return RETURN_OK; return RETURN_OK;
} }
@ -1384,6 +1394,7 @@ ReturnValue_t DeviceHandlerBase::initializeAfterTaskCreation() {
if(executingTask != nullptr) { if(executingTask != nullptr) {
pstIntervalMs = executingTask->getPeriodMs(); pstIntervalMs = executingTask->getPeriodMs();
} }
this->hkManager.initializeAfterTaskCreation();
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -1404,3 +1415,4 @@ object_id_t DeviceHandlerBase::getObjectId() const {
dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const { dur_millis_t DeviceHandlerBase::getPeriodicOperationFrequency() const {
return pstIntervalMs; return pstIntervalMs;
} }

View File

@ -387,7 +387,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, size_t replyLen = 0, bool periodic = false, uint16_t maxDelayCycles, PoolDataSetIF* replyDataSet = nullptr,
size_t replyLen = 0, bool periodic = false,
bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0); bool hasDifferentReplyId = false, DeviceCommandId_t replyId = 0);
/** /**
@ -401,7 +402,8 @@ protected:
* - @c RETURN_FAILED else. * - @c RETURN_FAILED else.
*/ */
ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand, ReturnValue_t insertInReplyMap(DeviceCommandId_t deviceCommand,
uint16_t maxDelayCycles, size_t replyLen = 0, bool periodic = false); uint16_t maxDelayCycles, PoolDataSetIF* dataSet = nullptr,
size_t replyLen = 0, bool periodic = false);
/** /**
* @brief A simple command to add a command to the commandList. * @brief A simple command to add a command to the commandList.
@ -429,6 +431,9 @@ protected:
uint16_t delayCycles, uint16_t maxDelayCycles, uint16_t delayCycles, uint16_t maxDelayCycles,
bool periodic = false); bool periodic = false);
ReturnValue_t setReplyDataset(DeviceCommandId_t replyId,
PoolDataSetIF* dataset);
/** /**
* @brief Can be implemented by child handler to * @brief Can be implemented by child handler to
* perform debugging * perform debugging
@ -482,8 +487,8 @@ protected:
* @param localDataPoolMap * @param localDataPoolMap
* @return * @return
*/ */
virtual ReturnValue_t initializePoolEntries( virtual ReturnValue_t initializeLocalDataPool(LocalDataPool& localDataPoolMap,
LocalDataPool& localDataPoolMap) override; LocalDataPoolManager& poolManager) override;
/** Get the HK manager object handle */ /** Get the HK manager object handle */
virtual LocalDataPoolManager* getHkManagerHandle() override; virtual LocalDataPoolManager* getHkManagerHandle() override;
@ -656,7 +661,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)
DataSetIF* dataSet = nullptr; PoolDataSetIF* dataSet = nullptr;
//! The command that expects this reply. //! The command that expects this reply.
DeviceCommandMap::iterator command; DeviceCommandMap::iterator command;
}; };
@ -1043,8 +1048,6 @@ private:
/** the object used to set power switches */ /** the object used to set power switches */
PowerSwitchIF *powerSwitcher = nullptr; PowerSwitchIF *powerSwitcher = nullptr;
/** Cached for initialize() */
static object_id_t defaultHkDestination;
/** HK destination can also be set individually */ /** HK destination can also be set individually */
object_id_t hkDestination = objects::NO_OBJECT; object_id_t hkDestination = objects::NO_OBJECT;
@ -1199,7 +1202,7 @@ private:
ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message); ReturnValue_t handleDeviceHandlerMessage(CommandMessage *message);
virtual ReturnValue_t initializeAfterTaskCreation() override; virtual ReturnValue_t initializeAfterTaskCreation() override;
DataSetIF* getDataSetHandle(sid_t sid) override; virtual DataSetIF* getDataSetHandle(sid_t sid) override;
void parseReply(const uint8_t* receivedData, void parseReply(const uint8_t* receivedData,
size_t receivedDataLen); size_t receivedDataLen);

View File

@ -12,6 +12,10 @@ union sid_t {
std::numeric_limits<uint64_t>::max(); std::numeric_limits<uint64_t>::max();
sid_t(): raw(INVALID_ADDRESS) {} sid_t(): raw(INVALID_ADDRESS) {}
sid_t(object_id_t objectId, uint32_t setId):
objectId(objectId),
ownerSetId(setId) {}
struct { struct {
object_id_t objectId ; object_id_t objectId ;
/** /**

View File

@ -25,7 +25,7 @@ public:
/** /**
* Helper functions which can be used to move HK data from the IPC store * Helper functions which can be used to move HK data from the IPC store
* to the telemetry store. * to the telemetry store. TODO: maybe not needed.
* @param formerStore * @param formerStore
* @param storeId * @param storeId
* @param newStore * @param newStore

View File

@ -8,7 +8,7 @@ const size_t PeriodicTaskIF::MINIMUM_STACK_SIZE = configMINIMAL_STACK_SIZE;
FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority, FixedTimeslotTask::FixedTimeslotTask(TaskName name, TaskPriority setPriority,
TaskStackSize setStack, TaskPeriod overallPeriod, TaskStackSize setStack, TaskPeriod overallPeriod,
void (*setDeadlineMissedFunc)()) : void (*setDeadlineMissedFunc)()) :
started(false), handle(NULL), pst(overallPeriod * 1000) { started(false), handle(nullptr), pst(overallPeriod * 1000) {
configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE); configSTACK_DEPTH_TYPE stackSize = setStack / sizeof(configSTACK_DEPTH_TYPE);
xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle); xTaskCreate(taskEntryPoint, name, stackSize, this, setPriority, &handle);
// All additional attributes are applied to the object. // All additional attributes are applied to the object.
@ -62,8 +62,10 @@ ReturnValue_t FixedTimeslotTask::startTask() {
ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId, ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) { uint32_t slotTimeMs, int8_t executionStep) {
if (objectManager->get<ExecutableObjectIF>(componentId) != nullptr) { ExecutableObjectIF* handler =
pst.addSlot(componentId, slotTimeMs, executionStep, this); objectManager->get<ExecutableObjectIF>(componentId);
if (handler != nullptr) {
pst.addSlot(componentId, slotTimeMs, executionStep, handler, this);
return HasReturnvaluesIF::RETURN_OK; return HasReturnvaluesIF::RETURN_OK;
} }
@ -76,8 +78,8 @@ uint32_t FixedTimeslotTask::getPeriodMs() const {
return pst.getLengthMs(); return pst.getLengthMs();
} }
ReturnValue_t FixedTimeslotTask::checkSequence() const { ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const {
return pst.checkSequence(); return pst.checkAndInitializeSequence();
} }
void FixedTimeslotTask::taskFunctionality() { void FixedTimeslotTask::taskFunctionality() {

View File

@ -54,7 +54,7 @@ public:
uint32_t getPeriodMs() const override; uint32_t getPeriodMs() const override;
ReturnValue_t checkSequence() const override; ReturnValue_t checkAndInitializeSequence() const override;
ReturnValue_t sleepFor(uint32_t ms) override; ReturnValue_t sleepFor(uint32_t ms) override;

View File

@ -132,7 +132,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t FixedTimeslotTask::checkSequence() const { ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const {
return pollingSeqTable.checkSequence(); return pollingSeqTable.checkSequence();
} }

View File

@ -61,7 +61,7 @@ public:
ReturnValue_t addSlot(object_id_t componentId, ReturnValue_t addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep); uint32_t slotTimeMs, int8_t executionStep);
ReturnValue_t checkSequence() const; ReturnValue_t checkAndInitializeSequence() const;
uint32_t getPeriodMs() const; uint32_t getPeriodMs() const;

View File

@ -49,7 +49,7 @@ ReturnValue_t FixedTimeslotTask::addSlot(object_id_t componentId,
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
ReturnValue_t FixedTimeslotTask::checkSequence() const { ReturnValue_t FixedTimeslotTask::checkAndInitializeSequence() const {
return pst.checkSequence(); return pst.checkSequence();
} }

View File

@ -33,7 +33,7 @@ public:
virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs, virtual ReturnValue_t addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep); int8_t executionStep);
virtual ReturnValue_t checkSequence() const; virtual ReturnValue_t checkAndInitializeSequence() const;
/** /**
* This static function can be used as #deadlineMissedFunc. * This static function can be used as #deadlineMissedFunc.

View File

@ -82,7 +82,7 @@ uint32_t PollingTask::getPeriodMs() const {
return pst.getLengthMs(); return pst.getLengthMs();
} }
ReturnValue_t PollingTask::checkSequence() const { ReturnValue_t PollingTask::checkAndInitializeSequence() const {
return pst.checkSequence(); return pst.checkSequence();
} }

View File

@ -42,7 +42,7 @@ class PollingTask: public TaskBase, public FixedTimeslotTaskIF {
uint32_t getPeriodMs() const; uint32_t getPeriodMs() const;
ReturnValue_t checkSequence() const; ReturnValue_t checkAndInitializeSequence() const;
ReturnValue_t sleepFor(uint32_t ms); ReturnValue_t sleepFor(uint32_t ms);
protected: protected:

View File

@ -3,13 +3,14 @@
#include <cstddef> #include <cstddef>
FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime, FixedSequenceSlot::FixedSequenceSlot(object_id_t handlerId, uint32_t setTime,
int8_t setSequenceId, PeriodicTaskIF* executingTask) : int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask) :
pollingTimeMs(setTime), opcode(setSequenceId) { pollingTimeMs(setTime), opcode(setSequenceId) {
handler = objectManager->get<ExecutableObjectIF>(handlerId); if(executableObject == nullptr) {
if(executingTask != nullptr) { return;
handler->setTaskIF(executingTask); }
} this->executableObject = executableObject;
handler->initializeAfterTaskCreation(); this->executableObject->setTaskIF(executingTask);
} }
FixedSequenceSlot::~FixedSequenceSlot() {} FixedSequenceSlot::~FixedSequenceSlot() {}

View File

@ -16,21 +16,23 @@ class PeriodicTaskIF;
class FixedSequenceSlot { class FixedSequenceSlot {
public: public:
FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs, FixedSequenceSlot( object_id_t handlerId, uint32_t setTimeMs,
int8_t setSequenceId, PeriodicTaskIF* executingTask ); int8_t setSequenceId, ExecutableObjectIF* executableObject,
PeriodicTaskIF* executingTask);
virtual ~FixedSequenceSlot(); virtual ~FixedSequenceSlot();
/** /**
* @brief Handler identifies which device handler object is executed in this slot. * @brief Handler identifies which object is executed in this slot.
*/ */
ExecutableObjectIF* handler = nullptr; ExecutableObjectIF* executableObject = nullptr;
/** /**
* @brief This attribute defines when a device handler object is executed. * @brief This attribute defines when a device handler object is executed.
* * @details
* @details The pollingTime attribute identifies the time the handler is executed in ms. * The pollingTime attribute identifies the time the handler is
* It must be smaller than the period length of the polling sequence. * executed in ms. It must be smaller than the period length of the
* polling sequence.
*/ */
uint32_t pollingTimeMs; uint32_t pollingTimeMs;
/** /**
* @brief This value defines the type of device communication. * @brief This value defines the type of device communication.

View File

@ -13,7 +13,7 @@ FixedSlotSequence::~FixedSlotSequence() {
} }
void FixedSlotSequence::executeAndAdvance() { void FixedSlotSequence::executeAndAdvance() {
current->handler->performOperation(current->opcode); current->executableObject->performOperation(current->opcode);
// if (returnValue != RETURN_OK) { // if (returnValue != RETURN_OK) {
// this->sendErrorMessage( returnValue ); // this->sendErrorMessage( returnValue );
// } // }
@ -81,34 +81,38 @@ uint32_t FixedSlotSequence::getLengthMs() const {
return this->lengthMs; return this->lengthMs;
} }
ReturnValue_t FixedSlotSequence::checkSequence() const { ReturnValue_t FixedSlotSequence::checkAndInitializeSequence() const {
if(slotList.empty()) { if(slotList.empty()) {
sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl; sif::error << "Fixed Slot Sequence: Slot list is empty!" << std::endl;
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
} }
auto slotIt = slotList.begin(); std::set<ExecutableObjectIF*> uniqueObjects;
uint32_t count = 0; uint32_t count = 0;
uint32_t time = 0; uint32_t time = 0;
while (slotIt != slotList.end()) { for(const auto& slot: slotList) {
if (slotIt->handler == nullptr) { if (slot.executableObject == nullptr) {
sif::error << "FixedSlotSequene::initialize: ObjectId does not exist!"
<< std::endl;
count++; count++;
} else if (slotIt->pollingTimeMs < time) {
sif::error << "FixedSlotSequence::initialize: Time: "
<< slotIt->pollingTimeMs
<< " is smaller than previous with " << time << std::endl;
count++;
} else {
// All ok, print slot.
//info << "Current slot polling time: " << std::endl;
//info << std::dec << slotIt->pollingTimeMs << std::endl;
} }
time = slotIt->pollingTimeMs; else if (slot.pollingTimeMs < time) {
slotIt++; sif::error << "FixedSlotSequence::initialize: Time: "
<< slot.pollingTimeMs << " is smaller than previous with "
<< time << std::endl;
count++;
}
else {
// All ok, print slot.
//sif::info << "Current slot polling time: " << std::endl;
//sif::info << std::dec << slotIt->pollingTimeMs << std::endl;
}
time = slot.pollingTimeMs;
// Ensure that each unique object is initialized once.
if(uniqueObjects.find(slot.executableObject) == uniqueObjects.end()) {
slot.executableObject->initializeAfterTaskCreation();
uniqueObjects.emplace(slot.executableObject);
}
} }
//info << "Number of elements in slot list: " //sif::info << "Number of elements in slot list: "
// << slotList.size() << std::endl; // << slotList.size() << std::endl;
if (count > 0) { if (count > 0) {
return HasReturnvaluesIF::RETURN_FAILED; return HasReturnvaluesIF::RETURN_FAILED;
@ -117,8 +121,9 @@ ReturnValue_t FixedSlotSequence::checkSequence() const {
} }
void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs, void FixedSlotSequence::addSlot(object_id_t componentId, uint32_t slotTimeMs,
int8_t executionStep, PeriodicTaskIF* executingTask) { int8_t executionStep, ExecutableObjectIF* executableObject,
this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs, executionStep, PeriodicTaskIF* executingTask) {
executingTask)); this->slotList.insert(FixedSequenceSlot(componentId, slotTimeMs,
this->current = slotList.begin(); executionStep, executableObject, executingTask));
this->current = slotList.begin();
} }

View File

@ -59,7 +59,7 @@ public:
* @param * @param
*/ */
void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId, void addSlot(object_id_t handlerId, uint32_t setTime, int8_t setSequenceId,
PeriodicTaskIF* executingTask); ExecutableObjectIF* executableObject, PeriodicTaskIF* executingTask);
/** /**
* Checks if the current slot shall be executed immediately after the one before. * Checks if the current slot shall be executed immediately after the one before.
@ -125,11 +125,14 @@ public:
SlotListIter current; SlotListIter current;
/** /**
* Iterate through slotList and check successful creation. * @brief Check and initialize slot list.
* @details
* Checks if timing is ok (must be ascending) and if all handlers were found. * Checks if timing is ok (must be ascending) and if all handlers were found.
* Also calls any initialization steps which are required after task
* creation.
* @return * @return
*/ */
ReturnValue_t checkSequence() const; ReturnValue_t checkAndInitializeSequence() const;
protected: protected:

View File

@ -22,8 +22,12 @@ public:
*/ */
virtual ReturnValue_t addSlot(object_id_t componentId, virtual ReturnValue_t addSlot(object_id_t componentId,
uint32_t slotTimeMs, int8_t executionStep) = 0; uint32_t slotTimeMs, int8_t executionStep) = 0;
/** Check whether the sequence is valid */
virtual ReturnValue_t checkSequence() const = 0; /**
* Check whether the sequence is valid and perform all other required
* initialization steps which are needed after task creation
*/
virtual ReturnValue_t checkAndInitializeSequence() const = 0;
}; };
#endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */ #endif /* FRAMEWORK_TASKS_FIXEDTIMESLOTTASKIF_H_ */