Sergei G / NetworkServices

Dependents:   coap-example Borsch coap-example

Fork of NetworkServices by AMETEK Powervar

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SNTPClient.cpp Source File

SNTPClient.cpp

00001 #include "SNTPClient.h"
00002 #include "DNSClient.h"
00003 
00004 #define MAX_TRY_WRITE 20
00005 #define MAX_TRY_READ 10
00006 
00007 //Debug is disabled by default
00008 #ifdef _SNTP_DEBUG_
00009 #define DBG(x, ...) std::printf("[SNTPClient : DBG]"x"\r\n", ##__VA_ARGS__); 
00010 #define WARN(x, ...) std::printf("[SNTPClient : WARN]"x"\r\n", ##__VA_ARGS__); 
00011 #define ERR(x, ...) std::printf("[SNTPClient : ERR]"x"\r\n", ##__VA_ARGS__); 
00012 #else
00013 #define DBG(x, ...) 
00014 #define WARN(x, ...)
00015 #define ERR(x, ...) 
00016 #endif
00017 
00018 #define INFO(x, ...) printf("[SNTPClient : INFO]"x"\r\n", ##__VA_ARGS__); 
00019 
00020 SNTPClient::SNTPClient(NetworkStack *ns, const char* url, uint8_t time_zone) {
00021     DNSClient dns(ns);
00022     
00023     if (dns.lookup(url)) {
00024         const char* dns_addr = dns.get_ip_address();
00025         memcpy(host, dns_addr, strlen(dns_addr));
00026         host[strlen(dns_addr)] = '\0';
00027     } else {
00028         memcpy(host, url, strlen(url));
00029         host[strlen(url)] = '\0';
00030     }
00031     
00032     port = ntp_port;
00033     m_ns = ns;
00034     m_udp = NULL;
00035     tz = time_zone;
00036 }
00037 
00038 bool SNTPClient::connect() {
00039     if (m_udp == NULL) {
00040         m_udp = new UDPSocket;
00041         m_udp->open(m_ns);
00042     }
00043     
00044     m_udp->set_blocking(false);
00045     m_udp->set_timeout(3000);
00046     m_udp->bind(rand()&0x7fff);
00047 
00048     sntp_server.set_ip_address(host);
00049     sntp_server.set_port(port);
00050 
00051     nsapi_addr_t na = sntp_server.get_addr();
00052     NTPformat.dstaddr[0] = na.bytes[0];
00053     NTPformat.dstaddr[1] = na.bytes[1];
00054     NTPformat.dstaddr[2] = na.bytes[2];
00055     NTPformat.dstaddr[3] = na.bytes[3];
00056     DBG("NTP Server: %s\r\n", sntp_server.get_ip_address());
00057 
00058     uint8_t Flag;
00059     NTPformat.leap = 0;           /* leap indicator */
00060     NTPformat.version = 4;        /* version number */
00061     NTPformat.mode = 3;           /* mode */
00062     NTPformat.stratum = 0;        /* stratum */
00063     NTPformat.poll = 0;           /* poll interval */
00064     NTPformat.precision = 0;      /* precision */
00065     NTPformat.rootdelay = 0;      /* root delay */
00066     NTPformat.rootdisp = 0;       /* root dispersion */
00067     NTPformat.refid = 0;          /* reference ID */
00068     NTPformat.reftime = 0;        /* reference time */
00069     NTPformat.org = 0;            /* origin timestamp */
00070     NTPformat.rec = 0;            /* receive timestamp */
00071     NTPformat.xmt = 1;            /* transmit timestamp */
00072 
00073     Flag = (NTPformat.leap<<6)+(NTPformat.version<<3)+NTPformat.mode; //one byte Flag
00074     memcpy(ntpmessage,(void const*)(&Flag),1);
00075 
00076     return true;
00077 }
00078 
00079 bool SNTPClient::getTime(datetime *time) {
00080     if (!m_udp) return false;
00081     
00082     uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40
00083 
00084     int n = m_udp->sendto(sntp_server, (char *)ntpmessage, sizeof(ntpmessage));
00085     
00086     char in_buffer[MAX_SNTP_BUF_SIZE];
00087     n = m_udp->recvfrom(&sntp_server, in_buffer, sizeof(in_buffer));
00088 
00089     if(n <= 0) {
00090         return false;
00091     }
00092 
00093     get_seconds_from_ntp_server((uint8_t *)in_buffer,startindex);
00094 
00095     time->yy = Nowdatetime.yy;
00096     time->mo = Nowdatetime.mo;
00097     time->dd = Nowdatetime.dd;
00098     time->hh = Nowdatetime.hh;
00099     time->mm = Nowdatetime.mm;
00100     time->ss = Nowdatetime.ss;
00101 
00102     return true;
00103 }
00104 
00105 bool SNTPClient::close() {
00106     if (m_udp) {
00107         delete m_udp;
00108         m_udp = NULL;
00109     }
00110     return true;
00111 }
00112 
00113 char* SNTPClient::getHost() {
00114     return host;
00115 }
00116 
00117 /*
00118 00)UTC-12:00 Baker Island, Howland Island (both uninhabited)
00119 01) UTC-11:00 American Samoa, Samoa
00120 02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii)
00121 03) UTC-09:30 Marquesas Islands
00122 04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska)
00123 05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California)
00124 06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state))
00125 07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta)
00126 08) UTC-07:00 Mexico (Chihuahua), United States (Colorado)
00127 09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras
00128 10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas)
00129 11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru
00130 12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec)
00131 13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.)
00132 14) UTC-04:30 Venezuela
00133 15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay,
00134 16) UTC-04:00 Puerto Rico, Trinidad and Tobago
00135 17) UTC-03:30 Canada (Newfoundland)
00136 18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay
00137 19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands
00138 20) UTC-01:00 Portugal (Azores), Cape Verde
00139 21) UTC&#177;00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira)
00140 22) UTC&#177;00:00 Spain (Canary Islands), Morocco, United Kingdom
00141 23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina,
00142 24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo,
00143 25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland
00144 26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia,
00145 27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine
00146 28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia,
00147 29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen
00148 30) UTC+03:30 (Summer)Iran
00149 31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates
00150 32) UTC+04:30 Afghanistan
00151 33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan
00152 34) UTC+05:30 India, Sri Lanka
00153 35) UTC+05:45 Nepal
00154 36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast)
00155 37) UTC+06:30 Cocos Islands, Myanmar
00156 38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam
00157 39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia
00158 40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan
00159 41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia))
00160 42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria)
00161 43) UTC+10:30 Lord Howe Island
00162 44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands
00163 45) UTC+11:30 Norfolk Island
00164 46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand
00165 47) UTC+12:45 (Summer)New Zealand
00166 48) UTC+13:00 Tonga
00167 49) UTC+14:00 Kiribati (Line Islands)
00168 */
00169 void SNTPClient::get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx)
00170 {
00171     tstamp seconds = 0;
00172     uint8_t i=0;
00173     for (i = 0; i < 4; i++)
00174     {
00175         seconds = (seconds << 8) | buf[idx + i];
00176     }
00177     switch (tz) // Time Zone
00178     {
00179     case 0:
00180         seconds -=  12*3600;
00181         break;
00182     case 1:
00183         seconds -=  11*3600;
00184         break;
00185     case 2:
00186         seconds -=  10*3600;
00187         break;
00188     case 3:
00189         seconds -=  (9*3600+30*60);
00190         break;
00191     case 4:
00192         seconds -=  9*3600;
00193         break;
00194     case 5:
00195     case 6:
00196         seconds -=  8*3600;
00197         break;
00198     case 7:
00199     case 8:
00200         seconds -=  7*3600;
00201         break;
00202     case 9:
00203     case 10:
00204         seconds -=  6*3600;
00205         break;
00206     case 11:
00207     case 12:
00208     case 13:
00209         seconds -= 5*3600;
00210         break;
00211     case 14:
00212         seconds -=  (4*3600+30*60);
00213         break;
00214     case 15:
00215     case 16:
00216         seconds -=  4*3600;
00217         break;
00218     case 17:
00219         seconds -=  (3*3600+30*60);
00220         break;
00221     case 18:
00222         seconds -=  3*3600;
00223         break;
00224     case 19:
00225         seconds -=  2*3600;
00226         break;
00227     case 20:
00228         seconds -=  1*3600;
00229         break;
00230     case 21:                            //?
00231     case 22:
00232         break;
00233     case 23:
00234     case 24:
00235     case 25:
00236         seconds +=  1*3600;
00237         break;
00238     case 26:
00239     case 27:
00240         seconds +=  2*3600;
00241         break;
00242     case 28:
00243     case 29:
00244         seconds +=  3*3600;
00245         break;
00246     case 30:
00247         seconds +=  (3*3600+30*60);
00248         break;
00249     case 31:
00250         seconds +=  4*3600;
00251         break;
00252     case 32:
00253         seconds +=  (4*3600+30*60);
00254         break;
00255     case 33:
00256         seconds +=  5*3600;
00257         break;
00258     case 34:
00259         seconds +=  (5*3600+30*60);
00260         break;
00261     case 35:
00262         seconds +=  (5*3600+45*60);
00263         break;
00264     case 36:
00265         seconds +=  6*3600;
00266         break;
00267     case 37:
00268         seconds +=  (6*3600+30*60);
00269         break;
00270     case 38:
00271         seconds +=  7*3600;
00272         break;
00273     case 39:
00274         seconds +=  8*3600;
00275         break;
00276     case 40:
00277         seconds +=  9*3600;
00278         break;
00279     case 41:
00280         seconds +=  (9*3600+30*60);
00281         break;
00282     case 42:
00283         seconds +=  10*3600;
00284         break;
00285     case 43:
00286         seconds +=  (10*3600+30*60);
00287         break;
00288     case 44:
00289         seconds +=  11*3600;
00290         break;
00291     case 45:
00292         seconds +=  (11*3600+30*60);
00293         break;
00294     case 46:
00295         seconds +=  12*3600;
00296         break;
00297     case 47:
00298         seconds +=  (12*3600+45*60);
00299         break;
00300     case 48:
00301         seconds +=  13*3600;
00302         break;
00303     case 49:
00304         seconds +=  14*3600;
00305         break;
00306 
00307     }
00308 
00309     //calculation for date
00310     calcdatetime(seconds);
00311 }
00312 
00313 void SNTPClient::calcdatetime(tstamp seconds)
00314 {
00315     uint8_t yf=0;
00316     tstamp n=0,d=0,total_d=0,rz=0;
00317     uint16_t y=0,r=0,yr=0;
00318     signed long long yd=0;
00319 
00320     n = seconds;
00321     total_d = seconds/(SECS_PERDAY);
00322     d=0;
00323     uint32_t p_year_total_sec=SECS_PERDAY*365;
00324     uint32_t r_year_total_sec=SECS_PERDAY*366;
00325     while(n>=p_year_total_sec)
00326     {
00327         if((EPOCH+r)%400==0 || ((EPOCH+r)%100!=0 && (EPOCH+r)%4==0))
00328         {
00329             n = n -(r_year_total_sec);
00330             d = d + 366;
00331         }
00332         else
00333         {
00334             n = n - (p_year_total_sec);
00335             d = d + 365;
00336         }
00337         r+=1;
00338         y+=1;
00339 
00340     }
00341 
00342     y += EPOCH;
00343 
00344     Nowdatetime.yy = y;
00345 
00346     yd=0;
00347     yd = total_d - d;
00348 
00349     yf=1;
00350     while(yd>=28)
00351     {
00352 
00353         if(yf==1 || yf==3 || yf==5 || yf==7 || yf==8 || yf==10 || yf==12)
00354         {
00355             yd -= 31;
00356             if(yd<0)break;
00357             rz += 31;
00358         }
00359 
00360         if (yf==2)
00361         {
00362             if (y%400==0 || (y%100!=0 && y%4==0))
00363             {
00364                 yd -= 29;
00365                 if(yd<0)break;
00366                 rz += 29;
00367             }
00368             else
00369             {
00370                 yd -= 28;
00371                 if(yd<0)break;
00372                 rz += 28;
00373             }
00374         }
00375         if(yf==4 || yf==6 || yf==9 || yf==11 )
00376         {
00377             yd -= 30;
00378             if(yd<0)break;
00379             rz += 30;
00380         }
00381         yf += 1;
00382 
00383     }
00384     Nowdatetime.mo=yf;
00385     yr = total_d-d-rz;
00386 
00387     yr += 1;
00388 
00389     Nowdatetime.dd=yr;
00390 
00391     //calculation for time
00392     seconds = seconds%SECS_PERDAY;
00393     Nowdatetime.hh = seconds/3600;
00394     Nowdatetime.mm = (seconds%3600)/60;
00395     Nowdatetime.ss = (seconds%3600)%60;
00396 
00397 }
00398 
00399 tstamp SNTPClient::changedatetime_to_seconds(void)
00400 {
00401     tstamp seconds=0;
00402     uint32_t total_day=0;
00403     uint16_t i=0,run_year_cnt=0,l=0;
00404 
00405     l = Nowdatetime.yy;//low
00406 
00407 
00408     for(i=EPOCH;i<l;i++)
00409     {
00410         if((i%400==0) || ((i%100!=0) && (i%4==0)))
00411         {
00412             run_year_cnt += 1;
00413         }
00414     }
00415 
00416     total_day=(l-EPOCH-run_year_cnt)*365+run_year_cnt*366;
00417 
00418     for(i=1;i<=Nowdatetime.mo;i++)
00419     {
00420         if(i==5 || i==7 || i==10 || i==12)
00421         {
00422             total_day += 30;
00423         }
00424         if (i==3)
00425         {
00426             if (l%400==0 && l%100!=0 && l%4==0)
00427             {
00428                 total_day += 29;
00429             }
00430             else
00431             {
00432                 total_day += 28;
00433             }
00434         }
00435         if(i==2 || i==4 || i==6 || i==8 || i==9 || i==11)
00436         {
00437             total_day += 31;
00438         }
00439     }
00440 
00441     seconds = (total_day+Nowdatetime.dd-1)*24*3600;
00442     seconds += Nowdatetime.ss;//seconds
00443     seconds += Nowdatetime.mm*60;//minute
00444     seconds += Nowdatetime.hh*3600;//hour
00445 
00446     return seconds;
00447 }