Advertisement
Guillaume_D

Untitled

Jan 30th, 2021
162
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.92 KB | None | 0 0
  1. //#define DEBUG_NTP
  2.  
  3. struct
  4. {
  5.     uint8_t  mode : 3;       // Only three bits. Mode. Client will pick mode 3 for client.
  6.     uint8_t  vn   : 3;       // Only three bits. Version number of the protocol.
  7.     uint8_t  li   : 2;       // Only two bits. Leap indicator.
  8.     uint8_t  stratum;        // Eight bits. Stratum level of the local clock.
  9.     uint8_t  poll;           // Eight bits. Maximum interval between successive messages.
  10.     uint8_t  precision;      // Eight bits. Precision of the local clock.
  11.     uint32_t rootDelay;      // 32 bits. Total round trip delay time.
  12.     uint32_t rootDispersion; // 32 bits. Max error aloud from primary clock source.
  13.     uint32_t refId;          // 32 bits. Reference clock identifier.
  14.     uint32_t refTm_s;        // 32 bits. Reference time-stamp seconds.
  15.     uint32_t refTm_f;        // 32 bits. Reference time-stamp fraction of a second.
  16.     uint32_t origTm_s;       // 32 bits. Originate time-stamp seconds.
  17.     uint32_t origTm_f;       // 32 bits. Originate time-stamp fraction of a second.
  18.     uint32_t rxTm_s;         // 32 bits. Received time-stamp seconds.
  19.     uint32_t rxTm_f;         // 32 bits. Received time-stamp fraction of a second.
  20.     uint32_t txTm_s;         // 32 bits and the most important field the client cares about. Transmit time-stamp seconds.
  21.     uint32_t txTm_f;         // 32 bits. Transmit time-stamp fraction of a second.
  22. } packet;                    // Total: 384 bits or 48 bytes.
  23.  
  24. #if !defined(ntohl)
  25. uint32_t ntohl(uint32_t n)
  26. {
  27.     return ((n & 0xFF) << 24) | ((n & 0xFF00) << 8) | ((n & 0xFF0000) >> 8) | ((n & 0xFF000000) >> 24);
  28. }
  29. #endif
  30.  
  31. uint16_t ntpFractionToMs( uint32_t fraction )
  32. {
  33.     return (uint16_t)(fraction * 1000ULL / 0x100000000ULL);
  34. }
  35.  
  36. enum ntpState : uint8_t
  37. {
  38.     STOPPED,
  39.     SEND,
  40.     WAIT,
  41.     PARSE,
  42.     SYNC_RTC,
  43.     DONE
  44. };
  45.  
  46. ntpState ntpCurrentState = STOPPED;
  47.  
  48. void ntpRequest()
  49. {
  50.     if ( ntpCurrentState == STOPPED && wifiConnected )
  51.     {
  52.         Serial.print( "[NTP] Starting request.\n" );
  53.         ntpRequesting = true;
  54.         ntpCurrentState = SEND;
  55.     }
  56.     else
  57.     {
  58.         Serial.print( "[NTP] Unable to start request.\n" );
  59.     }
  60. }
  61.  
  62. void loop_ntp()
  63. {
  64.     if ( ntpCurrentState != STOPPED )
  65.     {
  66.         static uint8_t retryCounter = 0;
  67.         static uint32_t startMillis = 0;
  68.         static uint16_t syncDelay = 0;
  69.  
  70.         switch ( ntpCurrentState )
  71.         {
  72.             case SEND :
  73.             {
  74.                 startMillis = currentMillis;
  75.                 memset( &packet, 0, sizeof( packet ) );
  76.                 packet.vn = 4;
  77.                 packet.mode = 3;
  78.                 WiFi.hostByName( ntpServerName, ntpServerIP );
  79.                 udp.flush();
  80.                 udp.beginPacket( ntpServerIP, 123 );
  81.                 udp.write(  ( uint8_t* ) &packet, sizeof( packet ) );
  82.                 udp.endPacket();
  83.                 retryCounter = 0;
  84.                 #if defined(DEBUG_NTP)
  85.                     Serial.print( "[NTP] Waiting server reply...\n" );
  86.                 #endif
  87.                 ntpCurrentState = WAIT;
  88.                 break;
  89.             }
  90.  
  91.             case WAIT :
  92.             {
  93.                 static uint32_t previousMillis = currentMillis;
  94.  
  95.                 if ( currentMillis - previousMillis >= 20UL )
  96.                 {
  97.                     if ( ++retryCounter < 250 )
  98.                     {
  99.                         previousMillis = currentMillis;
  100.                         ntpCurrentState = PARSE;
  101.                     }
  102.                     else
  103.                     {
  104.                         Serial.print( "[NTP] Timeout.\n" );
  105.                         retryCounter = 0;
  106.                         ntpCurrentState = DONE;
  107.                     }
  108.                 }
  109.                 break;
  110.             }
  111.  
  112.             case PARSE :
  113.             {
  114.                 switch ( udp.parsePacket() )
  115.                 {
  116.                     case 0 :
  117.                     {
  118.                         ntpCurrentState = WAIT;
  119.                         break;
  120.                     }
  121.                     case sizeof( packet ) :
  122.                     {
  123.                         udp.read( ( uint8_t* ) &packet, sizeof( packet ) );
  124.                         packet.txTm_s = ntohl( packet.txTm_s );
  125.                         packet.txTm_f = ntpFractionToMs( ntohl( packet.txTm_f ) );
  126.                         syncDelay = 1000 - packet.txTm_f;
  127.                        
  128.                         #if defined(DEBUG_NTP)
  129.                             Serial.printf( "[NTP] Received packet after %u ms. Parsing...\n", currentMillis - startMillis );
  130.                             packet.refTm_s  = ntohl( packet.refTm_s );
  131.                             packet.refTm_f  = ntpFractionToMs( ntohl( packet.refTm_f ) );
  132.                             packet.origTm_s = ntohl( packet.origTm_s );
  133.                             packet.origTm_f = ntpFractionToMs( ntohl( packet.origTm_f ) );
  134.                             packet.rxTm_s   = ntohl( packet.rxTm_s );
  135.                             packet.rxTm_f   = ntpFractionToMs( ntohl( packet.rxTm_f ) );
  136.                             Serial.printf( "li             = %hu\n",    packet.li );
  137.                             Serial.printf( "vn             = %hu\n",    packet.vn );
  138.                             Serial.printf( "mode           = %hu\n",    packet.mode );
  139.                             Serial.printf( "stratum        = %hu\n",    packet.stratum );
  140.                             Serial.printf( "poll           = %hu\n",    packet.poll );
  141.                             Serial.printf( "precision      = %hu\n",    packet.precision );
  142.                             Serial.printf( "rootDelay      = %u\n",     packet.rootDelay );
  143.                             Serial.printf( "rootDispersion = %u\n",     packet.rootDispersion );
  144.                             Serial.printf( "refId          = 0x%08X\n", packet.refId );
  145.                             Serial.printf( "refTm          = %u.%hu\n", packet.refTm_s,  packet.refTm_f  );
  146.                             Serial.printf( "origTm         = %u.%hu\n", packet.origTm_s, packet.origTm_f );
  147.                             Serial.printf( "rxTm           = %u.%hu\n", packet.rxTm_s,  packet.rxTm_f  );
  148.                             Serial.printf( "txTm           = %u.%hu\n", packet.txTm_s, packet.txTm_f );
  149.                             Serial.printf( "[NTP] Synchronizing RTC in %u ms...\n", syncDelay );
  150.                         #endif
  151.  
  152.                         startMillis = currentMillis;
  153.                         ntpCurrentState = SYNC_RTC;
  154.                         break;
  155.                     }
  156.                     default :
  157.                     {
  158.                         Serial.print( "[NTP] Bad packet length.\n" );
  159.                         udp.flush();
  160.                         ntpCurrentState = DONE;
  161.                         break;
  162.                     }
  163.                 }
  164.                 break;
  165.             }
  166.  
  167.             case SYNC_RTC :
  168.             {
  169.                 if ( currentMillis - startMillis >= syncDelay )
  170.                 {
  171.                     time_t unixTime = packet.txTm_s - 2208988800UL + 1;
  172.                     rtc.set( unixTime );
  173.                     portENTER_CRITICAL( &mux );
  174.                     rtcInterrupted = true;
  175.                     portEXIT_CRITICAL( &mux );
  176.                     nowLocal = tz.toLocal( unixTime );
  177.                     TimeElements tm;
  178.                     breakTime( nowLocal, tm );
  179.                     Serial.printf( "[NTP] RTC synchronized. Local time: %02d/%02d/%4d %02d:%02d:%02d\n",
  180.                         tm.Day, tm.Month, tmYearToCalendar(tm.Year), tm.Hour, tm.Minute, tm.Second );
  181.                     ntpCurrentState = DONE;
  182.                 }
  183.                 break;
  184.             }
  185.  
  186.             case DONE :
  187.             {
  188.                 ntpRequesting = false;
  189.                 ntpCurrentState = STOPPED;
  190.                 break;
  191.             }
  192.  
  193.             default :
  194.             {
  195.                 break;
  196.             }
  197.         }
  198.     }
  199. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement