#pragma once #include "freertos/FreeRTOS.h" #include "freertos/semphr.h" #include "esp_littlefs.h" #include "esp_err.h" #include #include #include #include #include "esp_log.h" #include // Forward declaration class LittleFSHandler; class FSGuard { public: FSGuard(LittleFSHandler* fs_handler, const std::string& relative_path, const char* flags); ~FSGuard(); esp_err_t close(); FILE* get_file() { return file_; } bool is_open() const { return file_ != nullptr; } private: LittleFSHandler* fs_handler_ = nullptr; FILE* file_; // prevent copying and moving FSGuard(const FSGuard&) = delete; FSGuard& operator=(const FSGuard&) = delete; FSGuard(FSGuard&& other) = delete; FSGuard& operator=(FSGuard&& other) = delete; }; //LittleFSHandler interface // All paths are relative to the mounted filesystem root // Implementations should handle initialization of the filesystem, and mounting if necessary // When destroyed, implementations should unmount the filesystem if necessary // All paths are relative to the mounted filesystem root, e.g. if mounted at /littlefs, and file is /data.txt, the full path is /littlefs/data.txt // File operations use standard C FILE* wrapped in FSGuard for RAII class LittleFSHandler { public: LittleFSHandler(); ~LittleFSHandler(); esp_err_t init(std::string base_path); esp_err_t init(const esp_vfs_littlefs_conf_t& config); std::string get_base_path() const; std::string get_full_path(const std::string& relative_path) const; // File operations esp_err_t write_file(const std::string& relative_path, const uint8_t* data, size_t size, size_t& out_bytes_written); esp_err_t write_file(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written); // esp_err_t append_file(const std::string& relative_path, const uint8_t* data, size_t size, size_t& out_bytes_written); esp_err_t append_file(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written); // esp_err_t read_file(const std::string& relative_path, const size_t max_size, uint8_t* out_data, size_t& out_size); esp_err_t read_file(FILE* file, const size_t max_size, uint8_t* out_data, size_t& out_size); // esp_err_t delete_file(const std::string& relative_path); // bool file_exists(const std::string& relative_path); esp_err_t get_file_size(const std::string& relative_path, size_t& out_size); // Directory operations esp_err_t create_directory(const std::string& relative_path); esp_err_t list_directory(const std::string& relative_path, std::vector& out_entries); protected: esp_err_t open_file_(const std::string& relative_path, const char* flags, FILE*& out_file); esp_err_t close_file_(FILE* file); // uses standard C FILE* for file operations esp_err_t write_if_different_(FILE* file, const uint8_t* data, size_t size); esp_err_t write_if_different_(FILE* file, const uint8_t* data, size_t size, size_t& out_bytes_written); friend class FSGuard; private: // bool is_initialized_() const; SemaphoreHandle_t fs_mutex_ = nullptr; bool initialized_ = false; std::string base_path_; };