ESP32/Arduino の 時刻取得のオフライン時の挙動
ESP32で現在時刻を取得するにはNTPを使いますが、オフライン/オフライン時の挙動が知りたかったので、軽くテストしてみました。
なお、NTP関連は下記に詳しい。(この記事含めて下手な日本語ページを見るよりは、機械翻訳でマニュアルを読むほうが素早く答にたどり着く)
結果
- 一度もオンラインになっていない場合は、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時間ごとに更新が行われる