Network Services
Fork of W5500Interface_K22F by
SNTPClient/SNTPClient.cpp
- Committer:
- dgriffin65
- Date:
- 2017-06-15
- Revision:
- 15:14382459c8b7
File content as of revision 15:14382459c8b7:
#include "SNTPClient.h" #include "DNSClient.h" #define MAX_TRY_WRITE 20 #define MAX_TRY_READ 10 //Debug is disabled by default #ifdef _SNTP_DEBUG_ #define DBG(x, ...) std::printf("[SNTPClient : DBG]"x"\r\n", ##__VA_ARGS__); #define WARN(x, ...) std::printf("[SNTPClient : WARN]"x"\r\n", ##__VA_ARGS__); #define ERR(x, ...) std::printf("[SNTPClient : ERR]"x"\r\n", ##__VA_ARGS__); #else #define DBG(x, ...) #define WARN(x, ...) #define ERR(x, ...) #endif #define INFO(x, ...) printf("[SNTPClient : INFO]"x"\r\n", ##__VA_ARGS__); SNTPClient::SNTPClient(NetworkStack *ns, const char* url, uint8_t time_zone) { DNSClient dns(ns); if (dns.lookup(url)) { const char* dns_addr = dns.get_ip_address(); memcpy(host, dns_addr, strlen(dns_addr)); host[strlen(dns_addr)] = '\0'; } else { memcpy(host, url, strlen(url)); host[strlen(url)] = '\0'; } port = ntp_port; m_ns = ns; m_udp = NULL; tz = time_zone; } bool SNTPClient::connect() { if (m_udp == NULL) { m_udp = new UDPSocket; m_udp->open(m_ns); } m_udp->set_blocking(false); m_udp->set_timeout(3000); m_udp->bind(rand()&0x7fff); sntp_server.set_ip_address(host); sntp_server.set_port(port); nsapi_addr_t na = sntp_server.get_addr(); NTPformat.dstaddr[0] = na.bytes[0]; NTPformat.dstaddr[1] = na.bytes[1]; NTPformat.dstaddr[2] = na.bytes[2]; NTPformat.dstaddr[3] = na.bytes[3]; DBG("NTP Server: %s\r\n", sntp_server.get_ip_address()); uint8_t Flag; NTPformat.leap = 0; /* leap indicator */ NTPformat.version = 4; /* version number */ NTPformat.mode = 3; /* mode */ NTPformat.stratum = 0; /* stratum */ NTPformat.poll = 0; /* poll interval */ NTPformat.precision = 0; /* precision */ NTPformat.rootdelay = 0; /* root delay */ NTPformat.rootdisp = 0; /* root dispersion */ NTPformat.refid = 0; /* reference ID */ NTPformat.reftime = 0; /* reference time */ NTPformat.org = 0; /* origin timestamp */ NTPformat.rec = 0; /* receive timestamp */ NTPformat.xmt = 1; /* transmit timestamp */ Flag = (NTPformat.leap<<6)+(NTPformat.version<<3)+NTPformat.mode; //one byte Flag memcpy(ntpmessage,(void const*)(&Flag),1); return true; } bool SNTPClient::getTime(datetime *time) { if (!m_udp) return false; uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40 int n = m_udp->sendto(sntp_server, (char *)ntpmessage, sizeof(ntpmessage)); char in_buffer[MAX_SNTP_BUF_SIZE]; n = m_udp->recvfrom(&sntp_server, in_buffer, sizeof(in_buffer)); if(n <= 0) { return false; } get_seconds_from_ntp_server((uint8_t *)in_buffer,startindex); time->yy = Nowdatetime.yy; time->mo = Nowdatetime.mo; time->dd = Nowdatetime.dd; time->hh = Nowdatetime.hh; time->mm = Nowdatetime.mm; time->ss = Nowdatetime.ss; return true; } bool SNTPClient::close() { if (m_udp) { delete m_udp; m_udp = NULL; } return true; } char* SNTPClient::getHost() { return host; } /* 00)UTC-12:00 Baker Island, Howland Island (both uninhabited) 01) UTC-11:00 American Samoa, Samoa 02) UTC-10:00 (Summer)French Polynesia (most), United States (Aleutian Islands, Hawaii) 03) UTC-09:30 Marquesas Islands 04) UTC-09:00 Gambier Islands;(Summer)United States (most of Alaska) 05) UTC-08:00 (Summer)Canada (most of British Columbia), Mexico (Baja California) 06) UTC-08:00 United States (California, most of Nevada, most of Oregon, Washington (state)) 07) UTC-07:00 Mexico (Sonora), United States (Arizona); (Summer)Canada (Alberta) 08) UTC-07:00 Mexico (Chihuahua), United States (Colorado) 09) UTC-06:00 Costa Rica, El Salvador, Ecuador (Galapagos Islands), Guatemala, Honduras 10) UTC-06:00 Mexico (most), Nicaragua;(Summer)Canada (Manitoba, Saskatchewan), United States (Illinois, most of Texas) 11) UTC-05:00 Colombia, Cuba, Ecuador (continental), Haiti, Jamaica, Panama, Peru 12) UTC-05:00 (Summer)Canada (most of Ontario, most of Quebec) 13) UTC-05:00 United States (most of Florida, Georgia, Massachusetts, most of Michigan, New York, North Carolina, Ohio, Washington D.C.) 14) UTC-04:30 Venezuela 15) UTC-04:00 Bolivia, Brazil (Amazonas), Chile (continental), Dominican Republic, Canada (Nova Scotia), Paraguay, 16) UTC-04:00 Puerto Rico, Trinidad and Tobago 17) UTC-03:30 Canada (Newfoundland) 18) UTC-03:00 Argentina; (Summer) Brazil (Brasilia, Rio de Janeiro, Sao Paulo), most of Greenland, Uruguay 19) UTC-02:00 Brazil (Fernando de Noronha), South Georgia and the South Sandwich Islands 20) UTC-01:00 Portugal (Azores), Cape Verde 21) UTC±00:00 Cote d'Ivoire, Faroe Islands, Ghana, Iceland, Senegal; (Summer) Ireland, Portugal (continental and Madeira) 22) UTC±00:00 Spain (Canary Islands), Morocco, United Kingdom 23) UTC+01:00 Angola, Cameroon, Nigeria, Tunisia; (Summer)Albania, Algeria, Austria, Belgium, Bosnia and Herzegovina, 24) UTC+01:00 Spain (continental), Croatia, Czech Republic, Denmark, Germany, Hungary, Italy, Kinshasa, Kosovo, 25) UTC+01:00 Macedonia, France (metropolitan), the Netherlands, Norway, Poland, Serbia, Slovakia, Slovenia, Sweden, Switzerland 26) UTC+02:00 Libya, Egypt, Malawi, Mozambique, South Africa, Zambia, Zimbabwe, (Summer)Bulgaria, Cyprus, Estonia, 27) UTC+02:00 Finland, Greece, Israel, Jordan, Latvia, Lebanon, Lithuania, Moldova, Palestine, Romania, Syria, Turkey, Ukraine 28) UTC+03:00 Belarus, Djibouti, Eritrea, Ethiopia, Iraq, Kenya, Madagascar, Russia (Kaliningrad Oblast), Saudi Arabia, 29) UTC+03:00 South Sudan, Sudan, Somalia, South Sudan, Tanzania, Uganda, Yemen 30) UTC+03:30 (Summer)Iran 31) UTC+04:00 Armenia, Azerbaijan, Georgia, Mauritius, Oman, Russia (European), Seychelles, United Arab Emirates 32) UTC+04:30 Afghanistan 33) UTC+05:00 Kazakhstan (West), Maldives, Pakistan, Uzbekistan 34) UTC+05:30 India, Sri Lanka 35) UTC+05:45 Nepal 36) UTC+06:00 Kazakhstan (most), Bangladesh, Russia (Ural: Sverdlovsk Oblast, Chelyabinsk Oblast) 37) UTC+06:30 Cocos Islands, Myanmar 38) UTC+07:00 Jakarta, Russia (Novosibirsk Oblast), Thailand, Vietnam 39) UTC+08:00 China, Hong Kong, Russia (Krasnoyarsk Krai), Malaysia, Philippines, Singapore, Taiwan, most of Mongolia, Western Australia 40) UTC+09:00 Korea, East Timor, Russia (Irkutsk Oblast), Japan 41) UTC+09:30 Australia (Northern Territory);(Summer)Australia (South Australia)) 42) UTC+10:00 Russia (Zabaykalsky Krai); (Summer)Australia (New South Wales, Queensland, Tasmania, Victoria) 43) UTC+10:30 Lord Howe Island 44) UTC+11:00 New Caledonia, Russia (Primorsky Krai), Solomon Islands 45) UTC+11:30 Norfolk Island 46) UTC+12:00 Fiji, Russia (Kamchatka Krai);(Summer)New Zealand 47) UTC+12:45 (Summer)New Zealand 48) UTC+13:00 Tonga 49) UTC+14:00 Kiribati (Line Islands) */ void SNTPClient::get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx) { tstamp seconds = 0; uint8_t i=0; for (i = 0; i < 4; i++) { seconds = (seconds << 8) | buf[idx + i]; } switch (tz) // Time Zone { case 0: seconds -= 12*3600; break; case 1: seconds -= 11*3600; break; case 2: seconds -= 10*3600; break; case 3: seconds -= (9*3600+30*60); break; case 4: seconds -= 9*3600; break; case 5: case 6: seconds -= 8*3600; break; case 7: case 8: seconds -= 7*3600; break; case 9: case 10: seconds -= 6*3600; break; case 11: case 12: case 13: seconds -= 5*3600; break; case 14: seconds -= (4*3600+30*60); break; case 15: case 16: seconds -= 4*3600; break; case 17: seconds -= (3*3600+30*60); break; case 18: seconds -= 3*3600; break; case 19: seconds -= 2*3600; break; case 20: seconds -= 1*3600; break; case 21: //? case 22: break; case 23: case 24: case 25: seconds += 1*3600; break; case 26: case 27: seconds += 2*3600; break; case 28: case 29: seconds += 3*3600; break; case 30: seconds += (3*3600+30*60); break; case 31: seconds += 4*3600; break; case 32: seconds += (4*3600+30*60); break; case 33: seconds += 5*3600; break; case 34: seconds += (5*3600+30*60); break; case 35: seconds += (5*3600+45*60); break; case 36: seconds += 6*3600; break; case 37: seconds += (6*3600+30*60); break; case 38: seconds += 7*3600; break; case 39: seconds += 8*3600; break; case 40: seconds += 9*3600; break; case 41: seconds += (9*3600+30*60); break; case 42: seconds += 10*3600; break; case 43: seconds += (10*3600+30*60); break; case 44: seconds += 11*3600; break; case 45: seconds += (11*3600+30*60); break; case 46: seconds += 12*3600; break; case 47: seconds += (12*3600+45*60); break; case 48: seconds += 13*3600; break; case 49: seconds += 14*3600; break; } //calculation for date calcdatetime(seconds); } void SNTPClient::calcdatetime(tstamp seconds) { uint8_t yf=0; tstamp n=0,d=0,total_d=0,rz=0; uint16_t y=0,r=0,yr=0; signed long long yd=0; n = seconds; total_d = seconds/(SECS_PERDAY); d=0; uint32_t p_year_total_sec=SECS_PERDAY*365; uint32_t r_year_total_sec=SECS_PERDAY*366; while(n>=p_year_total_sec) { if((EPOCH+r)%400==0 || ((EPOCH+r)%100!=0 && (EPOCH+r)%4==0)) { n = n -(r_year_total_sec); d = d + 366; } else { n = n - (p_year_total_sec); d = d + 365; } r+=1; y+=1; } y += EPOCH; Nowdatetime.yy = y; yd=0; yd = total_d - d; yf=1; while(yd>=28) { if(yf==1 || yf==3 || yf==5 || yf==7 || yf==8 || yf==10 || yf==12) { yd -= 31; if(yd<0)break; rz += 31; } if (yf==2) { if (y%400==0 || (y%100!=0 && y%4==0)) { yd -= 29; if(yd<0)break; rz += 29; } else { yd -= 28; if(yd<0)break; rz += 28; } } if(yf==4 || yf==6 || yf==9 || yf==11 ) { yd -= 30; if(yd<0)break; rz += 30; } yf += 1; } Nowdatetime.mo=yf; yr = total_d-d-rz; yr += 1; Nowdatetime.dd=yr; //calculation for time seconds = seconds%SECS_PERDAY; Nowdatetime.hh = seconds/3600; Nowdatetime.mm = (seconds%3600)/60; Nowdatetime.ss = (seconds%3600)%60; } tstamp SNTPClient::changedatetime_to_seconds(void) { tstamp seconds=0; uint32_t total_day=0; uint16_t i=0,run_year_cnt=0,l=0; l = Nowdatetime.yy;//low for(i=EPOCH;i<l;i++) { if((i%400==0) || ((i%100!=0) && (i%4==0))) { run_year_cnt += 1; } } total_day=(l-EPOCH-run_year_cnt)*365+run_year_cnt*366; for(i=1;i<=Nowdatetime.mo;i++) { if(i==5 || i==7 || i==10 || i==12) { total_day += 30; } if (i==3) { if (l%400==0 && l%100!=0 && l%4==0) { total_day += 29; } else { total_day += 28; } } if(i==2 || i==4 || i==6 || i==8 || i==9 || i==11) { total_day += 31; } } seconds = (total_day+Nowdatetime.dd-1)*24*3600; seconds += Nowdatetime.ss;//seconds seconds += Nowdatetime.mm*60;//minute seconds += Nowdatetime.hh*3600;//hour return seconds; }