Textbox eingaben bei NodeMCU

Hallo zusammen,

ich habe Probleme Werte, die ich in einem Browser einlesen will im Sketch zu verwenden. Bisher habe ich ein paar Buttons hinbekommen, die auch entsprechend meine Anweisungen ausführen. Bei Textfelder scheitere ich allerding. Vielleicht könnt ihr mir helfen??

https://pastebin.com/fxCHPngH

Es geht im Detail darum, dass ich mit dem Button "Vollfarbe" die RGB-Werte aus drei Textboxen übertragen möchte. Bisher konnte ich bereits ein Textfeld einfügen (Zeile 58), aber dann hört es auch auf...

Vorab denke ich mich herzlich für Eure Hilfe!!

Stelle bitte Deinen Sketch in Codetags hier ein, wenn Du willst, das man ihn liest.

Gruß Tommy

Sorry dafür, hier der Code:

#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
 
const char *ssid = "NodeMCUWIFI";
const char *password = "password";
int stateLED = LOW;
int stateMode = 0;
ESP8266WebServer server(80);
 
void handleRoot() {
    response();
}
 
void handleLedOn() {
  stateLED = LOW;
  digitalWrite(LED_BUILTIN, stateLED);
  response();
}
 
void handleLedOff() {
  stateLED = HIGH;
  digitalWrite(LED_BUILTIN, stateLED);
  response();
}
 
void handleMode1() { stateMode = 1; response(); }
void handleMode2() { stateMode = 2; response(); }
void handleMode3() { stateMode = 3; response(); }
void handleMode4() { stateMode = 4; response(); }
void handleMode5() { stateMode = 5; response(); }
void handleMode6() { stateMode = 6; response(); }
 
 
const String HtmlHtml = "<html><head>"
    "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head>";
const String HtmlHtmlClose = "</html>";
const String HtmlTitle = "<h1>Beleuchtung by ihmSelbst</h1>
\n";
const String HtmlLedStateLow = "<big>LED is now <b>ON</b></big>
\n";
const String HtmlLedStateHigh = "<big>LED is now <b>OFF</b></big>
\n";
const String HtmlStateMode1 = "<big>Aktueller Modus: <b>Rainbow</b></big>
\n";
const String HtmlStateMode2 = "<big>Aktueller Modus: <b>Rainbow 2</b></big>
\n";
const String HtmlStateMode3 = "<big>Aktueller Modus: <b>Kirmesmodus</b></big>
\n";
const String HtmlStateMode4 = "<big>Aktueller Modus: <b>Vollfarbe</b></big>
\n";
const String HtmlStateMode5 = "<big>Aktueller Modus: <b>Juggle</b></big>
\n";
const String HtmlStateMode6 = "<big>Aktueller Modus: <b>Fire2017</b></big>
\n";
const String HtmlButtons =
    "<a href=\"LEDOn\"><button style=\"display: block; width: 100%;\">ON</button></a>
"
    "<a href=\"Mode1\"><button style=\"display: block; width: 100%;\">Rainbow</button></a>
"
    "<a href=\"Mode2\"><button style=\"display: block; width: 100%;\">Rainbow 2</button></a>
"
    "<a href=\"Mode3\"><button style=\"display: block; width: 100%;\">Kirmesmodus</button></a>
"
    "<a href=\"Mode5\"><button style=\"display: block; width: 100%;\">Juggle</button></a>
"
    "<a href=\"Mode6\"><button style=\"display: block; width: 100%;\">Fire2017</button></a>
"
    "<a href=\"LEDOff\"><button style=\"display: block; width: 100%;\">OFF</button></a>
"
    "<a href=\"Mode4\"><button style=\"display: block; width: 100%;\">Vollfarbe</button></a>
";
 
const String HtmlTextfields =
    "<input type='text' name='Rot'>
";
 
void response(){
  String htmlRes = HtmlHtml + HtmlTitle;
  /*
  if(stateLED == LOW){
    htmlRes += HtmlLedStateLow;
  }else{
    htmlRes += HtmlLedStateHigh;
  }
  */
  if(stateMode == 1){
    htmlRes += HtmlStateMode1;
  }
  if(stateMode == 2){
    htmlRes += HtmlStateMode2;
  }
  if(stateMode == 3){
    htmlRes += HtmlStateMode3;
  }
  if(stateMode == 4){
    htmlRes += HtmlStateMode4;
  }
  if(stateMode == 5){
    htmlRes += HtmlStateMode5;
  }
  if(stateMode == 6){
    htmlRes += HtmlStateMode6;
  }
 
  htmlRes += HtmlButtons + HtmlTextfields;
  htmlRes += HtmlHtmlClose;
 
  server.send(200, "text/html", htmlRes);
}
 
void setup() {
    delay(1000);
    Serial.begin(9600);
    Serial.println();
 
    WiFi.softAP(ssid, password);
 
    IPAddress apip = WiFi.softAPIP();
    Serial.print("visit: \n");
    Serial.println(apip);
    server.on("/", handleRoot);
    server.on("/LEDOn", handleLedOn);
    server.on("/LEDOff", handleLedOff);
    server.on("/Mode1", handleMode1);
    server.on("/Mode2", handleMode2);
    server.on("/Mode3", handleMode3);
    server.on("/Mode4", handleMode4);
    server.on("/Mode5", handleMode5);
    server.on("/Mode6", handleMode6);
    server.begin();
    Serial.println("HTTP server beginned");
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, stateLED);
}
 
void loop() {
    server.handleClient();
}

Lass Dir doch mal den kompletten HTML-Text auf Serial ausgeben und schaue, ob er dem entspricht, was Du Dir vorstellst. Ich vermisse in diesem HTML-Text das Form-Tag mit der GET-Methode (die ist einfacher zu sehen und damit zu parsen). Ebenso die GET-Auswertung. Wie soll der Browser denn wissen, was er wie abzuzschicken hat?

Als Lektüre sei Dir SelfHtml und W3Schools empfohlen.

Gruß Tommy

Ich danke Dir für Deine rasche Antwort, aber genau hier liegt das Problem. Ich kann Dir gar nicht sagen warum, ich bekomme den Kotz in den Augen wenn es um HTML geht. Es ist ja nicht so als hätte ich zig mal versucht mir zumindest die Grundlagen anzueignen, aber das ist für mich ein Buch mit sieben Siegeln. Auch weiß ich, dass wahrscheinlich rudimentäre Grundlagen ausreichen um mein Vorhaben zu realisieren, aber das hilft wir wirklich im Moment nicht weiter.

Du hast bereits mit ein paar Sichtworten um Dich geworfen die wahrscheinlich schon so gut wie den ganzen Code wiederspiegeln... Ich will nicht dreisst klingen, aber dürfte ich Dich bitten mir anhand von Codebeispielen zu zeigen was noch zu tun ist?

Zudem habe ich kein Idee wie ich Codemäßig nach der Ausgabe der Werte parsen soll !?

Ich verzweifel hier noch. :)

Wenn Du Dich da nicht durchbeißt, lernst Du es nie.

Fange klein an. Eine kleine HTML-Seite, die nur Dein Textfeld und einen Button zum Senden beinhaltet.

<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="utf-8">
    <title>Test</title>
  </head>
  <body>
    <form method="GET" action="./auswertung">
      <input type="text" name="input1" /> <input type="submit" />
    </form>  
  </body>
</html>

Dann läßt Du Dir alles, was der Browser sendet auf Serial ausgeben.

Achte besonders auf Zeilen, die GET beinhalten. Die musst Du erfassen und auswerten.

Gruß Tommy

Also zuerst mal ein Formular basteln, Tommy56 hat das ja schon erwähnt.

Die über das Formular übergebenen Daten kriegst du dann mit:
server.args() … die Anzahl der übergebenen “Variablen”
server.argName(i) … der Name der übergebenen Variable
server.arg(i) … der “Wert” der Variable

Zum Beispiel kannst du mit folgendem Code das auf Serial ausgeben lassen:

// Print how many properties we received and then print their names and values.
Serial.print("Number of query properties: ");
Serial.println(server.args());
for (int i=0; i<server.args(); i++) {
   Serial.print(server.argName(i));
   Serial.println(server.arg(i));
}

Hinweis:
Die “arg” sind immer Strings, auch wenn du Zahlen übergibst. Falls du mit diesen rechnen möchtest, dann brauchst du zum Beispiel
toInt()
Beispiel:

int meineZahl  = server.arg(0).toInt();

Es gibt viele Infos über das Board im Buch von Neil Koban (PDF, englisch) hier: http://neilkolban.com/tech/esp8266/

Schau dir mal das an.https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WebServer/examples/SimpleAuthentification

Der ESP8266-Webserver ist ja noch viel komplexer ausgebaut, als ich bisher mitbekommen habe. Da muss man nicht mal mehr die GET-Zeile selbst zerlegen.

So, wie ich das sehe, sollte man die HTML-Seite evtl. auch im SPIFS unterbringen können.

Gruß Tommy

Tommy56: Der ESP8266-Webserver ist ja noch viel komplexer ausgebaut, als ich bisher mitbekommen habe. Da muss man nicht mal mehr die GET-Zeile selbst zerlegen.

So, wie ich das sehe, sollte man die HTML-Seite evtl. auch im SPIFS unterbringen können.

Gruß Tommy

Ja das geht auch. Ich hab es auch schon geschafft Dateien aus den Spiffs zu Downloaden.

Hast Du da evtl. einen Code oder machst Du "einfach" das File im SPIFFS auf und schreibst es in einer Schleife zum Client?

Gruß Tommy

Ich hab mir da was gebastelt. Ich häng den Namen der Datei dann einfach an die URL. Da ich im Moment nur mit dem Klingelkasten online bin kann ich dir das jetzt nicht schicken. Aber ich werde es nachholen.

Klingelkasten ist gut. ;)

Danke.

Gruß Tommy

Ich habe jetzt die halbe Nacht versucht die Tipps zu beherzigen, aber es läuft noch immer nicht.

Vielleicht könnt ihr mir sagen was noch immer falsch läuft?

hier der Code:

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

const char *ssid = "NodeMCUWIFI";
const char *password = "password";
int stateLED = LOW;
int stateMode = 0;
ESP8266WebServer server(80);

void handleRoot() {
    response();
}

void handleLedOn() {
  stateLED = LOW;
  digitalWrite(LED_BUILTIN, stateLED);
  response();
}

void handleLedOff() {
  stateLED = HIGH;
  digitalWrite(LED_BUILTIN, stateLED);
  response();
}

void handleMode1() { stateMode = 1; response(); }
void handleMode2() { stateMode = 2; response(); }
void handleMode3() { stateMode = 3; response(); }
void handleMode4() { stateMode = 4; response(); }
void handleMode5() { stateMode = 5; response(); }
void handleMode6() { stateMode = 6; response(); }


const String HtmlHtml = "<html><head>"
    "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\" /></head>";
const String HtmlHtmlClose = "</html>";
const String HtmlTitle = "<h1>Beleuchtung by ihmSelbst</h1>
\n";
const String HtmlLedStateLow = "<big>LED is now <b>ON</b></big>
\n";
const String HtmlLedStateHigh = "<big>LED is now <b>OFF</b></big>
\n";
const String HtmlStateMode1 = "<big>Aktueller Modus: <b>Rainbow</b></big>
\n";
const String HtmlStateMode2 = "<big>Aktueller Modus: <b>Rainbow 2</b></big>
\n";
const String HtmlStateMode3 = "<big>Aktueller Modus: <b>Kirmesmodus</b></big>
\n";
const String HtmlStateMode4 = "<big>Aktueller Modus: <b>Vollfarbe</b></big>
\n";
const String HtmlStateMode5 = "<big>Aktueller Modus: <b>Juggle</b></big>
\n";
const String HtmlStateMode6 = "<big>Aktueller Modus: <b>Fire2017</b></big>
\n";
const String HtmlStateSubmit = "<big>Aktueller Modus: <b>SUBMIT!</b></big>
\n";
const String HtmlButtons = 
    "<a href=\"LEDOn\"><button style=\"display: block; width: 100%;\">ON</button></a>
"
    "<a href=\"Mode1\"><button style=\"display: block; width: 100%;\">Rainbow</button></a>
"
    "<a href=\"Mode2\"><button style=\"display: block; width: 100%;\">Rainbow 2</button></a>
"
    "<a href=\"Mode3\"><button style=\"display: block; width: 100%;\">Kirmesmodus</button></a>
"
    "<a href=\"Mode5\"><button style=\"display: block; width: 100%;\">Juggle</button></a>
"
    "<a href=\"Mode6\"><button style=\"display: block; width: 100%;\">Fire2017</button></a>
"
    "<a href=\"LEDOff\"><button style=\"display: block; width: 100%;\">OFF</button></a>
"
    "<a href=\"Mode4\"><button style=\"display: block; width: 100%;\">Vollfarbe</button></a>
";

const String HtmlTextfields = 
    "R: <input type=\"text\" name=\"input1\" maxlength=\"3\" style=\"width:10%;\" /> G: <input type=\"text\" name=\"input2\" maxlength=\"3\" style=\"width:10%;\" /> B: <input type=\"text\" name=\"input3\" maxlength=\"3\" style=\"width:10%;\" /> <input type=\"submit\" value=\"Sende vollfarben\" style=\"width:25%;\" />";

void response(){

  Serial.print("Number of query properties: ");
  Serial.println(server.args());
  for (int i=0; i<server.args(); i++) 
  {
    Serial.print(server.argName(i));
    Serial.println(server.arg(i));
  }
  
  String htmlRes = HtmlHtml + HtmlTitle;
  /*
  if(stateLED == LOW){
    htmlRes += HtmlLedStateLow;
  }else{
    htmlRes += HtmlLedStateHigh;
  }
  */
  if(stateMode == 1){
    htmlRes += HtmlStateMode1;
  }
  if(stateMode == 2){
    htmlRes += HtmlStateMode2;
  }
  if(stateMode == 3){
    htmlRes += HtmlStateMode3;
  }
  if(stateMode == 4){
    htmlRes += HtmlStateMode4;
  }
  if(stateMode == 5){
    htmlRes += HtmlStateMode5;
  }
  if(stateMode == 6){
    htmlRes += HtmlStateMode6;
  }
  if(submit1 == 1){
    htmlRes += HtmlStateSubmit;
  }
  
  
  htmlRes += HtmlButtons + HtmlTextfields;
  htmlRes += HtmlHtmlClose;

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

void setup() {
    delay(1000);
    Serial.begin(9600);
    Serial.println();

    WiFi.softAP(ssid, password);

    IPAddress apip = WiFi.softAPIP();
    Serial.print("visit: \n");
    Serial.println(apip);
    server.on("/", handleRoot);
    server.on("/LEDOn", handleLedOn);
    server.on("/LEDOff", handleLedOff);
    server.on("/Mode1", handleMode1);
    server.on("/Mode2", handleMode2);
    server.on("/Mode3", handleMode3);
    server.on("/Mode4", handleMode4);
    server.on("/Mode5", handleMode5);
    server.on("/Mode6", handleMode6);
	server.on("submit", handleSubmit1);
    server.begin();
    Serial.println("HTTP server beginned");
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, stateLED);
}

void loop() {
    server.handleClient();
}

Ich danke vorab für Eure Hilfe!!

Damit “properties” übergeben werden, musst du ein Formular machen.
Du musst Form-Tags einsetzen - diese “umschließen” ein Formular.

Bei deinen Textfeldern könnte das zum Beispiel so aussehen (ich habe die Form-Tags ergänzt):

const String HtmlTextfields =
    "<form action=\"/\">"
    "R: <input type=\"text\" name=\"input1\" maxlength=\"3\" style=\"width:10%;\" /> G: <input type=\"text\" name=\"input2\" maxlength=\"3\" style=\"width:10%;\" /> B: <input type=\"text\" name=\"input3\" maxlength=\"3\" style=\"width:10%;\" />"
    "<input type=\"submit\" value=\"Sende vollfarben\" style=\"width:25%;\" />"
    "</form>";

Dann werden die Werte, die du bei R, G und B eingibst übertragen (an die URL angehängt).

Wenn du zum Beispiel eingibst
R: 10, G: 20, B:30
und auf “Sende Vollfarben” klickst, dann schaut die URL so aus:
http://192.168.4.1/?input1=10&input2=20&input3=30

Bei der Auswertung helfen dir die in #6 genannten Funktionen (server.args() und so weiter), die du ja schon in deinen Code eingebaut hast.

ihmSelbst: Ich habe jetzt die halbe Nacht versucht die Tipps zu beherzigen, aber es läuft noch immer nicht.

Vielleicht könnt ihr mir sagen was noch immer falsch läuft?

Du solltest evtl. die Antworten lesen, die Du bekommst. Ich hatte Dir bereits in #5 geschrieben, dass Deine Inputs in einen Form-Tag gehören iund Dir auchj ein Beispiel dazu gegeben.

Wenn Du unsere Antworten nicht berücksichtigst, brauchst Du Dich nicht zu wundern, wenn es nicht funktioniert.

Gruß Tommy

Auch ich hatte dir #7 ein Beispiel geschickt aus dem es ersichtlich ist wie es geht.
Hierdeine Eingabe die du für deine Zwecke kürzen musst

String content = "<html><body><form action='/login' method='POST'>To log in, please use : admin/admin
";

  content += "User:<input type='text' name='USERNAME' placeholder='user name'>
";

  content += "Password:<input type='password' name='PASSWORD' placeholder='password'>
";

  content += "<input type='submit' name='SUBMIT' value='Submit'></form>" + msg + "
";

  content += "You also can go <a href='/inline'>here</a></body></html>";

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

Und hier die Auswertung deiner Eingabe

if (server.arg("USERNAME") == "admin" && server.arg("PASSWORD") == "admin" )

Also Kopf abkühlen und dann noch mal los.
Gruß Fips

Vielen Dank, habe es dank Eurer Hilfe hinbekommen!