Refactor TM handling #450
@ -8,7 +8,6 @@
|
|||||||
#include <mission/tmtc/CcsdsIpCoreHandler.h>
|
#include <mission/tmtc/CcsdsIpCoreHandler.h>
|
||||||
#include <mission/tmtc/CfdpTmFunnel.h>
|
#include <mission/tmtc/CfdpTmFunnel.h>
|
||||||
#include <mission/tmtc/PusTmFunnel.h>
|
#include <mission/tmtc/PusTmFunnel.h>
|
||||||
#include <mission/tmtc/TmStoreRouter.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@
|
|||||||
#include <mission/tmtc/PersistentTmStore.h>
|
#include <mission/tmtc/PersistentTmStore.h>
|
||||||
#include <mission/tmtc/PusPacketFilter.h>
|
#include <mission/tmtc/PusPacketFilter.h>
|
||||||
#include <mission/tmtc/PusTmFunnel.h>
|
#include <mission/tmtc/PusTmFunnel.h>
|
||||||
|
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
|
||||||
#include <mission/tmtc/TmFunnelHandler.h>
|
#include <mission/tmtc/TmFunnelHandler.h>
|
||||||
#include <mission/tmtc/TmStoreRouter.h>
|
|
||||||
|
|
||||||
#include "OBSWConfig.h"
|
#include "OBSWConfig.h"
|
||||||
#include "devices/gpioIds.h"
|
#include "devices/gpioIds.h"
|
||||||
@ -160,12 +160,12 @@ void ObjectFactory::produceGenericObjects(HealthTableIF** healthTable_, PusTmFun
|
|||||||
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *timeStamper, sdcMan);
|
*pusFunnel = new PusTmFunnel(pusFunnelCfg, *timeStamper, sdcMan);
|
||||||
#if OBSW_ADD_TCPIP_SERVERS == 1
|
#if OBSW_ADD_TCPIP_SERVERS == 1
|
||||||
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
#if OBSW_ADD_TMTC_UDP_SERVER == 1
|
||||||
(*cfdpFunnel)->addDestination("UDP Server", *udpBridge, 0);
|
(*cfdpFunnel)->addLiveDestination("UDP Server", *udpBridge, 0);
|
||||||
(*pusFunnel)->addDestination("UDP Server", *udpBridge, 0);
|
(*pusFunnel)->addLiveDestination("UDP Server", *udpBridge, 0);
|
||||||
#endif
|
#endif
|
||||||
#if OBSW_ADD_TMTC_TCP_SERVER == 1
|
#if OBSW_ADD_TMTC_TCP_SERVER == 1
|
||||||
(*cfdpFunnel)->addDestination("TCP Server", *tcpBridge, 0);
|
(*cfdpFunnel)->addLiveDestination("TCP Server", *tcpBridge, 0);
|
||||||
(*pusFunnel)->addDestination("TCP Server", *tcpBridge, 0);
|
(*pusFunnel)->addLiveDestination("TCP Server", *tcpBridge, 0);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
// Every TM packet goes through this funnel
|
// Every TM packet goes through this funnel
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
|
|
||||||
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
#include <fsfw/devicehandlers/DeviceHandlerBase.h>
|
||||||
#include <mission/memory/SdCardMountedIF.h>
|
#include <mission/memory/SdCardMountedIF.h>
|
||||||
#include <mission/tmtc/TmStoreRouter.h>
|
|
||||||
|
|
||||||
#include "fsfw/objectmanager/SystemObjectIF.h"
|
#include "fsfw/objectmanager/SystemObjectIF.h"
|
||||||
#include "fsfw/power/PowerSwitchIF.h"
|
#include "fsfw/power/PowerSwitchIF.h"
|
||||||
|
@ -6,8 +6,9 @@ target_sources(
|
|||||||
TmFunnelBase.cpp
|
TmFunnelBase.cpp
|
||||||
CfdpTmFunnel.cpp
|
CfdpTmFunnel.cpp
|
||||||
tmFilters.cpp
|
tmFilters.cpp
|
||||||
|
PusLiveDemux.cpp
|
||||||
PusPacketFilter.cpp
|
PusPacketFilter.cpp
|
||||||
TmStoreRouter.cpp
|
PusTmRouteByFilterHelper.cpp
|
||||||
Service15TmStorage.cpp
|
Service15TmStorage.cpp
|
||||||
PersistentTmStore.cpp
|
PersistentTmStore.cpp
|
||||||
PusTmFunnel.cpp)
|
PusTmFunnel.cpp)
|
||||||
|
@ -75,36 +75,6 @@ ReturnValue_t CfdpTmFunnel::handlePacket(TmTcMessage& msg) {
|
|||||||
tmStore.deleteData(msg.getStorageId());
|
tmStore.deleteData(msg.getStorageId());
|
||||||
msg.setStorageId(newStoreId);
|
msg.setStorageId(newStoreId);
|
||||||
store_address_t origStoreId = newStoreId;
|
store_address_t origStoreId = newStoreId;
|
||||||
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
// TODO: Also route to persistent TM store
|
||||||
const auto& dest = destinations[idx];
|
return demultiplexLivePackets(origStoreId, newPacketData, packetLen);
|
||||||
if (destinations.size() > 1) {
|
|
||||||
if (idx < destinations.size() - 1) {
|
|
||||||
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
|
||||||
// to bother with send order and where the data is deleted.
|
|
||||||
store_address_t storeId;
|
|
||||||
result = tmStore.addData(&storeId, newPacketData, packetLen);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
msg.setStorageId(storeId);
|
|
||||||
} else {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PusTmFunnel::handlePacket: Store too full to create data copy or store "
|
|
||||||
"error"
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
msg.setStorageId(origStoreId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = tmQueue->sendMessage(dest.queueId, &msg);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << "PusTmFunnel::handlePacket: Error sending TM to downlink handler " << dest.name
|
|
||||||
<< " failed" << std::endl;
|
|
||||||
#endif
|
|
||||||
tmStore.deleteData(msg.getStorageId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
@ -69,14 +69,14 @@ ReturnValue_t PersistentTmStore::handleCommandQueue(StorageManagerIF& ipcStore,
|
|||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
SerializeAdapter::deSerialize(&dumpUntilUnixSeconds, accessor.second.data() + 4, &size,
|
||||||
SerializeIF::Endianness::NETWORK);
|
SerializeIF::Endianness::NETWORK);
|
||||||
dumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds, tmFunnel);
|
dumpFromUpTo(dumpFromUnixSeconds, dumpUntilUnixSeconds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersistentTmStore::dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel) {
|
void PersistentTmStore::dumpFrom(uint32_t fromUnixSeconds) {
|
||||||
return dumpFromUpTo(fromUnixSeconds, currentTv.tv_sec, tmFunnel);
|
return dumpFromUpTo(fromUnixSeconds, currentTv.tv_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnValue_t PersistentTmStore::storePacket(PusTmReader& reader) {
|
ReturnValue_t PersistentTmStore::storePacket(PusTmReader& reader) {
|
||||||
@ -166,8 +166,7 @@ void PersistentTmStore::deleteUpTo(uint32_t unixSeconds) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersistentTmStore::dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds,
|
void PersistentTmStore::dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds) {
|
||||||
TmFunnelBase& funnel) {
|
|
||||||
using namespace std::filesystem;
|
using namespace std::filesystem;
|
||||||
for (auto const& file : directory_iterator(basePath)) {
|
for (auto const& file : directory_iterator(basePath)) {
|
||||||
if (file.is_directory()) {
|
if (file.is_directory()) {
|
||||||
@ -180,7 +179,7 @@ void PersistentTmStore::dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnix
|
|||||||
}
|
}
|
||||||
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
|
auto fileEpoch = static_cast<uint32_t>(timegm(&fileTime));
|
||||||
if ((fileEpoch > fromUnixSeconds) and (fileEpoch + rolloverDiffSeconds <= upToUnixSeconds)) {
|
if ((fileEpoch > fromUnixSeconds) and (fileEpoch + rolloverDiffSeconds <= upToUnixSeconds)) {
|
||||||
fileToPackets(file, fileEpoch, funnel);
|
fileToPackets(file, fileEpoch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,8 +194,7 @@ ReturnValue_t PersistentTmStore::pathToTm(const std::filesystem::path& path, str
|
|||||||
return returnvalue::OK;
|
return returnvalue::OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PersistentTmStore::fileToPackets(const std::filesystem::path& path, uint32_t unixStamp,
|
void PersistentTmStore::fileToPackets(const std::filesystem::path& path, uint32_t unixStamp) {
|
||||||
TmFunnelBase& funnel) {
|
|
||||||
store_address_t storeId;
|
store_address_t storeId;
|
||||||
TmTcMessage message;
|
TmTcMessage message;
|
||||||
size_t size = std::filesystem::file_size(path);
|
size_t size = std::filesystem::file_size(path);
|
||||||
@ -212,12 +210,13 @@ void PersistentTmStore::fileToPackets(const std::filesystem::path& path, uint32_
|
|||||||
// CRC check to fully ensure this is a valid TM
|
// CRC check to fully ensure this is a valid TM
|
||||||
ReturnValue_t result = reader.parseDataWithCrcCheck();
|
ReturnValue_t result = reader.parseDataWithCrcCheck();
|
||||||
if (result == returnvalue::OK) {
|
if (result == returnvalue::OK) {
|
||||||
result = tmStore.addData(&storeId, fileBuf.data() + currentIdx, reader.getFullPacketLen());
|
// TODO: Blow the data out to the VC directly. Use IF function to do this.
|
||||||
if (result != returnvalue::OK) {
|
// result = tmStore.addData(&storeId, fileBuf.data() + currentIdx,
|
||||||
continue;
|
// reader.getFullPacketLen()); if (result != returnvalue::OK) {
|
||||||
}
|
// continue;
|
||||||
funnel.sendPacketToDestinations(storeId, message, fileBuf.data() + currentIdx,
|
// }
|
||||||
reader.getFullPacketLen());
|
// funnel.sendPacketToLiveDestinations(storeId, message, fileBuf.data() + currentIdx,
|
||||||
|
// reader.getFullPacketLen());
|
||||||
currentIdx += reader.getFullPacketLen();
|
currentIdx += reader.getFullPacketLen();
|
||||||
} else {
|
} else {
|
||||||
sif::error << "Parsing of PUS TM failed with code " << result << std::endl;
|
sif::error << "Parsing of PUS TM failed with code " << result << std::endl;
|
||||||
|
@ -32,8 +32,8 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|||||||
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, TmFunnelBase& tmFunnel);
|
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, TmFunnelBase& tmFunnel);
|
||||||
|
|
||||||
void deleteUpTo(uint32_t unixSeconds);
|
void deleteUpTo(uint32_t unixSeconds);
|
||||||
void dumpFrom(uint32_t fromUnixSeconds, TmFunnelBase& tmFunnel);
|
void dumpFrom(uint32_t fromUnixSeconds);
|
||||||
void dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds, TmFunnelBase& tmFunnel);
|
void dumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
|
||||||
|
|
||||||
// ReturnValue_t passPacket(PusTmReader& reader);
|
// ReturnValue_t passPacket(PusTmReader& reader);
|
||||||
ReturnValue_t storePacket(PusTmReader& reader);
|
ReturnValue_t storePacket(PusTmReader& reader);
|
||||||
@ -69,7 +69,7 @@ class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|||||||
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
||||||
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
||||||
static ReturnValue_t pathToTm(const std::filesystem::path& path, struct tm& time);
|
static ReturnValue_t pathToTm(const std::filesystem::path& path, struct tm& time);
|
||||||
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp, TmFunnelBase& funnel);
|
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp);
|
||||||
bool updateBaseDir();
|
bool updateBaseDir();
|
||||||
ReturnValue_t assignAndOrCreateMostRecentFile();
|
ReturnValue_t assignAndOrCreateMostRecentFile();
|
||||||
};
|
};
|
||||||
|
48
mission/tmtc/PusLiveDemux.cpp
Normal file
48
mission/tmtc/PusLiveDemux.cpp
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "PusLiveDemux.h"
|
||||||
|
|
||||||
|
#include <fsfw/storagemanager/storeAddress.h>
|
||||||
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
|
||||||
|
PusLiveDemux::PusLiveDemux(MessageQueueIF& ownerQueue) : ownerQueue(ownerQueue) {}
|
||||||
|
|
||||||
|
ReturnValue_t PusLiveDemux::demultiplexPackets(StorageManagerIF& tmStore,
|
||||||
|
store_address_t origStoreId, const uint8_t* tmData,
|
||||||
|
size_t tmSize) {
|
||||||
|
ReturnValue_t result = returnvalue::OK;
|
||||||
|
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
||||||
|
const auto& dest = destinations[idx];
|
||||||
|
if (destinations.size() > 1) {
|
||||||
|
if (idx < destinations.size() - 1) {
|
||||||
|
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
||||||
|
// to bother with send order and where the data is deleted.
|
||||||
|
store_address_t storeId;
|
||||||
|
result = tmStore.addData(&storeId, tmData, tmSize);
|
||||||
|
if (result == returnvalue::OK) {
|
||||||
|
message.setStorageId(storeId);
|
||||||
|
} else {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PusLiveDemux::handlePacket: Store too full to create data copy"
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
message.setStorageId(origStoreId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result = ownerQueue.sendMessage(dest.queueId, &message);
|
||||||
|
if (result != returnvalue::OK) {
|
||||||
|
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
||||||
|
sif::error << "PusLiveDemux::handlePacket: Error sending TM to downlink handler " << dest.name
|
||||||
|
<< std::endl;
|
||||||
|
#endif
|
||||||
|
tmStore.deleteData(message.getStorageId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PusLiveDemux::addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
||||||
|
uint8_t vcid) {
|
||||||
|
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
|
||||||
|
destinations.emplace_back(name, queueId, vcid);
|
||||||
|
}
|
34
mission/tmtc/PusLiveDemux.h
Normal file
34
mission/tmtc/PusLiveDemux.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#ifndef MISSION_TMTC_PUSLIVEDEMUX_H_
|
||||||
|
#define MISSION_TMTC_PUSLIVEDEMUX_H_
|
||||||
|
|
||||||
|
#include <fsfw/ipc/messageQueueDefinitions.h>
|
||||||
|
#include <fsfw/storagemanager/StorageManagerIF.h>
|
||||||
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class PusLiveDemux {
|
||||||
|
public:
|
||||||
|
PusLiveDemux(MessageQueueIF& ownerQueue);
|
||||||
|
ReturnValue_t demultiplexPackets(StorageManagerIF& tmStore, store_address_t origStoreId,
|
||||||
|
const uint8_t* tmData, size_t tmSize);
|
||||||
|
|
||||||
|
void addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
||||||
|
uint8_t vcid = 0);
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Destination {
|
||||||
|
Destination(const char* name, MessageQueueId_t queueId, uint8_t virtualChannel)
|
||||||
|
: name(name), queueId(queueId), virtualChannel(virtualChannel) {}
|
||||||
|
|
||||||
|
const char* name;
|
||||||
|
MessageQueueId_t queueId;
|
||||||
|
uint8_t virtualChannel = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
MessageQueueIF& ownerQueue;
|
||||||
|
TmTcMessage message;
|
||||||
|
std::vector<Destination> destinations;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* MISSION_TMTC_PUSLIVEDEMUX_H_ */
|
@ -86,18 +86,21 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
|
|||||||
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
sourceSequenceCount = sourceSequenceCount % ccsds::LIMIT_SEQUENCE_COUNT;
|
||||||
packet.updateErrorControl();
|
packet.updateErrorControl();
|
||||||
|
|
||||||
// TODO: 1. Send packet to persistent TM store when applicable.
|
// Send to persistent TM store if the packet matches some filter.
|
||||||
// 2. Send packet to live TM VC
|
MessageQueueId_t destination;
|
||||||
// 3. Send packet to TCP/IP destination
|
if (persistentTmMap.packetMatches(packet, destination)) {
|
||||||
return sendPacketToDestinations(origStoreId, message, packetData, size);
|
store_address_t storageId;
|
||||||
// timeval currentUptime{};
|
TmTcMessage msg(storageId);
|
||||||
// Clock::getUptime(¤tUptime);
|
result = tmStore.addData(&storageId, packetData, size);
|
||||||
// if (currentUptime.tv_sec - lastTvUpdate.tv_sec >
|
if (result != returnvalue::OK) {
|
||||||
// static_cast<signed int>(TV_UPDATE_INTERVAL_SECS)) {
|
sif::error << "PusLiveDemux::handlePacket: Store too full to create data copy" << std::endl;
|
||||||
// Clock::getClock_timeval(¤tTv);
|
} else {
|
||||||
// lastTvUpdate = currentUptime;
|
tmQueue->sendMessage(destination, &msg);
|
||||||
// }
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return demultiplexLivePackets(origStoreId, packetData, size);
|
||||||
|
// TODO: Will be moved to own thread.
|
||||||
// bool sdcUsable = sdcMan.isSdCardUsable(std::nullopt);
|
// bool sdcUsable = sdcMan.isSdCardUsable(std::nullopt);
|
||||||
// initStoresIfPossible(sdcUsable);
|
// initStoresIfPossible(sdcUsable);
|
||||||
// if (sdcUsable) {
|
// if (sdcUsable) {
|
||||||
@ -111,6 +114,7 @@ ReturnValue_t PusTmFunnel::handleTmPacket(TmTcMessage &message) {
|
|||||||
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }
|
const char *PusTmFunnel::getName() const { return "PUS TM Funnel"; }
|
||||||
|
|
||||||
void PusTmFunnel::initStoresIfPossible(bool sdCardUsable) {
|
void PusTmFunnel::initStoresIfPossible(bool sdCardUsable) {
|
||||||
|
// TODO: Those will be moved to own thread.
|
||||||
if (not storesInitialized and sdCardUsable and sdcMan.getCurrentMountPrefix() != nullptr) {
|
if (not storesInitialized and sdCardUsable and sdcMan.getCurrentMountPrefix() != nullptr) {
|
||||||
// miscStore.initializeTmStore();
|
// miscStore.initializeTmStore();
|
||||||
// okStore.initializeTmStore();
|
// okStore.initializeTmStore();
|
||||||
@ -126,5 +130,5 @@ ReturnValue_t PusTmFunnel::initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PusTmFunnel::addPersistentTmStoreRouting(PusPacketFilter filter, MessageQueueId_t dest) {
|
void PusTmFunnel::addPersistentTmStoreRouting(PusPacketFilter filter, MessageQueueId_t dest) {
|
||||||
router.addRouting(filter, dest);
|
persistentTmMap.addRouting(filter, dest);
|
||||||
}
|
}
|
||||||
|
@ -6,8 +6,8 @@
|
|||||||
#include <fsfw/tasks/ExecutableObjectIF.h>
|
#include <fsfw/tasks/ExecutableObjectIF.h>
|
||||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
#include <mission/tmtc/PusTmRouteByFilterHelper.h>
|
||||||
#include <mission/tmtc/TmFunnelBase.h>
|
#include <mission/tmtc/TmFunnelBase.h>
|
||||||
#include <mission/tmtc/TmStoreRouter.h>
|
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -39,7 +39,7 @@ class PusTmFunnel : public TmFunnelBase {
|
|||||||
TimeReaderIF &timeReader;
|
TimeReaderIF &timeReader;
|
||||||
bool storesInitialized = false;
|
bool storesInitialized = false;
|
||||||
SdCardMountedIF &sdcMan;
|
SdCardMountedIF &sdcMan;
|
||||||
PersistentTmStoreRouter router;
|
PusTmRouteByFilterHelper persistentTmMap;
|
||||||
|
|
||||||
ReturnValue_t handleTmPacket(TmTcMessage &message);
|
ReturnValue_t handleTmPacket(TmTcMessage &message);
|
||||||
void initStoresIfPossible(bool sdCardUsable);
|
void initStoresIfPossible(bool sdCardUsable);
|
||||||
|
19
mission/tmtc/PusTmRouteByFilterHelper.cpp
Normal file
19
mission/tmtc/PusTmRouteByFilterHelper.cpp
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
#include "PusTmRouteByFilterHelper.h"
|
||||||
|
|
||||||
|
#include <fsfw/ipc/MessageQueueIF.h>
|
||||||
|
|
||||||
|
PusTmRouteByFilterHelper::PusTmRouteByFilterHelper() = default;
|
||||||
|
|
||||||
|
bool PusTmRouteByFilterHelper::packetMatches(PusTmReader& reader, MessageQueueId_t& destination) {
|
||||||
|
for (const auto filterAndDest : routerMap) {
|
||||||
|
if (filterAndDest.first.packetMatches(reader)) {
|
||||||
|
destination = filterAndDest.second;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PusTmRouteByFilterHelper::addRouting(PusPacketFilter filter, MessageQueueId_t destination) {
|
||||||
|
routerMap.emplace_back(std::move(filter), destination);
|
||||||
|
}
|
@ -4,10 +4,21 @@
|
|||||||
#include <fsfw/ipc/messageQueueDefinitions.h>
|
#include <fsfw/ipc/messageQueueDefinitions.h>
|
||||||
#include <mission/tmtc/PusPacketFilter.h>
|
#include <mission/tmtc/PusPacketFilter.h>
|
||||||
|
|
||||||
class PersistentTmStoreRouter {
|
/**
|
||||||
|
* Simple composition of concrecte @PusPacketFilters which also maps them to
|
||||||
|
* a destination ID.
|
||||||
|
*/
|
||||||
|
class PusTmRouteByFilterHelper {
|
||||||
public:
|
public:
|
||||||
PersistentTmStoreRouter();
|
PusTmRouteByFilterHelper();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the packet matches any of the inserted filters and returns
|
||||||
|
* the destination if it does. Currently only supports one destination.
|
||||||
|
* @param reader
|
||||||
|
* @param destination
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
bool packetMatches(PusTmReader& reader, MessageQueueId_t& destination);
|
bool packetMatches(PusTmReader& reader, MessageQueueId_t& destination);
|
||||||
void addRouting(PusPacketFilter filter, MessageQueueId_t destination);
|
void addRouting(PusPacketFilter filter, MessageQueueId_t destination);
|
||||||
|
|
@ -5,8 +5,16 @@
|
|||||||
#include "fsfw/ipc/QueueFactory.h"
|
#include "fsfw/ipc/QueueFactory.h"
|
||||||
|
|
||||||
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
TmFunnelBase::TmFunnelBase(FunnelCfg cfg)
|
||||||
: SystemObject(cfg.objectId), name(cfg.name), tmStore(cfg.tmStore), ipcStore(cfg.ipcStore) {
|
: SystemObject(cfg.objectId),
|
||||||
tmQueue = QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth);
|
name(cfg.name),
|
||||||
|
tmStore(cfg.tmStore),
|
||||||
|
ipcStore(cfg.ipcStore),
|
||||||
|
tmQueue(QueueFactory::instance()->createMessageQueue(cfg.tmMsgDepth)),
|
||||||
|
liveDemux(*tmQueue) {}
|
||||||
|
|
||||||
|
ReturnValue_t TmFunnelBase::demultiplexLivePackets(store_address_t origStoreId,
|
||||||
|
const uint8_t *tmData, size_t tmSize) {
|
||||||
|
return liveDemux.demultiplexPackets(tmStore, origStoreId, tmData, tmSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
|
TmFunnelBase::~TmFunnelBase() { QueueFactory::instance()->deleteMessageQueue(tmQueue); }
|
||||||
@ -15,43 +23,7 @@ MessageQueueId_t TmFunnelBase::getReportReceptionQueue(uint8_t virtualChannel) c
|
|||||||
return tmQueue->getId();
|
return tmQueue->getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TmFunnelBase::addDestination(const char *name, const AcceptsTelemetryIF &downlinkDestination,
|
void TmFunnelBase::addLiveDestination(const char *name,
|
||||||
uint8_t vcid) {
|
const AcceptsTelemetryIF &downlinkDestination, uint8_t vcid) {
|
||||||
auto queueId = downlinkDestination.getReportReceptionQueue(vcid);
|
liveDemux.addDestination(name, downlinkDestination, vcid);
|
||||||
destinations.emplace_back(name, queueId, vcid);
|
|
||||||
}
|
|
||||||
|
|
||||||
ReturnValue_t TmFunnelBase::sendPacketToDestinations(store_address_t origStoreId,
|
|
||||||
TmTcMessage &message,
|
|
||||||
const uint8_t *packetData, size_t size) {
|
|
||||||
ReturnValue_t result = returnvalue::OK;
|
|
||||||
for (unsigned int idx = 0; idx < destinations.size(); idx++) {
|
|
||||||
const auto &dest = destinations[idx];
|
|
||||||
if (destinations.size() > 1) {
|
|
||||||
if (idx < destinations.size() - 1) {
|
|
||||||
// Create copy of data to ensure each TM recipient has its own copy. That way, we don't need
|
|
||||||
// to bother with send order and where the data is deleted.
|
|
||||||
store_address_t storeId;
|
|
||||||
result = tmStore.addData(&storeId, packetData, size);
|
|
||||||
if (result == returnvalue::OK) {
|
|
||||||
message.setStorageId(storeId);
|
|
||||||
} else {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << name << "::handlePacket: Store too full to create data copy" << std::endl;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
message.setStorageId(origStoreId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
result = tmQueue->sendMessage(dest.queueId, &message);
|
|
||||||
if (result != returnvalue::OK) {
|
|
||||||
#if FSFW_CPP_OSTREAM_ENABLED == 1
|
|
||||||
sif::error << name << "::handlePacket: Error sending TM to downlink handler " << dest.name
|
|
||||||
<< std::endl;
|
|
||||||
#endif
|
|
||||||
tmStore.deleteData(message.getStorageId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
||||||
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
||||||
#include <fsfw/tmtcservices/TmTcMessage.h>
|
#include <fsfw/tmtcservices/TmTcMessage.h>
|
||||||
|
#include <mission/tmtc/PusLiveDemux.h>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -26,11 +27,11 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
|||||||
uint32_t tmMsgDepth;
|
uint32_t tmMsgDepth;
|
||||||
};
|
};
|
||||||
explicit TmFunnelBase(FunnelCfg cfg);
|
explicit TmFunnelBase(FunnelCfg cfg);
|
||||||
void addDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
|
||||||
uint8_t vcid = 0);
|
|
||||||
ReturnValue_t sendPacketToDestinations(store_address_t origStoreId, TmTcMessage& message,
|
|
||||||
const uint8_t* packetData, size_t size);
|
|
||||||
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
[[nodiscard]] MessageQueueId_t getReportReceptionQueue(uint8_t virtualChannel) const override;
|
||||||
|
void addLiveDestination(const char* name, const AcceptsTelemetryIF& downlinkDestination,
|
||||||
|
uint8_t vcid = 0);
|
||||||
|
ReturnValue_t demultiplexLivePackets(store_address_t origStoreId, const uint8_t* tmData,
|
||||||
|
size_t tmSize);
|
||||||
|
|
||||||
~TmFunnelBase() override;
|
~TmFunnelBase() override;
|
||||||
|
|
||||||
@ -38,18 +39,8 @@ class TmFunnelBase : public AcceptsTelemetryIF, public SystemObject {
|
|||||||
const char* name;
|
const char* name;
|
||||||
StorageManagerIF& tmStore;
|
StorageManagerIF& tmStore;
|
||||||
StorageManagerIF& ipcStore;
|
StorageManagerIF& ipcStore;
|
||||||
|
|
||||||
struct Destination {
|
|
||||||
Destination(const char* name, MessageQueueId_t queueId, uint8_t virtualChannel)
|
|
||||||
: name(name), queueId(queueId), virtualChannel(virtualChannel) {}
|
|
||||||
|
|
||||||
const char* name;
|
|
||||||
MessageQueueId_t queueId;
|
|
||||||
uint8_t virtualChannel = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Destination> destinations;
|
|
||||||
MessageQueueIF* tmQueue = nullptr;
|
MessageQueueIF* tmQueue = nullptr;
|
||||||
|
PusLiveDemux liveDemux;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */
|
#endif /* MISSION_TMTC_TMFUNNELBASE_H_ */
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
#include "TmStoreRouter.h"
|
|
||||||
|
|
||||||
#include <fsfw/ipc/MessageQueueIF.h>
|
|
||||||
|
|
||||||
PersistentTmStoreRouter::PersistentTmStoreRouter() = default;
|
|
||||||
|
|
||||||
bool PersistentTmStoreRouter::packetMatches(PusTmReader& reader, MessageQueueId_t& destination) {
|
|
||||||
for (const auto filterAndDest : routerMap) {
|
|
||||||
if (filterAndDest.first.packetMatches(reader)) {
|
|
||||||
destination = filterAndDest.second;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PersistentTmStoreRouter::addRouting(PusPacketFilter filter, MessageQueueId_t destination) {
|
|
||||||
routerMap.emplace_back(std::move(filter), destination);
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user