(html) changing checkbox state depending on variable boolean

Hello guys,

I am currently working on an esp32 project and at the moment I am trying to implement a "smart" html checkbox on a web server. Let me explain.

I want to have a checkbox on a Website, which current status (checked or unchecked) should be updated every once in a while. When I say updated I mean that it's current state should adjusted to a boolean so that when i change the boolean by lets say a press of a hardware button the checkbox gets updated automatically. So that basically a buttonpress would do the same thing as ticking the checkbox but the checkbox on the webserver would get updated when a buttenpress and thus a status change would be detected.

As a basis for the checkbox currently use the code published here: https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/?unapproved=677718&moderation-hash=e7d115e73f50976449af402f9818b62e#comment-677718

Any ideas on how to pull this off or even better how i would have to adjust the code used in the linked example??

Have you checked out the Arduino IOT framework?

What you are trying to do is very easy using that framework... and you don't have to write all the HTML yourself.

Thanks for the guidence I'll make sure to look at it tomorrow :slight_smile:
I was in fact not aware of this thanks again.

uii, I did look at it in the last 20 min and it appears to me that the arduino IoT is kind of a different world. Because the rest of my code is already running i would like to stick to the manual approach of using the normal arduino IDE.
Like i said adjusting the presented code in the posted link would be superb.
Still thank you though.

I don't see the code, post it here.
It is not difficult to include a variable state in a webpage. To get a browser to keep requesting a webpage, there is HTML code to do that at regular intervals.
To get it to do so in some other way i don't know.
The browser has to make a request, and then the server serves the page.

/*********
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp32-async-web-server-espasyncwebserver-library/
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*********/

// Import required libraries
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>

// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

const char* PARAM_INPUT_1 = "output";
const char* PARAM_INPUT_2 = "state";

// Create AsyncWebServer object on port 80
AsyncWebServer server(80);

const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
  <title>ESP Web Server</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" href="data:,">
  <style>
    html {font-family: Arial; display: inline-block; text-align: center;}
    h2 {font-size: 3.0rem;}
    p {font-size: 3.0rem;}
    body {max-width: 600px; margin:0px auto; padding-bottom: 25px;}
    .switch {position: relative; display: inline-block; width: 120px; height: 68px} 
    .switch input {display: none}
    .slider {position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: #ccc; border-radius: 6px}
    .slider:before {position: absolute; content: ""; height: 52px; width: 52px; left: 8px; bottom: 8px; background-color: #fff; -webkit-transition: .4s; transition: .4s; border-radius: 3px}
    input:checked+.slider {background-color: #b30000}
    input:checked+.slider:before {-webkit-transform: translateX(52px); -ms-transform: translateX(52px); transform: translateX(52px)}
  </style>
</head>
<body>
  <h2>ESP Web Server</h2>
  %BUTTONPLACEHOLDER%
<script>function toggleCheckbox(element) {
  var xhr = new XMLHttpRequest();
  if(element.checked){ xhr.open("GET", "/update?output="+element.id+"&state=1", true); }
  else { xhr.open("GET", "/update?output="+element.id+"&state=0", true); }
  xhr.send();
}
</script>
</body>
</html>
)rawliteral";

// Replaces placeholder with button section in your web page
String processor(const String& var){
  //Serial.println(var);
  if(var == "BUTTONPLACEHOLDER"){
    String buttons = "";
    buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
    buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
    buttons += "<h4>Output - GPIO 33</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"33\" " + outputState(33) + "><span class=\"slider\"></span></label>";
    return buttons;
  }
  return String();
}

String outputState(int output){
  if(digitalRead(output)){
    return "checked";
  }
  else {
    return "";
  }
}

void setup(){
  // Serial port for debugging purposes
  Serial.begin(115200);

  pinMode(2, OUTPUT);
  digitalWrite(2, LOW);
  pinMode(4, OUTPUT);
  digitalWrite(4, LOW);
  pinMode(33, OUTPUT);
  digitalWrite(33, LOW);
  
  // Connect to Wi-Fi
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  // Print ESP Local IP Address
  Serial.println(WiFi.localIP());

  // Route for root / web page
  server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/html", index_html, processor);
  });

  // Send a GET request to <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
  server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    String inputMessage1;
    String inputMessage2;
    // GET input1 value on <ESP_IP>/update?output=<inputMessage1>&state=<inputMessage2>
    if (request->hasParam(PARAM_INPUT_1) && request->hasParam(PARAM_INPUT_2)) {
      inputMessage1 = request->getParam(PARAM_INPUT_1)->value();
      inputMessage2 = request->getParam(PARAM_INPUT_2)->value();
      digitalWrite(inputMessage1.toInt(), inputMessage2.toInt());
    }
    else {
      inputMessage1 = "No message sent";
      inputMessage2 = "No message sent";
    }
    Serial.print("GPIO: ");
    Serial.print(inputMessage1);
    Serial.print(" - Set to: ");
    Serial.println(inputMessage2);
    request->send(200, "text/plain", "OK");
  });

  // Start server
  server.begin();
}

void loop() {

}
Thats the Code published by Sara Santos. At the end of the day one of the ceckboxes would be enough and the controlling of the gpio stuff does not have to happen but can.
So the optimal goal would be to adjust the written code so that it auto updates.

Yeah so that does update the status of the checkbox when the variable state has changed. Still you will have to make a request from your browser to see the 'updated' page.
if you add

<META http-equiv="refresh" content="10;URL=/">

to the webpage, you can automate that to happen every 10 seconds

I don't know if that is what I am looking for. At least it is not the entire solution as I do not know how to set the state of the checkbox in the first place.

I think that this part of the script

buttons += "<h4>Output - GPIO 2</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"2\" " + outputState(2) + "><span class=\"slider\"></span></label>";
    buttons += "<h4>Output - GPIO 4</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"4\" " + outputState(4) + "><span class=\"slider\"></span></label>";
    buttons += "<h4>Output - GPIO 33</h4><label class=\"switch\"><input type=\"checkbox\" onchange=\"toggleCheckbox(this)\" id=\"33\" " + outputState(33) + "><span class=\"slider\"></span></label>";

in combination with this pat of the sketch

String outputState(int output){
  if(digitalRead(output)){
    return "checked";
  }
  else {
    return "";
  }
}

actually does that. checking for the state of GPIOs 2,4 & 33 (hmm this must be ESP32 code)

Personally i never use this method of including data in a webpage, because i find it rather 'unclear' what you actually do. I steer away from the whole 'rawliteral' thing.
Now i don't want to explain the method that you pulled of the internet and don't fully understand.
I don't even use ASyncWebserver, just the normal one, though differences are minimal.
If I want to host a page that has dynamic content, i create the page line by line adding to a String, and add, in this case, the word 'checked' in the appropriate location.

Ahh your right, thanks ! That's exactly the information I needed :smile: Huge Thank you for pointing that out for me :slight_smile:
Thanks for the additional information as well. If I ever do a project with a web server again I might look into it.