Skip to content

Instantly share code, notes, and snippets.

@Tugzrida
Created November 23, 2019 00:15
Show Gist options
  • Save Tugzrida/9c36a6ed30639689e73f4f66dfde83d6 to your computer and use it in GitHub Desktop.
Save Tugzrida/9c36a6ed30639689e73f4f66dfde83d6 to your computer and use it in GitHub Desktop.
Implementation of NTP and Australian DST in MicroPython
import time, socket
from struct import unpack
from machine import RTC
standardTimeOffset = 60 * 60 * 10 # The base TZ UTC offset in sec, AEST(UTC+10)
summerTimeDifference = 60 * 60 * 1 # The difference between the base TZ and DST TZ in sec, AEDT(UTC+11), 1 hour ahead
rtc = RTC()
lastSync = 0
def isDST(now):
# Returns true or false adhering to the Australian DST standard(begin DST at 2am (base TZ) on the first Sunday
# of October, end at 2am(base TZ) on the first Sunday of April.) Provided `now` should always be in base TZ.
month = now[1]
if (month >= 11 or month <= 3): return True # Nov, Dec, Jan, Feb, Mar are always summer time
if (month >= 5 and month <= 9): return False # May, Jun, Jul, Aug, Sep are always standard time
date = now[2]
hour = now[3]
dow = now[6]
lastSun = date - (dow + 1) # Representing the previous Sunday, even if today is Sunday
if (month == 10):
# DST if lastSun was this month or today is changing sunday and after 2am
return ((lastSun > 0) or (dow == 6 and hour >= 2))
if (month == 4):
# DST if lastSun was last month and today isn't changing sunday after 2am
return ((lastSun <= 0) and (dow != 6 or hour < 2))
def ntpSync():
# Sets the RTC to the current time in the base TZ, and sets lastSync to the current ticks.
global lastSync
NTP_QUERY = bytearray(48)
NTP_QUERY[0] = 0x1b
addr = socket.getaddrinfo("au.pool.ntp.org", 123)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.settimeout(1)
res = s.sendto(NTP_QUERY, addr)
msg = s.recv(48)
tm = time.localtime(unpack("!I", msg[40:44])[0] - 3155673600 + standardTimeOffset)
rtc.datetime((tm[0], tm[1], tm[2], tm[6] + 1, tm[3], tm[4], tm[5], 0))
lastSync = time.ticks_ms()
print("Time synced with NTP")
except OSError as e:
if e.args[0] == 110:
print('NTP timeout!')
else:
raise e
finally:
s.close()
def getTime():
# The function that should be used to get the time in other code.
# Updates the time from NTP if necessary, then returns a tuple of the standard time.localtime() tuple,
# and the current DST state bool.
if time.ticks_diff(time.ticks_ms(), lastSync) > 1800000:
ntpSync()
now = time.localtime()
dst = isDST(now)
if dst:
now = time.localtime(time.mktime(now) + summerTimeDifference)
return now, dst
ntpSync() # Initial sync of the RTC
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment