ESP-IDFを使ってみる

sntpクライアント


esp-idf/examples/protocolsフォルダーにはたくさんのサンプルコードが格納されています。
こ ちらにsntpによる時刻合わせのサンプルが有ります。
やたらにifdefによる分岐が有りますが、単純化すると以下の様になります。
/* LwIP SNTP example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "esp_sntp.h"

static const char *TAG = "example";


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

        // update 'now' variable with current time
        time_t now;
        time(&now);

        int timezone = 9;
        now = now + (timezone*60*60);
        struct tm timeinfo;
        localtime_r(&now, &timeinfo);
        char strftime_buf[64];
        strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
        ESP_LOGI(TAG, "The current date/time is: %s", strftime_buf);
}


static void initialize_sntp(void)
{
        sntp_setoperatingmode(SNTP_OPMODE_POLL);
        sntp_setservername(0, CONFIG_SNTP_TIME_SERVER);
        sntp_set_time_sync_notification_cb(time_sync_notification_cb);

        uint32_t interval = sntp_get_sync_interval();
        ESP_LOGI(TAG, "interval=%d", interval);

        //sntp_set_sync_interval(60000);

        sntp_init();
}


static void obtain_time(void)
{
        ESP_LOGI(TAG, "initialize_sntp");
        initialize_sntp();

        // wait for time to be set
        int retry = 0;
        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);
        }
}


void app_main(void)
{
        ESP_ERROR_CHECK( nvs_flash_init() );
        ESP_ERROR_CHECK( esp_netif_init() );
        ESP_ERROR_CHECK( esp_event_loop_create_default() );
        ESP_ERROR_CHECK( example_connect() );

        time_t now;
        time(&now);
        struct tm timeinfo;
        localtime_r(&now, &timeinfo);
        char strftime_buf[64];
        strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
        ESP_LOGI(TAG, "The first date/time is: %s", strftime_buf);

        obtain_time();
}

sntp_init()を呼び出すとSNTPクライアントタスクが常駐し、3600000ミリ秒(1時間)毎に時刻合わせを行います。
この間隔はsntp_set_sync_interval()で変更できますが、デフォルト値(3600000ミリ秒)は CONFIG_LWIP_SNTP_UPDATE_DELAY変数で決まります。
こ ちらにシステム時刻に関するAPIが公開されていて、タイムゾーンに関する記述が有りますが、一番簡単なタイムゾーンの設定は、
time(&now)で取り出した秒数に9時間、つまり9*60*60秒を加えることで、日本時間になります。
I (11081) example_connect: - IPv4 address: 192.168.10.117
I (11091) example: The first date/time is: Thu Jan  1 00:00:10 1970
I (11101) example: initialize_sntp
I (11101) example: interval=3600000
I (11111) example: Waiting for system time to be set... (1/15)
I (13111) example: Waiting for system time to be set... (2/15)
I (14731) example: Notification of a time synchronization event
I (14731) example: The current date/time is: Mon Jun 27 22:49:50 2022
I (3614771) example: Notification of a time synchronization event
I (3614771) example: The current date/time is: Mon Jun 27 23:49:50 2022

上記のコードを実行して放置しておくと、以下の様に1時間ごとにtime_sync_notification_cb()が呼び出されるので、時 刻が同期されている事が分かります。
I (3607815) MAIN: Notification of a time synchronization event
I (3607815) MAIN: The current date/time is: Sun Sep 10 19:58:02 2023
I (7207895) MAIN: Notification of a time synchronization event
I (7207895) MAIN: The current date/time is: Sun Sep 10 20:58:02 2023
I (10807975) MAIN: Notification of a time synchronization event
I (10807975) MAIN: The current date/time is: Sun Sep 10 21:58:02 2023
I (14408005) MAIN: Notification of a time synchronization event
I (14408015) MAIN: The current date/time is: Sun Sep 10 22:58:02 2023
I (18008075) MAIN: Notification of a time synchronization event
I (18008075) MAIN: The current date/time is: Sun Sep 10 23:58:02 2023
I (21608115) MAIN: Notification of a time synchronization event
I (21608115) MAIN: The current date/time is: Mon Sep 11 00:58:02 2023
I (25208175) MAIN: Notification of a time synchronization event
I (25208175) MAIN: The current date/time is: Mon Sep 11 01:58:03 2023

時刻に関してはPOSIXのAPIが使えるので、Linuxに慣れている方には扱い易いです。

続く...