跳转至

NTP

一、NTP 通信概述

很多场景中,由于业务需要,模块需要保持正确的系统时钟,才能正常工作。但是模块上电后的初试时间戳是 946713600(即 2000/01/01,16:00:00),所以同步时钟成为了开发者要解决的重要问题。对于 Cat.1 模块, 移动/电信卡, 通常会下发基站时间, 那么 sntp 就不是必要的, 而联通卡通常不会下发, 就需要 sntp 了

NTP(Network Time Protocol,网络时间协议)是用于同步系统时间的协议。它通过网络连接多个设备,确保这些设备的系统时钟保持一致。

本例程展示了如何使用 SNTP 授时服务来同步时间。

NTP 和简化版的 SNTP(Simple Network Time Protocol)主要区别在于精确度和复杂性。SNTP 通常用于不需要高精度同步的设备,如嵌入式系统。而 NTP 则用于要求较高时间精度的场景。

二、演示功能概述

本 demo 将连接 NTP 服务器进行时间同步。

三、准备硬件环境

3.1 780E 开发板一套,包括天线、USB 数据线.

淘宝购买链接:Air780E 核心板淘宝购买链接

此核心板的详细使用说明参考:Air780E 产品手册 中的 << 开发板 Core_Air780E 使用说明 V1.0.5.pdf>>,X.X.X 指版本号;核心板使用过程中遇到任何问题,可以直接参考这份使用说明 pdf 文档。

3.2 SIM 卡

请准备一张可正常上网的 SIM 卡,该卡可以是物联网卡或您的个人手机卡。

特别提醒:请确保 SIM 卡未欠费且网络功能正常,以便顺利进行后续操作。

3.3 数据通信线

typec 接口 USB 数据线即可。

3.4 PC 电脑

WINDOWS 系统。

四、准备软件环境

4.1 基本的下载调试工具

使用说明参考:Luatools 下载和详细使用

五、获取 NTP 授时软硬件资料

5.1 文档和工具:

5.2 demo 使用 api 介绍

socket.sntp(sntp_server)

作用:sntp 时间同步

传入值类型
解释
string/table
sntp 服务器地址 选填
int
适配器序号, 只能是 socket.ETH0(外置以太网),socket.LWIP_ETH(内置以太网),socket.LWIP_STA(内置 WIFI 的 STA),socket.LWIP_AP(内置 WIFI 的 AP),socket.LWIP_GP(内置蜂窝网络的 GPRS),socket.USB(外置 USB 网卡),如果不填,优先选择 soc 平台自带能上外网的适配器,若仍然没有,选择最后一个注册的适配器

返回值

os.time(mytime)

作用:时间戳函数

参数

传入值类型
解释
table
日期时间的 table
return
时间戳

返回值

os.date(fmt, time)

作用:日期函数

参数

传入值类型
解释
string
格式化字符串,可以是 nil
table
日期时间的 table

返回值

返回值类型
解释
table/string
根据 fmt 的不同,返回值不同

json.encode(obj,t)

作用:将对象序列化为 json 字符串

参数

传入值类型
解释
obj
需要序列化的对象
string
浮点数精度和模式,这项不存在的时候,为默认值”7f”,数字只支持”0~14”,模式只支持”f/g”

返回值

返回值类型
解释
string
序列化后的 json 字符串, 失败的话返回 nil
string
序列化失败的报错信息

json.decode(str)

作用:将字符串反序列化为对象

参数

传入值类型
解释
string
需要反序列化的 json 字符串

返回值

返回值类型
解释
obj
反序列化后的对象(通常是 table), 失败的话返回 nil
result
成功返回 1,否则返回 0
err
反序列化失败的报错信息

六、代码示例介绍

6.1 使用 ntp 服务器同步时间

6.1.1 demo 介绍

-- 开始时间同步
        socket.sntp()
        -- 自定义ntp地址
        -- socket.sntp("ntp.aliyun.com")
        -- socket.sntp({"baidu.com", "abc.com", "ntp.air32.cn"})
        -- 通常只需要几百毫秒就能成功,超时时间2s
        local ret = sys.waitUntil("NTP_UPDATE", 5000)
        if ret then
            -- 以下是获取/打印时间的演示,注意时区问题
            log.info("sntp", "时间同步成功", "本地时间", os.date())
            log.info("sntp", "时间同步成功", "UTC时间", os.date("!%c"))
            log.info("sntp", "时间同步成功", "RTC时钟(UTC时间)", json.encode(rtc.get()))
            -- os.time(rtc.get()) 需要 2023.07.21 之后的版本, 因为月份的命名差异mon/month
            -- log.info("sntp", "时间同步成功", "utc时间戳", os.time(rtc.get()))
            log.info("sntp", "时间同步成功", "本地时间戳", os.time())
            local t = os.date("*t")
            log.info("sntp", "时间同步成功", "本地时间os.date() json格式", json.encode(t))
            log.info("sntp", "时间同步成功", "本地时间os.date(os.time())", os.time(t))
            -- log.info("sntp", "时间同步成功", "本地时间", os.time())
            -- 正常使用, 一小时一次, 已经足够了, 甚至1天一次也可以
            -- sys.wait(3600000)
            -- 这里为了演示, 用5秒一次
            sys.wait(5000)
        else
            log.info("sntp", "时间同步失败")
            sys.wait(60000) -- 1分钟后重试
        end

        -- 时间戳, 精确到毫秒. 2023.11.15 新增
        -- 注意, 至少成功完成2次sntp,该时间戳才比较准确
        -- 如果仅完成了一次sntp, 时间戳比标准时间会慢一个网络延时的时长(10~500ms)不等
        if socket.ntptm then
            local tm = socket.ntptm()
            log.info("tm数据", json.encode(tm))
            log.info("时间戳", string.format("%u.%03d", tm.tsec, tm.tms))
            sys.wait(5000)
        end
    end
end)

sys.subscribe("NTP_ERROR", function()
    log.info("socket", "sntp error")
    -- socket.sntp()
end)

6.1.2 将程序下载到开发板

参考:将固件和脚本烧录到模块中:Luatools 下载和使用教程 - 合宙模组资料中心

七、功能验证

八、总结

本 demo 介绍了如何使用 ntp 服务器同步时间。

扩展

常见问题

1、ntp 同步时间后,这个 clock 精度高吗,需要多久同步一次

并不能保证任何时间任何地点都能百分百同步到正确的时间。 所以,如果用户项目中的业务逻辑严格依赖于时间同步功能 则不要使用本功能模块,建议使用自己的应用服务器来同步时间。

2、多长时间 ntp 同步一次

正常使用, 一小时一次, 已经足够了, 甚至 1 天一次也可以。

3、这个函数 socket.sntp()后每次在程序中调用 os.time 也是实时时间了吗?

是的,只要时间同步成功了,就是实时时间了。

给读者的话

本篇文章由Linden开发;

本篇文章描述的内容,如果有错误、细节缺失、细节不清晰或者其他任何问题,总之就是无法解决您遇到的问题;

请登录合宙技术交流论坛,点击文档找错赢奖金-Air780E-LuatOS-软件指南-网络驱动-NTP通信

用截图标注+文字描述的方式跟帖回复,记录清楚您发现的问题;

我们会迅速核实并且修改文档;

同时也会为您累计找错积分,您还可能赢取月度找错奖金!