Air780E模组如何通过NTP来确保时间同步?
很多场景中,模块需要保持正确的系统时钟,才能正常工作。但是模块上电后的初试时间戳是 946713600(即 2000/01/01,16:00:00),所以同步时钟成为了开发者要解决的重要问题。
一、NTP简介
NTP(Network Time Protocol,网络时间协议)是用于同步系统时间的协议。它通过网络连接多个设备,确保这些设备的系统时钟保持一致。
本例程展示了如何使用 SNTP 授时服务来同步时间。
NTP 和简化版的 SNTP(Simple Network Time Protocol)主要区别在于精确度和复杂性。SNTP 通常用于不需要高精度同步的设备,如嵌入式系统。而 NTP 则用于要求较高时间精度的场景。
本 demo 将连接 NTP 服务器进行时间同步。
二、准备硬件环境
2.1 780E 开发板一套,包括天线、USB 数据线.
此核心板的详细使用说明参考:Air780E 产品手册 中的 << 开发板 Core_Air780E 使用说明 V1.0.5.pdf>>,X.X.X 指版本号;核心板使用过程中遇到任何问题,可以直接参考这份使用说明 pdf 文档。

2.2 SIM 卡
请准备一张可正常上网的 SIM 卡,该卡可以是物联网卡或您的个人手机卡。
特别提醒:请确保 SIM 卡未欠费且网络功能正常,以便顺利进行后续操作。
2.3 数据通信线
typec 接口 USB 数据线即可。
2.4 PC 电脑
WINDOWS 系统。
三、准备软件环境
基本的下载调试工具
Luatools工具:Luatools新手必看:从下载开始的保姆级教程!-CSDN博客
四、获取 NTP 授时软硬件资料
4.1 文档和工具:
- 本 demo 使用的固件版本是:LuatOS-SoC_V1112_EC618_FULL.soc
- 本教程使用的 demo:https://gitee.com/openLuat/LuatOS-Air780E/tree/master/demo/sntp
- 将固件和脚本烧录到模块中:Luatools新手必看:从下载开始的保姆级教程!-CSDN博客
- 源码和固件已打包,如下所示: 点我,下载完整压缩文件包
4.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 | 反序列化失败的报错信息 |
五、代码示例介绍
5.1 使用 ntp 服务器同步时间
5.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)
5.1.2 将程序下载到开发板
参考:将固件和脚本烧录到模块中:Luatools新手必看:从下载开始的保姆级教程!-CSDN博客
六、功能验证

七、总结
本 demo 介绍了如何使用 ntp 服务器同步时间。
八、常见问题
1、ntp 同步时间后,这个 clock 精度高吗,需要多久同步一次
并不能保证任何时间任何地点都能百分百同步到正确的时间。 所以,如果用户项目中的业务逻辑严格依赖于时间同步功能 则不要使用本功能模块,建议使用自己的应用服务器来同步时间。
2、多长时间 ntp 同步一次
正常使用, 一小时一次, 已经足够了, 甚至 1 天一次也可以。
3、这个函数 socket.sntp()后每次在程序中调用 os.time 也是实时时间了吗?
是的,只要时间同步成功了,就是实时时间了。
更多推荐
所有评论(0)