SNTPClinet
Dependents: SSD1306_smart_watch smart_watch smart_watch
Revision 0:dc5f405fd011, committed 2015-06-29
- Comitter:
- eunkyoungkim
- Date:
- Mon Jun 29 04:26:32 2015 +0000
- Commit message:
- Add SNTPClient
Changed in this revision
SNTPClient.cpp | Show annotated file Show diff for this revision Revisions of this file |
SNTPClient.h | Show annotated file Show diff for this revision Revisions of this file |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SNTPClient.cpp Mon Jun 29 04:26:32 2015 +0000 @@ -0,0 +1,428 @@ +#include "SNTPClient.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(char * url, uint8_t time_zone) { + memcpy(host, url, strlen(url)); + host[strlen(url)] = '\0'; + port = ntp_port; + socket.set_blocking(false, 3000); + + tz = time_zone; +} + +bool SNTPClient::connect() { + socket.init(); + socket.bind(0); + if(sntp_server.set_address(host, port) < 0) + return false; + + uint32_t ip = str_to_ip(sntp_server.get_address()); + NTPformat.dstaddr[0] = (uint8_t)(ip >> 24); + NTPformat.dstaddr[1] = (uint8_t)(ip >> 16); + NTPformat.dstaddr[2] = (uint8_t)(ip >> 8); + NTPformat.dstaddr[3] = (uint8_t)(ip >> 0); + DBG("NTP Server: %s\r\n", sntp_server.get_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) { + uint16_t startindex = 40; //last 8-byte of data_buf[size is 48 byte] is xmt, so the startindex should be 40 + + socket.sendTo(sntp_server, (char *)ntpmessage, sizeof(ntpmessage)); + + char in_buffer[MAX_SNTP_BUF_SIZE]; + int n = socket.receiveFrom(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() { + int ret = socket.close(); + if (ret < 0) { + ERR("Could not close"); + return false; + } + 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; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SNTPClient.h Mon Jun 29 04:26:32 2015 +0000 @@ -0,0 +1,180 @@ +/** +* @author Raphael Kwon +* +* @section LICENSE +* +* Copyright (c) 2014 WIZnet Co., Ltd. +* +* Permission is hereby granted, free of charge, to any person obtaining a copy +* of this software and associated documentation files (the "Software"), to deal +* in the Software without restriction, including without limitation the rights +* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +* copies of the Software, and to permit persons to whom the Software is +* furnished to do so, subject to the following conditions: +* +* The above copyright notice and this permission notice shall be included in +* all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +* THE SOFTWARE. +* +* @section DESCRIPTION +* Simple Network Time Protocol Client +* +*/ + +#ifndef SNTPCLIENT_H +#define SNTPCLIENT_H + +#include "mbed.h" +#include "UDPSocket.h" + +/* + * @brief Define it for Debug & Monitor DNS processing. + * @note + */ +//#define _SNTP_DEBUG_ + +#define MAX_SNTP_BUF_SIZE sizeof(ntpformat) ///< maximum size of DNS buffer. */ +#define ntp_port 123 //ntp server port number +#define SECS_PERDAY 86400UL // seconds in a day = 60*60*24 +#define UTC_ADJ_HRS 9 // SEOUL : GMT+9 +#define EPOCH 1900 // NTP start year + +/* for ntpclient */ +typedef signed char s_char; +typedef unsigned long long tstamp; +typedef unsigned int tdist; + +typedef struct _ntpformat +{ + uint8_t dstaddr[4]; /* destination (local) address */ + char version; /* version number */ + char leap; /* leap indicator */ + char mode; /* mode */ + char stratum; /* stratum */ + char poll; /* poll interval */ + s_char precision; /* precision */ + tdist rootdelay; /* root delay */ + tdist rootdisp; /* root dispersion */ + char refid; /* reference ID */ + tstamp reftime; /* reference time */ + tstamp org; /* origin timestamp */ + tstamp rec; /* receive timestamp */ + tstamp xmt; /* transmit timestamp */ +} ntpformat; +typedef struct _datetime +{ + int yy; + int mo; + int dd; + int hh; + int mm; + int ss; +} datetime; +/* +typedef struct _datetime +{ + uint16_t yy; + uint8_t mo; + uint8_t dd; + uint8_t hh; + uint8_t mm; + uint8_t ss; +} datetime; +*/ +/** SNTPClient client Class. + * + * Example (ethernet network): + * @code + * #include "mbed.h" + * #include "EthernetInterface.h" + * #include "SNTPClient.h" + * + * int main() { + * EthernetInterface eth; + * eth.init(); //Use DHCP + * eth.connect(); + * printf("IP Address is %s\n\r", eth.getIPAddress()); + * + * SNTPClient ws("ws://sockets.mbed.org:443/ws/demo/rw"); + * ws.connect(); + * + * while (1) { + * int res = ws.send("SNTPClient Hello World!"); + * + * if (ws.read(recv)) { + * printf("rcv: %s\r\n", recv); + * } + * + * wait(0.1); + * } + * } + * @endcode + */ + + +class SNTPClient +{ + public: + /** + * Constructor + * + * @param url The SNTPClient host + */ + SNTPClient(char * url, uint8_t time_zone); + + /** + * Connect to the SNTPClient url + * + *@return true if the connection is established, false otherwise + */ + bool connect(); + + /** + * Read a SNTPClient message + * + * @param message pointer to the string to be read (null if drop frame) + * + * @return true if a SNTPClient frame has been read + */ + bool getTime(datetime *time); + + /** + * Close the SNTPClient connection + * + * @return true if the connection has been closed, false otherwise + */ + bool close(); + + /* + * Accessor: get host from the SNTPClient url + * + * @return host + */ + char* getHost(); + + private: + + uint16_t port; + char host[32]; + + UDPSocket socket; + Endpoint sntp_server; + + ntpformat NTPformat; + datetime Nowdatetime; + uint8_t ntpmessage[48]; + uint8_t tz; // Time Zone + + void get_seconds_from_ntp_server(uint8_t *buf, uint16_t idx); + tstamp changedatetime_to_seconds(void); + void calcdatetime(tstamp seconds); +}; + +#endif