ozone
December 13, 2020, 9:32am
1
Hallo zusammen,
ich habe folgendes Problem. Ich möchte mehrere Werte per ASyncWebServer und range slider an den ESP32 übergeben.
Das Ganze funktioniert im Hintergrund auch korrekt, nur wird beim obersten Slider der Wert beim ersten Laden bzw. jedem Websitenrefresh falsch angezeigt. Wird der "Set Temperatur" Slider einmal upgadete stimmt der Wert wieder bis zum Websiterefresh, dann steht immer der Wert des untersten Sliders drinne (egal welcher dies ist).
Lässt man sich den Seitenquelltext im Browser anzeigen steht auch der richtige Wert drinnen und die Sliderposition stimmt auch.
Die anderen Slider funktionieren einwandrei.
Ich finde den Fehler einfach nicht und es wäre super wenn mir jemand behilflich sein könnte.
Anbei der ESP32 Code der die Website erstellt + Screenshots.
Danke für Eure Rückmeldungen.
Grüße,
Stefan
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" >
<link rel="icon" href="data:,">
<style>
body { text-align: center; font-family: "Trebuchet MS", Arial; margin-left:auto; margin-right:auto;}
.slider { width: 300px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"> </script>
</head>
<body><h1>ESP32 L46 Aquacontrol</h1>
<p>Set Temperatur: <span id="setTempValue"> %SETTEMPRATURESLIDERVALUE% </span> </p>
<input type="range" min="20" max="30" step="0.5" class="slider" id="setTempSlider" onchange="setTemp(this.value)" value="%SETTEMPRATURESLIDERVALUE%"/>
<script>
var sliderSETTEMP = document.getElementById("setTempSlider");
var setTempVar = document.getElementById("setTempValue");
setTempVar.innerHTML = sliderSETTEMP.value;
sliderSETTEMP.oninput = function() {
sliderSETTEMP.value = this.value; setTempVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setTemp(temp) {
$.get("/sliderSETTEMP?value=" + temp + "&"); {Connection: close};
}
</script>
<p>Set on hour: <span id="setOnHourValue"> %SETONHOURSLIDERVALUE% </span></p>
<input type="range" min="0" max="12" class="slider" id="setOnHourSlider" onchange="setOnHour(this.value)" value="%SETONHOURSLIDERVALUE%"/>
<script>
var sliderONHOUR = document.getElementById("setOnHourSlider");
var setOnHourVar = document.getElementById("setOnHourValue");
setTempVar.innerHTML = sliderONHOUR.value;
sliderONHOUR.oninput = function() {
sliderONHOUR.value = this.value; setOnHourVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setOnHour(temp) {
$.get("/sliderONHOUR?value=" + temp + "&"); {Connection: close};
}
</script>
<p>Set on minute: <span id="setOnMinuteValue"> %SETONMINUTESLIDERVALUE% </span></p>
<input type="range" min="0" max="59" class="slider" id="setOnMinuteSlider" onchange="setOnMinute(this.value)" value="%SETONMINUTESLIDERVALUE%"/>
<script>
var sliderONMINUTE = document.getElementById("setOnMinuteSlider");
var setOnMinuteVar = document.getElementById("setOnMinuteValue");
setTempVar.innerHTML = sliderONMINUTE.value;
sliderONMINUTE.oninput = function() {
sliderONMINUTE.value = this.value; setOnMinuteVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setOnMinute(temp) {
$.get("/sliderONMINUTE?value=" + temp + "&"); {Connection: close};
}
</script>
<p>Set off hour: <span id="setOffHourValue"> %SETOFFHOURSLIDERVALUE% </span></p>
<input type="range" min="12" max="23" class="slider" id="setOffHourSlider" onchange="setOffHour(this.value)" value="%SETOFFHOURSLIDERVALUE%"/>
<script>
var sliderOFFHOUR = document.getElementById("setOffHourSlider");
var setOffHourVar = document.getElementById("setOffHourValue");
setTempVar.innerHTML = sliderOFFHOUR.value;
sliderOFFHOUR.oninput = function() {
sliderOFFHOUR.value = this.value; setOffHourVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setOffHour(temp) {
$.get("/sliderOFFHOUR?value=" + temp + "&"); {Connection: close};
}
</script>
<p>Set off minute: <span id="setOffMinuteValue"> %SETOFFMINUTESLIDERVALUE% </span></p>
<input type="range" min="0" max="59" class="slider" id="setOffMinuteSlider" onchange="setOffMinute(this.value)" value="%SETOFFMINUTESLIDERVALUE%"/>
<script>
var sliderOFFMINUTE = document.getElementById("setOffMinuteSlider");
var setOffMinuteVar = document.getElementById("setOffMinuteValue");
setTempVar.innerHTML = sliderOFFMINUTE.value;
sliderOFFMINUTE.oninput = function() {
sliderOFFMINUTE.value = this.value; setOffMinuteVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setOffMinute(temp) {
$.get("/sliderOFFMINUTE?value=" + temp + "&"); {Connection: close};
}
</script>
</body></html>
)rawliteral";
String processor(const String& var){
//Serial.println(var);
if (var == "SETTEMPRATURESLIDERVALUE"){
Serial.printf("Placeholder SETTEMPRATURESLIDERVALUE: %f \n",setTemperatur);
return String(setTemperatur);
}
else if (var == "SETONHOURSLIDERVALUE"){
Serial.printf("Placeholder SETONHOURSLIDERVALUE: %i \n",onHour);
return String(onHour);
}
else if (var == "SETONMINUTESLIDERVALUE"){
Serial.printf("Placeholder SETONMINUTESLIDERVALUE: %i \n",onMinute);
return String(onMinute);
}
else if (var == "SETOFFHOURSLIDERVALUE"){
Serial.printf("Placeholder SETOFFHOURSLIDERVALUE: %i \n",offHour);
return String(offHour);
}
else if (var == "SETOFFMINUTESLIDERVALUE"){
Serial.printf("Placeholder SETOFFMINUTESLIDERVALUE: %i \n",offMinute);
return String(offMinute);
}
return String();
}
Nach Websiterefresh wird der Set Tempratur Sliderwert falsch angezeigt
Nach ändern des Sliderwertes passt es bis zum erneuten Websiterefresh
noiasca
December 13, 2020, 9:54am
2
wenn sich das nicht nach 1 Sekunde mit dem AJAX Update aktualisiert VERMUTE ich das liegt an deinem Javascript - Response from Server.
Da du verstümmelten Code postest must du selber suchen.
ozone
December 13, 2020, 10:02am
3
Danke für die Antwort @noiasca
Anbei der fehlende Setup Code
void setup() {
//safePrefs(); only on first run
// put your setup code here, to run once:
Serial.begin(115200);
prefs.begin("Data",false);
readPrefs();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
if(!MDNS.begin(hostname)) {
Serial.println("Error starting mDNS");
return;
}
server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/slider?value=<inputMessage>
server.on("/sliderSETTEMP", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/slider?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
//sliderValue = inputMessage;
//setTemperatur = sliderValue.toFloat();
setTemperatur = inputMessage.toFloat();
}
Serial.println(setTemperatur);
safePrefs();
request->send(200, "text/plain", "OK");
});
server.on("/sliderONHOUR", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/slider?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
onHour = sliderValue.toInt();
}
Serial.println(onHour);
safePrefs();
request->send(200, "text/plain", "OK");
});
server.on("/sliderONMINUTE", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/slider?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
onMinute = sliderValue.toInt();
}
Serial.println(onMinute);
safePrefs();
request->send(200, "text/plain", "OK");
});
server.on("/sliderOFFHOUR", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/slider?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
offHour = sliderValue.toInt();
}
Serial.println(offHour);
safePrefs();
request->send(200, "text/plain", "OK");
});
server.on("/sliderOFFMINUTE", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/slider?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
offMinute = sliderValue.toInt();
}
Serial.println(offMinute);
safePrefs();
request->send(200, "text/plain", "OK");
});
server.begin();
}
noiasca
December 13, 2020, 10:13am
4
How to use this forum
Post a complete sketch (program code)! If you don't you waste time while people ask you to do that. However, with coding problems, if possible post a "minimal" sketch that demonstrates the problem - not hundreds of lines of code. If the problem goes away in the minimal sketch, it wasn't where you thought it was.
ozone
December 13, 2020, 3:51pm
5
Danke für den Hinweis @noiacsa . Ich habe den Code deutlich reduziert.
Auch mit 2 Slidern zeigt sich leider das selbe Verhalten.
Bei ersten Aufruf und jedem Refresh der Webpage, wird der setTemperatur Wert falsch angezeigt (der vom letztem Slider). Lässt man sich den Seitenquelltext anzeigen ist der richtige Wert zu sehen.
<p>Set Temperatur: <span id="setTempValue"> 24.5 </span> </p>
Die Debug Ausgaben ins Terminal zeigen auch immer die korrekten Werte
Wird der Sliderwert durch verschieben des Sliders verändert wird er korrekt angezeigt.
Vielleicht kann jemand meinen Fehler entdecken?
Beste Grüße,
Stefan
Anbei der vollständige Quellcode:
#include <Arduino.h>
#include <WiFi.h>
#include <ESPmDNS.h>
#include <ESPAsyncWebServer.h>
const char* ssid = "Net-SSID";
const char* password = "********";
const char* hostname = "L46Aqua";
AsyncWebServer server(80);
const char* PARAM_INPUT = "value";
String sliderValue = "0";
//Dimmereinstellung
int onHour = 6;
//Heater wertet
float setTemperatur = 25.0;
const char index_html[] PROGMEM = R"rawliteral(
<!DOCTYPE html><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1" >
<link rel="icon" href="data:,">
<style>
body { text-align: center; font-family: "Trebuchet MS", Arial; margin-left:auto; margin-right:auto;}
.slider { width: 300px; }
</style>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"> </script>
</head>
<body><h1>ESP32 L46 Aquacontrol</h1>
<p>Set Temperatur: <span id="setTempValue"> %SETTEMPRATURESLIDERVALUE% </span> </p>
<input type="range" min="20" max="30" step="0.5" class="slider" id="setTempSlider" onchange="setTemp(this.value)" value="%SETTEMPRATURESLIDERVALUE%"/>
<script>
var sliderSETTEMP = document.getElementById("setTempSlider");
var setTempVar = document.getElementById("setTempValue");
setTempVar.innerHTML = sliderSETTEMP.value;
sliderSETTEMP.oninput = function() {
sliderSETTEMP.value = this.value; setTempVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setTemp(temp) {
$.get("/sliderSETTEMP?value=" + temp + "&"); {Connection: close};
}
</script>
<p>Set on hour: <span id="setOnHourValue"> %SETONHOURSLIDERVALUE% </span></p>
<input type="range" min="0" max="12" class="slider" id="setOnHourSlider" onchange="setOnHour(this.value)" value="%SETONHOURSLIDERVALUE%"/>
<script>
var sliderONHOUR = document.getElementById("setOnHourSlider");
var setOnHourVar = document.getElementById("setOnHourValue");
setTempVar.innerHTML = sliderONHOUR.value;
sliderONHOUR.oninput = function() {
sliderONHOUR.value = this.value; setOnHourVar.innerHTML = this.value;
}
$.ajaxSetup({timeout:1000}); function setOnHour(temp) {
$.get("/sliderONHOUR?value=" + temp + "&"); {Connection: close};
}
</script>
</body></html>
)rawliteral";
String processor(const String& var){
Serial.print(var);
if (var == "SETTEMPRATURESLIDERVALUE"){
Serial.printf(" Placeholder SETTEMPRATURESLIDERVALUE: %f \n",setTemperatur);
return String(setTemperatur,1);
}
else if (var == "SETONHOURSLIDERVALUE"){
Serial.printf(" Placeholder SETONHOURSLIDERVALUE: %i \n",onHour);
return String(onHour);
}
return String();
}
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println(WiFi.localIP());
if(!MDNS.begin(hostname)) {
Serial.println("Error starting mDNS");
return;
}
server.on("/index.html", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/html", index_html, processor);
});
// Send a GET request to <ESP_IP>/slider?value=<inputMessage>
server.on("/sliderSETTEMP", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input value on <ESP_IP>/sliderSETTEMP?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
setTemperatur = sliderValue.toFloat();
//setTemperatur = inputMessage.toFloat();
}
Serial.printf("New setTemp from webpage : %f \n",setTemperatur);
request->send(200, "text/plain", "OK");
});
server.on("/sliderONHOUR", HTTP_GET, [] (AsyncWebServerRequest *request) {
String inputMessage;
// GET input1 value on <ESP_IP>/sliderONHOUR?value=<inputMessage>
if (request->hasParam(PARAM_INPUT)) {
inputMessage = request->getParam(PARAM_INPUT)->value();
sliderValue = inputMessage;
onHour = sliderValue.toInt();
}
Serial.printf("New onHour from webpage : %i \n",onHour);
request->send(200, "text/plain", "OK");
});
server.begin();
}
void loop() {
// put your main code here, to run repeatedly:
}
noiasca
December 13, 2020, 4:11pm
6
wie heißt diese Library im Bib-Manager genau - oder woher hast du sie?
#include <ESPAsyncWebServer.h>
ozone
December 14, 2020, 9:49am
7
So Fehler gefunden - Kopierfehler .
@noiasca Danke nochmals für den Tipp mit dem Vereinfachen, erst dadurch war ich nicht mehr blind für den Kopierfehler. Die ASyncWebserver Lib hab ich übrigends da her ESP32 Web Server with Slider: Control LED Brightness (PWM) | Random Nerd Tutorials
noiasca
December 14, 2020, 10:50am
8
fein das es klappt.
Ja das vereinfachen von Sketches hilft meistens sich auf das wesentliche konzentrieren zu können - und meist findet man es dann auch selber.
Mach doch Alles mit jQuery
Oben JavaScript und unten jQuery, hääää, warum das?
$.fn.RefreshData = function(){
$.ajax({
type: "GET",
url: "/my_ajax_handler", //muss im esp sketch vorhanden sein und Daten liefern
data: "",
cache: false,
success: function(html){
//hier wertest du das Ergebnis der Anfrage aus und übergibst die empfangenen Daten an das Steuerelement
$("#my_id ").val(html); //Wert von den empfangenen Daten
}
$(document).ready(function() {
//hier deine Werte per AJAX anfordern und an das Steuerelement übergeben
$().RefreshData();
//oder auch alle xxxx Millisekunden vom Server neu anfordern
setInterval($().RefreshData, xxxx);
});
Derfips
December 15, 2020, 7:33am
10
freddy64:
Mach doch Alles mit jQuery
Oben JavaScript und unten jQuery, hääää, warum das?
Besser ohne, aktuelles Javascript braucht kein jQuery!
Der ESP32 ist aber aufgrund seiner Leistung gerade prädestiniert dafür...und noch dazu mit dem AsyncWebServer.
Entweder die jQuery.js zur Laufzeit laden (wenn WiFi mit Internet Verbindung verwendet wird) oder in den SPIFFS hochladen und von da aus offline verwenden.
Ich mach es nur noch so. jQuery und bootstrap sind heutzutage einfach ein MUSS für Geräteabhängige Stilvorgaben mit CSS oder in der Fachsprache auch "responsive designs" genannt.
Aber Vorsicht bei Verwendung der aktuellsten Version des AsyncWebServers.
Da schleichen sich öfter mal Bugs ein, die das ganze System zum Absturz oder zum Stillstand bringen.
Öfter mal bei GitHub vorbeischauen und durch Issues lesen.
Ich verwende derzeit immer noch Version 2.1
Tommy56
December 15, 2020, 10:01pm
12
jQuery ist doch mittlerweile mit HTML5 und aktuellen JS-Versionen (fast) obsolet.
Gruß Tommy
Sind da auch alle Browser gleich bei HTML5.
Ich erlebe es fast täglich:
Firefox kann dieses, jenes aber nicht und ist bei scripts zu langsam.
Opera ist relativ fix wird aber kaum verwendet.
Safari kocht wieder seine eigene Suppe (ist halt Apple)
Chrome telefoniert ständig nach hause.
MS mit seinem suuuuper Edge wird mit Sicherheit auch bald wieder zum Problemfall wie früher.
if browser == ie8-> mach so, if browser == ie9 ->mach so, if browser == iexx ->lass es bleiben
Ich für mich verwende Opera. Passt, schnell, gut.
Für DEBUG Zwecke auf der Konsole muss dann doch wieder der Fuchs herhalten.
Derfips
December 16, 2020, 7:08am
14
freddy64:
....und ist bei scripts zu langsam.
Gilt das für Vanilla-Javascript und wird es mit jQuery besser?
Bootstrap 5 ohne jQuery
Der Abschied von jQuery bedeutet natürlich nicht, dass Bootstrap 5 keinen Support für JavaScript mehr mitbringt. Die Entscheidung gegen das Framework wurde aus den gleichen Gründen getroffen, die schon andere Projekte anführten: jQuery war früher einmal nötig, um komplexes Verhalten in JavaScript zu realisieren. Heute geht es jedoch auch ohne, da sich die Sprache weiterentwickelt hat.
Ouelle: Bootstrap 5 Alpha veröffentlicht: Kein jQuery mehr!
Wann Bootstrap 5 final erscheinen wird, ist noch nicht bekannt...
Bis dahin bleibe ich noch bei jQuery und danach werde ich auch nicht alle Webseiten Hals über Kopf umstellen.
Erst mal abwarten, bis sich die ersten 1.000.000 Web-Programmierer damit abgeschuftet und ihre Erfahrungen gemacht haben.