首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在esp-idf中从NTP服务器重新同步时间?

如何在esp-idf中从NTP服务器重新同步时间?
EN

Stack Overflow用户
提问于 2019-05-07 23:10:08
回答 3查看 4K关注 0票数 0

我使用带有esp-idf的ESP32。我需要正确的时间,因此我正在尝试与NTP服务器重新同步时间。我使用这个例子。1:https://github.com/espressif/esp-idf/tree/master/examples/protocols/sntp

当我再次调用obtain_time()方法时,设备正在重新启动。

我做错了什么?我没有找到任何有帮助的东西。

代码语言:javascript
复制
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...   

下面是我的方法:

代码语言:javascript
复制
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);
EN

回答 3

Stack Overflow用户

发布于 2019-12-01 04:46:10

要解决这个问题,您需要做几件事。1.)修改users/[username]/.platformio/packages/framework-espidf/components/lwip/lwip/src/apps/sntp/sntp.cusers/[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分钟左右打电话一次,但你可以等待更长的时间,也许一天一次,这将足以保持时钟的合理稳定。

代码语言:javascript
复制
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工程小组

票数 0
EN

Stack Overflow用户

发布于 2020-04-03 00:10:22

幸运的是,sntp_stop()函数不会删除以前的设置(包括服务器),因此您可以使用以下命令:

代码语言:javascript
复制
sntp_stop();
sntp_init();

在第一次运行时,同步需要大约30s,随后的运行需要大约500ms。

我将其放在一个FreeRTOS任务中:

代码语言:javascript
复制
#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);
}
票数 0
EN

Stack Overflow用户

发布于 2020-05-14 08:32:37

通过issue 4386SNTP documentation已更新为以下内容:

使用此初始化代码的

应用程序将定期同步时间。时间同步周期由CONFIG_LWIP_SNTP_UPDATE_DELAY决定(默认值为1小时)。要修改该变量,请在项目配置中设置CONFIG_LWIP_SNTP_UPDATE_DELAY。

您只需在应用程序中使用以下代码:

代码语言:javascript
复制
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56025619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档