您现在的位置是:首页 >技术交流 >esp32获取天气数据(基于esp-idf-5.2.3)网站首页技术交流

esp32获取天气数据(基于esp-idf-5.2.3)

fw_Coder 2025-02-20 00:01:02
简介esp32获取天气数据(基于esp-idf-5.2.3)

        首先需要esp32连接wifi上网, 再通过向天气网站服务器发送GET请求获取天气数据,这里有两个选择:1. 发送http请求,2. 发送https请求。这两种有什么区别请自行百度,总的来说https涉及加密算法更安全。

        这里我们选择方式2,发送https请求。因为HTTPS 是基于 TLS/SSL 的安全通信协议,而 TLS/SSL 依赖于设备的系统时间来进行证书验证,所以这里还需要获取sntp网络时间,并保存在nvs分区中。

1. esp32连接wifi、获取网络时间并备份

这里连接wifi、获取网络时间参考我的上一篇博客:esp32获取网络时间代码

由于上一篇博客没有备份时间,这里补充下时间备份的代码(将时间戳写入nvs分区保存)以及更新nvs时间的代码,这里将Ntp_time.c更改如下:

#include <stdio.h>
#include "incl/Ntp_time.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <string.h>
#include <sys/time.h>
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_netif_sntp.h"
#include "esp_netif.h"
#include "lwip/ip_addr.h"
#include "esp_sntp.h"
#include "esp_mac.h"

static const char* TAG = "myNTP";

#ifndef INET6_ADDRSTRLEN
#define INET6_ADDRSTRLEN 48
#endif

#define CONFIG_EXAMPLE_CONNECT_WIFI     // 使用wifi连接网络
#define STORAGE_NAMESPACE           "storage"           // 自定义NVS命名空间

RTC_DATA_ATTR static int boot_count = 0;
// sntp初始化标志位
bool sntp_inited_flag = 0;
// 获取sntp时间完成回调指针
static mySntp_done_t f_mySntp_done = NULL;

static esp_err_t obtain_time(void);

void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "Notification of a time synchronization event");
}

static void print_servers(void)
{
    ESP_LOGI(TAG, "List of configured NTP servers:");

    for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){
        if (esp_sntp_getservername(i)){
            ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i));
        } else {
            // we have either IPv4 or IPv6 address, let's print it
            char buff[INET6_ADDRSTRLEN];
            ip_addr_t const *ip = esp_sntp_getserver(i);
            if (ipaddr_ntoa_r(ip, buff, INET6_ADDRSTRLEN) != NULL)
                ESP_LOGI(TAG, "server %d: %s", i, buff);
        }
    }
}

static esp_err_t mySntp_init(void)
{
    esp_err_t ret;
#if LWIP_DHCP_GET_NTP_SRV 
    ESP_LOGI(TAG, "Initializing SNTP");
    esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(3, ESP_SNTP_SERVER_LIST("cn.pool.ntp.org", "time.windows.com", "ntp.sjtu.edu.cn"));
    config.start = false;                       // start SNTP service explicitly (after connecting)
    config.server_from_dhcp = true;             // accept NTP offers from DHCP server, if any (need to enable *before* connecting)
    config.renew_servers_after_new_IP = true;   // let esp-netif update configured SNTP server(s) after receiving DHCP lease
    config.index_of_first_server = 1;           // updates from server num 1, leaving server 0 (from DHCP) intact
    // configure the event on which we renew servers
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
    config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
#else
    config.ip_event_to_renew = IP_EVENT_ETH_GOT_IP;
#endif
    config.sync_cb = time_sync_notification_cb; // only if we need the notification function
    ret = esp_netif_sntp_init(&config);

#endif /* LWIP_DHCP_GET_NTP_SRV */

#if LWIP_DHCP_GET_NTP_SRV
    ESP_LOGI(TAG, "Starting SNTP");
    ret += esp_netif_sntp_start();
#endif
    print_servers();

    if(ret == ESP_OK) 
        return ret;
    return ESP_FAIL;
}

void sntp_task(void* param)
{
    ++boot_count;
    ESP_LOGI(TAG, "Boot count: %d", boot_count);

    time_t now;
    struct tm timeinfo;
    
    time(&now);
    localtime_r(&now, &timeinfo);
    // Is time set? If not, tm_year will be (1970 - 1900).
    if (timeinfo.tm_year < (2016 - 1900)) {
        ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
        if(mySntp_init() == ESP_OK)
            sntp_inited_flag = 1;
        if(obtain_time() != ESP_OK)
        {
            ESP_LOGE(TAG, "obtain time failed!");
            vTaskDelete(NULL);
        }
        // update 'now' variable with current time
        time(&now);
    }
    
    char strftime_buf[64];

    // Set timezone to China Standard Time
    setenv("TZ", "CST-8", 1);
    tzset();
    localtime_r(&now, &timeinfo);
    strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
    ESP_LOGI(TAG, "The current date/time in BeiJing is: %s", strftime_buf);
    f_mySntp_done();    // 成功获取sntp时间后调用

    // 进入睡眠模式10s
    // const int deep_sleep_sec = 10;
    // ESP_LOGI(TAG, "Entering deep sleep for %d seconds", deep_sleep_sec);
    // esp_deep_sleep(1000000LL * deep_sleep_sec);
    vTaskDelete(NULL);
}

static esp_err_t obtain_time(void)
{
    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 15;
    while (esp_netif_sntp_sync_wait(2000 / portTICK_PERIOD_MS) == ESP_ERR_TIMEOUT && ++retry < retry_count) {
        ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
    }
    time(&now);
    localtime_r(&now, &timeinfo);

    esp_netif_sntp_deinit();

    // 将时间戳写入nvs
    nvs_handle_t my_handle = 0;
    if(tim_write_into_nvs(&my_handle, &now) == ESP_OK)
        ESP_LOGI(TAG, "tim_write_into_nvs successful");
    else ESP_LOGE(TAG, "tim_write_into_nvs failed");

    if(retry == retry_count)
        return ESP_ERR_TIMEOUT;
    return  ESP_OK;
}

esp_err_t fetch_and_store_time_in_nvs(void *args)
{
    nvs_handle_t my_handle = 0;
    esp_err_t err;
    
    if(!sntp_inited_flag)
    {
        ESP_LOGE(TAG, "sntp don't init");
        err = ESP_FAIL;
        goto exit;
    }

    if (obtain_time() != ESP_OK) {
        err = ESP_FAIL;
        goto exit;
    }

    time_t now;
    time(&now);

    // 将时间戳写入nvs
    err = tim_write_into_nvs(&my_handle, &now);
    if(err != ESP_OK)
    {
        ESP_LOGE(TAG, "tim_write_into_nvs failed");
        goto exit;
    }

exit:
    if (my_handle != 0) {
        nvs_close(my_handle);
    }
    esp_netif_sntp_deinit();

    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Error updating time in nvs");
    } else {
        ESP_LOGI(TAG, "Updated time in NVS");
    }
    return err;
}

esp_err_t update_time_from_nvs(void)
{
    nvs_handle_t my_handle = 0;
    esp_err_t err;
    int64_t timestamp = 0;
    
    // 从nvs中读取网络时间
    err = tim_read_from_nvs(&my_handle, &timestamp);
    if (err == ESP_ERR_NVS_NOT_FOUND) {
        ESP_LOGI(TAG, "Time not found in NVS. Syncing time from SNTP server.");
        if (fetch_and_store_time_in_nvs(NULL) != ESP_OK) {
            err = ESP_FAIL;
        } else {
            err = ESP_OK;
        }
    } else if (err == ESP_OK) {
        struct timeval get_nvs_time;
        get_nvs_time.tv_sec = timestamp;
        settimeofday(&get_nvs_time, NULL);
    }

    // exit
    if (my_handle != 0) {
        nvs_close(my_handle);
    }
    return err;
}

void mySntp_start(mySntp_done_t f)
{
    f_mySntp_done = f;
    ESP_LOGI(TAG, "mySntp start");
    xTaskCreatePinnedToCore(sntp_task, "sntp_task", 4096, NULL, 3, NULL, 1);
}

esp_err_t tim_write_into_nvs(nvs_handle_t* handle, time_t* t)
{
    esp_err_t err;
    //Open
    err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, handle);
    if (err != ESP_OK) {
        return err;
    }

    //Write
    err = nvs_set_i64(*handle, "timestamp", *t);
    if (err != ESP_OK) {
        return err;
    }

    // commit
    err = nvs_commit(*handle);
    if (err != ESP_OK) {
        return err;
    }

    return err;
}

esp_err_t tim_read_from_nvs(nvs_handle_t* handle, int64_t* timestamp)
{
    esp_err_t err;
    err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, handle);
    if (err != ESP_OK) {
        ESP_LOGE(TAG, "Error opening NVS");
        return err;
    }
    return nvs_get_i64(*handle, "timestamp", timestamp);
}

 以下是Ntp_time.h

#ifndef __NTP_TIME_H
#define __NTP_TIME_H

#include "esp_err.h"
#include "nvs_flash.h"
#include <time.h>

// sntp时间获取完成回调定义
typedef void (*mySntp_done_t)(void);

/**
 * @description: 开始获取sntp网络时间
 * @param {mySntp_done_t} f   回调函数
 * @return {*}
 */
void mySntp_start(mySntp_done_t f);

/**
 * @description: 将时间戳备份至nvs
 * @param {nvs_handle_t*} handle    nvs操作句柄
 * @param {time_t*} t               时间戳指针
 * @return {*}  成功: ESP_OK;   失败: others
 */
esp_err_t tim_write_into_nvs(nvs_handle_t* handle, time_t* t);
esp_err_t tim_read_from_nvs(nvs_handle_t* handle, int64_t* timestamp);

/**
 * @description: Fetch the current time from SNTP and stores it in NVS.
 * @param {void*}
 * @return {*}  Successful: ESP_OK;    Failed: other flag
 */
esp_err_t fetch_and_store_time_in_nvs(void*);

/**
 * @description: Update the system time from time stored in NVS.
 * @return {*}  Successful: ESP_OK;    Failed: other flag
 */
esp_err_t update_time_from_nvs(void);

struct tm* get_time(void);

#endif

2. 获取例程源码

首先找到esp32的官方例程(自行上官网找,或者在esp-idf环境目录中查找一个example目录),我下载的SDK是保存在以下目录:

在example目录下找到https_request例程

打开https_request文件夹,将里面的main文件夹复制出来,删除time_sync.c文件

3. 开启Use ESP-TLS with mbedTLS选项

这里我们在上一篇博客的代码基础上增加https_request功能。首先新建https_reqst.c和.h文件,然后将https_request_example_main.c中的代码全部复制进来。

这里我们需要先启用Use ESP-TLS with mbedTLS(使用 mbedTLS 作为 ESP-TLS 后端)选项,但是我们不是基于示例项目,而是在上一篇博客的代码基础上,所以需要手动添加 Kconfig 文件来启用 Example Configuration 菜单。按照以下步骤在命令行中执行相应指令(也可手动添加):

1.在项目的 main 目录下创建 Kconfig.projbuild 文件:

    touch main/Kconfig.projbuild

2.编辑 Kconfig.projbuild 文件,添加以下内容:

    menu "Example Configuration"

        config EXAMPLE_USING_ESP_TLS_MBEDTLS
            bool "Use ESP-TLS with mbedTLS"
            default y
            help
                Enable this option to use mbedTLS as the backend for ESP-TLS.
    endmenu

3.将Kconfig.projbuild 文件保存为UTF-8格式

4.重新运行 menuconfig:

    idf.py menuconfig

在menuconfig --> Example Configuration中勾选[*] Use ESP-TLS with mbedTLS

4. 编写https_request功能代码

在https_reqst.c文件中我们将一些不必要的代码删除,这里我们为了方便直接使用证书包(https_request using crt bundle)发送https请求,所以将root_cert、local_cert证书部分以及server_supported_ciphersuites密码套件代码注释掉。

然后将app_main函数中的example_connect()连接wifi函数删除,并将app_main函数改名为https_request_start。再包含之前ntp代码的头文件,具体代码如下:

#include <string.h>
#include <stdlib.h>
#include <inttypes.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_system.h"
#include "esp_timer.h"
#include "nvs_flash.h"
#include "nvs.h"
#include "protocol_examples_common.h"
#include "esp_sntp.h"
#include "esp_netif.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"

#include "esp_tls.h"
#include "sdkconfig.h"
#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE && CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
#include "esp_crt_bundle.h"
#endif
#include "incl/Ntp_time.h"
#include "incl/https_reqst.h"

/* Constants that aren't configurable in menuconfig */
#define WEB_SERVER "www.howsmyssl.com"
#define WEB_PORT "443"
#define WEB_URL "https://www.howsmyssl.com/a/check"

#define SERVER_URL_MAX_SZ 256

static const char *TAG = "example";

/* Timer interval once every day (24 Hours) */
#define TIME_PERIOD (86400000000ULL)

static const char HOWSMYSSL_REQUEST[] = "GET " WEB_URL " HTTP/1.1
"
                             "Host: "WEB_SERVER"
"
                             "User-Agent: esp-idf/1.0 esp32
"
                             "
";

//#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
//static const char LOCAL_SRV_REQUEST[] = "GET " CONFIG_EXAMPLE_LOCAL_SERVER_URL " HTTP/1.1
"
//                             "Host: "WEB_SERVER"
"
//                             "User-Agent: esp-idf/1.0 esp32
"
//                             "
";
//#endif

/*
extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start");
extern const uint8_t server_root_cert_pem_end[]   asm("_binary_server_root_cert_pem_end");

extern const uint8_t local_server_cert_pem_start[] asm("_binary_local_server_cert_pem_start");
extern const uint8_t local_server_cert_pem_end[]   asm("_binary_local_server_cert_pem_end");
#if CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
static const int server_supported_ciphersuites[] = {MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384, MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256, 0};
static const int server_unsupported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, 0};
#endif
#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
static esp_tls_client_session_t *tls_client_session = NULL;
static bool save_client_session = false;
#endif
*/

static void https_get_request(esp_tls_cfg_t cfg, const char *WEB_SERVER_URL, const char *REQUEST)
{
    char buf[512];
    int ret, len;

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

    if (esp_tls_conn_http_new_sync(WEB_SERVER_URL, &cfg, tls) == 1) {
        ESP_LOGI(TAG, "Connection established...");
    } else {
        ESP_LOGE(TAG, "Connection failed...");
        int esp_tls_code = 0, esp_tls_flags = 0;
        esp_tls_error_handle_t tls_e = NULL;
        esp_tls_get_error_handle(tls, &tls_e);
        /* Try to get TLS stack level error and certificate failure flags, if any */
        ret = esp_tls_get_and_clear_last_error(tls_e, &esp_tls_code, &esp_tls_flags);
        if (ret == ESP_OK) {
            ESP_LOGE(TAG, "TLS error = -0x%x, TLS flags = -0x%x", esp_tls_code, esp_tls_flags);
        }
        goto cleanup;
    }

//#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
//    /* The TLS session is successfully established, now saving the session ctx for reuse */
//    if (save_client_session) {
//        esp_tls_free_client_session(tls_client_session);
//        tls_client_session = esp_tls_get_client_session(tls);
//    }
//#endif

    size_t written_bytes = 0;
    do {
        ret = esp_tls_conn_write(tls,
                                 REQUEST + written_bytes,
                                 strlen(REQUEST) - written_bytes);
        if (ret >= 0) {
            ESP_LOGI(TAG, "%d bytes written", ret);
            written_bytes += ret;
        } else if (ret != ESP_TLS_ERR_SSL_WANT_READ  && ret != ESP_TLS_ERR_SSL_WANT_WRITE) {
            ESP_LOGE(TAG, "esp_tls_conn_write  returned: [0x%02X](%s)", ret, esp_err_to_name(ret));
            goto cleanup;
        }
    } while (written_bytes < strlen(REQUEST));

    ESP_LOGI(TAG, "Reading HTTP response...");
    do {
        len = sizeof(buf) - 1;
        memset(buf, 0x00, sizeof(buf));
        ret = esp_tls_conn_read(tls, (char *)buf, len);

        if (ret == ESP_TLS_ERR_SSL_WANT_WRITE  || ret == ESP_TLS_ERR_SSL_WANT_READ) {
            continue;
        } else if (ret < 0) {
            ESP_LOGE(TAG, "esp_tls_conn_read  returned [-0x%02X](%s)", -ret, esp_err_to_name(ret));
            break;
        } else if (ret == 0) {
            ESP_LOGI(TAG, "connection closed");
            break;
        }

        len = ret;
        ESP_LOGD(TAG, "%d bytes read", len);
        /* Print response directly to stdout as it is read */
        for (int i = 0; i < len; i++) {
            putchar(buf[i]);
        }
        putchar('
'); // JSON output doesn't have a newline at end
    } while (1);

cleanup:
    esp_tls_conn_destroy(tls);
exit:
    for (int countdown = 10; countdown >= 0; countdown--) {
        ESP_LOGI(TAG, "%d...", countdown);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE && CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
static void https_get_request_using_crt_bundle(void)
{
    ESP_LOGI(TAG, "https_request using crt bundle");
    esp_tls_cfg_t cfg = {
        .crt_bundle_attach = esp_crt_bundle_attach,
    };
    https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST);
}
#endif // CONFIG_MBEDTLS_CERTIFICATE_BUNDLE && CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS

//static void https_get_request_using_cacert_buf(void)
//{
//    ESP_LOGI(TAG, "https_request using cacert_buf");
//    esp_tls_cfg_t cfg = {
//        .cacert_buf = (const unsigned char *) server_root_cert_pem_start,
//        .cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
//    };
//    https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST);
//}

//static void https_get_request_using_specified_ciphersuites(void)
//{
//#if CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
//
//    ESP_LOGI(TAG, "https_request using server supported ciphersuites");
//    esp_tls_cfg_t cfg = {
//        .cacert_buf = (const unsigned char *) server_root_cert_pem_start,
//        .cacert_bytes = server_root_cert_pem_end - server_root_cert_pem_start,
//        .ciphersuites_list = server_supported_ciphersuites,
//    };
//
//    https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST);
//
//    ESP_LOGI(TAG, "https_request using server unsupported ciphersuites");
//
//    cfg.ciphersuites_list = server_unsupported_ciphersuites;
//
//    https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST);
//#endif
//}
//
//static void https_get_request_using_global_ca_store(void)
//{
//    esp_err_t esp_ret = ESP_FAIL;
//    ESP_LOGI(TAG, "https_request using global ca_store");
//    esp_ret = esp_tls_set_global_ca_store(server_root_cert_pem_start, server_root_cert_pem_end - server_root_cert_pem_start);
//    if (esp_ret != ESP_OK) {
//        ESP_LOGE(TAG, "Error in setting the global ca store: [%02X] (%s),could not complete the https_request using global_ca_store", esp_ret, esp_err_to_name(esp_ret));
//        return;
//    }
//    esp_tls_cfg_t cfg = {
//        .use_global_ca_store = true,
//    };
//    https_get_request(cfg, WEB_URL, HOWSMYSSL_REQUEST);
//    esp_tls_free_global_ca_store();
//}

//#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
//static void https_get_request_to_local_server(const char* url)
//{
//    ESP_LOGI(TAG, "https_request to local server");
//    esp_tls_cfg_t cfg = {
//        .cacert_buf = (const unsigned char *) local_server_cert_pem_start,
//        .cacert_bytes = local_server_cert_pem_end - local_server_cert_pem_start,
//        .skip_common_name = true,
//    };
//    save_client_session = true;
//    https_get_request(cfg, url, LOCAL_SRV_REQUEST);
//}
//
//static void https_get_request_using_already_saved_session(const char *url)
//{
//    ESP_LOGI(TAG, "https_request using saved client session");
//    esp_tls_cfg_t cfg = {
//        .client_session = tls_client_session,
//    };
//    https_get_request(cfg, url, LOCAL_SRV_REQUEST);
//    esp_tls_free_client_session(tls_client_session);
//    save_client_session = false;
//    tls_client_session = NULL;
//}
//#endif

static void https_request_task(void *pvparameters)
{
    ESP_LOGI(TAG, "Start https_request example");

//#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
//    char *server_url = NULL;
//#ifdef CONFIG_EXAMPLE_LOCAL_SERVER_URL_FROM_STDIN
//    char url_buf[SERVER_URL_MAX_SZ];
//    if (strcmp(CONFIG_EXAMPLE_LOCAL_SERVER_URL, "FROM_STDIN") == 0) {
//        example_configure_stdin_stdout();
//        fgets(url_buf, SERVER_URL_MAX_SZ, stdin);
//        int len = strlen(url_buf);
//        url_buf[len - 1] = '';
//        server_url = url_buf;
//    } else {
//        ESP_LOGE(TAG, "Configuration mismatch: invalid url for local server");
//        abort();
//    }
//    printf("
Server URL obtained is %s
", url_buf);
//#else
//    server_url = CONFIG_EXAMPLE_LOCAL_SERVER_URL;
//#endif /* CONFIG_EXAMPLE_LOCAL_SERVER_URL_FROM_STDIN */
//    https_get_request_to_local_server(server_url);
//    https_get_request_using_already_saved_session(server_url);
//#endif

#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE && CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
    https_get_request_using_crt_bundle();
#endif
    ESP_LOGI(TAG, "Minimum free heap size: %" PRIu32 " bytes", esp_get_minimum_free_heap_size());
//    https_get_request_using_cacert_buf();
//    https_get_request_using_global_ca_store();
//    https_get_request_using_specified_ciphersuites();
    ESP_LOGI(TAG, "Finish https_request example");
    vTaskDelete(NULL);
}

void https_request_start(void)
{
    ESP_ERROR_CHECK(nvs_flash_init());
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());

    if (esp_reset_reason() == ESP_RST_POWERON) {
        ESP_LOGI(TAG, "Updating time from NVS");
        ESP_ERROR_CHECK(update_time_from_nvs());
    }

    const esp_timer_create_args_t nvs_update_timer_args = {
            .callback = (void *)&fetch_and_store_time_in_nvs,
    };

    esp_timer_handle_t nvs_update_timer;
    ESP_ERROR_CHECK(esp_timer_create(&nvs_update_timer_args, &nvs_update_timer));
    ESP_ERROR_CHECK(esp_timer_start_periodic(nvs_update_timer, TIME_PERIOD));

    xTaskCreate(&https_request_task, "https_get_task", 8192, NULL, 5, NULL);
}

5. 获取天气数据

        首先注册一个可以提供天气数据的平台,我这里使用的是心知天气,注册以及使用教程自行查看官方文档心知天气使用文档,或自行百度教程。最后将获取数据的api接口替换至WEB_URL 这个宏中即可。

注释掉的是api密钥,每个人的都是唯一的,自行按照文档获取。

6. main.c文件

        这里将发送https请求的步骤放置最后,先连接wifi后再获取sntp时间并备份,最后再发送https请求获取天气数据。 

#include <stdio.h>
#include <time.h>
#include "incl/simple_wifi_sta.h"
#include "incl/Ntp_time.h"
#include "incl/https_reqst.h"

static const char* TAG = "main";

static EventGroupHandle_t mySntpEvent;
#define MYSNTP_DONE_EV   BIT0  

// sntp时间获取完成回调
void mySntp_done_cb(void)
{
    ESP_LOGI(TAG, "mySntp_done, Beijing time was successfully obtained");
    xEventGroupSetBits(mySntpEvent, MYSNTP_DONE_EV);
}

void app_main(void)
{
    wifi_sta_init();    // sta模式下连接wifi

    ESP_LOGI(TAG,"the esp32 sdk version :%s
", esp_get_idf_version());

    mySntpEvent = xEventGroupCreate();

    do
    {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    } while (!get_wifi_status());       // 等待wifi连接成功

    mySntp_start(mySntp_done_cb);
    xEventGroupWaitBits(mySntpEvent, MYSNTP_DONE_EV, pdTRUE, pdTRUE, portMAX_DELAY);
    https_request_start();

    while (1)
    {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

7. 结果展示

获取到的是一个json数据包,接下来只需要解析出来得到数据即可,这部分大家自行百度。 

风语者!平时喜欢研究各种技术,目前在从事后端开发工作,热爱生活、热爱工作。