diff --git a/datapool/DataSetBase.h b/datapool/DataSetBase.h index 8bf9a99a3..a914ec6b4 100644 --- a/datapool/DataSetBase.h +++ b/datapool/DataSetBase.h @@ -102,7 +102,7 @@ public: virtual ReturnValue_t unlockDataPool() override; /* SerializeIF implementations */ - ReturnValue_t serialize(uint8_t** buffer, size_t* size, + virtual ReturnValue_t serialize(uint8_t** buffer, size_t* size, const size_t maxSize, bool bigEndian) const override; virtual size_t getSerializedSize() const override; virtual ReturnValue_t deSerialize(const uint8_t** buffer, size_t* size, diff --git a/datapoollocal/LocalDataPoolManager.cpp b/datapoollocal/LocalDataPoolManager.cpp index 58694508f..a9d131eb7 100644 --- a/datapoollocal/LocalDataPoolManager.cpp +++ b/datapoollocal/LocalDataPoolManager.cpp @@ -1,16 +1,17 @@ #include #include -#include -#include #include #include +#include #include -LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner) { +LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner, + uint32_t replyQueueDepth, bool appendValidityBuffer): + appendValidityBuffer(appendValidityBuffer) { if(owner == nullptr) { sif::error << "HkManager: Invalid supplied owner!" << std::endl; - std::exit(0); + return; } this->owner = owner; mutex = MutexFactory::instance()->createMutex(); @@ -23,6 +24,8 @@ LocalDataPoolManager::LocalDataPoolManager(OwnsLocalDataPoolIF* owner) { sif::error << "LocalDataPoolManager::LocalDataPoolManager: " "Could not set IPC store." << std::endl; } + hkQueue = QueueFactory::instance()->createMessageQueue(replyQueueDepth, + HousekeepingMessage::HK_MESSAGE_SIZE); } LocalDataPoolManager::~LocalDataPoolManager() {} @@ -36,13 +39,21 @@ ReturnValue_t LocalDataPoolManager::initializeHousekeepingPoolEntriesOnce() { } return result; } - sif::warning << "HousekeepingManager: The map" << std::endl; + sif::warning << "HousekeepingManager: The map should only be initialized " + "once!" << std::endl; return HasReturnvaluesIF::RETURN_OK; } ReturnValue_t LocalDataPoolManager::handleHousekeepingMessage( HousekeepingMessage& message) { - return HasReturnvaluesIF::RETURN_FAILED; + Command_t command = message.getCommand(); + switch(command) { + case(HousekeepingMessage::GENERATE_ONE_PARAMETER_REPORT): + case(HousekeepingMessage::GENERATE_ONE_DIAGNOSTICS_REPORT): + return generateHousekeepingPacket(message.getSid()); + default: + return CommandMessageIF::UNKNOWN_COMMAND; + } } ReturnValue_t LocalDataPoolManager::printPoolEntry( @@ -51,7 +62,7 @@ ReturnValue_t LocalDataPoolManager::printPoolEntry( if (poolIter == localDpMap.end()) { sif::debug << "HousekeepingManager::fechPoolEntry:" " Pool entry not found." << std::endl; - return OwnsLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; + return POOL_ENTRY_NOT_FOUND; } poolIter->second->print(); return HasReturnvaluesIF::RETURN_OK; @@ -61,6 +72,15 @@ MutexIF* LocalDataPoolManager::getMutexHandle() { return mutex; } +void LocalDataPoolManager::setHkPacketDestination( + MessageQueueId_t destinationQueueId) { + this->currentHkPacketDestination = destinationQueueId; +} + +const OwnsLocalDataPoolIF* LocalDataPoolManager::getOwner() const { + return owner; +} + ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid) { LocalDataSet* dataSetToSerialize = dynamic_cast( owner->getDataSetHandle(sid)); @@ -70,28 +90,56 @@ ReturnValue_t LocalDataPoolManager::generateHousekeepingPacket(sid_t sid) { return HasReturnvaluesIF::RETURN_FAILED; } store_address_t storeId; - size_t hkSize = dataSetToSerialize->getSerializedSize(); - uint8_t* storePtr = nullptr; - ReturnValue_t result = ipcStore->getFreeElement(&storeId, hkSize,&storePtr); + ReturnValue_t result = serializeHkPacketIntoStore(&storeId, + dataSetToSerialize); if(result != HasReturnvaluesIF::RETURN_OK) { - sif::warning << "HousekeepingManager::generateHousekeepingPacket: " - "Could not get free element from IPC store." << std::endl; return result; } - size_t size = 0; - dataSetToSerialize->serialize(&storePtr, &size, hkSize, false); - // and now we have to set a HK message and send it the queue. - return HasReturnvaluesIF::RETURN_OK; + + // and now we set a HK message and send it the HK packet destination. + MessageQueueMessage message; + HousekeepingMessage hkMessage(&message); + hkMessage.setHkReportMessage(sid, storeId); + if(hkQueue == nullptr) { + return QUEUE_NOT_SET; + } + + if(currentHkPacketDestination != MessageQueueIF::NO_QUEUE) { + result = hkQueue->sendMessage(currentHkPacketDestination, &hkMessage); + } + else { + result = hkQueue->sendToDefault(&hkMessage); + } + + return result; } -void LocalDataPoolManager::setHkPacketQueue(MessageQueueIF *msgQueue) { - this->hkPacketQueue = msgQueue; +ReturnValue_t LocalDataPoolManager::serializeHkPacketIntoStore( + store_address_t *storeId, LocalDataSet* dataSet) { + size_t hkSize = dataSet->getSerializedSize(); + uint8_t* storePtr = nullptr; + ReturnValue_t result = ipcStore->getFreeElement(storeId, hkSize,&storePtr); + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::warning << "HousekeepingManager::generateHousekeepingPacket: " + "Could not get free element from IPC store." << std::endl; + return result; + } + size_t size = 0; + + if(appendValidityBuffer) { + result = dataSet->serializeWithValidityBuffer(&storePtr, + &size, hkSize, false); + } + else { + result = dataSet->serialize(&storePtr, &size, hkSize, false); + } + + if(result != HasReturnvaluesIF::RETURN_OK) { + sif::error << "HousekeepingManager::serializeHkPacketIntoStore: " + "Serialization proccess failed!" << std::endl; + } + return result; } -void LocalDataPoolManager::setHkReplyQueue(MessageQueueIF *replyQueue) { - this->hkReplyQueue = replyQueue; -} -const OwnsLocalDataPoolIF* LocalDataPoolManager::getOwner() const { - return owner; -} + diff --git a/datapoollocal/LocalDataPoolManager.h b/datapoollocal/LocalDataPoolManager.h index d1a2d410c..c649cd684 100644 --- a/datapoollocal/LocalDataPoolManager.h +++ b/datapoollocal/LocalDataPoolManager.h @@ -13,6 +13,8 @@ #include +class LocalDataSet; + /** * @brief This class is the managing instance for local data pool. * @details @@ -37,8 +39,16 @@ class LocalDataPoolManager { friend class LocalPoolVector; friend class LocalDataSet; public: + static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING_MANAGER; - LocalDataPoolManager(OwnsLocalDataPoolIF* owner); + static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0x0); + static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0x1); + + static constexpr ReturnValue_t QUEUE_NOT_SET = MAKE_RETURN_CODE(0x2); + //static constexpr ReturnValue_t SET_NOT_FOUND = MAKE_RETURN_CODE(0x3); + + LocalDataPoolManager(OwnsLocalDataPoolIF* owner, + uint32_t replyQueueDepth = 20, bool appendValidityBuffer = true); virtual~ LocalDataPoolManager(); /* Copying forbidden */ @@ -57,10 +67,7 @@ public: ReturnValue_t initializeHousekeepingPoolEntriesOnce(); //! Set the queue for HK packets, which are sent unrequested. - void setHkPacketQueue(MessageQueueIF* msgQueue); - //! Set the queue for replies. This can be set manually or by the owner - //! class if the manager if message are relayed by it. - void setHkReplyQueue(MessageQueueIF* replyQueue); + void setHkPacketDestination(MessageQueueId_t destinationQueueId); const OwnsLocalDataPoolIF* getOwner() const; @@ -70,6 +77,10 @@ private: //! This is the map holding the actual data. Should only be initialized //! once ! bool mapInitialized = false; + //! This specifies whether a validity buffer is appended at the end + //! of generated housekeeping packets. + bool appendValidityBuffer = true; + LocalDataPool localDpMap; //! Every housekeeping data manager has a mutex to protect access @@ -79,13 +90,14 @@ private: //! The class which actually owns the manager (and its datapool). OwnsLocalDataPoolIF* owner = nullptr; - //! Used for replies. - //! (maybe we dont need this, the sender can be retrieved from command - //! message..) - MessageQueueIF* hkReplyQueue = nullptr; - //! Used for HK packets, which are generated without requests. - //! Maybe this will just be the TM funnel. - MessageQueueIF* hkPacketQueue = nullptr; + //! Queue used for communication, for example commands. + //! Is also used to send messages. + 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 currentHkPacketDestination = MessageQueueIF::NO_QUEUE; //! Global IPC store is used to store all packets. StorageManagerIF* ipcStore = nullptr; @@ -113,6 +125,8 @@ private: PoolEntry **poolEntry); void setMinimalSamplingFrequency(float frequencySeconds); + ReturnValue_t serializeHkPacketIntoStore(store_address_t* storeId, + LocalDataSet* dataSet); }; @@ -123,14 +137,14 @@ ReturnValue_t LocalDataPoolManager::fetchPoolEntry(lp_id_t localPoolId, if (poolIter == localDpMap.end()) { sif::debug << "HousekeepingManager::fechPoolEntry:" " Pool entry not found." << std::endl; - return OwnsLocalDataPoolIF::POOL_ENTRY_NOT_FOUND; + return POOL_ENTRY_NOT_FOUND; } *poolEntry = dynamic_cast< PoolEntry* >(poolIter->second); if(*poolEntry == nullptr) { sif::debug << "HousekeepingManager::fetchPoolEntry:" " Pool entry not found." << std::endl; - return OwnsLocalDataPoolIF::POOL_ENTRY_TYPE_CONFLICT; + return POOL_ENTRY_TYPE_CONFLICT; } return HasReturnvaluesIF::RETURN_OK; } diff --git a/datapoollocal/LocalDataSet.cpp b/datapoollocal/LocalDataSet.cpp index 243c9cc1d..bb4aafef2 100644 --- a/datapoollocal/LocalDataSet.cpp +++ b/datapoollocal/LocalDataSet.cpp @@ -1,22 +1,25 @@ #include #include +#include +#include + LocalDataSet::LocalDataSet(OwnsLocalDataPoolIF *hkOwner): DataSetBase() { - if(hkOwner != nullptr) { - hkManager = hkOwner->getHkManagerHandle(); - } - else { - // config error, error output here. - } + if(hkOwner == nullptr) { + sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" + << std::endl; + } + hkManager = hkOwner->getHkManagerHandle(); } LocalDataSet::LocalDataSet(object_id_t ownerId): DataSetBase() { - OwnsLocalDataPoolIF* hkOwner = objectManager->get( - ownerId); - if(hkOwner == nullptr) { - // config error, error output here. - } - hkManager = hkOwner->getHkManagerHandle(); + OwnsLocalDataPoolIF* hkOwner = objectManager->get( + ownerId); + if(hkOwner == nullptr) { + sif::error << "LocalDataSet::LocalDataSet: Owner can't be nullptr!" + << std::endl; + } + hkManager = hkOwner->getHkManagerHandle(); } LocalDataSet::~LocalDataSet() { @@ -27,9 +30,50 @@ ReturnValue_t LocalDataSet::lockDataPool(uint32_t timeoutMs) { return mutex->lockMutex(timeoutMs); } +ReturnValue_t LocalDataSet::serializeWithValidityBuffer(uint8_t **buffer, + size_t *size, const size_t maxSize, bool bigEndian) const { + ReturnValue_t result = HasReturnvaluesIF::RETURN_FAILED; + uint8_t validityMaskSize = std::ceil(static_cast(fillCount)/8.0); + uint8_t validityMask[validityMaskSize]; + uint8_t validBufferIndex = 0; + uint8_t validBufferIndexBit = 0; + for (uint16_t count = 0; count < fillCount; count++) { + if(registeredVariables[count]->isValid()) { + // set validity buffer here. + this->bitSetter(validityMask + validBufferIndex, + validBufferIndexBit, true); + if(validBufferIndexBit == 7) { + validBufferIndex ++; + validBufferIndexBit = 0; + } + else { + validBufferIndexBit ++; + } + } + result = registeredVariables[count]->serialize(buffer, size, maxSize, + bigEndian); + if (result != HasReturnvaluesIF::RETURN_OK) { + return result; + } + } + // copy validity buffer to end + std::memcpy(*buffer, validityMask, validityMaskSize); + *size += validityMaskSize; + return result; +} + ReturnValue_t LocalDataSet::unlockDataPool() { MutexIF* mutex = hkManager->getMutexHandle(); return mutex->unlockMutex(); } +void LocalDataSet::bitSetter(uint8_t* byte, uint8_t position, + bool value) const { + if(position > 7) { + sif::debug << "Pool Raw Access: Bit setting invalid position" << std::endl; + return; + } + uint8_t shiftNumber = position + (7 - 2 * position); + *byte |= 1UL << shiftNumber; +} diff --git a/datapoollocal/LocalDataSet.h b/datapoollocal/LocalDataSet.h index 54da5562c..0c3b3bd8d 100644 --- a/datapoollocal/LocalDataSet.h +++ b/datapoollocal/LocalDataSet.h @@ -55,6 +55,20 @@ public: */ ~LocalDataSet(); + /** + * Special version of the serilization function which appends a + * validity buffer at the end. Each bit of this validity buffer + * denotes whether the container data set entries are valid from left + * to right, MSB first. + * @param buffer + * @param size + * @param maxSize + * @param bigEndian + * @param withValidityBuffer + * @return + */ + ReturnValue_t serializeWithValidityBuffer(uint8_t** buffer, + size_t* size, const size_t maxSize, bool bigEndian) const ; protected: private: /** @@ -79,6 +93,16 @@ private: ReturnValue_t unlockDataPool() override; LocalDataPoolManager* hkManager; + + /** + * Sets the bit at the bit-position of a byte provided by its address + * to the specified value (zero or one). + * @param byte Pointer to byte to bitset. + * @param position MSB first, 0 to 7 possible. + * @param value Value to set. + * @return + */ + void bitSetter(uint8_t* byte, uint8_t position, bool value) const; }; #endif /* FRAMEWORK_DATAPOOLLOCAL_LOCALDATASET_H_ */ diff --git a/datapoollocal/OwnsLocalDataPoolIF.h b/datapoollocal/OwnsLocalDataPoolIF.h index cf94f946a..8d657879e 100644 --- a/datapoollocal/OwnsLocalDataPoolIF.h +++ b/datapoollocal/OwnsLocalDataPoolIF.h @@ -40,9 +40,7 @@ class OwnsLocalDataPoolIF { public: virtual~ OwnsLocalDataPoolIF() {}; - static constexpr uint8_t INTERFACE_ID = CLASS_ID::HOUSEKEEPING; - static constexpr ReturnValue_t POOL_ENTRY_NOT_FOUND = MAKE_RETURN_CODE(0XA0); - static constexpr ReturnValue_t POOL_ENTRY_TYPE_CONFLICT = MAKE_RETURN_CODE(0xA1); + static constexpr uint8_t INTERFACE_ID = CLASS_ID::LOCAL_POOL_OWNER_IF; virtual MessageQueueId_t getCommandQueue() const = 0; virtual ReturnValue_t initializeHousekeepingPoolEntries( diff --git a/housekeeping/HousekeepingMessage.h b/housekeeping/HousekeepingMessage.h index 75afc8eae..c6a33c835 100644 --- a/housekeeping/HousekeepingMessage.h +++ b/housekeeping/HousekeepingMessage.h @@ -96,6 +96,7 @@ public: void setParameter(uint32_t parameter); uint32_t getParameter() const; + sid_t getSid() const; void setHkReportMessage(sid_t sid, store_address_t storeId); void setHkDiagnosticsMessage(sid_t sid, store_address_t storeId); @@ -106,7 +107,7 @@ public: virtual size_t getMinimumMessageSize() const override; virtual void clear() override; private: - sid_t getSid() const; + void setSid(sid_t sid); virtual uint8_t* getData() override; diff --git a/returnvalues/FwClassIds.h b/returnvalues/FwClassIds.h index 870efb461..ddee539e3 100644 --- a/returnvalues/FwClassIds.h +++ b/returnvalues/FwClassIds.h @@ -61,8 +61,9 @@ enum { MUTEX_IF, //MUX 55 MESSAGE_QUEUE_IF,//MQI 56 SEMAPHORE_IF, //SPH 57 - HOUSEKEEPING, //HK 58 + LOCAL_POOL_OWNER_IF, //LPIF 58 POOL_VARIABLE_IF, //PVA 59 + HOUSEKEEPING_MANAGER, //HKM 60 FW_CLASS_ID_COUNT //is actually count + 1 ! };