adafruit / Adafruit_CircuitPython_NTP

Network Time Protocol (NTP) Helper for CircuitPython
MIT License
9 stars 18 forks source link

OverflowError: timestamp out of range for platform time_t #2

Closed mcgrailk3 closed 4 years ago

mcgrailk3 commented 4 years ago

Running the example on Adafruit Metro M4 Express AirLift (WiFi) creates this error. Running latest library as well.

OverflowError: timestamp out of range for platform time_t

jerryneedell commented 4 years ago

I have reproduced this error , but if I execute the ntp_simpletest.py code manually, line by line, at the REPL, it works ...

for some reason -- when the script is executed, the esp.get_time() call in ntp.set_time() is returning (0,)

jerryneedell commented 4 years ago

hmm

I added a loop to wait for esp.get_time() to return a non-zero result -- it works after 15 seconds

# Initialize the NTP object
ntp = NTP(esp)
while esp.get_time()[0] == 0 :
    print(esp.get_time())
    time.sleep(1)

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.0.0-alpha.1-2-gfebfc7e4e on 2019-09-02; Adafruit PyPortal with samd51j20
>>> 
>>> import ntptest
Connecting to AP...
could not connect to AP, retrying:  ('No such ssid', b'Needell Airport')
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(1568371142,)
Seconds since Jan 1, 1970: 1568371142 seconds
struct_time(tm_year=2019, tm_mon=9, tm_mday=13, tm_hour=10, tm_min=39, tm_sec=2, tm_wday=4, tm_yday=256, tm_isdst=-1)
It is currently 9/13/2019 at 10:39:2 UTC
>>> 

also ran on metro_m4_airlift -- one time it worked after 1 retry -- the next took 16 seconds

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.0.0-alpha.2-46-gb8200d729 on 2019-09-10; Adafruit Metro M4 Airlift Lite with samd51j19
>>> import ntptest
Connecting to AP...
(0,)
Seconds since Jan 1, 1970: 1568371357 seconds
struct_time(tm_year=2019, tm_mon=9, tm_mday=13, tm_hour=10, tm_min=42, tm_sec=37, tm_wday=4, tm_yday=256, tm_isdst=-1)
It is currently 9/13/2019 at 10:42:37 UTC
>>>
>>>
soft reboot

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.

Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.0.0-alpha.2-46-gb8200d729 on 2019-09-10; Adafruit Metro M4 Airlift Lite with samd51j19
>>> import ntptest
Connecting to AP...
could not connect to AP, retrying:  ('No such ssid', b'Needell Airport')
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
(0,)
Seconds since Jan 1, 1970: 1568371406 seconds
struct_time(tm_year=2019, tm_mon=9, tm_mday=13, tm_hour=10, tm_min=43, tm_sec=26, tm_wday=4, tm_yday=256, tm_isdst=-1)
It is currently 9/13/2019 at 10:43:26 UTC
>>> 
jerryneedell commented 4 years ago

this is not a problem with NTP but with ESP32SPI - opened issue there https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/issues/72

jerryneedell commented 4 years ago

I submitted a PR to have ESP32SPI raise an exception if the returned time is zero. https://github.com/adafruit/Adafruit_CircuitPython_ESP32SPI/pull/73

The adafruit_ntp.py library could be modiied to handle the exception or the ntp_simpletest.py can handle it - here is an example

import time
import board
import busio
from digitalio import DigitalInOut
from adafruit_esp32spi import adafruit_esp32spi
from adafruit_ntp import NTP

# If you are using a board with pre-defined ESP32 Pins:
esp32_cs = DigitalInOut(board.ESP_CS)
esp32_ready = DigitalInOut(board.ESP_BUSY)
esp32_reset = DigitalInOut(board.ESP_RESET)

# If you have an externally connected ESP32:
# esp32_cs = DigitalInOut(board.D9)
# esp32_ready = DigitalInOut(board.D10)
# esp32_reset = DigitalInOut(board.D5)

spi = busio.SPI(board.SCK, board.MOSI, board.MISO)
esp = adafruit_esp32spi.ESP_SPIcontrol(spi, esp32_cs, esp32_ready, esp32_reset)

print("Connecting to AP...")
while not esp.is_connected:
    try:
        esp.connect_AP(b"WIFI_SSID", b"WIFI_PASS")
    except RuntimeError as e:
        print("could not connect to AP, retrying: ", e)
        continue

# Initialize the NTP object
ntp = NTP(esp)

# Fetch and set the microcontroller's current UTC time
# keep retrying until valid time is returned
while True:
    try:
        ntp.set_time()
        break
    except ValueError as e:
        print("error gettiing time - retrying in 5 seconds: ", e)
        time.sleep(5)
        continue
# Get the current time in seconds since Jan 1, 1970
current_time = time.time()
print("Seconds since Jan 1, 1970: {} seconds".format(current_time))

# Convert the current time in seconds since Jan 1, 1970 to a struct_time
now = time.localtime(current_time)
print(now)

# Pretty-parse the struct_time
print("It is currently {}/{}/{} at {}:{}:{} UTC".format(
    now.tm_mon, now.tm_mday, now.tm_year,
    now.tm_hour,now.tm_min, now.tm_sec))

I ran this with the updated esp32SPI on a metro_m4_airlift_lite


Press any key to enter the REPL. Use CTRL-D to reload.
Adafruit CircuitPython 5.0.0-alpha.2-46-gb8200d729 on 2019-09-10; Adafruit Metro M4 Airlift Lite with samd51j19
>>> import ntp_simpletest
Connecting to AP...
could not connect to AP, retrying:  ('No such ssid', b'Needell Airport')
error gettiing time - retrying in 5 seconds:  _GET_TIME returned 0
error gettiing time - retrying in 5 seconds:  _GET_TIME returned 0
error gettiing time - retrying in 5 seconds:  _GET_TIME returned 0
Seconds since Jan 1, 1970: 1568476935 seconds
struct_time(tm_year=2019, tm_mon=9, tm_mday=14, tm_hour=16, tm_min=2, tm_sec=15, tm_wday=5, tm_yday=257, tm_isdst=-1)
It is currently 9/14/2019 at 16:2:15 UTC
>>> 

Let me know how you think we should proceed. Do you want a PR to just update the ntp_simpletest.py or do you want to handle the exception in the library? If so, do you want to limit the number of retries? It typically takes 15 seconds for the time to become valid.

mcgrailk3 commented 4 years ago

Hey sorry, I am just seeing this. Everything looks great. I'm impressed!

brentru commented 4 years ago

@jerryneedell I was playing around with this this AM and will submit a PR.

I added an valid_time property to the ntp object, set_time sets this property if valid, and a user would check against the property with a loop in the modified example code. This avoids blocking loops or printing in the library.

brentru commented 4 years ago

Patched in master and released, closing...