Home / Tutorials / ESP8266 Tutorial / NodeMCU Ajax: Dynamic Sensor Data on Web Page
pcbway
nodemcu ajax dynamic sensor data
ESP8266 Tutorial

NodeMCU Ajax: Dynamic Sensor Data on Web Page

Last time we managed to display sensor data to a NodeMCU web server. The problem with that code is that we need to refresh the page manually in order to update the sensor value. A better method is to use Ajax (asynchronous javascript and XML) so that we can request data from the ESP8266 server in the background with no page reloads.

Ajax is a combination of an XMLHttpRequest object and JavaScript. The XMLHttpRequest object performs the request on the server while the javascript DOM object updates the element on the web page. Besides updating page elements without reload, ajax also makes it possible to a) request data from a server - after the page has loaded; b) receive data from a server - after the page has loaded and c) send data to a server - in the background. W3Schools has a great tutorial on Ajax.

We shall now edit the sketch from last time to include the Ajax script. We will be using the same schematic:

nodemcu ajax sensor

Here is the Ajax script that we’ll be using:

function loadData(url, callback){
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function(){
 if(this.readyState == 4 && this.status == 200){
 callback.apply(xhttp);
 }
};
xhttp.open("GET", url, true);
xhttp.send();
}
function updateData(){
 document.getElementById("data").innerHTML = this.responseText;
}

The main Ajax script is the loadData() function. Inside this function, an XMLHttpRequest() object is created. The server waits for a readystate of 4 (done) and a http status of 200 (OK) before the web page element is updated via callback to updateData(). The request is then initiated via the open() and send() functions. Callback was necessary here to make the requests asynchronous, i.e., make the page still responsive even if there is a pending request.

In order for this function to be repeatedly called, we will be using the javascript setInterval() function. Here the loadData() function is called every second.

There are a couple of ways to get data from the sensor. What I did was save the data to a text file. This text file will then be read by the XMLHttpRequest object and then display its contents to the page element.

Full Code

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

// Replace with your network credentials
const char* ssid = "<Your-WiFi-SSID>";
const char* password = "<Your-WiFi-Password>";
ESP8266WebServer server(80);   //instantiate server at port 80 (http port)

String page = "";
String text = "";
double data;

void setup(void){
 pinMode(A0, INPUT);
 delay(1000);
 Serial.begin(115200);
 WiFi.begin(ssid, password); //begin WiFi connection
 Serial.println("");

 // Wait for connection
 while (WiFi.status() != WL_CONNECTED) {
 delay(500);
 Serial.print(".");
}

 Serial.println("");
 Serial.print("Connected to ");
 Serial.println(ssid);
 Serial.print("IP address: ");
 Serial.println(WiFi.localIP());
 server.on("/data.txt", [](){
   text = (String)data;
   server.send(200, "text/html", text);
 });
 server.on("/", [](){
   page = "<h1>Sensor to Node MCU Web Server</h1><h1>Data:</h1> <h1 id=\"data\">""</h1>\r\n";
   page += "<script>\r\n";
   page += "var x = setInterval(function() {loadData(\"data.txt\",updateData)}, 1000);\r\n";
   page += "function loadData(url, callback){\r\n";
   page += "var xhttp = new XMLHttpRequest();\r\n";
   page += "xhttp.onreadystatechange = function(){\r\n";
   page += " if(this.readyState == 4 && this.status == 200){\r\n";
   page += " callback.apply(xhttp);\r\n";
   page += " }\r\n";
   page += "};\r\n";
   page += "xhttp.open(\"GET\", url, true);\r\n";
   page += "xhttp.send();\r\n";
   page += "}\r\n";
   page += "function updateData(){\r\n";
   page += " document.getElementById(\"data\").innerHTML = this.responseText;\r\n";
   page += "}\r\n";
   page += "</script>\r\n";
   server.send(200, "text/html", page);
});

 server.begin();
 Serial.println("Web server started!");
}

void loop(void){
 data = analogRead(A0);
 delay(1000);
 server.handleClient();
}

Video:


 

You can also add CSS to make the web page look nicer. If you want to record the sensor readings, you can send NodeMCU data to Google sheets or save it to a database.

 

0 0 votes
Article Rating
Subscribe
Notify of
guest
30 Comments
Oldest
Newest Most Voted
SiW
SiW
8 years ago

Great tutorial!

My NodeMCU crashes though after 30 seconds with this error:

Exception (29):
epc1=0x4020dc0c epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000

ctx: sys
sp: 3ffffcd0 end: 3fffffb0 offset: 01a0

ets Jan 8 2013,rst cause:2, boot mode:(1,6)

ets Jan 8 2013,rst cause:4, boot mode:(1,6)

wdt reset

Any ideas how to fix this?

Sanz
Sanz
8 years ago

Hi,

In this tuttorial you put sensor data into text file, where u put the text file? SD card (perhaps)?

Patrik
Patrik
8 years ago
Reply to  Roland Pelayo

But it's not a textfile, it's just a global variable?

C Satish kumar
C Satish kumar
8 years ago

hlo,
i have run the code which u have mentioned in the tutorial above,but i m getting the error "stray '\302' in program" so can u tell how to resolve it.do i need to do changes in it???

Ruby
Ruby
8 years ago

Hi,

Fantastic tuttorial but i found some problem when i try to read 3 sensor using ajax method for my final project.Can you help me with my problem read 3 sensor using ajax method?

Thank You

Zamira
Zamira
8 years ago
Reply to  Roland Pelayo

Hi,

I try change your example according to your explanation, but I got this error:

invalid operands of types 'const char [14]' and 'const char [14]' to binary 'operator+'

For this:

data = "Air Quality: " + (String)T+ "Temperature: " + (String)T + "Ax: " + (String)Ax + "Ay: " + (String)Ay + "Az: " + (String)Az + "Gx: " + (String)Gx +"Gy: " + (String)Gy +"Gz: " + (String)Gz +;

I use MQ2 gas sensor and MPU6050 which can detect temperature, acceleration and rotational movement (gyro meter).
Can you help me to solve this problem?

Thank you.

Adrian
Adrian
8 years ago
Reply to  Roland Pelayo

Looks like the + right at the end...

Jan
Jan
7 years ago
Reply to  Roland Pelayo

Hi,

i changed the code for 3 sensors and its working. The issue i have is: The Sensor values are displayed in one row. I have no idea how to get a carriage return in HTML to have each sensor value in a single row. Can you help?

ROHIT
ROHIT
8 years ago

hey nice tutorial it worked. But can you tell me how can i decrease the time of update of data on server.

Denis
Denis
8 years ago

Hi,
very great serie of tutorials ; every sketchs are running without porblem ! many thanks for all of theses, they are very helpfull for my project
My next problem will be to integer a picture on the web page ..

Raul
Raul
8 years ago

Hi! Thanks for the tutorial.
I'm trying to do similar, but for show "Voltage" and "Current".
The problem is that Voltage and Current values I get from SPI communication with Arduino inside of
void loop(void){} function.

How can I get this values and show?

Asad
Asad
8 years ago

How it can do for 2 analog sensors

Anoop
Anoop
7 years ago

How can we do for two analog sensors , provided it has only one analog pin ..? Please help .

Jhaxe
Jhaxe
7 years ago

how to do if 2 or more analog sensor? thanks..

Aditi Agrawal
Aditi Agrawal
7 years ago

Hii I have been trying this code but I got this error.

Arduino: 1.8.8 (Windows 10), Board: "NodeMCU 1.0 (ESP-12E Module), 80 MHz, Flash, Disabled, 4M (no SPIFFS), v2 Lower Memory, Disabled, None, Only Sketch, 115200"

nodemcu_server:8:1: error: stray '\302' in program

ESP8266WebServer server(80);   //instantiate server at port 80 (http port)

^

nodemcu_server:8:1: error: stray '\240' in program

nodemcu_server:8:1: error: stray '\302' in program

nodemcu_server:8:1: error: stray '\240' in program

nodemcu_server:15:1: error: stray '\302' in program

 pinMode(A0, INPUT);

^

nodemcu_server:15:1: error: stray '\240' in program

nodemcu_server:16:1: error: stray '\302' in program

 delay(1000);

^

nodemcu_server:16:1: error: stray '\240' in program

nodemcu_server:17:1: error: stray '\302' in program

 Serial.begin(115200);

^

nodemcu_server:17:1: error: stray '\240' in program

nodemcu_server:18:1: error: stray '\302' in program

 WiFi.begin(ssid, password); //begin WiFi connection

^

nodemcu_server:18:1: error: stray '\240' in program

nodemcu_server:19:1: error: stray '\302' in program

 Serial.println("");

^

nodemcu_server:19:1: error: stray '\240' in program

nodemcu_server:21:1: error: stray '\302' in program

 // Wait for connection

^

nodemcu_server:21:1: error: stray '\240' in program

nodemcu_server:22:1: error: stray '\302' in program

 while (WiFi.status() != WL_CONNECTED) {

^

nodemcu_server:22:1: error: stray '\240' in program

nodemcu_server:23:1: error: stray '\302' in program

 delay(500);

^

nodemcu_server:23:1: error: stray '\240' in program

nodemcu_server:24:1: error: stray '\302' in program

 Serial.print(".");

^

nodemcu_server:24:1: error: stray '\240' in program

nodemcu_server:27:1: error: stray '\302' in program

 Serial.println("");

^

nodemcu_server:27:1: error: stray '\240' in program

nodemcu_server:28:1: error: stray '\302' in program

 Serial.print("Connected to ");

^

nodemcu_server:28:1: error: stray '\240' in program

nodemcu_server:29:1: error: stray '\302' in program

 Serial.println(ssid);

^

nodemcu_server:29:1: error: stray '\240' in program

nodemcu_server:30:1: error: stray '\302' in program

 Serial.print("IP address: ");

^

nodemcu_server:30:1: error: stray '\240' in program

nodemcu_server:31:1: error: stray '\302' in program

 Serial.println(WiFi.localIP());

^

nodemcu_server:31:1: error: stray '\240' in program

nodemcu_server:32:1: error: stray '\302' in program

 server.on("/data.txt", [](){

^

nodemcu_server:32:1: error: stray '\240' in program

nodemcu_server:33:1: error: stray '\302' in program

  text = (String)data;

^

nodemcu_server:33:1: error: stray '\240' in program

nodemcu_server:34:1: error: stray '\302' in program

   server.send(200, "text/html", text);

^

nodemcu_server:34:1: error: stray '\240' in program

nodemcu_server:34:1: error: stray '\302' in program

nodemcu_server:34:1: error: stray '\240' in program

nodemcu_server:34:1: error: stray '\302' in program

nodemcu_server:34:1: error: stray '\240' in program

nodemcu_server:35:1: error: stray '\302' in program

 });

^

nodemcu_server:35:1: error: stray '\240' in program

nodemcu_server:36:1: error: stray '\302' in program

 server.on("/", [](){

^

nodemcu_server:36:1: error: stray '\240' in program

nodemcu_server:54:2: error: stray '\302' in program

  server.send(200, "text/html", page);

^

nodemcu_server:54:2: error: stray '\240' in program

nodemcu_server:54:2: error: stray '\302' in program

nodemcu_server:54:2: error: stray '\240' in program

nodemcu_server:57:1: error: stray '\302' in program

 server.begin();

^

nodemcu_server:57:1: error: stray '\240' in program

nodemcu_server:58:1: error: stray '\302' in program

 Serial.println("Web server started!");

^

nodemcu_server:58:1: error: stray '\240' in program

nodemcu_server:62:1: error: stray '\302' in program

 data = analogRead(A0);

^

nodemcu_server:62:1: error: stray '\240' in program

nodemcu_server:63:1: error: stray '\302' in program

 delay(1000);

^

nodemcu_server:63:1: error: stray '\240' in program

nodemcu_server:64:1: error: stray '\302' in program

 server.handleClient();

^

nodemcu_server:64:1: error: stray '\240' in program

exit status 1
stray '\302' in program

I tried toggling line code but I still got the same error.

Can You please help me fix this.

Thank you.

Gibran Berriel
Gibran Berriel
7 years ago

Es posible graficar los resultados directamente desde el nodemcu?
Is it possible to graph the results directly from the nodemcu?

Joe Bauer
Joe Bauer
6 years ago

Thanks for this project. How is it possible to add an input field? I would like to be able to adjust the threshold value for my 'Smoke Alarm' project for my wife. Is there project that shows how to add an interger field?

Pritish Chavan
Pritish Chavan
6 years ago

server.on("/", [](){
page = "Sensor to Node MCU Web ServerData: ""\r\n";
page += "\r\n";
page += "var x = setInterval(function() {loadData(\"data.txt\",updateData)}, 1000);\r\n";
page += "function loadData(url, callback){\r\n";
page += "var xhttp = new XMLHttpRequest();\r\n";
page += "xhttp.onreadystatechange = function(){\r\n";
page += " if(this.readyState == 4 && this.status == 200){\r\n";
page += " callback.apply(xhttp);\r\n";
page += " }\r\n";
page += "};\r\n";
page += "xhttp.open(\"GET\", url, true);\r\n";
page += "xhttp.send();\r\n";
page += "}\r\n";
page += "function updateData(){\r\n";
page += " document.getElementById(\"data\").innerHTML = this.responseText;\r\n";
page += "}\r\n";
page += "\r\n";
server.send(200, "text/html", page);
});

In this function i want to put id value in array format is there possible or not.
if possible then how to write a statment
page = "Sensor to Node MCU Web ServerData: ""\r\n";

Contents

Index