Skip to content

Repository files navigation

latestPIOFooFooFoo

Foo

FileData

Замена EEPROM для ESP8266/32 для хранения любых данных в файлах

  • Механизм автоматического "флага" первой записи
  • Поддержка всех файловых систем (LittleFS, SPIFFS, SDFS)
  • Поддержка любых типов статических данных
  • Отложенная запись по таймауту
  • "Обновление" данных - файл не перезапишется, если данные не изменились

Примечание: библиотека сохраняет бинарные, т.е. непригодные для чтения человеком данные. Если нужно хранение данных в файле в читаемом формате - используйте библиотеку PairsFile

Совместимость

ESP8266, ESP32

Содержание

Установка

  • Библиотеку можно найти по названию FileData и установить через менеджер библиотек в:
    • Arduino IDE
    • Arduino IDE v2
    • PlatformIO
  • Скачать библиотеку .zip архивом для ручной установки:
    • Распаковать и положить в C:\Program Files (x86)\Arduino\libraries (Windows x64)
    • Распаковать и положить в C:\Program Files\Arduino\libraries (Windows x32)
    • Распаковать и положить в Документы/Arduino/libraries/
    • (Arduino IDE) автоматическая установка из .zip: Скетч/Подключить библиотеку/Добавить .ZIP библиотеку… и указать скачанный архив
  • Читай более подробную инструкцию по установке библиотек здесь

Обновление

  • Рекомендую всегда обновлять библиотеку: в новых версиях исправляются ошибки и баги, а также проводится оптимизация и добавляются новые фичи
  • Через менеджер библиотек IDE: найти библиотеку как при установке и нажать "Обновить"
  • Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!

Инициализация

FileData;
FileData(fs::FS* fs);
FileData(fs::FS* fs, constchar* path);
FileData(fs::FS* fs, constchar* path, uint8_t key);
FileData(fs::FS* fs, constchar* path, uint8_t key, void* data, size_t size);
FileData(fs::FS* fs, constchar* path, uint8_t key, void* data, size_t size, uint16_t tout);
// fs - файловая система, адрес (&LittleFS, &SDFS..)// path - путь (имя) файла. Может быть любым, как и расширение ("/myData", "/data/settings.dat")// key - ключ первой записи. Не рекомендуется задавать 0 и 255. Рекомендуется использовать символы ('A', 'F')// data - ссылка на переменную (массив, структуру, класс)// size - размер переменной, можно передать как sizeof(переменная)// tout - таймаут обновления в миллисекундах (умолч 5000)

Использование

В ESP8266/32 EEPROM память эмулируется из Flash памяти, реализация EEPROM во встроенной библиотеке имеет следующие минусы:

  • Размер ограничен 4 кБ
  • Весь указанный в EEPROM.begin() объём памяти дублируется в оперативной памяти до вызова EEPROM.end()
  • При любом изменении в "EEPROM" памяти (даже 1-го байта) и вызове EEPROM.commit() полностью стирается и перезаписывается весь сектор 4 кБ. То есть износ памяти происходит не по ячейкам, а полностью всей EEPROM области! Около 10-20 тысяч перезаписей данных и EEPROM памяти больше нет

Предлагается использовать для хранения данных файловую систему (например встроенную LittleFS), которая сама заботится о перезаписи памяти и занимается ротацией файлов по отведённой области, что многократно увеличивает ресурс памяти и надёжность хранения данных. Также это позволит "скачивать" сохранённые данные, делать бэкапы и так далее. Данная библиотека является аналогом EEManager и имеет схожие с ней механизмы и возможности:

  • "Подключение" статических переменных любого типа, библиотека сама будет читать и писать их содержимое в файл
  • Механизм "ключа первого запуска" - если файл не существует или не содержит указанный ключ - в файл будут записаны данные "по умолчанию"
  • Механизм отложенной записи по таймауту - после изменения данных достаточно дать библиотеке команду на обновление, и она обновит данные по истечению таймаута
// установить файловую систему и путь к файлуvoidsetFS(fs::FS* nfs, constchar* path);
// установить ключvoidsetKey(uint8_t key);
// подключить данные (переменную)voidsetData(void* data, size_t size);
// установить таймаут записиvoidsetTimeout(uint16_t tout);
// прочитать файл в переменную// возврат: FD_FS_ERR/FD_FILE_ERR/FD_WRITE/FD_ADD/FD_READ
FDstat_t read();
// обновить сейчас// возврат: FD_FS_ERR/FD_FILE_ERR/FD_WRITE/FD_NO_DIF
FDstat_t updateNow();
// отложить обновление на заданный таймаутvoidupdate();
// тикер, обновит данные по таймауту// возврат: FD_FS_ERR/FD_FILE_ERR/FD_WRITE/FD_NO_DIF/FD_WAIT/FD_IDLE
FDstat_t tick();
// записать данные в файл// возврат: FD_FS_ERR/FD_FILE_ERR/FD_WRITE
FDstat_t write();
// сбросить ключ// возврат: FD_FS_ERR/FD_FILE_ERR/FD_RESET
FDstat_t reset();
// включить режим увеличения данных с добавлением в файл без очисткиvoidaddWithoutWipe(bool addw);
// ============== СТАТУСЫ ==============FD_IDLE// 0 - холостая работаFD_WAIT// 1 - ожидание таймаутаFD_FS_ERR// 2 - ошибка файловой системыFD_FILE_ERR// 3 - ошибка открытия файлаFD_WRITE// 4 - запись данных в файлFD_READ// 5 - чтение данных из файлаFD_ADD// 6 - добавление данных в файлFD_NO_DIF// 7 - данные не отличаются (не записаны)FD_RESET// 8 - произведён сброс ключа

Порядок действий (глобальные данные)

Для хранения "настроек" программы в глобальной области, чтобы всегда иметь к ним доступ:

  1. Создать глобальную переменную и объект FileData
  2. Передать переменную в объект
  3. Прочитать данные read() при запуске
  4. Вызывать tick() в loop()
  5. После изменения данных вызвать update()
  6. По истечению таймаута данные сами запишутся в файл

Таким образом безопасно вызывать update() несколько раз подряд, например при изменении "настройки" кнопками - данные обновятся только после окончания ввода и таймаута

Порядок действий (локальные данные)

Для хранения настроек в файле и чтении/изменении внутри функций в программе:

  1. Создать переменную и объект FileData
  2. Передать переменную в объект
  3. Прочитать данные read()
  4. Если данные изменились и их нужно сохранить - вызвать updateNow()
voidfunc() {
Data mydata;
FileData data(&LittleFS, "/data.dat", 'A', &mydata, sizeof(mydata));
data.read();
// ...
data.updateNow();
}

Изменение данных

  • При изменении размера данных (при изменении количества полей в структуре) будет выполнен сброс при чтении - в файл запишется новая структура
  • При установке флага addWithoutWipe(true) и при увеличении размера данных: данные старого размера прочитаются из файла, затем в файл будут дописаны новые данные (разница со старым размером). Это удобно при разработке проекта - добавление новых "настроек" не будет сбрасывать старые

Пример

#include<Arduino.h>
#include<FileData.h>
#include<LittleFS.h>structData {
uint8_t val8;
uint16_t val16;
uint32_t val32 = 12345;
char str[20];
};
Data mydata;
FileData data(&LittleFS, "/data.dat", 'B', &mydata, sizeof(mydata));
voidsetup() {
Serial.begin(115200);
delay(1000);
Serial.println();
LittleFS.begin();
// прочитать данные из файла в переменную// при первом запуске в файл запишутся данные из структуры
FDstat_t stat = data.read();
switch (stat) {
caseFD_FS_ERR: Serial.println("FS Error");
break;
caseFD_FILE_ERR: Serial.println("Error");
break;
caseFD_WRITE: Serial.println("Data Write");
break;
caseFD_ADD: Serial.println("Data Add");
break;
caseFD_READ: Serial.println("Data Read");
break;
default:
break;
}
Serial.println("Data read:");
Serial.println(mydata.val8);
Serial.println(mydata.val16);
Serial.println(mydata.val32);
Serial.println(mydata.str);
}
voidloop() {
// data.tick(); // вызывать тикер в loop// можно отловить момент записиif (data.tick() == FD_WRITE) Serial.println("Data updated!");
// запишем в данные строку из монитора порта// а также присвоим остальным переменным случайные значенияif (Serial.available()) {
int len = Serial.readBytes(mydata.str, sizeof(mydata.str) - 1);
mydata.str[len] = '\0';
mydata.val8 = random(255);
mydata.val16 = random(65000);
Serial.println("Update");
// отложить обновление
data.update();
}
}

Версии

  • v1.0

Баги и обратная связь

При нахождении багов создавайте Issue, а лучше сразу пишите на почту alex@alexgyver.ru
Библиотека открыта для доработки и ваших Pull Request'ов!

При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:

  • Версия библиотеки
  • Какой используется МК
  • Версия SDK (для ESP)
  • Версия Arduino IDE
  • Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
  • Какой код загружался, какая работа от него ожидалась и как он работает в реальности
  • В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код

About

Замена EEPROM для ESP8266/32 для хранения любых данных в файлах

Resources

Stars

19 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages