ESP32 getting time from server too late

Hi guys I am using esp32 for one of my projects and getting time using NTP. Kindly see the below code

.

String get_time_from_the_server() {
timeClient.begin();                                    
timeClient.setTimeOffset(3600);                      
while (!timeClient.update()) {
  timeClient.forceUpdate();
}
  formattedDate = timeClient.getFormattedDate();
  int splitT = formattedDate.indexOf("T");
  timeStamp = formattedDate.substring(splitT + 1, formattedDate.length() - 1);
  return timeStamp;
}

This code works good, but the problem is sometimes it takes too long to get the time. Most of the time I can wait and get the data but sometimes it waits and waits and I need to reset my device which is unacceptable. It would be grateful if you guys suggest me some approaches that I can use to reduce the time or what should I do if it keeps on waiting other than resetting the device manually.

Regards,

I’m not sure if it will help you, but I made a non blocking ntp request. It won’t compile for you because it is tied to other parts of my code, but the errors should be easy to solve… Call loop_ntp() constantly, inside loop(). Call ntpRequest() to start requesting.

//#define DEBUG_NTP

struct
{
    uint8_t  mode : 3;       // Only three bits. Mode. Client will pick mode 3 for client.
    uint8_t  vn   : 3;       // Only three bits. Version number of the protocol.
    uint8_t  li   : 2;       // Only two bits. Leap indicator.
    uint8_t  stratum;        // Eight bits. Stratum level of the local clock.
    uint8_t  poll;           // Eight bits. Maximum interval between successive messages.
    uint8_t  precision;      // Eight bits. Precision of the local clock.
    uint32_t rootDelay;      // 32 bits. Total round trip delay time.
    uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
    uint32_t refId;          // 32 bits. Reference clock identifier.
    uint32_t refTm_s;        // 32 bits. Reference time-stamp seconds.
    uint32_t refTm_f;        // 32 bits. Reference time-stamp fraction of a second.
    uint32_t origTm_s;       // 32 bits. Originate time-stamp seconds.
    uint32_t origTm_f;       // 32 bits. Originate time-stamp fraction of a second.
    uint32_t rxTm_s;         // 32 bits. Received time-stamp seconds.
    uint32_t rxTm_f;         // 32 bits. Received time-stamp fraction of a second.
    uint32_t txTm_s;         // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
    uint32_t txTm_f;         // 32 bits. Transmit time-stamp fraction of a second.
} packet;                    // Total: 384 bits or 48 bytes.

#if !defined(ntohl)
uint32_t ntohl(uint32_t n)
{
    return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
}
#endif

uint16_t ntpFractionToMs( uint32_t fraction )
{
    return (uint16_t)(fraction * 1000ULL / 0x100000000ULL);
}

enum ntpState : uint8_t
{
    STOPPED,
    SEND,
    WAIT,
    PARSE,
    SYNC_RTC,
    DONE
};

ntpState ntpCurrentState = STOPPED;

void ntpRequest()
{
    if ( ntpCurrentState == STOPPED && wifiConnected )
	{
        Serial.print( "[NTP] Starting request.\n" );
        ntpRequesting = true;
        ntpCurrentState = SEND;
    }
    else
    {
        Serial.print( "[NTP] Unable to start request.\n" );
    }
}

void loop_ntp()
{
    if ( ntpCurrentState != STOPPED )
    {
        static uint8_t retryCounter = 0;
        static uint32_t startMillis = 0;
        static uint16_t syncDelay = 0;

        switch ( ntpCurrentState )
        {
            case SEND :
            {
                startMillis = currentMillis;
                memset( &packet, 0, sizeof( packet ) );
                packet.vn = 4;
                packet.mode = 3;
                WiFi.hostByName( ntpServerName, ntpServerIP );
                udp.flush();
                udp.beginPacket( ntpServerIP, 123 );
                udp.write(  ( uint8_t* ) &packet, sizeof( packet ) );
                udp.endPacket();
                retryCounter = 0;
                #if defined(DEBUG_NTP)
                    Serial.print( "[NTP] Waiting server reply...\n" );
                #endif
                ntpCurrentState = WAIT;
                break;
            }

            case WAIT :
            {
                static uint32_t previousMillis = currentMillis;

                if ( currentMillis - previousMillis >= 20UL )
                {
                    if ( ++retryCounter < 250 )
                    {
                        previousMillis = currentMillis;
                        ntpCurrentState = PARSE;
                    }
                    else
                    {
                        Serial.print( "[NTP] Timeout.\n" );
                        retryCounter = 0;
                        ntpCurrentState = DONE;
                    }
                }
                break;
            }

            case PARSE :
            {
                switch ( udp.parsePacket() )
                {
                    case 0 :
                    {
                        ntpCurrentState = WAIT;
                        break;
                    }
                    case sizeof( packet ) :
                    {
                        udp.read( ( uint8_t* ) &packet, sizeof( packet ) );
                        packet.txTm_s = ntohl( packet.txTm_s );
                        packet.txTm_f = ntpFractionToMs( ntohl( packet.txTm_f ) );
                        syncDelay = 1000 - packet.txTm_f;
                        
                        #if defined(DEBUG_NTP)
                            Serial.printf( "[NTP] Received packet after %u ms. Parsing...\n", currentMillis - startMillis );
                            packet.refTm_s  = ntohl( packet.refTm_s );
                            packet.refTm_f  = ntpFractionToMs( ntohl( packet.refTm_f ) );
                            packet.origTm_s = ntohl( packet.origTm_s );
                            packet.origTm_f = ntpFractionToMs( ntohl( packet.origTm_f ) );
                            packet.rxTm_s   = ntohl( packet.rxTm_s );
                            packet.rxTm_f   = ntpFractionToMs( ntohl( packet.rxTm_f ) );
                            Serial.printf( "li             = %hu\n",    packet.li );
                            Serial.printf( "vn             = %hu\n",    packet.vn );
                            Serial.printf( "mode           = %hu\n",    packet.mode );
                            Serial.printf( "stratum        = %hu\n",    packet.stratum );
                            Serial.printf( "poll           = %hu\n",    packet.poll );
                            Serial.printf( "precision      = %hu\n",    packet.precision );
                            Serial.printf( "rootDelay      = %u\n",     packet.rootDelay );
                            Serial.printf( "rootDispersion = %u\n",     packet.rootDispersion );
                            Serial.printf( "refId          = 0x%08X\n", packet.refId );
                            Serial.printf( "refTm          = %u.%hu\n", packet.refTm_s,  packet.refTm_f  );
                            Serial.printf( "origTm         = %u.%hu\n", packet.origTm_s, packet.origTm_f );
                            Serial.printf( "rxTm           = %u.%hu\n", packet.rxTm_s,  packet.rxTm_f  );
                            Serial.printf( "txTm           = %u.%hu\n", packet.txTm_s, packet.txTm_f );
                            Serial.printf( "[NTP] Synchronizing RTC in %u ms...\n", syncDelay );
                        #endif

                        startMillis = currentMillis;
                        ntpCurrentState = SYNC_RTC;
                        break;
                    }
                    default :
                    {
                        Serial.print( "[NTP] Bad packet length.\n" );
                        udp.flush();
                        ntpCurrentState = DONE;
                        break;
                    }
                }
                break;
            }

            case SYNC_RTC :
            {
                if ( currentMillis - startMillis >= syncDelay )
                {
                    time_t unixTime = packet.txTm_s - 2208988800UL + 1;
                    rtc.set( unixTime );
                    portENTER_CRITICAL( &mux );
                    rtcInterrupted = true;
                    portEXIT_CRITICAL( &mux );
                    nowLocal = tz.toLocal( unixTime );
                    TimeElements tm;
                    breakTime( nowLocal, tm );
                    Serial.printf( "[NTP] RTC synchronized. Local time: %02d/%02d/%4d %02d:%02d:%02d\n",
                        tm.Day, tm.Month, tmYearToCalendar(tm.Year), tm.Hour, tm.Minute, tm.Second );
                    ntpCurrentState = DONE;
                }
                break;
            }

            case DONE :
            {
                ntpRequesting = false;
                ntpCurrentState = STOPPED;
                break;
            }

            default :
            {
                break;
            }
        }
    }
}

Hello. Actually I do not have any problem if it blocks my code for 2 seconds or even 4 seconds. But the main thing is sometimes it gives me wrong time, means without updating. It returns 05:00:06.

The updated code is:

timeClient.update();
if (!timeClient.update()) {
Serial.println("I have come here");
timeClient.forceUpdate();
}

I removed while loop so that I do not get stuck in waiting for time. But it mostly returns 05:00:06.