• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

ESP8266 и sqlite3

Ну тут главное именно как распарсить показано.
А на счет добавления ход действий такой?
1. Читаем и парсим как и в первом случае.
2. Потом работаем с массивом и добавляем туда новый объект.
3. Далее пишем в файл. При чем я так понимаю надо все данные перезаписать.

Или же можно не читая его, просто добавить еще одну строку?
Хотя наверное нельзя. Там ведь массив объектов. Если бы просто объекты шли без массива, тогда просто строку дописать. Хотя может это и не проще.
 
Ну вроде написал я добавление объектов. А т.к. оно идет через считывание файла, а потом добавление или удаление элемента массива, то и удалить можно будет.
Смущает меня, что весь файл перезаписывается, хотя ведь это файл, а не база данных. Он все равно будет весь перезаписываться. И еще один момент, который я бы хотел уточнить.
Я считываю JsonArray в строку при помощи printTo(). А потом ее пишу в файл. Мне не нравиться, что в файле после этого строки в виде столбцов. Вот так:
Код:
[
  {
    "cyear": 2021,
    "cmonth": 12,
    "cday": 31,
    "chour": 23,
    "cmin": 55,
    "tin": 28.5,
    "tout": -13.6,
    "vlagn": 13.5,
    "davl": 745.6
  },
  {
    "cyear": 2021,
    "cmonth": 12,
    "cday": 31,
    "chour": 23,
    "cmin": 56,
    "tin": 28.3,
    "tout": -13.2,
    "vlagn": 13.3,
    "davl": 745.5
  },
Можно ли сделать, чтобы они постросно писались, как я раньше показывал:
Код:
[{"cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":55, "tin":28.5, "tout":-13.6, "vlagn":13.5, "davl":745.6},
{"cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":58, "tin":25.6, "tout":-3.7, "vlagn":15.8, "davl":747.8}]
Ну т.е. в одну строку. Так ведь файл будет меньше места занимать? Или я ошибаюсь?
Ну и собственно вот что у меня получилось. Собственно это тест, поэтому новые данные я передаю через ввод порта:
Код:
void loop() {
  if (Serial.available() > 0) {
    //Данные вносим через разделитель запятую. Знак разделяющий целое от десятых - точка.
    String str = Serial.readString();
    if (str != "")
    {
      char indata[str.length() + 1];
      strcpy(indata, str.c_str());
      str = "";
      addJsonObject(indata);
     }
  }
}
Ну а дальше считываю файл, добавляю в массив строку, ту что в порт передал в виде JsonObject, (или если потом надо будет удалить, удалю нужный объект), потом передаж JasonArray в строку, а потом сохраняю в файл.
Код:
void addJsonObject(char *instring) {
  String fileData = readFile("/2.json");
  char dataJson[fileData.length() + 1];
  strcpy(dataJson, fileData.c_str());
  DynamicJsonBuffer jsonBuffer;
  JsonArray& root = jsonBuffer.parseArray(dataJson);
  Serial.println(instring);
  //JsonObject obj = jsonBuffer.createObject();
  JsonObject& obj = jsonBuffer.parseObject(instring);
  root.add(obj);
  String out;
  root.printTo(out);
  Serial.println(out);
  writeFile("/2.json", out);
}

String readFile(String fileName) {
  File configFile = SPIFFS.open(fileName, "r");
  if (!configFile) {
    return "Failed";
  }
  String temp = configFile.readString();
  configFile.close();
  return temp;
}

String writeFile(String fileName, String strings ) {
  File configFile = SPIFFS.open(fileName, "w");
  if (!configFile) {
    return "Failed to open config file";
  }
  configFile.print(strings);
  configFile.close();
  return "Write sucsses";
}
Может оно и коряво или некрасиво, но работает.
Может посоветуете, что можно улучшить. Ну и как передавать не ввиде колонок, а ввиде строки.
 

EvgeniyS

Member
Может посоветуете, что можно улучшить. Ну и как передавать не ввиде колонок, а ввиде строки.
По поводу строки не задавался вопросом, знаю что есть 2 метода: printTo и prettyPrintTo.
По поводу улучшения, я бы советовал изучить документацию по arduinoJson и SPIFFS, за основу кода можно взять пример от автора.
 

azh.rwo.ru

New member
Прочитал весь тред, но в итоге не совсем понятно, что топик-стартер желает получить в итоге, просто попробовать sqlite
на esp8266 без привязки к задаче? Просто не могу представить себе реальную задачу, где надо иметь onboard базу данных с SQL запросами к ней в пределах esp8266.
 
Задача собственно понятное дело такая же бредовая, как и большинство конструкций на ардуино вообще. Просто хочу хранить историю измерений за определённый период. Понятно, что без этого можно легко прожить. Собственно сама метеостанция уже прекрасно и красиво все показывает. И понятно что я и сам в эту историю буду залезать раз в пол года а больше никто и не залезает. Но вот хочется. Собственно я уже от sqlite отказался. Причина выше. Делаю на json. Ну практически сделал. Осталось поэкспериментировать за какой период влезут данные на esp.
 

azh.rwo.ru

New member
Просто хочу хранить историю измерений за определённый период.
Как вариант - копай в сторону "time series database", реализации есть, но это ИМХО тоже не очень правильно. Если данные можно типизировать, то свой "движок" именно под эти данные и вперёд. :)
 

azh.rwo.ru

New member
Да я вроде на JSON уже остановился.
Хозяин барин как говорится, но смотри сколько ты сохраняешь лишнего
... {"cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":55, "tin":28.5, "tout":-13.6, "vlagn":13.5, "davl":745.6}
1. "cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":55, -- по сути это DATATIME, почему его не хранить в UnixTime формате?
2. Если места полей в структуре сохраняемого и размерность данных не меняется (а у тебя это так) то почему не хранить это всё массивом целых чисел?
3. JSON - же оставить для связи с внешними сущностями написав соответсвующий конвертор

ИМХО так
 
Хозяин барин как говорится, но смотри сколько ты сохраняешь лишнего
... {"cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":55, "tin":28.5, "tout":-13.6, "vlagn":13.5, "davl":745.6}
1. "cyear":2021, "cmonth":12, "cday":31, "chour":23, "cmin":55, -- по сути это DATATIME, почему его не хранить в UnixTime формате?
2. Если места полей в структуре сохраняемого и размерность данных не меняется (а у тебя это так) то почему не хранить это всё массивом целых чисел?
3. JSON - же оставить для связи с внешними сущностями написав соответсвующий конвертор

ИМХО так
Да, я тоже об этом думал уже. И хотел спросить, каков предел длинны строки?
На счет даты. Оно же все равно хранится в виде строки в JSON. Можно тоже массивом. Там ведь уже имеет значение количество символов. Итак да, сейчас буду все сокращать. Ну и если таки есть предел символов в строке, тогда наверное придется по дням файлы бить.
 

azh.rwo.ru

New member
Да, я тоже об этом думал уже. И хотел спросить, каков предел длинны строки?
В зависимости от реализации С++ видимо. :) Приблизительно равно размеру максимального куска незанятой памяти
На счет даты. Оно же все равно хранится в виде строки в JSON.
Это у тебя оно так хранится, при обработке всякие очеловеченные представления исключены.
Можно тоже массивом. Там ведь уже имеет значение количество символов. Итак да, сейчас буду все сокращать. Ну и если таки есть предел символов в строке, тогда наверное придется по дням файлы бить.
Ну да, датавремя создания и есть имя файла, очень логично ...типа 202103071759
 
Получил непонятную ошибку. Есть такая функция:
Код:
void addToBD(String fileName, char *instring) {
  int rec_to_delete;
  String fileData = readFile(fileName);
  char dataJson[fileData.length() + 1];
  strcpy(dataJson, fileData.c_str());
  DynamicJsonBuffer jsonBuffer;
  JsonArray& root = jsonBuffer.parseArray(dataJson);
  //Serial.println(instring);
  //JsonObject obj = jsonBuffer.createObject();
  JsonObject& obj = jsonBuffer.parseObject(instring);
  root.add(obj);
  if (fileName.indexOf("data_d.json") == 0) {
    rec_to_delete = root.size() - 1440;
  }
  else {
    rec_to_delete = root.size() - 2920;
  }
  if (rec_to_delete > 0) {
    for (int i=0; i<rec_to_delete; i++){
      root.remove(0);
    }
  }
  String out;
  root.printTo(out);
  out.replace("\n","");
  Serial.println(out);
  writeFile(fileName, out);
}
Пока не вставил выделенный фрагмент(странно, при редактировании выделяется. Н в общем после root.add(obj); и до String out, все работало. Выделенный фрагмент должен удалять записи из массива JSON. Для 2 разных файлов, разный предел. Ну это бог с ним. У меня ArduinoJson v5.8.3.
Вот здесь написано, как использовать remove, но выдает ошибку:
main:100:12: error: 'class ArduinoJson::JsonArray' has no member named 'remove'
root.remove(0);
 
И еще вопрос. Можно ли файл с SPIFFS скопировать на компьютер? Может как-то в программе можно настроить это копирование? Просто вдруг скажем понадобиться исправить какую-нибудь WEB страничку, т.к. утилита копирует все что есть, а того, чего нет стирает, получается потеряются все данные.
 

CodeNameHawk

Moderator
Команда форума
т.к. утилита копирует все что есть, а того, чего нет стирает,
т.к. утилита копирует все что есть - это хорошо.
чего нет стирает - это, как если этого нету?
Просто вдруг скажем понадобиться исправить какую-нибудь WEB страничку,
Есть в примерах ардуино иде, даже можно отредактировать на месте.
 
чего нет стирает - это, как если этого нету?
Ну скажем я возился с sqlite, там был файл базы sqlite, когда я убрал его из папки data он стерся и со SPIFFS. Ну и скажем я делал тестовый скетч для работы с JSON, когда я загрузил файлик для тестов, все htm странички от основного скетча удалились, т.к. их соответственно не было в папке data для теста.
Есть в примерах ардуино иде, даже можно отредактировать на месте.
Не видел. А не подскажите в каком примере? Вообще щас и сам конечно поищу.
 
Он не может пропасть из SPIFFS, ясное дело, если каждый раз не переписывать всю файловую систему.
Ну есть утилита ESP8266 Sketch Data Uploader. Она встраивается во вкладку Tool Arduino IDE. Вот этой утилитой я и пользуюсь. Я не знаю переписывает ли она всю файловую систему, но после такой загрузки на SPIFFS остаются только те файлы, что были в data. Остальные все стираются. Ну во всяком случае при запуске этой утилиты не предлагается выбор типа переписывать всю файловую систему или только дописать несуществующие файлы.
 

EvgeniyS

Member
И еще вопрос. Можно ли файл с SPIFFS скопировать на компьютер?
C++:
#include <ESPAsyncWebServer.h>
#include <SPIFFSEditor.h>
AsyncWebServer server(80);
void setup() {
    server.addHandler(new SPIFFSEditor()); //в редактор заходим по адресу [ваш ip]/edit
    server.begin();
}
Я не уверен, но не это ли вам нужно? Сам давно не использую, и насколько помню, редактор "кривоват"
 
C++:
#include <ESPAsyncWebServer.h>
#include <SPIFFSEditor.h>
AsyncWebServer server(80);
void setup() {
    server.addHandler(new SPIFFSEditor()); //в редактор заходим по адресу [ваш ip]/edit
    server.begin();
}
Я не уверен, но не это ли вам нужно? Сам давно не использую, и насколько помню, редактор "кривоват"
Не компилится. СНачала требует 2 новых библиотеки. Я их скачал. Потом сказал:
Код:
no matching function for call to 'esp8266webserver::ESP8266WebServerTemplate<WiFiServer>::addHandler(SPIFFSEditor*)
 
Сверху Снизу