adafruit-circuitpython-ntp 3.2.0__tar.gz → 3.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/PKG-INFO +1 -1
  2. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/adafruit_circuitpython_ntp.egg-info/PKG-INFO +1 -1
  3. adafruit_circuitpython_ntp-3.3.0/adafruit_ntp.py +145 -0
  4. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/examples/ntp_set_rtc.py +11 -6
  5. adafruit_circuitpython_ntp-3.3.0/examples/ntp_simpletest.py +32 -0
  6. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/pyproject.toml +1 -1
  7. adafruit_circuitpython_ntp-3.2.0/adafruit_ntp.py +0 -114
  8. adafruit_circuitpython_ntp-3.2.0/examples/ntp_simpletest.py +0 -27
  9. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.github/PULL_REQUEST_TEMPLATE/adafruit_circuitpython_pr.md +0 -0
  10. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.github/workflows/build.yml +0 -0
  11. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.github/workflows/failure-help-text.yml +0 -0
  12. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.github/workflows/release_gh.yml +0 -0
  13. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.github/workflows/release_pypi.yml +0 -0
  14. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.gitignore +0 -0
  15. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.pre-commit-config.yaml +0 -0
  16. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.pylintrc +0 -0
  17. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/.readthedocs.yaml +0 -0
  18. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/CODE_OF_CONDUCT.md +0 -0
  19. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/LICENSE +0 -0
  20. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/LICENSES/CC-BY-4.0.txt +0 -0
  21. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/LICENSES/MIT.txt +0 -0
  22. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/LICENSES/Unlicense.txt +0 -0
  23. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/README.rst +0 -0
  24. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/README.rst.license +0 -0
  25. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/adafruit_circuitpython_ntp.egg-info/SOURCES.txt +0 -0
  26. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/adafruit_circuitpython_ntp.egg-info/dependency_links.txt +0 -0
  27. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/adafruit_circuitpython_ntp.egg-info/requires.txt +0 -0
  28. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/adafruit_circuitpython_ntp.egg-info/top_level.txt +0 -0
  29. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/_static/favicon.ico +0 -0
  30. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/_static/favicon.ico.license +0 -0
  31. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/api.rst +0 -0
  32. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/api.rst.license +0 -0
  33. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/conf.py +0 -0
  34. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/examples.rst +0 -0
  35. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/examples.rst.license +0 -0
  36. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/index.rst +0 -0
  37. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/index.rst.license +0 -0
  38. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/docs/requirements.txt +0 -0
  39. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/examples/ntp_connection_manager.py +0 -0
  40. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/examples/ntp_cpython.py +0 -0
  41. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/optional_requirements.txt +0 -0
  42. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/requirements.txt +0 -0
  43. {adafruit_circuitpython_ntp-3.2.0 → adafruit_circuitpython_ntp-3.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: adafruit-circuitpython-ntp
3
- Version: 3.2.0
3
+ Version: 3.3.0
4
4
  Summary: Network Time Protocol (NTP) helper for Python
5
5
  Author-email: Adafruit Industries <circuitpython@adafruit.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: adafruit-circuitpython-ntp
3
- Version: 3.2.0
3
+ Version: 3.3.0
4
4
  Summary: Network Time Protocol (NTP) helper for Python
5
5
  Author-email: Adafruit Industries <circuitpython@adafruit.com>
6
6
  License: MIT
@@ -0,0 +1,145 @@
1
+ # SPDX-FileCopyrightText: 2022 Scott Shawcroft for Adafruit Industries
2
+ #
3
+ # SPDX-License-Identifier: MIT
4
+
5
+ """
6
+ `adafruit_ntp`
7
+ ================================================================================
8
+
9
+ Network Time Protocol (NTP) helper for CircuitPython
10
+
11
+ * Author(s): Scott Shawcroft
12
+
13
+ Implementation Notes
14
+ --------------------
15
+ **Hardware:**
16
+ **Software and Dependencies:**
17
+
18
+ * Adafruit CircuitPython firmware for the supported boards:
19
+ https://github.com/adafruit/circuitpython/releases
20
+
21
+ """
22
+ import struct
23
+ import time
24
+
25
+ from micropython import const
26
+
27
+
28
+ __version__ = "3.3.0"
29
+ __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NTP.git"
30
+
31
+ NTP_TO_UNIX_EPOCH = 2208988800 # 1970-01-01 00:00:00
32
+ PACKET_SIZE = const(48)
33
+
34
+
35
+ class NTP: # pylint:disable=too-many-instance-attributes
36
+ """Network Time Protocol (NTP) helper module for CircuitPython.
37
+ This module does not handle daylight savings or local time. It simply requests
38
+ UTC from a NTP server.
39
+ """
40
+
41
+ def __init__( # pylint:disable=too-many-arguments
42
+ self,
43
+ socketpool,
44
+ *,
45
+ server: str = "0.adafruit.pool.ntp.org",
46
+ port: int = 123,
47
+ tz_offset: float = 0,
48
+ socket_timeout: int = 10,
49
+ cache_seconds: int = 0,
50
+ ) -> None:
51
+ """
52
+ :param object socketpool: A socket provider such as CPython's `socket` module.
53
+ :param str server: The domain of the ntp server to query.
54
+ :param int port: The port of the ntp server to query.
55
+ :param float tz_offset: Timezone offset in hours from UTC. Only useful for timezone ignorant
56
+ CircuitPython. CPython will determine timezone automatically and adjust (so don't use
57
+ this.) For example, Pacific daylight savings time is -7.
58
+ :param int socket_timeout: UDP socket timeout, in seconds.
59
+ :param int cache_seconds: how many seconds to use a cached result from NTP server
60
+ (default 0, which respects NTP server's minimum).
61
+ """
62
+ self._pool = socketpool
63
+ self._server = server
64
+ self._port = port
65
+ self._socket_address = None
66
+ self._packet = bytearray(PACKET_SIZE)
67
+ self._tz_offset = int(tz_offset * 60 * 60)
68
+ self._socket_timeout = socket_timeout
69
+ self._cache_seconds = cache_seconds
70
+
71
+ # This is our estimated start time for the monotonic clock. We adjust it based on the ntp
72
+ # responses.
73
+ self._monotonic_start_ns = 0
74
+
75
+ self.next_sync = 0
76
+
77
+ def _update_time_sync(self) -> None:
78
+ """Update the time sync value. Raises OSError exception if no response
79
+ is received within socket_timeout seconds, ArithmeticError for substantially incorrect
80
+ NTP results."""
81
+ if self._socket_address is None:
82
+ self._socket_address = self._pool.getaddrinfo(self._server, self._port)[0][
83
+ 4
84
+ ]
85
+
86
+ self._packet[0] = 0b00100011 # Not leap second, NTP version 4, Client mode
87
+ for i in range(1, PACKET_SIZE):
88
+ self._packet[i] = 0
89
+ with self._pool.socket(self._pool.AF_INET, self._pool.SOCK_DGRAM) as sock:
90
+ sock.settimeout(self._socket_timeout)
91
+ local_send_ns = time.monotonic_ns() # expanded
92
+ sock.sendto(self._packet, self._socket_address)
93
+ sock.recv_into(self._packet)
94
+ # Get the time in the context to minimize the difference between it and receiving
95
+ # the packet.
96
+ local_recv_ns = time.monotonic_ns() # was destination
97
+
98
+ poll = struct.unpack_from("!B", self._packet, offset=2)[0]
99
+
100
+ cache_offset_s = max(2**poll, self._cache_seconds)
101
+ self.next_sync = local_recv_ns + cache_offset_s * 1_000_000_000
102
+
103
+ srv_recv_s, srv_recv_f = struct.unpack_from("!II", self._packet, offset=32)
104
+ srv_send_s, srv_send_f = struct.unpack_from("!II", self._packet, offset=40)
105
+
106
+ # Convert the server times from NTP to UTC for local use
107
+ srv_recv_ns = (srv_recv_s - NTP_TO_UNIX_EPOCH) * 1_000_000_000 + (
108
+ srv_recv_f * 1_000_000_000 // 2**32
109
+ )
110
+ srv_send_ns = (srv_send_s - NTP_TO_UNIX_EPOCH) * 1_000_000_000 + (
111
+ srv_send_f * 1_000_000_000 // 2**32
112
+ )
113
+
114
+ # _round_trip_delay = (local_recv_ns - local_send_ns) - (srv_send_ns - srv_recv_ns)
115
+ # Calculate (best estimate) offset between server UTC and board monotonic_ns time
116
+ clock_offset = (
117
+ (srv_recv_ns - local_send_ns) + (srv_send_ns - local_recv_ns)
118
+ ) // 2
119
+
120
+ self._monotonic_start_ns = clock_offset + self._tz_offset * 1_000_000_000
121
+
122
+ @property
123
+ def datetime(self) -> time.struct_time:
124
+ """Current time from NTP server. Accessing this property causes the NTP time request,
125
+ unless there has already been a recent request."""
126
+ if time.monotonic_ns() > self.next_sync:
127
+ self._update_time_sync()
128
+
129
+ # Calculate the current time based on the current and start monotonic times
130
+ current_time_s = (
131
+ time.monotonic_ns() + self._monotonic_start_ns
132
+ ) // 1_000_000_000
133
+
134
+ return time.localtime(current_time_s)
135
+
136
+ @property
137
+ def utc_ns(self) -> int:
138
+ """UTC (unix epoch) time in nanoseconds. Accessing this property causes the NTP time
139
+ request, unless there has already been a recent request. Raises OSError exception if
140
+ no response is received within socket_timeout seconds, ArithmeticError for substantially
141
+ incorrect NTP results."""
142
+ if time.monotonic_ns() > self.next_sync:
143
+ self._update_time_sync()
144
+
145
+ return time.monotonic_ns() + self._monotonic_start_ns
@@ -3,6 +3,7 @@
3
3
 
4
4
  """Example demonstrating how to set the realtime clock (RTC) based on NTP time."""
5
5
 
6
+ import os
6
7
  import time
7
8
 
8
9
  import rtc
@@ -11,15 +12,19 @@ import wifi
11
12
 
12
13
  import adafruit_ntp
13
14
 
14
- # Get wifi details and more from a secrets.py file
15
+ # Get wifi AP credentials from a settings.toml file
16
+ wifi_ssid = os.getenv("CIRCUITPY_WIFI_SSID")
17
+ wifi_password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
18
+ if wifi_ssid is None:
19
+ print("WiFi credentials are kept in settings.toml, please add them there!")
20
+ raise ValueError("SSID not found in environment variables")
21
+
15
22
  try:
16
- from secrets import secrets
17
- except ImportError:
18
- print("WiFi secrets are kept in secrets.py, please add them there!")
23
+ wifi.radio.connect(wifi_ssid, wifi_password)
24
+ except ConnectionError:
25
+ print("Failed to connect to WiFi with provided credentials")
19
26
  raise
20
27
 
21
- wifi.radio.connect(secrets["ssid"], secrets["password"])
22
-
23
28
  pool = socketpool.SocketPool(wifi.radio)
24
29
  ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600)
25
30
 
@@ -0,0 +1,32 @@
1
+ # SPDX-FileCopyrightText: 2022 Scott Shawcroft for Adafruit Industries
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ """Print out time based on NTP."""
5
+
6
+ import os
7
+ import time
8
+
9
+ import socketpool
10
+ import wifi
11
+
12
+ import adafruit_ntp
13
+
14
+ # Get wifi AP credentials from a settings.toml file
15
+ wifi_ssid = os.getenv("CIRCUITPY_WIFI_SSID")
16
+ wifi_password = os.getenv("CIRCUITPY_WIFI_PASSWORD")
17
+ if wifi_ssid is None:
18
+ print("WiFi credentials are kept in settings.toml, please add them there!")
19
+ raise ValueError("SSID not found in environment variables")
20
+
21
+ try:
22
+ wifi.radio.connect(wifi_ssid, wifi_password)
23
+ except ConnectionError:
24
+ print("Failed to connect to WiFi with provided credentials")
25
+ raise
26
+
27
+ pool = socketpool.SocketPool(wifi.radio)
28
+ ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600)
29
+
30
+ while True:
31
+ print(ntp.datetime)
32
+ time.sleep(1)
@@ -12,7 +12,7 @@ requires = [
12
12
  [project]
13
13
  name = "adafruit-circuitpython-ntp"
14
14
  description = "Network Time Protocol (NTP) helper for Python"
15
- version = "3.2.0"
15
+ version = "3.3.0"
16
16
  readme = "README.rst"
17
17
  authors = [
18
18
  {name = "Adafruit Industries", email = "circuitpython@adafruit.com"}
@@ -1,114 +0,0 @@
1
- # SPDX-FileCopyrightText: 2022 Scott Shawcroft for Adafruit Industries
2
- #
3
- # SPDX-License-Identifier: MIT
4
-
5
- """
6
- `adafruit_ntp`
7
- ================================================================================
8
-
9
- Network Time Protocol (NTP) helper for CircuitPython
10
-
11
- * Author(s): Scott Shawcroft
12
-
13
- Implementation Notes
14
- --------------------
15
- **Hardware:**
16
- **Software and Dependencies:**
17
-
18
- * Adafruit CircuitPython firmware for the supported boards:
19
- https://github.com/adafruit/circuitpython/releases
20
-
21
- """
22
- import struct
23
- import time
24
-
25
- from micropython import const
26
-
27
-
28
- __version__ = "3.2.0"
29
- __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_NTP.git"
30
-
31
- NTP_TO_UNIX_EPOCH = 2208988800 # 1970-01-01 00:00:00
32
- PACKET_SIZE = const(48)
33
-
34
-
35
- class NTP:
36
- """Network Time Protocol (NTP) helper module for CircuitPython.
37
- This module does not handle daylight savings or local time. It simply requests
38
- UTC from a NTP server.
39
- """
40
-
41
- def __init__(
42
- self,
43
- socketpool,
44
- *,
45
- server: str = "0.adafruit.pool.ntp.org",
46
- port: int = 123,
47
- tz_offset: float = 0,
48
- socket_timeout: int = 10,
49
- cache_seconds: int = 0,
50
- ) -> None:
51
- """
52
- :param object socketpool: A socket provider such as CPython's `socket` module.
53
- :param str server: The domain of the ntp server to query.
54
- :param int port: The port of the ntp server to query.
55
- :param float tz_offset: Timezone offset in hours from UTC. Only useful for timezone ignorant
56
- CircuitPython. CPython will determine timezone automatically and adjust (so don't use
57
- this.) For example, Pacific daylight savings time is -7.
58
- :param int socket_timeout: UDP socket timeout, in seconds.
59
- :param int cache_seconds: how many seconds to use a cached result from NTP server
60
- (default 0, which respects NTP server's minimum).
61
- """
62
- self._pool = socketpool
63
- self._server = server
64
- self._port = port
65
- self._socket_address = None
66
- self._packet = bytearray(PACKET_SIZE)
67
- self._tz_offset = int(tz_offset * 60 * 60)
68
- self._socket_timeout = socket_timeout
69
- self._cache_seconds = cache_seconds
70
-
71
- # This is our estimated start time for the monotonic clock. We adjust it based on the ntp
72
- # responses.
73
- self._monotonic_start = 0
74
-
75
- self.next_sync = 0
76
-
77
- @property
78
- def datetime(self) -> time.struct_time:
79
- """Current time from NTP server. Accessing this property causes the NTP time request,
80
- unless there has already been a recent request. Raises OSError exception if no response
81
- is received within socket_timeout seconds, ArithmeticError for substantially incorrect
82
- NTP results."""
83
- if time.monotonic_ns() > self.next_sync:
84
- if self._socket_address is None:
85
- self._socket_address = self._pool.getaddrinfo(self._server, self._port)[
86
- 0
87
- ][4]
88
-
89
- self._packet[0] = 0b00100011 # Not leap second, NTP version 4, Client mode
90
- for i in range(1, PACKET_SIZE):
91
- self._packet[i] = 0
92
- with self._pool.socket(self._pool.AF_INET, self._pool.SOCK_DGRAM) as sock:
93
- sock.settimeout(self._socket_timeout)
94
- sock.sendto(self._packet, self._socket_address)
95
- sock.recv_into(self._packet)
96
- # Get the time in the context to minimize the difference between it and receiving
97
- # the packet.
98
- destination = time.monotonic_ns()
99
- poll = struct.unpack_from("!B", self._packet, offset=2)[0]
100
-
101
- cache_offset = max(2**poll, self._cache_seconds)
102
- self.next_sync = destination + cache_offset * 1_000_000_000
103
- seconds = struct.unpack_from("!I", self._packet, offset=PACKET_SIZE - 8)[0]
104
-
105
- self._monotonic_start = (
106
- seconds
107
- + self._tz_offset
108
- - NTP_TO_UNIX_EPOCH
109
- - (destination // 1_000_000_000)
110
- )
111
-
112
- return time.localtime(
113
- time.monotonic_ns() // 1_000_000_000 + self._monotonic_start
114
- )
@@ -1,27 +0,0 @@
1
- # SPDX-FileCopyrightText: 2022 Scott Shawcroft for Adafruit Industries
2
- # SPDX-License-Identifier: MIT
3
-
4
- """Print out time based on NTP."""
5
-
6
- import time
7
-
8
- import socketpool
9
- import wifi
10
-
11
- import adafruit_ntp
12
-
13
- # Get wifi details and more from a secrets.py file
14
- try:
15
- from secrets import secrets
16
- except ImportError:
17
- print("WiFi secrets are kept in secrets.py, please add them there!")
18
- raise
19
-
20
- wifi.radio.connect(secrets["ssid"], secrets["password"])
21
-
22
- pool = socketpool.SocketPool(wifi.radio)
23
- ntp = adafruit_ntp.NTP(pool, tz_offset=0, cache_seconds=3600)
24
-
25
- while True:
26
- print(ntp.datetime)
27
- time.sleep(1)