|
| 1 | +from time import localtime |
| 2 | +from socket import socket, getaddrinfo, AF_INET, SOCK_DGRAM |
| 3 | +from struct import unpack |
| 4 | +from errno import ETIMEDOUT |
| 5 | +from machine import RTC |
| 6 | +import network |
| 7 | + |
| 8 | +wlan_sta = network.WLAN(network.STA_IF) |
| 9 | + |
| 10 | +class TZONE(object): |
| 11 | + |
| 12 | + def __init__(self, zone=0, win=True): |
| 13 | + self.zone = zone |
| 14 | + self.win = win |
| 15 | + # time zones is supported |
| 16 | + self.TIME_ZONE = {-11: -11, -10: -10, -9: -9, -8: -8, -7: -7, -6: -6, -5: -5, |
| 17 | + -4: -4, -3: -3, -2: -2, -1: -1, 0: 0, 1: 1, 2: 2, 3: 3, 4: 4, 5: 5, 6: 6, |
| 18 | + 7: 7, 8: 8, 9: 9, 10: 10, 11: 11, 12: 12, 13: 13, 14: 14} |
| 19 | + # months of summer and winter time |
| 20 | + self.MONTH = {'sum': 3, 'win': 10} # 3 - march, 10 - october |
| 21 | + |
| 22 | + self.NTP_DELTA = 2208988800 |
| 23 | + self.host = "cn.pool.ntp.org" |
| 24 | + |
| 25 | + def getntp(self, host="cn.pool.ntp.org"): |
| 26 | + # print('Get UTC time from NTP server...') |
| 27 | + NTP_QUERY = bytearray(48) |
| 28 | + NTP_QUERY[0] = 0x1b |
| 29 | + self.host = host |
| 30 | + |
| 31 | + if wlan_sta.isconnected() is False: |
| 32 | + raise OSError('Wifi Not Started') |
| 33 | + |
| 34 | + try: |
| 35 | + addr = getaddrinfo(self.host, 123)[0][-1] |
| 36 | + except OSError: # as exc: |
| 37 | + # if exc.args[0] == -2: |
| 38 | + print('Connect NTP Server: Error resolving pool NTP') |
| 39 | + return 0 |
| 40 | + s = socket(AF_INET, SOCK_DGRAM) |
| 41 | + s.settimeout(1) |
| 42 | + # res = s.sendto(NTP_QUERY, addr) |
| 43 | + s.sendto(NTP_QUERY, addr) |
| 44 | + |
| 45 | + try: |
| 46 | + msg = s.recv(48) |
| 47 | + except OSError as exc: |
| 48 | + if exc.args[0] == ETIMEDOUT: |
| 49 | + print('Connect NTP Server: Request Timeout') |
| 50 | + s.close() |
| 51 | + return 0 |
| 52 | + s.close() |
| 53 | + val = unpack("!I", msg[40:44])[0] |
| 54 | + return val - self.NTP_DELTA |
| 55 | + |
| 56 | + def sunday(self, year, month): |
| 57 | + for d in range(1, 32): |
| 58 | + a = (14 - month) // 12 |
| 59 | + y = year - a |
| 60 | + m = month + 12 * a - 2 |
| 61 | + if (((d + y + y // 4 - y // 100 + y // 400 + (31 * m) // 12)) % 7) == 0: |
| 62 | + if d + 7 > 31: |
| 63 | + return d |
| 64 | + |
| 65 | + def adj_tzone(self, utc): |
| 66 | + if utc[1] > self.MONTH['sum']: |
| 67 | + if utc[1] <= self.MONTH['win'] and utc[2] < self.sunday(utc[0], self.MONTH['win']): |
| 68 | + # print('TIME ZONE Summer:', self.TIME_ZONE[self.zone]) |
| 69 | + return self.TIME_ZONE[self.zone] |
| 70 | + if utc[1] == self.MONTH['sum'] and utc[2] >= self.sunday(utc[0], self.MONTH['sum']): |
| 71 | + # print('TIME ZONE Summer:', self.TIME_ZONE[self.zone]) |
| 72 | + return self.TIME_ZONE[self.zone] |
| 73 | + else: |
| 74 | + # print('TIME ZONE Winter:', self.TIME_ZONE[self.zone] - 1) |
| 75 | + return self.TIME_ZONE[self.zone] - 1 |
| 76 | + |
| 77 | + def setzone(self): |
| 78 | + ntp = self.getntp() |
| 79 | + z = self.adj_tzone(localtime(ntp)) if self.win else 0 |
| 80 | + utc = localtime(ntp + (3600 * z)) |
| 81 | + # print('Update time for Time Zone: ', z) |
| 82 | + RTC().datetime(utc) |
| 83 | + # print('Local Time: ', str(localtime())) |
0 commit comments