Espruino on ESP32 起動時に時刻合わせを行う
ESP32のRTCはバッテリバックアップされていないようなので、電源OFFで時刻を忘れてしまうようです。
あ、以前(Espruino on ESP32 でぽちっとな - いっぺーちゃんの いろいろやってみよ~) gettimeofday使わないようにしたので、RTCがバッテリバックアップされていてもダメか。
時刻合わせを行うには、SNTPでタイムサーバから時刻を取得するのが一般的ですが、EspruinoはUDP通信をサポートしていない(!!!?)ので、SNTP処理をJavascriptで記述できません。
次の記事では、時刻合わせをしておく必要があるので、とりあえず、起動時にSNTPを実行して時刻合わせを行うような処理を追加しておきます。
targets/esp32/main.c に以下の修正を加えます。
diff --git a/targets/esp32/main.c b/targets/esp32/main.c index 00a9dcf..024ad6b 100644 --- a/targets/esp32/main.c +++ b/targets/esp32/main.c @@ -41,6 +41,47 @@ static void timerTask(void *data) { } } +// ADD start [IPPEI] +#include "apps/sntp/sntp.h" +static void sntpTask(void *data) { + int t_flag = 0; + time_t now = 0; + int retry = 0; + const int retry_count = 10; + + jsiConsolePrintf("SNTP_task: Initializing SNTP\n"); + sntp_setoperatingmode(SNTP_OPMODE_POLL); + sntp_setservername(0, "pool.ntp.org"); + sntp_init(); + // wait for time to be set + retry = 0; + while(++retry < retry_count) { + // jsiConsolePrintf("SNTP_task: Waiting for system time to be set... (%d/%d)\n", retry, retry_count); + vTaskDelay(2000 / portTICK_PERIOD_MS); + time(&now); + //printf("SNTP_task: time :%ld\n", now); + if (now >= 946684800) { + // 2000/1/1 00:00:00 ~ + t_flag = 1; + // set system time + JsSysTime stime = (JsSysTime)now * (JsSysTime)(1000*1000); + jsiLastIdleTime = stime; + jshSetSystemTime(stime); + break; + } + } + if (!t_flag) { + jsiConsolePrintf("SNTP_task: **** system time is NOT set ****\n>"); + } + else { + jsiConsolePrintf("SNTP_task: system time is set\n>"); + } + // jsiConsolePrintf("SNTP_task: stop SNTP\n"); + sntp_stop(); + vTaskDelete(NULL); +} +// ADD end [IPPEI] + static void espruinoTask(void *data) { PWMInit(); @@ -91,10 +132,12 @@ int app_main(void) task_init(espruinoTask,"EspruinoTask",20000,5,0); task_init(uartTask,"ConsoleTask",2000,20,0); task_init(timerTask,"TimerTask",2048,19,0); + task_init(sntpTask,"sntpTask",2048,19,0); #else xTaskCreatePinnedToCore(&espruinoTask, "espruinoTask", 20000, NULL, 5, NULL, 0); xTaskCreatePinnedToCore(&uartTask,"uartTask",2000,NULL,20,NULL,0); xTaskCreatePinnedToCore(&timerTask,"timerTask",2048,NULL,19,NULL,0); + xTaskCreatePinnedToCore(&sntpTask,"sntpTask",2048,NULL,19,NULL,0); #endif return 0; }
処理としては、起動時に sntpTask を起動し、その中でSNTP処理を起動、時刻が設定されるのを待ちます。
時刻が設定されたら(2000年1月1日 00:00:00 以降の時刻を取得できたら設定済みとみなす)、システム時刻を設定し、SNTP処理を終了してタスクを終了します。
時刻が設定されていなければ、2秒待ってリトライ。retry_count回(あ、retry_count-1回か?サンプルプログラムから拾ってきたままだ(^^ゞ。。。その辺はあまり重要ではないので。)行ってもダメなら設定を諦めます。
使用するタイムサーバを変更したいときは、sntp_setservernameの第2パラメータを変更してください。
メインタスクで処理を行わず専用のタスクを起動しているのは、時刻設定待ちでシステム起動を中断しないためです。
無事時刻が設定されれば、コンソールに「SNTP_task: system time is set」と表示されます。
時刻を取得するには、
var date=new Date()
と実行すれば現在の時刻が取得できます。
時刻を年月日時分秒で確認するには以下のように実行します。
console.log(date.toString()) Sun Jul 23 2017 03:45:00 GMT+0000
。。。時刻が違うって?
デフォルトではグリニッジ標準時(GMT)です。
(UTCの方が正しいと思うけど、気にしない)
日本時間を表示するには、以下のようにtimezoneを設定します。
E.setTimeZone(9);
再度表示してみます。
console.log(date.toString()) Sun Jul 23 2017 12:45:00 GMT+0900
はい、できました。