#ifdef LANG_DE
  #include "html_DE.h"
  #include "html_main_DE.h"
#else
  #include "html.h"
  #include "html_main.h"
#endif

#ifdef FIRMWARE_VARIANT_THERMOSTAT
  //#ifdef LANG_DE
  //  #include "html_main_thermostat_DE.h"
  //  #include "html_thermostat_redTemps_DE.h"
  //  #include "html_confTherm_DE.h"
  //#else
    #include "html_main_thermostat.h"
    #include "html_thermostat_redTemps.h"
    #include "html_confTherm.h"
  //#endif
#elif FIRMWARE_VARIANT_HEATCONTROL
  #ifdef LANG_DE
    #include "html_main_heatcontrol_DE.h"
    #include "html_confHeatcontrol_DE.h"
  #else
    #include "html_main_heatcontrol.h"
    #include "html_confHeatcontrol.h"
  #endif
#else
  //#ifdef LANG_DE
  //  #include "html_main_minimal_DE.h"
  //#else
    #include "html_main_minimal.h"
  //#endif
#endif



#include "html_js_confpages.h"

#ifdef LANG_DE
  #include "html_conf_DE.h"
  #include "html_confAdd_DE.h"

  #include "html_confDevWiFi_DE.h"
  #include "html_confMqtt.h"
  #include "html_confWeb.h"
  #include "html_confTime.h"
  #include "html_confLog.h"

  #include "html_sysinfo_DE.h"
#else
  #include "html_conf.h"
  #include "html_confAdd.h"

  #include "html_confDevWiFi.h"
  #include "html_confMqtt.h"
  #include "html_confWeb.h"
  #include "html_confTime.h"
  #include "html_confLog.h"

  #include "html_sysinfo.h"
#endif


#ifdef ENABLE_FEATURE_FILESYSTEM_BROWSER
  //#ifdef LANG_DE
  //  #include "html_fsbrowser_DE.h"
  //#else
    #include "html_fsbrowser.h"
  //#endif
#endif

#ifdef ENABLE_FEATURE_WEB_CONSOLE
  //#ifdef LANG_DE
  //  #include "html_console_DE.h"
  //#else
    #include "html_console.h"
  //#endif
#endif

#if defined(ENABLE_FEATURE_WSCONSOLE) || defined(ENABLE_FEATURE_WSCONSOLE_UART)
#include "html_console_wsapp.js.h"
#endif

#ifdef ENABLE_FEATURE_WSCONSOLE
#include "html_console_ws.h"
#endif


void httpServerSendHtmlHeadChunked()
{
  httpServer.setContentLength(CONTENT_LENGTH_UNKNOWN); //Enable Chunked Transfer
  httpServer.send(200, "text/html", html_head_part1);
  httpServer.sendContent_P(PGMStr_FIRMWARE_NAME);
  httpServer.sendContent(" - ");
  httpServer.sendContent(confDevWiFi.deviceName);
  httpServer.sendContent_P(html_head_part2);
}

void httpServerSendHtmlBodyPageheadChunked()
{
  httpServer.sendContent_P(html_body_pagehead_part1);
  httpServer.sendContent_P(PGMStr_FIRMWARE_NAME);
  httpServer.sendContent(" - ");
  httpServer.sendContent(confDevWiFi.deviceName);
  httpServer.sendContent_P(html_body_pagehead_part2);
  if (configChangedRestartRequired)
    httpServer.sendContent_P(html_body_pagehead_confchangednote);
}

void httpServerSendHtmlFooterChunked()
{
  httpServer.sendContent_P(html_footer1);
  httpServer.sendContent_P(html_footer_a1);
  httpServer.sendContent_P(PGMStr_FIRMWARE_URL);
  httpServer.sendContent_P(html_footer_a2);
  httpServer.sendContent_P(PGMStr_FIRMWARE_NAME);
  httpServer.sendContent_P(html_footer_ae);
  httpServer.sendContent(" ");
  httpServer.sendContent_P(PGMStr_FIRMWARE_VERSION);
#ifdef DEBUGMODE
  httpServer.sendContent_P(PGMStr_WEB_DEBUGBUILD);
#endif
  httpServer.sendContent(" by ");
  httpServer.sendContent_P(html_footer_a1);
  httpServer.sendContent_P(PGMStr_FIRMWARE_COPYRIGHT_URL);
  httpServer.sendContent_P(html_footer_a2);
  httpServer.sendContent_P(PGMStr_FIRMWARE_COPYRIGHT);
  httpServer.sendContent_P(html_footer_ae);
  httpServer.sendContent_P(html_footer2);
  httpServer.sendContent("");
  httpServer.client().stop();
}


void httpServer_logWebRequest() {
    String _addr = httpServer.client().remoteIP().toString();
    String _method = (httpServer.method() == HTTP_GET) ? "GET" : "POST";

    if(httpServer.args() > 0) {
      String _args = "";
      for (uint8_t _i = 0; _i < httpServer.args(); _i++) {
        if(_i > 0) _args += ", ";
        _args += httpServer.argName(_i) + "=" + httpServer.arg(_i);
      }
      snprintf(logBuf, LOG_BUFFER_SIZE, "WEB: %s %s - %s (from %s)", _method.c_str(), httpServer.uri().c_str(), _args.c_str(), _addr.c_str());
    }
    else {
      snprintf(logBuf, LOG_BUFFER_SIZE, "WEB: %s %s (from %s)", _method.c_str(), httpServer.uri().c_str(), _addr.c_str());
    }
    
    sendLog(logBuf, LOGLEVEL_INFO);
}

bool httpIsAuthenticated()
{
  if (WifiInApMode && strlen(confSecrets.WiFiAPModePassword) >= 8)
    return true;
  if (confWeb.http_user_auth)
  {
    boolean useAuth = false;
    boolean isAuthenticated = false;
    // user authentication enabled - only allow access without authentication if no admin password is set
    // or if user1 credentials are empty (access in "user mode")
    if (strlen(confSecrets.http_pass) > 0 || strlen(confSecrets.http_pass1) > 0 || strlen(confSecrets.http_pass2) > 0)
      useAuth = true;
    if (strlen(confSecrets.http_pass) == 0)
    {
      return true; // no admin password set - in this case authentication is off
    }
    if (useAuth)
    {
      // allow access if one set of valid credentials are given
      if ((strlen(confSecrets.http_user) > 0 && strlen(confSecrets.http_pass) > 0))
      {
        if (httpServer.authenticate(confSecrets.http_user, confSecrets.http_pass))
          isAuthenticated = true;
      }
      if ((strlen(confSecrets.http_user1) > 0 && strlen(confSecrets.http_pass1) > 0))
      {
        if (httpServer.authenticate(confSecrets.http_user1, confSecrets.http_pass1))
          isAuthenticated = true;
      }
      if ((strlen(confSecrets.http_user2) > 0 && strlen(confSecrets.http_pass2) > 0))
      {
        if (httpServer.authenticate(confSecrets.http_user2, confSecrets.http_pass2))
          isAuthenticated = true;
      }
      // also allow access if admin credentials are set but user1 password is empty and user-authentication is enabled
      if (strlen(confSecrets.http_pass1) == 0)
      {
        isAuthenticated = true;
      }
      return isAuthenticated;
    }
    // allow access if all credentials are empty
    else
      return true;
  }
  // user authentication disabled - only allow access without password if no admin password is set
  else
  {
    if (strlen(confSecrets.http_pass) > 0)
    {
      if (httpServer.authenticate(confSecrets.http_user, confSecrets.http_pass))
        return true;
      else
        return false;
    }
    else
      return true;
  }
}



bool httpIsAuthenticatedAdmin()
{
  if (WifiInApMode && strlen(confSecrets.WiFiAPModePassword) >= 8)
    return true;
  boolean auth = false;
  if ((strlen(confSecrets.http_user) > 0 && strlen(confSecrets.http_pass) > 0))
    auth = true;
  if (auth)
  {
    if (!httpServer.authenticate(confSecrets.http_user, confSecrets.http_pass))
      return false;
    else
      return true;
  }
  else
    return true;
}



void httpServerHandleNotFound()
{
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += httpServer.uri();
  message += "\nMethod: ";
  message += (httpServer.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += httpServer.args();
  message += "\n";
  for (uint8_t i = 0; i < httpServer.args(); i++) {
    message += " " + httpServer.argName(i) + ": " + httpServer.arg(i) + "\n";
  }

  if (confLog.logWebRequests) {
    snprintf(logBuf, LOG_BUFFER_SIZE, "WEB: 404 - %s %s (from %s)", (httpServer.method() == HTTP_GET) ? "GET" : "POST", httpServer.uri().c_str(), httpServer.client().remoteIP().toString().c_str());
    sendLog(logBuf, LOGLEVEL_INFO);
  }

  httpServer.send(404, "text/plain", message);
  //httpServer.send(404, "text/plain", "404 NOT FOUND");
}



void httpSendUnauthorized()
{
  httpServer.send(401, "text/plain", "UNAUTHORIZED");
}



void httpSend200OK()
{
  httpServer.send(200, "text/plain", "OK");
}



bool httpCheckToken()
{
  if (confSecrets.http_token[0] != '\0')
  { // dont accept empty token
    if (httpServer.hasArg("token"))
    {
      char buf[20];
      httpServer.arg("token").toCharArray(buf, 20);
      if (strcmp(buf, confSecrets.http_token) == 0)
        return true;
      else
        return false;
    }
    else
      return false;
  }
  else
    return false;
}



void httpServerInit()
{
  httpServer.on("/style.css", []() {
    httpServer.sendHeader("cache-control", "max-age=86400", false);
    httpServer.send_P(200, "text/css", html_stylesheet);
  });

  httpServer.on("/favicon.ico", []() {
      httpServer.send(404, "text/plain", "404 NOT FOUND"); // send 404 without logging it
  });

  httpServer.on("/fdl", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else {
      char _bufVal[31];
      char _buf[51];
      if (httpServer.hasArg("f")) {
        httpServer.arg("f").toCharArray(_bufVal, 30);
        if (!LittleFS.exists(_bufVal))
        {
          sprintf(_buf, "404 - file %s not found", _bufVal);
          httpServer.send(404, "text/plain", _buf);
        }
        else {
          FS_downloadFile(_bufVal, false);
        }
      }
      else {
        httpServer.send(404, "text/plain", "400: bad request");
      }
    }
  });

  //httpServer.on("/fs/del", []() {
  httpServer.on("/fdel", HTTP_POST, []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      char _returnPage[31];
      if (httpServer.hasArg("rt")) {
        httpServer.arg("rt").toCharArray(_returnPage, 30);
      }
      else {
        strcpy(_returnPage, "/avrflash");
      }

      char _bufVal[31];
      char _buf[51];
      if (httpServer.hasArg("f")) {
        httpServer.arg("f").toCharArray(_bufVal, 30);
        if (FS_deleteFile(_bufVal))
        {
          //sprintf(_buf, "file %s deleted successfully.", _bufVal);
          //httpServer.send(200, "text/plain", _buf);
          httpServer.sendHeader("Location", _returnPage);      // Redirect the client to the success page
          httpServer.send(303);
        }
        else {
          sprintf(_buf, "404 - file %s not found", _bufVal);
          httpServer.send(404, "text/plain", _buf);
        }
      }
      else {
        httpServer.send(400, "text/plain", "400: bad request");
      }
    }
  });

  httpServer.on("/fupl", HTTP_POST,                       // if the client posts to the upload page
    [](){ 
      if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else httpServer.send(200); },                          // Send status 200 (OK) to tell the client we are ready to receive
    FS_handleFileUpload                                    // Receive and save the file
  );

  httpServer.on("/api", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      //if (confLog.logWebRequests || httpServer.args() > 0) httpServer_logWebRequest();
      if (confLog.logWebRequests) httpServer_logWebRequest();
      
      #ifdef FIRMWARE_VARIANT_THERMOSTAT
        if (httpServer.hasArg("BtnPlus"))
        {
          thermostat_setTempStepUp();
          sendLog(F("WEB: BtnPlus"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnMinus"))
        {
          thermostat_setTempStepDown();
          sendLog(F("WEB: BtnMinus"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnPset0"))
        {
          thermostat_setPresetTo(0);
          sendLog(F("WEB: BtnPset0"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnPset1"))
        {
          thermostat_setPresetTo(1);
          sendLog(F("WEB: BtnPset1"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnPset2"))
        {
          thermostat_setPresetTo(2);
          sendLog(F("WEB: BtnPset2"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnOn"))
        {
          thermostat_setHeatingmodeTo(1);
          sendLog(F("WEB: BtnOn"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnOff"))
        {
          thermostat_setHeatingmodeTo(0);
          sendLog(F("WEB: BtnOff"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnL1Plus"))
        {
          thermostat_setTempLowStepUp();
          sendLog(F("WEB: BtnL1Plus"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnL1Minus"))
        {
          thermostat_setTempLowStepDown();
          sendLog(F("WEB: BtnL1Minus"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnL2Plus"))
        {
          thermostat_setTempLow2StepUp();
          sendLog(F("WEB: BtnL2Plus"), LOGLEVEL_INFO);
        }
        if (httpServer.hasArg("BtnL2Minus"))
        {
          thermostat_setTempLow2StepDown();
          sendLog(F("WEB: BtnL2Minus"), LOGLEVEL_INFO);
        }

        if (httpServer.hasArg("setTemp"))
        {
          sendLog(F("WEB: /api?setTemp"), LOGLEVEL_INFO);
          char _bufVal[20];
          httpServer.arg("setTemp").toCharArray(_bufVal, 20);
          float _valueFloat = round(atof(_bufVal) * 2.0) / 2.0;
          thermostat_setTempTo(_valueFloat);
        }

        if (httpServer.hasArg("setPause"))
        {
          sendLog(F("WEB: /api?setPause"), LOGLEVEL_INFO);
          char _bufVal[20];
          httpServer.arg("setPause").toCharArray(_bufVal, 20);
          int _valueInt = atoi(_bufVal);
          thermostat_setHeatingPause(_valueInt);
        }

        if (httpServer.hasArg("setMode"))
        {
          sendLog(F("WEB: /api?setMode"), LOGLEVEL_INFO);
          char _bufVal[20];
          httpServer.arg("setMode").toCharArray(_bufVal, 20);
          int _valueInt = atoi(_bufVal);
          if (_valueInt >= 0 && _valueInt <= 1)
            thermostat_setHeatingmodeTo(_valueInt);
        }

        if (httpServer.hasArg("setPreset"))
        {
          sendLog(F("WEB: /api?setPreset"), LOGLEVEL_INFO);
          char _bufVal[20];
          httpServer.arg("setPreset").toCharArray(_bufVal, 20);
          int _valueInt = atoi(_bufVal);
          if (_valueInt >= 0 && _valueInt <= 2)
            thermostat_setPresetTo(_valueInt);
        }
      #endif // FIRMWARE_VARIANT_THERMOSTAT

      //char ch_currTemp[6];
      //char ch_currSetTemp[6];
      //dtostrf(sensor_DHT_currTemp, 1, 1, ch_currTemp );
      //dtostrf(setTemp, 1, 1, ch_currSetTemp );

      //build json object of program data
      StaticJsonDocument<850> json;

      json["devname"] = confDevWiFi.deviceName;
      json["ssid"] = WiFi.SSID();
      json["WiFiNum"] = persWM.getActiveWiFiNum();
      //json["uptime"] = uptimeStr;
      json["uptime"] = getUptimeStr();

      #ifdef ENABLE_FEATURE_NTP_TIME
      if (confTime.ntpEnable)
      {
        char _buf[13];
        updateTime();
        if (lt.tm_year > 70) // check if time has been synced
        {
          strftime(_buf, sizeof(_buf), "%H:%M", &lt);
          json["time"] = _buf;
          strftime(_buf, sizeof(_buf), "%d.%m.%Y", &lt);
          json["date"] = _buf;
        }
      }
      #endif

      json["freeheap"] = ESP.getFreeHeap();

      mqtt_updateCurrentStateName();
      json["mqttstate"] = mqttCurrentStateName;
      json["mqtthost"] = confMqtt.mqtt_server;

      if (mqtt_reconnects < 1) json["mqttreconn"] = mqtt_reconnects;
      else json["mqttreconn"] = mqtt_reconnects - 1;

      #ifdef FIRMWARE_VARIANT_HEATCONTROL
        json["tempFeed"] = owTemp_feed;
        json["tempReturn"] = owTemp_return;
        json["tempOut"] = owTemp_out;

        if (heatcontrol_in_heat_request) json["heatReq"] = 1;
        else json["heatReq"] = 0;

        if (heatcontrol_in_heat_active) json["statHeat"] = 1;
        else json["statHeat"] = 0;

        if (heatcontrol_out_heat) json["outHeat"] = 1;
        else json["outHeat"] = 0;

        if (heatcontrol_out_pump) json["outPump"] = 1;
        else json["outPump"] = 0;

        //if (heatcontrol_state_testmode_active) json["statTest"] = 1;
        //else json["statTest"] = 0;
        json["statTest"] = heatcontrol_testMode_getRemainingMins();

        //if (heatcontrol_state_pumpBacklash_active) json["pumpNL"] = 1;
        //else json["pumpNL"] = 0;
        json["pumpNL"] = heatcontrol_pumpBacklash_getRemainingMins();


        if (heatcontrol_in_sw_disableControl_heating) json["cDisHeat"] = 1;
        else json["cDisHeat"] = 0;

        if (heatcontrol_in_sw_disableControl_pump) json["cDisPump"] = 1;
        else json["cDisPump"] = 0;
        
        json["currHeatC"] = heatcontrol_currentHeatCurveValue;
        json["currHeatCOff"] = heatcontrol_currentHeatCurveValue + confHeatc.hystereseOff;
        json["currHeatCOn"] = heatcontrol_currentHeatCurveValue - confHeatc.hystereseOn ;
        
        json["statLockTime"] = heatcontrol_lockTime_getRemainingMins();
        
        if (heatcontrol_getLockActive()) json["statLock"] = 1;
        else json["statLock"] = 0;

        if (heatcontrol_getLockActive() && heatcontrol_lockTime_getRemainingMins() == 0) {
          json["lockUntilTFeed"] = heatcontrol_currentHeatCurveValue - confHeatc.hystereseOn;
        }
        else {
          json["lockUntilTFeed"] = "-";
        }
        

      #endif // FIRMWARE_VARIANT_HEATCONTROL
      
      #ifdef FIRMWARE_VARIANT_THERMOSTAT
      json["setTemp"] = thermostat_setTemp;
      json["currSetTemp"] = thermostat_currSetTemp;
      json["actSetTemp"] = thermostat_currActualSetTemp;

      uint8_t _heatingState;
      if(thermostat_turnHeatingOn) _heatingState = 1;
      else if(thermostat_heatingLockTime > 0) _heatingState = 2;
      else _heatingState = 0;
      
      json["heating"] = _heatingState;
      json["heatingLockTime"] = thermostat_heatingLockTime;
      json["heatingPause"] = thermostat_heatingPause;
      json["mode"] = thermostat_heatingMode;
      json["modeName"] = thermostat_currentModeName;
      json["pset"] = thermostat_preset;
      json["psetName"] = thermostat_currentPresetName;
      json["psetName0"] = confTherm.psetName0;
      json["psetName1"] = confTherm.psetName1;
      json["psetName2"] = confTherm.psetName2;
      json["tempLow"] = thermostat_setTempLow;
      json["tempLow2"] = thermostat_setTempLow2;
      #endif // FIRMWARE_VARIANT_THERMOSTAT

      #ifdef ENABLE_OUTSIDE_TEMP_MQTT
      json["outTemp"] = round1(outTemp);
      json["outHum"] = outHum;
      #endif

      #ifdef ENABLE_SENSOR_DHT22
      json["temp"] = round1(sensor_DHT_currTemp);
      json["hum"] = int(sensor_DHT_currHum);
      #endif

      char jsonchar[750];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /api



  httpServer.on("/confDataWeb", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      json["apiToken"] = confSecrets.http_token;
      json["httpUA"] = confSecrets.http_user;
      
      //json["httpPA"] =  confWeb.http_pass;
      if (strlen(confSecrets.http_pass) > 0)
        json["httpPA"] = "****";
      else
        json["httpPA"] = "";

      if (confWeb.http_user_auth)
        json["httpAuth"] = 1;
      else
        json["httpAuth"] = 0;

      json["httpU1"] = confSecrets.http_user1;
      
      //json["httpP1"] =  confSecrets.http_pass1;
      if (strlen(confSecrets.http_pass1) > 0)
        json["httpP1"] = "****";
      else
        json["httpP1"] = "";
      json["httpU2"] = confSecrets.http_user2;
      
      //json["httpP2"] =  confSecrets.http_pass2;
      if (strlen(confSecrets.http_pass2) > 0)
        json["httpP2"] = "****";
      else
        json["httpP2"] = "";

      if (confWeb.wConsole)
        json["wConsole"] = 1;
      else
        json["wConsole"] = 0;
        
      if (confWeb.wsConsole)
        json["wsConsole"] = 1;
      else
        json["wsConsole"] = 0;

      if (confWeb.enableOTA) json["enableOTA"] = 1;
      else json["enableOTA"] = 0;

      if (confWeb.FSbrowser) json["FSbrowser"] = 1;
      else json["FSbrowser"] = 0;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confdweb



  httpServer.on("/confDataSens", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      json["measInt"] = confSens.measureInterval;

      #ifdef ENABLE_SENSORS_ONEWIRE
        JsonArray jsonArr_sensAddr = json.createNestedArray("sensAddr");
        JsonArray jsonArr_sensVal = json.createNestedArray("sensVal");
        JsonArray jsonArr_sensAss = json.createNestedArray("sensAss");

        for (uint8_t i=0; i < oneWireSensors.getDeviceCount(); i++) {
          char devAddr[25];
          char jsonDatasetName[15];

          float tempC;

          tempC = oneWireSensors.getTempC(oneWireSensors_IndexToAddress[i]);
          sprintf(devAddr, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x", oneWireSensors_IndexToAddress[i][0], \
                                                                      oneWireSensors_IndexToAddress[i][1], \
                                                                      oneWireSensors_IndexToAddress[i][2], \
                                                                      oneWireSensors_IndexToAddress[i][3], \
                                                                      oneWireSensors_IndexToAddress[i][4], \
                                                                      oneWireSensors_IndexToAddress[i][5], \
                                                                      oneWireSensors_IndexToAddress[i][6], \
                                                                      oneWireSensors_IndexToAddress[i][7]);

          jsonArr_sensAddr.add(devAddr);
          jsonArr_sensVal.add(tempC);

          uint8_t _assignSens = 255;

          if(oneWireSensor_assignedDevToIndex[ONEWIRE_SENSOR_INDEX_FEED] == i) {
            jsonArr_sensAss.add("FEED");
            _assignSens = ONEWIRE_SENSOR_INDEX_FEED;
          }
          else if(oneWireSensor_assignedDevToIndex[ONEWIRE_SENSOR_INDEX_RETURN] == i) {
            jsonArr_sensAss.add("RETURN");
            _assignSens = ONEWIRE_SENSOR_INDEX_RETURN;
          }
          else if(oneWireSensor_assignedDevToIndex[ONEWIRE_SENSOR_INDEX_OUT] == i) {
            jsonArr_sensAss.add("OUT");
            _assignSens = ONEWIRE_SENSOR_INDEX_OUT;
          }
          else jsonArr_sensAss.add("");

          sprintf(jsonDatasetName, "assignSens_%d", i);
          json[jsonDatasetName] = _assignSens;
        }
        yield();
      #endif

        
      #ifdef ENABLE_SENSOR_DHT22
        json["DHT_tempCorr"] = confSens.DHT_tempCorrVal;
        json["DHT_humCorr"] = confSens.DHT_humCorrVal;
      #endif

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataSens



  httpServer.on("/confDataMqtt", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      if (confMqtt.mqtt_enable)
        json["mqttEnable"] = 1;
      else
        json["mqttEnable"] = 0;

      json["mqttHost"] = confMqtt.mqtt_server;
      json["mqttPort"] = confMqtt.mqtt_port;
      json["mqttUser"] = confSecrets.mqtt_user;

      //json["mqttPass"] =  confMqtt.mqtt_pass;
      if (strlen(confSecrets.mqtt_pass) > 0)
        json["mqttPass"] = "****";
      else
        json["mqttPass"] = "";

      json["inTop"] = confMqtt.mqtt_topic_in;
      json["outTop"] = confMqtt.mqtt_topic_out;

      if (confMqtt.mqtt_outRetain)
        json["outRet"] = 1;
      else
        json["outRet"] = 0;
      if (confMqtt.mqtt_outRetain_sensors)
        json["outRetSens"] = 1;
      else
        json["outRetSens"] = 0;

      json["outPubInt"] = confMqtt.mqtt_outPubInterval;
      json["outPubIntSens"] = confMqtt.mqtt_outPubInterval_sensors;

      json["willTop"] = confMqtt.mqtt_willTopic;
      json["willQos"] = confMqtt.mqtt_willQos;

      if (confMqtt.mqtt_willRetain)
        json["willRet"] = 1;
      else
        json["willRet"] = 0;

      json["willMsg"] = confMqtt.mqtt_willMsg;
      json["connMsg"] = confMqtt.mqtt_connMsg;

      if (confMqtt.mqtt_enable_heartbeat)
        json["hbEnable"] = 1;
      else
        json["hbEnable"] = 0;

      json["hbReconn"] = confMqtt.mqtt_heartbeat_maxage_reconnect;
      json["hbReboot"] = confMqtt.mqtt_heartbeat_maxage_reboot;

      if (confMqtt.mqtt_reconnect_silent)
        json["reconSilent"] = 1;
      else
        json["reconSilent"] = 0;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataMqtt



  httpServer.on("/setConfWeb", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      bool httpPASet, httpP1Set, httpP2Set;
      httpPASet = false;
      httpP1Set = false;
      httpP2Set = false;
      if (httpServer.hasArg("httpPASet"))
        httpPASet = true;
      if (httpServer.hasArg("httpP1Set"))
        httpP1Set = true;
      if (httpServer.hasArg("httpP2Set"))
        httpP2Set = true;

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }

          if (strcmp(bufName, "httpUA") == 0 || strcmp(bufName, "httpPA") == 0)
          {
            if (httpPASet)
              setConfig(bufName, bufValue);
          }
          else if (strcmp(bufName, "httpU1") == 0 || strcmp(bufName, "httpP1") == 0)
          {
            if (httpP1Set)
              setConfig(bufName, bufValue);
          }
          else if (strcmp(bufName, "httpU2") == 0 || strcmp(bufName, "httpP2") == 0)
          {
            if (httpP2Set)
              setConfig(bufName, bufValue);
          }
          else if (strcmp(bufName, "httpPASet") != 0 && strcmp(bufName, "httpP1Set") != 0 && strcmp(bufName, "httpP2Set") != 0) {
            setConfig(bufName, bufValue);
          }
          else {
            setConfig(bufName, bufValue);
          }
        }
      }
      yield();

      saveConf_Web();
      saveConf_Secrets();
      yield();
      loadConf_Web();
      loadConf_Secrets();
      yield();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfWeb



  httpServer.on("/setConfMqtt", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      bool mqttPassSet;
      mqttPassSet = false;
      if (httpServer.hasArg("mqttPassSet"))
        mqttPassSet = true;

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }

          if (strcmp(bufName, "mqttUser") == 0 || strcmp(bufName, "mqttPass") == 0)
          {
            if (mqttPassSet)
              setConfig(bufName, bufValue);
          }
          else
            setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Mqtt();
      saveConf_Secrets();
      yield();
      loadConf_Mqtt();
      loadConf_Secrets();

      //httpServerHandleConfSavedRestartPage();
      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfMqtt



  httpServer.on("/confDataDevWiFi", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      
      StaticJsonDocument<800> json;

      json["devName"] = confDevWiFi.deviceName;
      json["hostName"] = confDevWiFi.hostName;
      json["SSID1"] = confDevWiFi.WiFiSSID1;
      
      //json["WPW1"] = confDevWiFi.WiFiPW1;
      if (strlen(confSecrets.WiFiPW1) > 0)
        json["WPW1"] = "****";
      else
        json["WPW1"] = "";

      json["SSID2"] = confDevWiFi.WiFiSSID2;
      
      //json["WPW2"] = confDevWiFi.WiFiPW2;
      if (strlen(confSecrets.WiFiPW2) > 0)
        json["WPW2"] = "****";
      else
        json["WPW2"] = "";

      json["SSIDAP"] = confDevWiFi.WiFiAPModeSSID;
      json["WPWAP"] = confSecrets.WiFiAPModePassword;
      json["WAPtout"] = confDevWiFi.WiFiAPModeTimeout;
      json["WConnCheck"] = confDevWiFi.WiFiConnCheckInterval;
      json["Wretry"] = confDevWiFi.WiFiRetryInterval;
      json["Wreboot"] = confDevWiFi.WiFiRebootOnNoConnect;
      if(confDevWiFi.enableArduinoOTA) json["ArdOTA"] = 1;
      else json["ArdOTA"] = 0;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataDevWiFi



  httpServer.on("/setConfDevWiFi", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      bool WPW1Set, WPW2Set, WPWAPSet;
      WPW1Set = false;
      WPW2Set = false;
      WPWAPSet = false;
      if (httpServer.hasArg("WPW1Set"))
        WPW1Set = true;
      if (httpServer.hasArg("WPW2Set"))
        WPW2Set = true;
      if (httpServer.hasArg("WPWAPSet"))
        WPWAPSet = true;

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }

          if (strcmp(bufName, "SSID1") == 0 || strcmp(bufName, "WPW1") == 0)
          {
            if (WPW1Set)
              setConfig(bufName, bufValue);
          }
          else if (strcmp(bufName, "SSID2") == 0 || strcmp(bufName, "WPW2") == 0)
          {
            if (WPW2Set)
              setConfig(bufName, bufValue);
          }
          else if (strcmp(bufName, "WPWAP") == 0)
          {
            if (WPWAPSet)
              setConfig(bufName, bufValue);
          }
          else
            setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_DevWiFi();
      saveConf_Secrets();
      yield();
      loadConf_DevWiFi();
      loadConf_Secrets();

      //httpServerHandleConfSavedRestartPage();
      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfDevWiFi



#ifdef FIRMWARE_VARIANT_THERMOSTAT
  httpServer.on("/setConfTherm", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Therm();
      yield();
      loadConf_Therm();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfTherm
#endif // FIRMWARE_VARIANT_THERMOSTAT



#ifdef FIRMWARE_VARIANT_HEATCONTROL
  httpServer.on("/setConfHeatc", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Heatc();
      yield();
      loadConf_Heatc();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfHeatc
#endif // FIRMWARE_VARIANT_HEATCONTROL



  httpServer.on("/setConfAdd", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Add();
      yield();
      loadConf_Add();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfAdd

#ifdef ENABLE_FEATURE_NTP_TIME
  httpServer.on("/setConfTime", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Time();
      yield();
      loadConf_Time();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfTime
#endif

  httpServer.on("/setConfLog", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Log();
      yield();
      loadConf_Log();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfLog



  httpServer.on("/setConfSens", []() {
    if (!httpIsAuthenticatedAdmin())
      httpSendUnauthorized();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      for (int i = 0; i < httpServer.args(); i++)
      {
        char bufName[21];
        char bufValue[101];
        httpServer.argName(i).toCharArray(bufName, 20);
        httpServer.arg(i).toCharArray(bufValue, 100);

        if (strlen(bufName) > 0 && strcmp(bufName, "plain") != 0) // filter arg "plain" as it sometimes shows up containing ALL arguments
        {
          if(debug>0) {
            snprintf_P(logBuf, LOG_BUFFER_SIZE, PGMStr_web_setConf, bufName, bufValue);
            sendLog(logBuf);
          }
          setConfig(bufName, bufValue);
        }
      }
      yield();
      saveConf_Sens();
      yield();
      loadConf_Sens();

      httpServerHandlePage_confSaved();
    }
  }); //httpServer.on /setConfLog



#ifdef FIRMWARE_VARIANT_THERMOSTAT
  httpServer.on("/confDataTherm", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      
      StaticJsonDocument<500> json;

      if (confTherm.autoSaveSetTemp)
        json["autoSaveTemp"] = 1;
      else
        json["autoSaveTemp"] = 0;

      if (confTherm.autoSaveHeatingMode)
        json["autoSaveMode"] = 1;
      else
        json["autoSaveMode"] = 0;

      if (confTherm.saveToMqttRetained)
        json["saveToMqttRet"] = 1;
      else
        json["saveToMqttRet"] = 0;

      json["tempMin"] = confTherm.setTempMin;
      json["tempMax"] = confTherm.setTempMax;
      //json["measInt"] = confTherm.measureInterval;
      //json["dispInt"] = confTherm.displayInterval;
      //json["dispTout"] = confTherm.displayTimeout;

      //if (confTherm.PIR_enablesDisplay)
      //  json["PIRenDisp"] = 1;
      //else
      //  json["PIRenDisp"] = 0;

      if (confTherm.PIRenablesDisplay_preset0only)
        json["PIRenDispPs0"] = 1;
      else
        json["PIRenDispPs0"] = 0;

      if (confTherm.togglingTempHumAIDisplay)
        json["togTHdisp"] = 1;
      else
        json["togTHdisp"] = 0;

      json["minOffTime"] = confTherm.heatingMinOffTime;
      json["tempDec"] = confTherm.setTempDecreaseVal;
      json["hyst"] = confTherm.hysteresis;
      json["offMsg"] = confTherm.offMessage;
      json["modeName0"] = confTherm.modeName0;
      json["modeName1"] = confTherm.modeName1;
      json["psetName0"] = confTherm.psetName0;
      json["psetName1"] = confTherm.psetName1;
      json["psetName2"] = confTherm.psetName2;
      json["iTempLab"] = confTherm.iTempLabel;
      json["oTempLab"] = confTherm.oTempLabel;
      json["pauseTout"] = confTherm.pauseTout;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataTherm

  
#endif  // FIRMWARE_VARIANT_THERMOSTAT



#ifdef FIRMWARE_VARIANT_HEATCONTROL
  httpServer.on("/confDataHeatc", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      
      StaticJsonDocument<500> json;

      json["heatcm20"] = confHeatc.heatCurve[0];
      json["heatcm15"] = confHeatc.heatCurve[1];
      json["heatcm10"] = confHeatc.heatCurve[2]; 
      json["heatcm5"]  = confHeatc.heatCurve[3];
      json["heatc0"]   = confHeatc.heatCurve[4];
      json["heatc5"]   = confHeatc.heatCurve[5];
      json["heatc10"]  = confHeatc.heatCurve[6];
      json["heatc15"]  = confHeatc.heatCurve[7];
      json["heatc20"]  = confHeatc.heatCurve[8];

      json["heatlm20"] = confHeatc.heatLocktime[0];
      json["heatlm15"] = confHeatc.heatLocktime[1];
      json["heatlm10"] = confHeatc.heatLocktime[2]; 
      json["heatlm5"]  = confHeatc.heatLocktime[3];
      json["heatl0"]   = confHeatc.heatLocktime[4];
      json["heatl5"]   = confHeatc.heatLocktime[5];
      json["heatl10"]  = confHeatc.heatLocktime[6];
      json["heatl15"]  = confHeatc.heatLocktime[7];
      json["heatl20"]  = confHeatc.heatLocktime[8];

      json["heatCvHy0"]  = confHeatc.hystereseOff;
      json["heatCvHy1"]  = confHeatc.hystereseOn;
      
      json["heatOutTDis"]  = confHeatc.disableAboveTOut;
      
      json["heatTempFeedLimit"]  = confHeatc.tempFeedLimit;

      if (confHeatc.useHeatCurve) json["heatUseHC"] =  1;
      else json["heatUseHC"] =  0;

      if (confHeatc.forceHeatCurve) json["heatForceHC"] =  1;
      else json["heatForceHC"] =  0;

      if (confHeatc.forceHeatCurveAlsoForSwitchOn) json["heatForceHCAlsoOn"] =  1;
      else json["heatForceHCAlsoOn"] =  0;

      json["pumpnl"] = confHeatc.pumpBacklash;
      
      json["pumpForceInt"] = confHeatc.pump_forceRunInterval;
      json["pumpForceTime"] = confHeatc.pumpTime_forceRun;
      json["pumpForceBegin"] = confHeatc.pump_forceRunTimeBegin;
      json["pumpForceEnd"] = confHeatc.pump_forceRunTimeEnd;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataHeatc

  
#endif  // FIRMWARE_VARIANT_HEATCONTROL



  httpServer.on("/confDataAdd", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      json["outTempTop"] = confAdd.outTemp_topic_in;
      json["outHumTop"] = confAdd.outHum_topic_in;
      json["PIRTop"] = confAdd.mqtt_topic_pir;
      json["PIROnPld"] = confAdd.mqtt_payload_pir_on;
      json["PIROffPld"] = confAdd.mqtt_payload_pir_off;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataAdd

  httpServer.on("/confDataTime", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      if (confTime.ntpEnable)
        json["NTPEnable"] = 1;
      else
        json["NTPEnable"] = 0;

      json["NTPServer1"] = confTime.ntpServer1;
      json["NTPServer2"] = confTime.ntpServer2;
      json["TZStr"] = confTime.timeZoneStr;
      json["NTPSyncInt"] = confTime.ntpSyncInterval / 60;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataTime

  httpServer.on("/confDataLog", []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      StaticJsonDocument<1000> json;

      json["logLevSer"] = confLog.logLevelSerial;
      json["logLevWeb"] = confLog.logLevelWeb;
      json["logLevMqtt"] = confLog.logLevelMqtt;

      if (confLog.logWebRequests)
        json["logWebRequests"] = 1;
      else
        json["logWebRequests"] = 0;

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /confDataLog

  //get heap status, analog input value and all GPIO statuses in one json call
  httpServer.on("/sysinfod", HTTP_GET, []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();

      char buf[40];
      byte mac[6];
      WiFi.macAddress(mac);

      StaticJsonDocument<1000> json;
      json["DevName"] = confDevWiFi.deviceName;
      json["HostName"] = confDevWiFi.hostName;

      sprintf(buf, "%02X:%02X:%02X:%02X:%02X:%02X", (uint8_t)mac[0], (uint8_t)mac[1], (uint8_t)mac[2], (uint8_t)mac[3], (uint8_t)mac[4], (uint8_t)mac[5]);
      json["MAC"] = buf;

      json["IP"] = WiFi.localIP().toString();
      json["GW"] = WiFi.gatewayIP().toString();
      json["DNS"] = WiFi.dnsIP().toString();

      json["SSID"] = WiFi.SSID();
      json["WiFiConf"] = persWM.getActiveWiFiNum();
      json["UpTime"] = getUptimeStr();
      json["HeapFree"] = ESP.getFreeHeap();
      json["HeapFragment"] = ESP.getHeapFragmentation();
      json["HeapMaxBlock"] = ESP.getMaxFreeBlockSize();
      json["ResetReason"] = ESP.getResetReason();
      json["CoreVersion"] = ESP.getCoreVersion();
      json["SDKVersion"] = ESP.getSdkVersion();
      json["CPUfreq"] = ESP.getCpuFreqMHz();
      json["SketchSize"] = ESP.getSketchSize();
      json["FlashSize"] = ESP.getFlashChipRealSize();

      mqtt_updateCurrentStateName();
      json["mqtthost"] = confMqtt.mqtt_server;
      json["mqttstate"] = mqttCurrentStateName;
      json["mqttstatN"] = mqttclient.state();

      if (mqtt_reconnects < 1) json["mqttreconn"] = mqtt_reconnects;
      else json["mqttreconn"] = mqtt_reconnects - 1;
      json["mqttTopIn"] = confMqtt.mqtt_topic_in;
      json["mqttTopLog"] = mqtt_topic_log;
      json["mqttTopOut"] = confMqtt.mqtt_topic_out;


      sprintf(buf, "%s", PGMStr_FIRMWARE_NAME);
      json["FWName"] = buf;

      sprintf(buf, "%s", PGMStr_FIRMWARE_VERSION);
      json["FWVer"] = buf;

      sprintf(buf, "%s", PGMStr_FIRMWARE_COPYRIGHT);
      json["FWCr"] = buf;

      sprintf(buf, "%s", compile_date);
      json["FWBuilt"] = buf;
      #ifdef DEBUGMODE
            json["FWDebug"] = "yes";
      #else
            json["FWDebug"] = "no";
      #endif

      #ifdef ENABLE_FEATURE_NTP_TIME
      if (confTime.ntpEnable)
      {
        char buf[13];
        updateTime();
        if(lt.tm_year > 70) {
          strftime(buf, sizeof(buf), "%H:%M", &lt);
          json["Time"] = buf;
          strftime(buf, sizeof(buf), "%d.%m.%Y", &lt);
          json["Date"] = buf;
        }
      }
      #endif

      yield();

      char jsonchar[1000];
      serializeJson(json, jsonchar);
      httpServer.send(200, "application/json", jsonchar);
    }
  }); //httpServer.on /sysinfod


  httpServer.on("/sysinfo", HTTP_GET, []() {
    if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_sysInfo();
    }
  });


  #ifdef ENABLE_FEATURE_FILESYSTEM_BROWSER
  httpServer.on("/fs", HTTP_GET, []() {
    if(confWeb.FSbrowser) {
      if (!httpIsAuthenticatedAdmin())
        return httpServer.requestAuthentication();
      else
      {
        if (confLog.logWebRequests) httpServer_logWebRequest();
        strcpy(httpServer_returnPage, "/fs"); // save return page to global var as couldnt get it to work via http header when using file upload
        httpServerHandlePage_fsbrowser();
      }
    }
  });
  #endif


  httpServer.on("/", []() {
    String addr = httpServer.client().remoteIP().toString();
    if (confLog.logWebRequests) httpServer_logWebRequest();

    if (httpServer.hasArg("restart"))
    {
      if (httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()))
      {
        sendLog(F("WEB: /?restart"), LOGLEVEL_INFO);
        httpServerHandlePage_restart();
        //restart();
        restart_delayed(2);
      }
      else
        httpSendUnauthorized();
    }
    else if (httpServer.hasArg("mqttreconnect"))
    {
      if (httpIsAuthenticated() || (!httpIsAuthenticated() && httpCheckToken()))
      {
        sendLog(F("WEB: /?mqttreconnect"), LOGLEVEL_INFO);
        mqttReconnect();
        httpServer.sendHeader("Location", "/", true);
        httpServer.send(303);
      }
      else
        httpSendUnauthorized();
    }
    else if (httpServer.hasArg("clearconf"))
    {
      if (httpIsAuthenticatedAdmin() || (!httpIsAuthenticatedAdmin() && httpCheckToken()))
      {
        sendLog(F("WEB: /?clearconf"), LOGLEVEL_INFO);
        httpServerHandlePage_clearConf();

        yield();
        delay(5);
        deleteConfig();
      }
      else
        httpSendUnauthorized();
    }
    else if (httpServer.hasArg("clearwifi"))
    {
      if (httpIsAuthenticatedAdmin() || (!httpIsAuthenticatedAdmin() && httpCheckToken()))
      {
        sendLog(F("WEB: /?clearwifi"), LOGLEVEL_INFO);
        httpServerHandlePage_clearConf();

        yield();
        delay(5);
        confClearWiFiCredentials();
      }
      else
        httpSendUnauthorized();
    }
    else if (httpServer.hasArg("clearcreds"))
    {
      if (httpIsAuthenticatedAdmin() || (!httpIsAuthenticatedAdmin() && httpCheckToken()))
      {
        sendLog(F("WEB: /?clearcreds"), LOGLEVEL_INFO);
        httpServerHandlePage_clearConf();

        yield();
        delay(5);
        confClearCredentials();
      }
      else
        httpSendUnauthorized();
    }
    else if (!httpIsAuthenticated())
      return httpServer.requestAuthentication();
    else
    {
      httpServerHandlePage_main();
    }
  });

  httpServer.on("/conf", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_admin();
    }
  });

  httpServer.on("/confweb", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confWeb();
    }
  });

  httpServer.on("/confMqtt", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confMqtt();
    }
  });

  httpServer.on("/confDevWiFi", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confDevWiFi();
    }
  });

  httpServer.on("/confSens", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confSens();
    }
  });



  #ifdef FIRMWARE_VARIANT_THERMOSTAT
  httpServer.on("/confTherm", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confTherm();
    }
  });

  httpServer.on("/ThermRedTemps", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_ThermRedTemps();
    }
  });
  #endif



  #ifdef FIRMWARE_VARIANT_HEATCONTROL
  httpServer.on("/confHeatc", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confHeatc();
    }
  });
  #endif





  httpServer.on("/confAdd", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confAdd();
    }
  });

  #ifdef ENABLE_FEATURE_NTP_TIME
  httpServer.on("/confTime", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confTime();
    }
  });
  #endif

  httpServer.on("/confLog", []() {
    if (!httpIsAuthenticatedAdmin())
      return httpServer.requestAuthentication();
    else
    {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServerHandlePage_confLog();
    }
  });


#ifdef ENABLE_FEATURE_WSCONSOLE
  if (confWeb.wsConsole)
  {
    httpServer.on("/wsconsole", []() {
      if (!httpIsAuthenticatedAdmin())
        return httpServer.requestAuthentication();
      else
      {
        if (confLog.logWebRequests) httpServer_logWebRequest();

        wsValidSessionId = millis();
        char sidbuf[20];
        sprintf(sidbuf, "sessionId=%lu|", wsValidSessionId);
        httpServer.sendHeader("Set-Cookie", sidbuf);
        httpServerHandlePage_WSConsole();
      }
    });
    //httpServer.on("/wsapp.js", []() {
    //  httpServer.sendHeader("cache-control", "max-age=86400", false);
    //  httpServer.send_P(200, "text/javascript", js_wsapp);
    //});
  }
#endif


  httpServer.onNotFound([]() {
    String addr = httpServer.client().remoteIP().toString();
    httpServerHandleNotFound();
  }); //httpServer.onNotFound



#ifdef ENABLE_FEATURE_WEB_CONSOLE
  if (confWeb.wConsole)
  {
    httpServer.on("/console", []() {
      if (!httpIsAuthenticatedAdmin())
        return httpServer.requestAuthentication();
      else
      {
        if (confLog.logWebRequests) httpServer_logWebRequest();
        httpServerHandlePage_console();
      }
    });

    httpServer.on("/webcsapi", []() {
      if (!httpIsAuthenticatedAdmin())
        return httpServer.requestAuthentication();
      else
      {
        if (httpServer.hasArg("cmd"))
        {
          char buf[101];
          httpServer.arg("cmd").toCharArray(buf, 100);
          strlcpy(cmdPayload, buf, sizeof(cmdPayload));
          cmdInQueue = true;
          evalCmd();
        }
        if (confLog.logWebRequests) httpServer_logWebRequest();
        httpServer.send(200, "text/plain", webLogBuffer);
      }
    });
    httpServer.on("/csapp.js", []() {
      if (confLog.logWebRequests) httpServer_logWebRequest();
      httpServer.sendHeader("cache-control", "max-age=86400", false);
      httpServer.send_P(200, "text/javascript", js_csapp);
    });
  }
#endif

// HTTP Updater at /update
#ifdef ENABLE_FEATURE_HTTP_UPDATER
  httpUpdater.setup(&httpServer, "/update", confSecrets.http_user, confSecrets.http_pass);
#endif

  httpServer.begin();
} // httpServerInit()
