ESP32 の 時刻取得のオフライン時の挙動

# ESP32/Arduino の 時刻取得のオフライン時の挙動

ESP32で現在時刻を取得するにはNTPを使いますが、オフライン/オフライン時の挙動が知りたかったので、軽くテストしてみました。

なお、NTP関連は下記に詳しい。（この記事含めて下手な日本語ページを見るよりは、機械翻訳でマニュアルを読むほうが素早く答にたどり着く）

https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/system_time.html#sntp-time-synchronization

## 結果
+ 一度もオンラインになっていない場合は、getLocalTime()はタイムアウトを起こし、基準時間(1970/01/01 00:00:00)＋電源ON後の経過時間を返す。タイムアウトは第2引数にミリ秒単位で指定できる。省略時は5000(5秒)
+ オンラインになった時の最初のgetLocalTime時に少し時間がかかる(例では1.5秒)
+ 一度オンライン時にgetLocalTimeで時刻が取得できれば、その後はネットを切断しても時刻取得できる。実行時間も1ms以下

## 考察
以上から、

+ configTime()を一度実行
+ ネットワーク接続後、一度getLocalTime()を実行
+ その後はネットワークの状態に関わらず、時刻取得可

という利用方法が良い。

## 検証プログラムと結果
```esp32-localtime.c
#include <WiFi.h>

void test()
{
  unsigned long m;
  struct tm timeInfo;

  m = millis();
  getLocalTime(&timeInfo);  
  Serial.printf("getLocalTime() %luMS\n",millis()-m);
  Serial.printf("%04d/%02d/%02d %02d:%02d:%02d\n",timeInfo.tm_year+1900,timeInfo.tm_mon+1,timeInfo.tm_mday,timeInfo.tm_hour,timeInfo.tm_min,timeInfo.tm_sec);

  m = millis();
  configTime(9 * 3600L, 0, "ntp.nict.jp", "time.google.com", "ntp.jst.mfeed.ad.jp");
  Serial.printf("configTime() %luMS\n",millis()-m);
}

void setup() {
  Serial.begin( 115200 );
  delay(1000);
    
  Serial.println("\nOFFLINE");
  for(int i=0;i<3;i++){
    test();
    delay(1000);      
  }

  delay(1000);
  WiFi.begin("","");
  while (WiFi.status() != WL_CONNECTED) {
      delay(500);
  }

  Serial.println("\nONLINE");
  for(int i=0;i<3;i++){
    test();
    delay(1000);      
  }

  WiFi.disconnect(true);
  WiFi.mode(WIFI_OFF);
  delay(1000);
  Serial.println("\nOFFLINE");
  for(int i=0;i<3;i++){
    test();
    delay(1000);      
  }
}

void loop() {}
```

```
OFFLINE
getLocalTime() 5010MS
1970/01/01 00:00:06
configTime() 1MS
getLocalTime() 5010MS
1970/01/01 09:00:12
configTime() 0MS
getLocalTime() 5010MS
1970/01/01 09:00:18
configTime() 0MS

ONLINE
getLocalTime() 1450MS
2021/09/10 11:05:27
configTime() 1MS
getLocalTime() 0MS
2021/09/10 11:05:28
configTime() 0MS
getLocalTime() 0MS
2021/09/10 11:05:29
configTime() 0MS

OFFLINE
getLocalTime() 0MS
2021/09/10 11:05:31
configTime() 0MS
getLocalTime() 0MS
2021/09/10 11:05:32
configTime() 0MS
getLocalTime() 0MS
2021/09/10 11:05:33
configTime() 0MS
```

## NTP更新間隔
configureTime()のコードは下記

```esp-hal-time.c
void configTime(long gmtOffset_sec, int daylightOffset_sec, const char* server1, const char* server2, const char* server3)
{
    //tcpip_adapter_init();  // Should not hurt anything if already inited
    esp_netif_init();
    if(sntp_enabled()){
        sntp_stop();
    }
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, (char*)server1);
    sntp_setservername(1, (char*)server2);
    sntp_setservername(2, (char*)server3);
    sntp_init();
    setTimeZone(-gmtOffset_sec, daylightOffset_sec);
}
```

>An application with this initialization code will periodically synchronize the time. The time synchronization period is determined by CONFIG_LWIP_SNTP_UPDATE_DELAY (the default value is one hour). To modify the variable, set CONFIG_LWIP_SNTP_UPDATE_DELAY in project configuration.

とあり、一定時間ごとにサーバと通信して時刻の更新を行う。

```sdkconfig.h
#define CONFIG_LWIP_SNTP_UPDATE_DELAY 3600000
```

記述通り、デフォルトでは1時間ごとに更新が行われる