ESP32 support http

Hi.

I’ve been testing file transfers via HTTP, and it’s working well overall. However, I’m encountering an error that I can’t determine if it’s related to the SDK or IDF 5.1.1 (maybe its very old). The SDK seems to mix HTTP functionality with OTA, but I’m not using OTA at all.

#include "esp_log.h"
#include "esp_http_client.h"
#include "esp_system.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>

static const char *TAG = "HTTP_CLIENT";

// Configuración del servidor
#define SERVER1 "http://192.168.1.201:3000" // Servidor en Eleinco
#define SERVER2 "http://192.168.1.201:3000" // Servidor en Casa
#define BINSIZE 32768                       // 32 KB
#define SEND_INTERVAL_MS (120 * 1000)       // 2 minutos en milisegundos

static uint8_t bin_data[BINSIZE]; // Buffer para datos binarios
static int preferred_server = -1; // -1 indica que aún no se ha elegido servidor

// Manejador de eventos HTTP
static esp_err_t http_event_handler(esp_http_client_event_t *evt)
{
    switch (evt->event_id)
    {
    case HTTP_EVENT_ERROR:
        ESP_LOGE(TAG, "HTTP_EVENT_ERROR");
        break;
    case HTTP_EVENT_ON_CONNECTED:
        ESP_LOGI(TAG, "HTTP_EVENT_ON_CONNECTED");
        break;
    case HTTP_EVENT_HEADER_SENT:
        ESP_LOGI(TAG, "HTTP_EVENT_HEADER_SENT");
        break;
    case HTTP_EVENT_ON_HEADER:
        ESP_LOGI(TAG, "HTTP_EVENT_ON_HEADER: %s: %s", evt->header_key, evt->header_value);
        break;
    case HTTP_EVENT_ON_DATA:
        ESP_LOGI(TAG, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
        break;
    case HTTP_EVENT_ON_FINISH:
        ESP_LOGI(TAG, "HTTP_EVENT_ON_FINISH");
        break;
    case HTTP_EVENT_DISCONNECTED:
        ESP_LOGI(TAG, "HTTP_EVENT_DISCONNECTED");
        break;
    case HTTP_EVENT_REDIRECT:
        ESP_LOGI(TAG, "HTTP_EVENT_REDIRECT");
        break;
    default:
        ESP_LOGW(TAG, "Evento HTTP no manejado: %d", evt->event_id);
        break;
    }
    return ESP_OK;
}

// Generar datos aleatorios
static void generate_random_data(void)
{
    ESP_LOGI(TAG, "Generating random data...");
    for (int i = 0; i < BINSIZE; i++)
    {
        bin_data[i] = esp_random() % 256; // Genera byte aleatorio
    }
}

// Enviar datos binarios al servidor
static void send_binary_data(const char *url)
{
    ESP_LOGI(TAG, "Attempting to send data to: %s", url);

    // Construir la URL completa con la ruta /uploadBin
    char full_url[256];
    snprintf(full_url, sizeof(full_url), "%s/uploadBin", url);

    esp_http_client_config_t config = {
        .url = full_url,                     // Usar la URL completa con la ruta
        .event_handler = http_event_handler, // <-- ¡Este es clave!
        .timeout_ms = 10000,
    };

    esp_http_client_handle_t client = esp_http_client_init(&config);
    if (client == NULL)
    {
        ESP_LOGE(TAG, "Failed to initialize HTTP client");
        return;
    }

    // Configurar método POST y headers
    esp_http_client_set_method(client, HTTP_METHOD_POST);
    esp_http_client_set_header(client, "Content-Type", "application/octet-stream");
    esp_http_client_set_header(client, "Connection", "close");
    esp_http_client_set_header(client, "x-device-id", "IMU-8802"); // Añadir device ID

    // Configurar los datos a enviar
    esp_http_client_set_post_field(client, (const char *)bin_data, BINSIZE);

    // Ejecutar la solicitud
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK)
    {
        ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %lld", esp_http_client_get_status_code(client), esp_http_client_get_content_length(client));
        preferred_server = (strstr(url, "192.168.1.201") != NULL) ? 1 : 0;
    }
    else
    {
        ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
        preferred_server = -1;
    }

    // Cerrar explícitamente la conexión
    esp_http_client_close(client);
    esp_http_client_cleanup(client);
}

// Tarea principal para enviar datos periódicamente
static void http_client_task(void *pvParameters)
{
    generate_random_data();

    while (1)
    {
        const char *servers[] = {SERVER1, SERVER2};

        // Intentar con el servidor preferido primero, si está definido
        if (preferred_server >= 0 && preferred_server < 2)
        {
            send_binary_data(servers[preferred_server]);
        }
        else
        {
            // Probar ambos servidores
            for (int i = 0; i < 2; i++)
            {
                send_binary_data(servers[i]);
                if (preferred_server != -1)
                    break; // Si uno funcionó, salir
            }
        }

        // Esperar el intervalo definido antes de enviar de nuevo
        vTaskDelay(pdMS_TO_TICKS(SEND_INTERVAL_MS));
    }
}

// Inicializar el cliente HTTP
void http_client_init(void)
{
    xTaskCreate(http_client_task, "http_client_task", 4096, NULL, 5, NULL);
}
I (10636445) HTTP_CLIENT: Attempting to send data to: http://192.168.1.201:3000
I (10636467) HTTP_CLIENT: Conectado
E (10636468) HTTP_CLIENT: Failed to post https_ota event: 1, error: ESP_ERR_INVALID_STATE
E (10636471) HTTP_CLIENT: Failed to post https_ota event: 2, error: ESP_ERR_INVALID_STATE
E (10636704) HTTP_CLIENT: Failed to post https_ota event: 3, error: ESP_ERR_INVALID_STATE
E (10636704) HTTP_CLIENT: Failed to post https_ota event: 3, error: ESP_ERR_INVALID_STATE
E (10636711) HTTP_CLIENT: Failed to post https_ota event: 3, error: ESP_ERR_INVALID_STATE
E (10636720) HTTP_CLIENT: Failed to post https_ota event: 3, error: ESP_ERR_INVALID_STATE
I (10636729) HTTP_CLIENT: Datos recibidos, len=32
E (10636734) HTTP_CLIENT: Failed to post https_ota event: 4, error: ESP_ERR_INVALID_STATE
E (10636743) HTTP_CLIENT: Failed to post https_ota event: 5, error: ESP_ERR_INVALID_STATE
E (10636751) HTTP_CLIENT: Failed to post https_ota event: 6, error: ESP_ERR_INVALID_STATE
I (10636761) HTTP_CLIENT: HTTP POST Status = 200, content_length = -1
E (10636767) HTTP_CLIENT: Failed to post https_ota event: 6, error: ESP_ERR_INVALID_STATE
E (10636776) HTTP_CLIENT: Failed to post https_ota event: 6, error: ESP_ERR_INVALID_STATE ESP32 SDK  support http

Hi @Carlos,

Seems like the ota part is a typo/copy paste error in that version of the ESP-IDF. Looks like it has been corrected in the newer versions, commit.

static void http_dispatch_event_to_event_loop(int32_t event_id, const void* event_data, size_t event_data_size)
{
    esp_err_t err = esp_event_post(ESP_HTTP_CLIENT_EVENT, event_id, event_data, event_data_size, portMAX_DELAY);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Failed to post https_ota event: %"PRId32", error: %s", event_id, esp_err_to_name(err));
    }
}

I presume this is not all the code for the application as I can’t see where the connection is being brought up. Taking a guess though I would think it might be because you have not started the default event loop yet based on the esp_event_post() docs

Just need to add this call somewhere in your init code before the http client is started. See esp_http_client example.

    ESP_ERROR_CHECK(esp_event_loop_create_default());

Yes Rob, that is correct.
Thanks!