The issue: I have made a WEB app for setting. It has 2 options for RTC - SNTP and manual set up. SNTP works well. But manual not...
It received GET request like - rtc_datetime=2022-12-06T07%3A02
if(httpd_query_key_value(qry, "rtc_datetime", temp, MAX_GET_QRY_VAL_LEN) == ESP_OK) {
// decoding %3A to : etc
decode(temp,value);
//strcpy(value,temp);
ESP_LOGI(TAG, "Time is: %s", value);
if(value[0]=='\0') {
char resp[] = "Set manual time mode";
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
return ESP_OK;
}
//tm.tm_year = (value[0] - '0')*1000 + (value[1] - '0')*100 + (value[2] - '0')*10 + (value[3] - '0') - 1900;//year
tm.tm_year = string2int(value,4) - 1900;
ESP_LOGI(TAG, "year is: %d", tm.tm_year);
//tm.tm_mon = (value[5] - '0')*10 + (value[6] - '0'); //month
tm.tm_mon = string2int(value+5,2) - 1;
ESP_LOGI(TAG, "mon is: %d", tm.tm_mon);
//tm.tm_mday = (value[8] - '0')*10 + (value[9] - '0');; // day
tm.tm_mday = string2int(value+8,2);
ESP_LOGI(TAG, "day is: %d", tm.tm_mday);
//tm.tm_hour = (value[11] - '0')*10 + (value[12] - '0'); // hour
tm.tm_hour = string2int(value+11,2);
ESP_LOGI(TAG, "hour is: %d", tm.tm_hour);
//tm.tm_min = (value[14] - '0')*10 + (value[15] - '0'); // minute
tm.tm_min = string2int(value+14,2);
ESP_LOGI(TAG, "min is: %d", tm.tm_min);
tm.tm_sec = 0;
time_t t = mktime(&tm);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));
struct timeval new;
new.tv_usec = 0;
new.tv_sec = t;
settimeofday(&new, NULL);
//localtime(&t);
struct tm timeinfo2;
timeinfo2.tm_sec = 0;
timeinfo2.tm_min = 0;
time_t now2;// = time(NULL);
time(&now2);
localtime_r(&now2, &timeinfo2);
ESP_LOGI(TAG, "curr time - %4d-%2d-%2d %2d:%2d", timeinfo2.tm_year+1900, timeinfo2.tm_mon+1, timeinfo2.tm_mday, timeinfo2.tm_hour, timeinfo2.tm_min);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));
char resp[] = "Time is set";
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
asctime(&tm) shows correct time from URL. But time in timeinfo2 has difference 17 minutes and 53 seconds...
Line by line log:
I (16452) web server: GET request: form=rtc_form&rtc_datetime=2022-12-06T19%3A21&rtc_tz=458
I (16452) web server: r0_form
I (16452) web server: r1_form
I (16452) web server: rtc_form
I (16462) system config: sntp: 0
I (16462) system config: rtc_tz: 458
I (16462) system config: Save /spiffs/rtc.json
I (16492) system config: Set: {"rtc_sntp":0,"rtc_tz":458}
I (16492) web server: Time is: 2022-12-06T19:21
I (16492) web server: year is: 122
I (16492) web server: mon is: 11
I (16502) web server: day is: 6
I (16502) web server: hour is: 19
I (16512) web server: min is: 21
I (16512) web server: The local date and time is: Tue Dec 6 19:21:00 2022
I (16522) web server: curr time - 2022-12- 6 19:38
I (16522) web server: The local date and time is: Tue Dec 6 19:38:53 2022
I have no idea what I do wrong....
tm.tm_year = 2022 - 1900;
tm.tm_mon = 0;
tm.tm_mday = 0;
tm.tm_hour = 0;
tm.tm_min = 0;
tm.tm_sec = 0;
time_t t = mktime(&tm);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&tm));
struct timeval new;
new.tv_usec = 0;
new.tv_sec = t;
settimeofday(&new, NULL);
struct tm timeinfo2;
timeinfo2.tm_sec = 0;
timeinfo2.tm_min = 0;
time_t now2;
time(&now2);
localtime_r(&now2, &timeinfo2);
ESP_LOGI(TAG, "The local date and time is: %s", asctime(&timeinfo2));
So, this is the code without any data from GET request. Hm... What is a correct initialization for tm struct? I thing true is near... mktime() "makes" this issue or tm struct is wrong initialized. The same problem:
I (22892) web server: The local date and time is: Fri Dec 31 00:00:00 2021
I (22902) web server: The local date and time is: Fri Dec 31 00:17:53 2021
I add ctime() log for checking mktime() output, so it showes correct
time_t t = mktime(&tm);
ESP_LOGI(TAG, "Time from epoch t: %s", ctime(&t));
ESP_LOGI(TAG, "Time from tm: %s", asctime(&tm));
Console log:
I (18012) web server: Time from epoch t: Thu Dec 8 09:13:00 2022
I (18022) web server: Time from tm: Thu Dec 8 09:13:00 2022
I've found the same problem in espressif GitHub issues.
It looks like the issue is in the settimeofday()
function.
So, I implemented the same workaround:
settimeofday(&new, NULL);
struct timeval get_set_time;
gettimeofday(&get_set_time,NULL);
int time_diff = get_set_time.tv_sec - new.tv_sec;
ESP_LOGI(TAG, "Difference in time: %d", time_diff);
new.tv_sec -= time_diff;
settimeofday(&new, NULL);
Log:
I (15322) web server: Difference in time: 1073
Moreover, the project was migrated to IDF 5.0 version — the bug is no longer there in the settimeofday()
. So, the problem was solved.