ESP32学习笔记(41)——SNTP接口使用

一、SNTP简介

简单网络时间协议(Simple Network Time Protocol),由 NTP 改编而来,主要用来同步因特网中的计算机时钟。

SNTP 协议是用来同步本地的时间到 unix 时间戳。通常嵌入式设备上电,连接 AP(access point),获取 IP 地址后,就需要使用 SNTP 协议获取全球时间。以便于下一步的应用交互和使用。
SNTP 工作原理比较简单, 通俗来说,就是设备向 SNTP server 发送一包 SNTP 请求,服务器收到请求后回复一包 SNTP reply。其中 SNTP reply 中就含有 unix 时间戳。

ESP-IDF 编程指南——SNTP 时间同步

二、API说明

以下 SNTP 接口位于 lwip/include/apps/esp_sntp.h

2.1 sntp_setoperatingmode

2.2 sntp_setservername

2.3 sntp_set_time_sync_notification_cb

2.4 sntp_init

2.5 sntp_get_sync_status

三、示例代码

根据 examples\protocols\sntp 中的例程修改

在 menuconfig 中配置 SSID 和密码

核心部分:

//设置单播模式
sntp_setoperatingmode(SNTP_OPMODE_POLL);
//设置访问服务器
sntp_setservername(0, "pool.ntp.org");
//初始化SNTP模块
sntp_init();

完整代码:

/* LwIP SNTP example

   This example code is in the Public Domain (or CC0 licensed, at your option.)

   Unless required by applicable law or agreed to in writing, this
   software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
   CONDITIONS OF ANY KIND, either express or implied.
*/
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_sleep.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "esp_sntp.h"

static const char *TAG = "example";

static void obtain_time(void);
static void initialize_sntp(void);

void time_sync_notification_cb(struct timeval *tv)
{
    ESP_LOGI(TAG, "Notification of a time synchronization event");
}

void app_main(void)
{
    time_t now;
    struct tm timeinfo;
    time(&now);
    localtime_r(&now, &timeinfo);
    // Is time set? If not, tm_year will be (1970 - 1900).
    if (timeinfo.tm_year < (2021 - 1900)) {
        ESP_LOGI(TAG, "Time is not set yet. Connecting to WiFi and getting time over NTP.");
        obtain_time();
        // update 'now' variable with current time
        time(&now);
    }

    char strftime_buf[64];

    while (1)
    {
        // update 'now' variable with current time
        time(&now);

        // Set timezone to China Standard Time
        setenv("TZ", "CST-8", 1);
        tzset();
        localtime_r(&now, &timeinfo);
        strftime(strftime_buf, sizeof(strftime_buf), "%c", &timeinfo);
        ESP_LOGI(TAG, "The current date/time in Shanghai is: %s", strftime_buf);

        vTaskDelay(10000 / portTICK_PERIOD_MS);
    }
}

static void obtain_time(void)
{
    ESP_ERROR_CHECK( nvs_flash_init() );
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK( esp_event_loop_create_default() );

    /* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
     * Read "Establishing Wi-Fi or Ethernet Connection" section in
     * examples/protocols/README.md for more information about this function.
     */
    ESP_ERROR_CHECK(example_connect());

    initialize_sntp();

    // wait for time to be set
    time_t now = 0;
    struct tm timeinfo = { 0 };
    int retry = 0;
    const int retry_count = 10;
    while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++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);

    ESP_ERROR_CHECK( example_disconnect() );
}

static void initialize_sntp(void)
{
    ESP_LOGI(TAG, "Initializing SNTP");
    sntp_setoperatingmode(SNTP_OPMODE_POLL);
    sntp_setservername(0, "pool.ntp.org");
    sntp_set_time_sync_notification_cb(time_sync_notification_cb);
    sntp_init();
}

查看打印:

四、注意事项

  1. sntp_setservername 除了可以设置域名, 也可以设置 IP 地址, 例如 sntp_setservername(0, "120.25.115.20");
  2. 如果有必要, 请多设置几个 SNTP server,防止某个 SNTP server 暂时关闭服务而导致产品部分功能无法使用, 例如:
sntp_setservername(0, "ntp1.aliyun.com");
sntp_setservername(1, "210.72.145.44");		// 国家授时中心服务器 IP 地址
sntp_setservername(2, "1.cn.pool.ntp.org");        

说明:
默认情况下, ESP8266/ESP32 只允许开启一个 SNTP server(节省资源考虑), 如果用户需开启多个 SNTP server, 请配置:

  • ESP8266 请在 make menuconfig -> Component config -> LWIP -> DHCP -> Maximum bumber of NTP servers 修改为 3
  • ESP32 请在 make menuconfig -> Component config -> LWIP -> SNTP -> Maximum bumber of NTP servers 修改为 3

配置多个 SNTP server 时, 不是同时发送多个 SNTP 请求报文, 而是轮循方式. 第一个处理超时后, 进行和第二个 SNTP server 交互, 这样依次进行到最后一个, 最后一个处理超时后, 会再和第一个 SNTP server 交互

  1. 更新时间请求间隔SNTP_UPDATE_DELAY,到下一次发起更新时间请求的间隔时间,单位是ms,最小不能小于15s,也是通过make menuconfig修改CONFIG_LWIP_SNTP_UPDATE_DELAY
    在 make menuconfig -> Component config -> LWIP -> SNTP -> Request interval to update time (ms).

  2. 最好不在任何 callback 或中断处理函数中调用 obtain_time(), callback/中断中, 调用任何阻塞的 API, 理论上都有死锁的可能.

  3. 任何有校验服务器证书的 TLS 过程 (本地有 CA 证书), 请务必开启 SNTP 功能, 否则会因为校验服务器证书有效期失败而导致 TLS 握手失败

  4. NTP.ORG.cn中国NTP授时快速域名服务提供商

新加坡sgp.ntp.org.cn韩国kr.ntp.org.cn
中国cn.ntp.org.cn中国教育网edu.ntp.org.cn
中国香港hk.ntp.org.cn中国台湾tw.ntp.org.cn
美国us.ntp.org.cn韩国kr.ntp.org.cn
日本jp.ntp.org.cn德国de.ntp.org.cn
印度尼西亚ina.ntp.org.cn
  1. 时区:
  • CST-8:这时区的表示有点混
    CST却同时可以代表如下 4 个不同的时区:
    Central Standard Time (USA) UT-6:00
    Central Standard Time (Australia) UT+9:30
    China Standard Time UT+8:00
    Cuba Standard Time UT-4:00
setenv("TZ", "CST-8", 1);
  • GMT:(Greenwich Mean Time)是格林尼治平时
    GMT+8正好是中国的标准时区
setenv("TZ", "GMT+8", 1);
  1. 在成功获取了网络时间后,必须调用 sntp_stop(); 停止NTP请求,不然设备重启后会造成获取网络时间失败的现象,大概是服务器时根据心跳时间来删除客户端的,如果不是stop结束的客户端,下次连接服务器时就会出错

• 由 Leung 写于 2021 年 7 月 30 日

• 参考:ESP8266/ESP32 基础篇: 时间同步 SNTP 介绍和使用
    ESP32 SNTP配置
    ESP32的SDK开发之获取SNTP网络时间

### 回答1: ESP8266是一种低成本、高性能的Wi-Fi芯片,广泛应用于物联网(IoT)领域。SNTP(Simple Network Time Protocol)是一种基于UDP协议的时间同步协议,在物联网设备中具有重要的应用价值。 ESP8266通过SNTP协议与互联网中的时间服务器通信,获得准确的时间戳。这些时间戳可用于日志记录、事件触发、时间截止等应用场景。 SNTP协议本身非常简单,可以使用ESP8266的标准库集成到程序中。通过WiFi连接到局域网或互联网后,ESP8266可以与指定的时间服务器同步,获取与本地时间的时间差。为了准确,ES8266通常使用多个时间服务器进行同步,并进行平均计算。 值得注意的是,SNTP协议是基于UDP协议的,因此无法保证在传输过程中的可靠性。为了解决这个问题,ESP8266通常会定期进行时间同步,以保证时间准确性。当然,若是在时间同步失败的情况下采用短时间运行,错误也会相应地累积。因此,一些特殊的应用场景需要采用GPS等时间同步手段来确保时间的准确性。 总之,ESP8266通过SNTP协议可以快速、准确地获取互联网上的时间戳,因此在物联网设备的时间同步方面拥有巨大的应用潜力。 ### 回答2: ESP8266是一款低成本的Wi-Fi芯片,可以方便的接入互联网。SNTP(Simple Network Time Protocol)是一种简单的网络时间协议,用于同步网络设备的时间。 在ESP8266中,可以使用SNTP协议来同步设备的时间。通过连接SNTP服务器,ESP8266可以获取世界标准时间,并将其与本地时间进行比较和更新。这非常有用,因为设备的时间通常需要与其他设备同步,以便它们可以协调它们的操作。 ESP8266支持SNTP协议的库如下: • sntp.h • sntp.c 这些库可以在ESP8266的开发环境中进行安装和使用使用这些库,可以轻松地与SNTP服务进行通信,以便同步设备的时间。在使用这些库时,用户需要提供SNTP服务器的IP地址和端口号。然后,ESP8266会连接到服务器并获取当前的时间。 SNTP协议的一个重要特点是具有低带宽和延迟。这使得设备可以在非常低的成本和能耗下同步时间。由于ESP8266的能源需求非常低,因此使用SNTP协议进行时间同步是非常有效的方法。这使得ESP8266成为物联网设备设计的首选芯片之一。 ### 回答3: ESP8266是一款高性能、低功耗、易于开发的Wi-Fi芯片,可以通过SNTP协议进行时间同步。SNTP(Simple Network Time Protocol)是NTP协议的简化版本,用于进行网络时间同步。 在ESP8266上使用SNTP进行时间同步,需要先通过WiFi连接到网络。然后,使用SNTP协议向NTP服务器请求时间信息,并将服务器返回的时间设定为ESP8266的系统时间。这个过程可以使用ESP8266自带的API实现,也可以使用第三方库完成。 使用SNTP同步时间有很多好处,其中最主要的就是可以保证设备时间的准确性。在一些需要高精度时间的应用场景,比如金融、物流等领域,时间同步显得尤为关键。 总之,ESP8266虽然是一款小巧的芯片,但它拥有丰富的功能和强大的性能,可以为各种物联网应用提供稳定可靠的支持。SNTP协议则是保证ESP8266时间准确性的重要手段之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Leung_ManWah

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值