| 
									
										
										
										
											2016-12-30 23:38:51 +00:00
										 |  |  | /*
 | 
					
						
							|  |  |  |  * Acquires time from NTP server | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  | TimeChangeRule UTCr = {Last, Sun, Mar, 1, 0};     // UTC
 | 
					
						
							|  |  |  | Timezone tzUTC(UTCr, UTCr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule BST = {Last, Sun, Mar, 1, 60};        // British Summer Time
 | 
					
						
							|  |  |  | TimeChangeRule GMT = {Last, Sun, Oct, 2, 0};         // Standard Time
 | 
					
						
							|  |  |  | Timezone tzUK(BST, GMT); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule CEST = {Last, Sun, Mar, 2, 120};     //Central European Summer Time
 | 
					
						
							|  |  |  | TimeChangeRule CET = {Last, Sun, Oct, 3, 60};       //Central European Standard Time
 | 
					
						
							|  |  |  | Timezone tzEUCentral(CEST, CET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule EEST = {Last, Sun, Mar, 3, 180};     //Central European Summer Time
 | 
					
						
							|  |  |  | TimeChangeRule EET = {Last, Sun, Oct, 4, 120};       //Central European Standard Time
 | 
					
						
							|  |  |  | Timezone tzEUEastern(EEST, EET); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule EDT = {Second, Sun, Mar, 2, -240 };    //Daylight time = UTC - 4 hours
 | 
					
						
							|  |  |  | TimeChangeRule EST = {First, Sun, Nov, 2, -300 };     //Standard time = UTC - 5 hours
 | 
					
						
							|  |  |  | Timezone tzUSEastern(EDT, EST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule CDT = {Second, Sun, Mar, 2, -300 };    //Daylight time = UTC - 5 hours
 | 
					
						
							|  |  |  | TimeChangeRule CST = {First, Sun, Nov, 2, -360 };     //Standard time = UTC - 6 hours
 | 
					
						
							|  |  |  | Timezone tzUSCentral(CDT, CST); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-12 00:22:58 +00:00
										 |  |  | Timezone tzCASaskatchewan(CST, CST); //Central without DST
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  | TimeChangeRule MDT = {Second, Sun, Mar, 2, -360 };    //Daylight time = UTC - 6 hours
 | 
					
						
							|  |  |  | TimeChangeRule MST = {First, Sun, Nov, 2, -420 };     //Standard time = UTC - 7 hours
 | 
					
						
							|  |  |  | Timezone tzUSMountain(MDT, MST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Timezone tzUSArizona(MST, MST); //Mountain without DST
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule PDT = {Second, Sun, Mar, 2, -420 };    //Daylight time = UTC - 7 hours
 | 
					
						
							|  |  |  | TimeChangeRule PST = {First, Sun, Nov, 2, -480 };     //Standard time = UTC - 8 hours
 | 
					
						
							|  |  |  | Timezone tzUSPacific(PDT, PST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule ChST = {Last, Sun, Mar, 1, 480};     // China Standard Time = UTC + 8 hours
 | 
					
						
							|  |  |  | Timezone tzChina(ChST, ChST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule JST = {Last, Sun, Mar, 1, 540};     // Japan Standard Time = UTC + 9 hours
 | 
					
						
							|  |  |  | Timezone tzJapan(JST, JST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule AEDT = {Second, Sun, Oct, 2, 660 };    //Daylight time = UTC + 11 hours
 | 
					
						
							|  |  |  | TimeChangeRule AEST = {First, Sun, Apr, 3, 600 };     //Standard time = UTC + 10 hours
 | 
					
						
							|  |  |  | Timezone tzAUEastern(AEDT, AEST); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | TimeChangeRule NZDT = {Second, Sun, Sep, 2, 780 };    //Daylight time = UTC + 13 hours
 | 
					
						
							|  |  |  | TimeChangeRule NZST = {First, Sun, Apr, 3, 720 };     //Standard time = UTC + 12 hours
 | 
					
						
							|  |  |  | Timezone tzNZ(NZDT, NZST); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-31 22:08:50 +00:00
										 |  |  | TimeChangeRule NKST = {Last, Sun, Mar, 1, 510};     //Pyongyang Time = UTC + 8.5 hours
 | 
					
						
							|  |  |  | Timezone tzNK(NKST, NKST); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-29 00:19:56 +00:00
										 |  |  | TimeChangeRule IST = {Last, Sun, Mar, 1, 330};     // India Standard Time = UTC + 5.5 hours
 | 
					
						
							|  |  |  | Timezone tzIndia(IST, IST); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-23 19:54:00 +00:00
										 |  |  | Timezone* timezones[] = {&tzUTC, &tzUK, &tzEUCentral, &tzEUEastern, &tzUSEastern, &tzUSCentral, &tzUSMountain, &tzUSArizona, &tzUSPacific, &tzChina, &tzJapan, &tzAUEastern, &tzNZ, &tzNK, &tzIndia, &tzCASaskatchewan};   | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-28 23:03:58 +00:00
										 |  |  | void handleNetworkTime() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-10-18 11:26:39 +00:00
										 |  |  |   if (ntpEnabled && ntpConnected && millis() - ntpLastSyncTime > 50000000L && WLED_CONNECTED) | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |   { | 
					
						
							|  |  |  |     if (millis() - ntpPacketSentTime > 10000) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       sendNTPPacket(); | 
					
						
							|  |  |  |       ntpPacketSentTime = millis(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     if (checkNTPResponse()) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       ntpLastSyncTime = millis(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void sendNTPPacket() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2019-12-04 01:01:47 +00:00
										 |  |  |   if (!ntpServerIP.fromString(ntpServerName)) //see if server is IP or domain
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     #ifdef ESP8266
 | 
					
						
							|  |  |  |     WiFi.hostByName(ntpServerName, ntpServerIP, 750); | 
					
						
							|  |  |  |     #else
 | 
					
						
							|  |  |  |     WiFi.hostByName(ntpServerName, ntpServerIP); | 
					
						
							|  |  |  |     #endif
 | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |   DEBUG_PRINTLN("send NTP"); | 
					
						
							|  |  |  |   byte pbuf[NTP_PACKET_SIZE]; | 
					
						
							|  |  |  |   memset(pbuf, 0, NTP_PACKET_SIZE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   pbuf[0] = 0b11100011;   // LI, Version, Mode
 | 
					
						
							|  |  |  |   pbuf[1] = 0;     // Stratum, or type of clock
 | 
					
						
							|  |  |  |   pbuf[2] = 6;     // Polling Interval
 | 
					
						
							|  |  |  |   pbuf[3] = 0xEC;  // Peer Clock Precision
 | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |   // 8 bytes of zero for Root Delay & Root Dispersion
 | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |   pbuf[12]  = 49; | 
					
						
							|  |  |  |   pbuf[13]  = 0x4E; | 
					
						
							|  |  |  |   pbuf[14]  = 49; | 
					
						
							|  |  |  |   pbuf[15]  = 52; | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |   ntpUdp.beginPacket(ntpServerIP, 123); //NTP requests are to port 123
 | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |   ntpUdp.write(pbuf, NTP_PACKET_SIZE); | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |   ntpUdp.endPacket(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-14 12:16:28 +00:00
										 |  |  | bool checkNTPResponse() | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  | { | 
					
						
							|  |  |  |   int cb = ntpUdp.parsePacket(); | 
					
						
							|  |  |  |   if (cb) { | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |     DEBUG_PRINT("NTP recv, l="); | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |     DEBUG_PRINTLN(cb); | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |     byte pbuf[NTP_PACKET_SIZE]; | 
					
						
							|  |  |  |     ntpUdp.read(pbuf, NTP_PACKET_SIZE); // read the packet into the buffer
 | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |     unsigned long highWord = word(pbuf[40], pbuf[41]); | 
					
						
							|  |  |  |     unsigned long lowWord = word(pbuf[42], pbuf[43]); | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |     if (highWord == 0 && lowWord == 0) return false; | 
					
						
							|  |  |  |      | 
					
						
							|  |  |  |     unsigned long secsSince1900 = highWord << 16 | lowWord; | 
					
						
							|  |  |  |   | 
					
						
							|  |  |  |     DEBUG_PRINT("Unix time = "); | 
					
						
							| 
									
										
										
										
											2018-04-11 21:50:35 +00:00
										 |  |  |     unsigned long epoch = secsSince1900 - 2208988799UL; //subtract 70 years -1sec (on avg. more precision)
 | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |     setTime(epoch); | 
					
						
							|  |  |  |     DEBUG_PRINTLN(epoch); | 
					
						
							| 
									
										
										
										
											2018-01-13 23:53:16 +00:00
										 |  |  |     if (countdownTime - now() > 0) countdownOverTriggered = false; | 
					
						
							| 
									
										
										
										
											2017-02-07 15:02:27 +00:00
										 |  |  |     return true; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							| 
									
										
										
										
											2016-12-28 23:03:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  | void updateLocalTime() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-13 23:25:54 +00:00
										 |  |  |   unsigned long tmc = now()+ utcOffsetSecs; | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  |   local = timezones[currentTimezone]->toLocal(tmc); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-16 01:09:37 +00:00
										 |  |  | void getTimeString(char* out) | 
					
						
							| 
									
										
										
										
											2016-12-28 23:03:58 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  |   updateLocalTime(); | 
					
						
							| 
									
										
										
										
											2019-03-25 21:51:38 +00:00
										 |  |  |   byte hr = hour(local); | 
					
						
							|  |  |  |   if (useAMPM) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     if (hr > 11) hr -= 12; | 
					
						
							|  |  |  |     if (hr == 0) hr  = 12; | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |   sprintf(out,"%i-%i-%i, %i:%s%i:%s%i",year(local), month(local), day(local),  | 
					
						
							| 
									
										
										
										
											2019-03-25 21:51:38 +00:00
										 |  |  |                                        hr,(minute(local)<10)?"0":"",minute(local), | 
					
						
							| 
									
										
										
										
											2019-03-11 16:57:06 +00:00
										 |  |  |                                        (second(local)<10)?"0":"",second(local)); | 
					
						
							|  |  |  |   if (useAMPM) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     strcat(out,(hour(local) > 11)? " PM":" AM"); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2016-12-28 23:03:58 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-03-06 22:47:08 +00:00
										 |  |  | void setCountdown() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   countdownTime = timezones[currentTimezone]->toUTC(getUnixTime(countdownHour, countdownMin, countdownSec, countdownDay, countdownMonth, countdownYear)); | 
					
						
							|  |  |  |   if (countdownTime - now() > 0) countdownOverTriggered = false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-20 21:29:48 +00:00
										 |  |  | //returns true if countdown just over
 | 
					
						
							|  |  |  | bool checkCountdown() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2020-01-01 00:04:54 +00:00
										 |  |  |   unsigned long n = now(); | 
					
						
							| 
									
										
										
										
											2020-02-24 18:08:29 +00:00
										 |  |  |   if (countdownMode) local = countdownTime - n + utcOffsetSecs; | 
					
						
							| 
									
										
										
										
											2020-01-01 00:04:54 +00:00
										 |  |  |   if (n > countdownTime) { | 
					
						
							| 
									
										
										
										
											2020-02-24 18:08:29 +00:00
										 |  |  |     if (countdownMode) local = n - countdownTime + utcOffsetSecs; | 
					
						
							| 
									
										
										
										
											2020-01-01 00:04:54 +00:00
										 |  |  |     if (!countdownOverTriggered) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (macroCountdown != 0) applyMacro(macroCountdown); | 
					
						
							|  |  |  |       countdownOverTriggered = true; | 
					
						
							|  |  |  |       return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-02-20 21:29:48 +00:00
										 |  |  |   } | 
					
						
							|  |  |  |   return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-01-30 23:09:44 +00:00
										 |  |  | byte weekdayMondayFirst() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   byte wd = weekday(local) -1; | 
					
						
							|  |  |  |   if (wd == 0) wd = 7; | 
					
						
							|  |  |  |   return wd; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-09-22 20:49:24 +00:00
										 |  |  | void checkTimers() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (lastTimerMinute != minute(local)) //only check once a new minute begins
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     lastTimerMinute = minute(local); | 
					
						
							|  |  |  |     for (uint8_t i = 0; i < 8; i++) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |       if (timerMacro[i] != 0 | 
					
						
							|  |  |  |           && (timerHours[i] == hour(local) || timerHours[i] == 24) //if hour is set to 24, activate every hour 
 | 
					
						
							|  |  |  |           && timerMinutes[i] == minute(local) | 
					
						
							| 
									
										
										
										
											2019-01-30 23:09:44 +00:00
										 |  |  |           && (timerWeekday[i] & 0x01) //timer is enabled
 | 
					
						
							|  |  |  |           && timerWeekday[i] >> weekdayMondayFirst() & 0x01) //timer should activate at current day of week
 | 
					
						
							| 
									
										
										
										
											2018-09-22 20:49:24 +00:00
										 |  |  |       { | 
					
						
							|  |  |  |         applyMacro(timerMacro[i]); | 
					
						
							|  |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } |