diff --git a/README.rst b/README.rst index d1d7bbd..67a62ea 100644 --- a/README.rst +++ b/README.rst @@ -70,7 +70,7 @@ Usage Example wifi.radio.connect(wifi_ssid, wifi_password) pool = adafruit_connection_manager.get_radio_socketpool(wifi.radio) - ntp = adafruit_ntp.NTP(pool, tz_offset=0) + ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600) while True: print(ntp.datetime) diff --git a/adafruit_ntp.py b/adafruit_ntp.py index a41f598..bc6db0d 100644 --- a/adafruit_ntp.py +++ b/adafruit_ntp.py @@ -46,6 +46,7 @@ def __init__( port: int = 123, tz_offset: float = 0, socket_timeout: int = 10, + cache_seconds: int = 0, ) -> None: """ :param object socketpool: A socket provider such as CPython's `socket` module. @@ -55,6 +56,8 @@ def __init__( CircuitPython. CPython will determine timezone automatically and adjust (so don't use this.) For example, Pacific daylight savings time is -7. :param int socket_timeout: UDP socket timeout, in seconds. + :param int cache_seconds: how many seconds to use a cached result from NTP server + (default 0, which respects NTP server's minimum). """ self._pool = socketpool self._server = server @@ -63,6 +66,7 @@ def __init__( self._packet = bytearray(PACKET_SIZE) self._tz_offset = int(tz_offset * 60 * 60) self._socket_timeout = socket_timeout + self._cache_seconds = cache_seconds # This is our estimated start time for the monotonic clock. We adjust it based on the ntp # responses. @@ -74,7 +78,8 @@ def __init__( def datetime(self) -> time.struct_time: """Current time from NTP server. Accessing this property causes the NTP time request, unless there has already been a recent request. Raises OSError exception if no response - is received within socket_timeout seconds""" + is received within socket_timeout seconds, ArithmeticError for substantially incorrect + NTP results.""" if time.monotonic_ns() > self.next_sync: if self._socket_address is None: self._socket_address = self._pool.getaddrinfo(self._server, self._port)[ @@ -92,8 +97,11 @@ def datetime(self) -> time.struct_time: # the packet. destination = time.monotonic_ns() poll = struct.unpack_from("!B", self._packet, offset=2)[0] - self.next_sync = destination + (2**poll) * 1_000_000_000 + + cache_offset = max(2**poll, self._cache_seconds) + self.next_sync = destination + cache_offset * 1_000_000_000 seconds = struct.unpack_from("!I", self._packet, offset=PACKET_SIZE - 8)[0] + self._monotonic_start = ( seconds + self._tz_offset diff --git a/examples/ntp_connection_manager.py b/examples/ntp_connection_manager.py index b3cd28b..db3e4e9 100644 --- a/examples/ntp_connection_manager.py +++ b/examples/ntp_connection_manager.py @@ -33,7 +33,7 @@ # get the socket pool from connection manager socket = adafruit_connection_manager.get_radio_socketpool(radio) -# adjust tz_offset for locale... -ntp = adafruit_ntp.NTP(socket, tz_offset=-5) +# adjust tz_offset for locale, only ping NTP server every hour +ntp = adafruit_ntp.NTP(socket, tz_offset=-5, cache_seconds=3600) print(ntp.datetime) diff --git a/examples/ntp_cpython.py b/examples/ntp_cpython.py index 76d5735..e01a3b6 100644 --- a/examples/ntp_cpython.py +++ b/examples/ntp_cpython.py @@ -9,7 +9,7 @@ import adafruit_ntp # Don't use tz_offset kwarg with CPython because it will adjust automatically. -ntp = adafruit_ntp.NTP(socket) +ntp = adafruit_ntp.NTP(socket, cache_seconds=3600) while True: print(ntp.datetime) diff --git a/examples/ntp_set_rtc.py b/examples/ntp_set_rtc.py index 363c8b4..e4f331b 100644 --- a/examples/ntp_set_rtc.py +++ b/examples/ntp_set_rtc.py @@ -21,7 +21,7 @@ wifi.radio.connect(secrets["ssid"], secrets["password"]) pool = socketpool.SocketPool(wifi.radio) -ntp = adafruit_ntp.NTP(pool, tz_offset=0) +ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600) # NOTE: This changes the system time so make sure you aren't assuming that time # doesn't jump. diff --git a/examples/ntp_simpletest.py b/examples/ntp_simpletest.py index 0258e16..a3f1b70 100644 --- a/examples/ntp_simpletest.py +++ b/examples/ntp_simpletest.py @@ -20,7 +20,7 @@ wifi.radio.connect(secrets["ssid"], secrets["password"]) pool = socketpool.SocketPool(wifi.radio) -ntp = adafruit_ntp.NTP(pool, tz_offset=0) +ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600) while True: print(ntp.datetime)