Чтение файла json из SPIFFS и отображение содержащейся в нем информации на встроенной веб-странице

esp8266 json

Я работаю над интеллектуальным ИК-приемником, который считывает ИК-сигнал, декодирует его и сохраняет эту декодированную информацию в файле json, хранящемся в SPIFFS NodeMCU. Затем эта информация отображается на встроенном веб-сервере в виде таблицы.

Теперь моя проблема заключается в том, что, хотя я правильно сохраняю информацию о сигнале в файле json (и когда я пытаюсь распечатать его в консоли, он выглядит идеально), файл сына не передается правильно на мой веб-сервер, и таблица остается пустой. Я использую jQuery для чтения файла и внесения изменений в HTML. Все файлы веб-сервера (HTML, css и JavaScript) были сначала протестированы на моем локальном компьютере с помощью примера файла Json той же структуры, что и на моем SPIFFS, поэтому я точно знаю, что проблема не в нем.

Стоит отметить, что я столкнулся с этой проблемой при разработке на своем локальном компьютере, где таблица оставалась пустой, хотя файла json не было, но она была исправлена, когда я использовал расширение Live Server в VSCode. Однако я не понимаю, является ли это проблемой, почему нет сервера для передачи файла json, когда все файлы моего веб-интерфейса правильно передаются и загружаются из SPIFFS.

Я включу часть своего кода, и, конечно же, буду признателен за любую помощь.

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WiFiMulti.h> 
#include <ESP8266mDNS.h>
#include <ESP8266WebServer.h>
#include <Arduino.h>
#include <IRremoteESP8266.h>
#include <IRrecv.h>
#include <IRutils.h>
#include<FS.h>   // Подключаем библиотеку SPIFFS
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>

ESP8266WiFiMulti wifiMulti;     // Создаем экземпляр класса ESP8266WiFiMulti с именем 'wifiMulti'

ESP8266WebServer server(80);    // Создаем объект веб-сервера, который прослушивает HTTP-запрос на порту 80

String getContentType(String filename); // преобразовать расширение файла в тип MIME
bool handleFileRead(String path);       // отправляем нужный файл клиенту (если он существует)

// Объявление переменной для хранения размера объекта JSON
//постоянная емкость size_t = JSON_OBJECT_SIZE(10);

// Создание документа JSON для хранения записи сигнала
//DynamicJsonDocument doc(capacity);

// Объявление размера массива
const size_t array_capacity = JSON_ARRAY_SIZE(16) + JSON_OBJECT_SIZE(1) + 16*JSON_OBJECT_SIZE(9);

// Создание документа JSON для хранения всех записей сигналов во вложенном массиве
DynamicJsonDocument array_doc(array_capacity);

// Создание вложенного массива JSON для хранения всех записей сигналов
JsonArray signals = array_doc.createNestedArray("signals");

// Объявление объекта JSON для хранения одной записи сигнала
JsonObject signal_entry;

// Объявление метода, который сохраняет объект JSON в файл JSON, хранящийся на SPIFFS
void saveJSON();

// Объявление метода, который печатает JSON-файл, хранящийся на SPIFFS
void printJSON();

void setup(void){
  Serial.begin(115200);         // Запуск последовательной связи для отправки сообщений на компьютер
  delay(10);
  Serial.println('\n');

  Serial.println("Connecting ...");
  int i = 0;
  while (wifiMulti.run() != WL_CONNECTED) { // Подождите, пока сеть Wi-Fi подключится: просканируйте сети Wi-Fi и подключитесь к самой мощной из указанных выше сетей
    delay(250);
    Serial.print('.');
  }

SPIFFS.begin();                           // Запуск файловой системы SPI Flash
   
  server.begin();                           // Собственно запускаем сервер
  Serial.println("HTTP server started");

  server.onNotFound([]() {                              // Если клиент запрашивает любой URI
    if (!handleFileRead(server.uri()))                  // отправить его, если он существует
      server.send(404, "text/plain", "404: Not Found"); // в противном случае ответ с ошибкой 404 (Not Found)
  });

void loop(void){
  server.handleClient();                    // Слушаем HTTP-запросы от клиентов

//Создание объекта JSON из документа JSON
    signal_entry = signals.createNestedObject();

    //Присвоение правильных значений ключам в объекте JSON
    signal_entry["date"] = currentDate;
    signal_entry["protocol_type"] = protocol_type;
    signal_entry["bitNr_device"] = bitNr_device;
    signal_entry["bitNr_op"] = bitNr_op;
    signal_entry["codeDec_device"] = codeDec_device;
    signal_entry["codeDec_op"] = codeDec_op;
    signal_entry["codeHex_device"] = codeHex_device;
    signal_entry["codeHex_op"] = codeHex_op;
    signal_entry["codeBin_device"] = codeBin_device;
    signal_entry["codeBin_op"] = codeBin_op;
    
    serializeJsonPretty(signal_entry, Serial); 
    Serial.println("");
    
    saveJSON();
   }
}

String getContentType(String filename) { // преобразовать расширение файла в тип MIME
  if (filename.endsWith(".html")) return "text/html";
  else if (filename.endsWith(".css")) return "text/css";
  else if (filename.endsWith(".js")) return "application/javascript";
  else if (filename.endsWith(".ico")) return "image/x-icon";
  return "text/plain";
}

bool handleFileRead(String path) { // отправляем нужный файл клиенту (если он существует)
  Serial.println("handleFileRead: " + path);
  if (path.endsWith("/")) path += "index.html";         // Если запрашивается папка, отправляем индексный файл
  String contentType = getContentType(path);            // Получаем MIME-тип
  if (SPIFFS.exists(path)) {                            // Если файл существует
    File file = SPIFFS.open(path, "r");                 // Открой это
    size_t sent = server.streamFile(file, contentType); // И отправляем клиенту
    file.close();                                       // Затем снова закрываем файл
    return true;
  }
  Serial.println("\tFile Not Found");
  return false;                                         // Если файл не существует, возвращаем false
}

void saveJSON(){
  File jsonFile = SPIFFS.open("signals.json", "w");
  if (serializeJsonPretty(array_doc, jsonFile) == 0) {
    Serial.println("Failed to write to file");
  }
  jsonFile.close();
}

void printJSON(){
  uint8_t* pBuffer;
  File testFile = SPIFFS.open("signals.json", "r");
  if(testFile){
    unsigned int fileSize = testFile.size();
    pBuffer = (uint8_t*)malloc(fileSize + 1);
    testFile.read(pBuffer, fileSize);
    pBuffer[fileSize] = '\0';
    Serial.println((char*)pBuffer);                // Печатаем файл на последовательный монитор.
    testFile.close();
  }
  else{
    Serial.println("Failed to read to file");
  }
  free(pBuffer);
}

, 👍0

Обсуждение

Я думаю, что вы испортили свое копирование и вставку. Ваша функция loop(), кажется, находится в середине вашей функции setup()., @Majenko

Похоже, вы запускаете веб-страницу на своем ПК, но получаете json из ESP. Браузерам это не нравится, так как это своего рода межсайтовый скриптинг. Это может работать, если ESP также отправляет правильные заголовки разрешений. [Access-Control-Allow-Origin: *](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin), чтобы быть конкретным. Вы также можете открыть консоль разработчика в своем браузере, чтобы увидеть, появляются ли какие-либо ошибки. Также проверьте вкладку сети, чтобы узнать, запрашивается ли json., @Gerben

@Gerben Я не совсем уверен, что понимаю, что вы имеете в виду, моя веб-страница размещена на ESP, и я получаю к ней доступ через IP-адрес, однако в файле JS, связанном с моим HTML (кстати, оба хранятся в SPIFFS) я ищу файл json в той же папке, что и моя веб-страница, в этом проблема? И я проверил инструменты разработчика, да, файл json запрошен, и запрос имеет статус 200 OK., @Mo'men Alaswad

Неважно. Часть расширения VSCode меня сбила с толку, но, видимо, проблема не в этом., @Gerben


1 ответ


1

Помимо несколько странной проблемы с вложенностью loop() внутрь setup() (которую я отнесу к ошибке копирования и вставки), я думаю, что ваша основная проблема заключается в отсутствии типа содержимого.

Предполагается, что функция getContentType() угадывает тип содержимого по расширению имени файла. Однако там нечего обрабатывать файл .json. Таким образом, по умолчанию будет использоваться text/plain, который не будет интерпретироваться как данные JSON.

Вам нужно немного добавить, чтобы искать файлы JSON и соответствующим образом установить тип содержимого:

...
} else if (filename.endsWith(".json")) {
    return "application/json";
}
,

Я пробовал, но, к сожалению, это не то. В инструментах разработчика браузера запрашивается файл json, и запрос принимается, однако таблица остается пустой, даже если файл json отсутствует., @Mo'men Alaswad

Тогда что-то не так с кодом вашего сайта., @Majenko

попробуйте скопировать ответ и вручную проанализировать его с помощью JSON.parse()., @dandavis