#pragma once #include #include #include #include "NodePrefs.h" class DataStoreHost { public: virtual bool onContactLoaded(const ContactInfo& contact) =0; virtual bool getContactForSave(uint32_t idx, ContactInfo& contact) =0; virtual bool onChannelLoaded(uint8_t channel_idx, const ChannelDetails& ch) =0; virtual bool getChannelForSave(uint8_t channel_idx, ChannelDetails& ch) =0; }; class DataStore { FILESYSTEM* _fs; FILESYSTEM* _fsExtra; mesh::RTCClock* _clock; IdentityStore identity_store; void loadPrefsInt(const char *filename, NodePrefs& prefs, double& node_lat, double& node_lon); #if defined(NRF52_PLATFORM) || defined(STM32_PLATFORM) void checkAdvBlobFile(); #endif // Chunked save state File _saveFile; DataStoreHost* _saveHost = nullptr; uint32_t _saveIdx = 0; uint32_t _saveRecordsWritten = 0; bool _saveInProgress = false; bool _saveWriteOk = true; public: DataStore(FILESYSTEM& fs, mesh::RTCClock& clock); DataStore(FILESYSTEM& fs, FILESYSTEM& fsExtra, mesh::RTCClock& clock); void begin(); bool formatFileSystem(); FILESYSTEM* getPrimaryFS() const { return _fs; } FILESYSTEM* getSecondaryFS() const { return _fsExtra; } bool loadMainIdentity(mesh::LocalIdentity &identity); bool saveMainIdentity(const mesh::LocalIdentity &identity); void loadPrefs(NodePrefs& prefs, double& node_lat, double& node_lon); void savePrefs(const NodePrefs& prefs, double node_lat, double node_lon); void loadContacts(DataStoreHost* host); void saveContacts(DataStoreHost* host); // Chunked save — splits contact write across multiple loop iterations // to prevent blocking the main loop for 500ms+ on large contact lists. // Call beginSaveContacts(), then saveContactsChunk() each loop until it // returns false (done), then finishSaveContacts() to verify and commit. bool beginSaveContacts(DataStoreHost* host); bool saveContactsChunk(int batchSize = 20); // returns true if more to write void finishSaveContacts(); bool isSaveInProgress() const { return _saveInProgress; } void loadChannels(DataStoreHost* host); void saveChannels(DataStoreHost* host); void migrateToSecondaryFS(); uint8_t getBlobByKey(const uint8_t key[], int key_len, uint8_t dest_buf[]); bool putBlobByKey(const uint8_t key[], int key_len, const uint8_t src_buf[], uint8_t len); File openRead(const char* filename); File openRead(FILESYSTEM* fs, const char* filename); bool removeFile(const char* filename); bool removeFile(FILESYSTEM* fs, const char* filename); uint32_t getStorageUsedKb() const; uint32_t getStorageTotalKb() const; private: FILESYSTEM* _getContactsChannelsFS() const { if (_fsExtra) return _fsExtra; return _fs;}; };