Хранение любых данных в текстовом виде в формате "ключ":значение
- Быстрая и лёгкая реализация по сравнению с JSON
- Выделение буфера: статическое или динамическое (как у String)
- Доступ (чтение и запись) через []
- Нативная конвертация из любых типов на запись, вывод в выбранный тип на чтение
- Отдельный инструмент для esp8266/esp32 - автоматическая запись и чтение в файл
Совместима со всеми Arduino платформами (используются Arduino-функции)
Библиотека содержит в себе несколько классов для работы в разных сценариях:
PairsExt
Основной объект пар на основе статического внешнего char
массива указанной длины.
// конструктор
PairsExt();
PairsExt(char* str, uint16_t size); // подключить внешний буфер размера size
// методы
uint16_t getSize(); // получить размер буфера
void setBuffer(char* str, uint16_t len);// подключить буфер
void clear(); // очистить строку
bool changed(); // было изменение данных. Само сбросится в false
bool has(Text key); // проверка на существование
uint16_t amount(); // количество пар
void refresh(); // пересчитать длину строки и количество пар (после ручных изменений)
bool fromText(Text text); // создать из текста
bool set(Text key, Value value); // установить по ключу
bool set(Text key, void* var, size_t size); // установить по ключу
bool set(int idx, Value value); // установить по индексу
bool set(int idx, void* var, size_t size); // установить по индексу
Pair get(Text key); // получить по ключу
Pair get(int idx); // получить по индексу
bool remove(Text key); // удалить по ключу
bool remove(int idx); // удалить по индексу
Pairs
Объект пар на основе динамической строки. Методы такие же как у PairsExt
, за исключением setBuffer/reserve.
// конструктор
Pairs();
Pairs(uint16_t size); // с указанием резерва строки
// методы
bool reserve(uint16_t len); // зарезервировать строку
// копировать из другого экземпляра
bool copy(const Pairs& val);
// переместить из другого экземпляра
void move(Pairs& rval);
// освободить память
void reset();
// + наследует всё из PairsExt
PairsStatic
Основан на PairsExt
, но вместо внешнего массива создаёт свой, внутри объекта.
// конструктор
PairsStatic<макс. размер> ();
// методы
// + наследует всё из PairsExt
PairsFile
Автоматическое хранение и обновление базы пар для esp8266/esp32. Привязывается к файлу, записывает в него данные при изменении + выходе таймаута. Основано на динамическом классе Pairs
.
// конструктор
// Установить файловую систему, имя файла и таймаут
PairsFile(fs::FS* nfs = nullptr, const char* path = nullptr, uint32_t tout = 10000);
// методы
// наследует всё из Pairs
// установить файловую систему и имя файла
void setFS(fs::FS* nfs, const char* path);
// установить таймаут записи, мс (умолч. 10000)
void setTimeout(uint32_t tout = 10000);
// прочитать данные в буфер. Опционально заразервировать дополнительное место. true если прочитаны
bool begin(uint16_t res = 0);
// обновить данные в файле
bool update();
// тикер, вызывать в loop. Сам обновит данные при изменении и выходе таймаута, вернёт true
bool tick();
Pair
Объект пары, наследует Text для значения и содержит поле Text key для ключа.Text key;
Данные хранятся в текстовом виде в формате пар "ключ":значение
, между парами ставится разделитель \n
(перенос строки), после последней пары не ставится. Вид данных как текст:
"key0":value0
"key1":value1
"key2":value2
Во время редактирования через методы библиотеки (добавить, удалить, изменить) библиотека сама следит за корректным расположением разделителей.
В библиотеке реализован доступ к значениям через квадратные скобки на чтение и запись. Это удобно, но есть особенность: при чтении по ключу, которого нет в базе - будет создано новое поле с этим ключом и пустым значением! При использовании функции get()
этого не происходит. Например в базе нет ключа key
:
Serial.println(data.get("key")); // ничего не произойдёт
Serial.println(data["key"]); // будет создан ключ key с пустым значением
Ключ и значение не должны содержать неэкранированных двойных кавычек "
- это сломает чтение и запись! Библиотека не следит за этим и сама кавычки не экранирует. Если в поле значения нужен символ двойных кавычек - его нужно экранировать символом \
:
"key0":val"ue0 - неправильно
"key1":val\"ue1 - правильно
data["key"] = "val\"ue"; // неправильно (равносильно значению val"ue)
data["key"] = "val\\\"ue"; // правильно (равносильно значению val\"ue)
Pairs
в некоторых местах наследует инструменты из библиотеки StringUtils, полное описание смотри в документации. Например любой вызов data[key]
или data.get(key)
конвертируется в тип Text
:
Тип Text
может принимать:
const char*
,char*
,"строковые константы"
F("строки")
- строки из PROGMEMString
- строки
Тип Value
может принимать:
- Строки как в
Text
- Все целые числа (8, 16, 32, 64 бит)
double
иfloat
- Бинарные данные (base64)
data["key0"] = "val0";
data[F("key1")] = 1234;
data["key2"] = 3.14;
data[0] = F("abcd");
data.set("key0", "val0");
data.set("key1", 1234567ul);
Text
выводится в Print, автоматически сравнивается и конвертируется в любые типы данных, что позволяет получать значения напрямую:
data["key"] == 12345;
int i = data["key"];
float f = data["key"];
String s = data["key"];
char buf[20];
data["key"].toStr(buf);
data["key"] == data.get("key2");
Serial.println(data["key"]);
Serial.println(data.get("key"));
// итд
Сам объект Pairs также является экземпляром Text
, то есть всю базу пар можно:
Serial.println(data); // вывести в Print
String s = data; // скопировать в String
data1 == data2; // сравнить с другой базой (как строку)
Помимо данных в виде читаемого текста (числа, строки), библиотека позволяет хранить под ключом также сложные данные, например структуры и массивы. Они будут конвертированы в формат base64 и сохранены в виде текста, а при помощи Text::decodeB64
их можно распаковать и записать обратно:
struct S {
float f;
int i;
};
// запись
S s{3.14, 1234};
int arr[] = {1, 2, 3, 4, 5};
data["key1"] = pairs::Value(&s, sizeof(s)); // запаковать, способ 1
data.set("key2", &arr, sizeof(arr)); // запаковать, способ 2
// чтение
S s1;
int arr1[5];
// распаковать в указанную переменную
data["key1"].decodeB64(&s1, sizeof(s1));
data.get("key2").decodeB64(&arr1, sizeof(arr1));
У разных классов по сути отличается только инициализация:
char str[100] = {0};
PairsExt data(str, 100);
Pairs data;
PairsStatic<100> data;
PairsFile data(&LittleFS, "/data.dat");
data.begin();
// перед вызовом begin() файловая система должна быть запущена!
При ручных изменениях в буфере (данные скопированы откуда-то извне) нужно вызвать .refresh()
для пересчёта базы данных!
PairsFile data(&LittleFS, "/data.dat", 3000);
void setup() {
LittleFS.begin();
data.begin(); // прочитать из файла
data["key"] = "value"; // изменили
}
void loop() {
data.tick(); // тикаем тут. Само обновится после таймаута
}
- v1.0
- v1.1
- Динамическая String реализация заменена на свою
- Добавлена возможность задавать значения из PROGMEM
- Библиотека облегчена и ускорена
- Больше безопасности
- v1.2 - автоматическое разэкранирование при выводе в String
- v1.3 - добавлена зависимость от StringUtils. Оптимизация и увеличение возможностей
- v1.3.1 - оптимизация под StringUtils 1.3
- v1.4 - оптимизация, больше интеграции со StringUtils, хранение бинарных данных
- Требуется установленная библиотека StringUtils
- Библиотеку можно найти по названию Pairs и установить через менеджер библиотек в:
- 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: найти библиотеку как при установке и нажать "Обновить"
- Вручную: удалить папку со старой версией, а затем положить на её место новую. "Замену" делать нельзя: иногда в новых версиях удаляются файлы, которые останутся при замене и могут привести к ошибкам!
При нахождении багов создавайте Issue, а лучше сразу пишите на почту [email protected]
Библиотека открыта для доработки и ваших Pull Request'ов!
При сообщении о багах или некорректной работе библиотеки нужно обязательно указывать:
- Версия библиотеки
- Какой используется МК
- Версия SDK (для ESP)
- Версия Arduino IDE
- Корректно ли работают ли встроенные примеры, в которых используются функции и конструкции, приводящие к багу в вашем коде
- Какой код загружался, какая работа от него ожидалась и как он работает в реальности
- В идеале приложить минимальный код, в котором наблюдается баг. Не полотно из тысячи строк, а минимальный код