Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add configurable time between NTP calls #37

Merged
merged 5 commits into from
Jul 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 10 additions & 2 deletions adafruit_ntp.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that's a good default but I'd rather not change behavior. Instead, I'd default to None to indicate following the server.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll default it to zero- min(int, None) is an error.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, pushed the 'zero', and then changed all of the examples to use the 3600 value, since most people just copy/paste example code anyhow. Did it in a standalone commit in case you disagree and want me to revert.

(default 0, which respects NTP server's minimum).
"""
self._pool = socketpool
self._server = server
Expand All @@ -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.
Expand All @@ -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)[
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions examples/ntp_connection_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
2 changes: 1 addition & 1 deletion examples/ntp_cpython.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion examples/ntp_set_rtc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion examples/ntp_simpletest.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading