ntp.lua 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. --- 模块功能 : 网络授时
  2. -- @module ntp
  3. -- @author 稀饭放姜
  4. -- @license MIT
  5. -- @copyright openLuat
  6. -- @release 2017.10.21
  7. require "misc"
  8. require "socket"
  9. require "utils"
  10. require "log"
  11. local sbyte, ssub = string.byte, string.sub
  12. module(..., package.seeall)
  13. -- NTP服务器域名集合
  14. local timeServer = {
  15. "ntp1.aliyun.com",
  16. "edu.ntp.org.cn",
  17. "cn.ntp.org.cn",
  18. "ntp2.aliyun.com",
  19. "ntp3.aliyun.com",
  20. "ntp4.aliyun.com",
  21. "ntp5.aliyun.com",
  22. "ntp7.aliyun.com",
  23. "ntp6.aliyun.com",
  24. "s2c.time.edu.cn",
  25. "194.109.22.18",
  26. "210.72.145.44",
  27. }
  28. -- 同步超时等待时间
  29. local NTP_TIMEOUT = 8000
  30. -- 同步是否完成标记
  31. local ntpend = false
  32. --- 获取NTP服务器地址列表
  33. -- @return table,服务器地址列表
  34. -- @usage local addtable = ntp.getServers()
  35. function getServers()
  36. return timeServer
  37. end
  38. --- 设置NTP服务器地址列表
  39. -- @param st,tab类型,服务器地址列表
  40. -- @return 无
  41. -- @usage ntp.getServers({"1edu.ntp.org.cn","cn.ntp.org.cn"})
  42. function setServers(st)
  43. timeServer = st
  44. end
  45. --- NTP同步标志
  46. -- @return boole,NTP的同步状态true为成功,fasle为失败
  47. -- @usage local sta = ntp.isEnd()
  48. function isEnd()
  49. return ntpend
  50. end
  51. --- 同步时间,每个NTP服务器尝试3次,超时8秒,适用于被任务函数调用
  52. -- @param ts,每隔ts小时同步1次
  53. -- @param fnc,同步成功后回调函数
  54. -- @return 无
  55. -- @usage ntp.ntpTime() -- 只同步1次
  56. -- @usage ntp.ntpTime(1) -- 1小时同步1次
  57. -- @usage ntp.ntpTime(nil,fnc) -- 只同步1次,同步成功后执行fnc()
  58. -- @usage ntp.ntpTime(24,fnc) -- 24小时同步1次,同步成功后执行fnc()
  59. function ntpTime(ts,fnc)
  60. local rc, data, ntim
  61. ntpend = false
  62. while true do
  63. for i = 1, #timeServer do
  64. while not socket.isReady() do sys.wait(1000) end
  65. local c = socket.udp()
  66. if c:connect(timeServer[i], "123") then
  67. if c:send(string.fromhex("E30006EC0000000000000000314E31340000000000000000000000000000000000000000000000000000000000000000")) then
  68. rc, data = c:recv(NTP_TIMEOUT)
  69. if rc and #data == 48 then
  70. ntim = os.date("*t", (sbyte(ssub(data, 41, 41)) - 0x83) * 2 ^ 24 + (sbyte(ssub(data, 42, 42)) - 0xAA) * 2 ^ 16 + (sbyte(ssub(data, 43, 43)) - 0x7E) * 2 ^ 8 + (sbyte(ssub(data, 44, 44)) - 0x80) + 1)
  71. misc.setClock(ntim)
  72. ntpend = true
  73. if fnc ~= nil and type(fnc) == "function" then fnc() end
  74. c:close()
  75. break
  76. end
  77. end
  78. end
  79. c:close()
  80. sys.wait(1000)
  81. end
  82. if ntpend then
  83. sys.publish("NTP_SUCCEED")
  84. log.info("ntp.timeSync is date:", ntim.year .. "/" .. ntim.month .. "/" .. ntim.day .. "," .. ntim.hour .. ":" .. ntim.min .. ":" .. ntim.sec)
  85. if ts == nil or type(ts) ~= "number" then break end
  86. sys.wait(ts * 3600 * 1000)
  87. else
  88. log.info("ntp.timeSync is error!")
  89. sys.wait(1000)
  90. end
  91. end
  92. end
  93. --- 自动同步时间任务适合独立执行
  94. -- @return 无
  95. -- @param ts,每隔ts小时同步1次
  96. -- @param fnc,同步成功后回调函数
  97. -- @usage ntp.timeSync() -- 只同步1次
  98. -- @usage ntp.timeSync(1) -- 1小时同步1次
  99. -- @usage ntp.timeSync(nil,fnc) -- 只同步1次,同步成功后执行fnc()
  100. -- @usage ntp.timeSync(24,fnc) -- 24小时同步1次,同步成功后执行fnc()
  101. function timeSync(ts,fnc)
  102. sys.taskInit(ntpTime,ts,fnc)
  103. end