我使用带有esp-idf的ESP32。我需要正确的时间,因此我正在尝试与NTP服务器重新同步时间。我使用这个例子。1:https://github.com/espressif/esp-idf/tree/master/examples/protocols/sntp
当我再次调用obtain_time()方法时,设备正在重新启动。
我做错了什么?我没有找到任何有帮助的东西。
I (2259) initialise_wifi: Setting WiFi configuration SSID OpenWrt
I (2359) syncTime: I'm runing :)
I (2369) getTimeNow: Time is not set yet. Connecting to WiFi and getting time over NTP.
I (2389) initialize_sntp: Initializing SNTP
I (2389) obtain_time: Waiting for system time to be set... (1/10)
...
I (18389) obtain_time: Waiting for system time to be set... (9/10)
-----The time is correct, but when i'm trying resync with NTP
I (20639) getTimeNow: Time is not set yet. Connecting to WiFi and getting time over NTP.
I (20639) initialize_sntp: Initializing SNTP
assertion "Operating mode must not be set while SNTP client is running" failed: file "/home/lenovov510/esp/esp-idf/components/lwip/lwip/src/apps/sntp/sntp.c", line 600, function: sntp_s
etoperatingmode
abort() was called at PC 0x400d2c6b on core 1
ELF file SHA256: 145d1f5e047670ed10c462ae090b3e64db1c5aa158a9988417a513b2ee801051
Backtrace: 0x4008623c:0x3ffc7e00 0x40086489:0x3ffc7e20 0x400d2c6b:0x3ffc7e40 0x4011e251:0x3ffc7e70 0x400d28b4:0x3ffc7e90 0x400d28c7:0x3ffc7eb0 0x400d2aff:0x3ffc7f10 0x400d2bcd:0x3ffc7fa0
0x4008b569:0x3ffc7fc0
Rebooting... 下面是我的方法:
This give back the timestamp.
void getDateTime(char *dateTime)
{
char *TAG = "getDateTime";
time_t now;
struct tm timeinfo;
time(&now);
localtime_r(&now, &timeinfo);
char strftime_buf[64];
setenv("TZ", "GTM-2", 1);
tzset();
localtime_r(&now, &timeinfo);
strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
sprintf(dateTime, "20%d-%d-%d+%d:%d:%d", timeinfo.tm_year - 100, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec);
}
This method trying to update time.
void syncTime()
{
char *TAG = "syncTime";
obtain_time();
}
static void obtain_time(void)
{
static const char *TAG = "obtain_time";
initialize_sntp();
time_t now = 0;
struct tm timeinfo = {0};
int retry = 0;
const int retry_count = 10;
while (retry!=retry_count)// timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count )
{
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
vTaskDelay(2000 / portTICK_PERIOD_MS);
time(&now);
localtime_r(&now, &timeinfo);
}
}
//----
static void initialize_sntp(void)
{
static const char *TAG = "initialize_sntp";
ESP_LOGI(TAG, "Initializing SNTP");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();
...
//Update the timeInSec and Datettime variable
void updateTimeVariables(void *pvParameter)
{
char *TAG = "updateTimeVariables";
while (1 == 1)
{
getDateTime(dateTime);
timeInSec = getTimeNow();
vTaskDelay(500 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
//Sync NTP server.
void updateTime(void *pvParameter)
{
char *TAG = "updateTime";
while (1 == 1)
{
syncTime();
vTaskDelay(10000 / portTICK_PERIOD_MS);//1800000 / portTICK_PERIOD_MS);
}
vTaskDelete(NULL);
}
...
xTaskCreate(&updateTime, "updateTime", 4000, NULL, 6, NULL);
xTaskCreate(&updateTimeVariables, "updateTimeVariables", 4000, NULL, 0, NULL);发布于 2019-12-01 04:46:10
要解决这个问题,您需要做几件事。1.)修改users/[username]/.platformio/packages/framework-espidf/components/lwip/lwip/src/apps/sntp/sntp.c和users/[username]/.platformio/packages/framework-espidf/components/lwip/lwip/include/lwip/apps/sntp.h文件中的sntp.c文件,并更改以下内容:
a.)在sntp.c文件中-将static void sntp_request(void *arg)更改为“void sntp_request(void *arg)”,以使其他模块可以使用该函数。它位于源文件中的第490行附近。此外,在第160行,删除单词"static“以防止编译器错误。
b.)在sntp.h头文件中,添加语句void sntp_request(void *)以使函数原型可用于您的代码。
下面是我的代码,修改后的代码允许根据需要调用sntp_request()。我每隔30分钟左右打电话一次,但你可以等待更长的时间,也许一天一次,这将足以保持时钟的合理稳定。
bool sntp_1st_init = true; // 1st init call allowed
static void obtain_time(void)
{
if(sntp_1st_init) // doing this again?
{
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "north-america.pool.ntp.org");
ESP_LOGI(TAG, "Initializing SNTP");
sntp_1st_init = false; // don't call again
sntp_init(); // init and set time
}
else
{
ESP_LOGI(TAG, "Syncing System Time");
sntp_request(NULL); // sync time again
}
// wait for System time to be set by monitoring Date changes
int retry = 0;
const int retry_count = 15;
while(timeinfo.tm_year < (2016 - 1900) && ++retry < retry_count)
{
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)",
retry, retry_count);
vTaskDelay((1 * ONEsec) / portTICK_PERIOD_MS);
time(&now);
localtime_r(&now, &timeinfo);
}
}bool "sntp_1st_init“在程序启动时设置为true,在第一次sntp初始化后设置为false。对"sntp_setoperatingmode(SNTP_OPMODE_POLL)“的调用只能执行一次,因此必须放在sntp_1st_init代码部分。
我已经确认,通过将系统时间更改为除正确时间之外的其他时间,并观察到时间按预期进行了更正,这些更改会起作用。
原始作者通过使sntp_request()函数成为静态函数来限制sntp代码的功能,防止用户对计算机时钟时间进行额外的sntp校正。即使是最好的振荡器也会随着时间的推移而漂移,如果你要费心使用sntp,你不妨也考虑到时钟漂移校正。
希望这能有所帮助。
曾傑瑞
JWM工程小组
发布于 2020-04-03 00:10:22
幸运的是,sntp_stop()函数不会删除以前的设置(包括服务器),因此您可以使用以下命令:
sntp_stop();
sntp_init();在第一次运行时,同步需要大约30s,随后的运行需要大约500ms。
我将其放在一个FreeRTOS任务中:
#include "esp_sntp.h"
#include "freertos/task.h"
void update(void* pvParameters) {
while (true) {
sntp_stop();
sntp_init();
vTaskDelay(pdMS_TO_TICKS(60 * 60 * 1000));
}
}
void setup(void) {
// Add your SNTP setup code here
xTaskCreate(update, "NtpUpdate", 2048, NULL, tskIDLE_PRIORITY,
&updateHandle);
}发布于 2020-05-14 08:32:37
通过issue 4386,SNTP documentation已更新为以下内容:
使用此初始化代码的
应用程序将定期同步时间。时间同步周期由CONFIG_LWIP_SNTP_UPDATE_DELAY决定(默认值为1小时)。要修改该变量,请在项目配置中设置CONFIG_LWIP_SNTP_UPDATE_DELAY。
您只需在应用程序中使用以下代码:
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();https://stackoverflow.com/questions/56025619
复制相似问题