Version 2.1

This commit is contained in:
2024-03-04 12:35:37 +01:00
commit 5bae57fa1b
218 changed files with 71469 additions and 0 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 MiB

View File

@@ -0,0 +1,2 @@
https://bleche-nach-mass.de/blechzuschnitte/1090-magnetwaende?gclid=EAIaIQobChMI1Mfgl8m__QIVyud3Ch3O-wPpEAAYASAAEgIasvD_BwE#002-1091-6
235x120

View File

@@ -0,0 +1,874 @@
/*
N-Tools 2023
231112 -> Webseite Optimiert; kleinigkeiten für Uli;
231210 -> Fehler in der Schrift NT7x10 behoben
*/
#define VERSION (char *) "V2.1"
char ChipID[10] = "ERROR";
uint64_t macAddress = ESP.getEfuseMac();
uint64_t macAddressTrunc = (macAddress << 40);
#define R1_PIN 13
#define G1_PIN 27
#define B1_PIN 25
#define R2_PIN 12
#define G2_PIN 26
#define B2_PIN 4
#define A_PIN 19
#define B_PIN 23 // Changed from library default
#define C_PIN 18
#define D_PIN 5
#define E_PIN 15
#define LAT_PIN 17
#define OE_PIN 16
#define CLK_PIN 14
#define PANEL_RES_X 96 // Number of pixels wide of each INDIVIDUAL panel module.
#define PANEL_RES_Y 48 // Number of pixels tall of each INDIVIDUAL panel module.
#define NUM_ROWS 1 // Number of rows of chained INDIVIDUAL PANELS
#define NUM_COLS 1 // Number of INDIVIDUAL PANELS per ROW
#define PANEL_CHAIN NUM_ROWS*NUM_COLS // total number of panels chained one to another
//#define PIXEL_COLOR_DEPTH_BITS 2
// library includes
//#include <ESP32-VirtualMatrixPanel-I2S-DMA.h>
#include <ESP32-HUB75-MatrixPanel-I2S-DMA.h>
MatrixPanel_I2S_DMA *display = nullptr;
#include <WiFi.h>
#include <WiFiClient.h>
#include <WiFiAP.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <ElegantOTA.h>
#include <DNSServer.h>
AsyncWebServer webServer(80);
DNSServer dnsServer;
IPAddress ip_local(192, 168, 13, 1);
IPAddress ip_gateway(192, 168, 13, 1);
IPAddress ip_subnet(255, 255, 255, 0);
bool APEnabled = false;
char ssid[30] = "";
char pass[30] = "";
char appass[30] = "";
char localip[16];
#include "index_html.h"
const char* PARAM_SET = "set";
const char* PARAM_SAVE = "save";
const char* PARAM_TO = "to";
const char* PARAM_SHOWWHAT = "showWhat";
const char* PARAM_BRIGHTNESS = "brightness";
const char* PARAM_OPTIONS = "options";
const char* PARAM_SSID = "ssid";
const char* PARAM_PWD = "pwd";
const char* PARAM_RESET = "reset";
// Replaces placeholder with button section in your web page
char * html_processor(const String& var){
if(var == "VERSION"){
return VERSION;
}else if(var == "ID"){
return ChipID;
}else if(var == "LOCALIP"){
return localip;
}
return (char *) "not defined";
}
String toStringIp(IPAddress ip) {
String res = "";
for (int i = 0; i < 3; i++) {
res += String((ip >> (8 * i)) & 0xFF) + ".";
}
res += String(((ip >> 8 * 3)) & 0xFF);
return res;
}
void html_handle_notsuccess(AsyncWebServerRequest *request);
void html_handle_notsuccess(AsyncWebServerRequest *request){
request->send(200, "text/html", String("<a href='http://") + toStringIp(ip_local) + String("'>zur Konfigurationsseite</a><script> location.href = 'http://") + toStringIp(ip_local) + String("'; </script>"));
}
void html_root(AsyncWebServerRequest *request);
void html_root(AsyncWebServerRequest *request) {
request->send_P(200, "text/html", html_page_index, html_processor);
}
void html_poll(AsyncWebServerRequest *request);
void html_do(AsyncWebServerRequest *request);
//permanenter Speicher
#include <EEPROM.h>
//i2c
#include <Wire.h>
#include <RV-3028-C7.h>
RV3028 rtc;
const int PINRTC_CLOCK = 34;
bool rtcEnabled = false;
bool doRTCSecond = false;
#include <TimeLib.h>
#include <WeekNumber.h>
long ti_second = 0;
float brightness = 1.0;
uint8_t timeColor[3] = {0xff,0xff,0xff};
uint8_t tacticalTimeColor[3] = {0x88,0xff,0x00};
uint8_t dateColor[3] {0x10,0xff,0x00};
uint8_t kwColor[3] {0x10,0xff,0x00};
int8_t lastminutes = -1;
bool iDL = false;
bool savediDL = false;
long lastTimeSyncTime = 0;
uint8_t lastTimeSyncTyp = 0;
bool EEPROMDataNotSaved = false;
uint8_t options = 0;
uint8_t timeIndex = 0;
bool withSeconds = true;
bool alwaysAccessPoint = true;
void setPixelColor(uint8_t x,uint8_t y, uint8_t red, uint8_t green ,uint8_t blue){
display->drawPixelRGB888(x, y, red, green, blue);
}
//Zeichene eine Linie waagrecht x/y und z als länge
void LineH(uint8_t x, uint8_t y, uint8_t z, uint8_t red, uint8_t green ,uint8_t blue){
display->drawFastHLine(x,y,z,display->color565(red, green, blue));
}
//Zeichene eine Linie senkrecht x/y und z als länge
void LineV(uint8_t x, uint8_t y, int16_t z, uint8_t red, uint8_t green, uint8_t blue){
display->drawFastVLine(x,y,z,display->color565(red, green, blue));
}
void doClearTimeLEDs(uint8_t x=0,uint8_t y=0){
for(uint8_t i=0;i<24;i++){
display->drawFastHLine(x,y+i, 80, 0);
}
}
void doClearTacticalLEDs(uint8_t x=0,uint8_t y=0){
for(uint8_t i=0;i<16;i++){
display->drawFastHLine(x,y+i, 96, 0);
}
}
//eigene Schriften
#include <char5x7.h>
#include <char10x16.h>
#include <char16x24.h>
#include <tthcent8p.h>
#include <NT7x10.h>
#include <BundesSans6P.h>
#include <teko6P.h>
void showNTOOLS(void){
uint8_t zeile=12;
uint8_t spalte=25;
spalte += Out5x7Char('N',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('-',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('T',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('o',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('o',spalte,zeile-1,0,0,255)+1;
spalte += Out5x7Char('l',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('s',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('.',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('d',spalte,zeile,0,0,255)+1;
spalte += Out5x7Char('e',spalte,zeile,0,0,255)+1;
}
void drawSeconds(time_t t, uint8_t x=0, uint8_t y=0){
uint16_t tmp = 0;
uint8_t r = timeColor[0];
uint8_t g = timeColor[1];
uint8_t b = timeColor[2];
for(uint8_t i=0;i<16;i++){
display->drawFastHLine(x,y+i, 21, 0);
}
tmp = second(t);
Out10x16Char((tmp/10)+0x30,x,y,r,g,b);
tmp -= (tmp/10)*10;
x += 11;
Out10x16Char((tmp)+0x30,x,y,r,g,b);
}
void drawTime(time_t t,uint8_t x=0,uint8_t y=0){
uint8_t tmp = 0;
uint8_t r = timeColor[0];
uint8_t g = timeColor[1];
uint8_t b = timeColor[2];
tmp = hour(t);
if((tmp/10 > 0)){
if((tmp/10 == 1))
Out16x24Char((tmp/10)+0x30,x+6,y,r,g,b);
else
Out16x24Char((tmp/10)+0x30,x,y,r,g,b);
tmp -= (tmp/10)*10;
}
x += 19;
if((tmp == 1))
Out16x24Char((tmp)+0x30,x+3,y,r,g,b);
else
Out16x24Char((tmp)+0x30,x,y,r,g,b);
Out16x24Char(':',x+19,y,r,g,b);
x += 26;
tmp = minute(t);
if((tmp/10 == 1))
Out16x24Char((tmp/10)+0x30,x+6,y,r,g,b);
else
Out16x24Char((tmp/10)+0x30,x,y,r,g,b);
tmp -= (tmp/10)*10;
x += 19;
if((tmp == 1))
Out16x24Char((tmp)+0x30,x+3,y,r,g,b);
else
Out16x24Char((tmp)+0x30,x,y,r,g,b);
}
void showTime(time_t t,uint8_t x=12,uint8_t y=22){
uint16_t tmp = minute(t);
if(withSeconds){
drawSeconds(t,x+62,y+8);
x -= 11;
}
if(lastminutes != tmp){
lastminutes = tmp;
doClearTimeLEDs(x,y);
//Uhrzeit
drawTime(t,x,y);
}
}
char tacticalString[12] = "ddHHiiMMMyy";
void drawTactical(time_t t,uint8_t x = 0, uint8_t y = 0, uint8_t doCenterOf = 0){
uint8_t r = tacticalTimeColor[0];
uint8_t g = tacticalTimeColor[1];
uint8_t b = tacticalTimeColor[2];
display->setFont(&NT7x10);
display->setCursor(x, y+10);
display->setTextColor(display->color565(r,g,b));
uint16_t tmp = day(t);
tacticalString[0] = (tmp/10)+0x30;
tmp -= (tmp/10)*10;
tacticalString[1] = (tmp)+0x30;
tmp = hour(t);
tacticalString[2] = (tmp/10)+0x30;
tmp -= (tmp/10)*10;
tacticalString[3] = (tmp)+0x30;
tmp = minute(t);
tacticalString[4] = (tmp/10)+0x30;
tmp -= (tmp/10)*10;
tacticalString[5] = (tmp)+0x30;
tmp = month(t);
switch(tmp){
case 1:
tacticalString[6] = 'j';
tacticalString[7] = 'a';
tacticalString[8] = 'n';
break;
case 2:
tacticalString[6] = 'f';
tacticalString[7] = 'e';
tacticalString[8] = 'b';
break;
case 3:
tacticalString[6] = 'm';
tacticalString[7] = 'a';
tacticalString[8] = 'r';
break;
case 4:
tacticalString[6] = 'a';
tacticalString[7] = 'p';
tacticalString[8] = 'r';
break;
case 5:
tacticalString[6] = 'm';
tacticalString[7] = 'a';
tacticalString[8] = 'y';
break;
case 6:
tacticalString[6] = 'j';
tacticalString[7] = 'u';
tacticalString[8] = 'n';
break;
case 7:
tacticalString[6] = 'j';
tacticalString[7] = 'u';
tacticalString[8] = 'l';
break;
case 8:
tacticalString[6] = 'a';
tacticalString[7] = 'u';
tacticalString[8] = 'g';
break;
case 9:
tacticalString[6] = 's';
tacticalString[7] = 'e';
tacticalString[8] = 'p';
break;
case 10:
tacticalString[6] = 'o';
tacticalString[7] = 'c';
tacticalString[8] = 't';
break;
case 11:
tacticalString[6] = 'n';
tacticalString[7] = 'o';
tacticalString[8] = 'v';
break;
case 12:
tacticalString[6] = 'd';
tacticalString[7] = 'e';
tacticalString[8] = 'c';
break;
}
tmp = year(t)-2000;
tacticalString[9] = (tmp/10)+0x30;
tmp -= (tmp/10)*10;
tacticalString[10] = (tmp)+0x30;
if(doCenterOf > 0){
int16_t Tx,Ty;
uint16_t w,h;
display->getTextBounds(tacticalString,0,0,&Tx,&Ty,&w,&h);
x = ceil((doCenterOf - w)/2);
display->setCursor(x, y+10);
}
display->print(tacticalString);
}
void showTimeTactical(time_t t){
uint16_t tmp = minute(t);
uint8_t x = 8;
uint8_t y = 22;
if(withSeconds){
drawSeconds(t,x+62,y+8);
x -= 11;
}
if(lastminutes != tmp){
lastminutes = tmp;
doClearTacticalLEDs(0,7);
drawTactical(t,0,7,96);
//Uhrzeit
doClearTimeLEDs(x,y);
drawTime(t,x,y);
}
}
void doSetTime(unsigned long t){
rtc.reset();
rtc.setUNIX(t);
}
uint8_t isDayLight(uint8_t hour, uint8_t day, uint8_t wday, uint8_t month){
if( month < 3 || month > 10 ) // month 1, 2, 11, 12
return 0; // -> Winter
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 1;
}
uint8_t isDayLightEx(void){
long currentUNIXTime = now();
byte Month, Day, Hour, WDay;
Month = month(currentUNIXTime);
Day = day(currentUNIXTime);
Hour = hour(currentUNIXTime);
WDay = weekday();
return isDayLight(Hour,Day,WDay,Month);
}
void checkiDL(void){
iDL = isDayLightEx();
if(iDL != savediDL){
long currentUNIXTime = now();
if(iDL){
currentUNIXTime += (SECS_PER_HOUR);
}else{
currentUNIXTime -= (SECS_PER_HOUR);
}
setTime(currentUNIXTime);
doSetTime(currentUNIXTime);
savediDL = iDL;
EEPROM.put(10, savediDL);
EEPROM.commit();
}
}
void IRAM_ATTR rtc_clock(){ //Interrupt vom RTC
if(digitalRead(PINRTC_CLOCK)){
doRTCSecond = true;
}
}
void setup() {
//Serial.begin(115200);
//Dispolay INIT
HUB75_I2S_CFG::i2s_pins _pins = {
R1_PIN, G1_PIN, B1_PIN, R2_PIN, G2_PIN, B2_PIN,
A_PIN, B_PIN, C_PIN, D_PIN, E_PIN,
LAT_PIN, OE_PIN, CLK_PIN
};
HUB75_I2S_CFG mxconfig(
PANEL_RES_X, // module width
PANEL_RES_Y, // module height
PANEL_CHAIN, // chain length
_pins
);
mxconfig.double_buff = false;
mxconfig.i2sspeed = HUB75_I2S_CFG::HZ_10M;
mxconfig.latch_blanking = 4;
mxconfig.min_refresh_rate = 50;
display = new MatrixPanel_I2S_DMA(mxconfig);
display->begin();
display->setPanelBrightness(100);
display->clearScreen();
display->setFont(&TTHCENT8pt7b);
EEPROM.begin(256);
EEPROM.get(0, timeIndex);
EEPROM.get(1, options);
withSeconds = bitRead(options,0);
alwaysAccessPoint = bitRead(options,1);
EEPROM.get(5, brightness);
if(brightness < 0.10)
brightness = 0.10;
if(brightness > 1.0)
brightness = 1.0;
EEPROM.get(10, savediDL);
timeColor[0] = EEPROM.read(11);
timeColor[1] = EEPROM.read(12);
timeColor[2] = EEPROM.read(13);
tacticalTimeColor[0] = EEPROM.read(21);
tacticalTimeColor[1] = EEPROM.read(22);
tacticalTimeColor[2] = EEPROM.read(23);
dateColor[0] = EEPROM.read(31);
dateColor[1] = EEPROM.read(32);
dateColor[2] = EEPROM.read(33);
kwColor[0] = EEPROM.read(41);
kwColor[1] = EEPROM.read(42);
kwColor[2] = EEPROM.read(43);
EEPROM.get(101,ssid);
EEPROM.get(201,pass);
EEPROM.get(151,appass);
showNTOOLS();
display->setCursor(1, 34);
display->print("bitte warten");
Wire.begin(21,22);
Wire.setClock(100000);
if (rtc.begin() == true) {
display->drawPixelRGB888(1,0,0,255,0);
rtcEnabled = true;
rtc.setBackupSwitchoverMode(3);
rtc.enableClockOut(FD_CLKOUT_1);
pinMode(PINRTC_CLOCK, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PINRTC_CLOCK), rtc_clock, CHANGE);
setTime(rtc.getUNIX());
//prüfen ob Winterzeit
checkiDL();
}else{
display->drawPixelRGB888(1,0,255,0,0);
}
macAddressTrunc = (macAddressTrunc >> 40);
ultoa(macAddressTrunc,ChipID,10);
char NetName[30];
strcpy(NetName, "NTDU");
strcat(NetName, ChipID);
char APName[30];
strcpy(APName, "NT DesignUhr ");
strcat(APName, ChipID);
WiFi.persistent(false);
WiFi.begin(ssid,pass);
WiFi.hostname(NetName);
int xc = 0;
while ((WiFi.status() != WL_CONNECTED) && (xc < 10)) {
delay(1500);
xc++;
display->drawPixelRGB888(xc+6,0,255,255,0);
}
if (WiFi.status() == WL_CONNECTED) {
char str[5];
IPAddress lip;
lip = WiFi.localIP();
itoa(lip[0],str,10);
strcpy(localip, str);
strcat(localip, ".");
itoa(lip[1],str,10);
strcat(localip, str);
strcat(localip, ".");
itoa(lip[2],str,10);
strcat(localip, str);
strcat(localip, ".");
itoa(lip[3],str,10);
strcat(localip, str);
show5x7( 5, 2, localip, 255, 255, 255);
display->drawPixelRGB888(2, 0, 0, 255, 0);
configTime(0,0, "ptbtime1.ptb.de", "ptbtime2.ptb.de", "ptbtime3.ptb.de");
time_t timenow = time(nullptr);
xc = 0;
while((timenow < SECS_YR_2000) && (xc < 10)) {
delay(1000);
timenow = time(nullptr);
xc++;
display->drawPixelRGB888(xc+17,0,255,255,0);
}
if(timenow > SECS_YR_2000){
byte Month, Day, Hour;
setTime(timenow);
Month = month(timenow);
Day = day(timenow);
Hour = hour(timenow);
iDL = isDayLight(Hour,Day,weekday(),Month);
if(iDL)
timenow += (SECS_PER_HOUR * 2);
else
timenow += (SECS_PER_HOUR);
setTime(timenow);
if(rtcEnabled){
doSetTime(timenow);
}
savediDL = iDL;
EEPROM.put(10, savediDL);
EEPROM.commit();
display->drawPixelRGB888(3,0,0,255,0);
}else{
display->drawPixelRGB888(3,0,255,0,255);
}
delay(5000);
}else{
display->drawPixelRGB888(2,0,255,0,0);
APEnabled = true;
}
if(APEnabled || alwaysAccessPoint){
if(WiFi.status() == WL_CONNECTED)
WiFi.mode(WIFI_AP_STA);
else
WiFi.mode(WIFI_AP);
delay(100);
WiFi.softAPConfig(ip_local, ip_gateway, ip_subnet);
APEnabled = WiFi.softAP(APName, appass,2,0,1);
if(!APEnabled)
display->drawPixelRGB888(4,0,255,0,0);
else{
display->drawPixelRGB888(4,0,0,255,0);
dnsServer.setErrorReplyCode(DNSReplyCode::NoError);
dnsServer.start(53, "*", ip_local);
}
}else{
display->drawPixelRGB888(4,0,0,0,0);
}
ElegantOTA.begin(&webServer); // Start AsyncElegantOTA
webServer.onNotFound([](AsyncWebServerRequest *request){html_handle_notsuccess(request);});
webServer.on("/", HTTP_GET, [](AsyncWebServerRequest *request){html_root(request);});
webServer.on("/do", HTTP_GET, [] (AsyncWebServerRequest *request) {html_do(request);});
webServer.on("/poll", HTTP_GET, [] (AsyncWebServerRequest *request) {html_poll(request);});
webServer.begin();
delay(1000);
display->setPanelBrightness(ceil(255 * brightness));
display->clearScreen();
/*display->setTextColor(display->color565(128,255,0));
display->setFont(&NT7x10);
display->setCursor(13, 11);
display->print("alles gute im");
display->setCursor(17, 22);
display->setTextColor(display->color565(255,0,0));
display->print("neuen heim");
*/
}
void loop() {
if (millis() - ti_second > 1000) {
ti_second = millis();
if(!rtcEnabled){
doRTCSecond = true;
}
}
if(doRTCSecond){
doRTCSecond = false;
time_t currentUNIXTime = now();
if(rtcEnabled){
currentUNIXTime = rtc.getUNIX();
setTime(currentUNIXTime);
}
uint8_t Hour, Minute, Second, WDay;
Hour = hour(currentUNIXTime);
Minute = minute(currentUNIXTime);
Second = second(currentUNIXTime);
WDay = weekday();
checkiDL();
//Sonntag Reset ..
if((WDay == 1) && (Hour == 3) && (Minute == 1) && (Second == 0)){
ESP.restart();
}
switch(timeIndex){
case 0:
showTimeTactical(currentUNIXTime);
break;
case 1:
showTime(currentUNIXTime,4,10);
break;
case 2:
//showDateTime(currentUNIXTime);
break;
case 3:
showTime(currentUNIXTime,8,24);
break;
case 4:
//clock_center_x = 16;
//showAnalogTime(currentUNIXTime);
//showAnalogDate(currentUNIXTime);
break;
}
}
if(APEnabled)
dnsServer.processNextRequest();
ElegantOTA.loop();
}
void html_poll(AsyncWebServerRequest *request) {
long color = 0;
char ret[250];
char tempBuff[30];
strcpy(ret,(char *)"[");
if(rtcEnabled)
ltoa(rtc.getUNIX(),tempBuff,DEC);
else
ltoa(now(),tempBuff,DEC);
strcat(ret,tempBuff);
color = timeColor[0] << 16;
color += timeColor[1] << 8;
color += timeColor[2];
itoa(color,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
color = tacticalTimeColor[0] << 16;
color += tacticalTimeColor[1] << 8;
color += tacticalTimeColor[2];
itoa(color,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
color = dateColor[0] << 16;
color += dateColor[1] << 8;
color += dateColor[2];
itoa(color,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
itoa(timeIndex,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
itoa(lastTimeSyncTyp,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
itoa(lastTimeSyncTime,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
dtostrf(brightness, 10, 2, tempBuff);
strcat(ret,(char *)",\"");
strcat(ret,tempBuff);
strcat(ret,(char *)"\"");
itoa(rtcEnabled,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
itoa(EEPROMDataNotSaved,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
strcat(ret,(char *)",\"");
strcat(ret,ssid);
strcat(ret,(char *)"\"");
itoa(options,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
color = kwColor[0] << 16;
color += kwColor[1] << 8;
color += kwColor[2];
itoa(color,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
uint8_t kw = GetWeekNumber(year(now()),month(now()),day(now()));
itoa(kw,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
itoa(iDL,tempBuff,DEC);
strcat(ret,(char *)",");
strcat(ret,tempBuff);
strcat(ret,(char *)"]");
request->send(200, "text/plain", ret);
}
void html_do(AsyncWebServerRequest *request) {
String s_set,s_value,s_idx,s_value2;
uint32_t l_value;
if (request->hasParam(PARAM_SET)) {
s_set = request->getParam(PARAM_SET)->value();
if((s_set == "time") & (request->hasParam(PARAM_TO))) {
s_value = request->getParam(PARAM_TO)->value();
l_value = strtol(s_value.c_str(), NULL, 10);
doSetTime(l_value);
lastTimeSyncTyp = 3;
lastTimeSyncTime = now();
}else if(request->hasParam(PARAM_SHOWWHAT)) {
s_value = request->getParam(PARAM_SHOWWHAT)->value();
timeIndex = s_value.toInt();
display->clearScreen();
EEPROM.put(0, timeIndex);
EEPROMDataNotSaved = true;
}else if(((s_set == "color") | (s_set == "tcolor") | (s_set == "dcolor") | (s_set == "kwcolor")) & (request->hasParam(PARAM_TO))) {
s_value = request->getParam(PARAM_TO)->value();
uint8_t c[3];
l_value = strtol(s_value.c_str(), NULL, 16);
c[0] = l_value >> 16;
c[1] = l_value >> 8;
c[2] = l_value;
if(s_set == "color"){
timeColor[0] = c[0];
timeColor[1] = c[1];
timeColor[2] = c[2];
EEPROM.write(11,timeColor[0]);
EEPROM.write(12,timeColor[1]);
EEPROM.write(13,timeColor[2]);
EEPROMDataNotSaved = true;
}else if(s_set == "tcolor"){
tacticalTimeColor[0] = c[0];
tacticalTimeColor[1] = c[1];
tacticalTimeColor[2] = c[2];
EEPROM.write(21,tacticalTimeColor[0]);
EEPROM.write(22,tacticalTimeColor[1]);
EEPROM.write(23,tacticalTimeColor[2]);
EEPROMDataNotSaved = true;
}else if(s_set == "dcolor"){
dateColor[0] = c[0];
dateColor[1] = c[1];
dateColor[2] = c[2];
EEPROM.write(31,dateColor[0]);
EEPROM.write(32,dateColor[1]);
EEPROM.write(33,dateColor[2]);
EEPROMDataNotSaved = true;
}else if(s_set == "kwcolor"){
kwColor[0] = c[0];
kwColor[1] = c[1];
kwColor[2] = c[2];
EEPROM.write(41,kwColor[0]);
EEPROM.write(42,kwColor[1]);
EEPROM.write(43,kwColor[2]);
EEPROMDataNotSaved = true;
}
}else if((s_set == "option")) {
if(request->hasParam(PARAM_BRIGHTNESS)) {
s_value = request->getParam(PARAM_BRIGHTNESS)->value();
brightness = s_value.toFloat();
EEPROM.put(5,brightness);
EEPROMDataNotSaved = true;
display->setPanelBrightness(ceil(255 * brightness));
}
if(request->hasParam(PARAM_OPTIONS)) {
s_value = request->getParam(PARAM_OPTIONS)->value();
options = s_value.toInt();
EEPROM.put(1,options);
EEPROMDataNotSaved = true;
withSeconds = bitRead(options,0);
alwaysAccessPoint = bitRead(options,1);
display->clearScreen();
}
}else if((s_set == "wifi")) {
if((request->hasParam(PARAM_SSID)) && (request->hasParam(PARAM_PWD))){
s_value = request->getParam(PARAM_SSID)->value();
s_value2 = request->getParam(PARAM_PWD )->value();
if((s_value != ssid) || (s_value2 != pass)){
s_value.toCharArray(ssid, 30);
s_value2.toCharArray(pass, 30);
EEPROM.put(101,ssid);
EEPROM.put(201,pass);
EEPROMDataNotSaved = true;
}
}
}else if((s_set == "appass")) {
if(request->hasParam(PARAM_PWD)){
s_value2 = request->getParam(PARAM_PWD )->value();
if((s_value2 != appass)){
s_value2.toCharArray(appass, 30);
EEPROM.put(151,appass);
EEPROMDataNotSaved = true;
}
}
}
request->send(200, "text/plain", "OK");
lastminutes = -1;
}else if (request->hasParam(PARAM_SAVE)){
EEPROM.commit();
EEPROMDataNotSaved = false;
request->send(200, "text/plain", "OK");
}else if (request->hasParam(PARAM_RESET)){
request->send(200, "text/plain", "OK");
delay(1000);
ESP.restart();
}
request->send(200, "text/plain", "NOK");
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,560 @@
const char html_page_index[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<title>N-Tools.de Uhr</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta charset="UTF-8">
<link rel="icon" href="data:,">
<style>
html {font-family: Roboto, Arial; display: inline-block; text-align: center;}
body {font-size: 1.5rem; margin:0px auto; padding-bottom: 25px; min-height:100%;}
body * {font-size: 1.3rem;}
input[type=checkbox]{
transform: scale(1.5);
padding: 10px;
position: relative;
}
label {min-width: 150px;display: inline-block;text-align: left; padding-left: 5px;}
input,select,option { display: inline-block;text-align:center;}
h1,h2,h3{padding:0px;margin:0px;)}
h1{font-size: 1.7rem;}
.head{
background: linear-gradient(to bottom, #1b62d8 0%, #003399 100%);
text-align: right;
margin: 0px;
padding: 5px;
box-shadow: 0 8px 32px 0 rgb(0 0 0 / 40%), 0 3px 20px 0 rgb(0 0 0 / 38%);
color:#fff;
}
.site{
}
.option {
margin: 20px;
padding: 10px;
box-shadow: 0 16px 32px 0 rgb(0 0 0 / 40%), 0 6px 20px 0 rgb(0 0 0 / 38%);
min-width: 160px;
border-radius: 4px;
background-color: #fff;
display: inline-grid;
text-align: center;
overflow: hidden;
opacity: 0.8;
}
.value {
cursor: pointer;
display: block;
}
.act{
background-color: #000;
color: #fff;
padding: 2px 5px 2px 5px;
}
.m50{
min-width: 50%;
}
.fs25{
font-size: 2.5rem;
}
.fs12{
font-size: 1.2rem;
}
.fs17{
font-size: 1.7rem;
}
.fs075, .fs075 *{
font-size: 0.75rem;
}
.left{
text-align: left;
}
.margin25left{
margin-left: 25%;
}
.margin12left{
margin-left: 12%;
}
#te{
display: none;
position: fixed;
top: 10%;
left: 10%;
margin: auto;
padding: 3%;
box-shadow: 0 16px 32px 0 rgb(0 0 0 / 40%), 0 6px 20px 0 rgb(0 0 0 / 38%);
min-height: 70%;
width: 74%;
border-radius: 8px;
background-color: #fff;
text-align: center;
overflow: hidden;
opacity: 1.0;
}
#te > .value{
text-align: left;
}
#oe{
display: none;
position: fixed;
top: 10%;
left: 10%;
margin: auto;
padding: 3%;
box-shadow: 0 16px 32px 0 rgb(0 0 0 / 40%), 0 6px 20px 0 rgb(0 0 0 / 38%);
min-height: 70%;
width: 74%;
border-radius: 8px;
background-color: #fff;
text-align: center;
overflow: hidden;
opacity: 1.0;
}
#oe > .value{
text-align: left;
}
#close{
cursor: pointer;
text-align: right;
display: block;
}
#message{
display: none;
position: fixed;
top: 10%;
left: 35%;
margin: auto;
padding: 5px;
box-shadow: 0 16px 32px 0 rgb(0 0 0 / 40%), 0 6px 20px 0 rgb(0 0 0 / 38%);
width: 30%;
border-radius: 4px;
z-index: 9999;
}
input[type=button], input[type=submit], input[type=reset] {
background-color: #1b62d8;
border: none;
cursor: pointer;
color: #fff;
position: relative;
text-decoration: none;
text-transform: uppercase;
padding: 0.25rem 0.5rem;
@media(min-width: 600px) {
margin: 0 1em 2em;
}
&:hover { text-decoration: none; }
box-shadow: inset 0 0 20px rgba(255, 255, 255, 0);
outline: 1px solid;
outline-color: rgba(255, 255, 255, .5);
outline-offset: 0px;
text-shadow: none;
border-radius: 4px;
}
input[type=button]:hover {
box-shadow: 0 16px 32px 0 rgb(0 0 0 / 40%), 0 6px 20px 0 rgb(0 0 0 / 38%);
outline-color: rgba(255, 255, 255, 0);
outline-offset: 15px;
text-shadow: 1px 1px 2px #427388;
}
.wsnw{
white-space: nowrap;
}
.center{
text-align: center;
}
</style>
</head>
<body>
<div id="head" class="head">
<h1>N-Tools Design Uhr</h1>
<h3>`VERSION`</h3>
<h3>`ID`</h3>
<span style='font-size: 0.7rem;'>lokale IP: `LOCALIP`</span>
</div>
<div id="site" class="site">
<div id="message"></div>
<div class='option' onclick="editTime(-1);">
<div class='value'>
<label class="center">aktuell:</label><br>
<span class='act' id="actTime"></span><br>
<span class='act' id="actTacTime"></span><br>
<span class='act' id="actDate"></span><br>
<span class='act' id="actKW"></span>
</div><br>
<div class='fs075'>
<label>letzter abgleich:</label>
<span id="sync"></span>
</div>
</div><br>
<br>
<div class='option m50'>
<label for="showWhat">Zeige</label>
<select id="showWhat" onchange="setShowWhat();">
<option value=0>taktische Uhrzeit</option>
<option value=1>Uhrzeit</option>
<option value=2>Datum / Uhrzeit</option>
<option value=3>Wormser</option>
</select>
</div>
<div class='option m50' onclick="return false">
<span class="wsnw">
<label for="brigtness">Helligkeit LEDs</label>
<span><span id="brigtness"></span> %</span><br>
</span>
<div class="left">
<span class="wsnw">
<label for="SSID">SSID:</label>
<span id="SSID"></span>
</span>
<br>
<input type="button" onclick="editOption();" value="Optionen ändern"><br>
<br>
<span class="wsnw">
<input id="rtcactive" type='checkbox' onclick="return false" readonly>
<label for="rtcactive">RTC okay</label>
</span>
<span class="wsnw">
<input id="withSeconds" type='checkbox' onclick="return false" readonly>
<label for="withSeconds">Sekunden zeigen</label>
</span>
<span class="wsnw">
<input id="isSummerTime" type='checkbox' onclick="return false" readonly>
<label for="isSummerTime">Sommerzeit</label>
</span>
<span class="wsnw">
<input id="alwaysAccessPoint" type='checkbox' onclick="return false" readonly>
<label for="alwaysAccessPoint">AccessPoint erstellen auch bei erfolgreicher WiFi Verbindung</label>
</span>
</div>
</div>
<input id="d" type='text' style='width:80%;font-size:0.75rem;display:none;' value=''>
<div class='option m50'>
<input class="fs17" id="save" class="btn" type='button' value='dauerhaft speichern' onclick='save();'>
</div>
<div class='option m50'>
<input class="fs17" id="reset" class="btn" type='button' value='neu starten' onclick='reset();'>
</div>
<div id="te">
<div id="close" onclick="closeEdit();">X</div>
<div class='value'>
<h1><span id="el"></span></h1>
<label for="eActTimeC">Uhrzeit: </label><input type="color" id="eActTimeC" value=""><br>
<label for="eActTacTimeC">taktische Zeit: </label><input type="color" id="eActTacTimeC" value=""><br>
<label for="eActDateC">Datum: </label><input type="color" id="eActDateC" value=""><br>
<label for="eActKWC">KW: </label><input type="color" id="eActKWC" value=""><br>
<input type="button" class="btn fs12" onclick="setColor();closeEdit();" value="setzen"><br><br>
<input type="button" id="doSetTime" class="btn fs12" onclick="doSetTime();" value="Uhrzeit nach diesem Gerät setzen"><br>
</div>
</div>
<div id="oe">
<div id="close" onclick="closeOptionEdit();">X</div>
<div class='value'>
<h1><span id="el">Optionen</span></h1>
<input id="ebs" type='number' min="5" max="100" step="5"> %
<label for="ebs">Helligkeitsfaktor (in Prozent)</label><br>
<span>
<input id="eWithSeconds" type='checkbox'>
<label for="eWithSeconds">zeige Sekunden</label>
</span>
<span>
<input id="eAlwaysAccessPoint" type='checkbox'>
<label for="eAlwaysAccessPoint">AccessPoint erstellen auch bei erfolgreicher WiFi Verbindung</label>
</span>
<br>
<input type="button" class="btn" onclick="setOption();" value="setzen">
<br><br>
<span>
<label for="eSSID">SSID:</label>
<input id="eSSID" type='text' onclick="return false">
</span>
<br>
<span>
<label for="ePASS">Passwort:</label>
<input id="ePASS" type='text' onclick="return false">
</span>
<br>
<input type="button" class="btn" onclick="setWifi();" value="setzen">
<br><br>
<span>
<label for="apPASS">AccessPoint Passwort:</label>
<input id="apPASS" type='text' maxlength="64" minlength="8" onclick="return false">
</span>
<br>
<input type="button" class="btn" onclick="setAPPass();" value="setzen"><br>
</div>
</div>
</div>
<script>
var ti = new Date;
var EEPROMDataChanged = false;
function RGBToHex(rgb) {
// Choose correct separator
let sep = rgb.indexOf(",") > -1 ? "," : " ";
// Turn "rgb(r,g,b)" into [r,g,b]
rgb = rgb.substr(4).split(")")[0].split(sep);
let r = (+rgb[0]).toString(16),
g = (+rgb[1]).toString(16),
b = (+rgb[2]).toString(16);
if (r.length == 1)
r = "0" + r;
if (g.length == 1)
g = "0" + g;
if (b.length == 1)
b = "0" + b;
console.log("#" + r + g + b);
return "#" + r + g + b;
}
function closeEdit(){
document.getElementById("te").style.display = "none";
}
function editTime(_what){
if(_what == -1){
document.getElementById("el").innerHTML = 'Farben';
document.getElementById("eActTimeC").value = RGBToHex(document.getElementById('actTime').style.color);
document.getElementById("eActTacTimeC").value = RGBToHex(document.getElementById('actTacTime').style.color);
document.getElementById("eActDateC").value = RGBToHex(document.getElementById('actDate').style.color);
document.getElementById("eActKWC").value = RGBToHex(document.getElementById('actKW').style.color);
}
document.getElementById("te").style.display = "initial";
}
function closeOptionEdit(){
document.getElementById("oe").style.display = "none";
}
function editOption(){
document.getElementById('ebs').value = document.getElementById('brigtness').innerHTML;
document.getElementById('eSSID').value = document.getElementById('SSID').innerHTML;
document.getElementById("eWithSeconds").checked = document.getElementById("withSeconds").checked;
document.getElementById("eAlwaysAccessPoint").checked = document.getElementById("alwaysAccessPoint").checked;
document.getElementById("oe").style.display = "initial";
}
Number.prototype.AddZero= function(b,c){
var l= (String(b || 10).length - String(this).length)+1;
return l>0? new Array(l).join(c || '0')+this : this;
}
function showOK(){
document.getElementById("message").innerHTML='ok';
document.getElementById("message").style.backgroundColor = "#0f0";
document.getElementById("message").style.display = "initial";
setTimeout(function(){
document.getElementById("message").style.display = "none";
}, 2000);
}
function fetchHandle(res){
if(!res.ok){
console.log(res);
document.getElementById("site").style.backgroundColor = "#f00";
}else{
if(EEPROMDataChanged)
document.getElementById("site").style.backgroundColor = "#ffa";
else
document.getElementById("site").style.backgroundColor = "#fff";
return res;
}
}
function fetch_handle_response(res){
var elem=document.getElementById('d');
elem.value=res;
if(res == 'OK'){
showOK();
}else if(res[0] == '['){
try{
var data = JSON.parse(res);
ti = data[0];
showAktTimeFromUnix(ti);
colorString = "#" + data[1].toString(16).padStart(6, '0');
document.getElementById('actTime').style.color = colorString;
colorString = "#" + data[2].toString(16).padStart(6, '0');
document.getElementById('actTacTime').style.color = colorString;
colorString = "#" + data[3].toString(16).padStart(6, '0');
document.getElementById('actDate').style.color = colorString;
document.getElementById('showWhat').value = parseInt(data[4]);
switch(data[5]){
case 0:
document.getElementById('sync').innerHTML = " keiner";
break;
case 1:
document.getElementById('sync').innerHTML += " (GPS)";
break;
case 2:
document.getElementById('sync').innerHTML += " (NTP)";
break;
case 3:
document.getElementById('sync').innerHTML += " (manuel)";
break;
}
showTimeFromUnix(data[6],'sync');
document.getElementById('brigtness').innerHTML = (data[7]*100);
document.getElementById("rtcactive").checked = (data[8] == 1);
EEPROMDataChanged = (data[9] == 1);
if(EEPROMDataChanged){
document.getElementById("site").style.backgroundColor = "#ffa";
}
document.getElementById('SSID').innerHTML = data[10];
var options = parseInt(data[11]);
document.getElementById("withSeconds").checked = (options >> 0) & 0x1;
document.getElementById("alwaysAccessPoint").checked = (options >> 1) & 0x1;
colorString = "#" + data[12].toString(16).padStart(6, '0');
document.getElementById('actKW').style.color = colorString;
document.getElementById('actKW').innerHTML = "KW " + data[13];
document.getElementById("isSummerTime").checked = (data[14] == 1);
}catch(e){
console.log(e);
}
}
}
function doSend(_value1,_value2=[],_value3=[]){
var send_str = "/do?"+_value1[0]+"="+_value1[1];
if(_value2.length > 0){
send_str += "&"+_value2[0]+"="+_value2[1];
}
if(_value3.length > 0){
send_str += "&"+_value3[0]+"="+_value3[1];
}
fetch(send_str).then(fetchHandle).then((res) => res.text()).then((text) => fetch_handle_response(text)).catch((err) => { console.log(err);document.getElementById("site").style.backgroundColor = "#f00";});
}
function doPoll(){
var send_str = "/poll";
fetch(send_str).then(fetchHandle).then((res) => res.text()).then((text) => fetch_handle_response(text)).catch((err) => { console.log(err);document.getElementById("site").style.backgroundColor = "#f00";});
}
function doSetTime(_idx = -1){
var d=new Date();
d.setTime(d.getTime() - (d.getTimezoneOffset()*60*1000) + 1000);
doSend(['set','time'],['to',Math.floor(d /1000)],['idx',_idx]);
}
function setColor(){
var elem=document.getElementById('eActTimeC');
doSend(['set','color'],['to',elem.value.substring(1)]);
elem=document.getElementById('eActTacTimeC');
doSend(['set','tcolor'],['to',elem.value.substring(1)]);
elem=document.getElementById('eActDateC');
doSend(['set','dcolor'],['to',elem.value.substring(1)]);
elem=document.getElementById('eActKWC');
doSend(['set','kwcolor'],['to',elem.value.substring(1)]);
}
function setTimeFromUnix(_ti,_id){
var elem=document.getElementById(_id);
//var st = String(new Date(_ti*1000).toISOString().substr(0,19));
var st = new Date(parseInt(_ti) * 1000);
var sst = st.toISOString().slice(0,19);
elem.value = sst;
}
function showAktTimeFromUnix(_ti){
var elem=document.getElementById('actTime');
var elem2=document.getElementById('actTacTime');
var elem3=document.getElementById('actDate');
var st = new Date(parseInt(_ti) * 1000);
st.setTime(st.getTime() + (st.getTimezoneOffset()*60*1000));
//var sst = st.toUTCString();
var sstTime = ("0" + st.getHours()).slice(-2) + ":" + ("0" + st.getMinutes()).slice(-2) + ":" + ("0" + st.getSeconds()).slice(-2);
elem.innerHTML = sstTime;
const formatter = new Intl.DateTimeFormat('en', { month: 'short' });
const month = formatter.format(st);
var sstTacTime = ("0" + st.getDate()).slice(-2) + "" + ("0" + st.getHours()).slice(-2) + "" + ("0" + st.getMinutes()).slice(-2) + month.toLowerCase() + ("" + st.getFullYear()).slice(-2);
elem2.innerHTML = sstTacTime;
var sstDate = ("0" + st.getDate()).slice(-2) + "." + ("0"+(st.getMonth()+1)).slice(-2) + "." +st.getFullYear();
elem3.innerHTML = sstDate;
}
function showTimeFromUnix(_ti,_id){
var elem=document.getElementById(_id);
var st = new Date(parseInt(_ti) * 1000);
st.setTime(st.getTime() + (st.getTimezoneOffset()*60*1000));
//var sst = st.toUTCString();
var sst = ("0" + st.getDate()).slice(-2) + "." + ("0"+(st.getMonth()+1)).slice(-2) + "." +st.getFullYear() + " " + ("0" + st.getHours()).slice(-2) + ":" + ("0" + st.getMinutes()).slice(-2) + ":" + ("0" + st.getSeconds()).slice(-2);
elem.innerHTML = sst;
}
function setShowWhat(_what = -2){
if(_what == -2){
var elem=document.getElementById("showWhat");
doSend(['set','option'],['showWhat',elem.value]);
}else{
doSend(['set','option'],['showWhat',_what]);
}
}
function setBrightness(){
var elem=document.getElementById("ebs");
doSend(['set','option'],['brightness',(elem.value / 100)]);
}
function setWifi(){
var elem=document.getElementById("eSSID");
var elem2=document.getElementById("ePASS");
doSend(['set','wifi'],['ssid',encodeURIComponent(elem.value)],['pwd',encodeURIComponent(elem2.value)]);
}
function setAPPass(){
var elem=document.getElementById("apPASS");
var pwd = String(elem.value);
if(((pwd.length > 7) && (pwd.length < 65)) || (pwd.length==0)){
doSend(['set','appass'],['pwd',encodeURIComponent(pwd)]);
elem.value = '';
}else{
alert('Das AccessPoint Passwort muss leer oder zwischen 8 und 64 Zeichen lang sein!');
}
}
function setOption(){
setBrightness();
var option = 0;
if(document.getElementById("eWithSeconds").checked)
option += 1;
if(document.getElementById("eAlwaysAccessPoint").checked)
option += 2;
doSend(['set','option'],['options',option]);
}
function save() {
doSend(['save','']);
}
function reset() {
doSend(['reset','']);
}
function poll() {
doPoll();
setTimeout(function(){
poll();
}, 1000);
}
document.addEventListener("DOMContentLoaded", function(event) {
poll();
});
</script>
</body>
</html>
)rawliteral";