Doofe JavaScript Frage - Kommunikation zwischen HTML Seite und ESP8266

Hi zusammen,

ich breche mir grade an einer total simplen Sachen einen ab:
Der folgende Code funktioniert bis auf einen kleinen Schönheitsfehler super:

<!DOCTYPE HTML><html>
<head>
 <link rel="shortcut icon" href="#" />
 <title>Title</title>
 <style>
 body {
 min-width: 310px;
 max-width: 1920px;
 height: 400px;
 margin: 0 auto;
 }
 h1 {
 font-family: Arial;
 font-size: 1,5rem;
 text-align: center;
 }
 .slider 
 {
 width: 100px;
 }
 </style>
</head>
<body>
    <h1>Headline</h1>
 <table align="center" width="40%"> <!-- border=1px -->
 <tr>
 <td align=left>&emsp;Schwellwert</td>
 <!-- Eine Spalte (td) je verbundenem Client -->
 <td align=center>
 <span id="vSchwellwert">?</span> %
 <input class="slider" input type="range" min="-1" max="100"  onchange="vSchwellwertUpdaten(this.value)" id="SliderSchwellwert"/> 
 </td>
 </tr>
 </table>
</body>
<script type="text/javascript">

 //Variable initialisieren
 var vSchwellwert = -1;
 
 //Aktuellen Wert vom Microcontroller auslesen
 var xhttp = new XMLHttpRequest();
 xhttp.onreadystatechange = function() {
 if (this.readyState == 4 && this.status == 200) {
 vSchwellwert.value = this.responseText;
 vSchwellwert.innerHTML = this.responseText;
 document.getElementById("vSchwellwert").innerHTML = this.responseText;
 console.log(vSchwellwert);
 }
 }
 xhttp.open("GET", "/vSchwellwert", true);
 xhttp.send();
 
 //Slider auf Wert positionieren, der vom Microcontroller ausgelesen wurde
 //document.getElementById("SliderSchwellwert").value = vSchwellwert.innerHTML;
 
 //Aktion bei Veränderung des Sliders: SliderSchwellwert
 var eSlider_vSchwellwert = document.getElementById("SliderSchwellwert");
 vSchwellwert = document.getElementById("vSchwellwert");
    vSchwellwert.innerHTML = eSlider_vSchwellwert.value;
    eSlider_vSchwellwert.oninput = function() {
  eSlider_vSchwellwert = this.value;
      vSchwellwert.innerHTML = this.value;
    }
 //Geänderten Wert an Microcontroller senden
 function vSchwellwertUpdaten(value) {
 var xhr = new XMLHttpRequest();
 xhr.open("GET", "/update?vSchwellwert=" + value + "&", true);
 xhr.send();
 }
 </script>
</html>

Lediglich eine Kleinigkeit funktioniert nicht:
Der Slider wird beim aktualisieren der Seite IMMER in die Mitte gesetzt. Er soll aber dort positioniert werden, wo der ausgelesene Wert aktuell steht:

Ist der Schwellwert auf dem Microcontroller beispielsweise aktuell 0, soll die Seite so aufgerufen werden: richtig.jpg

Nicht aber so:
falsch.jpg

Was muss ich dazu ändern?

Vielen Dank vorab für jede Hilfe!

PS: Das Beispiel funktioniert nur sauber, wenn es auf einem Microcontroller läuft, da sonst die GET Requests ins Leere laufen.

Grüße
Noyen

richtig.jpg

falsch.jpg

Mit JavaScript kenne ich mich eigentlich gar nicht aus. PHP und HTML schon eher.

Kannst Du mit value="50" nicht den Startwert setzen?
Statt 50 natürlich den aktuellen Wert.

Also so diese Richtung:

<input class="slider" input type="range" min="-1" max="100" value="0"  onchange="vSchwellwertUpdaten(this.value)" id="SliderSchwellwert"/>

Dann sollte er doch ganz links positioniert werden.

Gruß, Jürgen

noyen:
Lediglich eine Kleinigkeit funktioniert nicht:

Vielen Dank vorab für jede Hilfe!

Vom originalen Dokument konnte ich nicht allzu viel erhalten.
Das hat mir der W3C Validator direkt um die Ohren......

The type attribute is unnecessary for JavaScript resources.

Da sind solche Warnungen noch das kleinere Übel.

Nebenbei, Tabellen sind ausschließlich für tabellarische Daten vorgesehen, es gibt in 2020 ausreichend Möglichkeiten eine Webseite zu strukturieren.

<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="#">
    <title>Title</title>
    <script>
      //Aktuellen Wert vom Microcontroller auslesen 
      //Slider auf Wert positionieren, der vom Microcontroller ausgelesen wurde

      document.addEventListener('DOMContentLoaded', async() => {
        const response = await fetch('/update');
        const t = await response.json();
        SliderSchwellwert.value = t;
        vSchwellwert.innerText = t;

        //Geänderten Wert an Microcontroller senden
        //Aktion bei Veränderung des Sliders: SliderSchwellwert

        SliderSchwellwert.addEventListener('input', () => {
          fetch(`/update?vSchwellwert=${event.target.value}`);
          vSchwellwert.innerText = event.target.value;
        });
      });
    </script>
    <style>
      body, div{
        display: flex;
      }
      body {
        align-items: center;
        flex-flow: column;
      }
      h2{
        font-family: Arial;
      }
      span{
        padding: 0 .2rem;
      }
      input{
	    margin-left: 1em;
      }
    </style>
  </head>
  <body>
    <h2>Headline</h2>
    <div>
      Schwellwert
      <span id="vSchwellwert">?</span>
      %
      <input type="range" min="-1" max="100" id="SliderSchwellwert"/>
    </div>
  </body>
</html>

Das mal als Vorschlag, man kann das natürlich auch individuell/anders machen!

Getestet mit meinen Dimmer Tab, da dein Webserver Code nicht zur Verfügung stand!

Gruß Fips

Guten Abend zusammen,

danke für eure Hilfestellung! (Sorry für meine späte Rückmeldung. Bin vor kurzem Papa geworden und bin etwas aus dem Rithmus :D)

Katsumi_S:
Kannst Du mit value="50" nicht den Startwert setzen?
Statt 50 natürlich den aktuellen Wert.

Im Grunde möchte ich genau das machen. Mein Problem: Der Wert ist in einer Variable gespeichert (im Beispiel "vSchwellwert"). Der Wert der Variablen wird aktuell beim Aufruf der Seite über die folgende Funktion vom ESP8266 ausgelesen:

 	//Variable initialisieren
	var vSchwellwert = -1;	
	//Aktuellen Wert vom Microcontroller auslesen
	var xhttp = new XMLHttpRequest();
	xhttp.onreadystatechange = function() {
			if (this.readyState == 4 && this.status == 200) {
				vSchwellwert.innerHTML = this.responseText;
				document.getElementById("vSchwellwert").innerHTML = this.responseText;
				console.log(vSchwellwert);
			}
		}
	xhttp.open("GET", "/vSchwellwert", true);
	xhttp.send();

Ich weiß "einfach" nicht, wie ich dem Schieberegler/Renge Slider den Wert dieser Variablen zuweise, nachdem diese vom ESP ausgelesen wurde :smiley:

Viele Grüße
Michael

@Derfips:

Derfips:
Nebenbei, Tabellen sind ausschließlich für tabellarische Daten vorgesehen, es gibt in 2020 ausreichend Möglichkeiten eine Webseite zu strukturieren.

Danke dir für deine ausführliche Hilfe und dein konstruktives Feedback!

Mittelfristig möchte ich die Seite durch einen Webentwicker nochmal "schön" machen lassen. Daher ist mein aktueller Fokus auf technischer Funktionalität. (Wenn du also noch einen Nebenjob suchst, können wir gerne mal Kontaktdaten austauschen :).)

Derfips:
Vom originalen Dokument konnte ich nicht allzu viel erhalten.
Das hat mir der W3C Validator direkt um die Ohren......
Da sind solche Warnungen noch das kleinere Übel.

Die Seite läuft auf einem ESP und benötigt dessen Responses um fehlerfrei zu arbeiten. Hier der entsprechende Code vom ESP. (Es wurde der "LittelFS" verwendet, um die Datei "index.html" auf den ESP zu kopieren):

//AsyncWebServer
#include <ESPAsyncWebServer.h>

//File System
#include <LittleFS.h>

//WLAN SSID & Password
const char *wlan_ssid     = "YourAccessPoint";
const char *wlan_password = "YourAccessPointPW";

//WLAN + WEB Server Konfiguration
AsyncWebServer HTML_server(80);

//Variablen
int vSchwellwert  = 0;

void setup() 
{
  //Debugging
  Serial.begin(115200);
  //Warten, bis Serieller Monitor bereit
  delay(200);
  Serial.println("###Setup###");

  //WLAN + Web Server Konfiguration
  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(wlan_ssid);
  //Set WiFi to access point (client data collection) AND station mode (html web server)
  WiFi.mode(WIFI_AP_STA); 
  WiFi.begin(wlan_ssid, wlan_password);
  
  if (WiFi.waitForConnectResult() != WL_CONNECTED) {
    Serial.println("WiFi Connect Failed! Rebooting...");
    delay(1000);
    ESP.restart();
  }

  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Initialize LittleFS
  if(!LittleFS.begin()){
    Serial.println("An Error has occurred while mounting LittleFS");
    return;
  }

  //Webseite ohne Authentifikation
  HTML_server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send(LittleFS, "/index.html");
  });

  //Funktion(en) zur Übergabe von Variablen an den Web Server
  HTML_server.on("/vSchwellwert", HTTP_GET, [](AsyncWebServerRequest *request){
    request->send_P(200, "text/plain", String(vSchwellwert).c_str());
  });


  // Send a GET request to <ESP_IP>/update?relay=<inputMessage>&state=<inputMessage2>
  HTML_server.on("/update", HTTP_GET, [] (AsyncWebServerRequest *request) {
    Serial.println("#HTML update setting#");
    String inputMessage;
    String inputParam;
    // GET input1 value on <ESP_IP>/update?vSchwellwert=<inputMessage>
    // e.G. http://192.168.43.123/update?vSchwellwert=0
    if (request->hasParam("vSchwellwert")) {
      inputMessage = request->getParam("vSchwellwert")->value();
      inputParam = "vSchwellwert";
      vSchwellwert = inputMessage.toInt();
      //Debugging
      Serial.print(inputParam);
      Serial.print(" wurde neu definiert: ");
      Serial.println(inputMessage.toInt());
      Serial.print("vSchwellwert: ");
      Serial.println(vSchwellwert);
    }
    else {
      inputMessage = "No message sent";
      inputParam = "none";
    }
    request->send(200, "text/plain", "OK");
  });
  
  HTML_server.begin();

  Serial.println("###Setup Ende###");
}


void loop(void) 
{ 

}

Ich habe das Javascript mal an deine Zweimal "server.on" angepasst, obwohl da auch ein "server.on" reichen würde.

<!DOCTYPE HTML> <!-- For more information visit: https://fipsok.de -->
<html lang="de">
  <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="shortcut icon" href="#">
    <title>Title</title>
    <script>
      document.addEventListener('DOMContentLoaded', async() => {
        const response = await fetch('/vSchwellwert');
        const t = await response.text();
        SliderSchwellwert.value = t;
        vSchwellwert.innerText = t;
        SliderSchwellwert.addEventListener('input', e => {
          fetch(`/update?vSchwellwert=${e.target.value}`);
          vSchwellwert.innerText = e.target.value;
        });
      });
    </script>
    <style>
      body, div{
        display: flex;
      }
      body {
        align-items: center;
        flex-flow: column;
      }
      h2{
        font-family: Arial;
      }
      span{
        padding: 0 .2rem;
      }
      input{
    margin-left: 1em;
      }
    </style>
  </head>
  <body>
    <h2>Headline</h2>
    <div>
      Schwellwert
      <span id="vSchwellwert">?</span>
      %
      <input type="range" min="-1" max="100" id="SliderSchwellwert"/>
    </div>
  </body>
</html>

Gilt als ungetestet da ich den "ESPAsyncWebServer" nicht habe und "vSchwellwert" in deinem Sketch nicht deklariert wurde!

Mittelfristig möchte ich die Seite durch einen Webentwicker nochmal "schön" machen lassen. Daher ist mein aktueller Fokus auf technischer Funktionalität. (Wenn du also noch einen Nebenjob suchst, können wir gerne mal Kontaktdaten austauschen :).)

Ich bin im Fahrzeugbau tätig (E-mobility for the masses), weder Webentwickler noch Programmierer, kontaktieren kannst du mich trotz alledem gerne z.B.: mittels Kontaktformular auf meiner Webseite.

Gruß Fips