Синтаксический анализ ответа JSON из потока

json esp stream

Я хочу разобрать ответ JSON из запроса GET. Обычно я делаю это с помощью строковой переменной для хранения ответа и последующего анализа этой строки с помощью библиотеки ArduinoJson, как показано ниже:

#include <Arduino.h>
#include "OTA.h"
#include "Credentials.h"
#include <HTTPClient.h>
#include <ArduinoJson.h>

const char url[] = "http://date.jsontest.com/";

HTTPClient getClient;

void getRequest(String &payload)
{
  getClient.begin(url);

  int httpCode = getClient.GET();

  if (httpCode > 0)
  {
    payload = getClient.getString();
    // Serial.print("HTTP Status: ");
    // Serial.println(httpCode);
  }
  else
  {
    Serial.println("Error on HTTP request");
  }
  getClient.end();
}

void parseResponse(String &payload)
{

  StaticJsonDocument<128> doc;

  DeserializationError error = deserializeJson(doc, payload);

  if (error)
  {
    Serial.print("deserializeJson() failed: ");
    Serial.println(error.c_str());
    return;
  }

  const char *time = doc["time"]; // "03:53:25 AM"
  // unsigned long *epoch = doc["milliseconds_since_epoch"]; // 1362196405309
  const char *date = doc["date"]; // "03-02-2013"

  Serial.println(date);
}

void setup()
{
  setupOTA("ESP-N2", mySSID, myPASSWORD);

  Serial.begin(115200);
}

void loop()
{
  ArduinoOTA.handle();

  unsigned long newTime = millis();
  static unsigned long oldTime = 0;
  String payload;

  if (newTime - oldTime >= 5000)
  {
    oldTime = newTime;
    getRequest(payload);
    parseResponse(payload);
    Serial.println();
  }
}

Я хочу избежать использования String и ArduinoJson offician reference page упоминает, что можно десериализовать непосредственно из входного потока, например, WiFiClient, ethernetclient или serial, но я не смог найти ни одного примера, показывающего его использование. Поэтому мне любопытно узнать, как им пользоваться.

Исходя из моего базового понимания потока, я полагаю, что мне нужно определить буфер или ячейку памяти, которая будет содержать входящие байты и, используя адрес этого буфера, должна считывать данные по битам. Так нужно ли мне делать что-то вроде этого:

char buffer[]= httpClient.getStream();

а затем передать этот буфер в качестве входных данных в функцию десериализации? или я совершенно неправильно понял?

, 👍0

Обсуждение

https://arduinojson.org/v6/how-to/use-arduinojson-with-httpclient/, @Mat


1 ответ


Лучший ответ:

2

HttpClient.GetStream() возвращает экземпляр Stream, который можно передать в deserializeJson(), например:

deserializeJson(doc, httpClient.getStream());

Однако, поступая таким образом, вы обходите код в HttpClient, который обрабатывает фрагментированную кодировку передачи, поэтому вы должны вызвать HttpClient.useHTTP10(true) перед вызовом GET, чтобы убедиться, что сервер не вернет фрагментированный ответ.

Смотрите, как использовать ArduinoJson с HttpClient?

,

Большое спасибо за объяснение. Я рад узнать об использовании потока. Это работает хорошо, но я также получаю [D][HttpClient.cpp:378] disconnect(): все еще данные в буфере (1), очистить. [D][HttpClient.cpp:387] disconnect(): tcp stop. Поскольку я читаю все потоковые данные, к каким данным это может относиться? Может ли это вызвать такую проблему, как утечка памяти или фрагментация?, @Zaffresky

Я добавил ChunkedStreamReader в свой StreamLib. он обертывает входной поток и декодирует фрагментированный ввод: https://github.com/jandrassy/StreamLib/blob/b9b31e7908479efd0149940df9de610439532506/examples/Advanced/ReadChunkedJSON/ReadChunkedJSON.ino#L36, @Juraj

Я следовал подходу, упомянутому в документации, но кажется, что мои запросы GET не работают, когда я использую http1.0. Мой сервер работает на aws (amplify) и использует http2. Что мне делать в этом случае?, @seddouguim