Question about expected ntp_sync behavior



  • Hi:
    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)
    

    then

    rtc.synced()
    

    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.

    Thanks,
    Phil



  • Any movement on this?



  • @paul-thornton
    Has the 'firmware team' addressed this?

    Thanks,
    Phil



  • @protean
    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[0] = 0x1b
                addr = socket.getaddrinfo('pool.ntp.org', 123)[0][-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])[0] - 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.


Log in to reply
 

Pycom on Twitter