默认的 TLS 功能是打开的, 这里可以使用 , 由于TLS证书有时间的要求,如果错误的系统时间可能会导致TLS报错。


#include "esp_crt_bundle.h"
#include "esp_err.h"
#include "esp_event.h"
#include "esp_http_client.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "esp_tls.h"
#include "esp_wifi.h"
#include "esp_wifi_default.h"
#include "esp_wifi_types_generic.h"
#include "freertos/FreeRTOS.h"
#include "freertos/idf_additions.h"
#include "freertos/task.h"
#include "lwip/sockets.h"
#include "mbedtls/platform_util.h"
#include "nvs_flash.h"
#include <assert.h>
#include <lwip/netdb.h>
#include <stdio.h>

static const char *TAG = "HTTPS";
bool isConnected = false;
static EventGroupHandle_t s_wifi_event_group;
#define WIFI_CONNECTED_BIT BIT0
#define WIFI_FAIL_BIT BIT1
static int s_retry_num = 0;

static void event_handler(void *arg, esp_event_base_t event_base,
                          int32_t event_id, void *event_data) {
  if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
    esp_wifi_connect();
  } else if (event_base == WIFI_EVENT &&
             event_id == WIFI_EVENT_STA_DISCONNECTED) {
    if (s_retry_num < 5) {
      esp_wifi_connect();
      s_retry_num += 1;
      ESP_LOGI("STA", "retry connect to the AP");
    } else {
      // 超时
      xEventGroupSetBits(s_wifi_event_group, WIFI_FAIL_BIT);
    }
  } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_CONNECTED) {
    wifi_event_sta_connected_t *event =
        (wifi_event_sta_connected_t *)event_data;
    ESP_LOGI("STA", "connected: %s", event->ssid);
  } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
    ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
    ESP_LOGI(TAG, "got ip:" IPSTR, IP2STR(&event->ip_info.ip));
    s_retry_num = 0;
    // 拿到 IP, 应该可以冲浪了
    xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
  }
}

void wifiInit() {

  // 初始化 netif 和事件轮训
  ESP_ERROR_CHECK(esp_netif_init());
  ESP_ERROR_CHECK(esp_event_loop_create_default());

  // 默认配置设置wifi
  wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
  ESP_ERROR_CHECK(esp_wifi_init(&cfg));

  // 注册事件回调
  ESP_ERROR_CHECK(esp_event_handler_instance_register(
      WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL, NULL));
  ESP_ERROR_CHECK(esp_event_handler_instance_register(
      IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, NULL, NULL));

  // 初始化 sta 和 netif, 个人感觉是为netif接入sta
  esp_netif_t *sta_netif = esp_netif_create_default_wifi_sta();
  assert(sta_netif);
  ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));

  // sta 配置, 你要连接哪个wifi
  wifi_config_t wifi_config = {
      .sta =
          {
              .ssid = "Man_2.4GHz",
              .password = "liang114514",
          },
  };
  ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));

  // 开始干活
  ESP_ERROR_CHECK(esp_wifi_start());
}

esp_err_t _http_event_handler(esp_http_client_event_t *evt) {
  switch (evt->event_id) {
  case HTTP_EVENT_ON_DATA:
	  // 可能会多次接受数据, 进阶是将接受到数据输入缓冲区
    ESP_LOGI(TAG, "HTTP data received: %s", (char *)evt->data);
    break;
  case HTTP_EVENT_ERROR:
    break;
  case HTTP_EVENT_ON_FINISH:
    break;
  case HTTP_EVENT_DISCONNECTED:
	  // 断开连接通常是HTTP接受到所有的报文, 可以发出信号通知接收到完整的报文
    break;
  default:
    break;
  }
  return ESP_OK;
}

void https_get_task(void *pvParameters) {
  // 配置 HTTPS 请求
  esp_http_client_config_t config = {
      .url = "<https://wttr.in/Beijing?format=%t+%c+%h>",
      .event_handler = _http_event_handler,
      .method = HTTP_METHOD_GET,
      .crt_bundle_attach = esp_crt_bundle_attach, // 使用 x509 证书包, tls 认证
  };

  // 初始化 HTTP 客户端
  esp_http_client_handle_t client = esp_http_client_init(&config);
  if (client == NULL) {
    ESP_LOGE(TAG, "Failed to initialize HTTP client");
    vTaskDelete(NULL);
    return;
  }

  // 发送请求
  esp_err_t err = esp_http_client_perform(client);
  if (err == ESP_OK) {

  } else {
    ESP_LOGE(TAG, "HTTPS request failed: %s", esp_err_to_name(err));
  }

  // 清理
  esp_http_client_cleanup(client);
  vTaskDelete(NULL);
}

void app_main() {
  esp_err_t ret = nvs_flash_init();
  if (ret == ESP_ERR_NVS_NO_FREE_PAGES ||
      ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
    ESP_ERROR_CHECK(nvs_flash_erase());
    ret = nvs_flash_init();
  }
  ESP_ERROR_CHECK(ret);

  s_wifi_event_group = xEventGroupCreate();
  wifiInit();
  // 无限等待, 返回
  EventBits_t bits = xEventGroupWaitBits(s_wifi_event_group,
                                         WIFI_CONNECTED_BIT | WIFI_FAIL_BIT,
                                         pdFALSE, pdFALSE, portMAX_DELAY);

  // esp_tls_t *tls = esp_tls_init();
  // if (!tls) {
  //   ESP_LOGE(TAG, "Failed to allocate esp_tls handle!");
  //   return;
  // }

  xTaskCreate(&https_get_task, "https_get_task", 8192, NULL, 5, NULL);
}
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "lwip/err.h"
#include "lwip/sys.h"
#include "esp_http_client.h"

#define EXAMPLE_WIFI_SSID "your_ssid"
#define EXAMPLE_WIFI_PASS "your_password"
#define MAX_HTTP_RECV_BUFFER 1024
#define TAG "HTTP_CLIENT"

static void wifi_init(void);
static void http_post_task(void *pvParameters);

// HTTP 事件处理回调函数
esp_err_t _http_event_handler(esp_http_client_event_t *evt)
{
    static char *output_buffer;  // 用于存储完整的 HTTP 响应
    static int output_len = 0;   // 响应数据的长度

    switch(evt->event_id) {
        case HTTP_EVENT_ON_DATA:
            // 接收到数据时,动态分配内存并追加数据
            if (!output_buffer) {
                output_buffer = (char *)malloc(evt->data_len);
                memcpy(output_buffer, evt->data, evt->data_len);
                output_len = evt->data_len;
            } else {
                output_buffer = (char *)realloc(output_buffer, output_len + evt->data_len);
                memcpy(output_buffer + output_len, evt->data, evt->data_len);
                output_len += evt->data_len;
            }
            break;

        case HTTP_EVENT_ON_FINISH:
            // 请求完成,打印完整的响应报文
            ESP_LOGI(TAG, "HTTP Response received, length=%d", output_len);
            ESP_LOGI(TAG, "Response:\\n%.*s", output_len, output_buffer);
            // 释放内存
            free(output_buffer);
            output_buffer = NULL;
            output_len = 0;
            break;

        case HTTP_EVENT_DISCONNECTED:
            ESP_LOGI(TAG, "HTTP Disconnected");
            // 释放内存
            if (output_buffer) {
                free(output_buffer);
                output_buffer = NULL;
                output_len = 0;
            }
            break;

        case HTTP_EVENT_ERROR:
            ESP_LOGE(TAG, "HTTP Error");
            break;

        default:
            break;
    }
    return ESP_OK;
}

static void http_post_task(void *pvParameters)
{
    // JSON 数据示例
    char post_data[] = "{\\"key\\":\\"value\\",\\"id\\":123}";

    // 配置 HTTP 客户端
    esp_http_client_config_t config = {
        .url = "<http://example.com/api>",  // 替换为目标 POST URL
        .method = HTTP_METHOD_POST,
        .event_handler = _http_event_handler,
        .timeout_ms = 10000,  // 设置超时时间
    };

    // 初始化 HTTP 客户端
    esp_http_client_handle_t client = esp_http_client_init(&config);

    // 设置请求头
    esp_http_client_set_header(client, "Content-Type", "application/json");

    // 设置 POST 数据
    esp_http_client_set_post_field(client, post_data, strlen(post_data));

    // 发送 HTTP POST 请求
    esp_err_t err = esp_http_client_perform(client);
    if (err == ESP_OK) {
        ESP_LOGI(TAG, "HTTP POST Status = %d, content_length = %d",
                 esp_http_client_get_status_code(client),
                 esp_http_client_get_content_length(client));
    } else {
        ESP_LOGE(TAG, "HTTP POST request failed: %s", esp_err_to_name(err));
    }

    // 清理客户端
    esp_http_client_cleanup(client);
    vTaskDelete(NULL);
}

static void wifi_event_handler(void *arg, esp_event_base_t event_base, int32_t event_id, void *event_data)
{
    if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
        esp_wifi_connect();
    } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();
        ESP_LOGI(TAG, "Retry to connect to the AP");
    } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
        ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
        ESP_LOGI(TAG, "Got IP:" IPSTR, IP2STR(&event->ip_info.ip));
        // WiFi 连接成功后启动 HTTP POST 任务
        xTaskCreate(&http_post_task, "http_post_task", 4096, NULL, 5, NULL);
    }
}

static void wifi_init(void)
{
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_instance_t instance_any_id;
    esp_event_handler_instance_t instance_got_ip;
    esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, &instance_any_id);
    esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, &instance_got_ip);

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = EXAMPLE_WIFI_SSID,
            .password = EXAMPLE_WIFI_PASS,
        },
    };
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
}

void app_main(void)
{
    // 初始化 NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // 初始化 WiFi
    wifi_init();
}