Question about expected ntp_sync behavior
I have a local NTP server on my LAN that I can enable and disable. If I disable the NTP server and then, on my WiPy initialize an rtc thusly:
rtc = RTC() rtc.init(datetime=None, source=RTC.XTAL_32KHZ) rtc.ntp_sync(NTP_Server, update_period=30)
returns false as expected. As long as I keep my NTP server turned off, then the synced() test will return false. As is expected, if I enable my NTP server, then within 30 seconds, or so, the rtc will sync up and synced() will return True. This is all good and as expected.
My problem is with the opposite direction, that is if I want my device to sync up every 30 seconds and tell me if it can't. In this case, I initialize and start the rtc with my NTP server enabled and all works as expected. Unfortunately, if I disable my NTP server, rtc.synced() has never returned False, indicating that it was unable to synchronize.
The documentation for rtc.synced() indicates "Returns True if the last ntp_sync has been completed, False otherwise', and the documentation for rtc.ntp_sync indicates "update_period is the number of seconds between updates. Shortest period is 15 seconds.".
In summary, then, in my example I would expect that the rtc would attempt an update every 30 seconds and that, after I disable the NTP server, that this update would fail resulting in a rtc.synced() = false.
I'm assuming that the statement:
Returns True if the last ntp_sync has been completed, False otherwise
Should really be
Returns True if the last ntp_sync ATTEMPT has been SUCCESSFULLY completed, False otherwise
Do others see the same behavior? Am I doing anything wrong here?
For completeness, my overall goal is to time synchronize a bunch of WiPy devices on a LAN, and my time synchronization requirements demand updates every hour, or so, and I need to know if these updates were successful.
Has the 'firmware team' addressed this?
Thanks for this idea, I think I can use it. In my case, though, I won't be able to do the 'manual' sync because my problem is generally that the NTP server on my LAN is down. But, I should just be able to set the sync status to false and then generate the alert that I need.
Have you tried ntp_sync(None) to reset it? I've done something like the code below to sync the clock manually when the NTP library was being weird.
Basically you can just sync NTP manually by using sockets library to call out to the NTP server, and then you can handle the timout it there however you want.
import gc import socket import struct import time from machine import RTC from machine import Timer gc.enable() rtc_synced = False def rtc_init(): global rtc_synced rtc = RTC() rtc.ntp_sync('pool.ntp.org', update_period=15) print('Waiting for RTC/NTP sync...') chrono = Timer.Chrono() chrono.start() while not rtc.synced(): # wait for 30 seconds, then give up and try manual NTP sync if chrono.read() > 30: print('Sync timed out after %s seconds...' % chrono.read()) rtc.ntp_sync(None) break time.sleep(1) if rtc.synced(): print('RTC Set from NTP daemon to UTC:', rtc.now()) rtc_synced = True else: print('Fetching time from NTP server manually...') try: NTP_QUERY = bytearray(48) NTP_QUERY = 0x1b addr = socket.getaddrinfo('pool.ntp.org', 123)[-1] s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.settimeout(3) s.sendto(NTP_QUERY, addr) msg = s.recv(48) s.close() # 70 years difference between NTP and Pycom epoch val = struct.unpack("!I", msg[40:44]) - 2208988800 tm = time.localtime(val) rtc.init(tm) rtc_synced = True gc.collect() except socket.timeout: print('Timed out while fetching time from remote server.') if not rtc.synced() and rtc_synced: print('RTC Set from manual NTP call to UTC:', rtc.now()) # adjust timezone if rtc_synced: # UTC-7/MST for testing time.timezone(-7*60*60) print('RTC adjusted from UTC to local timezone:', time.localtime()) else: print('Unable to set RTC', rtc.now()) print('Resetting NTP sync to 15 minutes') rtc.ntp_sync('pool.ntp.org', 60*15)
Thanks for bringing this to our attention. Ive let the firmware team know and they will look into it.