/*
 * 
 * 
 * Web related stuff 
 * 
 * 
 */

/*
 * 
 * return functions, they return things for the web stuff
 */

String returnHTMLheader(String MenuEntry = "") {
  String header;
  String activeMenu = "class='activeMenu'";
  // add first part of the header
  header += FPSTR(HTMLheaderP1);
  // add title tag 
  header += "<title>";
  // check if GrowName was set. if yes, its part of the page title.
  if(strlen(GrowName) > 0) {
    header += "CanGrow - ";
    header += GrowName;
  } else {
    header += "CanGrow";
  }
  // close title tag
  header += "</title>\n";
  
  // add additional header stuff, like loading guage files
  if(MenuEntry == "root") {
    header += "<link rel='stylesheet' type='text/css' href='gauge.css'>";
  }
  
  header += FPSTR(HTMLheaderP2);
  
  // first menu entry
  header += "<li><a  href='/'>&#x1F331; ";
  if(strlen(GrowName) > 0) {
    header += GrowName;
  } else {
    header += "CanGrow";
  }
  header += "</a></li>\n";
  
  // second menu entry
  header += "<li><a href='/growSettings' ";
  if(MenuEntry == "growSettings") {
      header += activeMenu;
    } 
  header += ">&#128262; Grow settings</a></li>\n";
  
	// third menu entry
  header += "<li><a href='/systemSettings' ";
  if(MenuEntry == "systemSettings") {
      header += activeMenu;
    } 
  header += ">&#9881; System settings</a></li>\n";
  
  // fourth menu entry
  header += "<li><a href='/wifiSettings' ";
  if(MenuEntry == "wifiSettings") {
      header += activeMenu;
    } 
  header += ">&#128225; WiFi settings</a></li>\n";
  
  // fifth menu entry
  header += "<li><a href='/help' ";
  if(MenuEntry == "help") {
      header += activeMenu;
    } 
  header += ">&#x2753; Help</a></li>\n";
  
  // sixth menu entry - time and status icons / info
  header += "<li><span class='MenuTime'>";
  header += timeClient.getFormattedTime();
  // status icons and info
  if(MaintenanceMode == true) {
    // status icons
    header += " | &#9208;&#65039; ";
    header += MaintenanceDuration - ((millis() - MaintenanceStarted) / 1000);
    header += "s";
  }
  header += "</span></li>\n";


  // CanGrow Version
  header += "<li><a href='https://git.la10cy.net/DeltaLima/CanGrow' target='_blank'>CanGrow v";
  header += CANGROW_VER;
  header += "</a></li>\n";
  
  // close <ul> and start <div>
  header += "</ul><div class='center'>";
  
  if(NeedRestart == true) {
    header += FPSTR(HTMLneedRestart);
  }
  
  return header;
}

/*
 * returnSelected(bool)
 * returns char[] "selected" if bool is true
 * useful for html forms, to represet a saved value as selected
 */
String returnStrSelected(byte savedValue, byte selectId) {
  String returnStr;
  
  if(configured == true) {
    if(savedValue == selectId) {
      returnStr = " selected ";
    } else {
      returnStr = "";
    }
  }
  
  return returnStr;
}

String returnStrDateFromEpoch(unsigned long epochTime) {
  String dateStr;
  byte Day = day(epochTime);
  byte Month = month(epochTime);
  unsigned int Year = year(epochTime);
  
  dateStr = Year;
  dateStr += "-";
  
  if(Month < 10) {
    dateStr += "0";
    dateStr += Month;
  } else {
    dateStr += Month;
  }
  
  dateStr += "-";
  
  if(Day < 10) {
    dateStr += "0";
    dateStr += Day;
  } else {
    dateStr += Day;
  }
  
  return dateStr;
}


/*
 * 
 * System pages like infos, errors
 * 
 */
 
void SysRestart() {
  String body = returnHTMLheader();
  // TODO only debug and development solution, remove this later
  if( (webserver.hasArg("confirmed")) || (NeedRestart == true) ) {
    body += "<h1>&#10071; Restarting</h1>";
    body += "<div class='infomsg'>After restart CanGrow will be connected to WiFi SSID<br><b>";
    body += WIFIssid;
    body += "</b><br>You get its IP-Address from the display or serial console.</div>";
    body += FPSTR(HTMLfooter);
    webserver.send(200, "text/html", body);
    Serial.println("Restarting... see you soon space cowboy!");
    delay(1000);
    ESP.restart();
  } else {
    body += "<h1>&#10071; Restart CanGrow</h1>";
    body += "<div class='infomsg'>Do you want to restart CanGrow?";
    body += "<br>Please confirm.";
    body += "<form action='/system/restart'><input type='hidden' name='confirmed' value='true' /><input type='submit' value='Confirm restart' /></form>";
    body += "</div>";
    body += FPSTR(HTMLfooter);
    webserver.send(200, "text/html", body);
  }
}

void SysWipe() {
  String body = returnHTMLheader();
  body += "<h1>&#10071;&#10071; Wiping EEPROM</h1>";
  body += "<div class='warnmsg'>All settings will be removed!!<br>";
  body += "<br>Please confirm wiping the EEPROM";
  body += "<form action='/system/wipeConfirm' method='post'><br>Please confirm: <input type='checkbox' id='confirm' name='confirm' required /><br><input type='submit' value='Confirm wiping' /></form>";
  body += "</div>";
  body += FPSTR(HTMLfooter);
  webserver.send(200, "text/html", body);

}


void Sys404() {
  String body = returnHTMLheader();
  body += "<div class='warnmsg'><h1>&#10071; &#65039; 404 - not found</h1></div>";
  body += FPSTR(HTMLfooter);
  webserver.send(404, "text/html", body);
}

void Syslogout() {
  String body = returnHTMLheader();
  body += "<h1>you are logged out.</h1>";
  body += FPSTR(HTMLfooter);
  
  // TODO does not work atm
  webserver.send(401, "text/html", body);  
}

void SysMaintenance() {
  String body = returnHTMLheader();
  
  // when requesting to handle Dimming 
  if( (webserver.hasArg("DimmOn")) || (webserver.hasArg("DimmOff")) ) {
    // check first if PWM is disabled / relais is used
    if(UseLEDrelais == true) {
      // if not, do it
      if( (webserver.hasArg("DimmOn")) ) {
        MaintenanceMode = true;
        MaintenanceStarted = millis();
        body += "<div class='infomsg'>&#x26C5; Dimm LED On for ";
        body += MaintenanceDuration;
        body += "s</div>";
      } else if( (webserver.hasArg("DimmOff")) ) {
        MaintenanceMode = false;
        body += "<div class='infomsg'>&#x26C5; Dimm LED Off</div>";
      }
    } else {
      // otherwise nice error
      body += "<div class='warnmsg'>&#x26C5; LED setting <pre>Use relais for LED (disable PWM)<pre> is set to <b>Yes</b> in &#128262; Grow settings</div>";
      
    }
  } else if(webserver.hasArg("PumpOnManual")) {
    if(UsePump == true) {
      PumpOnManual = true;
      body += "<div class='infomsg'>&#x1F4A7; Pump manual activated for ";
      body += PumpOnTime;
      body += "s</div>";
    } else {
      body += "<div class='warnmsg'>&#x1F4A7; Pump mode is set to <b>Off</b> in &#128262; Grow settings</div>";
    }
  }

  
  body += "<h2>&#x1f9f0; Maintenance</h2>";
  
  body += "Dimm LED <a class='button' href='/system/maintenance?DimmOn=1'>&#x26C5; On</a>&nbsp;&nbsp;<a class='button' href='/system/maintenance?DimmOff=1'>&#x2600;&#xfe0f; Off</a><br><br><br>";
  body += "Pump manual <a class='button' href='/system/maintenance?PumpOnManual=1'>&#x1F4A7; Activate for ";
  body += PumpOnTime;
  body += "s</a><br>";
  
  
  
  
  body += FPSTR(HTMLfooter);
  webserver.send(200, "text/html", body);
}

void SysUpdate() {
  String body = returnHTMLheader();
  
  body += "<h2>&#x1F504; Firmware update</h2>";
  
  body += "<b>Version:</b> ";
  body += CANGROW_VER;
  body += "<br><b>Build:</b> ";
  body += CANGROW_BUILD;
  
  body += FPSTR(HTMLupdate);
  
  body += FPSTR(HTMLfooter);
  webserver.send(200, "text/html", body);
}

  /*
   * TODO
   * DOES NOT WORK WHEN CONNECTED TO EXISTING WIFI
   * IDK WHY
   * 
   
   * void WebAuth() {
   * 
   * char webAuthRealm[] = "CanGrowRealm";
   *   if(!webserver.authenticate(WebUiUsername, WebUiPassword)) {
   *     String body = FPSTR(HTMLheader);
   *     body += "<h1>Login failed.</h1>";
   *     body += FPSTR(HTMLfooter);
   *     webserver.requestAuthentication(DIGEST_AUTH, webAuthRealm, body);
   *   }
   * }
   * 
   * void WebAuthApi() {
   *
   * TODO
   * DOES NOT WORK WHEN CONNECTED TO EXISTING WIFI
   * IDK WHY
   * 
   *
   *   char webAuthRealm[] = "CanGrowRealm";
   *   if(!webserver.authenticate(WebUiUsername, WebUiPassword)) {
   *     webserver.requestAuthentication(DIGEST_AUTH, webAuthRealm);
   *   }
   * }
   */

/*
 * 
 * Main UI pages
 * 
 */

/*
 * Gauge meter files
 */
void WEBgaugeCss() {
  //String css = CSSgauge;
  webserver.send(200, "text/css", FPSTR(CSSgauge));
}

void WEBgaugeJs() {
  //String javascript = JSgauge;
  webserver.send(200, "text/javascript", FPSTR(JSgauge));
}

/*
 * Root page
 */

void WEBroot() {
  if(FirstRun == true) {
      webserver.sendHeader("Location", String("/wifiSettings"), true);
      webserver.send(302, "text/plain", "please configure wifiSettings first");
    } else if(configured == false){
      webserver.sendHeader("Location", String("/systemSettings"), true);
      webserver.send(302, "text/plain", "please configure systemSettings first");
    } else if(strlen(GrowName) < 1){
      webserver.sendHeader("Location", String("/growSettings"), true);
      webserver.send(302, "text/plain", "please configure growSettings first");
    } else {
    String body = returnHTMLheader("root");
    
    body += "<h2>&#x1F331; ";
    body += GrowName;
    body += "</h2>";
    
    // add gauge meter
    body += FPSTR(HTMLgauge);
    // and give javascript the values
    // todo: auto refresh by api call
    body += "<script>";
    
    body += "gaugeTemperature.value('";
    body += valTemperature;
    body += "', 42, ' °C'); ";
    
    body += "gaugeHumidity.value('";
    body += valHumidity;
    body += "'); ";
    
    body += "gaugeSoilmoisture.value('";
    body += valSoilmoisture;
    body += "'); ";
    
    body += "</script><br>\n";
    
    // when an ESP32-Cam IP is given, display picture from it
    if(strlen(Esp32CamIP) > 0) {
      body += "<a href='http://";
      body += Esp32CamIP;
      body += "' target='_blank'><img class='centered' src='http://";
      body += Esp32CamIP;
      body += "/capture' alt='Image capture from ESP32CAM at ";
      body += Esp32CamIP;
      body += "'></a>\n<br>\n";
    }
    
    body += "<b>Grow started: &#x1F5D3;&#xFE0F;</b> ";
    body += returnStrDateFromEpoch(GrowStart);
    body += "<br>\n";
    body += "<b>Day of Grow: </b> ";
    if(DayNight == true) {
      body += " &#x1F31E; ";
    } else {
      body += " &#x1F31A; ";
    }
    body += DayOfGrow;
    body += "<br>\n";
    body += "<b>Grow status:</b> ";
    switch(growState()) {
      case 1:
        body += "&#x1F331; vegetation<br>\n";
      break;  
      case 2:
        body += "&#x1F33C; bloom (";
        body += DayOfGrow - DaysVeg;
        body += ")<br>\n";
      break;
      case 3: 
        body += "&#x1F342; harvest (";
        body += DayOfGrow - (DaysVeg + DaysBloom);
        body += ")<br>\n";
      break;
    }
    
    // VPD
    body += "<b>VPD (est.): ";
    // apply text color to the value according to this chart
    if(valVPD < 0) {
      body += "&#x26A0;&#xFE0F; <span class=''>";
      body += valVPD;
      body += "</span></b> (Danger! Check for disease!)";
    } else if(valVPD < 0.4 ) {
      body += "&#x26A0;&#xFE0F; <span class='vpd_danger1'>";
      body += valVPD;
      body += "</span></b> (Danger! Under transpiration!)";
    } else if(valVPD < 0.8 ) {
      body += "&#x1F343; <span class='vpd_earlyveg'>";
      body += valVPD;
      body += "</span></b> (Early vegetation)";
    } else if(valVPD < 1.2 ) {
      body += "&#x1F343; <span class='vpd_lateveg'>";
      body += valVPD;
      body += "</span></b> (Late vegetation)";
    } else if(valVPD < 1.6 ) {
      body += "&#x1F343; <span class='vpd_latebloom'>";
      body += valVPD;
      body += "</span></b> (Late bloom)";
    } else if(valVPD > 1.6 ) {
      body += "&#x26A0;&#xFE0F; <span class='vpd_danger2'>";
      body += valVPD;
      body += "</span></b> (Danger - over transpiration!)";
    }
    body += "<br>\n";
    
    
    if(UsePump > 0) {
      body += "<b>Pump water level:</b> ";
      switch(getWaterlevel()) {
        case 0:
          body += "<span style='color: green;'>OK</span>";
          break;
        case 1:
          body += "<span style='color: yellow;'>Warning</span>";
          break;
        case 2: 
          body += "<span style='color: red;'>Critical</span>";
          break;
      }
      body += "<br>\n";
    }
    
    body += "<b>Growlight brightness:</b> ";
    body += ((PinLEDPWM * 100) / 255);
    body += " %<br>\n";

    
    //~ body += "<form method='post' action='/switch'>\n";
    //~ body += "<b>MOSFET:</b> <select id='output' name='output' >\n";
    //~ body += "<option disabled value='' selected hidden>---</option>\n";
    //~ body += "<option value='1'>LED</option>\n";
    //~ body += "<option value='2'>FAN</option>\n";
    //~ body += "<option value='3'>PUMP</option>\n";
    //~ body += "</select><br>";
    
    //~ body += "<b>On/Off:</b> <select id='state' name='state' >\n";
    //~ body += "<option disabled value='' selected hidden>---</option>\n";
    //~ body += "<option value='1'>On</option>\n";
    //~ body += "<option value='0'>Off</option>\n";
    //~ body += "</select><br>\n";
    
    //~ body += "<b>Intensity:</b> <input type='range' id='OutputPWM' name='OutputPWM' min='1' max='255' value='255'/><br>\n";
    
    //~ body += "<input type='submit' value='Save'>\n";
    //~ body += "</form><br>\n";
    body += "<br><a class='button' href='/system/maintenance'>&#x1f9f0; Maintenance</a>";
    
    
    body += FPSTR(HTMLfooter);
    
    webserver.send(200, "text/html", body);
  }
}  

/*
 * 
 * settings pages
 * 
 * 
 */

/*
 * Grow page
 */
void WEBgrowSettings() {
  // if system settings are unconfigured, we cannot proceed with growSettings
  if(configured == false) {
      webserver.sendHeader("Location", String("/systemSettings"), true);
      webserver.send(302, "text/plain", "please configure systemSettings first");
    } else {
  
    String body = returnHTMLheader("growSettings");
    
    if(strlen(GrowName) < 1) {
      body += "<h1>Final step: Grow settings</h1>";
      body += "<p>Please configure all settings<br>";
      body += "</p>";
      GrowStart = timeClient.getEpochTime();
    }
    
    body += "<h2>&#128262; Grow settings</h2>";
    if(webserver.hasArg("success")) {
      body += FPSTR(HTMLsuccess);
    } 
    body += "<p>Here you can set everything grow related, like light hours, how much water, LED brightness<br>";
    body += "</p>";
    
    body += "<form method='post' action='/growSettings/save'>\n";
    
  
    
    body += "Grow name: <input type='text' name='GrowName' maxlength='31' value='";
    body += GrowName;
    body+= "' required><br>\n";
    
    
    body += "<input type='hidden' id='GrowStart' name='GrowStart' value='";
    body += GrowStart;
    body+= "' required>\n";
    
    // the input field, which calls javascript convertDateToEpoch() to write data to transmit to id GrowStart
    body += "Grow start date: <input type='date' id='GrowStart_sel' onChange='convertDateToEpoch(\"GrowStart_sel\", \"GrowStart\");' value='";
    body += returnStrDateFromEpoch(GrowStart);
    body += "' required><br><br>\n";
    
    
    
    body += "<b>Grow duration</b><br>";
    body += "Vegetation duration: <input class='inputShort' type='number' name='DaysVeg' min='0' max='255' value='";
    body += DaysVeg;
    body+= "' required> Days<br>\n";
    
    body += "Bloom duration: <input class='inputShort' type='number' name='DaysBloom' min='0' max='255' value='";
    body += DaysBloom;
    body+= "' required> Days<br><br>\n";
    
    
    body += "<b>Light configuration</b><br>";
    body += "LED ON vegetation: <input class='inputShort' type='number' name='LighthoursVeg' min='0' max='255' value='";
    body += LighthoursVeg;
    body+= "' required> Hours<br>\n";
    
    body += "LED ON bloom: <input class='inputShort' type='number' name='LighthoursBloom' min='0' max='255' value='";
    body += LighthoursBloom;
    body+= "' required> Hours<br>\n";
    
    body += "Sunrise: <input class='inputShort' type='number' name='SunriseHour' min='0' max='23' value='";
    body += SunriseHour;
    body+= "' required>\n";
    body += " <b>:</b> <input class='inputShort' type='number' name='SunriseMinute' min='0' max='59' value='";
    body += SunriseMinute;
    body+= "' required><br>\n";
    
    // SunFade bool
    body += "Fade in/out sunrise/sunset?: <select id='SunFade' name='SunFade' required>\n";
    body += "<option value='1'" + returnStrSelected(SunFade, 1) + ">Yes</option>\n";
    body += "<option value='0'" + returnStrSelected(SunFade, 0) + ">No</option>\n";
    body += "</select><br>\n";
    
    body += "Fade duration: <input class='inputShort' type='number' name='SunFadeDuration' min='1' max='255' value='";
    body += SunFadeDuration;
    body+= "' required> Minutes<br>\n";
    
    if(UseLEDrelais == false) {
      body += "LED brightness: <input type='range' id='PinLEDPWM' name='PinLEDPWM' min='0' max='255' value='";
      body += PinLEDPWM;
      body += "'/> %<br>\n";
    } else {
      body += "LED on/off: <select id='PinLEDPWM' name='PinLEDPWM' required>\n";
      body += "<option value='1'" + returnStrSelected(PinLEDPWM, 1) + ">On</option>\n";
      body += "<option value='0'" + returnStrSelected(PinLEDPWM, 0) + ">Off</option>\n";
      body += "</select><br>\n";
    }
    body += "<br>";
    
    body += "<b>Fan configuration</b><br>";
    if(UseFANrelais == false) {
      body += "FAN1 speed: <input type='range' id='PinFANPWM' name='PinFANPWM' min='0' max='255' value='";
      body += PinFANPWM;
      body += "'/> %<br>\n";
    } else {
      body += "FAN1 on/off: <select id='PinFANPWM' name='PinFANPWM' required>\n";
      body += "<option value='1'" + returnStrSelected(PinFANPWM, 1) + ">On</option>\n";
      body += "<option value='0'" + returnStrSelected(PinFANPWM, 0) + ">Off</option>\n";
      body += "</select><br>\n";
    }
    
    body += "FAN2 speed: <input type='range' id='PinFAN2PWM' name='PinFAN2PWM' min='0' max='255' value='";
    body += PinFAN2PWM;
    body += "'/> %<br><br>\n";
    









    body += "<b>Pump configuration</b><br>";

    // PumpMode byte
    body += "Pump mode: <select id='UsePump' name='UsePump' required>\n";
    if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    body += "<option value='0'" + returnStrSelected(UsePump, 0) + ">Off</option>\n";
    body += "<option value='1'" + returnStrSelected(UsePump, 1) + ">1</option>\n";
    body += "<option value='2'" + returnStrSelected(UsePump, 2) + ">2</option>\n";
    body += "<option value='3'" + returnStrSelected(UsePump, 3) + ">3</option>\n";
    body += "</select><br><p class='helpbox'><b>1:</b> Water every few days.<br> \
<b>2:</b> Water if the soil moisture falls below <i>Soilmoisture low</i> value<br> \
<b>3:</b> Water every few days if the soil moisture falls below <i>Soilmoisture low</i> value.</p>\n";

    // TODO ugly. can this done be better? 
    // PumpOnTime int
    body += "Pump ON time: <input class='inputShort' type='number' name='PumpOnTime' min='0' max='255' value='";
    body += PumpOnTime;
    body += "' required> Seconds<br>\n";

    // SoilmoistureLow byte
    body += "Soilmoisture low: <input class='inputShort' type='number' name='SoilmoistureLow' min='0' value='";
    body += SoilmoistureLow;
    body += "' required> %<br>\n";







    
    body += "Pump interval vegetation: every <input class='inputShort' type='number' name='PumpIntervalVeg' min='0' max='255' value='";
    body += PumpIntervalVeg;
    body += "' required> Days<br>\n";
    
    body += "Pump interval bloom: every <input class='inputShort' type='number' name='PumpIntervalBloom' min='0' max='255' value='";
    body += PumpIntervalBloom;
    body += "' required> Days<br><br>\n";
  
    
    body += "<input type='submit' value='&#x1F4BE; Save settings'>\n";
    body += "</form>\n"; 
    body += FPSTR(JSconvertDateToEpoch);
    body += FPSTR(HTMLfooter);
    
    webserver.send(200, "text/html", body);
  }
}

void WEBsystemSettings() {
  // if wifi settings are unconfigured, we cannot proceed with systemSettings
  if(FirstRun == true) {
      webserver.sendHeader("Location", String("/wifiSettings"), true);
      webserver.send(302, "text/plain", "please configure wifiSettings first");
    } else {
      
    String body = returnHTMLheader("systemSettings");
    
    if(configured == false) {
      body += "<h1>Step 2: System settings</h1>";
      body += "<p>Please configure all settings<br>";
      body += "</p>";
    }
    
    body += "<h2>&#9881; System settings</h2>";
    body += FPSTR(HTMLsystemSubNav);
    if(webserver.hasArg("success")) {
      body += FPSTR(HTMLsuccess);
    }  
    body += "<p>here you can set which features and sensors you use<br>";
    body += "</p>";
    
    // form starts
    body += "<form method='post' action='/systemSettings/save'>\n";
    
    // UseFan bool
    //~ body += "Fan mode: <select id='UseFan' name='UseFan' required>\n";
    //~ if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    //~ body += "<option value='1'" + returnStrSelected(UseFan, 0) + ">Off</option>\n";
    //~ body += "<option value='1'" + returnStrSelected(UseFan, 1) + ">Use</option>\n";
    //~ body += "<option value='0'" + returnStrSelected(UseFan, 2) + ">Do not use</option>\n";
    //~ body += "</select><br>\n";

/*  
    // UsePump bool
    body += "Use PUMP: <select id='UsePump' name='UsePump' required>\n";
    if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    body += "<option value='1'" + returnStrSelected(UsePump, 1) + ">Yes</option>\n";
    body += "<option value='0'" + returnStrSelected(UsePump, 0) + ">No</option>\n";
    body += "</select><br>\n";
*/
    
    body += "<b>Output configuration</b><br>";
    // OutputInvert bool
    body += "Invert Outputs: <select id='OutputInvert' name='OutputInvert' required>\n";
    if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    body += "<option value='0'" + returnStrSelected(OutputInvert, 0) + ">No</option>\n";
    body += "<option value='1'" + returnStrSelected(OutputInvert, 1) + ">Yes</option>\n";
    body += "</select><br>\n";
    body += "<p class='helpbox'>When using CanGrow PCB v0.6, set to <b>Yes</b></p>\n";

    // UseLEDrelais bool
    body += "Use relais for LED (disable PWM): <select id='UseLEDrelais' name='UseLEDrelais' required>\n";
    if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    body += "<option value='0'" + returnStrSelected(UseLEDrelais, 0) + ">No</option>\n";
    body += "<option value='1'" + returnStrSelected(UseLEDrelais, 1) + ">Yes</option>\n";
    body += "</select><br>\n";

    // UseFANrelais bool
    body += "Use relais for FAN1 (disable PWM): <select id='UseFANrelais' name='UseFANrelais' required>\n";
    if(configured == false){body += "<option disabled value='' selected hidden>---</option>\n";}
    body += "<option value='0'" + returnStrSelected(UseFANrelais, 0) + ">No</option>\n";
    body += "<option value='1'" + returnStrSelected(UseFANrelais, 1) + ">Yes</option>\n";
    body += "</select><br><br>\n";




    body += "<b>Sensor configuration</b><br>";

    // MoistureSensor_Type byte
    body += "Soilmoisture sensor: <select id='SelMoistureSensor_Type' name='MoistureSensor_Type' onchange='MoistureSensorType();' required>\n";
    if(configured == false) {
      body += "<option disabled value='' selected hidden>---</option>\n";
      }
    body += "<option value='1'" + returnStrSelected(MoistureSensor_Type, 1) + ">Analog capacitive</option>\n";
    body += "<option value='2'" + returnStrSelected(MoistureSensor_Type, 2) + ">I2C Chirp (0x20)</option>\n";
    body += "</select><br>\n";
  
    // SoilmoistureDry byte
    body += "Soilmoisture dry: <input type='number' id='iSoilmoistureDry' name='SoilmoistureDry' min='0' value='";
    body += SoilmoistureDry;
    body += "' required>\n";
    body += "<p class='helpbox'><b>Analog capacitive:</b> <i>360</i><br> \
<b>I2C Chirp:</b> <i>250</i></p>";

    // SoilmoistureWet byte
    body += "Soilmoisture wet: <input type='number' id='iSoilmoistureWet' name='SoilmoistureWet' min='0' value='";
    body += SoilmoistureWet;
    body += "' required>\n";
    body += "<p class='helpbox'><b>Analog capacitive:</b> <i>160</i><br> \
<b>I2C Chirp:</b> <i>485</i></p>";
    
    // MoistureSensor_Type Javascript
    body += FPSTR(JSsoilmoistureTypeSelect);

    
    // TemperatureSensor_Type byte
    body += "Temperature sensor: <select id='TemperatureSensor_Type' name='TemperatureSensor_Type' required>\n";
    if(configured == false) {
      body += "<option disabled value='' selected hidden>---</option>\n";
      }
    body += "<option value='1'" + returnStrSelected(TemperatureSensor_Type, 1) + ">I2C BME280 (0x76)</option>\n";
    body += "<option value='2'" + returnStrSelected(TemperatureSensor_Type, 2) + ">I2C BME280 (0x77)</option>\n";
    body += "<option value='3'" + returnStrSelected(TemperatureSensor_Type, 3) + ">I2C SHT31 (0x44)</option>\n";
    body += "<option value='4'" + returnStrSelected(TemperatureSensor_Type, 4) + ">I2C SHT31 (0x45)</option>\n";
    body += "<option value='5'" + returnStrSelected(TemperatureSensor_Type, 5) + ">I2C Chirp (0x20)</option>\n";
    body += "</select><br>\n";
    
    // HumiditySensor_Type byte
    body += "Humidity sensor: <select id='HumiditySensor_Type' name='HumiditySensor_Type' required>\n";
    if(configured == false) {
      body += "<option disabled value='' selected hidden>---</option>\n";
      }
    body += "<option value='1'" + returnStrSelected(HumiditySensor_Type, 1) + ">I2C BME280 (0x76)</option>\n";
    body += "<option value='2'" + returnStrSelected(HumiditySensor_Type, 2) + ">I2C BME280 (0x77)</option>\n";
    body += "<option value='3'" + returnStrSelected(HumiditySensor_Type, 3) + ">I2C SHT31 (0x44)</option>\n";
    body += "<option value='4'" + returnStrSelected(HumiditySensor_Type, 4) + ">I2C SHT31 (0x45)</option>\n";
    body += "</select><br><br>\n";
    


    body += "<b>General configuration</b><br>";
    
    // NtpOffset int
    body += "NTP offset/UTC timezone: <input class='inputShort' type='number' name='NtpOffset' min='-12' max='14' value='";
    body += NtpOffset;
    body+= "' required> Hours<br>\n";
    
    body += "Maintenance Duration: <input class='inputShort' type='number' name='MaintenanceDuration' min='0' max='900' value='";
    body += MaintenanceDuration;
    body += "' required> Seconds<br>\n";
    
    // PWMFrequency short
    body += "PWM Frequency: <input type='number' name='PWMFrequency' min='0' max='20000' value='";
    body += PWMFrequency;
    body += "' required> Hz<br>\n";
    
    // DisplayScreenDuration byte
    body += "Display rotation interval: <input class='inputShort' type='number' name='DisplayScreenDuration' min='0' max='255' value='";
    body += DisplayScreenDuration;
    body += "' required> Seconds<br>\n";
    body += "<p class='helpbox'><b>0</b> will always show sensor value screen</p>";
    
    body += "ESP32-Cam IP (optional): <input type='text' name='Esp32CamIP' maxlength='16' value='";
    body += Esp32CamIP;
    body += "' ><br><br>\n";
    
    
    body += "<input type='submit' value='&#x1F4BE; Save settings'>\n";
    body += "</form>\n";  
    
    
    body += FPSTR(HTMLfooter);
    
    webserver.send(200, "text/html", body);
  }
}  

void WEBwifiSettings() {
  byte ssidsAvail = WiFi.scanNetworks();
  String body = returnHTMLheader("wifiSettings");
  if(FirstRun == true) {
    body += "<h1>Welcome!</h1>";
    body += "<p>CanGrow is actually unconfigured. You need to Setup your WiFi first down below.<br>";
    body += "<br>After you entered your WiFi connection details, you need to restart and are step closer to your grow &#129382;";
    body += "<br>";
    body += "</p>";
  }
  body += "<h2>&#128225; WiFi settings</h2>\n";

  if(webserver.hasArg("success")) {
    body += FPSTR(HTMLsuccess);
  }
  
  if(FirstRun == false)  {
    body += "<u>Current Settings:</u><br>";
    body += "WiFi SSID: <b>";
    body += WIFIssid;
    body += "</b><br>\n";
    body += "Use DHCP: <b>";
    body += WIFIuseDHCP;
    body += "</b><br>\n";
    body += "IP address: <b>";
    body += WiFi.localIP().toString();
    body += "</b><br>\n";
    body += "Subnet mask: <b>";
    body += WiFi.subnetMask().toString();
    body += "</b><br>\n";
    body += "Gateway: <b>";
    body += WiFi.gatewayIP().toString();
    body += "</b><br>\n";
    body += "DNS: <b>";
    body += WiFi.dnsIP().toString();
    body += "</b><br><br>\n";
  }
  
  body += "<p>Select your wifi network from the SSID list.<br>To use DHCP leave IP, Subnet, Gateway and DNS fields blank!</p>";
  body += "<form method='post' action='/wifiSettings/save'>\n";
  body += "SSID: <select id='WIFIssid' name='WIFIssid' required>\n";
  body += "<option disabled value='' selected hidden>-Select your network-</option>";
  
  // build option list for selecting wifi
  Serial.println("Available Wifis: ");
  for(int i = 0 ; i < ssidsAvail; i++) {
    String wifiName = WiFi.SSID(i);
    Serial.println(wifiName);
    body += "<option value='" + wifiName + "'>";
    body += wifiName + "</option>\n";
  }
  body += "</select><br>\n";
  body += "Password: <input type='password' name='WIFIpassword'><br>\n";
  body += "IP: <input type='text' name='WIFIip'><br>\n";
  body += "Subnet mask: <input type='text' name='WIFInetmask'><br>\n";
  body += "Gateway: <input type='text' name='WIFIgateway'><br>\n";
  body += "DNS: <input type='text' name='WIFIdns'><br><br>\n";
  body += "<input type='submit' value='&#x1F4BE; Save settings'>\n";
  body += "</form>\n";
  body += FPSTR(HTMLfooter);
  
  webserver.send(200, "text/html", body);
} 

void WEBhelp() {
  String body = returnHTMLheader("help");
  body += FPSTR(HTMLhelp);
  body += FPSTR(HTMLfooter);
  webserver.send(200, "text/html", body);
}

  
/*
 * 
 * POSTs
 * 
 */  

void POSTgrowSettings() {
  
  PinLEDPWM = webserver.arg("PinLEDPWM").toInt();
  PinFANPWM = webserver.arg("PinFANPWM").toInt();
  PinFAN2PWM = webserver.arg("PinFAN2PWM").toInt();
  String GrowName_tmp = webserver.arg("GrowName");
  GrowName_tmp.toCharArray(GrowName, 32);
  
  
  GrowStart = webserver.arg("GrowStart").toInt();
  DaysVeg = webserver.arg("DaysVeg").toInt();
  DaysBloom = webserver.arg("DaysBloom").toInt();
  LighthoursVeg = webserver.arg("LighthoursVeg").toInt();
  LighthoursBloom = webserver.arg("LighthoursBloom").toInt();
  SunriseHour = webserver.arg("SunriseHour").toInt();
  SunriseMinute = webserver.arg("SunriseMinute").toInt();
  SunFade = webserver.arg("SunFade").toInt();
  SunFadeDuration = webserver.arg("SunFadeDuration").toInt();
  
  UsePump = webserver.arg("UsePump").toInt();
  PumpOnTime = webserver.arg("PumpOnTime").toInt();
  SoilmoistureLow = webserver.arg("SoilmoistureLow").toInt();
  
  PumpIntervalVeg = webserver.arg("PumpIntervalVeg").toInt();
  PumpIntervalBloom = webserver.arg("PumpIntervalBloom").toInt();
  
  // size is 32 byte
  EEPROM.put(170, GrowName);
  // size is 4 byte
  EEPROM.put(202, GrowStart);
  // size is 1 byte
  EEPROM.put(206, DaysVeg);
  // size is 1 byte
  EEPROM.put(207, DaysBloom);
  // size is 1 byte
  EEPROM.put(208, LighthoursVeg);
  // size is 1 byte
  EEPROM.put(209, LighthoursBloom);
  // size is 1 byte
  EEPROM.put(210, SunriseHour);
  // size is 1 byte
  EEPROM.put(211, SunriseMinute);
  // size is 1 byte
  EEPROM.put(213, PinLEDPWM);
  // size is 1 byte
  EEPROM.put(216, PinFANPWM);
  // size is 1 byte
  EEPROM.put(248, PinFAN2PWM);
  EEPROM.put(217, SunFade);
  EEPROM.put(218, SunFadeDuration);
  
  // size is 1 byte
  EEPROM.put(163, UsePump);
  // size is 1 byte
  EEPROM.put(164, PumpOnTime);
  // size is 1 byte
  EEPROM.put(166, SoilmoistureLow);
  
  
  // size is 1 byte
  EEPROM.put(241, PumpIntervalVeg);
  // size is 1 byte
  EEPROM.put(242, PumpIntervalBloom);
  
  EEPROM.commit();
  
  
  
  
  //analogWrite(PinLED, PinLEDPWM);
  
  Serial.println(":: POSTgrowSettings ::");
  
  Serial.print("GrowName: ");
  Serial.println(GrowName);
  Serial.print("GrowStart: ");
  Serial.println(GrowStart);
  Serial.print("DaysVeg: ");
  Serial.println(DaysVeg);
  Serial.print("DaysBloom: ");
  Serial.println(DaysBloom);
  Serial.print("LighthoursVeg: ");
  Serial.println(LighthoursVeg);
  Serial.print("LighthoursBloom: ");
  Serial.println(LighthoursBloom);
  Serial.print("SunriseHour: ");
  Serial.println(SunriseHour);
  Serial.print("SunriseMinute: ");
  Serial.println(SunriseMinute);
  Serial.print("PinLEDPWM: ");
  Serial.println(PinLEDPWM);
  Serial.print("PinFANPWM: ");
  Serial.println(PinFANPWM);
  Serial.print("PinFAN2PWM: ");
  Serial.println(PinFAN2PWM);

  Serial.print("UsePump: ");
  Serial.println(UsePump);
  Serial.print("PumpOnTime: ");
  Serial.println(PumpOnTime);
  Serial.print("SoilmoistureLow: ");
  Serial.println(SoilmoistureLow);

  Serial.print("PumpIntervalVeg: ");
  Serial.println(PumpIntervalVeg);
  Serial.print("PumpIntervalBloom: ");
  Serial.println(PumpIntervalBloom);
    

  
  webserver.sendHeader("Location", String("/growSettings?success"), true);
  webserver.send(302, "text/plain", "growSettings/save: success!\n");  
}


void POSTsystemSettings() {
  
  unsigned short UseLEDrelais_old = UseLEDrelais;
  unsigned short UseFANrelais_old = UseFANrelais;
  unsigned short PWMFrequency_old = PWMFrequency;
  
  NtpOffset = webserver.arg("NtpOffset").toInt();
  MoistureSensor_Type = webserver.arg("MoistureSensor_Type").toInt();


  UseFan = webserver.arg("UseFan").toInt();
  UseLEDrelais = webserver.arg("UseLEDrelais").toInt();
  UseFANrelais = webserver.arg("UseFANrelais").toInt();
  TemperatureSensor_Type = webserver.arg("TemperatureSensor_Type").toInt();
  MaintenanceDuration = webserver.arg("MaintenanceDuration").toInt();
  String Esp32CamIP_tmp = webserver.arg("Esp32CamIP");
  Esp32CamIP_tmp.toCharArray(Esp32CamIP, 221);  
  OutputInvert = webserver.arg("OutputInvert").toInt();
  SoilmoistureWet = webserver.arg("SoilmoistureWet").toInt();
  SoilmoistureDry = webserver.arg("SoilmoistureDry").toInt();
  HumiditySensor_Type = webserver.arg("HumiditySensor_Type").toInt();
  PWMFrequency = webserver.arg("PWMFrequency").toInt();
  DisplayScreenDuration = webserver.arg("DisplayScreenDuration").toInt();
  
  // when configured is false, set it to true and ensure outputs are set
  if(configured == false) {
    configured = true;
    pinMode(PinLED, OUTPUT);
    pinMode(PinPUMP, OUTPUT);
    pinMode(PinFAN, OUTPUT);
  }
  
  // size is 1 byte
  EEPROM.put(161, configured);
  // size is 1 byte
  EEPROM.put(162, UseFan);

  // size is 1 byte
  EEPROM.put(165, MoistureSensor_Type);

  // size is 2 byte
  EEPROM.put(167, NtpOffset);
  // size is 1 byte
  EEPROM.put(169, UseLEDrelais);
  // size is 1 byte
  EEPROM.put(214, TemperatureSensor_Type);
  // size is 1 byte
  EEPROM.put(215, UseFANrelais);
  EEPROM.put(219, MaintenanceDuration);
  EEPROM.put(221, Esp32CamIP);
  EEPROM.put(243, OutputInvert);
  EEPROM.put(244, SoilmoistureWet);
  EEPROM.put(246, SoilmoistureDry);
  EEPROM.put(249, HumiditySensor_Type);
  EEPROM.put(250, PWMFrequency);
  EEPROM.put(252, DisplayScreenDuration);
  
  // write data to EEPROM
  EEPROM.commit();
  

  
  // update time with new offset
  timeClient.setTimeOffset(NtpOffset * 60 * 60);
  timeClient.update();
  
  Serial.println(":: POSTsystemSettings ::");
  
  // when user uses an relais for LED control, we force here PinLEDPWM to 255
  // to ensure nothing bad happens and its turned on
  if( (UseLEDrelais == false) && (UseLEDrelais != UseLEDrelais_old) ) {
    PinLEDPWM = 255;
    EEPROM.put(213, PinLEDPWM);
    EEPROM.commit();
    Serial.println("UseLEDrelais is 0, forcing PinLEDPWM to max to prevent relais damage and ensure its turned on");
  }
  
  if( (UseFANrelais == false) && (UseFANrelais != UseFANrelais_old) ) {
    PinFANPWM = 255;
    EEPROM.put(215, PinFANPWM);
    EEPROM.commit();
    Serial.println("UseFANrelais is 0, forcing PinFANPWM to max to prevent relais damage and ensure its turned on");
  }
    
  if(PWMFrequency != PWMFrequency_old) {
    // if PWM freq changed, apply new settings
    analogWriteFreq(PWMFrequency);
  }
  
  Serial.print("configured: ");
  Serial.println(configured);
  Serial.print("UseFan: ");
  Serial.println(UseFan);

  Serial.print("MoistureSensor_Type: ");
  Serial.println(MoistureSensor_Type);

  Serial.print("NtpOffset: ");
  Serial.println(NtpOffset);
  Serial.print("UseLEDrelais: ");
  Serial.println(UseLEDrelais);
  Serial.print("UseFANrelais: ");
  Serial.println(UseFANrelais);
  Serial.print("TemperatureSensor_Type: ");
  Serial.println(TemperatureSensor_Type);
  Serial.print("MaintenanceDuration: ");
  Serial.println(MaintenanceDuration);
  
  if(strlen(GrowName)  < 1) {
    webserver.sendHeader("Location", String("/growSettings?success"), true);
  } else {
    webserver.sendHeader("Location", String("/systemSettings?success"), true);
  }
  
  webserver.send(302, "text/plain", "systemSettings/save: success!\n");
}


void POSTwifiSettings() {
  String WIFIssid_new = webserver.arg("WIFIssid");
  String WIFIpassword_new = webserver.arg("WIFIpassword");
  String WIFIip_new = webserver.arg("WIFIip");
  String WIFInetmask_new = webserver.arg("WIFInetmask");
  String WIFIgateway_new = webserver.arg("WIFIgateway");
  String WIFIdns_new = webserver.arg("WIFIdns");
  
  // convert String we got from webserver.arg to EEPROM friendly char[]
  WIFIssid_new.toCharArray(WIFIssid, 32);
  WIFIpassword_new.toCharArray(WIFIpassword, 64);
  
  // if WIFIip_new was not set, we assume DHCP should be used
  if(WIFIip_new.length() > 0) {
    WIFIip.fromString(WIFIip_new);
    WIFInetmask.fromString(WIFInetmask_new);
    WIFIgateway.fromString(WIFIgateway_new);
    WIFIdns.fromString(WIFIdns_new);
    // 
    WIFIuseDHCP = false;
  } else {
    WIFIuseDHCP = true;
  }
  
  // restart is needed to load the new settings
  NeedRestart = true;
    
  EEPROM.put(0, WIFIssid);
  EEPROM.put(32, WIFIpassword);
  EEPROM.put(96, WIFIip);
  EEPROM.put(112, WIFInetmask);
  EEPROM.put(128, WIFIgateway);
  EEPROM.put(144, WIFIdns);
  EEPROM.put(160, WIFIuseDHCP);
  EEPROM.commit();
  
  
  Serial.println(":: POSTwifiSettings ::");
  
  Serial.print("WIFIssid: ");
  Serial.println(WIFIssid_new);
  Serial.println(WIFIssid);
  Serial.print("WIFIpassword: ");
  Serial.println(WIFIpassword_new);
  Serial.println(WIFIpassword);
  Serial.print("WIFIip: ");
  Serial.println(WIFIip_new);
  Serial.print("WIFInetmask: ");
  Serial.println(WIFInetmask_new);
  Serial.print("WIFIgateway: ");
  Serial.println(WIFIgateway_new);
  Serial.print("WIFIdns: ");
  Serial.println(WIFIdns_new);
  Serial.print("WIFIuseDHCP: ");
  Serial.println(WIFIuseDHCP);


  webserver.sendHeader("Location", String("/wifiSettings?success"), true);
  webserver.send(302, "text/plain", "wifiSettings/save: success!\n");
  
}

void POSTsetOutput() {
  byte OutputState = webserver.arg("state").toInt();
  byte OutputNr = webserver.arg("output").toInt();
  //PinLEDPWM = webserver.arg("PinLEDPWM").toInt();
  byte OutputPWM = webserver.arg("OutputPWM").toInt();

  Serial.println(":: POSTsetOutput ::");
  Serial.print("OutputState: ");
  Serial.println(OutputState);
  Serial.print("OutputNr: ");
  Serial.println(OutputNr);
  
  if((OutputNr > 3) || (OutputNr < 1) || (OutputState > 255) || (OutputState < 0)) {
    webserver.send(400, "text/plain", "not valid\n");
  } else {
    
    if(OutputState > 0){
      setOutput(OutputNr, OutputPWM);
    } else {
      setOutput(OutputNr, 0);
    }
    
    
    webserver.sendHeader("Location", String("/?success"), true);
    webserver.send(302, "text/plain", "switch: success!\n");
    }
       
}
  

void POSTsetPumpManual() {
  PumpOnManual = webserver.arg("PumpOnManual").toInt();
  webserver.sendHeader("Location", String("/?success"), true);
  webserver.send(302, "text/plain", "switch: success!\n");
}

void POSTwipeConfirm() {
  String body = returnHTMLheader();
  // TODO only debug and development solution, remove this later
  String confirm = webserver.arg("confirm");
  if(confirm == "on") {
    body += "<div class='warnmsg'><h2>!! Wiping CanGrow's EEPROM !!</h2><br>Device will restart in a few seconds.<br>After restart a new WiFi 'CanGrow-unconfigured' will be created. To access the WebUI visit <a href='http://192.168.4.20'>http://192.168.4.20</a></div>";
    body += FPSTR(HTMLfooter);
    webserver.send(200, "text/html", body);
    wipeEEPROM();
  } else {
    webserver.send(400, "text/html", String("Error, 'confirm' missing nor wrong"));
  }

}


/* 
 * API section
 * 
 */
 
// return as json all sensor readings
void APIgetSensors() {
  
  JsonDocument jsonSensors;
    
  jsonSensors["soilmoisture"] = valSoilmoisture;
  jsonSensors["soilmoistureAvg"] = valSoilmoistureAvg;
  jsonSensors["soilmoistureRaw"] = valSoilmoistureRaw;
  jsonSensors["temperature"] = valTemperature;
  jsonSensors["humidity"] = valHumidity;
  jsonSensors["waterlevel"] = valWaterlevel;
  jsonSensors["vpd"] = valVPD;
  
  String body;
  serializeJsonPretty(jsonSensors, body);
  webserver.send(200, "text/json", body);
  
}  
  
void APIgetDebug() {
  
  JsonDocument jsonDebug;
  
  // Runtime vars
  JsonObject objRuntime = jsonDebug["runtime"].add<JsonObject>();
  objRuntime["PumpOnTimePassed"] = PumpOnTimePassed;
  objRuntime["PumpOnManual"] = PumpOnManual;
  objRuntime["valTemperature"] = valTemperature;
  objRuntime["valHumidity"] = valHumidity;
  objRuntime["valSoilmoisture"] = valSoilmoisture;
  objRuntime["valSoilmoistureRaw"] = valSoilmoistureRaw;
  objRuntime["valSoilmoistureAvg"] = valSoilmoistureAvg;
  objRuntime["valSoilmoistureAvg_tmp"] = valSoilmoistureAvg_tmp;
  objRuntime["valSoilmoistureAvg_count"] = valSoilmoistureAvg_count;
  objRuntime["NeedRestart"] = NeedRestart;
  objRuntime["FirstRun"] = FirstRun;
  objRuntime["ScreenToDisplay"] = ScreenToDisplay;
  objRuntime["ScreenIterationPassed"] = ScreenIterationPassed;
  objRuntime["DayNight"] = DayNight;
  objRuntime["MaintenanceMode"] = MaintenanceMode;
  objRuntime["MaintenanceStarted"] = MaintenanceStarted;
  
  
  // WiFi
  JsonObject objWiFi = jsonDebug["wifi"].add<JsonObject>();
  objWiFi["ssid"] = WIFIssid;
  objWiFi["dhcp"] = WIFIuseDHCP;
  objWiFi["ip"] = WiFi.localIP().toString();
  objWiFi["netmask"] = WiFi.subnetMask().toString();
  objWiFi["gateway"] = WiFi.gatewayIP().toString();
  objWiFi["dns"] = WiFi.dnsIP().toString();
  
  // System
  JsonObject objSystem = jsonDebug["system"].add<JsonObject>();
  objSystem["UseFan"] = UseFan;
  objSystem["UsePump"] = UsePump;
  objSystem["UseLEDrelais"] = UseLEDrelais;
  objSystem["UseFANrelais"] = UseFANrelais;
  objSystem["PumpOnTime"] = PumpOnTime;
  objSystem["MoistureSensor_Type"] = MoistureSensor_Type;
  objSystem["SoilmoistureLow"] = SoilmoistureLow;
  objSystem["TemperatureSensor_Type"] = TemperatureSensor_Type;
  objSystem["NtpOffset"] = NtpOffset;
  objSystem["MaintenanceDuration"] = MaintenanceDuration;
  objSystem["PumpOnTime"] = PumpOnTime;
  objSystem["PumpLastOn"] = PumpLastOn;
  objSystem["OutputInvert"] = OutputInvert;
  objSystem["SoilmoistureWet"] = SoilmoistureWet;
  objSystem["SoilmoistureDry"] = SoilmoistureDry;
  objSystem["HumiditySensor_Type"] = HumiditySensor_Type;
  objSystem["PWMFrequency"] = PWMFrequency;
  objSystem["DisplayScreenDuration"] = DisplayScreenDuration;
  objSystem["Esp32CamIP"] = Esp32CamIP;
   
  // Grow
  JsonObject objGrow = jsonDebug["grow"].add<JsonObject>();
  objGrow["GrowName"] = GrowName;
  objGrow["GrowStart"] = GrowStart;
  objGrow["GrowStartDate"] = returnStrDateFromEpoch(GrowStart);
  objGrow["DaysVeg"] = DaysVeg;
  objGrow["DaysBloom"] = DaysBloom;
  objGrow["LighthoursVeg"] = LighthoursVeg;
  objGrow["LighthoursBloom"] = LighthoursBloom;
  objGrow["SunriseHour"] = SunriseHour;
  objGrow["SunriseMinute"] = SunriseMinute;
  objGrow["SunFade"] = SunFade;
  objGrow["SunFadeDuration"] = SunFadeDuration;
  objGrow["PinLEDPWM"] = PinLEDPWM;
  objGrow["PinFANPWM"] = PinFANPWM;
  objGrow["PinFAN2PWM"] = PinFAN2PWM;
  objGrow["DayOfGrow"] = DayOfGrow;
  objGrow["PumpIntervalVeg"] = PumpIntervalVeg;
  objGrow["PumpIntervalBloom"] = PumpIntervalBloom;
  
  
  
  
  // Sensors
  JsonObject objSensors = jsonDebug["sensors"].add<JsonObject>();
  
  // Chirp
  objSensors["chirp"]["temperature"] = getTemperature(5);
  objSensors["chirp"]["soilmoisture"] = getSoilmoisture(2);
  objSensors["chirp"]["soilmoistureRAW"] = getSoilmoisture(2, true);
  objSensors["chirp"]["light"] = getLightchirp();
  
  // BME280 0x76
  objSensors["bme280_0x76"]["temperature"] = getTemperature(1);
  objSensors["bme280_0x76"]["humidity"] = getHumidity(1);
  //objSensors["bme280_0x76"]["preassure"] = bme.readPressure() / 100.0F;
  //objSensors["bme280_0x76"]["appAltitude"] = bme.readAltitude(SEALEVELPRESSURE_HPA);
  
  // BME280 0x77
  objSensors["bme280_0x77"]["temperature"] = getTemperature(2);
  objSensors["bme280_0x77"]["humidity"] = getHumidity(2);
  //objSensors["bme280_0x77"]["preassure"] = bme.readPressure() / 100.0F;
  //objSensors["bme280_0x77"]["appAltitude"] = bme.readAltitude(SEALEVELPRESSURE_HPA);
  
  // SHT31 0x44
  objSensors["sht31_0x44"]["temperature"] = getTemperature(3);
  objSensors["sht31_0x44"]["humidity"] = getHumidity(3);
  
  // SHT31 0x45
  objSensors["sht31_0x45"]["temperature"] = getTemperature(4);
  objSensors["sht31_0x45"]["humidity"] = getHumidity(4);
  
  // Analog
  objSensors["analog"]["soilmoisture"] = getSoilmoisture(1);
  objSensors["analog"]["soilmoistureRAW"] = getSoilmoisture(1, true);
  objSensors["analog"]["waterlevel"] = getWaterlevel();
  
  String body;
  
  serializeJsonPretty(jsonDebug, body);
  webserver.send(200, "text/json", body);
  
}  


/*
 * Web Handler 
 */

void WebHandler() {
    /* 
   * Webserver handlers
   * here are the generic webserver handlers like 404 not found
   * wifiSettings, ...
   * 
   * if you are looking for the single webpages handler, have a look to
   * 
   * WebHandler_unconfigured() and WebHandler_configured()
   */
  // style.css
  //webserver.on("/style.css", HTTP_GET, WEBstyleCSS);
  
  // Web root
  webserver.on("/", HTTP_GET, WEBroot);
  
  // WiFi Stuff
  webserver.on("/wifiSettings", HTTP_GET, WEBwifiSettings);
  webserver.on("/wifiSettings/save", HTTP_POST, POSTwifiSettings);
  
  // System stuff
  webserver.on("/systemSettings", HTTP_GET, WEBsystemSettings);
  webserver.on("/systemSettings/save", HTTP_POST, POSTsystemSettings);
  
  // Grow stuff
  webserver.on("/growSettings", HTTP_GET, WEBgrowSettings);
  webserver.on("/growSettings/save", HTTP_POST, POSTgrowSettings);
  // help
  webserver.on("/help", HTTP_GET, WEBhelp);
  
  // restart when NeedRestart is true
  webserver.on("/system/restart", HTTP_GET, SysRestart);
  // wipe eeprom triggered from WebGui
  webserver.on("/system/wipe", HTTP_GET, SysWipe); 
  // confirm wiping the device
  webserver.on("/system/wipeConfirm", HTTP_POST, POSTwipeConfirm); 
  // Maintenance mode
  webserver.on("/system/maintenance", HTTP_GET, SysMaintenance); 
  // system update with binary
  // update form
  webserver.on("/system/update", HTTP_GET, SysUpdate); 
  // update itself
  webUpdater.setup(&webserver, "/system/applyUpdate");
  // does not work atm TODO
  //webserver.on("/logout", [](){ webserver.send(401, "text/html", "logged out!"); });
  
  // 404 handling
  // favicon.ico is a special one, because its requested everytime and i dont wont to deliver the
  // failed whole page every call. we can save up this 0,5kb traffic :o) 
  webserver.on("/favicon.ico", [](){ webserver.send(404, "text/html", "404 - not found"); });
  webserver.onNotFound(Sys404);
  
  // switching MOSFETs
  webserver.on("/switch", HTTP_POST, POSTsetOutput); 
  webserver.on("/pumpManual", HTTP_POST, POSTsetPumpManual);
  
  // api stuff
  webserver.on("/api/sensors", HTTP_GET, APIgetSensors);
  webserver.on("/api/debug", HTTP_GET, APIgetDebug);
  
  // gauge meter stuff
  webserver.on("/gauge.css", HTTP_GET, WEBgaugeCss);
  webserver.on("/gauge.js", HTTP_GET, WEBgaugeJs);
}