AJAX with EthernetWebServer

Hello,

i am trying to update the webpage i made with the sensor data.
I have tried this approach:

<meta http-equiv="refresh" content="2">

Refreshing the weboage every 2 seconds but i want to use the other way for this task.
I searched on the net but i could only find examples with the WiFi. I am working with the Ethernet (W5500).
The webpage is saved on the flash of the ESP32S3, so it is not in the Arduino sketch.

Any help will be appreciated

Why do you think that HTML works differently on LAN vs. WLAN?

I have already tried to modify the WiFi examples for my porpuses.
The HTML:

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="20" name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<style>

h2{margin-top: 60px;
   margin-left: 60px;}

body {
  font-family: Arial, Helvetica, sans-serif;
}
* {
  box-sizing: border-box;
}

input[type=text], select, textarea {
  width: 70%;
  padding: 12px;
  margin-top: 10px;
  border: 1px solid #ccc;
  border-radius: 4px;
  resize: vertical;
}

label {
  padding: 24px 12px 12px 48px;
  display: inline-block;
}

input[type=submit] {
  background-color: #04AA6D;
  color: white;
  padding: 12px 20px;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  float: right;
  margin-top: 15px; 
  margin-right: 500px
}

input[type=submit]:hover {
  background-color: #45a049; 
}

.container {
  border-radius: 5px;
  background-color: white; /* #f2f2f2 */
  padding: 20px;
  margin-top: 75px; 
}

.col-25 {
  float: left;
  width: 25%;
  margin-top: 6px;
}

.col-75 {
  float: left;
  width: 75%;
  margin-top:6px;
}

/* Clear floats after the columns */
.row:after {
  content: "";
  display: table;
  clear: both;
  margin-top: 16px;
}

.navbar {
  overflow: hidden;
  background-color: white;
}

.navbar a {
  float: left;
  font-size: 16px;
  color: black;
  text-align: center;
  padding: 14px 16px;
  text-decoration: none;
}

.sidenav {
  height: 70%;
  width: 200px;
  position: fixed;
  z-index: 1;
  top: 120px;
  left: 100px;
  background-color: white;
  overflow-x: hidden;
  padding-top: 20px;
}

.sidenav a {
  padding: 6px 6px 36px 32px;
  text-decoration: none;
  font-size: 16px;
  color: black;
  display: block;
}

.dropdown {
  float: left;
  padding-left: 120px;
  overflow: hidden;
}

.dropdown .dropbtn {
  font-size: 16px;  
  border: none;
  outline: none;
  color: black;
  padding: 14px 16px;
  background-color: inherit;
  font-family: inherit;
  margin: 0;
}

.navbar a:hover, .dropdown:hover .dropbtn {
  color: blue;
}

.dropdown-content {
  display: none;
  position: absolute;
  background-color: white;
  min-width: 160px;
  box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
  z-index: 1;
}

.dropdown-content a {
  float: none;
  color: black;
  padding: 12px 16px;
  text-decoration: none;
  display: block;
  text-align: left;
}

.dropdown-content a:hover {
  background-color: white;
}

.dropdown:hover .dropdown-content {
  display: block;
}

.sidenav a:hover {
  color: blue;
}

.main {
  margin-left: 200px; /* Same as the width of the sidenav */
}

@media screen and (max-height: 450px) {
  .sidenav {padding-top: 15px;}
  .sidenav a {font-size: 18px;}
}

/* Responsive layout - when the screen is less than 600px wide, make the two columns stack on top of each other instead of next to each other */
@media screen and (max-width: 600px) {
  .col-25, .col-75, input[type=submit] {
    width: 100%;
    margin-top: 0;
  }
}

table, th, td {
  border:1px solid black;
  margin-left: 55px;
  margin-top: 35px;
}

</style>
</head>

<body style="background-color:white;">
<div class="w3-main" style="display: flex; justify-content: center; margin-top: 20px;">

    <span class="w3-button w3-hide-large w3-xxlarge w3-hover-text-grey" onclick="w3_open()"></span>
    <div class="w3-container">

<!---<nav class="navbar navbar-expand-xl navbar-light bg-light">--->


    <!---<div class="w3-section w3-bottombar w3-padding-16" style="text-align: right;" >
      <li class="nav-item dropdown">--->

<img src='https://wiki.amberg.deprag.de/allgemein/images/thumb/d/de/Logo-DEPRAG-machinesunlimited.svg/120px-Logo-DEPRAG-machinesunlimited.svg.png' style='margin-right: 20px; float: left;'  id='deprag-logo' width= '100' height= '30'>

<div class="navbar">
  <a href="index">Dashboard</a>
  <a href="software">Software</a>
  <a href="settings">Einstellungen</a>
  <a href="#news">Systeminfo</a>
  <a href="test">Service</a>
  <div class="dropdown">
    <button class="dropbtn"><i class="fa fa-fw fa-user"></i>Admin 
      <i class="fa fa-caret-down"></i>
    </button>
    <div class="dropdown-content">
      <a href="#">Mein Profil</a>
      <a href="#">Abmelden</a>
    </div>
  </div> 
</div>
<div class="sidenav">
  <a href="sensordata">Sensordaten</a>
  <a href="controlLED">Steuere LED</a>
</div>

<h2>Service<span style='font-size:30px;'>&#8594;</span>Sensordaten</h2>

<table style="width:80%">
  <tr>
    <th>IS</th>
    <th>RS</th>
    <th>GS</th>
    <th>BS</th>
  </tr>
  <tr>
    <td><span id="is1"></span></td>
    <td><span id="r1"></span></td>
    <td><span id="g1"></span></td>
    <td><span id="b1"></span></td>
  </tr>
  <tr>
    <td><span id="is2"></span></td>
    <td><span id="r2"></span></td>
    <td><span id="g2"></span></td>
    <td><span id="b2"></span></td>
  </tr>
  <tr>
    <td><span id="is3"></span></td>
    <td><span id="r3"></span></td>
    <td><span id="g3"></span></td>
    <td><span id="b3"></span></td>
  </tr>
  <tr>
    <td><span id="is4"></span></td>
    <td><span id="r4"></span></td>
    <td><span id="g4"></span></td>
    <td><span id="b4"></span></td>
  </tr>
</table>


<script>

setInterval(function() {
  // Call a function repetatively with 2 Second interval
  getData();
}, 2000); //2000mSeconds update rate

function loadDoc() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      document.getElementById("is1").innerHTML =
      this.responseText;
    }
  };
  xhttp.open("POST", "sensordata", true);
  xhttp.send();
}
</script>


</body>
</html>

And this is how the handlefunction get triggered:

ethernetServer.on("/sensordata", HTTP_GET, handleRGBRead);

And the handlefunction:

void handleRGBRead(){

  // Send the response to the client
  String response;

  File file = LittleFS.open("/sensordata.html", "r");
  if (file) {
    response += file.readString();
    file.close();

    tit1 = getToolInfo(0);
    tit2 = getToolInfo(1);
    tit3 = getToolInfo(2);
    tit4 = getToolInfo(3);

    // Inject sensor data into the HTML table
    response.replace("<span id=\"is1\"></span>", String(tit1.state.bits.occupied));
    response.replace("<span id=\"r1\"></span>", String(tit1.colorcode_red));
    response.replace("<span id=\"g1\"></span>", String(tit1.colorcode_green));
    response.replace("<span id=\"b1\"></span>", String(tit1.colorcode_blue));
    
    response.replace("<span id=\"is2\"></span>", String(tit2.state.bits.occupied));
    response.replace("<span id=\"r2\"></span>", String(tit2.colorcode_red));
    response.replace("<span id=\"g2\"></span>", String(tit2.colorcode_green));
    response.replace("<span id=\"b2\"></span>", String(tit2.colorcode_blue));
    
    response.replace("<span id=\"is3\"></span>", String(tit3.state.bits.occupied));
    response.replace("<span id=\"r3\"></span>", String(tit3.colorcode_red));
    response.replace("<span id=\"g3\"></span>", String(tit3.colorcode_green));
    response.replace("<span id=\"b3\"></span>", String(tit3.colorcode_blue));
    
    response.replace("<span id=\"is4\"></span>", String(tit4.state.bits.occupied));
    response.replace("<span id=\"r4\"></span>", String(tit4.colorcode_red));
    response.replace("<span id=\"g4\"></span>", String(tit4.colorcode_green));
    response.replace("<span id=\"b4\"></span>", String(tit4.colorcode_blue));

    // Repeat this for other sensor values

    Serial.println("Inside handleRGBRead()!!!");

    // Send the modified HTML as the HTTP response
    ethernetServer.send(200, "text/html", response);
  }  else {
    ethernetServer.send(404, "text/plain", "File not found");
  }


  // response += (htmlclose);    //Problem
  //ethernetServer.send(200, "text/html", response);handlecontrolLED
}

It hasn't worked.

Shouldn't your timer be calling loadDoc() instead of getData()?

Why ethernetserver?

@cedarlakeinstruments , yes you have right but that does not fix the problem.
Thanks anyway.
@zwieblum, why not?

Nowadays I would use the FetchAPI.
Here I have an example:
ESP8266 ESP32 webserver maxi (rothschopf.net)

Example 70 shows how the HTML, JavaScript and JSON are working together. You should be able to put the HTML and JavaScript into the Filesystem also.

Have you opened the browser debug window to see what errors it's reporting?

@noiasca, thank you.
i will take a look at it.
@cedarlakeinstruments, yes:
xhttp.send(); Error -> Failed to load resources, Status is 404 Not found

Well, probably ethernetserver binds to ethernat aka kable and not to any interface. As you did not provide the code it's hard to say, but I'd go with AsyncWebServer instead.

Which part of the code do you want to look at?
My sketch is not small and i cannot switch to WiFi because i have to work with the Ethernet.

This should tell you something...

And how is the ESP connected to ethernet?

You could provide a striped down version. Just the webserver your page, the JavaScript and a simulated data output. something we can test with our hardware.
The code should compile.

Furthermore a schematic how you have connected the wiznet to your ESP.

Thank you all for your replies.
I have made it and it wokrs now.
Here is my solution:
The javascript inside of the HTML file:

<script>


function updateSensorData() {
  var xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      var sensorData = JSON.parse(this.responseText);
      
      // Update sensor data for sensor 1
      document.getElementById("is1").innerHTML = sensorData.is1.is;
      document.getElementById("r1").innerHTML = sensorData.is1.r;
      document.getElementById("g1").innerHTML = sensorData.is1.g;
      document.getElementById("b1").innerHTML = sensorData.is1.b;

      // Update sensor data for sensor 2
      document.getElementById("is2").innerHTML = sensorData.is2.is;
      document.getElementById("r2").innerHTML = sensorData.is2.r;
      document.getElementById("g2").innerHTML = sensorData.is2.g;
      document.getElementById("b2").innerHTML = sensorData.is2.b;

      // Update sensor data for sensor 3
      document.getElementById("is3").innerHTML = sensorData.is3.is;
      document.getElementById("r3").innerHTML = sensorData.is3.r;
      document.getElementById("g3").innerHTML = sensorData.is3.g;
      document.getElementById("b3").innerHTML = sensorData.is3.b;

      // Update sensor data for sensor 4
      document.getElementById("is4").innerHTML = sensorData.is4.is;
      document.getElementById("r4").innerHTML = sensorData.is4.r;
      document.getElementById("g4").innerHTML = sensorData.is4.g;
      document.getElementById("b4").innerHTML = sensorData.is4.b;
      // Update other sensor data as needed
    }
  };
  xhttp.open("GET", "/readsensor", true);
  xhttp.send();
}

// Call the function initially and then at regular interval
updateSensorData();
setInterval(updateSensorData, 2000);

</script>

And the handle function inside the Arduino sketch:

void handleRGBRead(){
  
  // Read sensor data
  tit1 = getToolInfo(0);
  tit2 = getToolInfo(1);
  tit3 = getToolInfo(2);
  tit4 = getToolInfo(3);

  // Prepare JSON response
  String jsonResponse = "{";
  
  jsonResponse += "\"is1\": {" 
                     "\"is\":" + String(tit1.state.bits.occupied) + ","
                     "\"r\":" + String(tit1.colorcode_red) + ","
                     "\"g\":" + String(tit1.colorcode_green) + ","
                     "\"b\":" + String(tit1.colorcode_blue) + "},";
  
  jsonResponse += "\"is2\": {" 
                     "\"is\":" + String(tit2.state.bits.occupied) + ","
                     "\"r\":" + String(tit2.colorcode_red) + ","
                     "\"g\":" + String(tit2.colorcode_green) + ","
                     "\"b\":" + String(tit2.colorcode_blue) + "},";
  
  jsonResponse += "\"is3\": {" 
                     "\"is\":" + String(tit3.state.bits.occupied) + ","
                     "\"r\":" + String(tit3.colorcode_red) + ","
                     "\"g\":" + String(tit3.colorcode_green) + ","
                     "\"b\":" + String(tit3.colorcode_blue) + "},";
  
  jsonResponse += "\"is4\": {" 
                     "\"is\":" + String(tit4.state.bits.occupied) + ","
                     "\"r\":" + String(tit4.colorcode_red) + ","
                     "\"g\":" + String(tit4.colorcode_green) + ","
                     "\"b\":" + String(tit4.colorcode_blue) + "}";
  
  jsonResponse += "}";

  // Add data for other sensors as needed

  // Send JSON response
  ethernetServer.send(200, "application/json", jsonResponse);

}

And how the handle function gets triggered:

einethernetServer.on("/readsensor", HTTP_GET, handleRGBRead);

The only issue is that the table is getting bigger and smaller depending on how many digits are the sensordata.
The table is in the HTML

<table style="width:80%">
  <tr>
    <th>IS</th>
    <th>RS</th>
    <th>GS</th>
    <th>BS</th>
  </tr>
  <tr>
    <td><span id="is1"></span></td>
    <td><span id="r1"></span></td>
    <td><span id="g1"></span></td>
    <td><span id="b1"></span></td>
  </tr>
  <tr>
    <td><span id="is2"></span></td>
    <td><span id="r2"></span></td>
    <td><span id="g2"></span></td>
    <td><span id="b2"></span></td>
  </tr>
  <tr>
    <td><span id="is3"></span></td>
    <td><span id="r3"></span></td>
    <td><span id="g3"></span></td>
    <td><span id="b3"></span></td>
  </tr>
  <tr>
    <td><span id="is4"></span></td>
    <td><span id="r4"></span></td>
    <td><span id="g4"></span></td>
    <td><span id="b4"></span></td>
  </tr>
</table>

Thank you all for your help

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.