Add ntptime.py.

pull/29/head
Peter Hinch 2022-07-27 10:35:12 +01:00
rodzic 7379c9085a
commit bf14803480
2 zmienionych plików z 50 dodań i 0 usunięć

Wyświetl plik

@ -38,6 +38,7 @@ and modules which are documented and supported.
4.11 [Functors and singletons](./README.md#411-functors-and-singletons) Useful decorators.
4.12 [Quaternions](./README.md#412-quaternions) Scale, move and rotate 3D objects with minimal mathematics.
4.13 [A Pyboard power meter](./README.md#413-a-pyboard-power-meter) One of my own projects.
4.14 [NTP time](./README.md#414-ntp-time) More portable than official driver with other benefits.
5. [Module Index](./README.md#5-module-index) Supported code. Device drivers, GUI's, utilities.
5.1 [uasyncio](./README.md#51-uasyncio) Tutorial and drivers for asynchronous coding.
5.2 [Memory Device Drivers](./README.md#52-memory-device-drivers) Drivers for nonvolatile memory devices.
@ -297,6 +298,20 @@ enabling it to provide information on power factor and to work with devices
which generate as well as consume power. It uses the official LCD160CR display
as a touch GUI interface. It is documented [here](./power/README.md).
## 4.14 NTP Time
The official code has a number of drawbacks, mainly a lack of portability.
1. It does not check the host device's epoch. This version returns the number
of seconds since the host device's epoch.
2. It uses socket timeouts while the docs recommend select.poll as being more
portable. This version remedies that.
3. This version has very basic support for local time in the form of an offset
in hours relative to UTC.
4. In the event of a timeout this version returns 0: the caller should check
for this and re-try after a period.
Code is [here](./ntptime/ntptime.py).
##### [Index](./README.md#0-index)
# 5. Module index

35
ntptime/ntptime.py 100644
Wyświetl plik

@ -0,0 +1,35 @@
# Adapted from official ntptime by Peter Hinch July 2022
# The main aim is portability:
# Detects host device's epoch and returns time relative to that.
# Basic approach to local time: add offset in hours relative to UTC.
# Timeouts return a time of 0. These happen: caller should check for this.
# Replace socket timeout with select.poll as per docs:
# http://docs.micropython.org/en/latest/library/socket.html#socket.socket.settimeout
import socket
import struct
import select
from time import gmtime
# (date(2000, 1, 1) - date(1900, 1, 1)).days * 24*60*60
# (date(1970, 1, 1) - date(1900, 1, 1)).days * 24*60*60
NTP_DELTA = 3155673600 if gmtime(0)[0] == 2000 else 2208988800
# The NTP host can be configured at runtime by doing: ntptime.host = 'myhost.org'
host = "pool.ntp.org"
def time(hrs_offset=0): # Local time offset in hrs relative to UTC
NTP_QUERY = bytearray(48)
NTP_QUERY[0] = 0x1B
addr = socket.getaddrinfo(host, 123)[0][-1]
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
poller = select.poll()
poller.register(s, select.POLLIN)
s.sendto(NTP_QUERY, addr)
if poller.poll(1000): # time in milliseconds
msg = s.recv(48)
s.close()
val = struct.unpack("!I", msg[40:44])[0]
return val - NTP_DELTA + hrs_offset * 3600
s.close() # Timeout occurred
return 0