-- -----------------------------------------------------------------------------------
-- for a continuous run:
-- TIME=loadfile("ntp.lua")()
-- TIME:run(timer,updateinterval,syncinterval,[ntp-server])
-- TIME.hour TIME.minute TIME.second are updated every 'updateinterval'-seconds
-- NTP-server is queried every 'syncinterval'-seconds
--
-- a one-time run:
-- loadfile("ntp.lua")():sync(function(T) print(T:show_time()) end)
--
-- config:
-- choose a timer for udptimer
-- choose a timeout for udptimeout
-- timer-function to close connection is needed - memory leaks on unanswered sends :(
-- set tz according to your timezone
-- choose a NTP-server near you and don't stress them with a low syncinterval :)
-- -----------------------------------------------------------------------------------
return({
hour=0,
minute=0,
second=0,
lastsync=0,
ustamp=0,
tz=1,
udptimer=2,
udptimeout=1000,
ntpserver="193.170.62.252",
sk=nil,
sync=function(self,callback)
-- print("SYNC " .. self.ustamp .. " " .. self.ntpserver)
-- request string blindly taken from http://arduino.cc/en/Tutorial/UdpNTPClient ;)
local request=string.char( 227, 0, 6, 236, 0,0,0,0,0,0,0,0, 49, 78, 49, 52,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
)
self.sk=net.createConnection(net.UDP, 0)
self.sk:on("receive",function(sck,payload)
-- tmr.stop(self.udptimer)
sck:close()
self.lastsync=self:calc_stamp(payload:sub(41,44))
self:set_time()
if callback and type(callback) == "function" then
callback(self)
end
collectgarbage() collectgarbage()
-- print("DONE " .. self.ustamp)
end)
self.sk:connect(123,self.ntpserver)
tmr.alarm(self.udptimer,self.udptimeout,0,function() self.sk:close() end)
self.sk:send(request)
end,
calc_stamp=function(self,bytes)
local highw,loww,ntpstamp
highw = bytes:byte(1) * 256 + bytes:byte(2)
loww = bytes:byte(3) * 256 + bytes:byte(4)
ntpstamp=( highw * 65536 + loww ) + ( self.tz * 3600) -- NTP-stamp, seconds since 1.1.1900
self.ustamp=ntpstamp - 1104494400 - 1104494400 -- UNIX-timestamp, seconds since 1.1.1970
-- print(string.format("NTP: %u",ntpstamp))
-- print(string.format("UIX: %u",self.ustamp))
return(self.ustamp)
end,
set_time=function(self)
self.hour = self.ustamp % 86400 / 3600
self.minute = self.ustamp % 3600 / 60
self.second = self.ustamp % 60
-- print(string.format("%02u:%02u:%02u",hour,minute,second))
end,
show_time=function(self)
return(string.format("%02u:%02u:%02u",self.hour,self.minute,self.second))
end,
run=function(self,t,uinterval,sinterval,server)
if server then self.ntpserver = server end
self.lastsync = sinterval * 2 * -1 -- force sync on first run
tmr.alarm(t,uinterval * 1000,1,function()
self.ustamp = self.ustamp + uinterval
self:set_time()
-- print(self:show_time())
if self.lastsync + sinterval < self.ustamp then
self:sync()
end
end)
end
})