diff --git a/60LED_WS2812B_NTP_Clock.ino b/60LED_WS2812B_NTP_Clock.ino index c434a23..33bcb66 100644 --- a/60LED_WS2812B_NTP_Clock.ino +++ b/60LED_WS2812B_NTP_Clock.ino @@ -197,36 +197,6 @@ const char wifiInitialApPassword[] = "12345678"; // -- Configuration specific key. The value should be modified if config structure was changed. #define CONFIG_VERSION "V1.1.8" -const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\n\ - function colorCh(id)\n\ - {\n\ - var x=document.getElementById(id);\n\ - var s=document.getElementById(id + 'Val');\n\ - s.innerHTML = x.value;\n\ - }\n\n\ - document.addEventListener('DOMContentLoaded', function(event) {\n\ - let elements = document.querySelectorAll('input[type=\"password\"]');\n\ - for (let p of elements) {\n\ - let btn = document.createElement('INPUT'); btn.type = 'button'; btn.value = '🔓'; btn.style.width = 'auto'; p.style.width = '80%'; p.parentNode.insertBefore(btn,p.nextSibling);\n\ - btn.onclick = function() { if (p.type === 'password') { p.type = 'text'; btn.value = '🔒'; } else { p.type = 'password'; btn.value = '🔓'; } }\n\ - };\n\ - });\n"; - -// -- We need to create our custom HtmlFormatProvider to add some javasripts. -class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider -{ - protected: - String getScriptInner() override - { - return - HtmlFormatProvider::getScriptInner() + - String(FPSTR(CUSTOMHTML_SCRIPT_INNER)); - } - -}; -// -- Javascript block will be added to the header. -//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " "; -//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " "; DNSServer dnsServer; WebServer server(80); #ifdef ESP8266 @@ -323,216 +293,6 @@ Task brightnessFading(333, TASK_FOREVER, &brightnessFadingCallback); Task iotwebconfLoop(1000, TASK_FOREVER, &iotWebConfLoopCallback); Scheduler runner; -#ifdef ESP8266 -bool getLocalTime(struct tm * info, uint32_t ms) -{ - uint32_t start = millis(); - time_t now; - while ((millis() - start) <= ms) { - time(&now); - localtime_r(&now, info); - if (info->tm_year > (2016 - 1900)) { - return true; - } - delay(10); - } - return false; -} -#endif - -String printLocalTime() { - if (!getLocalTime(&timeinfo, 200)) { - Serial.println("Failed to obtain time"); - NTPreachable = false; - return "N/A"; - } - //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); - - char timeStringBuff[50]; //50 chars should be enough - strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); - //Serial.println(timeStringBuff); - NTPreachable = true; - return timeStringBuff; - -} - -/** - Handle web requests to "/" path. -*/ -void iotWebConfHandleRoot() { - // -- Let IotWebConf test and handle captive portal requests. - if (iotWebConf.handleCaptivePortal()) - { - // -- Captive portal request were already served. - return; - } - //char sTemp[12]; - String s = ""; - s += ""; - //s += CUSTOMHTML_BODY_INNER; - s += "RGB LED Clock"; - s += "RGB LED Clock"; - s += "

"; - s += ""; - s += "
Current Time:"; - s += printLocalTime(); - s += "
"; - s += ""; - s += ""; - s += ""; - if (singleSecond) { - s += ""; - } - if (allDotsOn) { - s += ""; - } - s += "
NTP Server:"; - s += ntpServerParam.value(); - s += "
Current Brightness value: "; - s += String(strip.GetBrightness()); - s += "
Max Brightness value: "; - s += maxBrightnessParam.value(); - s += "
Show Seconds: "; - s += (singleSecondParam.isChecked() ? "Yes" : "No"); - s += "
All Dots On: "; - s += (allDotsOnParam.isChecked() ? "Yes" : "No"); - s += "
Following Hour: "; - s += (followingHourParam.isChecked() ? "Yes" : "No"); - s += "
"; - s += "
High noon:
Hour color:
Minute color:
Seconds color:
Backlight:
Hour Marking:
"; - s += "

"; - s += "Go to configure page to change values."; - s += "\n"; - - server.send(200, "text/html; charset=UTF-8", s); -} - -void iotWebConfConfigSaved() -{ - //ToDo ntpServerParamValue; - MAX_BRIGHTNESS = maxBrightnessParam.value(); - singleSecond = singleSecondParam.isChecked() ? true : false; - //Serial.println(singleSecondParam.isChecked() ? "true" : "false"); - allDotsOn = allDotsOnParam.isChecked() ? true : false; - //Serial.println(allDotsOnParam.isChecked() ? "true" : "false"); -#if NUM_LEDS == 60 - followingHour = followingHourParam.isChecked() ? true : false; - if (!followingHour) { - hourOffset = 0 ; - } -#endif - //Serial.println(followingHourParam.isChecked() ? "true" : "false"); - - transformHtmltoStrip(&highnoonColor, (char*)&highnoonColorParam.value()); - transformHtmltoStrip(&hourColor, (char*)&hourColorParam.value()); - transformHtmltoStrip(&minuteColor, (char*)&minuteColorParam.value()); - transformHtmltoStrip(&secondsColor, (char*)&secondsColorParam.value()); - transformHtmltoStrip(&backlightColor, (char*)&backlightColorParam.value()); - transformHtmltoStrip(&hourMarkingColor, (char*)&hourMarkingColorParam.value()); - Serial.println("Configuration was updated."); -} - -void iotWebConf_Setup() { - - timeGroup.addItem(&ntpServerParam); - - ledGroup.addItem(&maxBrightnessParam); - ledGroup.addItem(&singleSecondParam); - ledGroup.addItem(&allDotsOnParam); -#if NUM_LEDS == 60 - ledGroup.addItem(&followingHourParam); -#endif - ledGroup.addItem(&hourColorParam); - ledGroup.addItem(&minuteColorParam); - ledGroup.addItem(&secondsColorParam); - ledGroup.addItem(&highnoonColorParam); - ledGroup.addItem(&backlightColorParam); - ledGroup.addItem(&hourMarkingColorParam); - - iotWebConf.addParameterGroup(&timeGroup); - iotWebConf.addParameterGroup(&ledGroup); - - iotWebConf.setConfigSavedCallback(&iotWebConfConfigSaved); - //iotWebConf.setWifiConnectionTimeoutMs(60000); - iotWebConf.setWifiConnectionCallback(&syncNTP); //NTP call after connection established - //iotWebConf.setFormValidator(&iotWebConfFormValidator); - iotWebConf.getApTimeoutParameter()->visible = true; - iotWebConf.setupUpdateServer( - [](const char* updatePath) { - httpUpdater.setup(&server, updatePath); - }, - [](const char* userName, char* password) { - httpUpdater.updateCredentials(userName, password); - }); - - iotWebConf.setHtmlFormatProvider(&customHtmlFormatProvider); - // -- Initializing the configuration. - iotWebConf.init(); - - // -- Set up required URL handlers on the web server. - server.on("/", iotWebConfHandleRoot); - server.on("/config", [] { iotWebConf.handleConfig(); }); - server.onNotFound([]() { - iotWebConf.handleNotFound(); - }); - - Serial.println("Ready."); - Serial.flush(); -} - -void syncNTP() { - if (iotWebConf.getState() == iotwebconf::OnLine) { - //init and get the time -#ifdef ESP8266 - //sntp_servermode_dhcp(0); - configTime(MYTZ, ntpServerParam.value()); -#endif -#ifdef ESP32 - configTime(0, 0, ntpServer); - // TZ string information: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html - setenv("TZ", "AEST-10", 1); - tzset(); // save the TZ variable - //setTimeZone(long offset, int daylight); - //configTime(gmtOffset_sec, daylightOffset_sec, ntpServerParamValue); -#endif - Serial.println(printLocalTime()); - if (NTPreachable) { - if (clockwiseRing) { - currentSec = timeinfo.tm_sec; - currentMin = timeinfo.tm_min; - currentHour = MOD(timeinfo.tm_hour, 12); - } - else { - //inverted logic - remaining time - currentSec = 60 - timeinfo.tm_sec; - currentMin = 60 - timeinfo.tm_min; - currentHour = 12 - MOD(timeinfo.tm_hour, 12); - } - Serial.println("NTP mapped: " + String(int(currentHour * NUM_LEDS / 12)) + ":" + String(int(currentMin * NUM_LEDS / 60)) + ":" + String(int(currentSec * NUM_LEDS / 60))); - bootAnim.disable(); - iotWebConfConfigSaved(); - ledRefresh.enable(); -#ifdef LDR_PIN - brightnessFading.enable(); -#endif - } - clockTick.enable(); //enable to check for ntp every 60 seconds - brightnessAdjustment.enable(); - } -} - void setup() { #ifdef LDR_PIN pinMode(LDR_PIN, INPUT_PULLUP); @@ -613,161 +373,3 @@ void loop() Serial.read(); */ } - -void ledRefreshCallback() { - temp = allDotsOn ? backlightColor : black; - strip.ClearTo(temp); - for (int dot = 0; dot < NUM_LEDS; dot++) { -#if NUM_LEDS == 60 - //1 dot hour marking - if (MOD(dot, 5) == 0) { - strip.SetPixelColor(dot, hourMarkingColor); - } -#endif -#if NUM_LEDS == 24 - //1 dot quarter marking - if (MOD(dot, 6) == 0) { - strip.SetPixelColor(dot, hourMarkingColor); - } -#endif - } - strip.SetPixelColor(0, highnoonColor); //define high noon - -#if NUM_LEDS == 60 - //3 dots hour - strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 - 1 + hourOffset), NUM_LEDS), hourColor); - strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 0 + hourOffset), NUM_LEDS), hourColor); - strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 1 + hourOffset), NUM_LEDS), hourColor); - if (singleSecond) { - strip.SetPixelColor(MOD(int(currentSec * NUM_LEDS / 60 + 0), NUM_LEDS), allDotsOn ? secondsColor : backlightColor); - } -#else - strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 0 + hourOffset), NUM_LEDS) , hourColor); -#endif - strip.SetPixelColor(MOD(int(currentMin * NUM_LEDS / 60 + 0), NUM_LEDS), minuteColor); - strip.Show(); -} - -// Scheduler -void clockTickCallback() { -#ifdef LDR_PIN - ldrValue = (ldrValue + analogRead(LDR_PIN)); -#endif - if (clockwiseRing) { - if (currentSec >= 60) { - currentSec = 0; - currentMin++; - if (!NTPreachable) { - syncNTP(); - } - if (currentMin >= 60) { - currentMin = 0; - currentHour++; - if (currentHour >= 12) { - currentHour = 0; - syncNTP(); - } - } - if (followingHour) { - hourOffset = int(currentMin * NUM_LEDS / 60 / 12); - //Serial.println("clockwise hourOffset: " + String(hourOffset)); - } - //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); - } - currentSec++; - - } - else { - if (currentSec < 0) { - currentSec = 59; - currentMin--; - if (!NTPreachable) { - syncNTP(); - } - if (currentMin < 0) { - currentMin = 59; - currentHour--; - if (currentHour < 0) { - currentHour = 11; - syncNTP(); - } - } - if (followingHour) { - hourOffset = 0 - int((60 - currentMin * NUM_LEDS / 60) / 12); //negative value - //Serial.println("Anticlockwise hourOffset: " + String(hourOffset)); - } - //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); - } - currentSec--; - } -} - -void bootAnimCallback() { - strip.ClearTo(black); - int tail = -1; - if (clockwiseRing) { - currentSec++; - if (currentSec >= NUM_LEDS) { - currentSec = 0; - } - } - else { - currentSec--; - tail = 1; - if (currentSec < 0) { - currentSec = NUM_LEDS - 1; - } - } - - if (iotWebConf.getState() == iotwebconf::OnLine && !NTPreachable) { - strip.ClearTo(white); - strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), black); - strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), black); - strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), black); - } - if (iotWebConf.getState() == iotwebconf::Connecting ) { - strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), white); - strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), whiter); - strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), white12); - } - if (iotWebConf.getState() == iotwebconf::ApMode ) { - strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), lightgreen); - strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), green); - strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkgreen); - } - if (iotWebConf.getState() == iotwebconf::Boot || iotWebConf.getState() == iotwebconf::NotConfigured) { - strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), orangered); - strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), red); - strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkred); - } - - strip.Show(); -} - -#ifdef LDR_PIN -void brightnessAdjustmentCallback() { - //Serial.println(ldrValue); - //brigthness begin - ldrValue = ldrValue / 10; - if (ldrValue == 0) { - targetBrightness = MAX_BRIGHTNESS; - } - else { - targetBrightness = int(MINIMAL_BRIGHTNESS + (MAX_BRIGHTNESS - MINIMAL_BRIGHTNESS) / ((ldrValue / LDR_SCALE) + 1) ); - } - //Serial.println("Brightness: " + String(strip.GetBrightness()) + "(" + String(ldrValue) + ")"); -} - -void brightnessFadingCallback() { - int currentBrightness = strip.GetBrightness(); - int diff = targetBrightness - currentBrightness; - int rate = rint(diff / 10); - strip.SetBrightness(currentBrightness + rate); - strip.Show(); - //Serial.println("Brightness: " + String(currentBrightness) + " diff " + String(rate)); -} -#endif - -void iotWebConfLoopCallback() { - iotWebConf.doLoop(); -} diff --git a/iotwebconf.ino b/iotwebconf.ino new file mode 100644 index 0000000..9a2c71a --- /dev/null +++ b/iotwebconf.ino @@ -0,0 +1,170 @@ +const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\n\ + function colorCh(id)\n\ + {\n\ + var x=document.getElementById(id);\n\ + var s=document.getElementById(id + 'Val');\n\ + s.innerHTML = x.value;\n\ + }\n\n\ + document.addEventListener('DOMContentLoaded', function(event) {\n\ + let elements = document.querySelectorAll('input[type=\"password\"]');\n\ + for (let p of elements) {\n\ + let btn = document.createElement('INPUT'); btn.type = 'button'; btn.value = '🔓'; btn.style.width = 'auto'; p.style.width = '80%'; p.parentNode.insertBefore(btn,p.nextSibling);\n\ + btn.onclick = function() { if (p.type === 'password') { p.type = 'text'; btn.value = '🔒'; } else { p.type = 'password'; btn.value = '🔓'; } }\n\ + };\n\ + });\n"; + +// -- We need to create our custom HtmlFormatProvider to add some javasripts. +class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider +{ + protected: + String getScriptInner() override + { + return + HtmlFormatProvider::getScriptInner() + + String(FPSTR(CUSTOMHTML_SCRIPT_INNER)); + } + +}; +// -- Javascript block will be added to the header. +//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " "; +//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " "; + +/** + Handle web requests to "/" path. +*/ +void iotWebConfHandleRoot() { + // -- Let IotWebConf test and handle captive portal requests. + if (iotWebConf.handleCaptivePortal()) + { + // -- Captive portal request were already served. + return; + } + //char sTemp[12]; + String s = ""; + s += ""; + //s += CUSTOMHTML_BODY_INNER; + s += "RGB LED Clock"; + s += "RGB LED Clock"; + s += "

"; + s += ""; + s += "
Current Time:"; + s += printLocalTime(); + s += "
"; + s += ""; + s += ""; + s += ""; + if (singleSecond) { + s += ""; + } + if (allDotsOn) { + s += ""; + } + s += "
NTP Server:"; + s += ntpServerParam.value(); + s += "
Current Brightness value: "; + s += String(strip.GetBrightness()); + s += "
Max Brightness value: "; + s += maxBrightnessParam.value(); + s += "
Show Seconds: "; + s += (singleSecondParam.isChecked() ? "Yes" : "No"); + s += "
All Dots On: "; + s += (allDotsOnParam.isChecked() ? "Yes" : "No"); + s += "
Following Hour: "; + s += (followingHourParam.isChecked() ? "Yes" : "No"); + s += "
"; + s += "
High noon:
Hour color:
Minute color:
Seconds color:
Backlight:
Hour Marking:
"; + s += "

"; + s += "Go to configure page to change values."; + s += "\n"; + + server.send(200, "text/html; charset=UTF-8", s); +} + +void iotWebConfConfigSaved() +{ + //ToDo ntpServerParamValue; + MAX_BRIGHTNESS = maxBrightnessParam.value(); + singleSecond = singleSecondParam.isChecked() ? true : false; + //Serial.println(singleSecondParam.isChecked() ? "true" : "false"); + allDotsOn = allDotsOnParam.isChecked() ? true : false; + //Serial.println(allDotsOnParam.isChecked() ? "true" : "false"); +#if NUM_LEDS == 60 + followingHour = followingHourParam.isChecked() ? true : false; + if (!followingHour) { + hourOffset = 0 ; + } +#endif + //Serial.println(followingHourParam.isChecked() ? "true" : "false"); + + transformHtmltoStrip(&highnoonColor, (char*)&highnoonColorParam.value()); + transformHtmltoStrip(&hourColor, (char*)&hourColorParam.value()); + transformHtmltoStrip(&minuteColor, (char*)&minuteColorParam.value()); + transformHtmltoStrip(&secondsColor, (char*)&secondsColorParam.value()); + transformHtmltoStrip(&backlightColor, (char*)&backlightColorParam.value()); + transformHtmltoStrip(&hourMarkingColor, (char*)&hourMarkingColorParam.value()); + Serial.println("Configuration was updated."); +} + +void iotWebConf_Setup() { + + timeGroup.addItem(&ntpServerParam); + + ledGroup.addItem(&maxBrightnessParam); + ledGroup.addItem(&singleSecondParam); + ledGroup.addItem(&allDotsOnParam); +#if NUM_LEDS == 60 + ledGroup.addItem(&followingHourParam); +#endif + ledGroup.addItem(&hourColorParam); + ledGroup.addItem(&minuteColorParam); + ledGroup.addItem(&secondsColorParam); + ledGroup.addItem(&highnoonColorParam); + ledGroup.addItem(&backlightColorParam); + ledGroup.addItem(&hourMarkingColorParam); + + iotWebConf.addParameterGroup(&timeGroup); + iotWebConf.addParameterGroup(&ledGroup); + + iotWebConf.setConfigSavedCallback(&iotWebConfConfigSaved); + //iotWebConf.setWifiConnectionTimeoutMs(60000); + iotWebConf.setWifiConnectionCallback(&syncNTP); //NTP call after connection established + //iotWebConf.setFormValidator(&iotWebConfFormValidator); + iotWebConf.getApTimeoutParameter()->visible = true; + iotWebConf.setupUpdateServer( + [](const char* updatePath) { + httpUpdater.setup(&server, updatePath); + }, + [](const char* userName, char* password) { + httpUpdater.updateCredentials(userName, password); + }); + + iotWebConf.setHtmlFormatProvider(&customHtmlFormatProvider); + // -- Initializing the configuration. + iotWebConf.init(); + + // -- Set up required URL handlers on the web server. + server.on("/", iotWebConfHandleRoot); + server.on("/config", [] { iotWebConf.handleConfig(); }); + server.onNotFound([]() { + iotWebConf.handleNotFound(); + }); + + Serial.println("Ready."); + Serial.flush(); +} + +void iotWebConfLoopCallback() { + iotWebConf.doLoop(); +} diff --git a/ledcontrol.ino b/ledcontrol.ino new file mode 100644 index 0000000..a4ec804 --- /dev/null +++ b/ledcontrol.ino @@ -0,0 +1,100 @@ + +void ledRefreshCallback() { + temp = allDotsOn ? backlightColor : black; + strip.ClearTo(temp); + for (int dot = 0; dot < NUM_LEDS; dot++) { +#if NUM_LEDS == 60 + //1 dot hour marking + if (MOD(dot, 5) == 0) { + strip.SetPixelColor(dot, hourMarkingColor); + } +#endif +#if NUM_LEDS == 24 + //1 dot quarter marking + if (MOD(dot, 6) == 0) { + strip.SetPixelColor(dot, hourMarkingColor); + } +#endif + } + strip.SetPixelColor(0, highnoonColor); //define high noon + +#if NUM_LEDS == 60 + //3 dots hour + strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 - 1 + hourOffset), NUM_LEDS), hourColor); + strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 0 + hourOffset), NUM_LEDS), hourColor); + strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 1 + hourOffset), NUM_LEDS), hourColor); + if (singleSecond) { + strip.SetPixelColor(MOD(int(currentSec * NUM_LEDS / 60 + 0), NUM_LEDS), allDotsOn ? secondsColor : backlightColor); + } +#else + strip.SetPixelColor(MOD(int(currentHour * NUM_LEDS / 12 + 0 + hourOffset), NUM_LEDS) , hourColor); +#endif + strip.SetPixelColor(MOD(int(currentMin * NUM_LEDS / 60 + 0), NUM_LEDS), minuteColor); + strip.Show(); +} + +void bootAnimCallback() { + strip.ClearTo(black); + int tail = -1; + if (clockwiseRing) { + currentSec++; + if (currentSec >= NUM_LEDS) { + currentSec = 0; + } + } + else { + currentSec--; + tail = 1; + if (currentSec < 0) { + currentSec = NUM_LEDS - 1; + } + } + + if (iotWebConf.getState() == iotwebconf::OnLine && !NTPreachable) { + strip.ClearTo(white); + strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), black); + strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), black); + strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), black); + } + if (iotWebConf.getState() == iotwebconf::Connecting ) { + strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), white); + strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), whiter); + strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), white12); + } + if (iotWebConf.getState() == iotwebconf::ApMode ) { + strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), lightgreen); + strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), green); + strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkgreen); + } + if (iotWebConf.getState() == iotwebconf::Boot || iotWebConf.getState() == iotwebconf::NotConfigured) { + strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), orangered); + strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), red); + strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkred); + } + + strip.Show(); +} + +#ifdef LDR_PIN +void brightnessAdjustmentCallback() { + //Serial.println(ldrValue); + //brigthness begin + ldrValue = ldrValue / 10; + if (ldrValue == 0) { + targetBrightness = MAX_BRIGHTNESS; + } + else { + targetBrightness = int(MINIMAL_BRIGHTNESS + (MAX_BRIGHTNESS - MINIMAL_BRIGHTNESS) / ((ldrValue / LDR_SCALE) + 1) ); + } + //Serial.println("Brightness: " + String(strip.GetBrightness()) + "(" + String(ldrValue) + ")"); +} + +void brightnessFadingCallback() { + int currentBrightness = strip.GetBrightness(); + int diff = targetBrightness - currentBrightness; + int rate = rint(diff / 10); + strip.SetBrightness(currentBrightness + rate); + strip.Show(); + //Serial.println("Brightness: " + String(currentBrightness) + " diff " + String(rate)); +} +#endif diff --git a/realtime.ino b/realtime.ino new file mode 100644 index 0000000..9d2f47d --- /dev/null +++ b/realtime.ino @@ -0,0 +1,129 @@ + +#ifdef ESP8266 +bool getLocalTime(struct tm * info, uint32_t ms) +{ + uint32_t start = millis(); + time_t now; + while ((millis() - start) <= ms) { + time(&now); + localtime_r(&now, info); + if (info->tm_year > (2016 - 1900)) { + return true; + } + delay(10); + } + return false; +} +#endif + +String printLocalTime() { + if (!getLocalTime(&timeinfo, 200)) { + Serial.println("Failed to obtain time"); + NTPreachable = false; + return "N/A"; + } + //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); + + char timeStringBuff[50]; //50 chars should be enough + strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); + //Serial.println(timeStringBuff); + NTPreachable = true; + return timeStringBuff; + +} + + +void syncNTP() { + if (iotWebConf.getState() == iotwebconf::OnLine) { + //init and get the time +#ifdef ESP8266 + //sntp_servermode_dhcp(0); + configTime(MYTZ, ntpServerParam.value()); +#endif +#ifdef ESP32 + configTime(0, 0, ntpServer); + // TZ string information: https://www.gnu.org/software/libc/manual/html_node/TZ-Variable.html + setenv("TZ", "AEST-10", 1); + tzset(); // save the TZ variable + //setTimeZone(long offset, int daylight); + //configTime(gmtOffset_sec, daylightOffset_sec, ntpServerParamValue); +#endif + Serial.println(printLocalTime()); + if (NTPreachable) { + if (clockwiseRing) { + currentSec = timeinfo.tm_sec; + currentMin = timeinfo.tm_min; + currentHour = MOD(timeinfo.tm_hour, 12); + } + else { + //inverted logic - remaining time + currentSec = 60 - timeinfo.tm_sec; + currentMin = 60 - timeinfo.tm_min; + currentHour = 12 - MOD(timeinfo.tm_hour, 12); + } + Serial.println("NTP mapped: " + String(int(currentHour * NUM_LEDS / 12)) + ":" + String(int(currentMin * NUM_LEDS / 60)) + ":" + String(int(currentSec * NUM_LEDS / 60))); + bootAnim.disable(); + iotWebConfConfigSaved(); + ledRefresh.enable(); +#ifdef LDR_PIN + brightnessFading.enable(); +#endif + } + clockTick.enable(); //enable to check for ntp every 60 seconds + brightnessAdjustment.enable(); + } +} + +// Scheduler +void clockTickCallback() { +#ifdef LDR_PIN + ldrValue = (ldrValue + analogRead(LDR_PIN)); +#endif + if (clockwiseRing) { + if (currentSec >= 60) { + currentSec = 0; + currentMin++; + if (!NTPreachable) { + syncNTP(); + } + if (currentMin >= 60) { + currentMin = 0; + currentHour++; + if (currentHour >= 12) { + currentHour = 0; + syncNTP(); + } + } + if (followingHour) { + hourOffset = int(currentMin * NUM_LEDS / 60 / 12); + //Serial.println("clockwise hourOffset: " + String(hourOffset)); + } + //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); + } + currentSec++; + + } + else { + if (currentSec < 0) { + currentSec = 59; + currentMin--; + if (!NTPreachable) { + syncNTP(); + } + if (currentMin < 0) { + currentMin = 59; + currentHour--; + if (currentHour < 0) { + currentHour = 11; + syncNTP(); + } + } + if (followingHour) { + hourOffset = 0 - int((60 - currentMin * NUM_LEDS / 60) / 12); //negative value + //Serial.println("Anticlockwise hourOffset: " + String(hourOffset)); + } + //Serial.println(String(interruptCounter) + " | Ring Index: " + String(currentHour / (12 / NUM_LEDS)) + ":" + String(currentMin / (60 / NUM_LEDS)) + ":" + String(currentSec / (60 / NUM_LEDS))); + } + currentSec--; + } +}