Не могу прочитать данные json esp 32 ошибка «parseObject() failed»

c++ esp32 json java

привет, я просто пытаюсь сделать счетчик подписки на Youtube со светодиодной матрицей 32 * 8 и esp 32, и у меня возникла эта проблема, когда я пытался получить подписчиков для подсчета так в чем проблема и как я могу это исправить? `

  ```    //######################## Отображение счетчика подписчиков YouTube на светодиодной матрице ######## ######################
        // Получает и отображает статистику канала YouTube
        //################# БИБЛИОТЕКИ #################
        String version = "v1.0";       // Версия этой программы
        
    #include <WiFi.h>
    #include <WiFiClientSecure.h>
    #include <ArduinoJson.h>     // https://github.com/bblanchon/ArduinoJson
    #include <SPI.h>
    #include <Adafruit_GFX.h>
    #include <Max72xxPanel.h>    // https://github.com/markruys/arduino-Max72xxPanel
    #include <time.h>
    //################ ПЕРЕМЕННЫЕ #################
    // Используйте свой собственный ключ API, зарегистрировав бесплатную учетную запись разработчика Youtube на http://www.youtube.com
    // Вывод светодиодной матрицы -> Пин ESP32
    // Вкк-> 3в
    // Земля -> Земля
    // ДИН-> Пин MOSI может использовать результаты оператора печати 23
    // КС-> SS pin использовать результаты оператора печати 5, возможно
    // CLK-> Может быть, вывод SCK использует результаты оператора печати 18.
    
    const char* channelId = "UCqTSLaEj9c4hiZkU0FfbaJA"; // Посмотрите информацию о вашем канале, нажмите на значок своего канала в правом верхнем углу, затем «Настройки», затем «Дополнительно»
    const char* apiKey    = "A--------------Aw"; // См. https://developers.google.com/youtube/v3/getting-started для ключа API, вы должны включить его, чтобы он работал!
    const char* host      = "https://www.googleapis.com";
    unsigned long lastConnectionTime = 0;                 // Время последнего подключения к серверу в миллисекундах
    const unsigned long  postingInterval = 10L*60L*1000L; // Задержка между обновлениями в миллисекундах, вы должны ограничить количество запросов YouTube в день максимум
    
    //################ ПРОГРАММНЫЕ ПЕРЕМЕННЫЕ и ОБЪЕКТЫ #################
    int pinCS = 5; // Прикрепите CS к этому контакту, DIN к MOSI и CLK к SCK (см. http://arduino.cc/en/Reference/SPI)
    int numberOfHorizontalDisplays = 4;
    int numberOfVerticalDisplays   = 1;
    int wait   = 35; // В миллисекундах
    int spacer = 1;
    int width  = 5 + spacer; // Ширина шрифта 5 пикселей
    int port   = 443;
    String time_str;
    
    Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays);
    
    struct channelStatistics{
      long viewCount;
      long commentCount;
      long subscriberCount;
      bool hiddenSubscriberCount;
      long videoCount;
    };
    
    // Измените свои учетные данные WiFi
    const char* ssid     = "SSid";
    const char* password = "PASS";
    
    channelStatistics channelStats;
    
    void setup() {
      Serial.begin(115200); // инициализируем последовательную связь
      Serial.println("Mosi="+String(MOSI));
      Serial.println("SS="+String(SS));
      Serial.println("SCK="+String(SCK));
      StartWiFi(ssid,password);
      StartTime();
    
      //------------------------------------------------ ----------------------
      configTime(0 * 3600, 0, "pool.ntp.org", "time.nist.gov");
      matrix.setIntensity(0); // Используйте значение от 0 до 15 для яркости
    // Настройте светодиодную матрицу под свои нужды
    // matrix.setPosition(0, 0, 0); // Первый дисплей находится в позиции <0, 0>
    // matrix.setPosition(1, 1, 0); // Второй дисплей находится в позиции <1, 0>
    // matrix.setPosition(2, 2, 0); // Третий дисплей находится в позиции <2, 0>
    // matrix.setPosition(3, 3, 0); // И последний дисплей находится в позиции <3, 0>
    // ...
      matrix.setRotation(0, 1);    // Первый дисплей - позиция повернута
      matrix.setRotation(1, 1);    // Первый дисплей - позиция повернута
      matrix.setRotation(2, 1);    // Первый дисплей - позиция повернута
      matrix.setRotation(3, 1);    // Первый дисплей - позиция повернута
      lastConnectionTime = millis();
      obtain_subscriber_stats();
    }
    
    void loop() {
      display_message("Subs: " + String(channelStats.subscriberCount));
      time_t now = time(nullptr);
      String time = String(ctime(&now));
      time.trim();
      display_message(" on " + time);
      if (millis() - lastConnectionTime > postingInterval) { // 15 минут
        obtain_subscriber_stats();
        lastConnectionTime = millis();
      }
    }
    
    //################ ФУНКЦИИ ПРОГРАММЫ #################
    
    void display_message(String message){ // Прокручиваем изображение влево
      matrix.fillScreen(LOW);
      for ( int i = 0 ; i < width * message.length() + matrix.width() - 1 - spacer; i++ ) {
        int letter = i / width;
        int x = (matrix.width() - 1) - i % width;
        int y = (matrix.height() - 8) / 2; // центрируем текст по вертикали
        while ( x + width - spacer >= 0 && letter >= 0 ) {
          if (letter < message.length()) matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // ВЫСОКИЙ означает, что передний план включен, НИЗКИЙ означает, что фон выключен, НИЗКИЙ< HIGH инвертирует дисплей
          letter--;
          x -= width;
        }
        matrix.write(); // Отправляем растровое изображение для отображения
        delay(wait);
      }
    }
    
    void obtain_subscriber_stats() {
      String command = "https://www.googleapis.com/youtube/v3/channels?part=statistics&id=" + строка (идентификатор канала);
      String response = GetRequestFromYoutube(command);       
      StaticJsonBuffer <200> jsonBuffer;
      JsonObject& root = jsonBuffer.parseObject(response); // Разбираем JSON
      if (!root.success()) {
        Serial.println(F("jsonBuffer.parseObject() failed"));
      }
      else
      {
        
        JsonObject& current                = root["items"][0]["statistics"];  
        long subscriberCount               = current["subscriberCount"];
        long viewCount                     = current["viewCount"];
        long commentCount                  = current["commentCount"];
        long hiddenSubscriberCount         = current["hiddenSubscriberCount"];
        long videoCount                    = current["videoCount"];
        channelStats.viewCount             = viewCount;
        channelStats.subscriberCount       = subscriberCount;
        channelStats.commentCount          = commentCount;
        channelStats.hiddenSubscriberCount = hiddenSubscriberCount;
        channelStats.videoCount            = videoCount;
       
        
      }  
      Serial.println("      View Count = " + String(channelStats.viewCount));
      Serial.println("Subscriber Count = " + String(channelStats.subscriberCount));
        Serial.println(GetRequestFromYoutube(command));
        Serial.println(response);
      // Serial.println(jsonBuffer.parseObject(ответ));
    
    }
    
    String GetRequestFromYoutube(String request) {
      String headers, body = "";
      bool Headers    = false;
      bool currentLineIsBlank = true;
      int  MessageLength = 1000;
      // Соединяемся с youtube API через ssl
      WiFiClientSecure client;
      if (client.connect(host, port)) {
        Serial.println(".... connected to server");
        char c;
        int ch_count=0;
        request += "&key=" + String(apiKey);
        request = "GET " + request;
        Serial.println(request);
        client.println(request);
        int now   = millis();
        while (millis()-now < 1500) {
          while (client.available()) {
            char c = client.read();
            if(!Headers){
              if (currentLineIsBlank && c == '\n') {
                Headers = true;
              }
              else{
                headers = headers + c;
              }
            } else {
              if (ch_count < MessageLength)  {
                body = body+c;
                ch_count++;
              }
            }
            if (c == '\n') {
              currentLineIsBlank = true;
            } else if (c != '\r') {
              currentLineIsBlank = false;
            }
          }
        }
      }
      return body;
    }
    
    ////////////// Wi-Fi, функции времени и даты //////////////////
    int StartWiFi(const char* ssid, const char* password) {
      int connAttempts = 0;
      Serial.print(F("\r\nConnecting to: ")); Serial.println(String(ssid));
      WiFi.begin(ssid, password);
      while (WiFi.status() != WL_CONNECTED ) {
        delay(500); Serial.print(".");
        if (connAttempts > 20) {
          Serial.println("\nFailed to connect to a Wi-Fi network");
          return -5;
        }
        connAttempts++;
      }
      Serial.print(F("WiFi connected at: "));
      Serial.println(WiFi.localIP());
      return 1;
    }
    
    void StartTime(){
      configTime(0, 0, "0.uk.pool.ntp.org", "time.nist.gov");
      setenv("TZ", "GMT0BST,M3.5.0/01,M10.5.0/02",1); // Изменить для вашего местоположения
      UpdateLocalTime();
    }
    
    void UpdateLocalTime(){
      struct tm timeinfo;
      while (!getLocalTime(&timeinfo)){
        Serial.println("Failed to obtain time");
      }
      //См. http://www.cplusplus.com/reference/ctime/strftime/
      Serial.println(&timeinfo, "%a %b %d %Y   %H:%M:%S"); // Отображает: суббота, 24 июня 2017 г., 14:05:49
      char output[50];
      strftime(output, 50, "%a %d-%b-%y  (%H:%M:%S)", &timeinfo);
      time_str = output;
    }
    ```

, 👍1

Обсуждение

почему вы не предоставляете всю информацию? ... Я совершенно уверен, что сообщение об ошибке длиннее, чем parseObject() failed, @jsotola

это полная проблема, если вы прочитаете код, вы найдете это, если статус `JsonObject& root = jsonBuffer.parseObject(response); // Разбираем JSON если (!root.success()) { Serial.println(F("Ошибка jsonBuffer.parseObject()")); }` он просто печатает это сообщение в последовательном мониторе, @ abdalrahmanabs

распечатайте содержимое и посмотрите на byre json. Вероятно, он либо слишком длинный, либо слишком умещается в 200 байт, либо форматирование нарушено., @Sim Son


1 ответ


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

0

В документации для ArduinoJson 5 перечислены причины, по которым parseObject() может возвращать false:

  1. Введен недопустимый формат JSON.
  2. StaticJsonBuffer слишком мал
  3. Слишком большой StaticJsonBuffer (переполнение стека)
  4. DynamicJsonBuffer не удается выделить память
  5. Вы вызвали parseObject() вместо parseArray()
  6. Ограничение вложенности слишком низкое.

Взглянув на ваш код, можно предположить, что проблема номер 2: StaticJsonBuffer очень маленький. Действительно, я не знаю, как выглядит ввод, но 200 байт, вероятно, слишком мало для хранения результата.

Вы можете использовать ArduinoJson Assistant, чтобы вычислить необходимую емкость для JsonBuffer. Не забудьте переключиться на DynamicJsonBuffer, если он станет больше 4 КБ.< /p>

Наконец, я настоятельно рекомендую вам перейти на ArduinoJson 6, потому что он предлагает больше функций, лучшую производительность, лучшую память. использование и улучшенные отчеты об ошибках при одинаковом размере кода и переносимости.

,