Парсинг данных с Open Meteo через HTTPClient и ArduinoJson

Возникла проблема с парсингом данных о погоде с Open Meteo на esp32s3

Обновляю данные через weather_task каждые 5 мин , при последовательном http запросе на втором http возникает ошибка

[  1571][I][weather_task.cpp:62] weather_task(): [weather_task] current weather API: http://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&current=temperature_2m,dew_point_2m,relative_humidity_2m,apparent_temperature,is_day,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m,uv_index&timeformat=unixtime&timezone=auto
[  1799][E][WiFiClient.cpp:517] flush(): fail on fd 48, errno: 11, "No more processes"
Current weather data обновлены
[  1808][I][weather_task.cpp:88] weather_task(): [weather_task] daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto
Free Heap: 188168
[  2021][E][weather_task.cpp:96] weather_task(): [weather_task] deserializeJson() failed: InvalidInput

если использовать один запрос неважно какой , то все нормально данные обновляются .

#include <Arduino.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <time.h>
#include "core.h"
#include "open_meteo.h"
#include "config.h"

static const char* TAG = "weather_task";

// Координаты 
const String latitude  = "55.783640";
const String longitude = "37.458337";

// URL для получения текущих данных: 
static const char *WEATHER_URL_CURRENT = 
        "http://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "current=temperature_2m,dew_point_2m,relative_humidity_2m,apparent_temperature,"
        "is_day,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m,uv_index&"
        "timeformat=unixtime&timezone=auto";

static const char *WEATHER_URL_HOURLY =
        "https://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "hourly=temperature_2m,dew_point_2m,precipitation_probability,rain,showers,snowfall,"
        "wind_speed_10m,wind_gusts_10m,sunshine_duration,cloud_cover,is_day&"
        "timeformat=unixtime&timezone=auto&forecast_days=3";

static const char *WEATHER_URL_DAILY =
        "https://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "daily=temperature_2m_max,temperature_2m_min,"
        "daylight_duration,sunshine_duration,"
        "rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,"
        "wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&"
        "timeformat=unixtime&timezone=auto";

extern SemaphoreHandle_t mutex;

void weather_task(void *pvParameter){

current_weather_data_t current_data = {0};
hourly_weather_data_t hourly_data[48] = {0};
daily_weather_data_t daily_data[7] = {0};

char url[512];

// флаг обновления данных
bool current_success = false;
bool hourly_success = false;
bool daily_success = false;

  for (;;) {

    HTTPClient http;

    // ------- current data -------
    sprintf(url, WEATHER_URL_CURRENT, latitude.c_str(), longitude.c_str());
    ESP_LOGI(TAG, "current weather API: %s", url);
    http.begin(url);
    
    if (http.GET() > 0) {
      JsonDocument doc;
      DeserializationError error = deserializeJson(doc, http.getString());
      if (error) {
        ESP_LOGE(TAG, "deserializeJson() failed: %s", error.c_str());
      } else {  
        current_data.temperature_2m = doc["current"]["temperature_2m"];
        current_data.is_day = doc["current"]["is_day"]; 
        current_data.weather_code = doc["current"]["weather_code"]; 
        current_data.cloud_cover = doc["current"]["cloud_cover"];
        current_data.uv_index = doc["current"]["uv_index"];
        current_data.wind_direction_10m = doc["current"]["wind_direction_10m"];
        current_data.wind_speed_10m = doc["current"]["wind_speed_10m"];
        current_data.wind_gusts_10m = doc["current"]["wind_gusts_10m"];

        current_success = true;
        Serial.println("Current weather data обновлены");
      }   
    }
    http.end();   

 
// ------- Daily data -------
    sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());
    ESP_LOGI(TAG, "daily weather API: %s", url);
    http.begin(url);

    if (http.GET() > 0) {
      JsonDocument doc;
      Serial.print("Получено: ");
      Serial.println(http.getString()); 
     // doc.clear();
      DeserializationError error = deserializeJson(doc, http.getString());

      if (error) {
        ESP_LOGE(TAG, "deserializeJson() failed: %s", error.c_str());
      } else {  
        for (int i = 0; i < NUM_DAYS; i++) {
          daily_data[i].time = doc["daily"]["time"][i];
          daily_data[i].weather_code = doc["daily"]["weather_code"][i];
          daily_data[i].sunrise = doc["daily"]["sunrise"][i];
          daily_data[i].sunset = doc["daily"]["sunset"][i]; 
          daily_data[i].rain_sum = doc["daily"]["rain_sum"][i]; 
  
          daily_success = true;
          ESP_LOGI(TAG, "Daily weather data обновлены");
        }
      }   
    }
    http.end();   

    if (current_success) { 
 // if (current_success && hourly_success && daily_success) {
        ESP_LOGI(TAG, "Все данные пришли");
        xSemaphoreTake(mutex, portMAX_DELAY);
        disp_weather(&current_data, hourly_data, daily_data);
        xSemaphoreGive(mutex);
    } else {
        ESP_LOGW(TAG, "данные не обновлены (current:%d, hourly:%d, daily:%d)",
                 current_success, hourly_success, daily_success);
    }
    

     // сброс флага для обновления
    current_success = false; 
    hourly_success = false;
    daily_success = false;
            
    vTaskDelay(1000 * 60 * 5 / portTICK_PERIOD_MS); // 10 Min
 }
}

task

xTaskCreatePinnedToCore(
      weather_task,
      "Weather Task",
      16384,
      NULL,
      1,
      NULL,
      1); 

что не так делаю?

проверил что приходит при втором запросе " Serial.println(http.getString());"

какая то хрень)))

[607463][I][weather_task.cpp:88] weather_task(): [weather_task] Call daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto
Free Heap: 189840
Получено: <html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx</center>
</body>
</html>
[607657][W][HTTPClient.cpp:1483] returnError(): error(-4): not connected
[607664][E][weather_task.cpp:98] weather_task(): [weather_task] deserializeJson() failed: EmptyInput

и еще допом появилась ошибка!!!

[  2149][W][HTTPClient.cpp:1483] returnError(): error(-4): not connected

проблема в том, что вы дважды вызываете http.getString() для одного и того же ответа HTTP Первый вызов забирает данные из потока, а второй получает пустую строку, уффф успел, пока все хорошие ответы не разобрали…

не совсем понял а как тогда данные от второго запроса получить не вызывая http.getString() ?

String response = http.getString();

поменял в каждой секции

JsonDocument doc;
String payload = http.getString();
DeserializationError error = deserializeJson(doc, payload);

[302185][I][weather_task.cpp:62] weather_task(): [weather_task] Call current weather API: http://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&current=temperature_2m,dew_point_2m,relative_humidity_2m,apparent_temperature,is_day,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m,uv_index&timeformat=unixtime&timezone=auto
[302390][E][WiFiClient.cpp:517] flush(): fail on fd 48, errno: 11, "No more processes"
Current weather data successfully retrieved
[302396][I][weather_task.cpp:89] weather_task(): [weather_task] Call daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto
Free Heap: 189600
Получено: <html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx</center>
</body>
</html>

[302588][E][weather_task.cpp:100] weather_task(): [weather_task] deserializeJson() failed: InvalidInput

результат тот же первый отрабатывает второй затык какой то , но ушла ошибка

[  2149][W][HTTPClient.cpp:1483] returnError(): error(-4): not connected

не понял вы теперь выполняете 1 раз или по прежнему 2 раза ?
считывайте в строку 1 раз, и работайте со строкой… должно работать…

Serial.println(http.getString()); // <<<< первый вызов
deserializeJson(doc, http.getString());// <<<< второй вызов

один то работает без проблем , мне три последовательно надо делать тк для open meteo три надо daily,current, hourly .

JsonDocument doc;
String payload = http.getString();
Serial.printf("Free Heap: %d\\n", ESP.getFreeHeap());
Serial.print("Получено: ");
Serial.println(payload); 
DeserializationError error = deserializeJson(doc, payload);

там поправил это я смотрю что пришло

последний вариант что пробовал

#include <Arduino.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#include <time.h>
#include "core.h"
#include "open_meteo.h"
#include "config.h"

static const char* TAG = "weather_task";

// Координаты 
const String latitude  = "55.783640";
const String longitude = "37.458337";

// URL для получения текущих данных: 
static const char *WEATHER_URL_CURRENT = 
        "http://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "current=temperature_2m,dew_point_2m,relative_humidity_2m,apparent_temperature,"
        "is_day,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m,uv_index&"
        "timeformat=unixtime&timezone=auto";

static const char *WEATHER_URL_HOURLY =
        "https://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "hourly=temperature_2m,dew_point_2m,precipitation_probability,rain,showers,snowfall,"
        "wind_speed_10m,wind_gusts_10m,sunshine_duration,cloud_cover,is_day&"
        "timeformat=unixtime&timezone=auto&forecast_days=3";

static const char *WEATHER_URL_DAILY =
        "https://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "daily=temperature_2m_max,temperature_2m_min,"
        "daylight_duration,sunshine_duration,"
        "rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,"
        "wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&"
        "timeformat=unixtime&timezone=auto";

extern SemaphoreHandle_t mutex;

void weather_task(void *pvParameter){

current_weather_data_t current_data = {0};
hourly_weather_data_t hourly_data[48] = {0};
daily_weather_data_t daily_data[7] = {0};

char url[512];

// Success flags for tracking if all API calls completed successfully
bool current_success = false;
bool hourly_success = false;
bool daily_success = false;

  for (;;) {

    HTTPClient http;
  //  JsonDocument doc;


    // ------- current data -------
    sprintf(url, WEATHER_URL_CURRENT, latitude.c_str(), longitude.c_str());
    ESP_LOGI(TAG, "Call current weather API: %s", url);
    http.begin(url);
    
    if (http.GET() > 0) {
      JsonDocument doc;
      String payload = http.getString();
      DeserializationError error = deserializeJson(doc, payload);
      if (error) {
        ESP_LOGE(TAG, "deserializeJson() failed: %s", error.c_str());
      } else {  
        current_data.temperature_2m = doc["current"]["temperature_2m"];
        current_data.is_day = doc["current"]["is_day"]; 
        current_data.weather_code = doc["current"]["weather_code"]; 
        current_data.cloud_cover = doc["current"]["cloud_cover"];
        current_data.uv_index = doc["current"]["uv_index"];
        current_data.wind_direction_10m = doc["current"]["wind_direction_10m"];
        current_data.wind_speed_10m = doc["current"]["wind_speed_10m"];
        current_data.wind_gusts_10m = doc["current"]["wind_gusts_10m"];

        current_success = true;
        Serial.println("Current weather data successfully retrieved");
      }   
    }
    http.end();   

    // ------- daily data -------
    sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());
    ESP_LOGI(TAG, "Call daily weather API: %s", url);
    http.begin(url);
    
    if (http.GET() > 0) {
      JsonDocument doc;
      String payload = http.getString();
      Serial.printf("Free Heap: %d\n", ESP.getFreeHeap());
      Serial.print("Получено: ");
      Serial.println(payload); 
      DeserializationError error = deserializeJson(doc, payload);
      if (error) {
        ESP_LOGE(TAG, "deserializeJson() failed: %s", error.c_str());
      } else {  
        current_data.temperature_2m = doc["current"]["temperature_2m"];
        current_data.is_day = doc["current"]["is_day"]; 
        current_data.weather_code = doc["current"]["weather_code"]; 
        current_data.cloud_cover = doc["current"]["cloud_cover"];
        current_data.uv_index = doc["current"]["uv_index"];
        current_data.wind_direction_10m = doc["current"]["wind_direction_10m"];
        current_data.wind_speed_10m = doc["current"]["wind_speed_10m"];
        current_data.wind_gusts_10m = doc["current"]["wind_gusts_10m"];

        current_success = true;
        Serial.println("Current weather data successfully retrieved");
      }   
    }
    http.end();   

    if (current_success) { 
// if (current_success && hourly_success && daily_success) {
        ESP_LOGI(TAG, "All weather data retrieved successfully - updating display");
        xSemaphoreTake(mutex, portMAX_DELAY);
        disp_weather(&current_data, hourly_data, daily_data);
        xSemaphoreGive(mutex);
    } else {
        ESP_LOGW(TAG, "Weather data skipping  (current:%d, hourly:%d, daily:%d)",
                 current_success, hourly_success, daily_success);
    }
    
    //} else {
     //   Serial.printf("HTTP Error code: %d\n", httpCode);
 // }

     // Reset success flags for next iteration
    current_success = false; 
    hourly_success = false;
    daily_success = false;
            
    vTaskDelay(1000 * 60 * 5 / portTICK_PERIOD_MS); // Every 10 Minutes == 144 calls per day}
 }
}

тогда может это поможет)))

void weather_task(void *pvParameter) {
    current_weather_data_t current_data = {0};
    hourly_weather_data_t hourly_data[48] = {0};
    daily_weather_data_t daily_data[7] = {0};
    char url[512];

    for (;;) {
        bool current_success = false;
        bool hourly_success = false;
        bool daily_success = false;

        // ========== 1. CURRENT ЗАПРОС ==========
        HTTPClient http;
        sprintf(url, WEATHER_URL_CURRENT, latitude.c_str(), longitude.c_str());
        ESP_LOGI(TAG, "current weather API: %s", url);
        
        http.useHTTP10(true);
        http.begin(url);
        
        int httpCode = http.GET();
        if (httpCode == 200) {
            // <<<<< СОЗДАНИЕ СТРОКИ payload_current >>>>>
            String payload_current = http.getString();  // ← ЗДЕСЬ создаётся строка занимающая память
            
            Serial.print("Current payload size: ");
            Serial.println(payload_current.length());  // например: 845 байт
            
            JsonDocument doc;
            DeserializationError error = deserializeJson(doc, payload_current);
            
            if (!error) {
                current_data.temperature_2m = doc["current"]["temperature_2m"];
                current_data.is_day = doc["current"]["is_day"];
                current_data.weather_code = doc["current"]["weather_code"];
                current_data.cloud_cover = doc["current"]["cloud_cover"];
                current_data.uv_index = doc["current"]["uv_index"];
                current_data.wind_direction_10m = doc["current"]["wind_direction_10m"];
                current_data.wind_speed_10m = doc["current"]["wind_speed_10m"];
                current_data.wind_gusts_10m = doc["current"]["wind_gusts_10m"];
                current_success = true;
                ESP_LOGI(TAG, "Current weather data обновлены");
            }
        } // <<<<< ЗДЕСЬ УДАЛЯЕТСЯ СТРОКА payload_current (выход из блока if) >>>>>
        
        http.end();
        vTaskDelay(pdMS_TO_TICKS(500));  // задержка между запросами

        // ========== 2. DAILY ЗАПРОС ==========
        sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());
        ESP_LOGI(TAG, "daily weather API: %s", url);
        
        http.begin(url);
        httpCode = http.GET();
        if (httpCode == 200) {
            // <<<<< СОЗДАНИЕ СТРОКИ payload_daily >>>>>
            String payload_daily = http.getString();  // ← ЗДЕСЬ создаётся новая строка
            
            Serial.print("Daily payload size: ");
            Serial.println(payload_daily.length());  // например: 1250 байт
            
            JsonDocument doc;
            DeserializationError error = deserializeJson(doc, payload_daily);
            
            if (!error) {
                for (int i = 0; i < NUM_DAYS && i < 7; i++) {
                    daily_data[i].time = doc["daily"]["time"][i];
                    daily_data[i].temperature_2m_max = doc["daily"]["temperature_2m_max"][i];
                    daily_data[i].temperature_2m_min = doc["daily"]["temperature_2m_min"][i];
                    daily_data[i].sunrise = doc["daily"]["sunrise"][i];
                    daily_data[i].sunset = doc["daily"]["sunset"][i];
                    daily_data[i].rain_sum = doc["daily"]["rain_sum"][i];
                }
                daily_success = true;
                ESP_LOGI(TAG, "Daily weather data обновлены");
            }
        } // <<<<< ЗДЕСЬ УДАЛЯЕТСЯ СТРОКА payload_daily (выход из блока if) >>>>>
        
        http.end();
        vTaskDelay(pdMS_TO_TICKS(500));  // задержка между запросами

        // ========== 3. HOURLY ЗАПРОС ==========
        sprintf(url, WEATHER_URL_HOURLY, latitude.c_str(), longitude.c_str());
        ESP_LOGI(TAG, "hourly weather API: %s", url);
        
        http.begin(url);
        httpCode = http.GET();
        if (httpCode == 200) {
            // <<<<< СОЗДАНИЕ СТРОКИ payload_hourly >>>>>
            String payload_hourly = http.getString();  // ← ЗДЕСЬ создаётся третья строка
            
            Serial.print("Hourly payload size: ");
            Serial.println(payload_hourly.length());  // например: 3200 байт
            
            JsonDocument doc;
            DeserializationError error = deserializeJson(doc, payload_hourly);
            
            if (!error) {
                int hours_to_get = min(48, (int)doc["hourly"]["time"].size());
                for (int i = 0; i < hours_to_get; i++) {
                    hourly_data[i].time = doc["hourly"]["time"][i];
                    hourly_data[i].temperature_2m = doc["hourly"]["temperature_2m"][i];
                    hourly_data[i].precipitation_probability = doc["hourly"]["precipitation_probability"][i];
                }
                hourly_success = true;
                ESP_LOGI(TAG, "Hourly weather data обновлены");
            }
        } // <<<<< ЗДЕСЬ УДАЛЯЕТСЯ СТРОКА payload_hourly (выход из блока if) >>>>>
        
        http.end();

        // Отображаем на дисплее
        if (current_success && daily_success && hourly_success) {
            ESP_LOGI(TAG, "Все данные пришли");
            xSemaphoreTake(mutex, portMAX_DELAY);
            disp_weather(&current_data, hourly_data, daily_data);
            xSemaphoreGive(mutex);
        } else {
            ESP_LOGW(TAG, "данные не обновлены (current:%d, daily:%d, hourly:%d)",
                     current_success, daily_success, hourly_success);
        }
        
        vTaskDelay(pdMS_TO_TICKS(1000 * 60 * 5)); // ждём 5 минут
    }
}

счас попробую

опять проблема с daily , current и hourly все гуд данные записываются как надо и отображаются .

Connecting to WiFi ...
Wi-Fi подключено.
IP адрес: 192.168.1.243
[  1568][I][weather_task.cpp:55] weather_task(): [weather_task] current weather API: http://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&current=temperature_2m,dew_point_2m,relative_humidity_2m,apparent_temperature,is_day,weather_code,cloud_cover,wind_speed_10m,wind_direction_10m,wind_gusts_10m,uv_index&timeformat=unixtime&timezone=auto
Current payload size: 755
[  1759][I][weather_task.cpp:81] weather_task(): [weather_task] Current weather data обновлены
[  2262][I][weather_task.cpp:90] weather_task(): [weather_task] daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto
[  2431][E][WiFiClient.cpp:517] flush(): fail on fd 49, errno: 128, "Socket is not connected"
[  2935][I][weather_task.cpp:123] weather_task(): [weather_task] hourly weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&hourly=temperature_2m,dew_point_2m,precipitation_probability,rain,showers,snowfall,wind_speed_10m,wind_gusts_10m,sunshine_duration,cloud_cover,is_day&timeformat=unixtime&timezone=auto&forecast_days=3
Hourly payload size: 4822
[  4916][I][weather_task.cpp:145] weather_task(): [weather_task] Hourly weather data обновлены
[  4917][W][weather_task.cpp:159] weather_task(): [weather_task] данные не обновлены (current:1, daily:0, hourly:1)

крыша уже едет , взял из порта на всякий случай daily weather API в браузере проверил все приходит .

отдельно взял esp ку для проверки чисто daily все работает .

#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h> 

static const char* TAG = "om_daily";

// Настройки Wi-Fi
const char* ssid = "";
const char* password = "";

// Координаты
const String latitude  = "55.783640";
const String longitude = "37.458337";
const char* TZ_INFO = "MSK-3"; 


struct DailyWeather {
  time_t time;
  time_t sunrise;      // Время восхода
  time_t sunset;       // Время заката
  float temp_min;      // Минимальная температура
  float temp_max;  
};

DailyWeather forecast[7];


void getWeatherData() {

char url[512];

  if (WiFi.status() == WL_CONNECTED) {
    HTTPClient http;
    JsonDocument doc;
   
static const char *WEATHER_URL_DAILY =
        "https://api.open-meteo.com/v1/forecast?"
        "latitude=%s&longitude=%s&"
        "daily=temperature_2m_max,temperature_2m_min,"
        "daylight_duration,sunshine_duration,"
        "rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,"
        "wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&"
        "timeformat=unixtime&timezone=auto";


    sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());
    ESP_LOGI(TAG, "Call daily weather API: %s", url);
    http.begin(url);
    int httpCode = http.GET();

    if (httpCode > 0) {
      String payload = http.getString();
      DeserializationError error = deserializeJson(doc, payload);

      if (!error) {
        JsonObject daily = doc["daily"];
        JsonArray times = daily["time"];
        JsonArray sunrises = daily["sunrise"];
        JsonArray sunsets = daily["sunset"];
        JsonArray tempsmin = daily["temperature_2m_min"];
        JsonArray tempsmax = daily["temperature_2m_max"];

        for (int i = 0; i < 7; i++) {
          forecast[i].time = (time_t)times[i]; 
          forecast[i].sunrise = (time_t)sunrises[i]; 
          forecast[i].sunset = (time_t)sunsets[i]; 
          forecast[i].temp_min = tempsmin[i];
          forecast[i].temp_max = tempsmax[i];
    
          
          Serial.printf("Day %d: Timestamp %ld, TempMin: %.1f, TempMax: %.1f\n", i, (long)forecast[i].time, forecast[i].temp_min, forecast[i].temp_max);

          
        //  Serial.printf("День %d: %s | Восход: %s | Закат: %s | Мин. темп: %.1f\n", 
          //              i+1, forecast[i].date.c_str(), forecast[i].sunrise.c_str(), 
           //             forecast[i].sunset.c_str(), forecast[i].temp_min);
        }
      }
    }
    http.end();
  }
}


void setup() {
  Serial.begin(115200);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi...");
  }
  Serial.println("Connected!");
  
  
  setenv("TZ", TZ_INFO, 1);
  tzset(); 

  getWeatherData();
  
struct tm time_info, sunrise_time, sunset_time; 
char buf1[80], buf2[80], buf3[80];
  
  localtime_r(&forecast[0].time, &time_info);
  strftime(buf1, sizeof(buf1), "%Y-%m-%d %H:%M:%S", &time_info);
  printf("Unix Time: %ld\n", (long)forecast[0].time);
  printf("Local Time: %s\n", buf1);

  localtime_r(&forecast[0].sunrise, &sunrise_time);
  strftime(buf2, sizeof(buf2), "%Y-%m-%d %H:%M:%S", &sunrise_time);
  printf("Unix Time: %ld\n", (long)forecast[0].sunrise);
  printf("Local Time: %s\n", buf2);

  localtime_r(&forecast[0].sunset, &sunset_time);
  strftime(buf3, sizeof(buf3), "%Y-%m-%d %H:%M:%S", &sunset_time);
  printf("Unix Time: %ld\n", (long)forecast[0].sunset);
  printf("Local Time: %s\n", buf3);

}

void loop() {}
Connecting to WiFi...
Connected!
[  1166][I][om_daily_json.ino:59] getWeatherData(): [om_daily] Call daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto
Day 0: Timestamp 1778014800, TempMin: 12.6, TempMax: 24.0
Day 1: Timestamp 1778101200, TempMin: 13.4, TempMax: 28.5
Day 2: Timestamp 1778187600, TempMin: 10.7, TempMax: 19.0
Day 3: Timestamp 1778274000, TempMin: 8.4, TempMax: 12.9
Day 4: Timestamp 1778360400, TempMin: 7.7, TempMax: 12.8
Day 5: Timestamp 1778446800, TempMin: 5.7, TempMax: 14.3
Day 6: Timestamp 1778533200, TempMin: 6.9, TempMax: 22.6
Unix Time: 1778014800
Local Time: 2026-05-06 00:00:00
Unix Time: 1778031358
Local Time: 2026-05-06 04:35:58
Unix Time: 1778087867
Local Time: 2026-05-06 20:17:47

а урл так точно правильно соберётся? Я собираю через строковую переменную

да все нормально собирается , проверено не раз.

вот же в порту он выводится

[  2262][I][weather_task.cpp:90] weather_task(): [weather_task] daily weather API: https://api.open-meteo.com/v1/forecast?latitude=55.783640&longitude=37.458337&daily=temperature_2m_max,temperature_2m_min,daylight_duration,sunshine_duration,rain_sum,showers_sum,snowfall_sum,precipitation_probability_max,wind_speed_10m_max,wind_gusts_10m_max,sunrise,sunset&timeformat=unixtime&timezone=auto

вроде как любую проблему можно решить 10ками способов…
давайте парсить 4 значения, и одно будет не читаемо))) реально ?

создайте больше объектов HTTPClient http;

// Current запрос
http.begin(url);   // используем этот объект
http.end();

// Daily запрос  
http.begin(url);   // снова используем ТОТ ЖЕ объект
http.end();

// Hourly запрос
http.begin(url);   // опять ТОТ ЖЕ объект
http.end();

верно или нет ?

  if (!error) {  
    // ❌ ОШИБКА! Здесь должны быть daily_data, а вы пишете в current_data!
    current_data.temperature_2m = doc["current"]["temperature_2m"];  // <- НЕПРАВИЛЬНО
    current_data.is_day = doc["current"]["is_day"];                 // <- НЕПРАВИЛЬНО
    // ...
    current_success = true;  // <- НЕПРАВИЛЬНО (должно быть daily_success)
  }   
// ------- daily data -------
sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());
ESP_LOGI(TAG, "Call daily weather API: %s", url);
http.begin(url);

if (http.GET() == 200) {  // лучше проверять на 200, а не >0
    JsonDocument doc;
    String payload = http.getString();
    Serial.printf("Free Heap: %d\n", ESP.getFreeHeap());
    Serial.print("Daily response: ");
    Serial.println(payload.substring(0, 200)); // печатаем только начало для отладки
    
    DeserializationError error = deserializeJson(doc, payload);
    if (error) {
        ESP_LOGE(TAG, "deserializeJson() failed: %s", error.c_str());
    } else {
        // ✅ ПРАВИЛЬНОЕ заполнение daily_data
        for (int i = 0; i < NUM_DAYS && i < 7; i++) {
            daily_data[i].time = doc["daily"]["time"][i];
            daily_data[i].temperature_2m_max = doc["daily"]["temperature_2m_max"][i];
            daily_data[i].temperature_2m_min = doc["daily"]["temperature_2m_min"][i];
            daily_data[i].sunrise = doc["daily"]["sunrise"][i];
            daily_data[i].sunset = doc["daily"]["sunset"][i];
            daily_data[i].rain_sum = doc["daily"]["rain_sum"][i];
            daily_data[i].weather_code = doc["daily"]["weather_code"][i]; // если есть
        }
        daily_success = true;  // ✅ ПРАВИЛЬНЫЙ флаг
        Serial.println("Daily weather data successfully retrieved");
    }
} else {
    ESP_LOGE(TAG, "Daily HTTP request failed");
}
http.end();

если не помог, на этом наши полномочия все)))

Даже очень помог , спасибо огромное .

Нашел в чем дело было в Api Daili в конце после выполнения

sprintf(url, WEATHER_URL_DAILY, latitude.c_str(), longitude.c_str());

были КРЯКОЗЯБРЫ тк char url[512] мал оказался , в реальности url Daily был 534 байта

с горем пополам зашел на сайт Open Meneo оказалось что можно получить данные в одном запросе , решил попробовать одним запросом,

увеличил размер char url[1024] ранее так много никогда не выделял , на выходе получил постоянную перегрузку Esp32

странно как то , жалуется типа памяти не хватает . в Task я выделил изначально 16384

xTaskCreatePinnedToCore(
      weather_task,
      "Weather Task",
      16384,
      NULL,
      1,
      NULL,
      1); 

проверил

ESP_LOGI(TAG, "Free: %d байт", (int)uxTaskGetStackHighWaterMark(NULL));

[1234920][I][weather_task.cpp:180] weather_task(): [weather_task] Free: 4912 байт

получается 4912-1024 url остается 3888 , странно как то до char url[900] норм

без всяких тасков ИИ выдал код получающий это:

16:21:30.246 -> --- Запрос погодных данных ---
16:21:30.907 -> Данные получены успешно!
16:21:30.907 -> 
16:21:30.907 -> === ПОГОДНЫЕ ДАННЫЕ ===
16:21:30.907 -> Текущая температура: 16.3°C
16:21:30.941 -> Скорость ветра: 12.6 km/h
16:21:30.941 -> Направление ветра: 340°
16:21:30.941 -> Код погоды: 3 - Пасмурно
16:21:30.941 -> 
16:21:30.941 -> --- Прогноз на ближайшие 12 часов ---
16:21:30.941 -> 00:00: 8.6°C, Влажность: 66%, Ветер: 5.0 km/h
16:21:30.941 -> 01:00: 8.0°C, Влажность: 67%, Ветер: 4.7 km/h
16:21:30.941 -> 02:00: 7.8°C, Влажность: 70%, Ветер: 4.6 km/h
16:21:30.974 -> 03:00: 7.4°C, Влажность: 74%, Ветер: 4.5 km/h
16:21:30.974 -> 04:00: 7.2°C, Влажность: 77%, Ветер: 4.4 km/h
16:21:30.974 -> 05:00: 7.2°C, Влажность: 77%, Ветер: 4.0 km/h
16:21:30.974 -> 06:00: 7.9°C, Влажность: 78%, Ветер: 4.5 km/h
16:21:30.974 -> 07:00: 9.5°C, Влажность: 73%, Ветер: 3.9 km/h
16:21:30.974 -> 08:00: 11.7°C, Влажность: 65%, Ветер: 2.9 km/h
16:21:30.974 -> 09:00: 13.4°C, Влажность: 62%, Ветер: 7.2 km/h
16:21:31.006 -> 10:00: 14.6°C, Влажность: 58%, Ветер: 8.4 km/h
16:21:31.006 -> 11:00: 15.5°C, Влажность: 54%, Ветер: 9.4 km/h
16:21:31.006 -> 
16:21:31.006 -> --- Информация о местоположении ---
16:21:31.006 -> Координаты: 44.2500, 42.0625
16:21:31.006 -> Часовой пояс: Europe/Moscow
16:21:31.006 -> =====================================
16:21:31.006 -> 

uxTaskGetStackHighWaterMark возвращает свободное место не в байтах. Правда это означает, что свободного места еще больше. А Вы в “правильном” месте вызвали uxTaskGetStackHighWaterMark?
PS: гугл говорит, что для ESP всё-таки в байтах.

Да в самом конце вызывал перед

vTaskDelay(1000 * 60 * 5 / portTICK_PERIOD_MS);

Для esp я тоже читал вроде в байтах.

А если

, то что выдает?