/*
  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");
}

