151 lines
5.6 KiB
C++
151 lines
5.6 KiB
C++
#ifndef MISSION_TMTC_TMSTOREBACKEND_H_
|
|
#define MISSION_TMTC_TMSTOREBACKEND_H_
|
|
|
|
#include <fsfw/ipc/CommandMessageIF.h>
|
|
#include <fsfw/objectmanager/SystemObject.h>
|
|
#include <fsfw/storagemanager/StorageManagerIF.h>
|
|
#include <fsfw/tmstorage/TmStoreFrontendSimpleIF.h>
|
|
#include <fsfw/tmtcpacket/pus/tm/PusTmReader.h>
|
|
#include <fsfw/tmtcservices/AcceptsTelemetryIF.h>
|
|
#include <mission/memory/SdCardMountedIF.h>
|
|
|
|
#include <filesystem>
|
|
#include <set>
|
|
|
|
#include "eive/eventSubsystemIds.h"
|
|
#include "eive/resultClassIds.h"
|
|
|
|
enum class RolloverInterval { MINUTELY, HOURLY, DAILY };
|
|
|
|
struct PersistentTmStoreArgs {
|
|
PersistentTmStoreArgs(object_id_t objectId, const char* baseDir, std::string baseName,
|
|
RolloverInterval intervalUnit, uint32_t intervalCount,
|
|
StorageManagerIF& tmStore, SdCardMountedIF& sdcMan)
|
|
: objectId(objectId),
|
|
baseDir(baseDir),
|
|
baseName(baseName),
|
|
intervalUnit(intervalUnit),
|
|
intervalCount(intervalCount),
|
|
tmStore(tmStore),
|
|
sdcMan(sdcMan) {}
|
|
|
|
object_id_t objectId;
|
|
const char* baseDir;
|
|
std::string baseName;
|
|
RolloverInterval intervalUnit;
|
|
uint32_t intervalCount;
|
|
StorageManagerIF& tmStore;
|
|
SdCardMountedIF& sdcMan;
|
|
};
|
|
|
|
struct DumpIndex {
|
|
uint32_t epoch = 0;
|
|
// Number of additional files with a suffix like .0, .1 etc.
|
|
uint8_t additionalFiles = 0;
|
|
// Define a custom comparison function based on the epoch variable
|
|
bool operator<(const DumpIndex& other) const { return epoch < other.epoch; }
|
|
};
|
|
|
|
class PersistentTmStore : public TmStoreFrontendSimpleIF, public SystemObject {
|
|
public:
|
|
enum class State { IDLE, DUMPING };
|
|
static constexpr uint8_t INTERFACE_ID = CLASS_ID::PERSISTENT_TM_STORE;
|
|
static constexpr ReturnValue_t DUMP_DONE = returnvalue::makeCode(INTERFACE_ID, 0);
|
|
static constexpr ReturnValue_t BUSY_DUMPING = returnvalue::makeCode(INTERFACE_ID, 1);
|
|
|
|
PersistentTmStore(PersistentTmStoreArgs args);
|
|
|
|
ReturnValue_t initializeTmStore();
|
|
State getState() const;
|
|
ReturnValue_t handleCommandQueue(StorageManagerIF& ipcStore, Command_t& execCmd);
|
|
|
|
void deleteUpTo(uint32_t unixSeconds);
|
|
ReturnValue_t startDumpFrom(uint32_t fromUnixSeconds);
|
|
ReturnValue_t startDumpFromUpTo(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
|
|
/**
|
|
*
|
|
* @param tmReader: Next packet will be loaded into the PUS TM reader. A CRC check will be
|
|
* performed on the packet. If that check fails, the file is considered corrupted and will
|
|
* be deleted for now.
|
|
* @param fileHasSwapped: If the CRC check fails, the file will be deleted and a new one has to
|
|
* be loaded. The dump can reach completion during that process. If a file is swapped, this
|
|
* boolean is set to true
|
|
* @return DUMP_DONE if dump is finished, returnvalue::OK if the next packet was loaded into the
|
|
* TM reader, and the returnvalue of the file swap operation if the CRC check failed and
|
|
* a new file was loaded.
|
|
*/
|
|
ReturnValue_t getNextDumpPacket(PusTmReader& tmReader, bool& fileHasSwapped);
|
|
/**
|
|
* Confirm the dump to advance the dump state machine.
|
|
* @param tmReader
|
|
* @param fileHasSwapped: If the confirmed dumps completes the current file, a new file will
|
|
* be loaded and this parameter will be set to true.
|
|
* @return If a file is swapped, the retrunvalue of the file swap operation.
|
|
*/
|
|
ReturnValue_t confirmDump(const PusTmReader& tmReader, bool& fileHasSwapped);
|
|
|
|
void getStartAndEndTimeCurrentOrLastDump(uint32_t& startTime, uint32_t& endTime) const;
|
|
ReturnValue_t storePacket(PusTmReader& reader);
|
|
ReturnValue_t cancelDump();
|
|
|
|
protected:
|
|
StorageManagerIF& tmStore;
|
|
|
|
private:
|
|
static constexpr uint8_t MAX_FILES_IN_ONE_SECOND = 10;
|
|
static constexpr size_t MAX_FILESIZE = 8192;
|
|
|
|
//! [EXPORT] : [SKIP]
|
|
static constexpr ReturnValue_t INVALID_FILE_DETECTED_AND_DELETED = returnvalue::makeCode(2, 1);
|
|
|
|
MessageQueueIF* tcQueue;
|
|
State state = State::IDLE;
|
|
bool baseDirUninitialized = true;
|
|
const char* baseDir;
|
|
std::string baseName;
|
|
uint8_t currentSameSecNumber = 0;
|
|
std::filesystem::path basePath;
|
|
// std::filesystem::path pathStart = basePath / baseName;
|
|
uint32_t rolloverDiffSeconds = 0;
|
|
std::array<uint8_t, 524> filePathBuf{};
|
|
size_t basePathSize;
|
|
std::array<uint8_t, MAX_FILESIZE> fileBuf{};
|
|
timeval currentTv;
|
|
timeval activeFileTv{};
|
|
|
|
struct ActiveDumpParams {
|
|
bool pendingPacketDump = false;
|
|
uint32_t fromUnixTime = 0;
|
|
uint32_t untilUnixTime = 0;
|
|
uint32_t currentFileUnixStamp = 0;
|
|
std::filesystem::path currentFile;
|
|
std::set<DumpIndex> orderedDumpFilestamps{};
|
|
std::set<DumpIndex>::iterator dumpIter;
|
|
std::optional<uint8_t> currentSameFileIdx = 0;
|
|
size_t fileSize = 0;
|
|
size_t currentSize = 0;
|
|
};
|
|
ActiveDumpParams dumpParams;
|
|
std::optional<std::filesystem::path> activeFile;
|
|
SdCardMountedIF& sdcMan;
|
|
|
|
/**
|
|
* To get the queue where commands shall be sent.
|
|
* @return Id of command queue.
|
|
*/
|
|
[[nodiscard]] MessageQueueId_t getCommandQueue() const override;
|
|
|
|
void calcDiffSeconds(RolloverInterval intervalUnit, uint32_t intervalCount);
|
|
ReturnValue_t buildDumpSet(uint32_t fromUnixSeconds, uint32_t upToUnixSeconds);
|
|
ReturnValue_t createMostRecentFile(std::optional<uint8_t> suffix);
|
|
static ReturnValue_t pathToTime(const std::filesystem::path& path, struct tm& time);
|
|
void fileToPackets(const std::filesystem::path& path, uint32_t unixStamp);
|
|
ReturnValue_t loadNextDumpFile();
|
|
ReturnValue_t createFileName(timeval& tv, std::optional<uint8_t> suffix, size_t& fullPathLength);
|
|
std::optional<uint8_t> extractSuffix(const std::string& pathStr);
|
|
bool updateBaseDir();
|
|
ReturnValue_t assignAndOrCreateMostRecentFile();
|
|
};
|
|
|
|
#endif /* MISSION_TMTC_TMSTOREBACKEND_H_ */
|