"""Functions to sync the hardware clock to internet network time servers Derived from the 2016 implementation. """ ___license___ = "MIT" import database import usocket import machine # (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60 NTP_DELTA = 3155673600 # With Mk3 Firmware an IP address string works 5%, hangs at socket.socket(..) 95%, could be a bug in 2016 upython? NTP_HOSTS = ["0.emfbadge.pool.ntp.org", "1.emfbadge.pool.ntp.org", "2.emfbadge.pool.ntp.org", "3.emfbadge.pool.ntp.org"] NTP_PORT = 123 def get_NTP_time(): for NTP_HOST in NTP_HOSTS: res = query_NTP_host(NTP_HOST) if res is not None: return res return None def query_NTP_host(_NTP_HOST): NTP_QUERY = bytearray(48) NTP_QUERY[0] = 0x1b # Catch exception when run on a network without working DNS try: addr = usocket.getaddrinfo(_NTP_HOST, NTP_PORT)[0][-1] except OSError: return None s = usocket.socket(usocket.AF_INET, usocket.SOCK_DGRAM) s.sendto(NTP_QUERY, addr) # Setting timeout for receiving data. Because we're using UDP, # there's no need for a timeout on send. msg = None try: msg = s.recv(48) except OSError: pass finally: s.close() if msg is None: return None import struct stratum = int(msg[1]) if stratum == 0: # KoD, reason doesn't matter, failover to next host return None val = struct.unpack("!I", msg[40:44])[0] print("Using NTP Host: %s, Stratum: %d" % (_NTP_HOST, stratum)) return val - NTP_DELTA def set_NTP_time(): import time print("Setting time from NTP") t = get_NTP_time() if t is None: print("Could not set time from NTP") return False tz = 0 with database.Database() as db: tz = db.get("timezone", 0) tz_minutes = int(abs(tz) % 100) * (1 if tz >= 0 else -1) tz_hours = int(tz / 100) t += (tz_hours * 3600) + (tz_minutes * 60) tm = time.localtime(t) tm = tm[0:3] + tm[3:6] rtc = machine.RTC() rtc.init(tm) return True