chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 13:04:25 +08:00
commit 548b49ebc0
20937 changed files with 5455372 additions and 0 deletions
@@ -0,0 +1,7 @@
# Embed the server root certificate into the final binary
#
# (If this was a component, we would set COMPONENT_EMBED_TXTFILES here.)
idf_component_register(SRCS "https_request_example_main.c" "time_sync.c"
INCLUDE_DIRS "include"
PRIV_REQUIRES esp-tls esp_wifi esp_timer nvs_flash
EMBED_TXTFILES server_root_cert.pem local_server_cert.pem)
@@ -0,0 +1,33 @@
menu "Example Configuration"
config EXAMPLE_USING_ESP_TLS_MBEDTLS
bool
depends on ESP_TLS_USING_MBEDTLS
default y
config EXAMPLE_CLIENT_SESSION_TICKETS
bool "Enable Client session ticket support"
default n
select ESP_TLS_CLIENT_SESSION_TICKETS
help
Enable the client session ticket support for the example.
config EXAMPLE_LOCAL_SERVER_URL
string "Local Server URL for testing session tickets"
default "https://192.168.0.106:8070"
depends on EXAMPLE_CLIENT_SESSION_TICKETS
help
The url of the server to which the example is going to connect in order to test the session ticket support.
config EXAMPLE_LOCAL_SERVER_URL_FROM_STDIN
bool
default y if EXAMPLE_LOCAL_SERVER_URL = "FROM_STDIN"
config EXAMPLE_SSL_PROTO_TLS1_3_CLIENT
bool "Enable TLS 1.3 client test"
default n
select MBEDTLS_SSL_PROTO_TLS1_3
help
Enable TLS 1.3 client test support for the example.
endmenu
@@ -0,0 +1,346 @@
/*
* HTTPS GET Example using plain Mbed TLS sockets
*
* Contacts the howsmyssl.com API via TLS v1.2 and reads a JSON
* response.
*
* Adapted from the ssl_client1 example in Mbed TLS.
*
* SPDX-FileCopyrightText: The Mbed TLS Contributors
*
* SPDX-License-Identifier: Apache-2.0
*
* SPDX-FileContributor: 2015-2026 Espressif Systems (Shanghai) CO LTD
*/
#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 "time_sync.h"
#include "esp_random.h"
/* Constants that aren't configurable in menuconfig */
#ifdef CONFIG_EXAMPLE_SSL_PROTO_TLS1_3_CLIENT
#define WEB_SERVER "tls13.browserleaks.com"
#define WEB_PORT "443"
#define WEB_URL "https://tls13.browserleaks.com/tls"
#else
#define WEB_SERVER "howsmyssl.com"
#define WEB_PORT "443"
#define WEB_URL "https://www.howsmyssl.com/a/check"
#endif
#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\r\n"
"Host: "WEB_SERVER"\r\n"
"User-Agent: esp-idf/1.0 esp32\r\n"
"\r\n";
#ifdef CONFIG_EXAMPLE_CLIENT_SESSION_TICKETS
static const char LOCAL_SRV_REQUEST[] = "GET " CONFIG_EXAMPLE_LOCAL_SERVER_URL " HTTP/1.1\r\n"
"Host: "WEB_SERVER"\r\n"
"User-Agent: esp-idf/1.0 esp32\r\n"
"\r\n";
#endif
/* Root cert for howsmyssl.com, taken from server_root_cert.pem
The PEM file was extracted from the output of this command:
openssl s_client -showcerts -connect www.howsmyssl.com:443 </dev/null
The CA root cert is the last cert given in the chain of certs.
To embed it in the app binary, the PEM file is named
in the component.mk COMPONENT_EMBED_TXTFILES variable.
*/
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
#if defined(CONFIG_EXAMPLE_SSL_PROTO_TLS1_3_CLIENT)
static const int server_supported_ciphersuites[] = {MBEDTLS_TLS1_3_AES_256_GCM_SHA384, MBEDTLS_TLS1_3_AES_128_CCM_SHA256, 0};
static const int server_unsupported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, 0};
#else
static const int server_supported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256, MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CCM, 0};
static const int server_unsupported_ciphersuites[] = {MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256, 0};
#endif // CONFIG_EXAMPLE_SSL_PROTO_TLS1_3_CLIENT
#endif // CONFIG_EXAMPLE_USING_ESP_TLS_MBEDTLS
#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;
}
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('\n'); // JSON output doesn't have a newline at end
} while (1);
#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
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,
#if defined(CONFIG_EXAMPLE_SSL_PROTO_TLS1_3_CLIENT)
.tls_version = ESP_TLS_VER_TLS_1_3,
#else
.tls_version = ESP_TLS_VER_TLS_1_2,
#endif
};
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,
.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,
};
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] = '\0';
server_url = url_buf;
} else {
ESP_LOGE(TAG, "Configuration mismatch: invalid url for local server");
abort();
}
printf("\nServer URL obtained is %s\n", 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 app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
* Read "Establishing Wi-Fi or Ethernet Connection" section in
* examples/protocols/README.md for more information about this function.
*/
ESP_ERROR_CHECK(example_connect());
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);
}
@@ -0,0 +1,3 @@
dependencies:
protocol_examples_common:
path: ${IDF_PATH}/examples/common_components/protocol_examples_common
@@ -0,0 +1,27 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Update the system time from time stored in NVS.
*
*/
esp_err_t update_time_from_nvs(void);
/**
* @brief Fetch the current time from SNTP and stores it in NVS.
*
*/
esp_err_t fetch_and_store_time_in_nvs(void*);
#ifdef __cplusplus
}
#endif
@@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE-----
MIICyDCCAbACCQC4RVDDRrCbrDANBgkqhkiG9w0BAQsFADAmMSQwIgYDVQQDDBtF
U1AzMiBIVFRQUyByZXF1ZXN0IGV4YW1wbGUwHhcNMjExMTE0MjAxMjQ4WhcNMzEx
MTEyMjAxMjQ4WjAmMSQwIgYDVQQDDBtFU1AzMiBIVFRQUyByZXF1ZXN0IGV4YW1w
bGUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9eiUPHf31rkkTQ7Pq
EHeefT5pC8VZvfpgQSOz4nQNvX94BysC+Ycv0MTnWn2yKk4fj/gXaf3mhlcmNwZO
CGMIgi9BzACWgOKAlUMXwbo3qOdMXRPgWvv/vv6xM5WdVjWPdC/LJOg41wqYblZ7
FTZhxw5K7wLkjiAZrWcm4bd993Z0Hy7WXWFMaBURjPehORq/E2GeL11o+aLGT/Fi
0c64gBsyiGt+RK5c/QkoS44WM77YwiUbzuKdLd5j4LXNcqc47Ac1oPl7vTSUQta+
4Ixaler/IC8yg9l2f9t1HsYNfL/6O61C1PoHSqwWwMU1eegdW33UYGrA00NSfSNI
7k8XAgMBAAEwDQYJKoZIhvcNAQELBQADggEBADqDXuXa90kwJGmbjyNMgmBdsCvg
0Z+bG085hjKY/TogH76E8bhbN0obXxIbht4LKNdrC76IIE/iY/EF+LRBiWCemUHV
Pgj16REG335R86VU9UTSoGte1oOK3ttmJ10bz1WeBSTOT21OyTqvI0+zWvei9Jel
ADDGck47sJoAbDv2FC6AhFjkmG0YsaoJtXsSAnKmLL+qsJ1z0ZIHxupIO7coG2fe
6ZZMWnLt5ODCopYCY6aVuODoJ4Ywe+Yu3tBPG7AF9em7MfUVngOJCGUrhu4RLCTm
3FT53VgKyMjQKVzeg9hkRvgePWX4oByWCmxzvWAV5oavh41BvpRsW4vBF54=
-----END CERTIFICATE-----
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC9eiUPHf31rkkT
Q7PqEHeefT5pC8VZvfpgQSOz4nQNvX94BysC+Ycv0MTnWn2yKk4fj/gXaf3mhlcm
NwZOCGMIgi9BzACWgOKAlUMXwbo3qOdMXRPgWvv/vv6xM5WdVjWPdC/LJOg41wqY
blZ7FTZhxw5K7wLkjiAZrWcm4bd993Z0Hy7WXWFMaBURjPehORq/E2GeL11o+aLG
T/Fi0c64gBsyiGt+RK5c/QkoS44WM77YwiUbzuKdLd5j4LXNcqc47Ac1oPl7vTSU
Qta+4Ixaler/IC8yg9l2f9t1HsYNfL/6O61C1PoHSqwWwMU1eegdW33UYGrA00NS
fSNI7k8XAgMBAAECggEADa5QFrNXrvGSnS16RCBEQtFQPE15Rm2NMn4Bke976bIR
Dh2WYXSa6jzsurex87dSRL0kcKxahNaWXFAEyIWagPbFar7MHBHaSOZ+Ha0DQRmU
+dKOqNho8aJcyXasCtw6qcz91nEnw1LjlPYCkIiLkKvKwGZZkx8f+jqnBAuwMAwa
VZzrtDw2zZAZXBspC9n9fa0IAY4rq7QWCl/HlTEody8VuLng7+WEhFJRJ0F1IK9v
U1NihTdZRuybWQvmcj3fh+44PHBNkljoPPwN361eNR9aYiU/KtTIa8En+ZQPyetH
rmr6rMsd7rBTTbPch6nanN5rsmWCMbQj3bD6LWuEQQKBgQDg50fMK2XQfZukPDjT
3rYBPCSKUdE8uzP5p2xurHLZa+zjrhkVu3895OaP4WHYNAOaaTMnxwTVY2xXMA/F
uoJmDpVzuDjgp1qjqDK96XMPSUs30dwI8LgYCfEm7gKZ7BFSn8QlhxeFIn4fhxwS
w6vBeNp0uL9Pjj/C2ZCDd6iWCQKBgQDXrOigR22OHWksAeDz/TVW/KEQEkFHvuF7
U87YyV+771TYT98fkKZ4zyStIK96eWumxmeBTVSg5zS+8aOFfWO3OL4Bfj45JWaJ
rblh/bgLUsa5J6jrm9ISVATfqN3GiEJw8LhkCjIqI269ku874jQrCifZPVKFffkf
2/1LSswEHwKBgQDU4PYrwnQ32X0GAt7DZM4f8x6fMnx8ILI8wAW56E85j5eFlxg1
Yuk4276FOA+WRv2WHbeHEjF4DgjRqjNztGuTUICULS7hLmdz+1Q0QJFhSb4B0wmU
CM4oKtjxQV6C9VkcPQ+7ediAczqwewHOnRmpIsycqPakxf+CXs8UMaIIiQKBgA8F
30pSz2HH0KydEONN7uo5PKrW6q8pr6EcjFrzY/S+TgWnQp57P+1IWICqty5ryMDc
LxeFoHB4ymbGhCJnQovfqvSFq6XlYggTDsexmaFISclZ5t1KhE58hb5ij9glY6Nk
USO+xhHDWBJiasGcFxAsa+wo5legF7tNYo5dDmr3AoGAQ+i2gtXpZELQZ9ODkIbR
wlvRTlElDkk/+a9O/k18eFv4uyw4locngsWtz6lpzJuXikj+LtnYKMInvZxwmyJT
n4MLb/SNxpaumZHhSZy5xU1x7RgBzR/NyaJIws70eDvc6g9PIe2ahVoDDMSZxtGN
3tplBVJpwQuwwoKFmE2ea9I=
-----END PRIVATE KEY-----
@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
-----END CERTIFICATE-----
@@ -0,0 +1,132 @@
/*
* SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <stdlib.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 "nvs_flash.h"
#include "nvs.h"
#include "esp_netif.h"
#include "esp_netif_sntp.h"
#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include "lwip/netdb.h"
#include "lwip/dns.h"
#include "time_sync.h"
static const char *TAG = "time_sync";
#define STORAGE_NAMESPACE "storage"
void initialize_sntp(void)
{
ESP_LOGI(TAG, "Initializing SNTP");
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(2,
ESP_SNTP_SERVER_LIST("time.windows.com", "pool.ntp.org" ) );
esp_netif_sntp_init(&config);
}
static esp_err_t obtain_time(void)
{
// wait for time to be set
int retry = 0;
const int retry_count = 10;
while (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(2000)) != ESP_OK && ++retry < retry_count) {
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
}
if (retry == retry_count) {
return ESP_FAIL;
}
return ESP_OK;
}
esp_err_t fetch_and_store_time_in_nvs(void *args)
{
nvs_handle_t my_handle = 0;
esp_err_t err;
initialize_sntp();
if (obtain_time() != ESP_OK) {
err = ESP_FAIL;
goto exit;
}
time_t now;
time(&now);
//Open
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
goto exit;
}
//Write
err = nvs_set_i64(my_handle, "timestamp", now);
if (err != ESP_OK) {
goto exit;
}
err = nvs_commit(my_handle);
if (err != ESP_OK) {
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;
err = nvs_open(STORAGE_NAMESPACE, NVS_READWRITE, &my_handle);
if (err != ESP_OK) {
ESP_LOGE(TAG, "Error opening NVS");
goto exit;
}
int64_t timestamp = 0;
err = nvs_get_i64(my_handle, "timestamp", &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;
}