From 696acf5e3f18925987f392f999782aadedfdc89e Mon Sep 17 00:00:00 2001 From: Emil Muratov Date: Wed, 3 Nov 2021 13:55:11 +0300 Subject: [PATCH 1/2] Examples/lwip: sntp example - updated ntp over dhcp code/comments Apply suggestions from code review Co-authored-by: david-cermak <38914379+david-cermak@users.noreply.github.com> Merges https://github.com/espressif/esp-idf/pull/7824 --- examples/protocols/sntp/README.md | 10 ++++ .../protocols/sntp/main/sntp_example_main.c | 49 +++++++++++++++++-- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/examples/protocols/sntp/README.md b/examples/protocols/sntp/README.md index 7e73265974..02fdb3c10c 100644 --- a/examples/protocols/sntp/README.md +++ b/examples/protocols/sntp/README.md @@ -20,6 +20,16 @@ Open the project configuration menu (`idf.py menuconfig`): When this example boots first time after ESP32 is reset, it connects to WiFi and obtains time using SNTP. See `initialize_sntp` function for details. +## Obtaining time using LwIP SNTP-over-DHCP module + +NTP server addresses could be automatically aquired via DHCP server option 42. This could be usefull on closed environments where public NTPs are not accessible +or to prefer local servers and reduce traffic to the outer world. +See following menuconfig options: + * `Component config-->LWIP-->SNTP-->Maximum number of NTP servers` + * `Component config-->LWIP-->SNTP-->Request NTP servers from DHCP` + * `Component config-->LWIP-->SNTP-->Maximum number of NTP servers aquired via DHCP` + * `Component config-->LWIP-->Enable LWIP Debug-->Enable SNTP debug messages` + ## Timekeeping Once time is synchronized, ESP32 will perform timekeeping using built-in timers. diff --git a/examples/protocols/sntp/main/sntp_example_main.c b/examples/protocols/sntp/main/sntp_example_main.c index 3733241640..d3679082cf 100644 --- a/examples/protocols/sntp/main/sntp_example_main.c +++ b/examples/protocols/sntp/main/sntp_example_main.c @@ -23,6 +23,10 @@ static const char *TAG = "example"; +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 48 +#endif + /* Variable holding number of times ESP32 restarted since first boot. * It is placed into RTC memory using RTC_DATA_ATTR and * maintains its value when ESP32 wakes from deep sleep. @@ -124,10 +128,15 @@ static void obtain_time(void) /** * NTP server address could be aquired via DHCP, - * see LWIP_DHCP_GET_NTP_SRV menuconfig option + * see following menuconfig options: + * 'LWIP_DHCP_GET_NTP_SRV' - enable STNP over DHCP + * 'LWIP_SNTP_DEBUG' - enable debugging messages + * + * NOTE: This call should be made BEFORE esp aquires IP address from DHCP, + * otherwise NTP option would be rejected by default. */ #ifdef LWIP_DHCP_GET_NTP_SRV - sntp_servermode_dhcp(1); + sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any #endif /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig. @@ -142,7 +151,7 @@ static void obtain_time(void) time_t now = 0; struct tm timeinfo = { 0 }; int retry = 0; - const int retry_count = 10; + const int retry_count = 15; while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) { ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count); vTaskDelay(2000 / portTICK_PERIOD_MS); @@ -157,10 +166,44 @@ static void initialize_sntp(void) { ESP_LOGI(TAG, "Initializing SNTP"); sntp_setoperatingmode(SNTP_OPMODE_POLL); + +/* + * If 'NTP over DHCP' is enabled, we set dynamic pool address + * as a 'secondary' server. It will act as a fallback server in case that address + * provided via NTP over DHCP is not accessible + */ +#if LWIP_DHCP_GET_NTP_SRV && SNTP_MAX_SERVERS > 1 + sntp_setservername(1, "pool.ntp.org"); + +#if LWIP_IPV6 && SNTP_MAX_SERVERS > 2 // statically assigned IPv6 address is also possible + ip_addr_t ip6; + if (ipaddr_aton("2a01:3f7::1", &ip6)) { // ipv6 ntp source "ntp.netnod.se" + sntp_setserver(2, &ip6); + } +#endif /* LWIP_IPV6 */ + +#else /* LWIP_DHCP_GET_NTP_SRV && (SNTP_MAX_SERVERS > 1) */ + // otherwise use DNS address from a pool sntp_setservername(0, "pool.ntp.org"); +#endif + sntp_set_time_sync_notification_cb(time_sync_notification_cb); #ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH); #endif sntp_init(); + + ESP_LOGI(TAG, "List of configured NTP servers:"); + + for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){ + if (sntp_getservername(i)){ + ESP_LOGI(TAG, "server %d: %s", i, sntp_getservername(i)); + } else { + // we have either IPv4 or IPv6 address, let's print it + char buff[INET6_ADDRSTRLEN]; + ip_addr_t const *ip = sntp_getserver(i); + if (ipaddr_ntoa_r(ip, buff, INET6_ADDRSTRLEN) != NULL) + ESP_LOGI(TAG, "server %d: %s", i, buff); + } + } } From 020047b0f9739457f5ea46571d890ca0dea70102 Mon Sep 17 00:00:00 2001 From: David Cermak Date: Tue, 23 Nov 2021 13:02:49 +0100 Subject: [PATCH 2/2] Examples/lwip: sntp example - Make SNTP server configurable Also updates NTP example test to allow more attempts --- examples/protocols/sntp/example_test.py | 2 +- examples/protocols/sntp/main/Kconfig.projbuild | 6 ++++++ examples/protocols/sntp/main/sntp_example_main.c | 4 ++-- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/protocols/sntp/example_test.py b/examples/protocols/sntp/example_test.py index 79d0880849..ff9b888670 100644 --- a/examples/protocols/sntp/example_test.py +++ b/examples/protocols/sntp/example_test.py @@ -15,7 +15,7 @@ def test_examples_sntp(env, extra_data): dut.expect_all('Time is not set yet. Connecting to WiFi and getting time over NTP.', 'Initializing SNTP', - 'Waiting for system time to be set... (1/10)', + re.compile(r'Waiting for system time to be set... \(\d+/\d+\)'), 'Notification of a time synchronization event', timeout=60) diff --git a/examples/protocols/sntp/main/Kconfig.projbuild b/examples/protocols/sntp/main/Kconfig.projbuild index 45e1737413..490365acb3 100644 --- a/examples/protocols/sntp/main/Kconfig.projbuild +++ b/examples/protocols/sntp/main/Kconfig.projbuild @@ -1,5 +1,11 @@ menu "Example Configuration" + config SNTP_TIME_SERVER + string "SNTP server name" + default "pool.ntp.org" + help + Hostname of the main SNTP server. + choice SNTP_TIME_SYNC_METHOD prompt "Time synchronization method" default SNTP_TIME_SYNC_METHOD_IMMED diff --git a/examples/protocols/sntp/main/sntp_example_main.c b/examples/protocols/sntp/main/sntp_example_main.c index d3679082cf..e5e81f800a 100644 --- a/examples/protocols/sntp/main/sntp_example_main.c +++ b/examples/protocols/sntp/main/sntp_example_main.c @@ -183,8 +183,8 @@ static void initialize_sntp(void) #endif /* LWIP_IPV6 */ #else /* LWIP_DHCP_GET_NTP_SRV && (SNTP_MAX_SERVERS > 1) */ - // otherwise use DNS address from a pool - sntp_setservername(0, "pool.ntp.org"); + // otherwise, use DNS address from a pool + sntp_setservername(0, CONFIG_SNTP_TIME_SERVER); #endif sntp_set_time_sync_notification_cb(time_sync_notification_cb);