Merge pull request 'colorPicker' (#7) from colorPicker into master

Reviewed-on: #7
This commit is contained in:
coelner 2021-05-06 21:20:19 +02:00
commit 00eb84389b
4 changed files with 361 additions and 122 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
*.bin

View File

@ -1,6 +1,4 @@
#include <WiFi.h>
#include "time.h" #include "time.h"
#include <TaskScheduler.h> #include <TaskScheduler.h>
@ -9,8 +7,17 @@
#include <IotWebConfUsing.h> #include <IotWebConfUsing.h>
// UpdateServer includes // UpdateServer includes
#ifdef ESP8266 #ifdef ESP8266
#include <ESP8266WiFi.h>
# include <ESP8266HTTPUpdateServer.h> # include <ESP8266HTTPUpdateServer.h>
#include <TZ.h>
#define MYTZ TZ_Europe_Berlin
#include <coredecls.h> // settimeofday_cb()
//#include <Schedule.h>
//#include <PolledTimeout.h>
#include <sys/time.h> // struct timeval
#include <sntp.h> // sntp_servermode_dhcp()
#elif defined(ESP32) #elif defined(ESP32)
#include <WiFi.h>
// For ESP32 IotWebConf provides a drop-in replacement for UpdateServer. // For ESP32 IotWebConf provides a drop-in replacement for UpdateServer.
# include <IotWebConfESP32HTTPUpdateServer.h> # include <IotWebConfESP32HTTPUpdateServer.h>
#endif #endif
@ -22,14 +29,23 @@
Light Resistance (at 10 Lux): 5-10 Kohm Light Resistance (at 10 Lux): 5-10 Kohm
Dark Resistance: 0.5 Mohm Dark Resistance: 0.5 Mohm
over a 56k voltage divider . Dark (0.5MOhm) , 10Lux (5-10kOhm) over a 56k voltage divider . Dark (0.5MOhm) , 10Lux (5-10kOhm)
-----------------
ESP8266 24LED
5V--10k-+-LDR--GND -ADC
- 150k--220k-+-100k--GND
*/ */
#ifdef ESP8266
#define LDR_PIN A0
#define IOTWEBCONF_DEBUG_DISABLED
#define DATA_PIN D7 //DMA RDX0/GPIO3 | Uart1 TXD1/GPIO2 | UART0 GPIO1
#elif defined(ESP32)
#define LDR_PIN A6 #define LDR_PIN A6
#define NUM_LEDS 60
#define COLOR_ORDER GRB
#define DATA_PIN 17 #define DATA_PIN 17
#endif
#define NUM_LEDS 60
#define SERIAL_BAUD 115200 #define SERIAL_BAUD 115200
//#define RGBW #define RGBW
volatile bool singleSecond = true; //show seconds volatile bool singleSecond = true; //show seconds
volatile bool allDotsOn = true; //lighten up all leds volatile bool allDotsOn = true; //lighten up all leds
volatile bool followingHour = true; //move hour like an analog one volatile bool followingHour = true; //move hour like an analog one
@ -44,8 +60,14 @@ void brightnessAdjustmentCallback();
#define MINIMAL_BRIGHTNESS 5 #define MINIMAL_BRIGHTNESS 5
#define LDR_SCALE 16 #define LDR_SCALE 16
#define colorSaturation 255 #define colorSaturation 255
//NeoPixelBrightnessBus<NeoGrbwFeature, Neo800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //SK6812 #ifdef ESP8266
NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //NeoPixelBrightnessBus<NeoGrbwFeature, Neo800KbpsMethod> strip(NUM_LEDS);//RDX0 GPIO3
//NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266AsyncUart0Sk6812Method> strip(NUM_LEDS);
//NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266Uart0Sk6812Method> strip(NUM_LEDS);
NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp8266BitBang800KbpsMethod> strip(NUM_LEDS, DATA_PIN);
#elif defined(ESP32)
NeoPixelBrightnessBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //ESP32
#endif
RgbwColor red(colorSaturation, 0, 0, 0); RgbwColor red(colorSaturation, 0, 0, 0);
RgbwColor green(0, colorSaturation, 0, 0); RgbwColor green(0, colorSaturation, 0, 0);
RgbwColor blue(0, 0, colorSaturation, 0); RgbwColor blue(0, 0, colorSaturation, 0);
@ -57,16 +79,55 @@ RgbwColor black(0);
RgbwColor gold(HtmlColor( 0xFFD700 ) ); RgbwColor gold(HtmlColor( 0xFFD700 ) );
RgbwColor orangered(HtmlColor( 0xFF4500 ) ); RgbwColor orangered(HtmlColor( 0xFF4500 ) );
RgbwColor orange(HtmlColor( 0xFFA500 ) ); RgbwColor orange(HtmlColor( 0xFFA500 ) );
RgbwColor darkred(HtmlColor(0x800000)); RgbwColor darkred(HtmlColor( 0x800000) );
RgbwColor darkgreen(HtmlColor(0x006400)); RgbwColor darkgreen(HtmlColor( 0x006400) );
RgbwColor lightgreen(HtmlColor(0x90ee90)); RgbwColor lightgreen(HtmlColor( 0x30ee30) );
RgbwColor temp; RgbwColor temp;
RgbwColor secondsColor = black;
RgbwColor minuteColor = darkred;
RgbwColor hourColor = gold;
RgbwColor highnoonColor = white12;
RgbwColor backlightColor = white;
RgbwColor hourMarkingColor = whiter;
void transformtoHtmlColor (char* sOutput, RgbwColor* inputColor) {
//Serial.printf("InputColor: R:%i G:%i B:%i W:%i\n", inputColor.R, inputColor.G, inputColor.B, inputColor.W);
if (inputColor->IsMonotone())
{
//Serial.print("White: "); Serial.println(inputColor->W);
HtmlColor(RgbColor(inputColor->W, inputColor->W, inputColor->W)).ToNumericalString(sOutput, 12);
//Serial.println((char*)sOutput);
}
else {
//Serial.print("Color: "); Serial.print(inputColor->R); Serial.print(inputColor->G); Serial.println(inputColor->B);
HtmlColor(RgbColor(inputColor->R, inputColor->G, inputColor->B)).ToNumericalString(sOutput, 12);
//Serial.println((char*)sOutput);
}
}
void transformHtmltoStrip(RgbwColor* outputColor, char* sInput) {
HtmlColor htmlTemp;
//Serial.print("HtmltoStrip ");
//Serial.println((char*)sInput);
htmlTemp.Parse<HtmlColorNames>( sInput );
RgbwColor stripColor( htmlTemp );
//Serial.printf("StripColor: R:%i G:%i B:%i W:%i\n", stripColor.R, stripColor.G, stripColor.B, stripColor.W);
memcpy(outputColor, &stripColor, sizeof(stripColor));
}
#else #else
#define MINIMAL_BRIGHTNESS 20 #define MINIMAL_BRIGHTNESS 20
#define LDR_SCALE 16 #define LDR_SCALE 16
#define colorSaturation 192 #define colorSaturation 192
//NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //ws2812B #ifdef ESP8266
NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //NeoPixelBrightnessBus<NeoGrbFeature, Neo800KbpsMethod> strip(NUM_LEDS);//RDX0 GPIO3 Broken due IoTWebConf
NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266Uart1800KbpsMethod> strip(NUM_LEDS);
//NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp8266BitBang800KbpsMethod> strip(NUM_LEDS, DATA_PIN);
#elif defined(ESP32)
NeoPixelBrightnessBus<NeoGrbFeature, NeoEsp32I2s1800KbpsMethod> strip(NUM_LEDS, DATA_PIN); //ESP32
#endif
RgbColor red(colorSaturation, 0, 0); RgbColor red(colorSaturation, 0, 0);
RgbColor green(0, colorSaturation, 0); RgbColor green(0, colorSaturation, 0);
RgbColor blue(0, 0, colorSaturation); RgbColor blue(0, 0, colorSaturation);
@ -75,70 +136,115 @@ RgbColor black(0);
RgbColor white(30, 40, 35); //darkish dirt RgbColor white(30, 40, 35); //darkish dirt
RgbColor whiter(120, 120, 120); //darkish dirt RgbColor whiter(120, 120, 120); //darkish dirt
RgbColor white12(255, 255, 255); //darkish dirt RgbColor white12(255, 255, 255); //darkish dirt
RgbColor gold(HtmlColor( 0xFFD700 ) ); RgbColor gold(HtmlColor( 0xFFD700 ));
RgbColor orangered(HtmlColor( 0xFF4500 ) ); RgbColor orangered(HtmlColor( 0xFF4500 ));
RgbColor orange(HtmlColor( 0xFFA500 ) ); RgbColor orange(HtmlColor( 0xFFA500 ));
RgbColor darkred(HtmlColor(0x800000)); RgbColor darkred(HtmlColor( 0x800000 ));
RgbColor darkgreen(HtmlColor(0x006400)); RgbColor darkgreen(HtmlColor( 0x006400 ));
RgbColor lightgreen(HtmlColor(0x90ee90)); RgbColor lightgreen(HtmlColor( 0x90ee90 ));
RgbColor temp; RgbColor temp;
RgbColor secondsColor = black;
RgbColor minuteColor = darkred;
RgbColor hourColor = gold;
RgbColor highnoonColor = white12;
RgbColor backlightColor = white;
RgbColor hourMarkingColor = whiter;
void transformtoHtmlColor (char* sOutput, RgbColor* inputColor) {
HtmlColor(RgbColor(inputColor->R, inputColor->G, inputColor->B)).ToNumericalString(sOutput, 12);
}
void transformHtmltoStrip(RgbColor* outputColor, char* sInput) {
HtmlColor htmlTemp;
//Serial.print("HtmltoStrip ");
//Serial.println((char*)sInput);
htmlTemp.Parse<HtmlColorNames>( sInput );
RgbColor stripColor( htmlTemp );
//Serial.printf("StripColor: R:%i G:%i B:%i W:%i\n", stripColor.R, stripColor.G, stripColor.B, stripColor.W);
memcpy(outputColor, &stripColor, sizeof(stripColor));
}
#endif #endif
//NTP handler
//const char* ntpServer = "pool.ntp.org"; //const char* ntpServer = "pool.ntp.org";
const long gmtOffset_sec = 3600; //ToDo changable from user const long gmtOffset_sec = 3600; //ToDo changable from user
const int daylightOffset_sec = 3600; const int daylightOffset_sec = 3600;
struct tm timeinfo; struct tm timeinfo;
volatile int currentSec = 59; volatile int currentSec = 59;
volatile int currentMin = 1; volatile int currentMin = 1;
volatile int currentHour = 2; volatile int currentHour = 2;
volatile bool NTPreachable = false;
#ifdef LDR_PIN
// variable for storing the potentiometer value // variable for storing the potentiometer value
volatile unsigned int ldrValue = 0; volatile unsigned int ldrValue = 0;
#endif
volatile int MAX_BRIGHTNESS = 200; volatile int MAX_BRIGHTNESS = 200;
// WebPortal // WebPortal
const char thingName[] = "NTP-Clock-RGBLED"; const char thingName[] = "NTP-Clock-RGBLED";
const char wifiInitialApPassword[] = "12345678"; const char wifiInitialApPassword[] = "12345678";
//ToDo add internal LED and check visibility
#define STRING_LEN 63 #define STRING_LEN 63
#define NUMBER_LEN 4 #define NUMBER_LEN 4
// -- Maximal length the input-range attributes can have.
#define COLOR_ATTR_LENGTH 60
// -- Configuration specific key. The value should be modified if config structure was changed. // -- Configuration specific key. The value should be modified if config structure was changed.
#define CONFIG_VERSION "V1.0.0" #define CONFIG_VERSION "V1.1.4"
// -- Javascript block will be added to the header. 🔒 🔓
const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\n\ const char CUSTOMHTML_SCRIPT_INNER[] PROGMEM = "\n\
document.addEventListener('DOMContentLoaded', function(event) {\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\ let elements = document.querySelectorAll('input[type=\"password\"]');\n\
for (let p of elements) {\n\ for (let p of elements) {\n\
let btn = document.createElement('INPUT'); btn.type = 'button'; btn.value = '🔓'; btn.style.width = 'auto'; p.style.width = '83%'; p.parentNode.insertBefore(btn,p.nextSibling);\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\ btn.onclick = function() { if (p.type === 'password') { p.type = 'text'; btn.value = '🔒'; } else { p.type = 'password'; btn.value = '🔓'; } }\n\
};\n\ };\n\
});\n"; });\n";
//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " <link rel='icon' src='data:image/png;base64,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'/>"; const char IOTWEBCONF_HTML_FORM_COLOR_PARAM[] PROGMEM =
DNSServer dnsServer; "<div class='{s}' '><label for='{i}'>{b}</label> (<span id='{i}Val'>{v}</span>)"
WebServer server(80); "<input type='{t}' id='{i}' "
#ifdef ESP8266 "name='{i}' style=\"padding: unset\" maxlength={l} placeholder='{p}' value='{v}' {c}/>"
ESP8266HTTPUpdateServer httpUpdater; "<div class='em'>{e}</div></div>\n";
#elif defined(ESP32)
HTTPUpdateServer httpUpdater;
#endif
char ntpServerParamValue[STRING_LEN]; // -- Our custom class declaration. You should move it to a .h fine in your project.
char maxBrightnessParamValue[NUMBER_LEN]; class ColorWithValueParameter : public iotwebconf::NumberParameter
char singleSecondParamValue[STRING_LEN]; {
char allDotsOnParamValue[STRING_LEN]; public:
char followingHourParamValue[STRING_LEN]; ColorWithValueParameter(
const char* label, const char* id, char* valueBuffer, int length,
const char* defaultValue
) : iotwebconf::NumberParameter(
label, id, valueBuffer, length, defaultValue)
{
snprintf(
this->_colorAttr, COLOR_ATTR_LENGTH,
"oninput='colorCh(this.id)'");
IotWebConf iotWebConf(thingName, &dnsServer, &server, wifiInitialApPassword, CONFIG_VERSION); this->customHtml = this->_colorAttr;
IotWebConfParameterGroup timeGroup = IotWebConfParameterGroup("Time", "Time settings"); };
IotWebConfTextParameter ntpServerParam = IotWebConfTextParameter("NTP Server", "ntpServer", ntpServerParamValue, STRING_LEN, "pool.ntp.org"); protected:
IotWebConfParameterGroup ledGroup = IotWebConfParameterGroup("LED", "LED settings"); // Overrides
IotWebConfNumberParameter maxBrightnessParam = IotWebConfNumberParameter("Max BRIGHTNESS", "max brightness", maxBrightnessParamValue, NUMBER_LEN, "200", "20..254", "min='20' max='254' step='1'"); virtual String renderHtml(
IotWebConfCheckboxParameter singleSecondParam = IotWebConfCheckboxParameter("Show Seconds", "singleSecond", singleSecondParamValue, STRING_LEN, true); bool dataArrived, bool hasValueFromPost, String valueFromPost) override
IotWebConfCheckboxParameter allDotsOnParam = IotWebConfCheckboxParameter("all Dots lighten on", "allDotsOn", allDotsOnParamValue, STRING_LEN, true); {
IotWebConfCheckboxParameter followingHourParam = IotWebConfCheckboxParameter("following Hour", "followingHour", followingHourParamValue, STRING_LEN, true); return TextParameter::renderHtml("color", hasValueFromPost, valueFromPost);
};
virtual String getHtmlTemplate()
{
return FPSTR(IOTWEBCONF_HTML_FORM_COLOR_PARAM);
};
private:
char _colorAttr[COLOR_ATTR_LENGTH];
};
// -- We need to create our custom HtmlFormatProvider to add some javasripts.
class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider
{ {
protected: protected:
@ -157,22 +263,87 @@ class CustomHtmlFormatProvider : public iotwebconf::HtmlFormatProvider
} }
*/ */
}; };
// -- 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 = '🔓'; 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 = '🔒'; } else { p.type = 'password'; btn.value = '🔓'; } }\n\
};\n\
});\n";
*/
//const char CUSTOMHTML_BODY_INNER[] PROGMEM = " <link rel='icon' src='data:image/png;base64,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'/>";
DNSServer dnsServer;
WebServer server(80);
#ifdef ESP8266
ESP8266HTTPUpdateServer httpUpdater;
#elif defined(ESP32)
HTTPUpdateServer httpUpdater;
#endif
char ntpServerParamValue[STRING_LEN];
char maxBrightnessParamValue[NUMBER_LEN];
char singleSecondParamValue[STRING_LEN];
char allDotsOnParamValue[STRING_LEN];
char followingHourParamValue[STRING_LEN];
char hourColorParamValue[COLOR_ATTR_LENGTH];
char minuteColorParamValue[COLOR_ATTR_LENGTH];
char secondsColorParamValue[COLOR_ATTR_LENGTH];
char highnoonColorParamValue[COLOR_ATTR_LENGTH];
char backlightColorParamValue[COLOR_ATTR_LENGTH];
char hourMarkingColorParamValue[COLOR_ATTR_LENGTH];
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);
ColorWithValueParameter hourColorParam = ColorWithValueParameter("Stundenfarbe", "hourColorParam", hourColorParamValue, COLOR_ATTR_LENGTH, "#FFD700");
ColorWithValueParameter minuteColorParam = ColorWithValueParameter("Minutenfarbe", "minuteColorParam", minuteColorParamValue, COLOR_ATTR_LENGTH, "#800000");
ColorWithValueParameter secondsColorParam = ColorWithValueParameter("Sekundenfarbe", "secondsColorParam", secondsColorParamValue, COLOR_ATTR_LENGTH, "#000000");
ColorWithValueParameter highnoonColorParam = ColorWithValueParameter("12Uhr Farbe", "highnoonColorParam", highnoonColorParamValue, COLOR_ATTR_LENGTH, "#C0C0C0");
ColorWithValueParameter backlightColorParam = ColorWithValueParameter("Hintergrundfarbe", "backlightColorParam", backlightColorParamValue, COLOR_ATTR_LENGTH, "#1E2823");
ColorWithValueParameter hourMarkingColorParam = ColorWithValueParameter("Stundenmarkierung", "hourMarkingColorParam", hourMarkingColorParamValue, COLOR_ATTR_LENGTH, "#787878");
// -- An instance must be created from the class defined above. // -- An instance must be created from the class defined above.
CustomHtmlFormatProvider customHtmlFormatProvider; CustomHtmlFormatProvider customHtmlFormatProvider;
//ToDo color Picker Second, 12Clock, Minute, Hour
Task bootAnim(200, TASK_FOREVER, &bootAnimCallback); Task bootAnim(200, TASK_FOREVER, &bootAnimCallback);
Task clockTick(1000, TASK_FOREVER, &clockTickCallback); Task clockTick(1000, TASK_FOREVER, &clockTickCallback);
Task ledRefresh(200, TASK_FOREVER, &ledRefreshCallback); Task ledRefresh(200, TASK_FOREVER, &ledRefreshCallback);
#ifdef LDR_PIN
Task brightness(10000, TASK_FOREVER, &brightnessAdjustmentCallback); Task brightness(10000, TASK_FOREVER, &brightnessAdjustmentCallback);
#endif
//Task iotwebconfLoop(200, TASK_FOREVER, &iotWebConf.doLoop); //Task iotwebconfLoop(200, TASK_FOREVER, &iotWebConf.doLoop);
Scheduler runner; 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() { String printLocalTime() {
if (!getLocalTime(&timeinfo)) { if (!getLocalTime(&timeinfo, 200)) {
Serial.println("Failed to obtain time"); Serial.println("Failed to obtain time");
NTPreachable = false;
return ""; return "";
} }
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); //Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
@ -180,6 +351,7 @@ String printLocalTime() {
char timeStringBuff[50]; //50 chars should be enough char timeStringBuff[50]; //50 chars should be enough
strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo); strftime(timeStringBuff, sizeof(timeStringBuff), "%A, %B %d %Y %H:%M:%S", &timeinfo);
//Serial.println(timeStringBuff); //Serial.println(timeStringBuff);
NTPreachable = true;
return timeStringBuff; return timeStringBuff;
} }
@ -194,7 +366,7 @@ void iotWebConfHandleRoot() {
// -- Captive portal request were already served. // -- Captive portal request were already served.
return; return;
} }
char sTemp[12];
String s = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>"; String s = "<!DOCTYPE html><html lang=\"en\"><head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"/>";
s += "<meta http-equiv=\"refresh\" content=\"30\">"; s += "<meta http-equiv=\"refresh\" content=\"30\">";
//s += CUSTOMHTML_BODY_INNER; //s += CUSTOMHTML_BODY_INNER;
@ -204,7 +376,8 @@ void iotWebConfHandleRoot() {
s += "<table>"; s += "<table>";
s += "<tr><td>Current Time:</td><td>"; s += "<tr><td>Current Time:</td><td>";
s += printLocalTime(); s += printLocalTime();
s += "</td></tr><tr></tr><tr><td>NTP Server:</td><td>"; s += "</td></tr></table><table>";
s += "<tr></tr><tr><td>NTP Server:</td><td>";
s += ntpServerParamValue; s += ntpServerParamValue;
s += "</td><tr><tr><td>Current Brightness value: </td><td>"; s += "</td><tr><tr><td>Current Brightness value: </td><td>";
s += String(strip.GetBrightness()); s += String(strip.GetBrightness());
@ -216,7 +389,35 @@ void iotWebConfHandleRoot() {
s += (allDotsOn ? "Yes" : "No"); s += (allDotsOn ? "Yes" : "No");
s += "</td></tr><tr><td>Following Hour: </td><td>"; s += "</td></tr><tr><td>Following Hour: </td><td>";
s += (followingHour ? "Yes" : "No"); s += (followingHour ? "Yes" : "No");
s += "<td></tr></table>"; s += "</td></tr><tr><td>";
s += "<tr><td>High noon: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &highnoonColor);
s += sTemp;
s += ";\"><td></tr>";
s += "<tr><td>Hour color: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &hourColor);
s += sTemp;
s += ";\"><td></tr>";
s += "<tr><td>Minute color: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &minuteColor);
s += sTemp;
s += ";\"><td></tr>";
if (singleSecond) {
s += "<tr><td>Seconds color: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &secondsColor);
s += sTemp;
s += ";\"><td></tr>";
}
if (allDotsOn) {
s += "<tr><td>Backlight: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &backlightColor);
s += sTemp;
s += ";\"><td></tr>";
}
s += "<tr><td>Hour Marking: </td><td style=\"border: 1px solid #000000; background-color:";
transformtoHtmlColor ((char*)&sTemp, &hourMarkingColor);
s += sTemp;
s += ";\"><td></tr></table>";
s += "<p>"; s += "<p>";
s += "Go to <a href='config'>configure page</a> to change values."; s += "Go to <a href='config'>configure page</a> to change values.";
s += "</body></html>\n"; s += "</body></html>\n";
@ -234,30 +435,15 @@ void iotWebConfConfigSaved()
//Serial.println(allDotsOnParam.isChecked() ? "true" : "false"); //Serial.println(allDotsOnParam.isChecked() ? "true" : "false");
followingHour = followingHourParam.isChecked() ? true : false; followingHour = followingHourParam.isChecked() ? true : false;
//Serial.println(followingHourParam.isChecked() ? "true" : "false"); //Serial.println(followingHourParam.isChecked() ? "true" : "false");
transformHtmltoStrip(&highnoonColor, (char*)&highnoonColorParamValue);
transformHtmltoStrip(&hourColor, (char*)&hourColorParamValue);
transformHtmltoStrip(&minuteColor, (char*)&minuteColorParamValue);
transformHtmltoStrip(&secondsColor, (char*)&secondsColorParamValue);
transformHtmltoStrip(&backlightColor, (char*)&backlightColorParamValue);
transformHtmltoStrip(&hourMarkingColor, (char*)&hourMarkingColorParamValue);
Serial.println("Configuration was updated."); Serial.println("Configuration was updated.");
} }
/*
bool iotWebConfFormValidator(iotwebconf::WebRequestWrapper* webRequestWrapper)
{
Serial.println("Validating form.");
boolean valid = true;
int l = server.arg(ntpServerParam.getId()).length();
if (l < 3)
{
ntpServerParam.errorMessage = "Please provide at least 3 characters for this test!";
valid = false;
}
int b = atoi(maxBrightnessParamValue);
if (b < MINIMAL_BRIGHTNESS || b > 254)
{
valid = false;
}
return valid;
}
*/
void iotWebConf_Setup() { void iotWebConf_Setup() {
@ -267,6 +453,12 @@ void iotWebConf_Setup() {
ledGroup.addItem(&singleSecondParam); ledGroup.addItem(&singleSecondParam);
ledGroup.addItem(&allDotsOnParam); ledGroup.addItem(&allDotsOnParam);
ledGroup.addItem(&followingHourParam); ledGroup.addItem(&followingHourParam);
ledGroup.addItem(&hourColorParam);
ledGroup.addItem(&minuteColorParam);
ledGroup.addItem(&secondsColorParam);
ledGroup.addItem(&highnoonColorParam);
ledGroup.addItem(&backlightColorParam);
ledGroup.addItem(&hourMarkingColorParam);
iotWebConf.addParameterGroup(&timeGroup); iotWebConf.addParameterGroup(&timeGroup);
iotWebConf.addParameterGroup(&ledGroup); iotWebConf.addParameterGroup(&ledGroup);
@ -301,8 +493,20 @@ void iotWebConf_Setup() {
void syncNTP() { void syncNTP() {
if (iotWebConf.getState() == IOTWEBCONF_STATE_ONLINE) { if (iotWebConf.getState() == IOTWEBCONF_STATE_ONLINE) {
//init and get the time //init and get the time
configTime(gmtOffset_sec, daylightOffset_sec, ntpServerParamValue); #ifdef ESP8266
//sntp_servermode_dhcp(0);
configTime(MYTZ, ntpServerParamValue);
#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()); Serial.println(printLocalTime());
if (NTPreachable) {
//inverted logic - remaining time //inverted logic - remaining time
currentSec = 60 - timeinfo.tm_sec; currentSec = 60 - timeinfo.tm_sec;
currentMin = 60 - timeinfo.tm_min; currentMin = 60 - timeinfo.tm_min;
@ -311,36 +515,42 @@ void syncNTP() {
bootAnim.disable(); bootAnim.disable();
ledRefresh.enable(); ledRefresh.enable();
clockTick.enable(); clockTick.enable();
#ifdef LDR_PIN
brightness.enable(); brightness.enable();
#endif
}
} }
} }
void setup() { void setup() {
#ifdef LDR_PIN
pinMode(LDR_PIN, INPUT_PULLUP); pinMode(LDR_PIN, INPUT_PULLUP);
#endif
pinMode(DATA_PIN, OUTPUT); pinMode(DATA_PIN, OUTPUT);
Serial.begin(SERIAL_BAUD); Serial.begin(SERIAL_BAUD);
Serial.flush(); Serial.flush();
Serial.print("\n\n\nCPU Frequency is: "); Serial.print("\n\n\nCPU Frequency is: ");
#ifdef ESP8266
Serial.print(ESP.getCpuFreqMHz());
#elif defined(ESP32)
Serial.print(getCpuFrequencyMhz()); //Get CPU clock Serial.print(getCpuFrequencyMhz()); //Get CPU clock
#endif
Serial.println(" Mhz"); Serial.println(" Mhz");
Serial.print("MAC address: "); Serial.print("MAC address: ");
Serial.println(WiFi.macAddress()); //Get CPU clock Serial.println(WiFi.macAddress()); //Get CPU clock
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");
strip.Begin(); strip.Begin();
strip.SetBrightness( MINIMAL_BRIGHTNESS );
strip.ClearTo(white); strip.ClearTo(white);
strip.SetBrightness( MINIMAL_BRIGHTNESS );
strip.Show(); strip.Show();
runner.init(); runner.init();
runner.addTask(ledRefresh); runner.addTask(ledRefresh);
runner.addTask(clockTick); runner.addTask(clockTick);
#ifdef LDR_PIN
runner.addTask(brightness); runner.addTask(brightness);
#endif
runner.addTask(bootAnim); runner.addTask(bootAnim);
bootAnim.enable(); bootAnim.enable();
@ -359,34 +569,40 @@ void loop()
} }
void ledRefreshCallback() { void ledRefreshCallback() {
temp = allDotsOn ? white : black; temp = allDotsOn ? backlightColor : black;
strip.ClearTo(temp); strip.ClearTo(temp);
//1 dot hour marking //1 dot hour marking
for (int dot = 0; dot < NUM_LEDS; dot++) { for (int dot = 0; dot < NUM_LEDS; dot++) {
if (MOD(dot, 5) == 0) { if (MOD(dot, 5) == 0) {
strip.SetPixelColor(dot, whiter); strip.SetPixelColor(dot, hourMarkingColor);
} }
} }
//3 dots hour //3 dots hour
strip.SetPixelColor(MOD((currentHour * 5 - 1 + hourOffset), NUM_LEDS), gold); strip.SetPixelColor(MOD((currentHour * 5 - 1 + hourOffset), NUM_LEDS), hourColor);
strip.SetPixelColor(MOD((currentHour * 5 + 0 + hourOffset), NUM_LEDS), gold); strip.SetPixelColor(MOD((currentHour * 5 + 0 + hourOffset), NUM_LEDS), hourColor);
strip.SetPixelColor(MOD((currentHour * 5 + 1 + hourOffset), NUM_LEDS), gold); strip.SetPixelColor(MOD((currentHour * 5 + 1 + hourOffset), NUM_LEDS), hourColor);
strip.SetPixelColor(0, white12); //define high noon strip.SetPixelColor(0, highnoonColor); //define high noon
if (singleSecond) { if (singleSecond) {
strip.SetPixelColor(MOD((currentSec + 0), NUM_LEDS), (allDotsOn ? black : white)); strip.SetPixelColor(MOD((currentSec + 0), NUM_LEDS), (secondsColor));
//strip.SetPixelColor(MOD((currentSec + 0), NUM_LEDS), (allDotsOn ? black : secondsColor));
} }
strip.SetPixelColor(MOD((currentMin + 0), NUM_LEDS), darkred); strip.SetPixelColor(MOD((currentMin + 0), NUM_LEDS), minuteColor);
strip.Show(); strip.Show();
} }
// Scheduler // Scheduler
void clockTickCallback() { void clockTickCallback() {
#ifdef LDR_PIN
ldrValue = (ldrValue + analogRead(LDR_PIN)); ldrValue = (ldrValue + analogRead(LDR_PIN));
#endif
if (currentSec < 0) { if (currentSec < 0) {
currentSec = 59; currentSec = 59;
currentMin--; currentMin--;
if (!NTPreachable) {
syncNTP();
}
if (currentMin < 0) { if (currentMin < 0) {
currentMin = 59; currentMin = 59;
currentHour--; currentHour--;
@ -406,29 +622,39 @@ void clockTickCallback() {
void bootAnimCallback() { void bootAnimCallback() {
strip.ClearTo(black); strip.ClearTo(black);
int tail = -1;
currentSec--; currentSec--;
if (currentSec < 0) { if (currentSec < 0) {
currentSec = 59; currentSec = NUM_LEDS-1;
tail = 1;
}
if (iotWebConf.getState() == IOTWEBCONF_STATE_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_STATE_CONNECTING) { if (iotWebConf.getState() == IOTWEBCONF_STATE_CONNECTING) {
strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), white); strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), white);
strip.SetPixelColor(MOD((currentSec - 1), NUM_LEDS), whiter); strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), whiter);
strip.SetPixelColor(MOD((currentSec - 2), NUM_LEDS), white12); strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), white12);
} }
if (iotWebConf.getState() == IOTWEBCONF_STATE_AP_MODE) { if (iotWebConf.getState() == IOTWEBCONF_STATE_AP_MODE) {
strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), lightgreen); strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), lightgreen);
strip.SetPixelColor(MOD((currentSec - 1), NUM_LEDS), green); strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), green);
strip.SetPixelColor(MOD((currentSec - 2), NUM_LEDS), darkgreen); strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkgreen);
} }
if (iotWebConf.getState() == IOTWEBCONF_STATE_BOOT || iotWebConf.getState() == IOTWEBCONF_STATE_NOT_CONFIGURED) { if (iotWebConf.getState() == IOTWEBCONF_STATE_BOOT || iotWebConf.getState() == IOTWEBCONF_STATE_NOT_CONFIGURED) {
strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), orangered); strip.SetPixelColor(MOD((currentSec - 0), NUM_LEDS), orangered);
strip.SetPixelColor(MOD((currentSec - 1), NUM_LEDS), red); strip.SetPixelColor(MOD((currentSec - 1 * tail), NUM_LEDS), red);
strip.SetPixelColor(MOD((currentSec - 2), NUM_LEDS), darkred); strip.SetPixelColor(MOD((currentSec - 2 * tail), NUM_LEDS), darkred);
} }
strip.Show(); strip.Show();
} }
#ifdef LDR_PIN
void brightnessAdjustmentCallback() { void brightnessAdjustmentCallback() {
//Serial.println(ldrValue); //Serial.println(ldrValue);
//brigthness begin //brigthness begin
@ -441,7 +667,8 @@ void brightnessAdjustmentCallback() {
x = int(MINIMAL_BRIGHTNESS + (MAX_BRIGHTNESS - MINIMAL_BRIGHTNESS) / ((ldrValue / LDR_SCALE) + 1) ); x = int(MINIMAL_BRIGHTNESS + (MAX_BRIGHTNESS - MINIMAL_BRIGHTNESS) / ((ldrValue / LDR_SCALE) + 1) );
strip.SetBrightness(x); strip.SetBrightness(x);
} }
Serial.println("Brightness: " + String(strip.GetBrightness()) + "(" + String(ldrValue) + ")"); //Serial.println("Brightness: " + String(strip.GetBrightness()) + "(" + String(ldrValue) + ")");
ldrValue = 0; ldrValue = 0;
strip.Show(); strip.Show();
} }
#endif

View File

@ -1,13 +1,15 @@
# Anleitung RGB LED Uhr # Anleitung RGB LED Uhr
Dies ist eine Beschreibung der RGB LED Uhr Nach jeden Neustart wird der eigene WiFi Accesspoint für 30 Sekunden aktiviert. Verbindet man sich mit diesem, so kann man etwaige Fehler korrigieren.
# Schnellstart # Schnellstart
Sobald die Uhr mit Strom versorgt wird ( 5V, 500mAh) bietet das Board (Lolin32lite) einen WiFi Accesspoint "NTP-Clock-RGBLED" an und drei LEDs in roten Farben kreisen schnell herum. Zu diesem kann man sich verbinden (Passwort: 12345678) bzw das Smartphone meldet, dass eine Anmeldung erforderlich ist. Man kommt zunächst auf der Übersichtsseite an. Diese ist prinzipiell uninteressant, stattdessen muss die Internetverbindung konfiguriert werden. Hierzu klickt man auf "Config" und trägt die folgenden drei Dinge ein: Sobald die Uhr mit Strom versorgt wird ( 5V, 500mAh) bietet das Board (Lolin32lite) einen WiFi Accesspoint "NTP-Clock-RGBLED" an und drei LEDs in roten Farben kreisen schnell herum. Zu diesem kann man sich verbinden (Passwort: 12345678) bzw. das Smartphone meldet, dass eine Anmeldung erforderlich ist. Man kommt zunächst auf der Übersichtsseite an. Diese ist später erst interessant, stattdessen muss die Internetverbindung konfiguriert werden. Hierzu klickt man auf "Config" und trägt die folgenden drei Dinge ein:
- Ein Passwort für die Uhr
- Ein Passwort für die Uhr bzw den temporären Accesspoint
- Den Namen des Wlans - Den Namen des Wlans
- Das Passwort des Wlans - Das Passwort des Wlans
Der Rest ist nicht notwendig. Sobald man die Werte gespeichert hat, trennt man das Smartphone vom WLAN. Die drei kreisenden LEDs können dann weiß kurz aufleuchten, üblicherweise sieht man dies nicht, da sobald die Uhrzeit verfügbar ist, diese angezeigt wird. Damit ist die Uhr konfiguriert.
Ab sofort ist die Uhr unter einer neuen IP erreichbar, sodass dort weitere Einstellungen vorgenommen werden können. Die Uhr merkt sich auch die Einstellungen. Der Rest ist nicht notwendig. Sobald man die Werte gespeichert hat, trennt man das Smartphone vom WLAN der Uhr. Die drei kreisenden LEDs können dann weiß kurz aufleuchten. Üblicherweise sieht man dies nicht, da sobald die Uhrzeit verfügbar ist, diese angezeigt wird. In seltenen Fällen wird der Ring weiß beleuchtet und drei schwarze LEDs kreisen. Dies bedeutet, dass keine Uhrzeit zur Verfügung steht. Ansonsten ist damit die Uhr konfiguriert.
Ab sofort ist die Uhr unter einer neuen IP erreichbar (nachzusehen im Router), sodass dort weitere Einstellungen vorgenommen werden können. Die Uhr merkt sich auch die getätigten Einstellungen.
# erweiterte Einstellungen # erweiterte Einstellungen
Es wird unter der IP 192.168.4.1 ein Webserver angeboten (sofern über den Accesspoint direkt verbunden), der zwei Webseiten anzeigen kann. Primär wird die Statusseite angezeigt, die alle wesentlichen Parameter auflistet: Es wird unter der IP 192.168.4.1 ein Webserver angeboten (sofern über den Accesspoint direkt verbunden), der zwei Webseiten anzeigen kann. Primär wird die Statusseite angezeigt, die alle wesentlichen Parameter auflistet:
- Aktuelle NTP Zeit - Aktuelle NTP Zeit
@ -17,6 +19,12 @@ Ab sofort ist die Uhr unter einer neuen IP erreichbar, sodass dort weitere Einst
- Anzeige der einzelnen Sekunden - Anzeige der einzelnen Sekunden
- Aufleuchten aller LEDs - Aufleuchten aller LEDs
- Folgende Stunde (wie auf einer analogen Uhr) - Folgende Stunde (wie auf einer analogen Uhr)
- Farbwahl der 12Uhr Markierung
- Farbwahl der aktuelle Stunde (3LED)
- Farbwahl der aktuellen Minute (1LED)
- Farbwahl der aktuellen Sekunde (1LED)
- Farbwahl der übrigen LEDs
- Farbwahl der restlichen Stunden (10 LEDs)
Unten auf der Statusseite gibt es einen Link zur Konfigurationsseite, eine Möglichkeit für den Upload einer neuen Firmware sowie die aktuelle Firmwareversion wird angezeigt. Unten auf der Statusseite gibt es einen Link zur Konfigurationsseite, eine Möglichkeit für den Upload einer neuen Firmware sowie die aktuelle Firmwareversion wird angezeigt.
@ -44,13 +52,16 @@ Unten auf der Statusseite gibt es einen Link zur Konfigurationsseite, eine Mögl
- Show Seconds - Show Seconds
- all Dots lighten up - all Dots lighten up
- following Hour - following Hour
- hourColor
- minuteColor
- secondsColor
- highnoonColor
- backlightColor
- hourMarkingColor
- firmware update link - firmware update link
- Firmware config version 'xxxx' - Firmware config version 'xxxx'
## ausstehende Verbesserungen ## ausstehende Verbesserungen
- [ ] RGB Auswahl Sekunden
- [ ] RGB Auswahl Minuten
- [ ] RGB Auswahl Stunden
- [ ] RGB Auswahl 12 Uhr
- [ ] flüssige Helligkeitsadaptierung - [ ] flüssige Helligkeitsadaptierung
- [ ] härtes non-blocking Verhalten