2020-12-01 21:15:19 +01:00
|
|
|
# Copyright 2020 Google LLC
|
|
|
|
#
|
|
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
# you may not use this file except in compliance with the License.
|
|
|
|
# You may obtain a copy of the License at
|
|
|
|
#
|
|
|
|
# https://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
#
|
|
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
# See the License for the specific language governing permissions and
|
|
|
|
# limitations under the License.
|
2018-12-05 02:52:31 +01:00
|
|
|
import random
|
2024-02-27 08:05:22 +01:00
|
|
|
import time
|
2024-03-01 17:13:18 +01:00
|
|
|
from typing import Generator, Optional
|
2024-02-27 08:05:22 +01:00
|
|
|
|
2024-02-27 07:58:25 +01:00
|
|
|
import urequests
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
import asynced
|
2024-02-27 08:05:22 +01:00
|
|
|
import compat
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
|
2024-03-01 17:13:18 +01:00
|
|
|
def _fetch() -> Optional[dict]:
|
2018-12-05 02:52:31 +01:00
|
|
|
try:
|
2024-02-27 08:05:22 +01:00
|
|
|
return urequests.get("http://worldtimeapi.org/api/ip").json()
|
2018-12-05 02:52:31 +01:00
|
|
|
except OSError as ex:
|
2024-02-27 08:05:22 +01:00
|
|
|
print("OSError", ex)
|
2018-12-05 02:52:31 +01:00
|
|
|
return None
|
2020-11-29 20:51:54 +01:00
|
|
|
except ValueError as ex:
|
2024-02-27 08:05:22 +01:00
|
|
|
print("ValueError", ex)
|
2020-11-29 20:51:54 +01:00
|
|
|
return None
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
|
2018-12-10 15:52:34 +01:00
|
|
|
def _jitter(mid: int) -> int:
|
2024-02-27 07:58:25 +01:00
|
|
|
return compat.randint(mid, mid * 120 // 100)
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
|
2024-03-01 17:13:18 +01:00
|
|
|
def _sync() -> Generator[Optional[dict], None, None]:
|
2018-12-05 02:52:31 +01:00
|
|
|
while True:
|
|
|
|
# Poll quickly until the first result comes in.
|
|
|
|
while True:
|
|
|
|
got = _fetch()
|
|
|
|
if got is not None:
|
|
|
|
yield got
|
|
|
|
break
|
2024-02-27 07:58:25 +01:00
|
|
|
yield from asynced.delay(_jitter(5))
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
# Poll slowly until the connection drops.
|
|
|
|
while True:
|
2018-12-10 16:33:52 +01:00
|
|
|
yield from asynced.delay(_jitter(60 * 60))
|
2018-12-05 02:52:31 +01:00
|
|
|
got = _fetch()
|
|
|
|
if got is None:
|
|
|
|
break
|
|
|
|
yield got
|
|
|
|
|
|
|
|
|
2024-02-27 07:58:25 +01:00
|
|
|
def _get_day_sec(resp):
|
2024-02-27 08:05:22 +01:00
|
|
|
parts = resp.get("datetime", "").split("T")
|
2024-02-27 07:58:25 +01:00
|
|
|
if len(parts) != 2:
|
|
|
|
return None
|
2024-02-27 08:05:22 +01:00
|
|
|
hms = parts[1].split("+")[0].split(":")
|
2024-02-27 07:58:25 +01:00
|
|
|
if len(hms) != 3:
|
|
|
|
return None
|
2024-02-27 08:05:22 +01:00
|
|
|
return float(hms[0]) * 3600 + float(hms[1]) * 60 + float(hms[2])
|
|
|
|
|
|
|
|
|
2024-03-01 17:13:18 +01:00
|
|
|
def day_sec() -> Generator[Optional[float], None, None]:
|
2018-12-05 02:52:31 +01:00
|
|
|
s = _sync()
|
|
|
|
# Spin until the first result comes in.
|
|
|
|
for got in s:
|
|
|
|
if got is None:
|
2024-03-01 17:13:18 +01:00
|
|
|
yield None
|
2018-12-05 02:52:31 +01:00
|
|
|
continue
|
2024-02-27 07:58:25 +01:00
|
|
|
local = compat.monotonic()
|
|
|
|
base = _get_day_sec(got)
|
2018-12-05 02:52:31 +01:00
|
|
|
if base is not None:
|
|
|
|
break
|
|
|
|
good = got
|
|
|
|
|
2024-03-01 17:13:18 +01:00
|
|
|
assert base is not None
|
2018-12-05 02:52:31 +01:00
|
|
|
for got in s:
|
2024-02-27 07:58:25 +01:00
|
|
|
now = base + compat.monotonic() - local
|
2024-03-01 17:13:18 +01:00
|
|
|
yield now % (60 * 60 * 24)
|
2018-12-05 02:52:31 +01:00
|
|
|
|
|
|
|
if got is not None:
|
|
|
|
# Update the baseline.
|
2024-02-27 07:58:25 +01:00
|
|
|
b2 = _get_day_sec(got)
|
2018-12-05 02:52:31 +01:00
|
|
|
if b2 is not None:
|
2024-02-27 07:58:25 +01:00
|
|
|
local = compat.monotonic()
|
2018-12-05 02:52:31 +01:00
|
|
|
base = b2
|
|
|
|
good = got
|
|
|
|
|
|
|
|
|
|
|
|
def test():
|
2024-03-01 17:13:18 +01:00
|
|
|
for secs in day_sec():
|
2018-12-05 02:52:31 +01:00
|
|
|
print(secs)
|
2024-02-27 07:58:25 +01:00
|
|
|
compat.sleep(0.3)
|
2018-12-10 15:52:34 +01:00
|
|
|
|
|
|
|
|
2024-02-27 08:05:22 +01:00
|
|
|
if __name__ == "__main__":
|
2018-12-10 15:52:34 +01:00
|
|
|
test()
|