diff --git a/60LED_WS2812B_NTP_Clock.ino b/60LED_WS2812B_NTP_Clock.ino index 24e863d..ec9d817 100644 --- a/60LED_WS2812B_NTP_Clock.ino +++ b/60LED_WS2812B_NTP_Clock.ino @@ -6,6 +6,15 @@ #include #include +#include +// UpdateServer includes +#ifdef ESP8266 +# include +#elif defined(ESP32) +// For ESP32 IotWebConf provides a drop-in replacement for UpdateServer. +# include +#endif + #define MOD(a,b) ((((a)%(b))+(b))%(b)) /* Model I @@ -15,7 +24,6 @@ over a 56k voltage divider . Dark (0.5MOhm) , 10Lux (5-10kOhm) */ #define LDR_PIN A6 - #define NUM_LEDS 60 #define COLOR_ORDER GRB #define DATA_PIN 17 @@ -44,7 +52,7 @@ RgbwColor blue(0, 0, colorSaturation, 0); RgbwColor realWhite(colorSaturation); RgbColor white(0, 0, 0, 40); //darkish dirt RgbwColor whiter(0, 0, 0, 120); //darkish dirt -RgbwColor white12(0,0,0,192); //darkish dirt +RgbwColor white12(0, 0, 0, 192); //darkish dirt RgbwColor black(0); RgbwColor gold(HtmlColor( 0xFFD700 ) ); RgbwColor orangered(HtmlColor( 0xFF4500 ) ); @@ -55,7 +63,7 @@ RgbwColor temp; #define MINIMAL_BRIGHTNESS 20 #define LDR_SCALE 16 #define colorSaturation 192 -//NeoPixelBrightnessBus strip(NUM_LEDS, DATA_PIN); +//NeoPixelBrightnessBus strip(NUM_LEDS, DATA_PIN); //ws2812B NeoPixelBrightnessBus strip(NUM_LEDS, DATA_PIN); RgbColor red(colorSaturation, 0, 0); RgbColor green(0, colorSaturation, 0); @@ -79,7 +87,7 @@ const int daylightOffset_sec = 3600; struct tm timeinfo; volatile int currentSec = 59; volatile int currentMin = 1; -volatile int currentHour = 1; +volatile int currentHour = 2; // variable for storing the potentiometer value volatile unsigned int ldrValue = 0; @@ -88,27 +96,65 @@ int MAX_BRIGHTNESS = 200; // WebPortal const char thingName[] = "NTP-Clock-RGBLED"; const char wifiInitialApPassword[] = "12345678"; +//ToDo add internal LED and check visibility #define STRING_LEN 63 #define NUMBER_LEN 4 // -- Configuration specific key. The value should be modified if config structure was changed. -#define CONFIG_VERSION "dem3" +#define CONFIG_VERSION "dem6" +// -- Javascript block will be added to the header. 🔒 🔓 +const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\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 = 'show'; btn.style.width = 'auto'; p.style.width = '83%'; p.parentNode.insertBefore(btn,p.nextSibling);\n\ + btn.onclick = function() { if (p.type === 'password') { p.type = 'text'; btn.value = 'hide'; } else { p.type = 'password'; btn.value = 'show'; } }\n\ + };\n\ +});\n"; +//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " "; DNSServer dnsServer; WebServer server(80); +#ifdef ESP8266 +ESP8266HTTPUpdateServer httpUpdater; +#elif defined(ESP32) +HTTPUpdateServer httpUpdater; +#endif -char ntpServerParamValue[STRING_LEN] = "pool.ntp.org"; -char maxBrightnessParamValue[NUMBER_LEN] = "100"; +char ntpServerParamValue[STRING_LEN]; +char maxBrightnessParamValue[NUMBER_LEN]; +char singleSecondParamValue[STRING_LEN]; +char allDotsOnParamValue[STRING_LEN]; +char followingHourParamValue[STRING_LEN]; IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION); +IotWebConfParameterGroup timeGroup = IotWebConfParameterGroup("Time", "Time Settings"); +IotWebConfTextParameter ntpServerParam = IotWebConfTextParameter("NTP Server", "ntpServer", ntpServerParamValue, STRING_LEN, "pool.ntp.org"); +IotWebConfParameterGroup ledGroup = IotWebConfParameterGroup("LED", "LED settings"); +IotWebConfNumberParameter maxBrightnessParam = IotWebConfNumberParameter("Max BRIGHTNESS", "max brightness", maxBrightnessParamValue, NUMBER_LEN, "200", "20..254", "min='20' max='254' step='1'"); +IotWebConfCheckboxParameter singleSecondParam = IotWebConfCheckboxParameter("Show Seconds", "singleSecond", singleSecondParamValue, STRING_LEN, true); +IotWebConfCheckboxParameter allDotsOnParam = IotWebConfCheckboxParameter("all Dots lighten on", "allDotsOn", allDotsOnParamValue, STRING_LEN, true); +IotWebConfCheckboxParameter followingHourParam = IotWebConfCheckboxParameter("following Hour", "followingHour", followingHourParamValue, STRING_LEN, true); -IotWebConfParameter ntpServerParam = IotWebConfParameter("NTP Server", "ntpServer", ntpServerParamValue, STRING_LEN, "text", "pool.ntp.org", "pool.ntp.org"); -IotWebConfSeparator separator1 = IotWebConfSeparator("LED settings"); -IotWebConfParameter maxBrightnessParam = IotWebConfParameter("Max BRIGHTNESS", "max brightness", maxBrightnessParamValue, NUMBER_LEN, "number", "20..254", "200", "min='20' max='254' step='1'"); -//IotWebConfParameter singleSecondParam = IotWebConfParameter("Show Seconds", "singleSecond", singleSecondParamValue, STRING_LEN, "text", "Yes", "Yes"); -//IotWebConfParameter allDotsOnParam = IotWebConfParameter("all Dots lighten on", "allDotsOn", allDotsOnParamValue, STRING_LEN, "text", "Yes", "Yes"); -//IotWebConfParameter followingHourParam = IotWebConfParameter("following Hour", "followingHour ", followingHourParamValue, STRING_LEN, "text", "Yes", "Yes"); - -//Version3.X.X IotWebConfCheckboxParameter checkboxParam = IotWebConfCheckboxParameter("Check param", "checkParam", checkboxParamValue, STRING_LEN, true); +class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider +{ + protected: + String getScriptInner() override + { + return + HtmlFormatProvider::getScriptInner() + + String(FPSTR(CUSTOMHTML_SCRIPT_INNER)); + } + /* + String getBodyInner() override + { + return + String(FPSTR(CUSTOMHTML_BODY_INNER)) + + HtmlFormatProvider::getBodyInner(); + } + */ +}; +// -- An instance must be created from the class defined above. +CustomHtmlFormatProvider customHtmlFormatProvider; //ToDo color Picker Second, 12Clock, Minute, Hour @@ -137,20 +183,19 @@ String printLocalTime() { /** Handle web requests to "/" path. */ -void handleRoot() { +void iotWebConfHandleRoot() { // -- Let IotWebConf test and handle captive portal requests. if (iotWebConf.handleCaptivePortal()) { // -- Captive portal request were already served. return; } - //char timeStringBuff[50]; //50 chars should be enough - //strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); String s = ""; s += ""; - s += ""; - s += "RGB LED ClockRGB LED Clock"; + //s += CUSTOMHTML_BODY_INNER; + s += "RGB LED Clock"; + s += "RGB LED Clock"; s += "

"; s += ""; s += "
Current Time:"; @@ -172,19 +217,26 @@ void handleRoot() { s += "Go to configure page to change values."; s += "\n"; - server.send(200, "text/html", s); + server.send(200, "text/html; charset=UTF-8", s); } -void configSaved() +void iotWebConfConfigSaved() { //ToDo ntpServerParamValue; MAX_BRIGHTNESS = atoi(maxBrightnessParamValue); + singleSecond = singleSecondParam.isChecked() ? true : false; + //Serial.println(singleSecondParam.isChecked() ? "true" : "false"); + allDotsOn = allDotsOnParam.isChecked() ? true : false; + //Serial.println(allDotsOnParam.isChecked() ? "true" : "false"); + followingHour = followingHourParam.isChecked() ? true : false; + //Serial.println(followingHourParam.isChecked() ? "true" : "false"); Serial.println("Configuration was updated."); } -boolean formValidator() +boolean iotWebConfFormValidator() { + Serial.println("Validating form."); boolean valid = true; @@ -199,32 +251,35 @@ boolean formValidator() { valid = false; } - return valid; } void iotWebConf_Setup() { - iotWebConf.addParameter(&ntpServerParam); - iotWebConf.addParameter(&separator1); - iotWebConf.addParameter(&maxBrightnessParam); - /* - iotWebConf.addParameter(&separator1); - iotWebConf.addParameter(&singleSecondParam); - iotWebConf.addParameter(&separator1); - iotWebConf.addParameter(&allDotsOnParam); - iotWebConf.addParameter(&separator1); - iotWebConf.addParameter(&followingHourParam); - */ - iotWebConf.setConfigSavedCallback(&configSaved); - iotWebConf.setWifiConnectionCallback(&syncNTP); //NTP call after connection established - iotWebConf.setFormValidator(&formValidator); - iotWebConf.getApTimeoutParameter()->visible = true; + timeGroup.addItem(&ntpServerParam); + + ledGroup.addItem(&maxBrightnessParam); + ledGroup.addItem(&singleSecondParam); + ledGroup.addItem(&allDotsOnParam); + ledGroup.addItem(&followingHourParam); + + iotWebConf.addParameterGroup(&timeGroup); + iotWebConf.addParameterGroup(&ledGroup); + + iotWebConf.setConfigSavedCallback(&iotWebConfConfigSaved); + 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("/", handleRoot); + server.on("/", iotWebConfHandleRoot); server.on("/config", [] { iotWebConf.handleConfig(); }); server.onNotFound([]() { iotWebConf.handleNotFound(); @@ -252,7 +307,6 @@ void syncNTP() { } void setup() { - pinMode(LDR_PIN, INPUT_PULLUP); pinMode(DATA_PIN, OUTPUT); @@ -265,7 +319,7 @@ void setup() { Serial.println("-----------------------\nSettings\n-----------------------"); Serial.printf("Show single second: \t%s\n", singleSecond ? "yes" : "no"); Serial.printf("Lighten up all LEDs: \t%s\n", allDotsOn ? "yes" : "no"); - Serial.printf("Following Hour: \t%s\n\n", followingHour? "yes" : "no"); + Serial.printf("Following Hour: \t%s\n\n", followingHour ? "yes" : "no"); strip.Begin(); strip.SetBrightness( MINIMAL_BRIGHTNESS ); diff --git a/README.md b/README.md index e69de29..19224fa 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,31 @@ +# Anleitung RGB LED Uhr + +Dies ist eine Beschreibung der RGB LED Uhr +# Schnellstart +Sobald die Uhr mit Strom versorgt wird ( 5V, 500mAh) bietet das Board (Lolin32lite) einen WiFi Accesspoint "NTP-Clock-RGBLED" an. Zu diesem kann man sich verbinden (Passwort: 12345678). Es wird unter der IP 192.168.4.1 ein Webserver angeboten, der zwei Webseiten anzeigen kann. Primär wird die Statusseite angezeigt, die alle wesentlichen Parameter auflistet: + - Aktuelle NTP Zeit + - der gewählte NTP Server + - aktuelle Helligkeit + - maximale Helligkeit + - Anzeige der einzelnen Sekunden + - Aufleuchten aller LEDs + - Folgende Stunde wie auf einer analogen Uhr + +Unten auf der Statusseite gibt es einen Link zur Konfigurationsseite +## technische Details + + - ESP32 (Lolin32 Lite) + - SK6812 or WS2812B 60 LED ring + - LDR over Resistor voltage divider + - LED ring powered over 3.3V (WS2812B) rail or USB VCC (SK6812) + - LED Output Pin 17 (requirement for NeoPixel library as I2C is used) + - LDR analog measure pin A6 + + +## ausstehende Verbesserungen + - [ ] RGB Auswahl Sekunden + - [ ] RGB Auswahl Minuten + - [ ] RGB Auswahl Stunden + - [ ] RGB Auswahl 12 Uhr + - [ ] flüssige Helligkeitsadaptierung + - [ ] Firmware Update über Upload