In this project, we will create an ESP32 web server that displays real-time data from a connected light sensor.  ![[../images/Pasted image 20250126201657.png]] ```cpp #include const int ldrPin = 33; WebServer webServer(80); void showLightLevel() { int lightLevel = analogRead(ldrPin); // Convert the integer lightLevel to a string and construct the HTML content String htmlContent = "
Light Level: " + String(lightLevel) + "
"; // Send the constructed HTML content webServer.send(200, "text/html", htmlContent); } void setup() { Serial.begin(115200); pinMode(ldrPin,INPUT); connectToWiFi(); webServer.on("/", HTTP_GET, showLightLevel); webServer.begin(); // Start the server } void loop() { webServer.handleClient(); // Handle incoming client requests } ``` Most of the code is the same as the previous project. ```cpp webServer.on("/", HTTP_GET, showLightLevel); ``` We use the showLightLevel() function inside webServer.on. The showLightLevel function acts as a callback function. This means that when a client accesses the root page ("/") via a browser, the showLightLevel() function will be executed. At this point, showLightLevel() is not called immediately; it simply informs the webServer instance about what action to perform when a client accesses the "/" route. ```cpp void showLightLevel() { int lightLevel = analogRead(ldrPin); // Convert the integer lightLevel to a string and construct the HTML content String htmlContent = "
Light Level: " + String(lightLevel) + "
"; // Send the constructed HTML content webServer.send(200, "text/html", htmlContent); } ``` In the showLightLevel function, we read the light sensor data using analogRead from ESP32 GPIO 33. Instead of using a const char*, we use the String type, which makes it easier to combine the string and sensor value into htmlContent. Finally, we send the htmlContent to the client using webServer.send. Open a browser and visit the ESP32’s web page. You’ll see the light sensor value displayed. Press F5 or refresh the page to view the updated light sensor value. ![[../images/Pasted image 20250126193930.png]] Manually refreshing the page every time to update the light level is inconvenient. To improve this, we modify the code to include an auto-update feature. To automatically update the light sensor value on the webpage without requiring a manual refresh, we can use **JavaScript with AJAX**. This method allows the browser to request the updated value from the ESP32 server asynchronously, without reloading the entire page. ```cpp #include const int ldrPin = 33; WebServer webServer(80); void homePage() { String htmlContent = R"rawliteral(
Light Sensor
--
)rawliteral"; webServer.send(200, "text/html", String(htmlContent)); } void showLightLevel() { int lightLevel = analogRead(ldrPin); webServer.send(200, "text/plain", String(lightLevel)); } void setup() { Serial.begin(115200); pinMode(ldrPin, INPUT); connectToWiFi(); webServer.on("/", HTTP_GET, homePage); webServer.on("/light", HTTP_GET, showLightLevel); webServer.begin(); } void loop() { webServer.handleClient(); } ``` ```cpp webServer.on("/light", HTTP_GET, showLightLevel); ``` We have moved the raw light sensor reading to the /light route, which you can access at http://esp32-ip-address/light. Note that in the showLightLevel() function, the webServer.send method uses the text/plain content type to send the response. ```cpp webServer.on("/", HTTP_GET, homePage); ``` When a client accesses the home page, it is served by the homePage() function, which returns an HTML page containing JavaScript code. Notice that in the homePage() function, the webServer.send method uses the text/html content type to send the response. Let's have a look at the returned HTML code in details. ```cpp R"rawliteral(...)" ``` R"rawliteral(...)" is a **raw string literal** in C++. It allows you to define a string without having to escape characters like quotes, backslashes, or newline characters. This is particularly useful for embedding large blocks of text (such as HTML, JSON, or code) where escaping characters would be cumbersome. ```java ``` This block of JavaScript code is responsible for fetching the light sensor data from the server and updating the displayed value on the webpage every second. Here’s a detailed breakdown: ```cpp fetch("/light").then(response => response.text()).then(data => ``` The fetch function makes an **HTTP request** to the server. In this case, it requests the /light route from the ESP32 server (which is where the light sensor data is served). Once the fetch request is complete, the .then() method is used to handle the response.The first .then() takes the response object and converts it into text using the .text() method. This method returns another Promise containing the raw sensor data as a string (the light level). After converting the response to text, the second .then() method is triggered, and the result (which is the light sensor data) is passed as the data argument. ```cpp document.getElementById('lightLevel').innerText = data; ``` Inside this block, the document.getElementById('lightLevel').innerText = data; line updates the webpage by setting the inner text of the span element with the id="lightLevel" to the fetched light sensor value. ```cpp setInterval(updateLightLevel, 1000); ``` This line calls the updateLightLevel function every **1000 milliseconds** (or 1 second). setInterval is a built-in JavaScript function that runs the provided function at a specified interval (in milliseconds). In this case, updateLightLevel will run every second to update the light level on the page. ![[../images/Pasted image 20250126201530.png]] ![[../images/Pasted image 20250126201542.png]]