ESPAsyncWebServer обслуживает большой массив из оперативной памяти - PullRequest
2 голосов
/ 02 мая 2020

Я пытаюсь обслуживать большой массив с плавающей запятой с 8192 значениями из кучи ESP32 с помощью библиотеки ESPAsyncWebServer для ArduinoIDE. Μ C - это ESP32 devkit c, и я хочу получить доступ к массиву с помощью браузера. Вот код для массива:

#include "AsyncJson.h"
#include "ArduinoJson.h"
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

#define SAMPLES 8192

static float * vReal;

void setup() {
  vReal = (float *) malloc(SAMPLES * sizeof(float));
  assert(vReal != NULL);
}

void loop() {
  //Put something into the array
  for (int i = 0; i < SAMPLES; i++)
  {
    vReal[i] = 1.1;
  }
}

В данный момент я использую «Arduino Json Basi c Response» и отправляю большой массив частями из 512 значений. С 1024 значениями я получаю переполнение стека в задаче async_tcp, если я пытаюсь получить доступ к массиву через браузер, поэтому я установил его на 512 значений. Вот код для этого:

server.on("/array1", HTTP_GET, [](AsyncWebServerRequest * request) {
AsyncResponseStream *response = request->beginResponseStream("application/json");
const size_t CAPACITY = JSON_ARRAY_SIZE(512); //Compute size of array
StaticJsonDocument<CAPACITY> vRealPart;
JsonArray array = vRealPart.to<JsonArray>();
for (int i = 0; i < 512; i++)
{
  vRealPart.add(vReal[i]);
}
serializeJson(vRealPart, *response); //Print to HTML
request->send(response);
});

Я делаю это 16 раз, чтобы обслуживать весь массив. Позже я вызываю пути "/ array1", "/ array2", "/ array3" ... с помощью JavaScript и анализирую JSON. Это вывод, если один из путей вызывается в веб-браузере:

[0.334593,0.427480,0.181299,0.066654,0.271184,0.356220,0.374454,0.235625,...]

Это работает до сих пор большую часть времени, но я думаю, что это очень затянуто. Было бы неплохо, если бы существовал только один путь со всем массивом. Он работает с файлом stati c из SPIFFS, например:

server.serveStatic("/jsonArray1", SPIFFS, "/jsonArray1");

Но для записи всего массива в fla sh требуется много времени. Хотя чтение действительно быстрое.

Я также попробовал «Arduino Json Advanced Response», но я не смог заставить его работать с JsonArray. К сожалению, примеры на странице GitHub из ESPAsyncWebServer для Arduino Json устарели, поскольку они немного изменили синтаксис в новой версии (v6).

В двух словах: Каков наилучший способ обслуживания таких большие массивы из кучи ESP32 с библиотекой ESPAsyncWebServer? Цель состоит в том, чтобы обработать массив позже с помощью JavaScript в веб-браузере.

Спасибо за вашу помощь!

Bentiedem

PS: Если это поможет: я делаю БПФ с библиотекой arduinoFFT от тока двигателя. Поэтому я делаю AD C и сохраняю 16384 значения из аналого-цифрового преобразователя в массив. Этот массив передается в библиотеку FFT. На выходе получается массив с 8192 значениями. Этот результат находится в куче и должен быть перенесен в мой веб-интерфейс для отображения результата. Я хочу сохранить массивы в оперативной памяти для скорости. Для каждого измерения вы получаете массив результатов с 8192 значениями.

1 Ответ

0 голосов
/ 02 мая 2020

Вот предложение, как вы можете использовать массивы, скомпилированные в fla sh:

const uint16_t SAMPLESPERSEND = 8196;
const uint8_t SAMPLESNUMSIZE = 8; // as your nums are 0.271184 so 8 chars

float myMeasureVals [SAMPLESPERSEND];
char myValueArray[SAMPLESPERSEND * (SAMPLESNUMSIZE + 1) + 2 + 1] = {'\0'};
char numBufferArray[SAMPLESNUMSIZE + 1] = {'\0'}; // Converter helper array

, затем вы добавляете с этим кодом значения

server.on("/array", HTTP_GET, [](AsyncWebServerRequest * request) {
AsyncResponseStream *response = request->beginResponseStream("application/json");
  strcpy (myValueArray, "[");
  for (uint16_t i = 0; i < SAMPLESPERSEND; i++) {
    if (i!=0) strcat (myValueArray, ",");
    // float myTempValue = function2GetValues(); // direct froma function
    float myTempValue = myMeasureVals [i];
    // dtostrf(floatvar, StringLengthIncDecimalPoint, numVarsAfterDecimal, charbuf);
    dtostrf(myTempValue, 2, 6, numBufferArray);
    strcat (myValueArray, numBufferArray);
  }
  strcat (myValueArray, "]");
  myValueArray [strlen(myValueArray)] = '\0'; // terminate correct
  Serial.println(myValueArray);  // Only debug
 request->send(myValueArray);
  myValueArray[0] = '\0';  // empty array for next part
});

Код компилируется, не проверял отправку может быть обработан таким образом или должен использоваться метод chunked. Обычно я использую такие большие массивы только при настройке и чтении из FileSystem. Обработка здесь та же, что и у Arduino Json, но только с несколькими строками кода и без фрагментации кучи, если вам нужно долго и стабильно работающее приложение.
EDIT
Мои предпочтения Решением будет постоянная запись в файл в SPIFFS (см. пример регистратора данных SD или этот пост ) и обслуживание файла. Для ~ 10.000 значений это самый чистый метод. Как добавить скобки и запятые, показано в приведенном выше коде, поэтому содержимое этого файла - один большой JSON, который можно быстро обработать с помощью javascript. И, например, используя 10 различных файлов журнала, вы можете восстановить данные в случае сетевых ошибок или аналогичных действий

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...