diff --git a/Time.cpp b/Time.cpp index 5ca1327..0d4ba04 100644 --- a/Time.cpp +++ b/Time.cpp @@ -240,13 +240,13 @@ static uint32_t nextSyncTime = 0; static timeStatus_t Status = timeNotSet; getExternalTime getTimePtr; // pointer to external sync function +getExternalTime getDaylightSavingPtr = 0; // pointer to external sync function //setExternalTime setTimePtr; // not used in this version #ifdef TIME_DRIFT_INFO // define this to get drift data time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync #endif - time_t now() { // calculate number of seconds passed since last call to now() while (millis() - prevMillis >= 1000) { @@ -262,6 +262,12 @@ time_t now() { time_t t = getTimePtr(); if (t != 0) { setTime(t); + + if (getDaylightSavingPtr!=0) { + t+=getDaylightSavingPtr(); + setTime(t); + } + } else { nextSyncTime = sysTime + syncInterval; Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync; @@ -315,6 +321,10 @@ void setSyncProvider( getExternalTime getTimeFunction){ now(); // this will sync the clock } +void setDaylightsavingProvider( getExternalTime getTimeFunction){ + getDaylightSavingPtr = getTimeFunction; +} + void setSyncInterval(time_t interval){ // set the number of seconds between re-sync syncInterval = (uint32_t)interval; nextSyncTime = sysTime + syncInterval; diff --git a/TimeLib.h b/TimeLib.h index ddb1668..e001796 100644 --- a/TimeLib.h +++ b/TimeLib.h @@ -133,6 +133,7 @@ char* dayShortStr(uint8_t day); timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider void setSyncInterval(time_t interval); // set the number of seconds between re-sync +void setDaylightsavingProvider( getExternalTime getTimeFunction); // for adding daylight saving /* low level functions to convert to and from system time */ void breakTime(time_t time, tmElements_t &tm); // break time_t into elements diff --git a/examples/TimeNTP_ESP8266WiFiDayLight/TimeNTP_ESP8266WiFiDayLight.ino b/examples/TimeNTP_ESP8266WiFiDayLight/TimeNTP_ESP8266WiFiDayLight.ino new file mode 100644 index 0000000..8096ce0 --- /dev/null +++ b/examples/TimeNTP_ESP8266WiFiDayLight/TimeNTP_ESP8266WiFiDayLight.ino @@ -0,0 +1,180 @@ +/* + * TimeNTP_ESP8266WiFi.ino + * Example showing time sync to NTP time source + * + * This sketch uses the ESP8266WiFi library + */ + +#include +#include +#include + +const char ssid[] = "*************"; // your network SSID (name) +const char pass[] = "********"; // your network password + +// NTP Servers: +static const char ntpServerName[] = "us.pool.ntp.org"; +//static const char ntpServerName[] = "time.nist.gov"; +//static const char ntpServerName[] = "time-a.timefreq.bldrdoc.gov"; +//static const char ntpServerName[] = "time-b.timefreq.bldrdoc.gov"; +//static const char ntpServerName[] = "time-c.timefreq.bldrdoc.gov"; + +const int timeZone = 1; // Central European Time +//const int timeZone = -5; // Eastern Standard Time (USA) +//const int timeZone = -4; // Eastern Daylight Time (USA) +//const int timeZone = -8; // Pacific Standard Time (USA) +//const int timeZone = -7; // Pacific Daylight Time (USA) + + +WiFiUDP Udp; +unsigned int localPort = 8888; // local port to listen for UDP packets + +time_t getNtpTime(); +void digitalClockDisplay(); +void printDigits(int digits); +void sendNTPpacket(IPAddress &address); + +void setup() +{ + Serial.begin(9600); + while (!Serial) ; // Needed for Leonardo only + delay(250); + Serial.println("TimeNTP Example"); + Serial.print("Connecting to "); + Serial.println(ssid); + WiFi.begin(ssid, pass); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.print("IP number assigned by DHCP is "); + Serial.println(WiFi.localIP()); + Serial.println("Starting UDP"); + Udp.begin(localPort); + Serial.print("Local port: "); + Serial.println(Udp.localPort()); + Serial.println("waiting for sync"); + setDaylightsavingProvider(isgermansommerzeit); + setSyncProvider(getNtpTime); + setSyncInterval(300); +} + +time_t prevDisplay = 0; // when the digital clock was displayed + +void loop() +{ + if (timeStatus() != timeNotSet) { + if (now() != prevDisplay) { //update the display only if time has changed + prevDisplay = now(); + digitalClockDisplay(); + } + } +} + +void digitalClockDisplay() +{ + // digital clock display of the time + Serial.print(hour()); + printDigits(minute()); + printDigits(second()); + Serial.print(" "); + Serial.print(day()); + Serial.print("."); + Serial.print(month()); + Serial.print("."); + Serial.print(year()); + Serial.println(); +} + +void printDigits(int digits) +{ + // utility for digital clock display: prints preceding colon and leading 0 + Serial.print(":"); + if (digits < 10) + Serial.print('0'); + Serial.print(digits); +} + +/*-------- NTP code ----------*/ + +const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message +byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets + +time_t getNtpTime() +{ + IPAddress ntpServerIP; // NTP server's ip address + + while (Udp.parsePacket() > 0) ; // discard any previously received packets + Serial.println("Transmit NTP Request"); + // get a random server from the pool + WiFi.hostByName(ntpServerName, ntpServerIP); + Serial.print(ntpServerName); + Serial.print(": "); + Serial.println(ntpServerIP); + sendNTPpacket(ntpServerIP); + uint32_t beginWait = millis(); + while (millis() - beginWait < 1500) { + int size = Udp.parsePacket(); + if (size >= NTP_PACKET_SIZE) { + Serial.println("Receive NTP Response"); + Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer + unsigned long secsSince1900; + // convert four bytes starting at location 40 to a long integer + secsSince1900 = (unsigned long)packetBuffer[40] << 24; + secsSince1900 |= (unsigned long)packetBuffer[41] << 16; + secsSince1900 |= (unsigned long)packetBuffer[42] << 8; + secsSince1900 |= (unsigned long)packetBuffer[43]; + return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR; + } + } + Serial.println("No NTP Response :-("); + return 0; // return 0 if unable to get the time +} + +time_t isgermansommerzeit() { + // http://www.mikrocontroller.net/topic/25069 + // http://www.mikrocontroller.net/attachment/8391/TIME.C + + // volle Monate mit Winterzeit + if ( (month() < 3) || (month() > 10) ) { // month 1, 2, 11, 12 + return 0; // -> Winterzeit + } + + byte wday = weekday(); + + if (day() - wday >= 25 && (wday || hour() >= 2) ) { // after last Sunday 2:00 + if ( month() == 10 ) // October -> Winter + return 0; + } else { // before last Sunday 2:00 + if ( month() == 3 ) // March -> Winter + return 0; + } + + return 60*60; +} + +// send an NTP request to the time server at the given address +void sendNTPpacket(IPAddress &address) +{ + // set all bytes in the buffer to 0 + memset(packetBuffer, 0, NTP_PACKET_SIZE); + // Initialize values needed to form NTP request + // (see URL above for details on the packets) + packetBuffer[0] = 0b11100011; // LI, Version, Mode + packetBuffer[1] = 0; // Stratum, or type of clock + packetBuffer[2] = 6; // Polling Interval + packetBuffer[3] = 0xEC; // Peer Clock Precision + // 8 bytes of zero for Root Delay & Root Dispersion + packetBuffer[12] = 49; + packetBuffer[13] = 0x4E; + packetBuffer[14] = 49; + packetBuffer[15] = 52; + // all NTP fields have been given values, now + // you can send a packet requesting a timestamp: + Udp.beginPacket(address, 123); //NTP requests are to port 123 + Udp.write(packetBuffer, NTP_PACKET_SIZE); + Udp.endPacket(); +} +