ntp_test.lua 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. -- LuaTools需要PROJECT和VERSION这两个信息
  2. PROJECT = "sntpdemo"
  3. VERSION = "1.0.0"
  4. --[[
  5. 核心逻辑:
  6. 1.判断是否联网,
  7. 2.网络就绪后开始时间同步
  8. 3.时间同步成功,获取本地时间和UTC时间,循环默认时间打印一次
  9. 4.时间同步失败,进行重试获取
  10. ]]
  11. -- 配置常量:集中管理参数,方便后续调整
  12. local CONFIG = {
  13. -- 等待NTP同步结果的超时时间(ms)
  14. sntp_timeout = 5000,
  15. -- 同步成功后,下次同步间隔(ms),默认15秒
  16. success_interval = 15000,
  17. -- 同步失败后,重试间隔(ms),默认1分钟
  18. fail_retry_interval = 60000,
  19. -- 失败重试最大间隔(ms),避免无限递增,默认5分钟
  20. max_retry_backoff = 300000,
  21. -- 自定义NTP服务器列表,可选配置,默认使用内置的ntp服务器地址
  22. ntp_servers = {
  23. "ntp.aliyun.com",
  24. "ntp.air32.cn",
  25. "time1.cloud.tencent.com"
  26. }
  27. }
  28. -- 打印时间信息的工具函数:抽离重复逻辑,提高可读性
  29. local function print_time_details()
  30. -- 获取本地时间字符串
  31. -- 本地时间字符串 Tue Sep 30 00:22:21 2025
  32. log.info("sntp", "本地时间字符串", os.date())
  33. -- 获取UTC时间字符串
  34. -- UTC时间字符串 Mon Sep 29 16:22:21 2025
  35. log.info("sntp", "UTC时间字符串", os.date("!%c"))
  36. -- 格式化本地时间字符串
  37. -- 本地时间字符串 2025-09-30 00:22:21
  38. log.info("sntp", "格式化本地时间字符串", os.date("%Y-%m-%d %H:%M:%S"))
  39. -- 格式化UTC时间字符串
  40. -- UTC时间字符串 2025-09-29 16:22:21
  41. log.info("sntp", "格式化UTC时间字符串", os.date("!%Y-%m-%d %H:%M:%S"))
  42. -- RTC时钟原始数据(UTC时间)
  43. local rtc_time = rtc.get()
  44. log.info("sntp", "RTC时钟(UTC)", json.encode(rtc_time))
  45. -- 本地时间戳(秒级)
  46. log.info("sntp", "本地时间戳", os.time())
  47. -- 获取本地时间的table
  48. -- 本地时间table {"wday":3,"min":22,"yday":273,"hour":0,"isdst":false,"year":2025,"month":9,"sec":21,"day":30}
  49. local local_struct_time = os.date("*t")
  50. log.info("sntp", "本地时间结构", json.encode(local_struct_time))
  51. log.info("sntp", "结构时间转时间戳", os.time(local_struct_time))
  52. end
  53. -- 打印高精度时间戳
  54. local function print_high_precision_time()
  55. if not socket.ntptm then
  56. -- 不支持则跳过
  57. return
  58. end
  59. local ntp_time = socket.ntptm()
  60. if ntp_time and ntp_time.tsec then
  61. log.info("tm数据", json.encode(ntp_time))
  62. -- 格式化:秒.毫秒
  63. log.info("sntp", "高精度时间戳", string.format("%u.%03d", ntp_time.tsec, ntp_time.tms))
  64. else
  65. log.warn("sntp", "高精度时间戳获取失败")
  66. end
  67. end
  68. -- SNTP同步主逻辑
  69. local function sntp_sync_loop()
  70. -- 等待网络就绪(IP获取成功)
  71. -- 30秒超时,避免无限等待
  72. if not sys.waitUntil("IP_READY", 30000) then
  73. log.error("sntp", "网络未就绪,退出同步")
  74. return
  75. end
  76. log.info("sntp", "网络就绪,开始时间同步流程")
  77. -- 失败重试计数,用于动态调整间隔
  78. local fail_retry_count = 0
  79. while true do
  80. -- 执行SNTP同步,使用自定义服务器列表
  81. -- log.info("sntp", "开始同步,服务器列表:", json.encode(CONFIG.ntp_servers))
  82. -- socket.sntp(CONFIG.ntp_servers)
  83. log.info("sntp", "开始同步:")
  84. -- 使用内置的ntp服务器地址
  85. socket.sntp()
  86. -- 等待同步结果(成功:NTP_UPDATE,失败:超时)
  87. local sync_success = sys.waitUntil("NTP_UPDATE", CONFIG.sntp_timeout)
  88. if sync_success then
  89. -- 同步成功:重置失败计数,打印时间信息
  90. fail_retry_count = 0
  91. log.info("sntp", "时间同步成功")
  92. print_time_details()
  93. print_high_precision_time()
  94. -- 等待下次同步(使用成功间隔)
  95. sys.wait(CONFIG.success_interval)
  96. else
  97. -- 同步失败:累加失败计数,动态调整重试间隔
  98. fail_retry_count = fail_retry_count + 1
  99. local retry_interval = math.min(
  100. CONFIG.fail_retry_interval * (2 ^ (fail_retry_count - 1)),
  101. -- 不超过最大间隔
  102. CONFIG.max_retry_backoff
  103. )
  104. log.warn("sntp", "时间同步失败", "重试次数:", fail_retry_count, "下次重试间隔(ms):", retry_interval)
  105. sys.wait(retry_interval)
  106. end
  107. end
  108. end
  109. -- 订阅NTP错误消息
  110. sys.subscribe("NTP_ERROR", function(err_info)
  111. log.error("sntp", "同步过程发生错误", err_info or "未知错误")
  112. end)
  113. -- 启动SNTP同步任务
  114. sys.taskInit(sntp_sync_loop)