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

ESP8266 и sqlite3

В начале функция инициализации sqlite. Она вызывается в функции setup. Там задается шедулер по которому раз в минуту данные датчиков заносятся в базу.
Ну и далее db_exec и callback.
 

CodeNameHawk

Moderator
Команда форума
Я не буду проверять правильно ли вы скопировали.
Делайте все проще, залили пример, проверили работает - меняете одну строку, например расширение файла, если работает двигаетесь дальше, если пример не работает, то писать отсебятину нет смысла.
 
А вы какой пример брали из библиотеки?
Очевидно так и придщется делать. Только видно моя ошибка в том, что я не из библиотеки пример брал, а с того видео iomoio. Там я все хорошо скопировал. И ведь работало пока мало записей было.
 
Удалил файл созданный на компе. В скетче путь написал /FLASH/weather.sql3 и о чудо! Файл создался и начал размер у него меняться. Но, дальше чуда не случилось. На теперь уже 26 записях выдал out of memory. Странно. Размер файла 4 килобайта. Может где-то ограничение прописано?
 
Мда. Все-таки английский не мое. Вчера до 11 сидел и сегодня утром. Максиму чего нашел как-то подходящее вот:
Код операции [SQLITE_FCNTL_CHUNK_SIZE] используется для запроса того, чтобы VFS расширяла и усекала файл базы данных кусками размера, указанного пользователем. Четвертый аргумент [sqlite3_file_control ()] должен указывать на целое число (тип int), содержащее новый размер блока для использования в назначенной базе данных. Выделение файлового пространства базы данных большими фрагментами (скажем, по 1 МБ за раз) может уменьшить фрагментацию файловой системы и повысить производительность в некоторых системах.
Но как и где это задать для теста?
 
Блин, все воскресенье сегодня в этом sqlite3.h лазаю. Подскажите, что вы там нашли? То ли я недопонимаю английский. В школе я французский учил. Конечно уже и к английскому приблатыкался, но ничего не нахожу. Написал новый скетч, откуда убрал практически все. Сделал только автозаполнение базы. Теперь 145 записей вносится, файл получается размером 7680. Но потом снова out of memory. Вот мой скетч:
Код:
#include <ESP8266WiFi.h>
#include <TickerScheduler.h>
#include <sqlite3.h>
#include <vfs.h>
#include <FS.h>

// Для файловой системы
File fsUploadFile;

//Планировщик задач (Число задач)
TickerScheduler ts(1);

void setup() {
  Serial.begin(115200);
  FS_init();
  sqlite_init();
}

void loop() {
  ts.update();

  if (Serial.available() > 0) {
    String str = Serial.readString();
    if (str != "") {
      char query[str.length() + 1];
      strcpy(query, str.c_str());
      str = "";
      db_exec(query);
    }
  }
}

// Инициализация FFS
void FS_init(void) {
  system_update_cpu_freq(SYS_CPU_160MHZ); 
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount SPIFFS");
    return;
  }
  Dir dir = SPIFFS.openDir("/");
  while (dir.next()) {
    String fileName = dir.fileName();
    size_t fileSize = dir.fileSize();
    Serial.print(fileName); Serial.println(fileSize);
  }
}

void sqlite_init() {
  sqlite3_initialize();
  int cmin = 0;
  int chour = 0;
  int csec = 0;
  ts.add(0, 10000, [&](void*) {
    String tIn = "27.5";//(String)GettIn();
    String tOut = "-4.3";//(String)GettOut();
    String humidity = "21";//(String)Gethumidity();
    String pressure = "745";//(String)Getpressure();
    String str = "INSERT INTO day_p (cyear, cmonth, cday, chour, cmin, tin, tout, vlag, davl) ";
    str += "VALUES (2021, 2, 28, " + String(chour) + ", " + String(cmin);
    str += ", " + tIn + ", " + tOut + ", " + humidity + ", " + pressure + ");";
    str += "Select count(cyear) from day_p group by cyear;";
    char query[str.length() + 1];
    strcpy(query, str.c_str());
    str = "";
    db_exec(query);
    csec = csec + 10;
    if (csec == 60) {
      csec = 0;
      cmin++;
    }
    if (cmin == 60) {
      cmin = 0;
      chour++;
    }
  }, nullptr, true);
}

void db_exec(const char *sql) {
   sqlite3 *db;
   int rc;
   const char *dbf = "/FLASH/weather.sql3";
   char *ErrMsg = 0;
   const char* data = 0;
   Serial.println(sql);
   File db_file_obj;
   vfs_set_spiffs_file_obj(&db_file_obj);
   if (sqlite3_open(dbf, &db)) {
       Serial.print(F("Can't open database: "));
       Serial.println(sqlite3_errmsg(db));
       return;
   }
   else Serial.println("DB opened");
   rc = sqlite3_exec(db, sql, callback, (void*)data, &ErrMsg);
   if (rc != SQLITE_OK) {
       Serial.print(F("SQL error: "));
       Serial.println(ErrMsg);
       sqlite3_free(ErrMsg);
   }
   Serial.println(rc);
   sqlite3_close(db);
  
}

static int callback(void *data, int argc, char **argv, char **azColName) {
  for (int i = 0; i < argc; i++){
    if (i > 0) {
      Serial.print(" | ");
    }
    Serial.print(argv[i]);
  }
  Serial.println();
  return 0;
}
 

CodeNameHawk

Moderator
Команда форума
Тут что то похожее на вашу проблему
https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html
Only implemented in SPIFFS. Performs a quick garbage collection operation on SPIFFS, possibly making writes perform faster/better in the future. On very full or very fragmented filesystems, using this call can avoid or reduce issues where SPIFFS reports free space but is unable to write additional data to a file. See this discussion <https://github.com/esp8266/Arduino/pull/6340#discussion_r307042268> for more info.
Но далеко не факт, что проблема в файловой системе.
 
Тут что то похожее на вашу проблему
https://arduino-esp8266.readthedocs.io/en/latest/filesystem.html

Но далеко не факт, что проблема в файловой системе.
Спасибо. Посмотрю. Возможно и в файловой системе дело. Вообще мне перестает нравится идея с sqlite. То места не хватает, то файл портится, пишет, что это не БД и никак его не восстановить, то еще какую-то ошибку выдает, точно как звучит не помню, но БД снова не восстанавливается. Может конечно и физическая проблема, сама ESP бракованая.
 

CodeNameHawk

Moderator
Команда форума
Вставьте в ваш цикл проверку оставшейся доступной памяти, у меня перестало вставлять, когда память уменьшилась до 10600 байт.
Serial.println(ESP.getFreeHeap());
А потом, когда файл стал больше 7 кБ, база пишет, что SQL error: disk I/O error, при попытке добавить новую запись.
 
Последнее редактирование:
Вставьте в ваш цикл проверку оставшейся доступной памяти, у меня перестало вставлять, когда память уменьшилась до 10600 байт.
Serial.println(ESP.getFreeHeap());
У меня в изначальном скетче была эта проверка раз в 5 минут. Там значение не менялось. Попробую сегодня в тестовом скетче вставить.
 
Все. Перелом мозга заработал. Сутра бьюсь с этой littleFS. Не открывайет файл базы данных и все. Может быть с littleFS VFS не надо использовать? Просто ни одного вообще примера не нашел где бы люди sqlite с littleFS использовали.
 
Наверное littlefs не прокатит. В библиотеке VFS есть функция vfs_set_spiffs_file_obj. В описании так и написано, что она устанавливает объект file перед открытием файла в SPIFFS. Открыть файл без VFS у меня так же не получается.
 

CodeNameHawk

Moderator
Команда форума
Если интернета нет, я бы смотрел в сторону Raspberry Pi или Android тв приставки.
 
Если интернета нет, я бы смотрел в сторону Raspberry Pi или Android тв приставки.
Это вы о выкладывании данных в интернет? Ну как нет. Сейчас есть. Ну просто неинтересно мне само выкладывание данных в инет. Не раз уже нарывался на их пропажу. Тут конечно не критичные данные. Есть и есть, нет и бог с ними. Но меня заинтересовало именно хранение на этой маленькой платочке в совокупности с веб сервером и точкой доступа. В интернет просто не интересно.
Ну Raspberry Pi слышал, правда вообще никак не рассматривал, да и цена вопроса так на порядок выше. Тут 200 рублей, а там 2000 (ну это так округленно). А что на Android ТВ приставке можно БД хранить?
В ощем еще денек-другой повожусь, попробую найти нормальный англоязычный форум, а там буду JSON пробовать. Хотя конечно с SQL даже и Light работать много удобнее.
 
Сверху Снизу