Webinterface to control esp8266

Hi,

I am working on a new project. For lack of the ability to do real programming, obviously I stuck at the moment.
I want to control a LED-dim-program on a esp8266 and therefore I have to make a webinterface to input the user values.
I have test this and this sucessfully but I am not able to put things together to get my own working interface.
First, I have made the html-page.

<!DOCTYPE html>
<html>
<head>
  <title>illumination fish tank</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" type="text/css" href="style.css">
  <link rel="icon" type="image/png" href="favicon.png">
  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
</head>
<body>
  <div class="topnav">
    <h1>illumination fish tank <i class="fas fa-cogs"></i></h1>
  </div>
  <div class="card-grid">
  <div class="card">
  <p class="card-title">setup automated illumination</p>
        <form>
		
		<b>switch automated illumination on and off.</b><br><br>
          <input type="checkbox" id="state" name="switch" value="on" checked>
          <label for="state">on/off</label>
		  <br>
		  <br><b>if switched on, set sunrise and sunset time (24h format)</b></br><br>
          <label for="steps">sunrise (format: hh:mm)</label>
          <input type="time" id="sunrise" name="sunrise"><br><br>
		  <label for="steps">sunset (format: hh:mm)</b></label>
		  <input type="time" id="sunset " name="sunset">
        </form>
		<button onclick="submitForm()">save</button>
  </div>     
</div>  	
<br><br>
  <div class="card-grid">
            <div class="card">
                
                <p class="card-title">actual illumination value</p>
				<select name="illumination value">
  <option value="0">off</option>
  <option value="20">25%</option>
  <option value="50">50%</option>
  <option value="75">75%</option>
  <option value="100">100%</option>
  <option selected value="90">Default</option>
</select>
                    
               
                <button onclick="submitForm()">set action</button>
            </div>         
        </div>

  
  
</body>
<script src="script.js"></script>
</html>

It looks like this at the moment:
webint

So it is not that complicate.
If someone want's to setup the upper part of the form, he can fill the fields and submit by clicking save.
If you want to change the illumination value, you can choose from a drop down list and click set action.
I have saved that together with a script:
direct

So the really big problems are the script and maybe the c++ codepart in the arduino/esp8266 to get the data.
I do not really have a script yet only this scrap

var gateway = `ws://${window.location.hostname}/ws`;
var websocket;
window.addEventListener('load', onload);
var direction;

function onload(event) {
    initWebSocket();
}
function getValues(){
    websocket.send("getValues");
}

function initWebSocket() {
    console.log('Trying to open a WebSocket connection…');
    websocket = new WebSocket(gateway);
    websocket.onopen = onOpen;
    websocket.onclose = onClose;
    websocket.onmessage = onMessage;
}

function onOpen(event) {
    console.log('Connection opened');
	getValues();
}

function onClose(event) {
    console.log('Connection closed');
       setTimeout(initWebSocket, 2000);
}


function submitForm(){

    }



function onMessage(event) {
    console.log(event.data);
    direction = event.data;
	 var myObj = JSON.parse(event.data);
    var keys = Object.keys(myObj);

   
}

So, who of you great guys

  • and I really mean you are great because in the german section of this forum the helpful answers are rare; people there are focused to correct my spelling (even if I am natural speaker in german) and start some discussion which does not fit to my problems-
    who of you have time and want to help me in this project? I hope there is anyone out there.

Greetings
Sven

Hi,
There are many ways to serve web pages on an esp and so I found it very difficult to get started myself as every example I looked at was completely different...
so I created the below script which may be of help/interest as I think it demonstrates the easiest to follow way of serving simple web pages.
If you look at handleButton() this shows how to build and send the html and how to act on button clicks etc. which may be a good starting point for what you are wanting to do?

I don't know much about html-coding.
From a first quick look it looks like a promising and easy to understand example-code.

What I find really astonishing is the fact that the client.print function accepts the html-code well formatted spread over multiple lines without using the "backslash"-character that allows for extend to multiple lines.

best regards Stefan

Hi,
It gets a bit confusing as you are writing one language inside another one, it gets really silly if you then start adding javascript inside this - lol
BTW - I have just modified it so that it also shows how you can enter a value.

I am no expert myself in any of this which is why I am always trying to find the easiest way of doing this sort of thing so I can try and keep it as simple as I can.

I find this site really handy as you can search for how to do stuff in HTML and also try it out in their examples - HTML Reference
e.g. W3Schools Tryit Editor

I copy & pasted the RAW Version of your code into the Arduino-IDE
and uploaded it to an ESP32

it did compile
The ESP32 does connect to my WiFi
and I was able call the main-page.

But when I try the URL
http://192.168.178.143/test
I get an error-message website not reachable

So what could cause this error?

Hi,
I usually use PlatformIO but I just gave it a try in my Arduino IDE (I am using 1.8.16 but any should be ok) and copied/pasted the raw sketch from the above link and it worked ok - so I have no idea :frowning:

If the http://192.168.178.143/ is working then the others should work...
Does http://192.168.178.143/button or http://192.168.178.143/ajax work?

I did find in Arduino IDE the latest esp32 board manager caused me some issues so I stayed with v1.0.6, so I just tried downloading the latest version and whilst it still works it did seem reluctant to connect to my wifi and very slow to respond at first....
There seems to me something wrong with the latest esp32 board manager in Arduino IDE as I had lots of strange issues with it, unless someone else knows what is going on here maybe try using v1.0.6 of the ESP32 board manager?

hm.. -- ?? where did you get the version 1.0.6 from?
If I look up the board-manager in Arduino-IDE 1.8.19 is see this

The additional board manager url is this
https://dl.espressif.com/dl/package_esp32_index.json

I tested this asynchronius Webserver-Code

and it is running smoothly

Then I tested this one

runs smoothly too
best regards Stefan

Hi,
I wonder if you are getting your esp32 files from a different repository as yours doesn't even seem to show v1.0.6 let alone 2.x
Have a look in FILE, PREFERENCES and make sure the entry you have in ADDITIONAL BOARDS for esp32 is:
https://dl.espressif.com/dl/package_esp32_index.json

@crazysky for a such simple web interface, websocket is really not needed and it will make all things much difficult than necessary because you have to handle two kind of server on your ESP: webpage server an websocket server (your web browser will act as a client both for two technologies).

An Ajax request will do the job as well and it's simpler to understand for a beginner.
In your HTML code you are using a form, without sending the data inserted in the form and then you are using a button calling a JS function to do more or less the same thing.

Starting from your source I've edited like this (the script is embedded in HTML, but you can put in a distinct file if you prefer) with BOTH the methods.

In the JS script code you will find:

  • a first function for the button;
  • a "submit" event listener for the form.

The button-function I think is simple to understand (it rely on Javascript Fetch API), but regarding the form I usually avoid to let it doing the job as default because the webpage will be redirected to the "action" defined webpage (in HTML section) and this is not wanted most of the times.

In order to undestand very well how the webpage work, I suggest you to open the developer tools in your browser (F12) and set the "network" tab.

<!DOCTYPE html>
<html>
   <head>
      <title>illumination fish tank</title>
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <link rel="stylesheet" type="text/css" href="style.css">
      <link rel="icon" type="image/png" href="favicon.png">
      <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
   </head>
   <body>
      <div class="topnav">
         <h1>illumination fish tank <i class="fas fa-cogs"></i></h1>
      </div>
      <div class="card-grid">
         <div class="card">
            <p class="card-title">setup automated illumination</p>
            <form enctype="text/plain" action="/setTime" method="post" name="set-time">
               <b>switch automated illumination on and off.</b><br><br>
               <input type="checkbox" id="state" name="switch" value="on" checked>
               <label for="state">on/off</label>
               <br>
               <br>
               <b>if switched on, set sunrise and sunset time (24h format)</b><br>
               <label for="steps">sunrise (format: hh:mm)</label>
               <input type="time" id="sunrise" name="sunrise"><br><br>
               <label for="steps">sunset (format: hh:mm)</label>
               <input type="time" id="sunset " name="sunset">
               <br>
               <input type="submit" value="Save">
            </form>
            <!--<button onclick="submitForm()">save</button>-->
         </div>
      </div>
      <br><br>
      <div class="card-grid">
         <div class="card">
            <p class="card-title">actual illumination value</p>
            <select id="illumination-value" name="illumination value">
               <option value="0">off</option>
               <option value="20">25%</option>
               <option value="50">50%</option>
               <option value="75">75%</option>
               <option value="100">100%</option>
               <option selected value="90">Default</option>
            </select>
            <button onclick="setIllumination()">set action</button><br>
            <div id="server-response"></div>
         </div>
      </div>
      
      <script>
        // This function will be called from "set action" 
        function setIllumination() {
          var element = document.getElementById("illumination-value")
          var url = new URL("http://" + `${window.location.hostname}` + "/setIllumination")
          url.searchParams.append("light-level", element.value)
          
          // Fetch the GET request with params
          fetch(url)
         
          // Handle the server response 
          // (usually server will reply after a little time)
          .then(response => response.text())
          .then(text => {
            document.getElementById("server-response").innerHTML = text
            console.log(text)
          })
         
          // Handle errors (optional)
          .catch((error) => { 
            console.log(error) 
          })
        }
        
    
        // This listener will prevent form submit to reload page, 
        // and then execute the submit of forma data
        document.addEventListener("submit", (e) => {
          // Store reference to form to make later code easier to read
          const form = e.target;
       
          // POST data using the Fetch API
          fetch(form.action, {
            method: form.method,
            body: new FormData(form),
          })
          
          // Handle the server response
          .then(response => response.text())
          .then(text => {
            console.log(text)
          })
          
          // Prevent the default form submit
          e.preventDefault();
        });
      </script>
   </body>
</html>

And from the ESP side you need to add the two Ajax request handlers (just an example of how-to)

void handleIllumination() {
  if (server.hasArg("light-level")) {
    String reply = "Illumination level: ";
    reply += server.arg("light-level").toInt();
    Serial.println(reply);
    server.send(200, "text/plain", reply);
  }
}

void handleSetTime() {
  if (server.hasArg("switch")) {
    String reply = "Switch state: ";
    reply += server.arg("switch");
    Serial.println(reply);
  }

  if (server.hasArg("sunrise")) {
    String reply = "Sunrise: ";
    reply += server.arg("sunrise");
    Serial.println(reply);
  }

  if (server.hasArg("sunset")) {
    String reply = "Sunset: ";
    reply +=server.arg("sunset");
    Serial.println(reply);
  }
   server.send(200, "text/plain", "setup automated illumination done");
}


void setup() {
.....
  server.on("/setIllumination", HTTP_GET, handleIllumination);
  server.on("/setTime", HTTP_POST, handleSetTime);
....

Hey, thanks a lot! I tried to do that but something may be missing. I get this error when I want to compile it:
'class AsyncWebServer' has no member named 'hasArg'

I've not used external library AsyncWebServer but the WebServer class included with ESP core.
You should check in the examples of AsyncWebServer how to add handlers for specific pages.

This is taken from the example simple_server.ino

    // Send a POST request to <IP>/post with a form field message set to <message>
    server.on("/post", HTTP_POST, [](AsyncWebServerRequest *request){
        String message;
        if (request->hasParam(PARAM_MESSAGE, true)) {
            message = request->getParam(PARAM_MESSAGE, true)->value();
        } else {
            message = "No message sent";
        }
        request->send(200, "text/plain", "Hello, POST: " + message);
    });

The author of library use a "lamba function" (the code with [](AsyncWebServerRequest *request)) inside the definition of handler.

If you want define it as a separate function, you could write:

void myHandlerFunction (AsyncWebServerRequest *request){
   String message;
   if (request->hasParam(PARAM_MESSAGE, true)) {
     message = request->getParam(PARAM_MESSAGE, true)->value();
   } 
   else {
      message = "No message sent";
   }
   request->send(200, "text/plain", "Hello, POST: " + message);
}

and then add the handler ot webserver

 server.on("/post", HTTP_POST, myHandlerFunction );

THank you so much for your effort.
This is too complicate for me. I can't make it. I have found another possible solution.

#include <Arduino.h>
#ifdef ESP32
  #include <WiFi.h>
  #include <AsyncTCP.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);


// Replace with your network credentials
const char* ssid = "fjhf";
const char* password = "jgfhj";

const char* PARAM_INPUT_1 = "sunrise";
const char* PARAM_INPUT_2 = "sunset";
const char* PARAM_INPUT_3 = "activate";
const char* PARAM_INPUT_4 = "illumination";
String sunset = "";
String activate = "";
String sunrise = "";
String illumination = "";

// HTML web page to handle 3 input fields (input1, input2, input3)
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html><head>
  <title>fish tank controlpanel</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  </head><body>
  <form action="/get">
    sunrise: <input type="time" name="sunrise">
    <input type="submit" value="Submit">
  </form><br>
  <form action="/get">
    sunset: <input type="time" name="sunset">
    <input type="submit" value="Submit">
</form><br>
<form action="/get">
 on: <input type="radio" name="activate" value="on"><br>
  off: <input type="radio" name="activate"  value="off"><br>
     <input type="submit" value="Submit">
</form>
<form action="/get">
  <label for="illumination">Choose a illumination value:</label>
  <select id="illumination" name="illumination">
    <option value="0">off</option>
    <option value="25">25%</option>
    <option value="50">50%</option>
    <option value="75">75%</option>
    <option value="100">100%</option>
    <option value="90">Default</option>
  </select>
  <input type="submit" value="Submit">
</form>

</body></html>)rawliteral";

void notFound(AsyncWebServerRequest *request) {
  request->send(404, "text/plain", "Not found");
}

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Failed!");
    return;
  }
  Serial.println();
  Serial.print("IP Address: ");
  Serial.println(WiFi.localIP());

  // Send web page with input fields to client
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html);
  });

  // Send a GET request to <ESP_IP>/get?input1=<inputMessage>
  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage;
    String inputParam;
    // GET input1 value on <ESP_IP>/get?input1=<inputMessage>
    if (request->hasParam(PARAM_INPUT_1)) {
      inputMessage = request->getParam(PARAM_INPUT_1)->value();
      inputParam = PARAM_INPUT_1;
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_2)) {
      inputMessage = request->getParam(PARAM_INPUT_2)->value();
      inputParam = PARAM_INPUT_2;
    }
        // GET input3 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_3)) {
      inputMessage = request->getParam(PARAM_INPUT_3)->value();
      inputParam = PARAM_INPUT_3;
    }
            // GET input4 value on <ESP_IP>/get?input2=<inputMessage>
    else if (request->hasParam(PARAM_INPUT_4)) {
      inputMessage = request->getParam(PARAM_INPUT_4)->value();
      inputParam = PARAM_INPUT_4;
    }
 
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    Serial.println(inputMessage);
    request->send(200, "text/html", "HTTP GET request sent to your ESP on input field (" 
                                     + inputParam + ") with value: " + inputMessage +
                                     "<br><a href=\"/\">Return to Home Page</a>");


if (inputParam == "activate") {
      activate = inputMessage;
    }
    // GET input2 value on <ESP_IP>/get?input2=<inputMessage>
    else if (inputParam == "sunset") {
      sunset = inputMessage;
    }
        // GET input3 value on <ESP_IP>/get?input2=<inputMessage>
    else if (inputParam == "sunrise") {
         sunrise = inputMessage;
    }
            // GET input4 value on <ESP_IP>/get?input2=<inputMessage>
    else if (inputParam == "illumination") {
         illumination = inputMessage;
    }
    Serial.print("state: ");
    Serial.println(activate);
    Serial.print("sunset: ");
    Serial.println(sunset);
    Serial.print("sunrise: ");
    Serial.println(sunrise);
    Serial.print("illumination: ");
    Serial.println(illumination);
  });
  server.onNotFound(notFound);
  server.begin();
}

void loop() {
  
}

It does not look very nice at the moment. Maybe I can improve the design by myself.
But it seems to work now. If I make some entries and submit them, they become values of my variables. So I can work with it.

Maybe you have some suggestions to improve this? For Example, it would be nice if the webinterface would show the actual values for sunset and sunrise and the activation state next to fields where I can make the entries.
screen

You are now passing the HTML page directly from memory instead from files hosted in flash memory like before.
If you change time by time the approach, every advise we give you became inconsistent.

Aniway, with your new code you are passing all parameters from webpage to ESP with a form, so Javascript it's not needed, but if you want to put actual values of variables in the webpage, you need to "create" the HTML code at runtime every time this values change.
The downside to all of this is that you have to load the webage into SRAM to be able to edit it .

From my point of view is the worst method to implement a webserver with ESP mcus.

It's far better add (again) a small <script></script> section to your HTML code. Then when the page is loaded, browser will call the javascript function getActualValues() wich "ask" to the ESP to send back the actual values of variables encoded as JSON string .

JSON string is very useful with Javascript because the parser is included natively and the usage is very simple.

I've edited again your last HTML code adding some span elements for showing the actual values, the script mentioned before and the onload event to the body tag

<!DOCTYPE HTML>
<html>
   <head>
      <title>fish tank controlpanel</title>
      <meta name="viewport" content="width=device-width, initial-scale=1">
   </head>
   <body onload="getActualValues()">
      <form action="/get">
         sunrise: <input type="time" name="sunrise">
         <input type="submit" value="Submit">
         <span id="sunrise-actual">xxxx</span> 
      </form>
      <br>
      <form action="/get">
         sunset: <input type="time" name="sunset">
        <input type="submit" value="Submit">
        <span id="sunset-actual">xxxx</span> 
      </form>
      <br>
      <form action="/get">
         on: <input type="radio" name="activate" value="on"><br>
         off: <input type="radio" name="activate"  value="off"><br>
         <input type="submit" value="Submit">
         <br>
         <b><span id="activate-actual">Actual state: xxxx</span></b>
      </form>
      <form action="/get">
         <label for="illumination">Choose a illumination value:</label>
         <select id="illumination" name="illumination">
            <option value="0">off</option>
            <option value="25">25%</option>
            <option value="50">50%</option>
            <option value="75">75%</option>
            <option value="100">100%</option>
            <option value="90">Default</option>
         </select>
         <input type="submit" value="Submit">
      </form>
      
      <script>      
        function getActualValues() {
          var url = new URL("http://" + `${window.location.hostname}` + "/getValues")
          fetch(url)

          .then(response => response.json())
          .then(data => {
            console.log(data)
            document.getElementById("sunrise-actual").innerHTML = data.sunrise
            document.getElementById("sunset-actual").innerHTML = data.sunset
            document.getElementById("activate-actual").innerHTML = "Actual state: " + data.activate
          })
        }
      </script>
   </body>
</html>

ESP side:

.......
server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String json = "{\"activate\":";
  json += "\"" + activate + "\",";
  json += "\"sunset\":";
  json += "\"" + sunset + "\",";
  json += "\"sunrise\":";
  json += "\"" + sunrise + "\",";
  json += "\"illumination\":";
  json += "\"" + illumination + "\"}";
  Serial.println(json);
  request->send(200, "text/json", json);
}

......

I can't do the ESP-side thing :frowning:
I think it's a bloody mess now.

//
// A simple server implementation showing how to:
//  * serve static messages
//  * read GET and POST parameters
//  * handle missing pages / 404s
//

#include <Arduino.h>
#ifdef ESP32
#include <WiFi.h>
#include <AsyncTCP.h>
#elif defined(ESP8266)
#include <ESP8266WiFi.h>
#include <ESPAsyncTCP.h>
#endif
#include <ESPAsyncWebServer.h>

AsyncWebServer server(80);

const char* ssid = "fjhfghj";
const char* password = "nfgjhgj";

const char* PARAM_MESSAGE = "message";

void notFound(AsyncWebServerRequest *request) {
    request->send(404, "text/plain", "Not found");
}

void setup() {

    Serial.begin(115200);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    if (WiFi.waitForConnectResult() != WL_CONNECTED) {
        Serial.printf("WiFi Failed!\n");
        return;
    }

    Serial.print("IP Address: ");
    Serial.println(WiFi.localIP());



  server.on("/get", HTTP_GET, [] (AsyncWebServerRequest *request) {
  String json = "{\"activate\":";
  json += "\"" + activate + "\",";
  json += "\"sunset\":";
  json += "\"" + sunset + "\",";
  json += "\"sunrise\":";
  json += "\"" + sunrise + "\",";
  json += "\"illumination\":";
  json += "\"" + illumination + "\"}";
  Serial.println(json);
  request->send(200, "text/json", json);
}

    server.onNotFound(notFound);

    server.begin();
}

void myHandlerFunction (AsyncWebServerRequest *request){
   String message;
   if (request->hasParam(PARAM_MESSAGE, true)) {
     message = request->getParam(PARAM_MESSAGE, true)->value();
   } 
   else {
      message = "No message sent";
   }
   request->send(200, "text/plain", "Hello, POST: " + message);
}

void handleIllumination (AsyncWebServerRequest *request) {
  if (server.hasArg("light-level")) {
    String reply = "Illumination level: ";
    reply += server.arg("light-level").toInt();
    Serial.println(reply);
    server.send(200, "text/plain", reply);
  }
}

void handleSetTime (AsyncWebServerRequest *request) {
  if (server.hasArg("switch")) {
    String reply = "Switch state: ";
    reply += server.arg("switch");
    Serial.println(reply);
  }

  if (server.hasArg("sunrise")) {
    String reply = "Sunrise: ";
    reply += server.arg("sunrise");
    Serial.println(reply);
  }

  if (server.hasArg("sunset")) {
    String reply = "Sunset: ";
    reply +=server.arg("sunset");
    Serial.println(reply);
  }
   server.send(200, "text/plain", "setup automated illumination done");
}

void loop() {
}

Yes it is!

Ok, let's reset all things.

I suppose you want come back to the "flash-hosted" file approach? If yes, lock this concept and work on it! Stop looking at web tutorial and youtube videos confusing yourself.

Would you like to try this library of mine? I can give you direct support, also with Github issues if you want.
cotestatnt/esp-fs-webserver: From FSBrowser.ino example to an Arduino library (github.com)

It's just a "wrapper" for the webserver class included with the default ESP core for Arduino (starting from inclueded example FSbrowser.ino), with the intention to write simpler ESP code.

The main advantage for a beginner in web page design is the included "online" HTML/CSS/Javascript web editor: you can edit directly the page inside the ESP memory without upload every time the new firmware.
In this way you can immediatly see what happen when you change something in webpage source code and practice yourself with HTML, Javascript and CSS coding (in order to create nice webpages)

It's not mandatory of course, but it will help I think.

Hey guy, finally it seems to work now! I took the simpleserver example and add the stuff of your post #9.
I had to adapt the servername and I have uploaded a new index.html file also containing the content of #9.
Now the very simple interface is working. Ok, one thing is not really working. I just can switch the checkbox to "on". If I do not check it, there is send nothing to the esp. So it is not possible to switch it off at the moment.

#include <esp-fs-webserver.h>  // https://github.com/cotestatnt/esp-fs-webserver

#include <FS.h>
#ifdef ESP8266
  #include <LittleFS.h>
  #define FILESYSTEM LittleFS
#elif defined(ESP32)
  #include <FFat.h>
  #define FILESYSTEM FFat
#endif

#ifndef LED_BUILTIN
#define LED_BUILTIN 2
#endif

// In order to set SSID and password open the /setup webserver page
// const char* ssid;
// const char* password;

uint8_t ledPin = LED_BUILTIN;
bool apMode = false;
char* hostname = "fsbrowser";

#ifdef ESP8266
  ESP8266WebServer server(80);
#elif defined(ESP32)
  WebServer server(80);
#endif
FSWebServer myWebServer(FILESYSTEM, server);


////////////////////////////////  Filesystem  /////////////////////////////////////////
void startFilesystem(){
  // FILESYSTEM INIT
  if ( FILESYSTEM.begin()){
    File root = FILESYSTEM.open("/", "r");
    File file = root.openNextFile();
    while (file){
      const char* fileName = file.name();
      size_t fileSize = file.size();
      Serial.printf("FS File: %s, size: %lu\n", fileName, (long unsigned)fileSize);
      file = root.openNextFile();
    }
    Serial.println();
  }
  else {
    Serial.println("ERROR on mounting filesystem. It will be formmatted!");
    FILESYSTEM.format();
    ESP.restart();
  }
}

////////////////////////////  HTTP Request Handlers  ////////////////////////////////////
void handleLed() {
  // If new led state is specified - http://xxx.xxx.xxx.xxx/led?val=1
  if(myWebServer.webserver->hasArg("val")) {
    int value = myWebServer.webserver->arg("val").toInt();
    digitalWrite(ledPin, value);
  }
  // else simple toggle the actual state
  else {
    digitalWrite(ledPin, !digitalRead(ledPin));
  }
  String reply = "LED is now ";
  reply += digitalRead(ledPin) ? "OFF" : "ON";
  myWebServer.webserver->send(200, "text/plain", reply);
}

void handleSetTime() {
  if (myWebServer.webserver->hasArg("switch")) {
    String reply = "Switch state: ";
    reply += myWebServer.webserver->arg("switch");
    Serial.println(reply);
  }

  if (myWebServer.webserver->hasArg("sunrise")) {
    String reply = "Sunrise: ";
    reply += myWebServer.webserver->arg("sunrise");
    Serial.println(reply);
  }

  if (myWebServer.webserver->hasArg("sunset")) {
    String reply = "Sunset: ";
    reply +=myWebServer.webserver->arg("sunset");
    Serial.println(reply);
  }
   myWebServer.webserver->send(200, "text/plain", "setup automated illumination done");
}

void handleIllumination() {
  if (myWebServer.webserver->hasArg("light-level")) {
    String reply = "Illumination level: ";
    reply += myWebServer.webserver->arg("light-level").toInt();
    Serial.println(reply);
    myWebServer.webserver->send(200, "text/plain", reply);
  }
}


void setup(){
  Serial.begin(115200);

  // FILESYSTEM INIT
  startFilesystem();

  // Try to connect to flash stored SSID, start AP if fails after timeout
  IPAddress myIP = myWebServer.startWiFi(15000, "ESP8266_AP", "123456789" );

  // Add custom page handlers to webserver
  myWebServer.addHandler("/led", HTTP_GET, handleLed);
  myWebServer.addHandler("/setIllumination", HTTP_GET, handleIllumination);
  myWebServer.addHandler("/setTime", HTTP_POST, handleSetTime);
  // Start webserver
  if (myWebServer.begin()) {
    Serial.print(F("ESP Web Server started on IP Address: "));
    Serial.println(myIP);
    Serial.println(F("Open /setup page to configure optional parameters"));
    Serial.println(F("Open /edit page to view and edit files"));
  }

  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  myWebServer.run();
  
}


and I did not remove the LED part yet. It was a good example.

This is an incomprehensible behavior of the form checkbox component .

As you can read from googling this topic, a possible solution is to use an hidden checkbox with the same name.

 <input type='hidden' id="hidden-activate" name="activate" value="off">
 <input type="checkbox" id="activate" name="activate" value="on" checked>
 <label for="state">on/off</label>

It works but you will have a post payload like this when the "real" checkbox is true (some other JS coding is needed to prevent):

activate: off
activate: on
sunrise: 10:00
sunset: 11:00

Is not a real problem, because you will set off with no effect because alreay off, and immediatly after it will be on as expected.

Anyway, a more clean solution would be to use two radio components instead a hidden/not-hidden checkboxes

<label for="activate">ON</label>
<input type="radio" name="activate" value="on" checked>
<label for="activate">OFF</label>
<input type="radio" name="activate" value="off">

yes, I think the radio buttons are the best solution. So thank you very much for your patience. You helped me a lot. I try to go on by myself now and I will open another thread if I get problems somewhere.
Thank you!

just one more thing :wink:

If I want to add a void function
like here:


void handleIllumination() {
  if (myWebServer.webserver->hasArg("light-level")) {
    String reply = "Illumination level: ";
    reply += myWebServer.webserver->arg("light-level").toInt();
    prozent = myWebServer.webserver->arg("light-level").toInt();
    Serial.println(reply);
    Serial.println(prozent);
    calcreverse();
    myWebServer.webserver->send(200, "text/plain", reply);
  }
}

calcreverse();

I just can't do that and I do not understand why.

exit status 1
'calcreverse' was not declared in this scope; did you mean 'reverse'?