const int NTP_PACKET_SIZE = 48; // NTP timestamp is in the first 48 bytes byte packetBufferNTPOut[NTP_PACKET_SIZE]; // buffer to hold incoming and outgoing NTP packets byte packetBufferNTPIn[NTP_PACKET_SIZE]; // buffer to hold incoming NTP packets IPAddress timeServer(129, 6, 15, 28); // time-a.nist.gov NTP server unsigned int localPort = 2390; // local port to listen for NTP UDP packets /************************************************************************** Initialize the port that will receive responses from an NTP Server. **************************************************************************/ void initTimePort(){ Udp.begin(localPort); // Open the local UDP Port } /************************************************************************** Initialize the packet that will be used to request time from an NTP Server. **************************************************************************/ void initNTPRequest() { // set all bytes in the buffer to 0 memset(packetBufferNTPOut, 0, NTP_PACKET_SIZE); // Initialize values needed to form NTP request // (see URL above for details on the packets) packetBufferNTPOut[0] = 0b11100011; // LI, Version, Mode packetBufferNTPOut[1] = 0; // Stratum, or type of clock packetBufferNTPOut[2] = 6; // Polling Interval packetBufferNTPOut[3] = 0xEC; // Peer Clock Precision // 8 bytes of zero for Root Delay & Root Dispersion packetBufferNTPOut[12] = 49; packetBufferNTPOut[13] = 0x4E; packetBufferNTPOut[14] = 49; packetBufferNTPOut[15] = 52; } /************************************************************************** Send pre-initialized time request packet **************************************************************************/ unsigned long sendNTPpacket() { Udp.beginPacket(timeServer, 123); //NTP requests are to port 123 Udp.write(packetBufferNTPOut, NTP_PACKET_SIZE); Udp.endPacket(); } /************************************************************************** Receive NTP time data **************************************************************************/ String receiveNTPpacket(){ if ( Udp.parsePacket() ) { // We've received a packet, read the data from it Udp.read(packetBufferNTPIn, NTP_PACKET_SIZE); // read the packet into the buffer // The timestamp starts at byte 40 of the received packet and is four bytes, // or two words, long. First, extract the two words and combine the four bytes // into an unsigned long integer. unsigned long highWord = word(packetBufferNTPIn[40], packetBufferNTPIn[41]); unsigned long lowWord = word(packetBufferNTPIn[42], packetBufferNTPIn[43]); unsigned long secsSince1900 = highWord << 16 | lowWord; // Serial.print("Seconds since Jan 1 1900 = " ); // Serial.println(secsSince1900); // Subtract midnight 01/01/2018 (CST) in seconds NTP time (3723775200)so we can // calculate the number of days since new years, which allows us to easily // derive the date. The extra 3600 seconds (1 hr) is to compensate for DST. unsigned long epoch = secsSince1900 - 3723775200 + 3600; // calculate the number of days since new years... int days = (epoch/86400)+1; int years = 2018; // Turn days into the date that gets used while (true){ dateString = showDate(days, years); if (dateString != ""){ break; } else { days -= 365; // if 2019 or beyond, decrement the days by 1 year years += 1; // increment the year number and try again } } // fetch the timeString timeString = showTime(epoch); // merge strings return dateString + timeString; } else { Serial.println("Timeout"); return ""; } } /************************************************************************** Extract a human-readable time from the epoch. **************************************************************************/ String showTime(unsigned long epoch){ // calculate the hour (86400 equals secs per day) String strTemp; int temp = (epoch % 86400L) / 3600; if (temp < 10){ strTemp = "0"; } strTemp = strTemp + temp + ":"; // calculate the minute (3600 equals secs per minute) temp = ((epoch % 3600) / 60); if (temp < 10){ strTemp = strTemp + "0"; } strTemp = strTemp + temp + ":"; // calculate the seconds temp = (epoch % 60); if ( temp < 10 ) { strTemp = strTemp + "0"; } strTemp = strTemp + temp; return strTemp; } /************************************************************************** Extract a human-readable time from the day number and the year. **************************************************************************/ String showDate(int days, int years){ bool leapyear = false; if (years % 4 == 0){ leapyear = true; } if (days <= 31){ // January if (days < 10) { return "0" + String(days) + ("/01/")+ years + (" "); } else { return String(days) + ("/01/")+ years + (" "); } } if (days <= 59){ // February if (days-31 < 10) { return "0" + String(days-31) + ("/02/")+ years + (" "); } else { return String(days-31) + ("/02/")+ years + (" "); } } if ((days == 60) && leapyear){ // February 29th (Leap Year) return String(days-31) + ("/02/")+ years + (" "); } // If we are in a leap year and after Feb 29th, decrement days // to corrrect the day count for the extra day. if (leapyear){ days -= 1; } if (days <= 90){ // March if (days-59 < 10) { return "0" + String(days-59) + ("/03/")+ years + (" "); } else { return String(days-59) + ("/03/")+ years + (" "); } } if (days <= 120){ // April if (days-90 < 10){ return "0" + String(days-90) + ("/04/")+ years + (" "); } else { return String(days-90) + ("/04/")+ years + (" "); } } if (days <= 151){ // May if (days-120 < 10) { return "0" + String(days-120) + ("/05/")+ years + (" "); } else { return String(days-120) + ("/05/")+ years + (" "); } } if (days <= 181){ // June if (days-151 < 10) { return "0" + String(days-151) + ("/06/")+ years + (" "); } else { return String(days-151) + ("/06/")+ years + (" "); } } if (days <= 212){ // July if (days-181 < 10) { return "0" + String(days-181) + ("/07/")+ years + (" "); } else { return String(days-181) + ("/07/")+ years + (" "); } } if (days <= 243){ // August if (days-212) { return "0" + String(days-212) + ("/08/")+ years + (" "); } else { return String(days-212) + ("/08/")+ years + (" "); } } if (days <= 273){ // September if (days-243) { return "0" + String(days-243) + ("/09/")+ years + (" "); } else { return String(days-243) + ("/09/")+ years + (" "); } } if (days <= 304){ // October if (days-273) { return "0" + String(days-273) + ("/10/")+ years + (" "); } else { return String(days-273) + ("/10/")+ years + (" "); } } if (days <= 334){ // November if (days-304) { return "0" + String(days-304) + ("/11/")+ years + (" "); } else { return String(days-304) + ("/11/")+ years + (" "); } } if (days <= 365){ // December if (days-334) { return "0" + String(days-334) + ("/12/")+ years + (" "); } else { return String(days-334) + ("/12/")+ years + (" "); } } else { return ""; } }