Dear Rui,
I created an asynchronous web server with ESP32 based on the course book. I use it for measurement, it works perfectly, thank you very much.
There is only one problem: I read the measurement interval time from a setup file on an SD card into a variable called ‘mervarido’ and it is given in seconds. I then use it in several places in the program (mervarido * 1000) in the form of microseconds.
Unfortunately, I can’t use it in this format in the Java script of the Website, it seems that if I type it in place of the original 10000, it can’t be interpreted by Java, it doesn’t update every 10 seconds.
Unfortunately, I don’t know much Java, so I’m asking for your help: how can I pass this variable to the ‘setInterval’ function for all my measurement data (temperature, humidity, etc.) instead of 10000? I am thinking of the following function:
setInterval (function () {
var xhttp = new XMLHttpRequest ();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
document.getElementById (“temperature”). innerHTML = this.responseText;
}
};
xhttp.open (“GET”, “/ temperature”, true);
xhttp.send ();
}, 10000);
Thank you very much for your help in advance as well.
Sincerely, Peter
Hi.
Do you have all your HTML code including CSS and Javascript into the index_html variable, right?
I think, you can use a placeholder so that value is replaced with the value of the variable. For example:
setInterval (function () { var xhttp = new XMLHttpRequest (); xhttp.onreadystatechange = function () { if (this.readyState == 4 && this.status == 200) { document.getElementById (“temperature”). innerHTML = this.responseText; } }; xhttp.open (“GET”, “/ temperature”, true); xhttp.send (); }, %INTERVAL%);
Then, you need the processor() function to replace the INTERVAL placeholder with the value of the variable:
String processor(const String& var){ //Serial.println(var); if(var == "INTERVAL"){ String interval = String(mervarido*1000); return interval ; } }
However, I’m not sure if this is the best approach.
A better approach would be to use websockets or server-sent events. We don’t have any tutorials about these subjects at the moment. We have some projects that use server-sent events that you can have a look to see if you can implement in your code. Server-sent events allow the server to send updated to the client whenever you want. In your case, it would be every mervarido seconds.
These three projects use server-sent events:
- https://randomnerdtutorials.com/esp32-esp-now-wi-fi-web-server/
- https://randomnerdtutorials.com/esp32-iot-shield-pcb-dashboard/
- https://raw.githubusercontent.com/RuiSantosdotme/Random-Nerd-Tutorials/master/Projects/ESP32/ESP32_BME680_Web_Server.ino –> this is the simplest code that use server-sent events – it will be easier if you take a look at this first.
See if any of the alternatives I’ve mentioned work for you.
Tell me if you need further help.
Regards,
Sara
Dear Sara,
Thank you so much for your quick help, these are smart tips.
I will try them soon.
Thanks to Peter
Dear Sara,
Your solution worked perfectly, thank you very much!
Regardless, I will also study the projects you recommend, I will definitely learn a lot from them.
Regards: Peter
Dear Sara,
I would have another question: is there a sample project in which ESP32 communicates to/from LabView via WiFi? It can be a data logger, or a control, in one or both directions, all interested.
many thanks: Peter
Hi Peter.
I’m glad it worked.
About LabView, we don’t have any tutorials about that :/
Regards,
Sara
I worked with LabView many years ago when it first came out. I created a dashboard for a power company. I have not kept up with it.
In all likelihood they now have an API available (Do they?) so it should be fairly easy to call and transmit/receive data. Do you have a link to documentation?
A quick Bing search showed these:
Dear Steve,
Thanks for the information and links.
3 years ago I made an instrument program for a self-designed handheld instrument (PIC18F) in LabView. It connected to the PC via a plain serial port / USB converter, so LabView treated the input as a serial port. Now I want to do something similar in such a way that both the instrument and the PC are connected to the local WiFi network. The handheld instrument has an ESP32 and works as an Asyncron Web Server, the PC connects via its own WiFi unit and runs LabView on it. To do this, I am looking for some sample document, especially for ESP32, on how to send as a Web server a single plain string in which the measured data is listed. So ESP32 doesn’t have to send any Web pages, just a simple, approx. A string of 100 characters in length. This string is taken via a WiFi interface by LabView and processes the measurement data in the string. Well, I’m stuck here now …
Regards: Peter
What you would do is not send HTML but send a string (I would recommend a JSON string) instead. Look at examples where ESP32 is set up as a web server. In those examples wherever a web page is created and sent you would instead send the (JSON) string. Give it a try and if you have any issues post back.
I have been thinking about this a little more and you may want to rethink your application.
I’m guessing here but I think your original application was as a data logger that you would then connect to the PC and it would grab all the readings over the serial port. Now you want to send each reading as it is taken. How am I doing?
The problem with running an ESP32 as a web server in a handheld unit is it will be always on and you will be eating up batteries. You want to do this the other way around. The ESP32 stays in sleep until an interrupt is received (eg. you push a button). Then it takes a reading and sends to a server over WiFi. This will maximize battery life.
The server can be any computer. You can even use the one Labview is running on (If it’s a PC I would use WAMP). Otherwise a SBC (Single Board Computer) like a Raspberry PI (I like Odroid) could be used. This gives an Apache Web Server, MySQL and PHP. If you go SBC the OS I use is DietPi which is very easy to set up.
RNT has various tutorials like https://randomnerdtutorials.com/esp32-http-get-post-arduino/#http-get-2 and https://randomnerdtutorials.com/cloud-weather-station-esp32-esp8266/ that show you how to POST data to a web server and populate a DB. All Labview would have to do is read the data out of the DB.
For a tutorial on how to use interrupts check out the Multi-tasking the Arduino series of articles.
Finally you could just use MQTT:
ESP32 MQTT – Publish DHT11/DHT22 Temperature and Humidity Readings (Arduino IDE)
Steve, you gave me some really good ideas, thank you very much for your efforts.
I will try them all the way through, try the JSON string, the POST function, and so on. I can learn a lot from everything and gain experience.
I also have the RNT course book, it is a very good and useful document, I use it regularly and think further about its examples.
Thanks for the help, if I get stuck, I’ll sign up.
Peter
Great!
Thanks Steve, for your detailed answers.
Peter, if you need further help, just ask.
Regards,
Sara
Dear Sara,
I ask for your help again.
I would like to use the great example “ESP32 / ESP8266 Plot Sensor Readings in Real Time Charts – Web Server” in my own project.
I did everything as described, but unfortunately I made a mistake somewhere because the project doesn’t work. There are small differences in my project:
– I use SHT31 sensor to measure temperature and humidity,
– I do not measure pressure, but ozone gas concentration
– the measurement interval is 5 seconds
These sensors work perfectly in the other part of the project and provide the data properly here as well.
Error description:
1. when calling the IP address of ESP32 (this is 192.168.1.6 for me) only the text part of index.html is displayed (also shown in the photo) the diagrams are not. Moreover, you don’t even get to the GET / temperature call, it stops for some reason.
2. If I enter 192.168.1.6/temperature in the browser, the measured temperature value will be displayed on the screen (see photo) and will behave the same when entering a humidity and ozone concentration call.
3. Of course, the 5 second repeat does not happen either
I tried Firefox, Edge, Chrome browsers, nothing changes, the error is present in all of them.
Sorry to bother you with this, but I’ve been struggling with it for 3 days now, I’ve tried a lot of variations (index.html in SPIFFS, internal memory variable in the code, etc.) but I can’t find the bug.
Unfortunately, I can’t upload photos here, but I’ll be happy to email them if needed. Please provide an email address, I will send it there if you see fit.
I look forward to your reply.
Peter
index.html:
<!DOCTYPE HTML><html>
<head>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<script src=”https://code.highcharts.com/highcharts.js”></script>
<style>
body {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto;
}
h2 {
font-family: Arial;
font-size: 2.5rem;
text-align: center;
}
</style>
</head>
<body>
<h2>TGD-1020WO3N Monitor</h2>
<div id=”chart-temperature” class=”container”></div>
<div id=”chart-humidity” class=”container”></div>
<div id=”chart-ozonekonc” class=”container”></div>
</body>
<script>
var chartT = new Highcharts.Chart({
chart:{ renderTo : ‘chart-temperature’ },
title: { text: ‘Temperature’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: ‘#059e8a’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Temperature’ }
//title: { text: ‘Temperature (Fahrenheit)’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/temperature”, true);
xhttp.send();
}, 5000) ;
var chartH = new Highcharts.Chart({
chart:{ renderTo:’chart-humidity’ },
title: { text: ‘Rel.Humidity’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
}
series: { color: ‘#0043af’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Rel.Humidity’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/rel_humidity”, true);
xhttp.send();
}, 5000) ;
var chartO = new Highcharts.Chart({
chart:{ renderTo:’chart-ozonekonc’ },
title: { text: ‘Ozone conc.’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: ‘#18009c’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Ozone conc.’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartO.series[0].data.length > 40) {
chartO.series[0].addPoint([x, y], true, true, true);
} else {
chartO.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/ozonekonc”, true);
xhttp.send();
}, 5000) ;
</script>
</html>
functions:
String serv_read_c_Temperature(){
temperature = sht31.readTemperature();
if (! isnan(temperature)) {
Serial.print(“Temp C= “); Serial.println(temperature);
return String(temperature);
} else {
Serial.println(“Hőmérséklet kiolvasási hiba!”);
return “–“;
}
}
String serv_read_c_Humidity(){
rhumid = sht31.readHumidity();
if (! isnan(rhumid)) {
Serial.print(“R.Hum. %= “); Serial.println(rhumid);
return String(rhumid);
} else {
Serial.println(“Páratartalom kiolvasási hiba!”);
return “–“;
}
}
String serv_read_c_Ozonekonc(){
//************* ide jön az ózon mérés elvégzése rutin *************
if (! isnan(ozoneppm)) {
Serial.print(“Ózon konc. ppm= “); Serial.println(ozoneppm);
return String(ozoneppm);
} else {
Serial.println(“Ózon koncentráció kiolvasási hiba!”);
return “–“;
}
}
server.on calls:
server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/index.html”);
});
server.on(“/temperature”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, serv_read_c_Temperature().c_str());
});
server.on(“/rel_humidity”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, serv_read_c_Humidity().c_str());
});
server.on(“/ozonekonc”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, serv_read_c_Ozonekonc().c_str());
});
// Server indítása
server.begin();
There was a bug in index.html at the beginning of the </script> tag, I fixed it, but unfortunately the bug phenomenon remained.
Index.html again:
<!DOCTYPE HTML><html>
<head>
<meta name=”viewport” content=”width=device-width, initial-scale=1″>
<script src=”https://code.highcharts.com/highcharts.js”></script>
<style>
body {
min-width: 310px;
max-width: 800px;
height: 400px;
margin: 0 auto;
}
h2 {
font-family: Arial;
font-size: 2.5rem;
text-align: center;
}
</style>
</head>
<body>
<h2>TGD-1020WO3N Monitor</h2>
<div id=”chart-temperature” class=”container”></div>
<div id=”chart-humidity” class=”container”></div>
<div id=”chart-ozonekonc” class=”container”></div>
</body>
<script>
var chartT = new Highcharts.Chart({
chart:{ renderTo : ‘chart-temperature’ },
title: { text: ‘Temperature’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: ‘#059e8a’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Temperature’ }
//title: { text: ‘Temperature (Fahrenheit)’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartT.series[0].data.length > 40) {
chartT.series[0].addPoint([x, y], true, true, true);
} else {
chartT.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/temperature”, true);
xhttp.send();
}, 5000) ;
var chartH = new Highcharts.Chart({
chart:{ renderTo:’chart-humidity’ },
title: { text: ‘Rel.Humidity’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
}
series: { color: ‘#0043af’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Rel.Humidity’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartH.series[0].data.length > 40) {
chartH.series[0].addPoint([x, y], true, true, true);
} else {
chartH.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/rel_humidity”, true);
xhttp.send();
}, 5000) ;
var chartO = new Highcharts.Chart({
chart:{ renderTo:’chart-ozonekonc’ },
title: { text: ‘Ozone conc.’ },
series: [{
showInLegend: false,
data: []
}],
plotOptions: {
line: { animation: false,
dataLabels: { enabled: true }
},
series: { color: ‘#18009c’ }
},
xAxis: { type: ‘datetime’,
dateTimeLabelFormats: { second: ‘%H:%M:%S’ }
},
yAxis: {
title: { text: ‘Ozone conc.’ }
},
credits: { enabled: false }
});
setInterval(function ( ) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
var x = (new Date()).getTime(),
y = parseFloat(this.responseText);
//console.log(this.responseText);
if(chartO.series[0].data.length > 40) {
chartO.series[0].addPoint([x, y], true, true, true);
} else {
chartO.series[0].addPoint([x, y], true, false, true);
}
}
};
xhttp.open(“GET”, “/ozonekonc”, true);
xhttp.send();
}, 5000) ;
</script>
</html>
I would use Firefox with dev tools to see if there is any error in HTML/JavaScript.
Hi Steve,
Thank you so much for the idea! Successful, the script works! 🙂
I installed the DEV tool and also quickly learned how to debug with FireFox tools and found the bug, the JavaScript part was missing 1 piece comma.
Thanks again, I learned a lot again …
BR: Peter