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

ESP8266 и sqlite3

EvgeniyS

Member
Вот я о чем. Вот скажем массив:
Код:
[{"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}]
Ну это первые 2 записи. Потом соответственно случается 57 минута и надо все то же с новыми показателями датчиков записать.
Так я правильно понимаю, что надо взять файл, распарсить его, получить переменную скажем array, добавить в нее новый элемент и записать в файл? Все у меня получается кроме последнего действия.
Чтобы просто добавить запись в файл не обязательно его парсить, можно взять данные, серилизовать в JSON строку, открыть файл и дописать в него.
 

EvgeniyS

Member
Вот я о чем. Вот скажем массив:
Код:
[{"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}]
Вот именно, у вас массив а в коде ниже вы парсите объект.
 
Ну вот инфа в файле у меня скажем в таком виде хранится.
Вот я считал данные из файла:
Код:
  String fileData = readFile("2.json");
  char dataJson[fileData.length() + 1];
  strcpy(dataJson, fileData.c_str());
Мне нужно:
1. Скажем построить табличку по этим данным. Ну или график. Т.е. мне нужно вытащить из этой строки показания и в столбцы вставить.
2. Добавить такую же строку в массив. Ну с этим я пока не занимался. Не разбирался точнее.
С буфером я поработал как в вашей ссылке. Я понимаю там надо функцию отдльную делать, т.к. число данных будет менятся. ну пока для конкретного случая. Получился буфер 512. Но все равно пустые значения.
 

EvgeniyS

Member
Но все равно пустые значения.
У вас в файле массив с 2 объектами а вы пытаетесь парсить объект.
Скажем построить табличку по этим данным. Ну или график. Т.е. мне нужно вытащить из этой строки показания и в столбцы вставить.
Я бы сделал веб морду, отправлял туда файл по вебсокету или еще как-нибудь, и таблицы\графики рисовал на клиенте, благо javascript работает с JSON "из коробки".
 
У вас в файле массив с 2 объектами а вы пытаетесь парсить объект.
Да, я понимаю, что что-то не то делаю. Но никак не вьеду где массив с объектами, а где объект с массивом. А как тогда надо читать эту строку?
Хотя идея с тем, чтобы разобрать его в веб морде хорошая. попробую. И все же ради интереса и на будущее, можно как-то прочитать такую строку из файла и разобрать ее в скетче?
 

EvgeniyS

Member
Да, я понимаю, что что-то не то делаю. Но никак не вьеду где массив с объектами, а где объект с массивом. А как тогда надо читать эту строку?
{ } - объект, [ ] - массив, соотвественно:
JSON:
[{"param1":0,"param2":2},{"param1":0,"param2":2}]
- это массив, содержащий 2 объекта
JSON:
{[1,2,3],[3,2,1]}
- это объект, содержащий 2 массива.
 
Спасибо! Тоже потихоньку въезжать стал. Наверное все-таки я правильно сразу данные построил. Нужен мне массив с объектами. И эти объекты будут добавляться.
Ну а все же в скетче можно как-то прочитать такой массив и разобрать по значениям?
 

EvgeniyS

Member
Ну а все же в скетче можно как-то прочитать такой массив и разобрать по значениям?
Ну так я давал ссылку где байтики для JSON считаются, опуститесь чуть ниже, там генерируются готовые примеры по серилизации\десериализации, подставляйте свои переменные и вуаля.
 
Ну так я давал ссылку где байтики для JSON считаются, опуститесь чуть ниже, там генерируются готовые примеры по серилизации\десериализации, подставляйте свои переменные и вуаля.
Я их видел, но как-то странно там писалось. Там получается для каждого объекта своя переменная. Я думал можно как-то с одной переменной и нуменрацией. Как если в браузере такой файл открыть, там первый объект имеет индекс 0, второй 1 и я думал можно так и обращаться. Просто ведь число объектов будет неизвестно и создать переменную с индексом можно, а кучу переменных, не зная сколько их. Не знаю. ВОт так как получилось:
Код:
JsonObject& root_0 = root[0];
int root_0_cyear = root_0["cyear"]; // 2021
int root_0_cmonth = root_0["cmonth"]; // 12
int root_0_cday = root_0["cday"]; // 31
int root_0_chour = root_0["chour"]; // 23
int root_0_cmin = root_0["cmin"]; // 55
float root_0_tin = root_0["tin"]; // 28.5
float root_0_tout = root_0["tout"]; // -13.6
float root_0_vlagn = root_0["vlagn"]; // 13.5
float root_0_davl = root_0["davl"]; // 745.6

JsonObject& root_1 = root[1];
int root_1_cyear = root_1["cyear"]; // 2021
int root_1_cmonth = root_1["cmonth"]; // 12
int root_1_cday = root_1["cday"]; // 31
int root_1_chour = root_1["chour"]; // 23
int root_1_cmin = root_1["cmin"]; // 56
float root_1_tin = root_1["tin"]; // 28.3
float root_1_tout = root_1["tout"]; // -13.2
float root_1_vlagn = root_1["vlagn"]; // 13.3
float root_1_davl = root_1["davl"]; // 745.5
 

EvgeniyS

Member
Как если в браузере такой файл открыть, там первый объект имеет индекс 0, второй 1 и я думал можно так и обращаться.
Так и тут тоже самое, что мешает создать массив структур и туда записывать данные?
 

EvgeniyS

Member
Я их видел, но как-то странно там писалось. Там получается для каждого объекта своя переменная. Я думал можно как-то с одной переменной и нуменрацией. Как если в браузере такой файл открыть, там первый объект имеет индекс 0, второй 1 и я думал можно так и обращаться. Просто ведь число объектов будет неизвестно и создать переменную с индексом можно, а кучу переменных, не зная сколько их.
Набросал черновой пример:
C++:
struct data_t{
  int param1;
  int param2;
  int param3;
}
data_t jsonData[10];

void parseData()
{
    File myData = SPIFFS.open("myfile.json", "r");
      if (!myData) {
    Serial.printf("Cannot load config file!\n");
    return;
  }
  DynamicJsonBuffer buffer;
  JsonObject& root = buffer.parseArray(myData);
  for(uint8_t i=0; i<root.size(); i++){
    JsonVariant v = root[i].as<const JsonObject&>();
    if(v.success()){
      jsonData[i].param1 = v["param1"].as<int>();
      jsonData[i].param2 = v["param2"].as<int>();
      jsonData[i].param3 = v["param3"].as<int>();
    }
  }
}

parseData();
 
expected initializer before 'jsonData' пишет.
А вот эти параметры должны быть одного типа? Просто что значит требует инициализации? Объявить массив jsonData заранее?
 
С инициализвцией разобрался. Надо точку с запятой после закрвающей скобки структуры поставить. Но теперь вообще выдает:
Error compiling for board NodeMCU 1.0 (ESP-12E Module). При чем никаких ошибок не указывает.
 
Разобрался, там была моя ошибка. Но теперь все один в один и выдает
invalid initialization of reference of type 'ArduinoJson::JsonObject&' from expression of type 'ArduinoJson::JsonArray'
 
Изменил
Код:
JsonObject& root = buffer.parseArray(myData);
на
Код:
JsonArray& root = buffer.parseArray(myData);
ошибок не дает. Содержимое файла в текстовом виде читает как раньше, но root.size() выдает равное 0.
 
Набросал черновой пример:
C++:
struct data_t{
  int param1;
  int param2;
  int param3;
}
data_t jsonData[10];

void parseData()
{
    File myData = SPIFFS.open("myfile.json", "r");
      if (!myData) {
    Serial.printf("Cannot load config file!\n");
    return;
  }
  DynamicJsonBuffer buffer;
  JsonObject& root = buffer.parseArray(myData);
  for(uint8_t i=0; i<root.size(); i++){
    JsonVariant v = root[i].as<const JsonObject&>();
    if(v.success()){
      jsonData[i].param1 = v["param1"].as<int>();
      jsonData[i].param2 = v["param2"].as<int>();
      jsonData[i].param3 = v["param3"].as<int>();
    }
  }
}

parseData();
Итак, благодаря вашей помощи довел пример до ума. Пусть теперь на просторах инета будет рабочий пример по распарсиванию JSON файла (такого типа хотя бы как мой). А то сколько искал, не находил ничего.
Код:
#include <ArduinoJson.h>
#include <FS.h>

File fsUploadFile;

DynamicJsonBuffer jsonBuffer;

void setup() {
  Serial.begin(115200);
  delay(5);
  Serial.println("");
  if (!SPIFFS.begin()) {
    Serial.println("Failed to mount SPIFFS");
    return;
  }
  String fileData = readFile("/2.json");
  char dataJson[fileData.length() + 1];
  strcpy(dataJson, fileData.c_str());
  Serial.println(dataJson);
  JsonArray& root = jsonBuffer.parseArray(dataJson);
  for (int i=0; i<root.size(); i++) {
    JsonVariant v = root[i].as<const JsonObject&>();
    if (v.success()) {
      Serial.print(String(v["cday"].as<int>()));Serial.print(".");
      Serial.print(String(v["cmonth"].as<int>()));Serial.print(".");
      Serial.print(String(v["cyear"].as<int>()));Serial.print(" ");
      Serial.print(String(v["chour"].as<int>()));Serial.print(":");
      Serial.println(String(v["cmin"].as<int>()));
      Serial.print("Температура в комнате - ");Serial.println(String(v["tin"].as<float>()));
      Serial.print("Температура на улице - ");Serial.println(String(v["tout"].as<float>()));
      Serial.print("Влажность - ");Serial.println(String(v["vlagn"].as<float>()));
      Serial.print("Давление - ");Serial.println(String(v["davl"].as<float>()));
    }
  }
}

void loop() {
  // put your main code here, to run repeatedly:

}

String readFile(String fileName) {
  File configFile = SPIFFS.open(fileName, "r");
  if (!configFile) {
    return "Failed";
  }
  String temp = configFile.readString();
  configFile.close();
  return temp;
}
Теперь приступаю к добавлению в него новых объектов, а потом будем думать об удалении объектов.
 

EvgeniyS

Member
Пусть теперь на просторах инета будет рабочий пример по распарсиванию JSON файла
Думаю не стоит выкладывать такой пример, хотя бы потому что:
1. Вы используете JsonBuffer как глобальную переменную, чего автор библиотеки крайне не рекомендует.
2. Зачем файл копировать в String, создавая лишние переменные и динамические выделения в памяти? Не проще ли сразу прочитанный файл отправить в парсер?
3. Зачем столько Serial.print(ln)? Можно так:
C++:
Serial.printf("Температура в комнате -  %f\n",v["tin"].as<float>());
 
Думаю не стоит выкладывать такой пример, хотя бы потому что:
1. Вы используете JsonBuffer как глобальную переменную, чего автор библиотеки крайне не рекомендует.
2. Зачем файл копировать в String, создавая лишние переменные и динамические выделения в памяти? Не проще ли сразу прочитанный файл отправить в парсер?
3. Зачем столько Serial.print(ln)? Можно так:
C++:
Serial.printf("Температура в комнате -  %f\n",v["tin"].as<float>());
Да, по поводу глобальной переменной согласен. Это откуда-то из других скетчей вылезло.
А парсение файла не заработало. Массив получался нулевой. А вот как только я строку подставил, сразу сработало.
По поводу Serial.print это судя по всему от безграмотности. Но это я не сам придумал, так в примерах еще когда я только начинал все делали.
 

EvgeniyS

Member
А парсение файла не заработало. Массив получался нулевой. А вот как только я строку подставил, сразу сработало.
Странно, у меня работает (причем уже в готовых проектах).
Но это я не сам придумал, так в примерах еще когда я только начинал все делали.
Вот поэтому и не стоит выкладывать в инет, чтобы другие не копипастили. ;)
 
Сверху Снизу