| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137 |
- -- LuaTools需要PROJECT和VERSION这两个信息
- PROJECT = "sntpdemo"
- VERSION = "1.0.0"
- --[[
- 核心逻辑:
- 1.判断是否联网,
- 2.网络就绪后开始时间同步
- 3.时间同步成功,获取本地时间和UTC时间,循环默认时间打印一次
- 4.时间同步失败,进行重试获取
- ]]
- -- 配置常量:集中管理参数,方便后续调整
- local CONFIG = {
- -- 等待NTP同步结果的超时时间(ms)
- sntp_timeout = 5000,
- -- 同步成功后,下次同步间隔(ms),默认15秒
- success_interval = 15000,
- -- 同步失败后,重试间隔(ms),默认1分钟
- fail_retry_interval = 60000,
- -- 失败重试最大间隔(ms),避免无限递增,默认5分钟
- max_retry_backoff = 300000,
- -- 自定义NTP服务器列表,可选配置,默认使用内置的ntp服务器地址
- ntp_servers = {
- "ntp.aliyun.com",
- "ntp.air32.cn",
- "time1.cloud.tencent.com"
- }
- }
- -- 打印时间信息的工具函数:抽离重复逻辑,提高可读性
- local function print_time_details()
- -- 获取本地时间字符串
- -- 本地时间字符串 Tue Sep 30 00:22:21 2025
- log.info("sntp", "本地时间字符串", os.date())
- -- 获取UTC时间字符串
- -- UTC时间字符串 Mon Sep 29 16:22:21 2025
- log.info("sntp", "UTC时间字符串", os.date("!%c"))
- -- 格式化本地时间字符串
- -- 本地时间字符串 2025-09-30 00:22:21
- log.info("sntp", "格式化本地时间字符串", os.date("%Y-%m-%d %H:%M:%S"))
- -- 格式化UTC时间字符串
- -- UTC时间字符串 2025-09-29 16:22:21
- log.info("sntp", "格式化UTC时间字符串", os.date("!%Y-%m-%d %H:%M:%S"))
- -- RTC时钟原始数据(UTC时间)
- local rtc_time = rtc.get()
- log.info("sntp", "RTC时钟(UTC)", json.encode(rtc_time))
- -- 本地时间戳(秒级)
- log.info("sntp", "本地时间戳", os.time())
- -- 获取本地时间的table
- -- 本地时间table {"wday":3,"min":22,"yday":273,"hour":0,"isdst":false,"year":2025,"month":9,"sec":21,"day":30}
- local local_struct_time = os.date("*t")
- log.info("sntp", "本地时间结构", json.encode(local_struct_time))
- log.info("sntp", "结构时间转时间戳", os.time(local_struct_time))
- end
- -- 打印高精度时间戳
- local function print_high_precision_time()
- if not socket.ntptm then
- -- 不支持则跳过
- return
- end
- local ntp_time = socket.ntptm()
- if ntp_time and ntp_time.tsec then
- log.info("tm数据", json.encode(ntp_time))
- -- 格式化:秒.毫秒
- log.info("sntp", "高精度时间戳", string.format("%u.%03d", ntp_time.tsec, ntp_time.tms))
- else
- log.warn("sntp", "高精度时间戳获取失败")
- end
- end
- -- SNTP同步主逻辑
- local function sntp_sync_loop()
- -- 等待网络就绪(IP获取成功)
- -- 30秒超时,避免无限等待
- if not sys.waitUntil("IP_READY", 30000) then
- log.error("sntp", "网络未就绪,退出同步")
- return
- end
- log.info("sntp", "网络就绪,开始时间同步流程")
- -- 失败重试计数,用于动态调整间隔
- local fail_retry_count = 0
- while true do
- -- 执行SNTP同步,使用自定义服务器列表
- -- log.info("sntp", "开始同步,服务器列表:", json.encode(CONFIG.ntp_servers))
- -- socket.sntp(CONFIG.ntp_servers)
- log.info("sntp", "开始同步:")
- -- 使用内置的ntp服务器地址
- socket.sntp()
- -- 等待同步结果(成功:NTP_UPDATE,失败:超时)
- local sync_success = sys.waitUntil("NTP_UPDATE", CONFIG.sntp_timeout)
- if sync_success then
- -- 同步成功:重置失败计数,打印时间信息
- fail_retry_count = 0
- log.info("sntp", "时间同步成功")
- print_time_details()
- print_high_precision_time()
- -- 等待下次同步(使用成功间隔)
- sys.wait(CONFIG.success_interval)
- else
- -- 同步失败:累加失败计数,动态调整重试间隔
- fail_retry_count = fail_retry_count + 1
- local retry_interval = math.min(
- CONFIG.fail_retry_interval * (2 ^ (fail_retry_count - 1)),
- -- 不超过最大间隔
- CONFIG.max_retry_backoff
- )
- log.warn("sntp", "时间同步失败", "重试次数:", fail_retry_count, "下次重试间隔(ms):", retry_interval)
- sys.wait(retry_interval)
- end
- end
- end
- -- 订阅NTP错误消息
- sys.subscribe("NTP_ERROR", function(err_info)
- log.error("sntp", "同步过程发生错误", err_info or "未知错误")
- end)
- -- 启动SNTP同步任务
- sys.taskInit(sntp_sync_loop)
|