#include "led_clock_time.hpp" TimeChangeRule CEST = {"CEST", Last, Sun, Mar, 2, 120}; // Central European Summer Time TimeChangeRule CET = {"CET ", Last, Sun, Oct, 3, 60}; // Central European Standard Time Timezone CE(CEST, CET); void led_clock_time::init(bool debug) { Serial.println(); http = new HTTPClient(); timedebug = debug; Serial.println("Try to connect to wifi first time ... maybe captive portal will b started ..."); connectWifi(); // isconnected should be true after here if not in debug mode ... Serial.printf("Connection status : %s\n", isconnected == true?"connected":"not connected"); wasalreadyconnected = isconnected; rtc_ready = rtc_init(); // at least timeisvalid should be true after here ... if(timeisvalid == false) { if(isconnected == false) { //nothing to show ... keep waiting forever in the captive portal ... captivepotal_timeout = 0; Serial.println("RTC time is not valid and there is no connection to Wifi - will go into cpative portal mode and wait for valid config. Please connect via Wifi to 'BlueLedclock'."); connectWifi(); } } } bool led_clock_time::rtc_init() { bool rc = true; Rtc = new RtcDS3231(Wire); Rtc->Begin(); RtcDateTime compiled = RtcDateTime(__DATE__, __TIME__); Serial.println(); Serial.println("RTC init ..."); if (!Rtc->IsDateTimeValid()) { if (Rtc->LastError() != 0) { Serial.print("RTC communications error = "); Serial.println(Rtc->LastError()); return(false); } else { Serial.println("RTC lost confidence in the DateTime!"); if(false == rtc_settime(compiled)) { return(false); } } } if (!Rtc->GetIsRunning()) { Serial.println("RTC was not actively running, starting now"); Rtc->SetIsRunning(true); } Serial.println("Check RTC time - set to accurate time if needed and possible."); if(false == syncTime()) { RtcDateTime now = Rtc->GetDateTime(); if (now.TotalSeconds() < compiled.TotalSeconds()) { rc = rtc_settime(compiled); } } Rtc->Enable32kHzPin(false); Rtc->SetSquareWavePin(DS3231SquareWavePin_ModeNone); rc = rtc_gettime(); Serial.printf("RTC time is: %d:%d:%d . Valid time bit is set to '%s'\n", int_hour, int_minute, int_second, timeisvalid==true?"true":"false"); if(rc == false) { Serial.println("RTC setup finished with a failure! Time couldn't set to actual value!"); } else { Serial.println("RTC setup finished with success!"); } return(rc); } bool led_clock_time::rtc_settime(RtcDateTime newtime) { bool rc = false; if((millis() - lastwrittentortc > WAITBEFOREWRITERTCAGAIN_MS) || (lastwrittentortc ==0)) { lastwrittentortc = millis(); //Serial.println("Try to write time to RTC."); Rtc->SetDateTime(newtime); RtcDateTime gettime = Rtc->GetDateTime(); if (newtime.TotalSeconds() <= gettime.TotalSeconds()) { rc = true; } else { Serial.printf("Current RTC read time (%d) is smaller than the provided time (%d) that was written before to RTC. This is not correct!", gettime.TotalSeconds(), newtime.TotalSeconds()); } } else { rc = true; } if(rc == false) { Serial.println("RTC set time finished with a failure! Time couldn't set to actual value!"); timeisvalid = false; } else { timeisvalid = true; } return(rc); } bool led_clock_time::gettime(uint32_t *hour, uint32_t *minute, uint32_t *second) { if(0 == timedebug) { syncTime(); rtc_gettime(); } else { dbg_gettime(); } *hour = int_hour; *second = int_second; *minute = int_minute; return(timeisvalid); } bool led_clock_time::rtc_gettime(void) { bool rc = true; RtcDateTime now = Rtc->GetDateTime(); int_second = now.Second(); int_minute = now.Minute(); int_hour = now.Hour(); if((int_hour == 0) && (int_minute == 0) && (int_second == 0) && (now.Year() == 2000)) { rc = false; timeisvalid = false; Serial.printf("RTC is stucked at %02d:%02d:%02d %02d.%02d.%04d this is a failure! Time couldn't set to actual value!\n", int_hour, int_minute, int_second, now.Day(), now.Month(), now.Year()); } return(rc); } void led_clock_time::dbg_gettime(void) { timeisvalid = 0; timesynced = false; int_second = int_second + 1; if(int_second > 59) { int_second = 0; int_minute++; if(int_minute > 59) { int_minute = 0; int_hour++; if(int_hour > 11) { int_hour = 0; } } } } bool led_clock_time::connectWifi() { if(timedebug == false) { if ((WiFi.status() != WL_CONNECTED)) { isconnected = false; Serial.printf("Looking for Wifi: captive portal is open for about %ld seconds.\n",captivepotal_timeout ); wifiManager.setDebugOutput(false); //sets timeout until configuration portal gets turned off wifiManager.setTimeout(captivepotal_timeout); //in seconds captivepotal_timeout = 30; //and goes into a blocking loop awaiting configuration if(false == wifiManager.autoConnect("BlueLedClock")) { Serial.println("Failed to connect to WiFi and hit timeout ... (reset clock to retry). "); } else { Serial.println("Connect to WiFi. "); isconnected = true; } } else { isconnected = true; } } else { isconnected = false; } return isconnected; } bool led_clock_time::isConnectedToWifi() { if ((WiFi.status() != WL_CONNECTED)) { if(wasalreadyconnected == true) { connectWifi(); } else { isconnected = false; } } else{ isconnected = true; } return isconnected; } bool led_clock_time::isTimenSynced() { return timesynced; } bool led_clock_time::syncTime() { TimeChangeRule *tcr; // pointer to the time change rule, use to get the TZ abbrev int httpCode = -1; if((timelastsync == 0) || (((millis()/1000)- timelastsync) > NTP_SYNC_CYCLE_SECS)) { if(true == isConnectedToWifi()) { http->begin(TIMEURL); // start connection and send HTTP header httpCode = http->GET(); // httpCode will be negative on error if (httpCode == HTTP_CODE_OK) { String epoch_str = http->getString(); epoch = epoch_str.toInt(); epoch = CE.toLocal(epoch, &tcr); if(epoch > 0) { struct tm * timeinfo = localtime(&epoch); char timestr[9] = ""; char datestr[12] = ""; sprintf(timestr, "%02d:%02d:%02d",timeinfo->tm_hour, timeinfo->tm_min, timeinfo->tm_sec); sprintf(datestr, "%s %d %d", MONTH_STR[timeinfo->tm_mon].c_str(), timeinfo->tm_mday, 1900+timeinfo->tm_year); RtcDateTime rtctime = RtcDateTime(datestr, timestr); if(rtc_settime(rtctime) == true) { timelastsync = millis()/1000; //Serial.printf("Synced time: %s %s\n", datestr, timestr ); timesynced = true; } } } } } if( HTTP_CODE_OK != httpCode ) { if(((millis()/1000)- timelastsync) > (NTP_SYNC_MAX_TRIES * NTP_SYNC_CYCLE_SECS)) timesynced = false; } return(timesynced); }