A first look at AJAX,
Asynchronous Javascript and XML (eXtensible Markup Language)
Last time we used a web page to send commands to the ESP32. One could easily add buttons or other web features that send differing values to be interpreted by the ESP32. For instance, if we were steering a robot 1 could be forward, 2, reverse, 3, left, 4, right and 0 stop.
In this section, we will turn things around and see how the ESP32 can send data to a web page. With a temperature/humidity sensor we could build a remote weather station. The ultrasound detector can give us a warning if the robot is too close to another object. In this example, we will create a touch sensor object and send data showing that the robot has been touched.
Let's say you have an expensive Magic card set stored in a metal cabinet at home. A cheap ESP32 connected to the cabinet can be used to warn you that someone has touched the cabinet.
setInterval(function() {
// Call a function repetatively with 0.2 Second interval
var xhttp = new XMLHttpRequest(); // A new XML request called xhttp
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) { // If ready and new
document.getElementById("demo").innerHTML = this.responseText;
console.log(this.responseText);
}
};
xhttp.open("GET", "/readTouch", true); // /readTouch is one end of the communication between HTML and ESP32
xhttp.send();
}, 200 ); //200mSeconds update rate
This section of code uses AJAX. wrapped in the setInterval(function(){ function. This causes the function to be called every interval, 500ms in this case.
The paragraph with the id set to "demo" is changed to the text coming in from the request.
We can also see the text in the web browser console by using console.log(......).
The open("GET" sends the text "/readTouch" in a request. The receiving end is going to wait for "readTouch" and respond. Our XMLHttpRequest object will capture that response in this.responseText. That is the essence of a web server. It waits for requests of particular types and responds accordingly.
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html);
});
When the server is first started it will get a "/" request and send the index_html rawliteral. This could be anything and it will show up on the web page but because index_html is properly formatted HTML it looks like a web page.
server.on("/readTouch", HTTP_GET, [](AsyncWebServerRequest *request){ // This is the other end of readTouch
request->send(200, "text/HTML", String(check).c_str()); // sending the touch value to HTML
});
When a call back to the web server contains "/readTouch" the ESP32 code will send text. In this case the check variable is converted to a String
check = myTouch.Update(); // Find the touch value
The myTouch object we created earlier uses it's Update method to return a value. The variable check is made equal to the returned value.
Here is the complete sketch.
/********
Adapted by M Druiven, https://sites.google.com/view/sparboticsesp32
May 10/2021
Adapted from Rui Santos
Project details at https://RandomNerdTutorials.com/esp32-web-server-slider-pwm/
and Sharifdeen Ashshak ESP8266 Temperature and Humidity AsynchronousWeb Server
*********/
// Import required libraries
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "**************************"; // Set to your own SSID
const char* password = "************************"; // Set to your own WiFi password
String str;
char charStr[2];
int check;
AsyncWebServer server(80); // Create AsyncWebServer object on port 80
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ESP Web Server</title>
</head>
<body>
<h1>My Great Esp32 Web Server</h1>
<p><a href="http://4992.ca">Sparbotics</a></p>
<p> <a href="https://sites.google.com/view/sparboticsesp32">Sparbotics ESP32</a></p>
<hr>
<h1><p>Touch Value<p>
<p id="demo">Touch content.</p></h1>
</form>
<script>
setInterval(function() {
// Call a function repetatively with 0.5 Second interval
var xhttp = new XMLHttpRequest(); // A new XML request called xhttp
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) { // If ready and new
document.getElementById("demo").innerHTML = this.responseText;
console.log(this.responseText);
}
};
xhttp.open("GET", "/readTouch", true); // /readTouch is one end of the communication between HTML and ESP32
xhttp.send();
}, 500 ); //500mSeconds update rate
</script>
</body>
</html>
)rawliteral";
class touch {
int touchPin;
public:
touch(int pin) {
touchPin = pin;
}
int Update() {
return touchRead(touchPin);
}
};
touch myTouch(15); // Make a touch object
void setup(){
Serial.begin(115200); // Serial port for debugging purposes
// 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);
});
server.on("/readTouch", HTTP_GET, [](AsyncWebServerRequest *request){ // This is the other end of readTouch
request->send(200, "text/HTML", String(check).c_str()); // sending the touch value to HTML
});
server.begin(); // Start server
}
void loop() {
check = myTouch.Update(); // Find the touch value
Serial.println(check); // You can also see your touch value on the serial monitor when the ESP32 is connected
delay(500); // every 1/2 second
}