this will take a image from C328 serial camera and store those images in mbed flash as html and this html page is uploaded into the server at ip:192.168.1.2
lwip/SNTPClient/SNTPClient.cpp@0:e1a0471e5ffb, 2010-12-15 (annotated)
- Committer:
- mitesh2patel
- Date:
- Wed Dec 15 15:01:56 2010 +0000
- Revision:
- 0:e1a0471e5ffb
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mitesh2patel | 0:e1a0471e5ffb | 1 | /* |
mitesh2patel | 0:e1a0471e5ffb | 2 | * SNTPClient.cpp |
mitesh2patel | 0:e1a0471e5ffb | 3 | * SNTP (Simple NTP) client |
mitesh2patel | 0:e1a0471e5ffb | 4 | * Written by iva2k |
mitesh2patel | 0:e1a0471e5ffb | 5 | * |
mitesh2patel | 0:e1a0471e5ffb | 6 | * Wrapper around LWIP/sntp for MBED, with DST rules. |
mitesh2patel | 0:e1a0471e5ffb | 7 | * This implementation relies on: |
mitesh2patel | 0:e1a0471e5ffb | 8 | * 1. LWIP (http://www.sics.se/~adam/lwip/) adopted for MBED |
mitesh2patel | 0:e1a0471e5ffb | 9 | * http://mbed.org/projects/cookbook/svn/EMAC/lwip/trunk |
mitesh2patel | 0:e1a0471e5ffb | 10 | * 2. LWIP's contributed SNTP client (sntp.c and sntp.h) from |
mitesh2patel | 0:e1a0471e5ffb | 11 | * http://cvs.savannah.gnu.org/viewvc/contrib/apps/sntp/?root=lwip |
mitesh2patel | 0:e1a0471e5ffb | 12 | * (used version 1.8) |
mitesh2patel | 0:e1a0471e5ffb | 13 | * |
mitesh2patel | 0:e1a0471e5ffb | 14 | * Changes needed in LWIP/sntp: |
mitesh2patel | 0:e1a0471e5ffb | 15 | * - pointer typecast (line 594) - fixes mbed compiler problem |
mitesh2patel | 0:e1a0471e5ffb | 16 | * - #include "sntp.h" moved after lwip/opt.h et.al - for re-defines. |
mitesh2patel | 0:e1a0471e5ffb | 17 | * - pbuf_free(p) in sntp_send_request() (line 602) - fixes memory leak BUG. |
mitesh2patel | 0:e1a0471e5ffb | 18 | * - changing sntp_dns_found() to delayed sntp_try_next_server() - to unblock if network is disconnected. |
mitesh2patel | 0:e1a0471e5ffb | 19 | * |
mitesh2patel | 0:e1a0471e5ffb | 20 | * Changes in MBED's LWIP: |
mitesh2patel | 0:e1a0471e5ffb | 21 | * - modified lwipopts.h (this file is automatically included into sntp.c) |
mitesh2patel | 0:e1a0471e5ffb | 22 | * |
mitesh2patel | 0:e1a0471e5ffb | 23 | * Requirements: |
mitesh2patel | 0:e1a0471e5ffb | 24 | * + direct RTC update from receiving the NTP time packet |
mitesh2patel | 0:e1a0471e5ffb | 25 | * + optionally support more than one NTP server |
mitesh2patel | 0:e1a0471e5ffb | 26 | * + the IP address of the NTP server(s) stored in a local file |
mitesh2patel | 0:e1a0471e5ffb | 27 | * + timeout error recovery should the NTP server(s) not be available. No RTC update should the NTP access fail |
mitesh2patel | 0:e1a0471e5ffb | 28 | * + allow for a UTC offset, also stored in the local file |
mitesh2patel | 0:e1a0471e5ffb | 29 | * + DST correction |
mitesh2patel | 0:e1a0471e5ffb | 30 | * + use DNS for NTP servers IP address resolution |
mitesh2patel | 0:e1a0471e5ffb | 31 | * + periodic updates at specified time intervals |
mitesh2patel | 0:e1a0471e5ffb | 32 | * |
mitesh2patel | 0:e1a0471e5ffb | 33 | * TODO: |
mitesh2patel | 0:e1a0471e5ffb | 34 | * . DST correction |
mitesh2patel | 0:e1a0471e5ffb | 35 | * - record metrics (count of updates, failed tries?, correction more than epsilon, etc.?) |
mitesh2patel | 0:e1a0471e5ffb | 36 | */ |
mitesh2patel | 0:e1a0471e5ffb | 37 | |
mitesh2patel | 0:e1a0471e5ffb | 38 | #include "mbed.h" |
mitesh2patel | 0:e1a0471e5ffb | 39 | #include "lwip/opt.h" |
mitesh2patel | 0:e1a0471e5ffb | 40 | #include "SNTPClient.h" |
mitesh2patel | 0:e1a0471e5ffb | 41 | |
mitesh2patel | 0:e1a0471e5ffb | 42 | #define SNTP_EPSILON 10 // time difference noticed as big update (in seconds). |
mitesh2patel | 0:e1a0471e5ffb | 43 | |
mitesh2patel | 0:e1a0471e5ffb | 44 | //#define SNTP_DST_TESTS // Define this to run DST algorithms tests |
mitesh2patel | 0:e1a0471e5ffb | 45 | |
mitesh2patel | 0:e1a0471e5ffb | 46 | typedef struct DST_ZONE_DESCR { |
mitesh2patel | 0:e1a0471e5ffb | 47 | tDST_ZONE zone; |
mitesh2patel | 0:e1a0471e5ffb | 48 | const char *name; |
mitesh2patel | 0:e1a0471e5ffb | 49 | int gmt; |
mitesh2patel | 0:e1a0471e5ffb | 50 | int dst; |
mitesh2patel | 0:e1a0471e5ffb | 51 | int hr1; |
mitesh2patel | 0:e1a0471e5ffb | 52 | int wk1; |
mitesh2patel | 0:e1a0471e5ffb | 53 | int wday1; |
mitesh2patel | 0:e1a0471e5ffb | 54 | int mon1; |
mitesh2patel | 0:e1a0471e5ffb | 55 | int hr2; |
mitesh2patel | 0:e1a0471e5ffb | 56 | int wk2; |
mitesh2patel | 0:e1a0471e5ffb | 57 | int wday2; |
mitesh2patel | 0:e1a0471e5ffb | 58 | int mon2; |
mitesh2patel | 0:e1a0471e5ffb | 59 | pFncDstCalc fnc; |
mitesh2patel | 0:e1a0471e5ffb | 60 | } tDST_ZONE_DESR; |
mitesh2patel | 0:e1a0471e5ffb | 61 | |
mitesh2patel | 0:e1a0471e5ffb | 62 | static tDST_ZONE_DESR gSntpDstZones[] = { |
mitesh2patel | 0:e1a0471e5ffb | 63 | #define _(z, fnc, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2) \ |
mitesh2patel | 0:e1a0471e5ffb | 64 | { z, #z, gmt, dst, hr1,wk1,wday1,mon1, hr2,wk2,wday2,mon2, fnc }, |
mitesh2patel | 0:e1a0471e5ffb | 65 | #include "DstZones.h" |
mitesh2patel | 0:e1a0471e5ffb | 66 | }; |
mitesh2patel | 0:e1a0471e5ffb | 67 | #define DST_ZONE_DESCR_CNT (sizeof(gSntpDstZones)/sizeof(gSntpDstZones[0])) |
mitesh2patel | 0:e1a0471e5ffb | 68 | |
mitesh2patel | 0:e1a0471e5ffb | 69 | const char *SNTPDstZoneName(tDST_ZONE zone) { |
mitesh2patel | 0:e1a0471e5ffb | 70 | if (zone >= DST_ZONE_DESCR_CNT) |
mitesh2patel | 0:e1a0471e5ffb | 71 | return ""; |
mitesh2patel | 0:e1a0471e5ffb | 72 | return gSntpDstZones[zone].name; |
mitesh2patel | 0:e1a0471e5ffb | 73 | } |
mitesh2patel | 0:e1a0471e5ffb | 74 | |
mitesh2patel | 0:e1a0471e5ffb | 75 | #ifdef __cplusplus |
mitesh2patel | 0:e1a0471e5ffb | 76 | extern "C" { |
mitesh2patel | 0:e1a0471e5ffb | 77 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 78 | tDST_ZONE gSntpDstZone = DST_NONE; // DST zone - rule selector |
mitesh2patel | 0:e1a0471e5ffb | 79 | unsigned int gSntpRecvTimeout_s = 3; // 3 sec; SNTP_RECV_TIMEOUT |
mitesh2patel | 0:e1a0471e5ffb | 80 | unsigned int gSntpUpdateDelay_s = 3600; // 1 hour; SNTP_UPDATE_DELAY |
mitesh2patel | 0:e1a0471e5ffb | 81 | signed int gSntpTimezone = 0*3600; // seconds from UTC to local time |
mitesh2patel | 0:e1a0471e5ffb | 82 | signed int gSntpDST = 0*3600; // seconds from UTC to local time |
mitesh2patel | 0:e1a0471e5ffb | 83 | bool gSntpRtcUtc = false; // true to keep RTC in UTC, false to keep in local time |
mitesh2patel | 0:e1a0471e5ffb | 84 | unsigned int gSntpUpdates = 0; // Track number of all clock NTP updates |
mitesh2patel | 0:e1a0471e5ffb | 85 | unsigned int gSntpUpdatesBig = 0; // Track number of significant clock NTP updates |
mitesh2patel | 0:e1a0471e5ffb | 86 | bool gSntpRunning = false; // true if SNTP service is running |
mitesh2patel | 0:e1a0471e5ffb | 87 | Timeout gSntpDelay; // For async calls. |
mitesh2patel | 0:e1a0471e5ffb | 88 | Ticker gSntpTicker; // There is no RTC interrupt on MBED (yet). Use (more wastefull) timer. |
mitesh2patel | 0:e1a0471e5ffb | 89 | time_t gSntpRtcTCR = 0; // Timer Capture Register equivalent (in RTC time - either local or UTC depending on gSntpRtcUtc) |
mitesh2patel | 0:e1a0471e5ffb | 90 | signed int gSntpRtcTCRDST = 0; // New DST value for when RTC crosses gSntpRtcTCR |
mitesh2patel | 0:e1a0471e5ffb | 91 | |
mitesh2patel | 0:e1a0471e5ffb | 92 | static void SNTPSetDSTEx(unsigned int dst, bool adjust_clock) { |
mitesh2patel | 0:e1a0471e5ffb | 93 | if (adjust_clock && !gSntpRtcUtc && gSntpDST != dst) { |
mitesh2patel | 0:e1a0471e5ffb | 94 | time_t seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 95 | seconds -= gSntpDST; // Convert from old local time |
mitesh2patel | 0:e1a0471e5ffb | 96 | seconds += dst; // Convert to new local time |
mitesh2patel | 0:e1a0471e5ffb | 97 | set_time(seconds); |
mitesh2patel | 0:e1a0471e5ffb | 98 | if (gSntpRtcTCR) { |
mitesh2patel | 0:e1a0471e5ffb | 99 | // Adjust our alarm clock |
mitesh2patel | 0:e1a0471e5ffb | 100 | gSntpRtcTCR -= gSntpDST; |
mitesh2patel | 0:e1a0471e5ffb | 101 | gSntpRtcTCR += dst; |
mitesh2patel | 0:e1a0471e5ffb | 102 | } |
mitesh2patel | 0:e1a0471e5ffb | 103 | } |
mitesh2patel | 0:e1a0471e5ffb | 104 | gSntpDST = dst; |
mitesh2patel | 0:e1a0471e5ffb | 105 | } |
mitesh2patel | 0:e1a0471e5ffb | 106 | |
mitesh2patel | 0:e1a0471e5ffb | 107 | #if 0 |
mitesh2patel | 0:e1a0471e5ffb | 108 | // Custom DST zone function example |
mitesh2patel | 0:e1a0471e5ffb | 109 | // USA (since 2007) |
mitesh2patel | 0:e1a0471e5ffb | 110 | // Calculate start or stop DST point for given year based on rules |
mitesh2patel | 0:e1a0471e5ffb | 111 | // tz - Timezone |
mitesh2patel | 0:e1a0471e5ffb | 112 | // year - current year. DST changes well away from year end, so does not matter what timezone. |
mitesh2patel | 0:e1a0471e5ffb | 113 | // start - DST_START for start, DST_STOP for stop |
mitesh2patel | 0:e1a0471e5ffb | 114 | // Returns DST point (in local time). DST_STOP time is in DST |
mitesh2patel | 0:e1a0471e5ffb | 115 | static tDstPoint _sntp_dst_calc_custom(int tz, int year, tDST_START start) { |
mitesh2patel | 0:e1a0471e5ffb | 116 | tDstPoint ret; |
mitesh2patel | 0:e1a0471e5ffb | 117 | struct tm t; |
mitesh2patel | 0:e1a0471e5ffb | 118 | |
mitesh2patel | 0:e1a0471e5ffb | 119 | // USA: 3600; 2, Second SUN, March; 2, First SUN, November |
mitesh2patel | 0:e1a0471e5ffb | 120 | int dst = 3600; // DST shift (seconds) |
mitesh2patel | 0:e1a0471e5ffb | 121 | int hour; // Hour of the change |
mitesh2patel | 0:e1a0471e5ffb | 122 | int N; // Week in the month |
mitesh2patel | 0:e1a0471e5ffb | 123 | int wday; // Day of the week |
mitesh2patel | 0:e1a0471e5ffb | 124 | int month; |
mitesh2patel | 0:e1a0471e5ffb | 125 | if (start == DST_START) { |
mitesh2patel | 0:e1a0471e5ffb | 126 | hour = 2; // (0-23) Hour of the change |
mitesh2patel | 0:e1a0471e5ffb | 127 | N = 2-1; // 2nd in the month |
mitesh2patel | 0:e1a0471e5ffb | 128 | wday = 0; // Sunday |
mitesh2patel | 0:e1a0471e5ffb | 129 | month = 2; // March |
mitesh2patel | 0:e1a0471e5ffb | 130 | } else { // DST_STOP |
mitesh2patel | 0:e1a0471e5ffb | 131 | hour = 2; // (0-23) Hour of the change |
mitesh2patel | 0:e1a0471e5ffb | 132 | N = 1-1; // 1st in the month |
mitesh2patel | 0:e1a0471e5ffb | 133 | wday = 0; // Sunday |
mitesh2patel | 0:e1a0471e5ffb | 134 | month = 10; // November |
mitesh2patel | 0:e1a0471e5ffb | 135 | } |
mitesh2patel | 0:e1a0471e5ffb | 136 | |
mitesh2patel | 0:e1a0471e5ffb | 137 | t.tm_sec = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 138 | t.tm_min = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 139 | t.tm_hour = hour; // 0-23 |
mitesh2patel | 0:e1a0471e5ffb | 140 | t.tm_year = year - 1900; // |
mitesh2patel | 0:e1a0471e5ffb | 141 | t.tm_mon = month; // 0-11 |
mitesh2patel | 0:e1a0471e5ffb | 142 | t.tm_mday = 1+N*7; // 1-31, first possible date for Nth given weekday |
mitesh2patel | 0:e1a0471e5ffb | 143 | mktime(&t); // Calculate tm_wday |
mitesh2patel | 0:e1a0471e5ffb | 144 | t.tm_mday += (wday-t.tm_wday+14)%7; // Shift to wday |
mitesh2patel | 0:e1a0471e5ffb | 145 | ret.t = mktime(&t); |
mitesh2patel | 0:e1a0471e5ffb | 146 | ret.dst = (start == DST_START) ? dst : 0; |
mitesh2patel | 0:e1a0471e5ffb | 147 | ret.dstshift = dst; |
mitesh2patel | 0:e1a0471e5ffb | 148 | return ret; |
mitesh2patel | 0:e1a0471e5ffb | 149 | } |
mitesh2patel | 0:e1a0471e5ffb | 150 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 151 | |
mitesh2patel | 0:e1a0471e5ffb | 152 | // Calculate start or stop DST point for given year based on rules for the DST zone |
mitesh2patel | 0:e1a0471e5ffb | 153 | // tz - Timezone |
mitesh2patel | 0:e1a0471e5ffb | 154 | // zone - DST zone |
mitesh2patel | 0:e1a0471e5ffb | 155 | // year - current year. DST changes well away from year end, so does not matter timezone. |
mitesh2patel | 0:e1a0471e5ffb | 156 | // start - DST_START for start, DST_STOP for stop |
mitesh2patel | 0:e1a0471e5ffb | 157 | // Returns DST point (in standard local time). DST_STOP time is in NOT IN DST |
mitesh2patel | 0:e1a0471e5ffb | 158 | static tDstPoint _sntp_dst_calc(int tz, tDST_ZONE zone, int year, tDST_START start) { |
mitesh2patel | 0:e1a0471e5ffb | 159 | tDstPoint ret; |
mitesh2patel | 0:e1a0471e5ffb | 160 | |
mitesh2patel | 0:e1a0471e5ffb | 161 | ret.t = 0; |
mitesh2patel | 0:e1a0471e5ffb | 162 | ret.dst = 0; |
mitesh2patel | 0:e1a0471e5ffb | 163 | ret.dstshift = 0; |
mitesh2patel | 0:e1a0471e5ffb | 164 | if (zone == DST_NONE || zone >= DST_ZONE_DESCR_CNT) |
mitesh2patel | 0:e1a0471e5ffb | 165 | return ret; |
mitesh2patel | 0:e1a0471e5ffb | 166 | |
mitesh2patel | 0:e1a0471e5ffb | 167 | tDST_ZONE_DESR *descr = &gSntpDstZones[zone]; |
mitesh2patel | 0:e1a0471e5ffb | 168 | if (descr->fnc) { |
mitesh2patel | 0:e1a0471e5ffb | 169 | // Use custom function |
mitesh2patel | 0:e1a0471e5ffb | 170 | ret = descr->fnc(tz, year, start); |
mitesh2patel | 0:e1a0471e5ffb | 171 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 172 | // Use rules |
mitesh2patel | 0:e1a0471e5ffb | 173 | struct tm t; |
mitesh2patel | 0:e1a0471e5ffb | 174 | t.tm_sec = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 175 | t.tm_min = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 176 | t.tm_hour = (start == DST_START) ? descr->hr1 : descr->hr2; |
mitesh2patel | 0:e1a0471e5ffb | 177 | t.tm_year = year - 1900; // |
mitesh2patel | 0:e1a0471e5ffb | 178 | t.tm_mon = (start == DST_START) ? descr->mon1 : descr->mon2; // 0-11 |
mitesh2patel | 0:e1a0471e5ffb | 179 | int wk =((start == DST_START) ? descr->wk1 : descr->wk2) -1; |
mitesh2patel | 0:e1a0471e5ffb | 180 | int wday = (start == DST_START) ? descr->wday1: descr->wday2; |
mitesh2patel | 0:e1a0471e5ffb | 181 | if (wk < 0) { |
mitesh2patel | 0:e1a0471e5ffb | 182 | // For "Last in the month" - we go to next month, then move back by one week |
mitesh2patel | 0:e1a0471e5ffb | 183 | t.tm_mon += 1; // 0-11 |
mitesh2patel | 0:e1a0471e5ffb | 184 | if (t.tm_mon > 11) { |
mitesh2patel | 0:e1a0471e5ffb | 185 | t.tm_mon -= 12; |
mitesh2patel | 0:e1a0471e5ffb | 186 | t.tm_year += 1; |
mitesh2patel | 0:e1a0471e5ffb | 187 | } |
mitesh2patel | 0:e1a0471e5ffb | 188 | t.tm_mday = 1+0*7; // 1-31, first possible date for Nth given weekday |
mitesh2patel | 0:e1a0471e5ffb | 189 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 190 | t.tm_mday = 1+wk*7; // 1-31, first possible date for Nth given weekday |
mitesh2patel | 0:e1a0471e5ffb | 191 | } |
mitesh2patel | 0:e1a0471e5ffb | 192 | mktime(&t); // Calculate tm_wday |
mitesh2patel | 0:e1a0471e5ffb | 193 | t.tm_mday += (wday-t.tm_wday+14)%7; // Shift to wday |
mitesh2patel | 0:e1a0471e5ffb | 194 | ret.t = mktime(&t); |
mitesh2patel | 0:e1a0471e5ffb | 195 | if (wk < 0) { |
mitesh2patel | 0:e1a0471e5ffb | 196 | ret.t -= 7 * 24 * 3600; |
mitesh2patel | 0:e1a0471e5ffb | 197 | } |
mitesh2patel | 0:e1a0471e5ffb | 198 | if (descr->gmt) { |
mitesh2patel | 0:e1a0471e5ffb | 199 | ret.t += tz; |
mitesh2patel | 0:e1a0471e5ffb | 200 | } |
mitesh2patel | 0:e1a0471e5ffb | 201 | ret.dst = (start == DST_START) ? descr->dst : 0; |
mitesh2patel | 0:e1a0471e5ffb | 202 | ret.dstshift = descr->dst; |
mitesh2patel | 0:e1a0471e5ffb | 203 | } |
mitesh2patel | 0:e1a0471e5ffb | 204 | if (start == DST_STOP) { |
mitesh2patel | 0:e1a0471e5ffb | 205 | ret.t -= ret.dstshift; |
mitesh2patel | 0:e1a0471e5ffb | 206 | // this correction is due to the fact that rules are given in local time with DST, |
mitesh2patel | 0:e1a0471e5ffb | 207 | // but calculations are made in standard local time (without DST adjustment) |
mitesh2patel | 0:e1a0471e5ffb | 208 | } |
mitesh2patel | 0:e1a0471e5ffb | 209 | return ret; |
mitesh2patel | 0:e1a0471e5ffb | 210 | } |
mitesh2patel | 0:e1a0471e5ffb | 211 | |
mitesh2patel | 0:e1a0471e5ffb | 212 | // Calculate desired DST point relative to now based on rules for the DST zone |
mitesh2patel | 0:e1a0471e5ffb | 213 | // tz - timezone |
mitesh2patel | 0:e1a0471e5ffb | 214 | // zone - DST zone |
mitesh2patel | 0:e1a0471e5ffb | 215 | // now - current time (standard local time = excluding DST). |
mitesh2patel | 0:e1a0471e5ffb | 216 | // index - 0 for immediate next, +1 for second next, -1 for immediate previous |
mitesh2patel | 0:e1a0471e5ffb | 217 | // Returns DST point (in standard local time) |
mitesh2patel | 0:e1a0471e5ffb | 218 | static tDstPoint _sntp_dst_point(int tz, tDST_ZONE zone, time_t now, int index) { |
mitesh2patel | 0:e1a0471e5ffb | 219 | tDstPoint ret; |
mitesh2patel | 0:e1a0471e5ffb | 220 | int year; |
mitesh2patel | 0:e1a0471e5ffb | 221 | tDST_START type; |
mitesh2patel | 0:e1a0471e5ffb | 222 | struct tm *pt = localtime(&now); |
mitesh2patel | 0:e1a0471e5ffb | 223 | |
mitesh2patel | 0:e1a0471e5ffb | 224 | ret.t = 0; |
mitesh2patel | 0:e1a0471e5ffb | 225 | ret.dst = 0; |
mitesh2patel | 0:e1a0471e5ffb | 226 | ret.dstshift = 0; |
mitesh2patel | 0:e1a0471e5ffb | 227 | if (zone == DST_NONE || zone >= DST_ZONE_DESCR_CNT) |
mitesh2patel | 0:e1a0471e5ffb | 228 | return ret; |
mitesh2patel | 0:e1a0471e5ffb | 229 | |
mitesh2patel | 0:e1a0471e5ffb | 230 | // Algorithm |
mitesh2patel | 0:e1a0471e5ffb | 231 | // 1. Determine where now is in respect to current year DST points (find for index=0) |
mitesh2patel | 0:e1a0471e5ffb | 232 | // 2. Use index to shift year and type |
mitesh2patel | 0:e1a0471e5ffb | 233 | // 3. return the point |
mitesh2patel | 0:e1a0471e5ffb | 234 | // This algorithm relies on DST start date being before DST stop date in the year. |
mitesh2patel | 0:e1a0471e5ffb | 235 | |
mitesh2patel | 0:e1a0471e5ffb | 236 | year = pt->tm_year + 1900; |
mitesh2patel | 0:e1a0471e5ffb | 237 | type = DST_START; |
mitesh2patel | 0:e1a0471e5ffb | 238 | ret = _sntp_dst_calc(tz, zone, year, type); |
mitesh2patel | 0:e1a0471e5ffb | 239 | if (now > ret.t) { |
mitesh2patel | 0:e1a0471e5ffb | 240 | type = DST_STOP; |
mitesh2patel | 0:e1a0471e5ffb | 241 | ret = _sntp_dst_calc(tz, zone, year, type); |
mitesh2patel | 0:e1a0471e5ffb | 242 | if (now > ret.t) { |
mitesh2patel | 0:e1a0471e5ffb | 243 | // It is next year's start point |
mitesh2patel | 0:e1a0471e5ffb | 244 | type = DST_START; |
mitesh2patel | 0:e1a0471e5ffb | 245 | year += 1; |
mitesh2patel | 0:e1a0471e5ffb | 246 | } |
mitesh2patel | 0:e1a0471e5ffb | 247 | } |
mitesh2patel | 0:e1a0471e5ffb | 248 | // Now year and type are right for index=0 |
mitesh2patel | 0:e1a0471e5ffb | 249 | |
mitesh2patel | 0:e1a0471e5ffb | 250 | // Calculate where index points to - shift year and type |
mitesh2patel | 0:e1a0471e5ffb | 251 | int norm = (index > 0) ? (int)(index/2) : (int)((index-1)/2); |
mitesh2patel | 0:e1a0471e5ffb | 252 | year += norm; |
mitesh2patel | 0:e1a0471e5ffb | 253 | index -= norm*2; // Now index is (0,1) |
mitesh2patel | 0:e1a0471e5ffb | 254 | if (index) { |
mitesh2patel | 0:e1a0471e5ffb | 255 | // Flip the type |
mitesh2patel | 0:e1a0471e5ffb | 256 | type = (type == DST_START) ? DST_STOP : DST_START; |
mitesh2patel | 0:e1a0471e5ffb | 257 | } |
mitesh2patel | 0:e1a0471e5ffb | 258 | |
mitesh2patel | 0:e1a0471e5ffb | 259 | ret = _sntp_dst_calc(tz, zone, year, type); |
mitesh2patel | 0:e1a0471e5ffb | 260 | return ret; |
mitesh2patel | 0:e1a0471e5ffb | 261 | |
mitesh2patel | 0:e1a0471e5ffb | 262 | // struct tm t; |
mitesh2patel | 0:e1a0471e5ffb | 263 | // t.tm_sec = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 264 | // t.tm_min = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 265 | // t.tm_hour = 0; // 0-23 |
mitesh2patel | 0:e1a0471e5ffb | 266 | // t.tm_mday = 0; // 1-31 |
mitesh2patel | 0:e1a0471e5ffb | 267 | // t.tm_mon = 0; // 0-11 |
mitesh2patel | 0:e1a0471e5ffb | 268 | // t.tm_year = 2005-1900; // year since 1900 |
mitesh2patel | 0:e1a0471e5ffb | 269 | // t.tm_wday = 0; // 0-6 Day of week (Sunday = 0) |
mitesh2patel | 0:e1a0471e5ffb | 270 | // t.tm_yday = 0; // Day of year (0 - 365) |
mitesh2patel | 0:e1a0471e5ffb | 271 | // t.tm_isdst = -1; // Nonzero = Daylight saving time |
mitesh2patel | 0:e1a0471e5ffb | 272 | } |
mitesh2patel | 0:e1a0471e5ffb | 273 | |
mitesh2patel | 0:e1a0471e5ffb | 274 | #if defined(LWIP_DEBUG) |
mitesh2patel | 0:e1a0471e5ffb | 275 | // Print DST dates report |
mitesh2patel | 0:e1a0471e5ffb | 276 | static void _sntp_dst_dates(int tz, tDST_ZONE zone, int year) { |
mitesh2patel | 0:e1a0471e5ffb | 277 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 278 | tDstPoint r; |
mitesh2patel | 0:e1a0471e5ffb | 279 | printf("\r\nDST DATES for zone %d/%s:\r\n", (int)zone, SNTPDstZoneName(zone)); |
mitesh2patel | 0:e1a0471e5ffb | 280 | |
mitesh2patel | 0:e1a0471e5ffb | 281 | r = _sntp_dst_calc(tz, zone, year, DST_START); |
mitesh2patel | 0:e1a0471e5ffb | 282 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 283 | printf(" %d DST BEGINS (+%04d sec) %s\r\n", year, r.dst, _buffer); |
mitesh2patel | 0:e1a0471e5ffb | 284 | |
mitesh2patel | 0:e1a0471e5ffb | 285 | r = _sntp_dst_calc(tz, zone, year, DST_STOP); |
mitesh2patel | 0:e1a0471e5ffb | 286 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 287 | printf(" %d DST ENDS (+%04d sec) %s\r\n", year, r.dst, _buffer); |
mitesh2patel | 0:e1a0471e5ffb | 288 | } |
mitesh2patel | 0:e1a0471e5ffb | 289 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 290 | |
mitesh2patel | 0:e1a0471e5ffb | 291 | #ifdef SNTP_DST_TESTS |
mitesh2patel | 0:e1a0471e5ffb | 292 | static void test_sntp_dst_calc(int tz, tDST_ZONE zone) { |
mitesh2patel | 0:e1a0471e5ffb | 293 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 294 | tDstPoint r; |
mitesh2patel | 0:e1a0471e5ffb | 295 | int year; |
mitesh2patel | 0:e1a0471e5ffb | 296 | |
mitesh2patel | 0:e1a0471e5ffb | 297 | printf("\r\nTEST: _sntp_dst_calc(tz=%d, zone=%d/%s)\r\n", tz, (int)zone, SNTPDstZoneName(zone)); |
mitesh2patel | 0:e1a0471e5ffb | 298 | |
mitesh2patel | 0:e1a0471e5ffb | 299 | for (year = 1999; year < 2016; year++) { |
mitesh2patel | 0:e1a0471e5ffb | 300 | r = _sntp_dst_calc(tz, zone, year, DST_START); |
mitesh2patel | 0:e1a0471e5ffb | 301 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 302 | printf(" (0,%d,start) %s %d\r\n", year, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 303 | |
mitesh2patel | 0:e1a0471e5ffb | 304 | r = _sntp_dst_calc(tz, zone, year, DST_STOP); |
mitesh2patel | 0:e1a0471e5ffb | 305 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 306 | printf(" (0,%d,stop ) %s %d\r\n", year, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 307 | } |
mitesh2patel | 0:e1a0471e5ffb | 308 | } |
mitesh2patel | 0:e1a0471e5ffb | 309 | |
mitesh2patel | 0:e1a0471e5ffb | 310 | static void test_sntp_dst_point(int index) { |
mitesh2patel | 0:e1a0471e5ffb | 311 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 312 | struct tm t; |
mitesh2patel | 0:e1a0471e5ffb | 313 | tDstPoint r; |
mitesh2patel | 0:e1a0471e5ffb | 314 | int tz=gSntpTimezone; |
mitesh2patel | 0:e1a0471e5ffb | 315 | tDST_ZONE zone=gSntpDstZone; |
mitesh2patel | 0:e1a0471e5ffb | 316 | int year = 2009, day, month; |
mitesh2patel | 0:e1a0471e5ffb | 317 | |
mitesh2patel | 0:e1a0471e5ffb | 318 | int norm = (index > 0) ? (int)(index/2) : (int)((index-1)/2); |
mitesh2patel | 0:e1a0471e5ffb | 319 | printf("\r\nTEST: _sntp_dst_point(%d) norm=%d\r\n", index, norm); |
mitesh2patel | 0:e1a0471e5ffb | 320 | |
mitesh2patel | 0:e1a0471e5ffb | 321 | t.tm_sec = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 322 | t.tm_min = 0; // 0-59 |
mitesh2patel | 0:e1a0471e5ffb | 323 | t.tm_hour = 9; // 0-23 |
mitesh2patel | 0:e1a0471e5ffb | 324 | t.tm_year = year-1900; |
mitesh2patel | 0:e1a0471e5ffb | 325 | |
mitesh2patel | 0:e1a0471e5ffb | 326 | day = 1; |
mitesh2patel | 0:e1a0471e5ffb | 327 | for (month = 0; month < 2; month++) { |
mitesh2patel | 0:e1a0471e5ffb | 328 | t.tm_mon = month; |
mitesh2patel | 0:e1a0471e5ffb | 329 | t.tm_mday = day; |
mitesh2patel | 0:e1a0471e5ffb | 330 | t.tm_year = year-1900; |
mitesh2patel | 0:e1a0471e5ffb | 331 | r = _sntp_dst_point(tz, zone, mktime(&t), index); |
mitesh2patel | 0:e1a0471e5ffb | 332 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 333 | printf(" (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 334 | } |
mitesh2patel | 0:e1a0471e5ffb | 335 | |
mitesh2patel | 0:e1a0471e5ffb | 336 | for (day = 1; day < 32; day++) { |
mitesh2patel | 0:e1a0471e5ffb | 337 | t.tm_mon = month; |
mitesh2patel | 0:e1a0471e5ffb | 338 | t.tm_mday = day; |
mitesh2patel | 0:e1a0471e5ffb | 339 | t.tm_year = year-1900; |
mitesh2patel | 0:e1a0471e5ffb | 340 | r = _sntp_dst_point(tz, zone, mktime(&t), index); |
mitesh2patel | 0:e1a0471e5ffb | 341 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 342 | printf(" (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 343 | } |
mitesh2patel | 0:e1a0471e5ffb | 344 | |
mitesh2patel | 0:e1a0471e5ffb | 345 | day = 30; |
mitesh2patel | 0:e1a0471e5ffb | 346 | for (; month < 10; month++) { |
mitesh2patel | 0:e1a0471e5ffb | 347 | t.tm_mon = month; |
mitesh2patel | 0:e1a0471e5ffb | 348 | t.tm_mday = day; |
mitesh2patel | 0:e1a0471e5ffb | 349 | t.tm_year = year-1900; |
mitesh2patel | 0:e1a0471e5ffb | 350 | r = _sntp_dst_point(tz, zone, mktime(&t), index); |
mitesh2patel | 0:e1a0471e5ffb | 351 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 352 | printf(" (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 353 | } |
mitesh2patel | 0:e1a0471e5ffb | 354 | |
mitesh2patel | 0:e1a0471e5ffb | 355 | for (day = 1; day < 32; day++) { |
mitesh2patel | 0:e1a0471e5ffb | 356 | t.tm_mon = month; |
mitesh2patel | 0:e1a0471e5ffb | 357 | t.tm_mday = day; |
mitesh2patel | 0:e1a0471e5ffb | 358 | t.tm_year = year-1900; |
mitesh2patel | 0:e1a0471e5ffb | 359 | r = _sntp_dst_point(tz, zone, mktime(&t), index); |
mitesh2patel | 0:e1a0471e5ffb | 360 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&r.t)); |
mitesh2patel | 0:e1a0471e5ffb | 361 | printf(" (0,%02d/%02d/%d,%d) %s %d\r\n", month+1, day, year, index, _buffer, r.dst); |
mitesh2patel | 0:e1a0471e5ffb | 362 | } |
mitesh2patel | 0:e1a0471e5ffb | 363 | |
mitesh2patel | 0:e1a0471e5ffb | 364 | } |
mitesh2patel | 0:e1a0471e5ffb | 365 | #endif // SNTP_DST_TESTS |
mitesh2patel | 0:e1a0471e5ffb | 366 | |
mitesh2patel | 0:e1a0471e5ffb | 367 | // Set current DST |
mitesh2patel | 0:e1a0471e5ffb | 368 | static void _sntp_dst_now(void) { |
mitesh2patel | 0:e1a0471e5ffb | 369 | time_t now = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 370 | // Convert to standart local time (no DST) |
mitesh2patel | 0:e1a0471e5ffb | 371 | now = gSntpRtcUtc ? (now + gSntpTimezone) : (now - gSntpDST); |
mitesh2patel | 0:e1a0471e5ffb | 372 | |
mitesh2patel | 0:e1a0471e5ffb | 373 | // Check DST setting for now |
mitesh2patel | 0:e1a0471e5ffb | 374 | tDstPoint dst = _sntp_dst_point(gSntpTimezone, gSntpDstZone, now, -1); |
mitesh2patel | 0:e1a0471e5ffb | 375 | |
mitesh2patel | 0:e1a0471e5ffb | 376 | #ifdef LWIP_DEBUG |
mitesh2patel | 0:e1a0471e5ffb | 377 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 378 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&dst.t)); |
mitesh2patel | 0:e1a0471e5ffb | 379 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ( |
mitesh2patel | 0:e1a0471e5ffb | 380 | "DEBUG: _sntp_dst_now(%d) based on last DST change on (%d) %s to (+%04d sec)\r\n", |
mitesh2patel | 0:e1a0471e5ffb | 381 | now, dst.t, _buffer, dst.dst)); |
mitesh2patel | 0:e1a0471e5ffb | 382 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 383 | |
mitesh2patel | 0:e1a0471e5ffb | 384 | // Change RTC |
mitesh2patel | 0:e1a0471e5ffb | 385 | SNTPSetDSTEx(dst.dst, true); |
mitesh2patel | 0:e1a0471e5ffb | 386 | } |
mitesh2patel | 0:e1a0471e5ffb | 387 | |
mitesh2patel | 0:e1a0471e5ffb | 388 | // Plan for next DST change |
mitesh2patel | 0:e1a0471e5ffb | 389 | static void _sntp_dst_schedule(void) { |
mitesh2patel | 0:e1a0471e5ffb | 390 | time_t now = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 391 | // Convert to standart local time (no DST) |
mitesh2patel | 0:e1a0471e5ffb | 392 | now = gSntpRtcUtc ? (now + gSntpTimezone) : (now - gSntpDST); |
mitesh2patel | 0:e1a0471e5ffb | 393 | |
mitesh2patel | 0:e1a0471e5ffb | 394 | // Check next DST change point |
mitesh2patel | 0:e1a0471e5ffb | 395 | tDstPoint dst = _sntp_dst_point(gSntpTimezone, gSntpDstZone, now, 0); |
mitesh2patel | 0:e1a0471e5ffb | 396 | |
mitesh2patel | 0:e1a0471e5ffb | 397 | if (dst.t) { |
mitesh2patel | 0:e1a0471e5ffb | 398 | |
mitesh2patel | 0:e1a0471e5ffb | 399 | #ifdef LWIP_DEBUG |
mitesh2patel | 0:e1a0471e5ffb | 400 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 401 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&dst.t)); |
mitesh2patel | 0:e1a0471e5ffb | 402 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 403 | |
mitesh2patel | 0:e1a0471e5ffb | 404 | // Set our alarm clock |
mitesh2patel | 0:e1a0471e5ffb | 405 | // Convert from standard local to UTC time or local time |
mitesh2patel | 0:e1a0471e5ffb | 406 | dst.t = gSntpRtcUtc ? (dst.t - gSntpTimezone) : (dst.t + gSntpDST); |
mitesh2patel | 0:e1a0471e5ffb | 407 | |
mitesh2patel | 0:e1a0471e5ffb | 408 | #ifdef LWIP_DEBUG |
mitesh2patel | 0:e1a0471e5ffb | 409 | if (time(NULL) > dst.t) { |
mitesh2patel | 0:e1a0471e5ffb | 410 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ( |
mitesh2patel | 0:e1a0471e5ffb | 411 | "DEBUG: _sntp_dst_schedule() ASSERTION FAILED !(%d<%d) trying to schedule for the past: %s (+%04d sec)\r\n", |
mitesh2patel | 0:e1a0471e5ffb | 412 | time(NULL), dst.t, _buffer, dst.dst)); |
mitesh2patel | 0:e1a0471e5ffb | 413 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 414 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ( |
mitesh2patel | 0:e1a0471e5ffb | 415 | "DEBUG: _sntp_dst_schedule() scheduled in %d seconds, set for %s (+%04d sec)\r\n", |
mitesh2patel | 0:e1a0471e5ffb | 416 | dst.t-time(NULL), _buffer, dst.dst)); |
mitesh2patel | 0:e1a0471e5ffb | 417 | } |
mitesh2patel | 0:e1a0471e5ffb | 418 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 419 | } |
mitesh2patel | 0:e1a0471e5ffb | 420 | gSntpRtcTCR = dst.t; |
mitesh2patel | 0:e1a0471e5ffb | 421 | gSntpRtcTCRDST = dst.dst; |
mitesh2patel | 0:e1a0471e5ffb | 422 | } |
mitesh2patel | 0:e1a0471e5ffb | 423 | |
mitesh2patel | 0:e1a0471e5ffb | 424 | // RTC ISR - called upon each RTC tick |
mitesh2patel | 0:e1a0471e5ffb | 425 | static void _sntp_isr(void) { |
mitesh2patel | 0:e1a0471e5ffb | 426 | time_t seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 427 | if (gSntpRtcTCR && seconds > gSntpRtcTCR ) { |
mitesh2patel | 0:e1a0471e5ffb | 428 | // DST change has arrived |
mitesh2patel | 0:e1a0471e5ffb | 429 | gSntpRtcTCR = 0; |
mitesh2patel | 0:e1a0471e5ffb | 430 | // Disable ISR and avoid extra calcs in SNTPSetDSTEx() |
mitesh2patel | 0:e1a0471e5ffb | 431 | |
mitesh2patel | 0:e1a0471e5ffb | 432 | //if (gSntpRtcTCRDST != gSntpDST) { |
mitesh2patel | 0:e1a0471e5ffb | 433 | // Change to/from DST |
mitesh2patel | 0:e1a0471e5ffb | 434 | SNTPSetDSTEx(gSntpRtcTCRDST, true); |
mitesh2patel | 0:e1a0471e5ffb | 435 | gSntpRtcTCRDST = 0; |
mitesh2patel | 0:e1a0471e5ffb | 436 | |
mitesh2patel | 0:e1a0471e5ffb | 437 | // Schedule callback to plan for next DST change (take it out of ISR context) |
mitesh2patel | 0:e1a0471e5ffb | 438 | gSntpDelay.attach(_sntp_dst_schedule, 1.0); |
mitesh2patel | 0:e1a0471e5ffb | 439 | |
mitesh2patel | 0:e1a0471e5ffb | 440 | #ifdef LWIP_DEBUG |
mitesh2patel | 0:e1a0471e5ffb | 441 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 442 | if (gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 443 | seconds += gSntpTimezone + gSntpDST; // Convert to local time |
mitesh2patel | 0:e1a0471e5ffb | 444 | } |
mitesh2patel | 0:e1a0471e5ffb | 445 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&seconds)); |
mitesh2patel | 0:e1a0471e5ffb | 446 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ( |
mitesh2patel | 0:e1a0471e5ffb | 447 | "DEBUG: _sntp_isr() changed DST. datetime=%s\r\n", _buffer)); |
mitesh2patel | 0:e1a0471e5ffb | 448 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 449 | |
mitesh2patel | 0:e1a0471e5ffb | 450 | //} |
mitesh2patel | 0:e1a0471e5ffb | 451 | |
mitesh2patel | 0:e1a0471e5ffb | 452 | } |
mitesh2patel | 0:e1a0471e5ffb | 453 | } |
mitesh2patel | 0:e1a0471e5ffb | 454 | |
mitesh2patel | 0:e1a0471e5ffb | 455 | // NTP Callback - timestamp from NTP server arrives here |
mitesh2patel | 0:e1a0471e5ffb | 456 | void SntpClientSet(time_t seconds) { |
mitesh2patel | 0:e1a0471e5ffb | 457 | time_t old_seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 458 | if (!gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 459 | seconds += gSntpTimezone + gSntpDST; // Convert to local time |
mitesh2patel | 0:e1a0471e5ffb | 460 | } |
mitesh2patel | 0:e1a0471e5ffb | 461 | set_time(seconds); |
mitesh2patel | 0:e1a0471e5ffb | 462 | |
mitesh2patel | 0:e1a0471e5ffb | 463 | // Special tasks for the very first NTP updates |
mitesh2patel | 0:e1a0471e5ffb | 464 | if (!gSntpUpdates) { |
mitesh2patel | 0:e1a0471e5ffb | 465 | |
mitesh2patel | 0:e1a0471e5ffb | 466 | #if defined(LWIP_DEBUG) |
mitesh2patel | 0:e1a0471e5ffb | 467 | // Report DST dates for the zone |
mitesh2patel | 0:e1a0471e5ffb | 468 | struct tm *pt = localtime(&seconds); |
mitesh2patel | 0:e1a0471e5ffb | 469 | _sntp_dst_dates(gSntpTimezone, gSntpDstZone, pt->tm_year+1900); |
mitesh2patel | 0:e1a0471e5ffb | 470 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 471 | |
mitesh2patel | 0:e1a0471e5ffb | 472 | // DST scheduler |
mitesh2patel | 0:e1a0471e5ffb | 473 | _sntp_dst_now(); |
mitesh2patel | 0:e1a0471e5ffb | 474 | _sntp_dst_schedule(); |
mitesh2patel | 0:e1a0471e5ffb | 475 | |
mitesh2patel | 0:e1a0471e5ffb | 476 | // Enable RTC ISR |
mitesh2patel | 0:e1a0471e5ffb | 477 | gSntpTicker.attach(_sntp_isr, 1.0); |
mitesh2patel | 0:e1a0471e5ffb | 478 | } |
mitesh2patel | 0:e1a0471e5ffb | 479 | |
mitesh2patel | 0:e1a0471e5ffb | 480 | if (gSntpUpdates && abs((int)(old_seconds - seconds)) > SNTP_EPSILON) { |
mitesh2patel | 0:e1a0471e5ffb | 481 | printf("SNTP settime() corrected big difference: (%d) seconds, more than %d. Big updates count=%d.\r\n", |
mitesh2patel | 0:e1a0471e5ffb | 482 | old_seconds-seconds, SNTP_EPSILON, gSntpUpdatesBig); |
mitesh2patel | 0:e1a0471e5ffb | 483 | gSntpUpdatesBig ++; |
mitesh2patel | 0:e1a0471e5ffb | 484 | } |
mitesh2patel | 0:e1a0471e5ffb | 485 | |
mitesh2patel | 0:e1a0471e5ffb | 486 | gSntpUpdates++; |
mitesh2patel | 0:e1a0471e5ffb | 487 | |
mitesh2patel | 0:e1a0471e5ffb | 488 | if (1) { |
mitesh2patel | 0:e1a0471e5ffb | 489 | char _buffer[64]; |
mitesh2patel | 0:e1a0471e5ffb | 490 | if (gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 491 | seconds += gSntpTimezone + gSntpDST; // Convert to local time |
mitesh2patel | 0:e1a0471e5ffb | 492 | } |
mitesh2patel | 0:e1a0471e5ffb | 493 | strftime(_buffer, sizeof(_buffer), "%A %m/%d/%Y %H:%M:%S", localtime(&seconds)); |
mitesh2patel | 0:e1a0471e5ffb | 494 | printf("SNTP settime() #%d seconds=%d TZ=%0.1f datetime=%s\r\n", |
mitesh2patel | 0:e1a0471e5ffb | 495 | gSntpUpdates, seconds, gSntpTimezone/3600.0, _buffer); |
mitesh2patel | 0:e1a0471e5ffb | 496 | } |
mitesh2patel | 0:e1a0471e5ffb | 497 | } |
mitesh2patel | 0:e1a0471e5ffb | 498 | #ifdef __cplusplus |
mitesh2patel | 0:e1a0471e5ffb | 499 | }; |
mitesh2patel | 0:e1a0471e5ffb | 500 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 501 | |
mitesh2patel | 0:e1a0471e5ffb | 502 | #ifdef __cplusplus |
mitesh2patel | 0:e1a0471e5ffb | 503 | extern "C" { |
mitesh2patel | 0:e1a0471e5ffb | 504 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 505 | |
mitesh2patel | 0:e1a0471e5ffb | 506 | #include "lwip/def.h" |
mitesh2patel | 0:e1a0471e5ffb | 507 | #include "lwip/pbuf.h" |
mitesh2patel | 0:e1a0471e5ffb | 508 | #include "lwip/sys.h" |
mitesh2patel | 0:e1a0471e5ffb | 509 | #include "lwip/stats.h" |
mitesh2patel | 0:e1a0471e5ffb | 510 | #include "netif/etharp.h" |
mitesh2patel | 0:e1a0471e5ffb | 511 | #include "string.h" |
mitesh2patel | 0:e1a0471e5ffb | 512 | |
mitesh2patel | 0:e1a0471e5ffb | 513 | #ifdef __cplusplus |
mitesh2patel | 0:e1a0471e5ffb | 514 | }; |
mitesh2patel | 0:e1a0471e5ffb | 515 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 516 | |
mitesh2patel | 0:e1a0471e5ffb | 517 | // Accomodating sntp timeout functions |
mitesh2patel | 0:e1a0471e5ffb | 518 | #if NO_SYS |
mitesh2patel | 0:e1a0471e5ffb | 519 | #include "sntp.h" |
mitesh2patel | 0:e1a0471e5ffb | 520 | extern void sntp_request(void *arg); // this is dirty hack around "static" function. Some linkers may revolt! |
mitesh2patel | 0:e1a0471e5ffb | 521 | extern void sntp_try_next_server(void *arg); |
mitesh2patel | 0:e1a0471e5ffb | 522 | extern char* sntp_server_addresses[]; |
mitesh2patel | 0:e1a0471e5ffb | 523 | extern u8_t sntp_current_server; |
mitesh2patel | 0:e1a0471e5ffb | 524 | extern u8_t sntp_num_servers; |
mitesh2patel | 0:e1a0471e5ffb | 525 | static void (*sntp_addresses_free)(void*) = NULL; |
mitesh2patel | 0:e1a0471e5ffb | 526 | static Timeout _sntp_timer1; |
mitesh2patel | 0:e1a0471e5ffb | 527 | static Timeout _sntp_timer2; |
mitesh2patel | 0:e1a0471e5ffb | 528 | void sntp_sys_timeout(u32_t timeout_s, void (*func)(void *arg), void *arg) { |
mitesh2patel | 0:e1a0471e5ffb | 529 | // all we really need to track is only 2 functions: sntp_request, sntp_try_next_server |
mitesh2patel | 0:e1a0471e5ffb | 530 | Timeout *t = NULL; |
mitesh2patel | 0:e1a0471e5ffb | 531 | if (func == &sntp_request) { |
mitesh2patel | 0:e1a0471e5ffb | 532 | t = &_sntp_timer1; |
mitesh2patel | 0:e1a0471e5ffb | 533 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_timeout(), func=sntp_request\r\n")); |
mitesh2patel | 0:e1a0471e5ffb | 534 | } else if (func == &sntp_try_next_server) { |
mitesh2patel | 0:e1a0471e5ffb | 535 | t = &_sntp_timer2; |
mitesh2patel | 0:e1a0471e5ffb | 536 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_timeout(), func=sntp_try_next_server\r\n")); |
mitesh2patel | 0:e1a0471e5ffb | 537 | } |
mitesh2patel | 0:e1a0471e5ffb | 538 | if (t) { |
mitesh2patel | 0:e1a0471e5ffb | 539 | t->detach(); |
mitesh2patel | 0:e1a0471e5ffb | 540 | t->attach((void(*)(void))func, 1.0*timeout_s); |
mitesh2patel | 0:e1a0471e5ffb | 541 | // Another shortcut - we have no arg to pass, so just typecast the func. |
mitesh2patel | 0:e1a0471e5ffb | 542 | } |
mitesh2patel | 0:e1a0471e5ffb | 543 | } |
mitesh2patel | 0:e1a0471e5ffb | 544 | |
mitesh2patel | 0:e1a0471e5ffb | 545 | void sntp_sys_untimeout(void (*func)(void *arg), void *arg) { |
mitesh2patel | 0:e1a0471e5ffb | 546 | Timeout *t = NULL; |
mitesh2patel | 0:e1a0471e5ffb | 547 | if (func == &sntp_request) { |
mitesh2patel | 0:e1a0471e5ffb | 548 | t = &_sntp_timer1; |
mitesh2patel | 0:e1a0471e5ffb | 549 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_untimeout(), func=sntp_request\r\n")); |
mitesh2patel | 0:e1a0471e5ffb | 550 | } else if (func == &sntp_try_next_server) { |
mitesh2patel | 0:e1a0471e5ffb | 551 | t = &_sntp_timer2; |
mitesh2patel | 0:e1a0471e5ffb | 552 | LWIP_DEBUGF(SNTP_DEBUG_STATE, ("DEBUG: IN sntp_sys_untimeout(), func=sntp_try_next_server\r\n")); |
mitesh2patel | 0:e1a0471e5ffb | 553 | } |
mitesh2patel | 0:e1a0471e5ffb | 554 | if (t) { |
mitesh2patel | 0:e1a0471e5ffb | 555 | t->detach(); |
mitesh2patel | 0:e1a0471e5ffb | 556 | } |
mitesh2patel | 0:e1a0471e5ffb | 557 | } |
mitesh2patel | 0:e1a0471e5ffb | 558 | |
mitesh2patel | 0:e1a0471e5ffb | 559 | #else // NO_SYS |
mitesh2patel | 0:e1a0471e5ffb | 560 | #error "I don't know how to compile LWIP/SNTP with NO_SYS=0" |
mitesh2patel | 0:e1a0471e5ffb | 561 | #endif // NO_SYS |
mitesh2patel | 0:e1a0471e5ffb | 562 | |
mitesh2patel | 0:e1a0471e5ffb | 563 | // Can be called when already running |
mitesh2patel | 0:e1a0471e5ffb | 564 | void SNTPSetDstZone(tDST_ZONE zone) { |
mitesh2patel | 0:e1a0471e5ffb | 565 | if (zone >= DST_ZONE_DESCR_CNT) |
mitesh2patel | 0:e1a0471e5ffb | 566 | return; // ERR_INVALID_ARG |
mitesh2patel | 0:e1a0471e5ffb | 567 | |
mitesh2patel | 0:e1a0471e5ffb | 568 | gSntpDstZone = zone; |
mitesh2patel | 0:e1a0471e5ffb | 569 | |
mitesh2patel | 0:e1a0471e5ffb | 570 | if (gSntpRunning) { |
mitesh2patel | 0:e1a0471e5ffb | 571 | // DST scheduler |
mitesh2patel | 0:e1a0471e5ffb | 572 | _sntp_dst_now(); |
mitesh2patel | 0:e1a0471e5ffb | 573 | _sntp_dst_schedule(); |
mitesh2patel | 0:e1a0471e5ffb | 574 | } |
mitesh2patel | 0:e1a0471e5ffb | 575 | } |
mitesh2patel | 0:e1a0471e5ffb | 576 | |
mitesh2patel | 0:e1a0471e5ffb | 577 | void SNTPSetRecvTimeout(unsigned int val_s) { gSntpRecvTimeout_s = val_s; } |
mitesh2patel | 0:e1a0471e5ffb | 578 | void SNTPSetUpdateDelay(unsigned int val_s) { gSntpUpdateDelay_s = val_s; } |
mitesh2patel | 0:e1a0471e5ffb | 579 | void SNTPSetTimezone(float hours_from_utc, bool adjust_clock) { |
mitesh2patel | 0:e1a0471e5ffb | 580 | if (adjust_clock && !gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 581 | time_t seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 582 | seconds -= gSntpTimezone; // Convert from old local time |
mitesh2patel | 0:e1a0471e5ffb | 583 | seconds += hours_from_utc * 3600; // Convert to new local time |
mitesh2patel | 0:e1a0471e5ffb | 584 | set_time(seconds); |
mitesh2patel | 0:e1a0471e5ffb | 585 | if (gSntpRtcTCR) { |
mitesh2patel | 0:e1a0471e5ffb | 586 | // Adjust our alarm clock |
mitesh2patel | 0:e1a0471e5ffb | 587 | gSntpRtcTCR -= gSntpTimezone; |
mitesh2patel | 0:e1a0471e5ffb | 588 | gSntpRtcTCR += hours_from_utc * 3600; |
mitesh2patel | 0:e1a0471e5ffb | 589 | } |
mitesh2patel | 0:e1a0471e5ffb | 590 | } |
mitesh2patel | 0:e1a0471e5ffb | 591 | gSntpTimezone = hours_from_utc * 3600; |
mitesh2patel | 0:e1a0471e5ffb | 592 | } |
mitesh2patel | 0:e1a0471e5ffb | 593 | void SNTPSetDST(float hours_from_utc, bool adjust_clock) { |
mitesh2patel | 0:e1a0471e5ffb | 594 | SNTPSetDSTEx(hours_from_utc * 3600, adjust_clock); |
mitesh2patel | 0:e1a0471e5ffb | 595 | } |
mitesh2patel | 0:e1a0471e5ffb | 596 | |
mitesh2patel | 0:e1a0471e5ffb | 597 | static int sntp_num_servers_alloc = 0; |
mitesh2patel | 0:e1a0471e5ffb | 598 | static void _SNTPClrAddresses(void) { |
mitesh2patel | 0:e1a0471e5ffb | 599 | if (!sntp_num_servers_alloc) sntp_num_servers_alloc = sntp_num_servers; |
mitesh2patel | 0:e1a0471e5ffb | 600 | // Here we save the original size of the sntp_server_addresses[] array. |
mitesh2patel | 0:e1a0471e5ffb | 601 | |
mitesh2patel | 0:e1a0471e5ffb | 602 | if (sntp_addresses_free) { |
mitesh2patel | 0:e1a0471e5ffb | 603 | for (int i=0; i<sntp_num_servers; i++) { |
mitesh2patel | 0:e1a0471e5ffb | 604 | sntp_addresses_free(sntp_server_addresses[i]); |
mitesh2patel | 0:e1a0471e5ffb | 605 | } |
mitesh2patel | 0:e1a0471e5ffb | 606 | } |
mitesh2patel | 0:e1a0471e5ffb | 607 | sntp_current_server = 0; |
mitesh2patel | 0:e1a0471e5ffb | 608 | sntp_num_servers = 0; |
mitesh2patel | 0:e1a0471e5ffb | 609 | sntp_addresses_free = NULL; |
mitesh2patel | 0:e1a0471e5ffb | 610 | } |
mitesh2patel | 0:e1a0471e5ffb | 611 | static int _SNTPAddAddress(const char* server_address) { |
mitesh2patel | 0:e1a0471e5ffb | 612 | if (sntp_num_servers+1 > sntp_num_servers_alloc) |
mitesh2patel | 0:e1a0471e5ffb | 613 | return -1; |
mitesh2patel | 0:e1a0471e5ffb | 614 | sntp_server_addresses[sntp_num_servers] = (char*)malloc(strlen(server_address)+1); |
mitesh2patel | 0:e1a0471e5ffb | 615 | if (sntp_server_addresses[sntp_num_servers] == NULL) return -1; // Out of memory |
mitesh2patel | 0:e1a0471e5ffb | 616 | strcpy(sntp_server_addresses[sntp_num_servers], server_address); |
mitesh2patel | 0:e1a0471e5ffb | 617 | sntp_num_servers++; |
mitesh2patel | 0:e1a0471e5ffb | 618 | return 0; |
mitesh2patel | 0:e1a0471e5ffb | 619 | } |
mitesh2patel | 0:e1a0471e5ffb | 620 | |
mitesh2patel | 0:e1a0471e5ffb | 621 | // Override default servers list. |
mitesh2patel | 0:e1a0471e5ffb | 622 | // For no-copy, pass pointer to free() in p_free. |
mitesh2patel | 0:e1a0471e5ffb | 623 | // Returns: actual number of servers set (limited by allocated buffer size) |
mitesh2patel | 0:e1a0471e5ffb | 624 | // WARNING! There is no interlock to ensure that SNTP service does not read its data while we are updating it. |
mitesh2patel | 0:e1a0471e5ffb | 625 | // This function is intended to be called only before SNTPClientInit(). |
mitesh2patel | 0:e1a0471e5ffb | 626 | int SNTPSetAddresses(const char* server_addresses[], int count, void (*p_free)(void*)) { |
mitesh2patel | 0:e1a0471e5ffb | 627 | // In order to use sntp.c as-is, we hack into its static variables. |
mitesh2patel | 0:e1a0471e5ffb | 628 | // Not all compilers/linkers will support that. |
mitesh2patel | 0:e1a0471e5ffb | 629 | |
mitesh2patel | 0:e1a0471e5ffb | 630 | _SNTPClrAddresses(); |
mitesh2patel | 0:e1a0471e5ffb | 631 | if (count > sntp_num_servers_alloc) |
mitesh2patel | 0:e1a0471e5ffb | 632 | count = sntp_num_servers_alloc; |
mitesh2patel | 0:e1a0471e5ffb | 633 | for (int i=0; i<count; i++) { |
mitesh2patel | 0:e1a0471e5ffb | 634 | if (p_free) { |
mitesh2patel | 0:e1a0471e5ffb | 635 | sntp_server_addresses[i] = (char *)server_addresses[i]; |
mitesh2patel | 0:e1a0471e5ffb | 636 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 637 | _SNTPAddAddress(server_addresses[i]); |
mitesh2patel | 0:e1a0471e5ffb | 638 | } |
mitesh2patel | 0:e1a0471e5ffb | 639 | } |
mitesh2patel | 0:e1a0471e5ffb | 640 | sntp_num_servers = count; |
mitesh2patel | 0:e1a0471e5ffb | 641 | sntp_current_server = 0; |
mitesh2patel | 0:e1a0471e5ffb | 642 | sntp_addresses_free = p_free ? p_free : &free; |
mitesh2patel | 0:e1a0471e5ffb | 643 | return count; |
mitesh2patel | 0:e1a0471e5ffb | 644 | } |
mitesh2patel | 0:e1a0471e5ffb | 645 | |
mitesh2patel | 0:e1a0471e5ffb | 646 | // Trim whitespace/CRLFs from both ends of a given string |
mitesh2patel | 0:e1a0471e5ffb | 647 | char * str_cleanup(char *in) { |
mitesh2patel | 0:e1a0471e5ffb | 648 | char * out = in; |
mitesh2patel | 0:e1a0471e5ffb | 649 | // Trim leading spaces and CR/LF |
mitesh2patel | 0:e1a0471e5ffb | 650 | while (*out == ' ' || *out == '\t' || *out == '\r' || *out == '\n') |
mitesh2patel | 0:e1a0471e5ffb | 651 | out ++; |
mitesh2patel | 0:e1a0471e5ffb | 652 | // Trim trailing spaces and CR/LF |
mitesh2patel | 0:e1a0471e5ffb | 653 | int len = strlen(out)-1; |
mitesh2patel | 0:e1a0471e5ffb | 654 | while (out[len] == ' ' || out[len] == '\t' || out[len] == '\r' || out[len] == '\n') { |
mitesh2patel | 0:e1a0471e5ffb | 655 | out[len] = '\0'; |
mitesh2patel | 0:e1a0471e5ffb | 656 | len--; |
mitesh2patel | 0:e1a0471e5ffb | 657 | } |
mitesh2patel | 0:e1a0471e5ffb | 658 | return out; |
mitesh2patel | 0:e1a0471e5ffb | 659 | } |
mitesh2patel | 0:e1a0471e5ffb | 660 | |
mitesh2patel | 0:e1a0471e5ffb | 661 | #ifndef CRLF |
mitesh2patel | 0:e1a0471e5ffb | 662 | #define CRLF "\r\n" |
mitesh2patel | 0:e1a0471e5ffb | 663 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 664 | void SNTPWriteIniFile(FILE * f) { |
mitesh2patel | 0:e1a0471e5ffb | 665 | fprintf(f, "# SNTP Configuration file" CRLF); |
mitesh2patel | 0:e1a0471e5ffb | 666 | fprintf(f, CRLF "[Servers]" CRLF); |
mitesh2patel | 0:e1a0471e5ffb | 667 | for (int i=0; i<sntp_num_servers; i++) { |
mitesh2patel | 0:e1a0471e5ffb | 668 | fprintf(f, "%s" CRLF, sntp_server_addresses[i]); |
mitesh2patel | 0:e1a0471e5ffb | 669 | } |
mitesh2patel | 0:e1a0471e5ffb | 670 | fprintf(f, CRLF "[Global]" CRLF); |
mitesh2patel | 0:e1a0471e5ffb | 671 | fprintf(f, "RtcUtc=%d" CRLF, (int)gSntpRtcUtc); |
mitesh2patel | 0:e1a0471e5ffb | 672 | fprintf(f, "Timezone=%0.1f" CRLF, gSntpTimezone / 3600.0); |
mitesh2patel | 0:e1a0471e5ffb | 673 | fprintf(f, "DstZone=%d" CRLF, gSntpDstZone); |
mitesh2patel | 0:e1a0471e5ffb | 674 | fprintf(f, "# %s" CRLF, SNTPDstZoneName(gSntpDstZone)); |
mitesh2patel | 0:e1a0471e5ffb | 675 | fprintf(f, "UpdateDelay=%d" CRLF, gSntpUpdateDelay_s); |
mitesh2patel | 0:e1a0471e5ffb | 676 | fprintf(f, "RecvTimeout=%d" CRLF, gSntpRecvTimeout_s); |
mitesh2patel | 0:e1a0471e5ffb | 677 | fprintf(f, CRLF "##END" CRLF); |
mitesh2patel | 0:e1a0471e5ffb | 678 | } |
mitesh2patel | 0:e1a0471e5ffb | 679 | |
mitesh2patel | 0:e1a0471e5ffb | 680 | // Simple ini file parser for SNTP configuration (Case-sensitive!) |
mitesh2patel | 0:e1a0471e5ffb | 681 | // This function is intended to be called only before SNTPClientInit(). |
mitesh2patel | 0:e1a0471e5ffb | 682 | // Returns: 0 if OK, errno otherwise |
mitesh2patel | 0:e1a0471e5ffb | 683 | enum { |
mitesh2patel | 0:e1a0471e5ffb | 684 | SECT_NONE, |
mitesh2patel | 0:e1a0471e5ffb | 685 | SECT_SERVERS, |
mitesh2patel | 0:e1a0471e5ffb | 686 | SECT_GLOBAL, |
mitesh2patel | 0:e1a0471e5ffb | 687 | }; |
mitesh2patel | 0:e1a0471e5ffb | 688 | int SNTPReadIniFile(const char* filename) { |
mitesh2patel | 0:e1a0471e5ffb | 689 | FILE *f; |
mitesh2patel | 0:e1a0471e5ffb | 690 | char buf[512]; |
mitesh2patel | 0:e1a0471e5ffb | 691 | bool addresses_cleared = false; |
mitesh2patel | 0:e1a0471e5ffb | 692 | |
mitesh2patel | 0:e1a0471e5ffb | 693 | f = fopen(filename, "r"); |
mitesh2patel | 0:e1a0471e5ffb | 694 | if (!f) |
mitesh2patel | 0:e1a0471e5ffb | 695 | return -1; // errno not used? |
mitesh2patel | 0:e1a0471e5ffb | 696 | |
mitesh2patel | 0:e1a0471e5ffb | 697 | char *buf1, *buf2; |
mitesh2patel | 0:e1a0471e5ffb | 698 | int section=SECT_NONE; |
mitesh2patel | 0:e1a0471e5ffb | 699 | int line = 0; |
mitesh2patel | 0:e1a0471e5ffb | 700 | while (fgets(buf, sizeof(buf)/sizeof(buf[0]), f)) { |
mitesh2patel | 0:e1a0471e5ffb | 701 | line++; |
mitesh2patel | 0:e1a0471e5ffb | 702 | buf1 = str_cleanup(buf); |
mitesh2patel | 0:e1a0471e5ffb | 703 | if (*buf1 == '#' || *buf1 == '\0') |
mitesh2patel | 0:e1a0471e5ffb | 704 | continue; // Comment line or empty line - skip |
mitesh2patel | 0:e1a0471e5ffb | 705 | if (*buf1 == '[') { |
mitesh2patel | 0:e1a0471e5ffb | 706 | // New section |
mitesh2patel | 0:e1a0471e5ffb | 707 | if (0 == strncmp(buf1,"[Servers]", sizeof("[Servers]")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 708 | section=SECT_SERVERS; |
mitesh2patel | 0:e1a0471e5ffb | 709 | if (!addresses_cleared) { |
mitesh2patel | 0:e1a0471e5ffb | 710 | // Clear addresses only once. |
mitesh2patel | 0:e1a0471e5ffb | 711 | _SNTPClrAddresses(); |
mitesh2patel | 0:e1a0471e5ffb | 712 | addresses_cleared = true; |
mitesh2patel | 0:e1a0471e5ffb | 713 | } |
mitesh2patel | 0:e1a0471e5ffb | 714 | } else if (0 == strncmp(buf1,"[Global]", sizeof("[Global]")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 715 | section=SECT_GLOBAL; |
mitesh2patel | 0:e1a0471e5ffb | 716 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 717 | section=SECT_NONE; |
mitesh2patel | 0:e1a0471e5ffb | 718 | fprintf(stderr, "File \"%s\", line %d - section \"%s\" is not understood.\r\n", filename, line, buf1); |
mitesh2patel | 0:e1a0471e5ffb | 719 | } |
mitesh2patel | 0:e1a0471e5ffb | 720 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 721 | // Section values |
mitesh2patel | 0:e1a0471e5ffb | 722 | switch (section) { |
mitesh2patel | 0:e1a0471e5ffb | 723 | case SECT_SERVERS: |
mitesh2patel | 0:e1a0471e5ffb | 724 | if (_SNTPAddAddress(buf1)) { |
mitesh2patel | 0:e1a0471e5ffb | 725 | fprintf(stderr, "File \"%s\", line %d - cannot add server \"%s\" - exceeded allocated slots.\r\n", filename, line, buf1); |
mitesh2patel | 0:e1a0471e5ffb | 726 | } |
mitesh2patel | 0:e1a0471e5ffb | 727 | break; |
mitesh2patel | 0:e1a0471e5ffb | 728 | case SECT_GLOBAL: |
mitesh2patel | 0:e1a0471e5ffb | 729 | buf2 = strchr(buf1, '='); |
mitesh2patel | 0:e1a0471e5ffb | 730 | if (buf2) { |
mitesh2patel | 0:e1a0471e5ffb | 731 | *buf2++ = '\0'; // Now buf1 has variable name, buf2 has value |
mitesh2patel | 0:e1a0471e5ffb | 732 | buf2 = str_cleanup(buf2); |
mitesh2patel | 0:e1a0471e5ffb | 733 | if (0 == strncmp(buf1, "Timezone", sizeof("Timezone")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 734 | gSntpTimezone = strtod(buf2, &buf2) * 3600; |
mitesh2patel | 0:e1a0471e5ffb | 735 | } else if (0 == strncmp(buf1, "UpdateDelay", sizeof("UpdateDelay")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 736 | gSntpUpdateDelay_s = strtoul(buf2, &buf2, 10); |
mitesh2patel | 0:e1a0471e5ffb | 737 | } else if (0 == strncmp(buf1, "RecvTimeout", sizeof("RecvTimeout")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 738 | gSntpRecvTimeout_s = strtoul(buf2, &buf2, 10); |
mitesh2patel | 0:e1a0471e5ffb | 739 | } else if (0 == strncmp(buf1, "RtcUtc", sizeof("RtcUtc")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 740 | gSntpRtcUtc = (bool)strtol(buf2, &buf2, 10); |
mitesh2patel | 0:e1a0471e5ffb | 741 | } else if (0 == strncmp(buf1, "DstZone", sizeof("DstZone")-1)) { |
mitesh2patel | 0:e1a0471e5ffb | 742 | // FIXME: It would be nice to allow human-readable string here. |
mitesh2patel | 0:e1a0471e5ffb | 743 | gSntpDstZone = (tDST_ZONE)strtol(buf2, &buf2, 10); |
mitesh2patel | 0:e1a0471e5ffb | 744 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 745 | fprintf(stderr, "File \"%s\", line %d - unrecognized variable \"%s\" in section [Global]\r\n", filename, line, buf1); |
mitesh2patel | 0:e1a0471e5ffb | 746 | } |
mitesh2patel | 0:e1a0471e5ffb | 747 | } else { |
mitesh2patel | 0:e1a0471e5ffb | 748 | fprintf(stderr, "File \"%s\", line %d - unrecognized statement in section [Global]: %s\r\n", filename, line, buf1); |
mitesh2patel | 0:e1a0471e5ffb | 749 | } |
mitesh2patel | 0:e1a0471e5ffb | 750 | break; |
mitesh2patel | 0:e1a0471e5ffb | 751 | default: |
mitesh2patel | 0:e1a0471e5ffb | 752 | fprintf(stderr, "File \"%s\", line %d - unrecognized statement / no section: %s\r\n", filename, line, buf1); |
mitesh2patel | 0:e1a0471e5ffb | 753 | } |
mitesh2patel | 0:e1a0471e5ffb | 754 | } |
mitesh2patel | 0:e1a0471e5ffb | 755 | } |
mitesh2patel | 0:e1a0471e5ffb | 756 | fclose(f); |
mitesh2patel | 0:e1a0471e5ffb | 757 | printf("SNTP configuration read from file \"%s\", %d lines.\r\n", filename, line); |
mitesh2patel | 0:e1a0471e5ffb | 758 | return 0; |
mitesh2patel | 0:e1a0471e5ffb | 759 | } |
mitesh2patel | 0:e1a0471e5ffb | 760 | |
mitesh2patel | 0:e1a0471e5ffb | 761 | // Start the SNTP client |
mitesh2patel | 0:e1a0471e5ffb | 762 | void SNTPClientInit(void) { |
mitesh2patel | 0:e1a0471e5ffb | 763 | |
mitesh2patel | 0:e1a0471e5ffb | 764 | #ifdef SNTP_DST_TESTS |
mitesh2patel | 0:e1a0471e5ffb | 765 | // Test our DST algorithms |
mitesh2patel | 0:e1a0471e5ffb | 766 | test_sntp_dst_calc(gSntpTimezone, gSntpDstZone); |
mitesh2patel | 0:e1a0471e5ffb | 767 | test_sntp_dst_point(-2); |
mitesh2patel | 0:e1a0471e5ffb | 768 | test_sntp_dst_point(-1); |
mitesh2patel | 0:e1a0471e5ffb | 769 | test_sntp_dst_point(0); |
mitesh2patel | 0:e1a0471e5ffb | 770 | test_sntp_dst_point(1); |
mitesh2patel | 0:e1a0471e5ffb | 771 | test_sntp_dst_point(2); |
mitesh2patel | 0:e1a0471e5ffb | 772 | #endif |
mitesh2patel | 0:e1a0471e5ffb | 773 | |
mitesh2patel | 0:e1a0471e5ffb | 774 | // SNTPv4 RFC 4330 enforces a minimum update time of 15 seconds |
mitesh2patel | 0:e1a0471e5ffb | 775 | if (gSntpUpdateDelay_s < 15) { |
mitesh2patel | 0:e1a0471e5ffb | 776 | gSntpUpdateDelay_s = 15; |
mitesh2patel | 0:e1a0471e5ffb | 777 | } |
mitesh2patel | 0:e1a0471e5ffb | 778 | |
mitesh2patel | 0:e1a0471e5ffb | 779 | gSntpRunning = true; |
mitesh2patel | 0:e1a0471e5ffb | 780 | |
mitesh2patel | 0:e1a0471e5ffb | 781 | // Just call this to start SNTP client: |
mitesh2patel | 0:e1a0471e5ffb | 782 | sntp_init(); |
mitesh2patel | 0:e1a0471e5ffb | 783 | |
mitesh2patel | 0:e1a0471e5ffb | 784 | // // Enable RTC ISR |
mitesh2patel | 0:e1a0471e5ffb | 785 | // gSntpTicker.attach(_sntp_isr, 1); |
mitesh2patel | 0:e1a0471e5ffb | 786 | // We do it from first NTP response |
mitesh2patel | 0:e1a0471e5ffb | 787 | } |
mitesh2patel | 0:e1a0471e5ffb | 788 | |
mitesh2patel | 0:e1a0471e5ffb | 789 | // Use instead of system time() |
mitesh2patel | 0:e1a0471e5ffb | 790 | // Returns local time |
mitesh2patel | 0:e1a0471e5ffb | 791 | time_t SNTPTime(void) { |
mitesh2patel | 0:e1a0471e5ffb | 792 | time_t seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 793 | if (gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 794 | seconds += gSntpTimezone + gSntpDST; // Convert to local time |
mitesh2patel | 0:e1a0471e5ffb | 795 | } |
mitesh2patel | 0:e1a0471e5ffb | 796 | return seconds; |
mitesh2patel | 0:e1a0471e5ffb | 797 | } |
mitesh2patel | 0:e1a0471e5ffb | 798 | |
mitesh2patel | 0:e1a0471e5ffb | 799 | // Use instead of system set_time() |
mitesh2patel | 0:e1a0471e5ffb | 800 | // seconds - local time |
mitesh2patel | 0:e1a0471e5ffb | 801 | void SNTPSetTime(time_t seconds) { |
mitesh2patel | 0:e1a0471e5ffb | 802 | if (gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 803 | seconds -= gSntpTimezone + gSntpDST; // Convert from local time |
mitesh2patel | 0:e1a0471e5ffb | 804 | } |
mitesh2patel | 0:e1a0471e5ffb | 805 | set_time(seconds); |
mitesh2patel | 0:e1a0471e5ffb | 806 | } |
mitesh2patel | 0:e1a0471e5ffb | 807 | |
mitesh2patel | 0:e1a0471e5ffb | 808 | // Use instead of system time() |
mitesh2patel | 0:e1a0471e5ffb | 809 | // Returns UTC time |
mitesh2patel | 0:e1a0471e5ffb | 810 | time_t SNTPTimeUTC(void) { |
mitesh2patel | 0:e1a0471e5ffb | 811 | time_t seconds = time(NULL); |
mitesh2patel | 0:e1a0471e5ffb | 812 | if (!gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 813 | seconds -= gSntpTimezone + gSntpDST; // Convert from local time |
mitesh2patel | 0:e1a0471e5ffb | 814 | } |
mitesh2patel | 0:e1a0471e5ffb | 815 | return seconds; |
mitesh2patel | 0:e1a0471e5ffb | 816 | } |
mitesh2patel | 0:e1a0471e5ffb | 817 | |
mitesh2patel | 0:e1a0471e5ffb | 818 | // Use instead of system set_time() |
mitesh2patel | 0:e1a0471e5ffb | 819 | // seconds - UTC time |
mitesh2patel | 0:e1a0471e5ffb | 820 | void SNTPSetTimeUTC(time_t seconds) { |
mitesh2patel | 0:e1a0471e5ffb | 821 | if (!gSntpRtcUtc) { |
mitesh2patel | 0:e1a0471e5ffb | 822 | seconds += gSntpTimezone + gSntpDST; // Convert to local time |
mitesh2patel | 0:e1a0471e5ffb | 823 | } |
mitesh2patel | 0:e1a0471e5ffb | 824 | set_time(seconds); |
mitesh2patel | 0:e1a0471e5ffb | 825 | } |
mitesh2patel | 0:e1a0471e5ffb | 826 | |
mitesh2patel | 0:e1a0471e5ffb | 827 | //END |