Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //#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;
- }
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement