#include "PusTmFunnel.h" #include "eive/definitions.h" #include "fsfw/pus/Service5EventReporting.h" #include "eive/objects.h" #include "fsfw/ipc/CommandMessage.h" #include "fsfw/ipc/QueueFactory.h" #include "fsfw/objectmanager.h" #include "fsfw/tmstorage/TmStoreMessage.h" #include "tmtc/pusIds.h" #include "fsfw/tmtcpacket/pus/tm/PusTmZcWriter.h" PusTmFunnel::PusTmFunnel(TmFunnelBase::FunnelCfg cfg, TimeReaderIF &timeReader, SdCardMountedIF &sdcMan) : TmFunnelBase(cfg), timeReader(timeReader), miscStore(objects::MISC_TM_STORE, "tm", "misc", RolloverInterval::HOURLY, 2, currentTv, tmStore, sdcMan), okStore(objects::OK_TM_STORE, "tm", "ok", RolloverInterval::MINUTELY, 30, currentTv, tmStore, sdcMan), notOkStore(objects::NOT_OK_TM_STORE, "tm", "nok", RolloverInterval::MINUTELY, 30, currentTv, tmStore, sdcMan), hkStore(objects::HK_TM_STORE, "tm", "hk", RolloverInterval::MINUTELY, 15, currentTv, tmStore, sdcMan), sdcMan(sdcMan) { Clock::getClock_timeval(¤tTv); Clock::getUptime(&lastTvUpdate); hkStore.addApid(config::EIVE_PUS_APID); hkStore.addService(pus::PUS_SERVICE_3); miscStore.addApid(config::EIVE_PUS_APID); miscStore.addService(pus::PUS_SERVICE_17); miscStore.addService(pus::PUS_SERVICE_2); miscStore.addService(pus::PUS_SERVICE_200); miscStore.addService(pus::PUS_SERVICE_201); miscStore.addService(pus::PUS_SERVICE_9); miscStore.addService(pus::PUS_SERVICE_20); okStore.addApid(config::EIVE_PUS_APID); okStore.addServiceSubservice(pus::PUS_SERVICE_5, Service5EventReporting::Subservice::NORMAL_REPORT); okStore.addService(pus::PUS_SERVICE_8); okStore.addServiceSubservice(pus::PUS_SERVICE_1, 1); okStore.addServiceSubservice(pus::PUS_SERVICE_1, 3); okStore.addServiceSubservice(pus::PUS_SERVICE_1, 5); okStore.addServiceSubservice(pus::PUS_SERVICE_1, 7); notOkStore.addApid(config::EIVE_PUS_APID); notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 2); notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 3); notOkStore.addServiceSubservice(pus::PUS_SERVICE_5, 4); notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 2); notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 4); notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 6); notOkStore.addServiceSubservice(pus::PUS_SERVICE_1, 8); } PusTmFunnel::~PusTmFunnel() = default; ReturnValue_t PusTmFunnel::performOperation(uint8_t) { CommandMessage cmdMessage; ReturnValue_t result; try { result = okStore.handleCommandQueue(ipcStore, *this); if (result != returnvalue::OK) { sif::error << "PusTmFunnel::performOperation: Issue handling OK store command" << std::endl; } result = notOkStore.handleCommandQueue(ipcStore, *this); if (result != returnvalue::OK) { sif::error << "PusTmFunnel::performOperation: Issue handling NOT OK store command" << std::endl; } result = hkStore.handleCommandQueue(ipcStore, *this); if (result != returnvalue::OK) { sif::error << "PusTmFunnel::performOperation: Issue handling HK store command" << std::endl; } result = miscStore.handleCommandQueue(ipcStore, *this); if (result != returnvalue::OK) { sif::error << "PusTmFunnel::performOperation: Issue handling MISC store command" << std::endl; } } catch (const std::bad_optional_access &e) { sif::error << e.what() << "when handling TM store command" << std::endl; } TmTcMessage currentMessage; unsigned int count = 0; result = tmQueue->receiveMessage(¤tMessage); while (result == returnvalue::OK) { result = handleTmPacket(currentMessage); if (result != returnvalue::OK) { sif::warning << "TmFunnel packet handling failed" << std::endl; break; } count++; if (count == 500) { sif::error << "PusTmFunnel: Possible message storm detected" << std::endl; break; } result = tmQueue->receiveMessage(¤tMessage); } if (result == MessageQueueIF::EMPTY) { return returnvalue::OK; } return result; } ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) { uint8_t *packetData = nullptr; size_t size = 0; store_address_t origStoreId = message.getStorageId(); ReturnValue_t result = tmStore.modifyData(origStoreId, &packetData, &size); if (result != returnvalue::OK) { return result; } PusTmZeroCopyWriter packet(timeReader, packetData, size); result = packet.parseDataWithoutCrcCheck(); if (result != returnvalue::OK) { #if FSFW_CPP_OSTREAM_ENABLED == 1 sif::warning << "PusTmFunnel::handlePacket: Error parsing received PUS packet" << std::endl; #endif return result; } packet.setSequenceCount(sourceSequenceCount++); sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT; packet.updateErrorControl(); timeval currentUptime{}; Clock::getUptime(¤tUptime); if (currentUptime.tv_sec - lastTvUpdate.tv_sec > static_cast(TV_UPDATE_INTERVAL_SECS)) { Clock::getClock_timeval(¤tTv); lastTvUpdate = currentUptime; } bool sdcUsable = sdcMan.isSdCardUsable(std::nullopt); initStoresIfPossible(sdcUsable); if (sdcUsable) { miscStore.passPacket(packet); okStore.passPacket(packet); notOkStore.passPacket(packet); hkStore.passPacket(packet); } return sendPacketToDestinations(origStoreId, message, packetData, size); } const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; } void PusTmFunnel::initStoresIfPossible(bool sdCardUsable) { if (not storesInitialized and sdCardUsable) { miscStore.initializeTmStore(); okStore.initializeTmStore(); hkStore.initializeTmStore(); notOkStore.initializeTmStore(); storesInitialized = true; } } ReturnValue_t PusTmFunnel::initialize() { initStoresIfPossible(sdcMan.isSdCardUsable(std::nullopt)); return returnvalue::OK; }