arduino-esp32 icon indicating copy to clipboard operation
arduino-esp32 copied to clipboard

More than one HTTPS client; Arduino as ESP-IDF component

Open kungfupizza opened this issue 1 year ago • 4 comments

Board

ESP32S3

Device Description

ESP32S3 Mini 1

Hardware Configuration

Bare devkit

Version

v3.0.1

IDE Name

VSCode

Operating System

Windows 11

Flash frequency

40MHz

PSRAM enabled

no

Upload speed

115200

Description

I have brought in Arduino ESP32 as an IDF component, created multiple tasks. task 1- WiFiClientSecure to run HTTPS requests task 2- esp_http_client(from ESP-IDF) to run some more HTTPS requests task 3- HTTPS OTA via ESP_IDF.

They are started in the order as above. Task 1 can do what it is supposed to do. Task 2 CONNECTS but gets stuck when sending; does not ever return. Task 3 also cannot make HTTP requests.

If I comment out task 1. Task 2 and 3 can run well.

Sketch

- Bring in esp32-arduino as ESP-IDF component
- Multiple tasks with multiple HTTP clients, via ESP-IDF and Arduino
- Try sending through all clients

Debug Message

Task 2 stuck at: 
I (23631) esp-x509-crt-bundle: Certificate validated
I (24036) data: HTTP_EVENT_ON_CONNECTED

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • [X] I confirm I have checked existing issues, online documentation and Troubleshooting guide.

kungfupizza avatar Jun 18 '24 19:06 kungfupizza

Minimal code to reproduce is required

me-no-dev avatar Jun 19 '24 04:06 me-no-dev

Please consider this dummy code to support.

#include <FreeRTOS.h>
#include <task.h>
#include "esp_http_client.h"
#include <NetworkClientSecure.h>
static const char *TAG = "HTTP_CLIENT";

#define STACK_SIZE 2048
static WiFiClientSecure ardClient;

void Task1(void *pvParameters) {
  while (1) {
    if (!ardClient.connect(server, 443)) {
    Serial.println("Connection failed!");
  } else {
    Serial.println("Connected to server!");
    // Make a HTTP request:
    ardClient.println("GET https://www.howsmyssl.com/a/check HTTP/1.0");
    ardClient.println("Host: www.howsmyssl.com");
    ardClient.println("Connection: close");
    ardClient.println();

    while (ardClient.connected()) {
      String line = ardClient.readStringUntil('\n');
      if (line == "\r") {
        Serial.println("headers received");
        break;
      }
    }
    // if there are incoming bytes available
    // from the server, read them and print them:
    while (ardClient.available()) {
      char c = ardClient.read();
      Serial.write(c);
    }

    ardClient.stop();
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

void Task2(void *pvParameters) {
  while (1) {
    esp_http_client_config_t config = {
        .host = CONFIG_EXAMPLE_HTTP_ENDPOINT,
        .path = "/get",
        .query = "esp",
        .event_handler = _http_event_handler,
        .user_data = local_response_buffer,        // Pass address of local buffer to get response
        .disable_auto_redirect = true,
    };
    esp_http_client_handle_t client = esp_http_client_init(&config);

    // GET
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP GET Status = %d, content_length = %"PRId64,
                esp_http_client_get_status_code(client),
                esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP GET request failed: %s", esp_err_to_name(err));
    }
    vTaskDelay(pdMS_TO_TICKS(500));
    printf("Task 2 is running\n");
  }
}

void Task3(void *pvParameters) {
  while (1) {
    // Simulate some work
    vTaskDelay(pdMS_TO_TICKS(2000));
    printf("Task 3 is running\n");
  }
}

int main(void) {
  // Create the tasks
WiFi.begin(ssid, password);

  // attempt to connect to Wifi network:
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    // wait 1 second for re-trying
    delay(1000);
  }

  Serial.print("Connected to ");
  Serial.println(ssid);
  TaskHandle_t xTask1Handle, xTask2Handle, xTask3Handle;
  xTaskCreate(Task1, "Task 1", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xTask1Handle);
  xTaskCreate(Task2, "Task 2", STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xTask2Handle);
  xTaskCreate(Task3, "Task 3", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTask3Handle);

  // We should never get here as the scheduler is now running
  while (1);
}

kungfupizza avatar Jun 20 '24 13:06 kungfupizza

The following fixed code works just fine. You were leaking memory from the esp_http_client and sketch was not complete

#include "esp_http_client.h"
#include <NetworkClientSecure.h>
#include <WiFi.h>
#define STACK_SIZE 8192

static unsigned char local_response_buffer[2048];
static NetworkClientSecure ardClient;

void Task1(void *pvParameters) {
  while (1) {
    ardClient.setInsecure();
    if (!ardClient.connect("www.howsmyssl.com", 443)) {
      Serial.print("Connection failed! ");
      Serial.println(ESP.getFreeHeap());
    } else {
      Serial.println("Connected to server!");
      // Make a HTTP request:
      ardClient.println("GET /a/check HTTP/1.0");
      ardClient.println("Host: www.howsmyssl.com");
      ardClient.println("Connection: close");
      ardClient.println();
  
      while (ardClient.connected()) {
        String line = ardClient.readStringUntil('\n');
        if (line == "\r") {
          Serial.println("headers received");
          break;
        }
      }
      // if there are incoming bytes available
      // from the server, read them and print them:
      while (ardClient.available()) {
        char c = ardClient.read();
        //Serial.write(c);
      }
  
      ardClient.stop();
    }
    vTaskDelay(pdMS_TO_TICKS(1000));
    Serial.printf("Task 1 is running ");
    Serial.println(ESP.getFreeHeap());
  }
}

void Task2(void *pvParameters) {
  esp_http_client_config_t config;
  memset(&config, 0, sizeof(esp_http_client_config_t));
  config.host = "www.google.com";
  config.path = "/";
  config.query = "search=esp";
  config.disable_auto_redirect = true;
  config.event_handler = NULL;
  config.user_data = local_response_buffer;  // Pass address of local buffer to get response
  esp_http_client_handle_t client = esp_http_client_init(&config);
  
  while (1) {
    // GET
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
      Serial.printf("HTTP GET Status = %d, content_length = %" PRId64 "\n",
               esp_http_client_get_status_code(client),
               esp_http_client_get_content_length(client));
      esp_http_client_close(client);
    } else {
      Serial.printf("HTTP GET request failed: %s\n", esp_err_to_name(err));
    }
    vTaskDelay(pdMS_TO_TICKS(500));
    Serial.printf("Task 2 is running ");
    Serial.println(ESP.getFreeHeap());
  }
}

void Task3(void *pvParameters) {
  while (1) {
    // Simulate some work
    vTaskDelay(pdMS_TO_TICKS(2000));
    Serial.printf("Task 3 is running ");
    Serial.println(ESP.getFreeHeap());
  }
}

void setup() {
  Serial.begin(115200);
  Serial.setDebugOutput(true);
  // Create the tasks
  WiFi.begin(ssid, pass);

  // attempt to connect to Wifi network:
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    // wait 1 second for re-trying
    delay(1000);
  }

  Serial.println("Connected");
  TaskHandle_t xTask1Handle, xTask2Handle, xTask3Handle;
  xTaskCreate(Task1, "Task 1", STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, &xTask1Handle);
  xTaskCreate(Task2, "Task 2", STACK_SIZE, NULL, tskIDLE_PRIORITY + 2, &xTask2Handle);
  xTaskCreate(Task3, "Task 3", STACK_SIZE, NULL, tskIDLE_PRIORITY, &xTask3Handle);
}

void loop() {
  vTaskDelay(pdMS_TO_TICKS(2000));
}

me-no-dev avatar Jun 27 '24 10:06 me-no-dev

while(1); anywhere in the code is a very bad idea!

me-no-dev avatar Jun 27 '24 10:06 me-no-dev

@me-no-dev I updated arduino-esp32 to v3.0.2 and ESP-IDF to v5.1.4 to get it working. Thank you for checking.

kungfupizza avatar Jul 01 '24 10:07 kungfupizza