Archiv verlassen und diese Seite im Standarddesign anzeigen : esp8266, Arduino IDE: neuer Versuch: warum wird website sofort beendet?
hallo,
ich will nochmal einen Anlauf starten:
Board ESP-12E nodeMCU (esp8266),
Arduino Board core nodeMCU 1.0, version 2.5.2
wer kann sagen, warum die hier aufgebaute Website zum Eingeben von username und passwort unter Version 2.5.2 zwar kurz aufgebaut wird, dann aber sofort beendet wird?
Der Fehler tritt unter nodeMCU 1.0, version 2.4.0 noch NICHT auf.
Vermutlich ist ein Fehler drin versteckt, der bei der alten core Version geduldet wird, aber unter der neuen dann doch als Fehler sichtbar wird.
Nur: Wo ist der Fehler?
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
client.flush();
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.print(script);
//stopping client
client.stop();
delay(1);
//clearing string for next read
//readString = "";
}
}
delay(1);
}
}
Website in Firefox:
(Seite wird kurz aufgebaut, dann sofort wieder weg, stattdessen Fehler-Website:
Fehler: Verbindung unterbrochen
Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde.
Die Website könnte vorübergehend nicht erreichbar sein, versuchen Sie es bitte später nochmals.
Wenn Sie auch keine andere Website aufrufen können, überprüfen Sie bitte die Netzwerk-/Internetverbindung.
Wenn Ihr Computer oder Netzwerk von einer Firewall oder einem Proxy geschützt wird, stellen Sie bitte sicher,
dass Firefox auf das Internet zugreifen darf.
Serial Konsole, neuer core:
strupwd >>><<<
website_upwd>>>admin<<<
readString>>>GET /logout HTTP/1.1
GET /logout HTTP/1.1
Bei der alten core Version werden diese 4 Zeilen NICHT seriell ausgegeben, die Login-Seite steht stabil und wartet auf Eingaben.
Wer hat die rettende Idee?
Solang eine Verbindung zum Client besteht, würde ich kein client.stop() senden. Die Disconnect-Nachricht könnte vielleicht daher kommen. Probehalber vor diesem Befehl ein großzügiges delay(x) von mehreren Sekunden einbauen. Sehen, wie sich das Verhalten dann darstellt. Wird die Seite dann aufgebaut, verschwindet aber nach ein paar Sekunden und es erscheint wieder die Disconnect-Message, dann wird es wohl am client.stop() liegen, das die Verbindung unterbricht.
MfG
auch wenns englisch ist
https://forum.arduino.cc/index.php?topic=245829.0
da wird empfohlen auch vor dem stop den empfangspuffer zu leeren!
und das flush gehört natürlich wie Moppi schon sagte direkt vor das stop um sicher zu gehen dass alle Daten transferiert worden sind bevor man den Socket schließt
hallo,
danke, der test hat immerhin schon funktioniert:
Die Seite wird jetzt nach delay(1000) ca. 1 sec lang angezeigt und danach dann abgebrochen mit derselben obigen Fehlermeldung.
Was kann man jetzt machen?
ich korrigiere meine Aussage, erst flush(), dann RX leer machen, dann delay(1000), dann stop()
ich korrigiere meine Aussage, erst flush(), dann RX leer machen, dann delay(1000), dann stop()
danke, nur verstehe ich jetzt noch nicht was genau wohin soll,
kannst du da mal bitte direkt in meinem Code korrigieren und in code tags posten?
edit: was bedeutet z.B. auch "RX leer machen"?
//stopping client
client.flush();
delay(1000); // debug
client.stop();
das macht bis jetzt noch keinen Unterschied (bricht ebenfalls wieder nach ca. 1 sec. ab, ohne delay(1000) auch wieder sofort)...
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.print(script);
//stopping client
client.flush();
delay(1000); // debug
client.stop();
//clearing string for next read
//readString = "";
}
}
delay(1);
}
}
Ich hatte nochmal bei flush() nachgelesen. Mein Verständnis war jetzt so: Es soll Zeichen, die noch nicht übertragen wurden, aus dem Puffer entfernen. Ich würde erst client.print(..), dann delay(...), dann client.flush(), dann client.stop().
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.print(script);
delay(1000); // debug
//stopping client
client.flush();
client.stop();
//clearing string for next read
//readString = "";
}
}
delay(1);
}
}
so?
das macht auch noch genau dieselben Fehler sowohl mit als auch ohne delay(1000);
mal so versuchen:
while (client.connected()){}
client.stop();
statt
delay(1000); // debug
//stopping client
client.flush();
client.stop();
PS: ich habe glaub ich kein nodeMCU mit Version 2.5.x
flush löst nur das senden verbleibender Bytes aus dem FIFO/internen Puffer aus (ungefähr wie beim trennen eines USB DAtenträger um keine Daten im Puffer zu verlieren)
delay kommt danach, da die daten auch erst übertragen werden müssen
dann sollte man folgende Schleife einbauen
while(client.connected()) {
while(client.available()) {
Serial.write(client.read());
}
}
und DANN erst schließen
das Serial.write() ist nur zu Debugzwecken und du kannst einfach in eine dummy variable auslesen wenn die restlichen Daten unwichtig sind, abe erstmal mit Debug Ausgabe um zu wissen ob der Browser überhaupt noch was sendet
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.print(script);
while(client.connected()) {
delay(10);
/*
while(client.available()) {
Serial.write(client.read());
}
*/
}
delay(100);
client.stop(); // edited
//clearing string for next read
//readString = "";
}
}
delay(1);
}
}
jaaa...!
das hat jetzt zum ersten Mal gefunzt! 8)
Das werde ich jetzt ausgiebig testen und dann berichten!
Tausend Dank auf jeden Fall schon einmal an euch beide!
JETZT hast du dein client.close() allerdings auch entfernt, was zu "socketverstopfung" führen kann.
ach so, ich dachte, der soll auch mit weg?
soll der auch direkt dahinter?
while(client.connected()) {
while(client.available()) {
Serial.write(client.read());
}
}
delay(100);
client.stop();
- - - Aktualisiert - - -
PS,
habe es mal so gemacht,
einziger "Schönheitsfehler" jetzt noch: ich muss immer 2x hintereinander auf den "Daten absenden"-Button klicken (oder ENTER-Taste), damit usrname+pwd übertragen werden, aber nach dem 2. mal klappt es jetzt (ohne client.stop() war es auch schon so).
auch wenn ich die while-Schleife ersetze durch
while(client.connected()) {
delay(10);
/* while(client.available()) {
Serial.write(client.read());
}*/
}
ändert sich das nicht.
(Serial ist ja stand-allone nicht mehr verfügbar!)
Ich denke:
Du müsstest Dich entscheiden, ob die Connection zum Client bestehen bleibt oder geschlossen wird.
WiFiClient client = wifiserver.available();
Jetzt kannst Du mittels client mit dem Browser kommunizieren, der eine Verbindung hergestellt hat.
Die Verbindung sollte jetzt bestehen.
Da Du das jedesmal machst, wenn ein Datenaustausch mit dem Client statt gefunden hat, müsstest Du die Verbindung beenden, s. client.stop().
Der Client, also der Browser soll aber wohl wissen müssen, was passieren wird. Dazu sendest Du einen Header:
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
In diesem steht aber nicht, dass die Connection geschlossen werden soll.
Vielleicht mal mit einem korrekten Header anfangen:
script += ("HTTP/1.1 200 OK\r\n");
script += ("Content-Type: text/html\r\n");
script += ("Connection: close\r\n");
...
Von vorne:
Zuerst mit WiFiClient client = wifiserver.available(); ein Objekt holen, dass Kommunikation mit dem Browser erlaubt (Browser hat Connection hergestellt). Das kannst Du zur Not mit if(client)... überprüfen.
Dann prüfen, ob der Browser Daten gesendet hat und diese alle einlesen und verarbeiten.
Wenn fest steht, was er gesendet hat und die Daten (User und Passwort) richtig waren, dann die Seitendaten senden (inkl. dem Header wie oben).
Nach dem Datentransfer dem Browser mit delay(x) etwas Zeit geben, die Daten zu empfangen.
Dann, am Schluss, zum Schließen der Connection client.stop() verwenden.
MfG
Ich denke:
Du müsstest Dich entscheiden, ob die Connection zum Client bestehen bleibt oder geschlossen wird.
WiFiClient client = wifiserver.available();
Jetzt kannst Du mittels client mit dem Browser kommunizieren, der eine Verbindung hergestellt hat.
Die Verbindung sollte jetzt bestehen.
Da Du das jedesmal machst, wenn ein Datenaustausch mit dem Client statt gefunden hat, müsstest Du die Verbindung beenden, s. client.stop().
Der Client, also der Browser soll aber wohl wissen müssen, was passieren wird. Dazu sendest Du einen Header:
script += ("HTTP/1.1 200 OK \n");
script += ("Content-Type: text/html \n");
script += ("\n"); // do not forget this one //????
In diesem steht aber nicht, dass die Connection geschlossen werden soll.
Vielleicht mal mit einem korrekten Header anfangen:
script += ("HTTP/1.1 200 OK\r\n");
script += ("Content-Type: text/html\r\n");
script += ("Connection: close\r\n");
...
Von vorne:
Zuerst mit WiFiClient client = wifiserver.available(); ein Objekt holen, dass Kommunikation mit dem Browser erlaubt (Browser hat Connection hergestellt). Das kannst Du zur Not mit if(client)... überprüfen.
Dann prüfen, ob der Browser Daten gesendet hat und diese alle einlesen und verarbeiten.
Wenn fest steht, was er gesendet hat und die Daten (User und Passwort) richtig waren, dann die Seitendaten senden (inkl. dem Header wie oben).
Nach dem Datentransfer dem Browser mit delay(x) etwas Zeit geben, die Daten zu empfangen.
Dann, am Schluss, zum Schließen der Connection client.stop() verwenden.
MfG
hi,
WiFiClient client = wifiserver.available();
habe ich ja schon ganz oben im Code stehen.
Ich habe nun die alten 3 Codezeilen durch die 3 neuen ersetzt, allerdings baut er jetzt gar keine website mehr auf - was habe ich übersehen? (ggf: wie lautet der komplette neue Code, falls nicht nur 1 Zeile betroffen ist?)
ich habs mal etwas umgestellt - versuch das mal:
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
if (client) {
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
//client.flush();
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK\r\n");
script += ("Content-Type: text/html\r\n");
script += ("Connection: close\r\n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.println(script);
delay(100);
//stopping client
client.stop();
//clearing string for next read
//readString = "";
}
}
//delay(1);
}
}
}
leider springt er jetzt sofort wieder raus, wie ganz am Anfang,
und wenn ich einsetze vor client.stop();
//stopping client
while(client.connected()) {
delay(10);
}
client.stop();
dann baut er sie auf, beibt aber ewig drin hängen, auch nach korrektem login+pwd :(
strupwd und struname werden doch überhaupt nicht aus dem gelesenen String readString extrahiert, aber anschließend verglichen und dann davon abhängig gemacht, ob authorized = true;
Das haut irgendwie hinten und vorne noch nicht hin.
dieser Teil mit der Extrahierung von strupwd und struname ist hier nur verkürzt wiedergegeben, um die Lesbarkeit zu erhöhen, meine eigene Methode ist recht kompliziert.
Wie würdest DU diese Extrahierung samt Vergleich machen, und, wo wir gerade dabei sind, ggf. mit POST anstelle von GET?
Vieleicht liegt ja tatsächlich hier der Hase im Pfeffer...?
ich habs nochmals geändert und ein Schnipsel eingefügt:
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
if (client) {
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
while ( c != '\n') {
c = client.read();
}
if (c == '\n') {
//client.flush();
//now output html data header
String script = "";
script += ("HTTP/1.1 200 OK\r\n");
script += ("Content-Type: text/html\r\n");
script += ("Connection: close\r\n");
script += ("\n"); // do not forget this one //????
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
client.println(script);
delay(100);
//stopping client
client.stop();
//clearing string for next read
//readString = "";
}
}
//delay(1);
}
}
}
entscheidend ist, dass die Seite jedesmal angezeigt wird, wenn der Browser eine Anfrage an den Server stellt. Denn erst dann kann man das Passwort eingeben und den Namen, was dann ausgewertet werden muss.
Ob das Passwort stimmt oder ob der Vergleich dazu hinhaut wissen wir nicht, weil der Teil fehlt. Man kann das umschreiben, ich habe aber nicht die Möglichkeit, das mit 2.5.x zu probieren - glaub ich.
Muss mal sehen. Das kann so schwer nicht sein.
in dieser Form springt es wieder sofort aus der Website raus, wie ganz am Anfang.
- - - Aktualisiert - - -
mit
while(client.connected()) {
delay(10);
}
client.stop();
baut er wieder auf, bleibt aber auch wieder komplett im Formular hängen (wie zuvor)
wie lese ich diese version beim nodemcu aus?
Werkzeuge => Board => Boardverwalter =>....
dann in der Eingabezeile
nodeMCU
eingeben
dann steht die Version ganz oben im Feld, Version auswählen ganz unten
34420
34418
habe 2.2.0, update wird geladen
jetzt 2.5.2
beim nächsten Programmupload auf das Board dann hoffentlich 2.5.2
Ich bin mir zwar nicht sicher was du genau bezwecken willst, aber ich würde erstmal versuchen zu verstehen was ich für ein Verhalten erwarte, mich darüber schlau machen wie Browser sich in der gegebenen Situation verhalten und wie ich meinen Code bauen muss damit es auch mit jedem Browser überall funktioniert.
Webseiten darstellen ist kein Problem, man akzeptiert einen Client, ließt die Anfrage per client.read() aus, sucht die passende Webseite für die aufgerufene Adresse und gibt den HTML code zurück, flush, stop und fertig ist der Lack, das sollte auch einfach so ohne irgendwelche Probleme funktionieren.
Webaufrufe mit Daten vom Browser zum Server geht per GET oder POST, wobei man die GET Daten auch sofort übermitteln kann, sofern man weis was man eingeben muss.
Per POST braucht es erst ein Formular, welches man vorher auch zum Client senden muss, dafür braucht es also 2 Anfragen, die erste Anfrage welche die Webseite mit dem Formular an den client sendet und die 2te Anfrage als Action mit POST und dem ausgefüllten Formular.
Was du also schreiben musst ist eine Schleife, welche (sofern die Verbindung zum Browser offen hält mit wie Moppi schon beschrieben hatte, was allerdings auch nicht garantiert ist) immer client.read() benutzt um Anfragen zu empfangen, auszuwerten und zu verarbeiten und zu beantworten.
Zu jeder Anfrage muss es auch eine Webseite als Antwort geben, sonst beschwert sich dein Browser wie in deinem Fall dass der Server die Verbindung geschlossen hat!
Was du brauchst ist ein strukturierterer Ansatz für deine Aufgabe. Außerdem solltest du dich mit einfachen Session-Cookies beschäftigen, sonst bekomst du spätestens dann Probleme wenn du längere Zeit auf der Webseite bist, weil dein Browser irgendwann den Socket von sich aus schließt und du einen neuen "client" bekommst den du dann wieder neu authentifizieren musst. (oder du speicherst dir die IP des client als trick, aber das ist bei leibe nicht sicher und nur als workaround gemeint!!!!!!!)
--------------
Am besten schreibst du erstmal einen dummen Server, welcher Browseranfragen annimmt und an den Browser zurück spiegelt um erstmale in Gefühl für die Anfragen zu bekommen.
Wenn das klappt, braust du dir eine einfache Webseite zusammen, welche bei der richtigen Adresse auch ausgegeben wird.
Dann baust du in einer der Seiten einen Knopf für eine GET und einen Knopf + Formular für eine POST Anfrage ein.
Auf jeder Seite lässt du Platz um den Inhalt der Anfrage zu posten und auf Anfragen die du nicht lesen kannst Antwortest du dem Browser wie beim ersten Schritt mit der Anfrage als Antwort um zu verstehen was genau der Browser da gesendet hat.
So hangelst du dich dann bei deinem Adress-Parser langsam vorwärst und musst nicht in einem einzelnen Codeblock rumstricken
naja, es funktioniert doch im Prinzip, bis auf einen "Schönheitsfehler", username wird korrekt geprüft und pwd auch - zumindest in der Version Seite 2 oben
https://www.roboternetz.de/community/threads/74132-esp8266-Arduino-IDE-neuer-Versuch-warum-wird-website-sofort-beendet?p=655516&viewfull=1#post655516 ,
und auch wenn man hier noch 2x hintereinander ENTER drücken muss.
Diesen Schönheitsfehler gilt es nun zufinden und ebenfalls auszumerzen - unter core 2.4.0 hat es ja auch noch 100%ig funktioniert.
Sehr schön wäre es auch, wenn man GET durch POST ersetzen könnte.
Cookies will ich keine setzen.
Deine sehr allgemeinen Tipps kann ich allerdings nicht umsetzen, mein Ursprungscode war bereits so leistungsfähig wie ich es überhaupt verstehen und schreiben konnte - für einen ganz neu geschriebenen Code wäre ich ntl auch sehr dankbar ;).
Ich habe oben mal eine Empfehlung ergänzt wie du dich an deine konkrete Problematik heranarbeiten kannst.
Ich wollte eigentlich nur so höflich wie möglich darauf hinweisen dass man mit dem Code wie er ist nicht unbedingt weiterarbeiten sollte und nochmal sauber neu anfangen sollte weil amn sonst mit Phänomenen und Seiteneffekten arbeitet die nicht im geringsten Hilfreich für das Verständnis sind.
Ich schlage vor du schreibst einfach nochmal ein neues Beispiel welches nichts weiter macht als Anfragen entgegen zu nehmen und diese als HTML oder Text an den Browser zurück spiegelt.
Mit dem String den du da spiegelst kannst du dann einen Parser bauen um die Anfrage auszuwerten und entsprechend Webseiten auszugeben.
Wenn das klappt, kannst du dir dann eine POST und GET Anfrage in einer deiner Webseiten einbauen und spiegeln lassen um deinen Parser zu erweitern
edit: ich versuche hier nur mal einen kleinen Objektorientierten Ansatz für das Verständnis
Ich bin der Server und du der Browser, du kannst mich entweder mit der Zimmernummer und dem Geheimen Passwort ansprechen (GET mit Daten in der Aufrufzeile ... unsicher weil Klartext) und ich lasse dich rein
oder du musst erstmal mich fragen ob ich dir das Klemmbrett(Webseite) mit dem Login Formular gebe (GET) damit du es mir ausgefüllt zurück geben kannst (POST)
In jedem Fall muss ich wissen wer du bist und solange ich dich sehe (offener Socket) weis ich auch dass die Formulardaten oder Anfragen von dir sind. Wenn du allerdings nur einmal außer Sichtweite gehst muss ich annehmen dass du nicht mehr du bist oder du dich mir gegenüber ausweist.
ich selber kann es nicht besser und ich würde es momentan auch nicht anders machen, so wie ich das Prinzip verstehe
- vlt hat Moppi ja mit seiner Version noch etwas mehr Erfolg, denn die letzte hängt ja auch wieder.
Wir hatten das Thema ja schon öfter - ich brauche keine allgemeinen Ratschläge, was ich brauche, sondern Code, der kompilierbar ist und den ich testen kann.
Konkrete Codevorschläge also immer gerne! 8)
Das Problem ist, dass du noch nicht mal die Grundlage zu verstehen scheinst wenn man den Code ansieht. (nicht bös gemeint) Du verarbeitest nicht mal die Anfrage sondern wartest einfach auf "irgendeine" Anfrage und spuckst die Webseite aus.
Wenn du jemals authorized auf true setzt sollte der Browser theoretisch nie wieder antworten weil der client schon nach dem verbinden sofort mit einem return abgewürgt wird.
wie gesagt, es funktioniert alles bis core 2.4.0, erst danch nicht mehr.
Sogar jetzt aber geht das Einloggen und Ausloggen (aus der Haupt-html-Seite) einwandfrei, denn dadurch wird authorized wieder auf false gesetzt.
Je nachdem,, wie authorized gesetzt ist, wird im Hauptprogramm (loop() ) entweder die Login Seite aufgerufen oder die Haupt-Website.
Wirklich hilfreich ist jetzt tatsächlich nur funktionierender Code für core 2.5.2
Je nachdem,, wie authorized gesetzt ist, wird im Hauptprogramm (loop() ) entweder die Login Seite aufgerufen oder die Haupt-Website.
ah okay das war aus dem code auf seite 1 jetzt irgendwie nicht ersichtlich :D
Wirklich hilfreich ist jetzt tatsächlich nur funktionierender Code für core 2.5.2
dafür müsste ich erstmal arbeiten wenn du verstehst was ich meine :)
tatsächlich lese ich aber auch die Eingabe aus und verarbeite sie (was ja auch funktioniert):
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// hier fehlt ein kleiner Teil fürs Parsen:
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{...}
wenn du aber hier nicht am Code mit-arbeiten willst, dann herzlichen Dank bis hierhin... :)
naja du versuchst das passwort und den usernamen zu finden aber du wertest nicht wirklich effektiv den aufruf aus und damit fehlt dir schonmal das grundlegende verständnis wie anfragen aussehen udn funktionieren
man kann nicht alles einfach so abkürzen oder muss sich einer library bedienen
wenn du aber hier nicht am Code mit-arbeiten willst, dann herzlichen Dank bis hierhin...
warum versuche ich dir gegenüber überhaupt noch freundlich zu sein wenn du einem immer die Tür ins Kreuz schlägst ... merkst du es eigentlich noch? Renn halt gegen deine selbst gemauerte Wand bis dir der Schädel platzt...
s.o., ich habe dafür eigene Funktionen
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
ich brauche nun konkrete Codevorschläge...
ich warte mal, ob Moppi noch was einfällt.
Ich habe mit der 2.5.2 auch Probleme. Opera zeigt den Seiteninhalt an, aber dafür hängt das nodeMCU. Firefox bringt die Meldung mit dem Reset, zeigt den Inhalt nicht an, dafür hängt das nodeMCU nicht.
Habe den Beispielcode von hier verwendet und etwas angepasst, damit bei mir der Login im WLAN funktioniert: https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/server-examples.html
Original funktioniert dieser Code gar nicht, weil der auf "\n" wartet und wo er es tut, kommt irgendwas durcheinander.
MfG
bei mir haben alle Versionen seit 2.4.0 das geschilderte "Problem", irgendwie scheinen die eher für Fehler oder Ungenauigkeiten im Code anfällig zu sein - trotzdem müsste man es zum Laufen kriegen, sonst würden sie ja auch unter 2.4.0 nicht laufen.
- - - Aktualisiert - - -
PS,
hier übrigens meine Parserfunktionen, um username + pwd herauszufiltern:
//----------------------------------------------------------------------------
// String functions
//----------------------------------------------------------------------------
int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}
//-------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;
//-------------------------------------------------------
char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
const char* kini = "&"; // start of varname: '&'
const char* kin2 = "?"; // start of varname: '?'
const char* kequ = "="; // end of varname, start of argument: '='
char needle[TOKLEN] = ""; // complete pattern: &varname=abc1234
strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) {
needle[0]=kin2[0];
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
}
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' ')||(ch=='\0') ||(ch=='\n')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}
// *SNIP*
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd
sie funktionieren sehr gut, und sehr wschl liegt hier wirklich nicht das Problem - lasse mich aber gern vom Gegenteil überzeugen!
Ja, schon. Bloß wenn Ivan Grokhotkov keinen lauffähigen Code hinbekommt ...
:)
Kannst Du bis auf die Grundfesten alles auseinandernehmen, das kann Wochen oder Monate dauern.
Probleme mit Datentypen, Steuerzeichen, Formaten ....
Ja, schon. Bloß wenn Ivan Grokhotkov keinen lauffähigen Code hinbekommt ...
:)
...der ja auch nicht viel anders aussieht als unserer hier... :roll:
Das Problem liegt in der Übertragung zum Browser oder am Inhalt selber. Kann nicht sein, dass ein Browser zwar den Inhalt anzeigt, aber das nodeMCU (vmtl. während der Kommuniaktion) hängen bleibt und ein anderer Browser den Inhalt gar nicht anzeigt und ihn also nicht interpretieren kann, dafür aber das nodeMCU nicht hängt.
Bei mir funktioniert es ab dieser Stelle z.B. gar nicht, mit keinem der beiden Browser:
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n')
immerhin funktioniert ja die Version auf S. 2
https://www.roboternetz.de/community/threads/74132-esp8266-Arduino-IDE-neuer-Versuch-warum-wird-website-sofort-beendet?p=655516&viewfull=1#post655516
schon ziemlich gut, danke noch mal
- vlt fällt ja jemand noch was ein wegen des 2x Enter- oder Button-drücken müssens... 8)
letzteres passiert, wenn eine Eingabe verloren geht. Oder das Programm wartet auf Zeichen, kann die Übertragenen nicht zuordnen und verwirft sie - und erst beim nächsten Mal klappts wieder. Das kann auch dort passieren, wo Du das Passwort und den User extrahierst (bzw. die Zeichen dafür einliest).
ja, ich denke da auch an das endofline-Zeichen \n vs. \r\n etc...
es geht aber nicht zufällig verloren, sondern immer das 1. Mal und immer nur das 1. Mal, und beim 2. Mal klappt es immer!
@Moppi:
wie gehst du jetzt mit deinem Fehler bei der 2.5.2 um? gehst du wieder zurück auf 2.2.x oder 2.4.x oder versuchst du, es unter dem neuen Core zum Laufen zu kriegen?
(Es sind ja auch etliche Bug Fixes und neue Funktionen seit 2.5.x dazu gekommen sowie veränderte ältere Wifiserver und Websever Lbs im githiub repo https://github.com/espressif/arduino-esp32)
Keine Ahnung, HaWe, ich brauchs momentan nicht und würde später nochmal ein Update ausführen.
Obwohl interessant wärs, wie sich der Code, den ich hatte, unter Version 2.4.x verhält.
Aber mit etwas Zeit würde ich noch etwas herumprobieren, Senden und Empfangen funktioniert vom Prinzip, das sieht nach einem Kommunikationsproblem aus. Hatte schon überlegt, genau zu schauen welche Bytes ankommen und auch selber Funktionen zu schreiben, um die zu verschicken, damit ich genau weiß, was da passiert.
Ich verwende nur die ESP8266WiFi.h
Mich würde jetzt interessieren, ob es bei Dir besser läuft jetzt. Das Problem mit dem doppelten Senden müsste man noch hinbekommen können, muss man suchen..
MfG
Login wie gehabt 2x.
Ansonsten klappt die Kommunikation zu anderen esp8266 Web Clients einwandfrei, auch zu UDP Servern.
(Version wie auf S.2 oben (editierte Version)
Das Beispielprogramm von Ivan funktioniert sehr gut. Unter Version 2.2.0. Nicht jedoch unter 2.5.2 - dort kommt es zu den Fehlern!
Lager doch mal Deine Routine, die Passwort und Username extrahier, in eine extra Funktion aus und binde die dann via Funktionsaufruf in dem Code ein, an dem wir gestern herumgespielt haben. Dann kann man gezielt suchen.
MfG
ja, ähnlich wie bei mir vorher...
- - - Aktualisiert - - -
Probier doch auch mal 2.4.0, ich wette, da läuft auch der Ivan bei dir! 8)
2.5.2 funktioniert nicht
2.4.2 funktioniert nicht
2.4.1 funktioniert nicht
2.4.0 funktioniert
2.4.1 funktioniert auch nicht bei mir, nur bis 2.4.0
über mehrere Versionen hinweg funktioniert es schon nicht mehr, dass das keinem auffällt?
String line = client.readStringUntil('\r');
Serial.print(line);
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n')
könnte in diesem Zusammenhang an readStringUntil() liegen, bzw. dem, was darin verwendet wird und sich seit Version 2.4.0 geändert hat.
doch, bei den issues gab es schon Meldungen, aber die neuen original-examples von esp klappten ja wieder weiterhin - nur für Code von anderen wie von Ivan oder von mir übernehmen die esp Leute keinen Support und verweisen aufs esp Forum. Ohne erkennbare Lösung, soweit ich es sehe.
Ich finde aber auch im esp32 repo keine original-esp-Codebeispiele für Eingabe von Strings per GET oder POST.
- - - Aktualisiert - - -
ich selber verwende ja nicht Ivans examples, aber nachdem du ja damit Erfahrung hast: melde doch mal deine Probleme mit 2.4.x ++ in Ivans issues!
hier ist ja deine/Ivans (?) repo bei github: https://github.com/esp8266/Arduino/blob/master/doc/esp8266wifi/server-examples.rst
Wie es aussieht, gibt es (auch) ein Problem beim Senden der Daten an den Browser.
Opera stellt den Seiteninhalt dar, mach aber kein Refresh mehr. Da scheint beim Header was falsch zu sein, was am Browser ankommt (im Arduino-IDE-Quelltext ändert der sich ja nicht).
Firefox hat dann auch ein Problem und zeigt gar nichts an, wundert sich nur, dass die Connection beendet (reset) wird und bringt die Meldung (macht nat. dann auch kein Refresh der Seite).
Was ist denn "original-esp" ??? Welche LIBs gehören dazu und wo ist dazu die Doku??? - Dann benutzt man eben nur diese Sachen.
ja, so etwas hast du ja oben schon gesschrieben.
Hast du die aktuelle Version des Codes verwendet?
https://github.com/esp8266/Arduino/blob/master/doc/esp8266wifi/server-examples.rst
Hast du die aktuelle Version des Codes verwendet?
Sieht danach aus
komplett so, unverändert?
#include <ESP8266WiFi.h>
const char* ssid = "********";
const char* password = "********";
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.printf("Connecting to %s ", ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
server.begin();
Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str());
}
// prepare a web page to be send to a client (web browser)
String prepareHtmlPage()
{
String htmlPage =
String("HTTP/1.1 200 OK\r\n") +
"Content-Type: text/html\r\n" +
"Connection: close\r\n" + // the connection will be closed after completion of the response
"Refresh: 5\r\n" + // refresh the page automatically every 5 sec
"\r\n" +
"<!DOCTYPE HTML>" +
"<html>" +
"Analog input: " + String(analogRead(A0)) +
"</html>" +
"\r\n";
return htmlPage;
}
void loop()
{
WiFiClient client = server.available();
// wait for a client (web browser) to connect
if (client)
{
Serial.println("\n[Client connected]");
while (client.connected())
{
// read line by line what the client (web browser) is requesting
if (client.available())
{
String line = client.readStringUntil('\r');
Serial.print(line);
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n')
{
client.println(prepareHtmlPage());
break;
}
}
}
delay(1); // give the web browser time to receive the data
// close the connection:
client.stop();
Serial.println("[Client disonnected]");
}
}
oh, ich hab was gefunden. muss noch mit 2.5.2 überprüfen.
ok, alles klar so weit:
Ab Version 2.4.1 muss zwingend im Response-Header, im Arduino-IDE-Quelltext "Content-Length" angegeben werden, damit der Browser weiß, auf wieviele Zeichen er vom Server wartet.
Gut möglich, dass das vorher automatisch irgendwo hinzugefügt worden ist, aber ab Version 2.4.1 nicht mehr.
Update:
ich habe den Code jtzt auf einem neuen esp8266 selber getestet, und tatsächlich tritt es auch bei mir so auf wie bei dir (Firefox):
2.2.0: läuft, website:
Analog input 2
2.5.2: sofortiger Abbruch,
Fehler: Verbindung unterbrochen
Die Verbindung zum Server wurde zurückgesetzt, während die Seite geladen wurde.
Die Website könnte vorübergehend nicht erreichbar sein, versuchen Sie es bitte später nochmals.
Wenn Sie auch keine andere Website aufrufen können, überprüfen Sie bitte die Netzwerk-/Internetverbindung.
Wenn Ihr Computer oder Netzwerk von einer Firewall oder einem Proxy geschützt wird, stellen Sie bitte sicher, dass Firefox auf das Internet zugreifen darf.
ich habe jetzt hier einen issue eröffnet: https://github.com/esp8266/Arduino/issues/6661
nimm mal den Quelltext:
#include <ESP8266WiFi.h>
//#include <ESP8266WebServer.h>
//#include <FS.h> // muss vor <detail\RequestHandlersImpl.h> stehen
//#include <detail\RequestHandlersImpl.h>
String ssid = "...";
String password = "...";
//ESP8266WebServer webserver(80); // Webserver-Instanz f�r Port 80 erstellen
WiFiServer server(80);
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.println("Connecting to " + ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), password.c_str());
WiFi.config(IPAddress(xxx,xxx,xxx,xx), IPAddress(xxx,xxx,xxx,xxx), IPAddress(xxx,xxx,xxx,xxx), IPAddress(xxx,xxx,xxx,xxx));
//WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
delay(500);
Serial.print(".");
}
Serial.println(" connected");
server.begin();
Serial.printf("Web server started, open %s in a web browser\n", WiFi.localIP().toString().c_str());
}
// prepare a web page to be send to a client (web browser)
String prepareHtmlPage()
{
String htmlPage =
String("HTTP/1.1 200 OK\r\n") +
"Content-Length: 44\r\n"+
"Content-Type: text/html\r\n" +
"Connection: close\r\n" + // the connection will be closed after completion of the response
"Refresh: 5\r\n" + // refresh the page automatically every 5 sec
"\r\n" +
"<!DOCTYPE html>" +
"<html>" +
"Analog input: " + String(analogRead(A0)) +
"</html>" +
"\r\n";
return htmlPage;
}
void loop()
{
WiFiClient client = server.available();
// wait for a client (web browser) to connect
if (client)
{
Serial.println("\n[Client connected]");
while (client.connected())
{
// read line by line what the client (web browser) is requesting
if (client.available())
{
String line = client.readStringUntil('\r');
Serial.print(line);
// wait for end of client's request, that is marked with an empty line
if (line.length() == 1 && line[0] == '\n')
{
client.println(prepareHtmlPage());
delay(100); // give the web browser time to receive the data
// close the connection:
client.stop();
Serial.println("[Client disonnected]");
break;
}
}
}
}
}
ja, funktioniert jetzt mit 2.5.2 (habe WiFi.config() momentan auskommentiert)
was ist passiert?
weiter oben lesen: https://www.roboternetz.de/community/threads/74132-esp8266-Arduino-IDE-neuer-Versuch-warum-wird-website-sofort-beendet?p=655595&viewfull=1#post655595
- - - Aktualisiert - - -
@hawe
habe Deinen ersten Quelltext, nach den neuen Erkenntnissen, nochmals modifiziert:
bool authorized=false;
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
//---------------------------------------
// debug
// authorized=true;
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
readString.toCharArray(strinput, MAXLEN);
// cstringarg(strinput, "uname", struname); // uname
// cstringarg(strinput, "upwd", strupwd); // upwd
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
{
authorized = true;
readString = "";
return;
// return; // <<< selbes Ergebnis, egal ob kommentiert oder auskommentiert
}
//if HTTP request has ended
if (c == '\n') {
client.flush();
//now output html data header
String script="";
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
//----------------------------------
String script1 = "";
script1 += ("HTTP/1.1 200 OK \n");
script1 += ("Content-Type: text/html \n");
script1 += ("Content-Length: ") + script.length() + ("\n");
script1 += ("\n"); // do not forget this one //????
script = script1+script;
client.print(script);
delay(100);
//stopping client
client.stop();
//clearing string for next read
//readString = "";
}
}
delay(1);
}
}
KORREKTUR !!
update:
ich hatte noch das alte
while(client.connected()) {
delay(10);
}
vor dem client.close() mit drin, aber nun rausgelöscht....:
UND JETZT schaltet er korrekt nach dem 1. Enter/Button Click durch!
4x nachgetestet, nach Neustart und zwischen-Abort, immer ok!
Ich verneige mich - und werde es jetzt noch über ein paar Stunden weiter testen+beobachten!
Tausend Dank! 8)
Hä?
Verstehe ich nicht. Wo hattest Du client.close() drinnen?
Wie sieht der Code jetzt aus, wo es funktioniert?
MfG
äh, sorry, vor
// close the connection:
client.stop();
der "echte" ungekürzte Code ist dieser hier:
void handleNotAuthorized() {
String readString = "";
char strinput[MAXLEN], strupwd[TOKLEN], struname[TOKLEN] ;
WiFiClient client = wifiserver.available();
strcpy(strinput, "");
strcpy(strupwd, "");
strcpy(struname, "");
while ( client.connected() ) {
if (authorized) return;
if ( client.available() ) {
char c = client.read();
//read char by request
readString = "";
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
if(strstr(website_upwd,strupwd)!=NULL & strstr(website_uname,struname)!=NULL)
readString.toCharArray(strinput, MAXLEN);
// cstringarg( char* haystack, char* vname, char* sarg )
// haystack pattern: &varname=1234abc, delimiters &, \n, \0, SPACE, EOF
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd
// debug
Serial.print("strupwd >>>"); Serial.print(strupwd); Serial.println("<<<");
Serial.print("website_upwd>>>"); Serial.print(website_upwd); Serial.println("<<<");
Serial.print("readString>>>");Serial.println(readString);
if ( (strlen(strupwd)==strlen(website_upwd)) && (strcmp(website_upwd, strupwd)==0)
&& (strlen(struname)==strlen(website_uname)) && (strcmp(website_uname, struname)==0)
)
{
authorized = true;
readString = "";
return;
}
//if HTTP request has ended
if (c == '\n') {
client.flush();
//now output html data header
String script="";
script += ("<!DOCTYPE html> \n");
script += ("<html> \n");
script += ("<head> \n");
// utf-8 für "°" Zeichen
script += "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"> \n" ;
script += "<title>" ;
script += "</title> \n" ;
script += "</head> \n" ;
script += "<body> \n" ;
script += ("<h2><p style=\"color:rgb(255,0,191);\"> log in to proceed: </p> </h2> \n");
script += ("<FORM ACTION='/' method=GET > \n");
script += ("<h2>user name: <INPUT TYPE=text NAME='uname' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2>password : <INPUT TYPE=PASSWORD NAME='upwd' VALUE='' MAXLENGTH='50'> </h2> \n");
script += ("<h2><INPUT TYPE=SUBMIT></h2> \n");
script += ("</FORM> \n");
script += ("<BR> \n");
script += ("</body> \n");
script += ("</html> \n");
//----------------------------------
String script1 = "";
script1 += "HTTP/1.1 200 OK \n";
script1 += "Content-Type: text/html \n";
script1 += "Content-Length: " + (String)script.length() + "\n";
script1 += "\n"; // do not forget this one //????
script = script1+script;
client.print(script);
delay(100);
//stopping client
/*
while(client.connected()) {
delay(10);
}
*/
client.stop();
}
}
delay(1);
}
}
Warum so: (String)script.length()
bei mir funktionierte das auch ohne das "(String)"
???
PS: gib mal: "(String)" bei google ein, mit Gänsefüßchen oder ohne! :):)
:p
bei mir ging es zunächst nicht, aber es stört jetzt auch nicht weiter ;)
Soll das (String) extra in String konvertieren?
ja, genau, habe es noch mal getestet und dann kommt ohne (String):
ESP8266_ServerHomeWebMail_078:1273:59: error: invalid operands of types 'const char*' and 'const char [2]' to binary 'operator+'
script1 += "Content-Length: " + script.length() + "\n";
was ja eigentlich verständlich ist, denn lenghth() ist ja eine Zahl, die man nicht an cstrings addieren kann.
Ok. Gut! Danke! Hatte so etwas ähnliches im Hinterkopf. Nur es gibt Funktionen, wo man es nicht extra konvertieren muss. Hätte auch mit String(script.length(), DEZ) oder schlicht mit String(script.length()) funktioniert?
Jetzt können wir jedenfalls 2.5.2 weiter verwenden.
ja, String(...) funktioniert auch als Funktion, (String) ist ein explizites typecasting.
Und ja, ich freue mich auch sehr, dass jetzt de 2.5.2 funktioniert!
Nochmals vielen Dank für die erfolgreiche Mitarbeit und Hilfe!
PS,
ein Randproblem: wie lösen eigentlich Arduinorianer das Extrahieren des eingegeben Strings?
das ist zwar etwas, das ich gelöst habe mit eigenen Funktionen, aber ich kann mir ehrlich gessagt nicht vorstellen, dass es da bei Arduino noch keine fertige Funktion gibt...?
//----------------------------------------------------------------------------
// String functions
//----------------------------------------------------------------------------
int16_t strstrpos(char * haystack, char * needle) // find 1st occurance of substr in str
{
char *p = strstr(haystack, needle);
if (p) return p - haystack;
return -1; // Not found = -1.
}
//-------------------------------------------------------
const int MAXLEN = 1024;
const int TOKLEN = 64;
//-------------------------------------------------------
char * cstringarg( char* haystack, char* vname, char* sarg ) {
int i=0, pos=-1;
unsigned char ch=0xff;
const char* kini = "&"; // start of varname: '&'
const char* kin2 = "?"; // start of varname: '?'
const char* kequ = "="; // end of varname, start of argument: '='
char needle[TOKLEN] = ""; // complete pattern: &varname=abc1234
strcpy(sarg,"");
strcpy(needle, kini);
strcat(needle, vname);
strcat(needle, kequ);
pos = strstrpos(haystack, needle);
if(pos==-1) {
needle[0]=kin2[0];
pos = strstrpos(haystack, needle);
if(pos==-1) return sarg;
}
pos=pos+strlen(vname)+2; // start of value = kini+vname+kequ
while( (ch!='&')&&(ch!='\0') ) {
ch=haystack[pos+i];
if( (ch=='&')||(ch==';')||(ch==' \n')||(ch=='\r') ||(ch=='\0')
||(i+pos>=strlen(haystack))||(i>TOKLEN-1) ) {
sarg[i]='\0';
return sarg;
}
if( (ch!='&') ) {
sarg[i]=ch;
i++;
}
}
return sarg;
}
// *SNIP*
cstringarg(strinput, "uname", struname); // uname
cstringarg(strinput, "upwd", strupwd); // upwd
if ( (strlen(strupwd)==strlen(website_upwd)) && (strcmp(website_upwd, strupwd)==0)
&& (strlen(struname)==strlen(website_uname)) && (strcmp(website_uname, struname)==0)
)
{
//...
}
Mit String-Funktionen.
Normalerweise geht das sinngemäß:
1. Liefere erstes Vorkommen eines Zeichens in Zeichenkette
2. extrahiere aus erster Zeichenkette eine Neue, von Position bis Position
3. suche in neuer Zeichenkette nach Zeichen, dass das Ende markiert
4. extrahiere vom Anfang der Zeichenkette bis zu der Position des Endezeichens
5. gewünschter Inhalt ist extrahiert
Zwei Methoden für Strings habe ich für Arduino schon gefunden:
- indexOf()
- lastIndexOf()
interessant auch:
- substring()
indexOf() findet die Position eines gesuchten Zeichens
substring() extrahiert eine Zeichenkette anhand einer Start- und Endposition
Arduino.cc, TUTORIALS (https://www.arduino.cc/en/Tutorial/HomePage)> Built-In Examples (https://www.arduino.cc/en/Tutorial/BuiltInExamples)> 08.Strings
ja, so schrittweise habe ich es ja prinzipiell auch gemacht in meinen Funktionen, ich meinte aber fertige Arduino-Funktionen, die prinzipiell alles komplett erledigen ( allerdings bei mir mit ISO C ctrings, nicht C++ Strings)
Musst Du eine Funktion schreiben, dies das dann erledigt, wie Du das brauchst. Oder vielleicht gibt es eine fertige Bibliothek schon?
Braucht man aber auch nicht wirklich. Wenn man die Zeichenkette kennt, die kommt, also weiß, wo Start- und Endzeichen sind, kann man so einen Ausdruck in einer Codezeile formulieren.
MfG
zum Beispiel:
Wenn der String so vom Browser, per GET, übermittelt wird:
?uname=...&upwd=...
Dann kann die ganze Zeile eingelesen werden mit:
String rS = client.readStringUntil('\r');
Und das Extrahieren der Informationen in der richtigen Reihenfolge, wenn nur zwei Felder existieren, könnte dann so funktionieren:
String website_uname = rS.substring(rS.indexOf('=')+1,rS.indexOf('&'));
String website_upwd = rS.substring(rS.lastIndexOf('=')+1);
Sollen die Feldbezeichnungen überprüft werden, stehen die Feldbezeichnungen und deren inhalte (upwd=...) in anderer Reihenfolge, soll die Funktion Inhalte, beliebig übermittelter Formularfelder, extrahieren? - Dann wird das Vorgehen natürlich komplizierter.
MfG
PS: der Code ist nur beispielhaft, habe nicht verifiziert, ob er so fehlerfrei compiliert wird. Soll nur der Anschauung dienen, wie es gemeint ist.
nein, es ging doch nicht darum, so eine Funktion aus Einzel-Schritten neu zu schreiben, genau das habe ich doch bereits getan (cstringarg() ).
Es ging darum, ob Arduino so etwas wie mein cstringarg() bereits fertig für diese und ähnliche Zwecke zur Verfügung stellt, das würde es für komplette Anfänger einfacher machen und es müsste nicht jeder das Rad neu erfinden.
Ich hatte Dich schon richtig verstanden, ich kenne doch Deinen Quellcode mit dem cstringarg() wo wir lange dran gebastelt haben, weil da auch was im argen war. Da kamen auch noch in andern Foren Fragen dazu auf.
Anfänger und Arduino-"Bordmittel", da würde ich schon so etwas hernehmen: rS.substring(rS.indexOf('=')+1,rS.indexOf('&'));
Ist auch für Anfänger einfach zu verstehen, ist ja nichts besonderes dran. Das Rad ist ja damit schon erfunden. Das sind gängige Lösungen, die Du überall antriffst (C++,Java,JavaScript ..).
Man muss noch was anderes bedenken:
Für so kleine Aufgaben lohnt es nicht, viel Overhead dazu zu packen, was den Gesamtquellcode und das fertige Kompilat unnötig aufblähen würde. Solche Universalmethoden (bei Objekten) belegen eine Menge Platz, nur, damit es einen kleinen Tacken bequemer ist. Damit belegst Du dann ein Vielfaches an Speicherplatz mehr, mal von der Rechenzeit / Taktzyklen abgesehen. Für seine eigenen Zwecke kann man das in eine Funktion packen, um das nicht immer neu schreiben zu müssen. Allerdings ist der Funktionsaufruf, in Gänze, dann vermutlich kaum kürzer.
MfG
mit cstringarg() lag nichts "m Argen", das funktionierte von Anfang an bis jetzt einwandfrei, und es kann ja vielfache verschiedene Variablen über ihre verschiedenen Namen und samt ihrer verschiedenen Werte aus sehr langen zusammengesetzten cstrings herausextrahieren. Bei meinem Ursprungscode war prinzipiell der einzige Knackpunkt, dass zusätzlich eine Längenübermittlung beim Lesen und senden eines hthml-Inputstrings nötig ist.
Man braucht so etwas wie cstringarg() allerdings ständig, auch z.B. wenn man z.B. zwischen esp-Master und mehreren esp clients Variablenwerte hin und her schicken will.
Aber ich verstehe deine Antwort dann also richtig als "nein, du kennst auch noch keine komplette, fertige Funktion dafür in einer existierenden Arduino-Lib"... 8)
Nein, ich kenne keine fertigen Bibliotheken, weil ich bis jetzt keine brauchte, sie also auch nie gesucht habe.
Da Du aber nach Arduino-Funktionen fragtest, kann man wohl nur die String-Methoden nennen, die ermöglichen Strings zu durchsuchen und Teile daraus zu extrahieren.
MfG
nein, denn es ging ja in meiner Frage um eine fertige Funktion, die alles mit Suchen und Extrahieren komplett macht.
Und jetzt? Was soll daraus werden? Wie es soll es weiter gehen?
MfG
https://github.com/nodejs/http-parser
so etwas in der Art?
Und statt
recved = recv(fd, buf, len, 0);
macht du halt deine client.read() Schleife und befüllst den "buf" selbst
edit: die examples sind allesamt gruselig (malloc und co.) ... aber anpassbar
ich habe den Parser jetzt noch nicht getestet, aber auf den 1. Blick könnte er machen was er soll.
Arduinorianer müssten dann allerdings diese Lib in ihren Code einbinden, was aber vermutlich auch nicht (viel) einfacher ist als mein cstringarg(). Ich dachte, dass eine integrierte Arduino-Funktion dafür zur Verfügung stehen könnte, in einer Arduino-Standardbibliothek. Scheint es aber tatsächlich nicht zu geben.
Mal gucken, ich verwende dann selber meine cstringarg() weiter, vielleicht wird mal eine Lib mit noch mehr Funktionen draus und die kann ich dann ja Arduino für den Library-Manager zum Upload/Download anbieten.
dass eine integrierte Arduino-Funktion dafür zur Verfügung stehen könnte
der Wifiserver und der WifiESPServer und der ESP8266Server scheinen da wohl eine art Unterstützung zu haben, aber das waren sehr diffuse Diskussionen in englisch bei denen es nicht exakt um dein Problem ging, daher kann ichd a auch nichts genaueres dazu sagen, aber es hat mich auch stark gewundert dass man mit µPython-Flask so umfangreiche Unterstützung bekommt aber der Arduino WifiServer so spärlich bestückt ist
ja, das kenne ich auch teilweise. Die Libs für esp (Wifi- und Web-Server etc.) stammen aber von esp, nicht von Arduino, und die esp-devs sind da eh sehr komisch drauf. ;)
da eh sehr komisch drauf
ich würde eher sagen sie denken weiter, gerade WEIL arduino an manchen Stellen echt Schwächen hat, aber die Umsetzung ist definitiv "individuell"
edit: noch ein anderer Ansatz als Idee ohne irgendwas probiert oder gesucht zu haben ... wie wäre es mit regular expressions?! ich denke dafür müsste arduino definitv eine Unterstützung aufweisen, aber regular Expressions sind für sich schon wieder ein neues Arbeitsthema (ich komm jendefalls nciht so wirklich klar damit), bietet aber extrem flexible Scan-Möglichkeiten ohne mit Stringutils rum zu machen. Und man kann es auch bequem simulieren
Einfach den Request ausgeben lassen und kopieren, bei https://regex101.com/ z.B. eingeben und den regulären Ausdruck solange tunen bis er das richtige ausspuckt :)
Es gibt eine Bibliothek für Arduino: https://playground.arduino.cc/Code/TextFinder/
MfG
Das sieht doch mal nach RegEx-Lite aus :D nette Library!
der Wifiserver und der WifiESPServer und der ESP8266Server scheinen da wohl eine art Unterstützung zu haben, aber das waren sehr diffuse Diskussionen in englisch bei denen es nicht exakt um dein Problem ging, daher kann ichd a auch nichts genaueres dazu sagen, aber es hat mich auch stark gewundert dass man mit µPython-Flask so umfangreiche Unterstützung bekommt aber der Arduino WifiServer so spärlich bestückt ist
Die ESP8266WebServer-Klasse stellt bessere Methoden zur Verfügung, mit denen sich viele dieser Sachen erledigen lassen, wie Daten aus dem Header auslesen etc.. So weit ich - kurz überflogen - gesehen habe, ist dort einiges enthalten, um das Handling mit Webseiten zu vereinfachen.
MfG
Die ESP8266WebServer-Klasse stellt bessere Methoden zur Verfügung, mit denen sich viele dieser Sachen erledigen lassen, wie Daten aus dem Header auslesen etc.. So weit ich - kurz überflogen - gesehen habe, ist dort einiges enthalten, um das Handling mit Webseiten zu vereinfachen.
MfG
aber nichts, was meinem cstringarg() entspricht, für Anwendungen wie bei dem TOP Beispiel.
.args(): liefert Zahl der Parameter, im Query-String
.argName(x): liefert den Namen des Arguments x, vom Query-String
.arg(x): liefert den Parameter, des Arguments x, vom Query-String
.arg(String name): liefert den Wert des Parameters name
MfG
in welcher lib für welche Klasse?
Verstehe ich nicht. https://www.roboternetz.de/community/threads/74132-esp8266-Arduino-IDE-neuer-Versuch-warum-wird-website-sofort-beendet?p=655726&viewfull=1#post655726
Verstehe ich nicht. https://www.roboternetz.de/community/threads/74132-esp8266-Arduino-IDE-neuer-Versuch-warum-wird-website-sofort-beendet?p=655726&viewfull=1#post655726
du gibst nur Methoden an,
.args(): liefert Zahl der Parameter, im Query-String
.argName(x): liefert den Namen des Arguments x, vom Query-String
.arg(x): liefert den Parameter, des Arguments x, vom Query-String
.arg(String name): liefert den Wert des Parameters name
die sind aber gekapselt in Klassen.
Es sind z.B. keine Methoden der String-Klasse und auch keine Methoden der WiFiClient -Klasse.
Also wie heißt die Klasse dazu?
oder, anders gefragt:
wie willst du diese Funktionen nutzen, wenn du einen String erhalten hast über
WiFiClient client = wifiserver.available();
...
while ( (readString.length() < TOKLEN) && (c != '\n') ) {
readString += c;
c = client.read();
}
ich verrate dir dazu so viel: Dies alles funktioniert nicht:
client.args(): liefert Zahl der Parameter, im Query-String
client.argName(x): liefert den Namen des Arguments x, vom Query-String
client.arg(x): liefert den Parameter, des Arguments x, vom Query-String
client.arg(String name): liefert den Wert des Parameters name
// und ebensowenig:
readString.args(): liefert Zahl der Parameter, im Query-String
readString.argName(x): liefert den Namen des Arguments x, vom Query-String
readString.arg(x): liefert den Parameter, des Arguments x, vom Query-String
readString.arg(String name): liefert den Wert des Parameters name
Generating function prototypes...
error: 'class WiFiClient' has no member named 'args'
...
exit status 1
'class WiFiClient' has no member named 'args'
denn vermutlich sind es Methoden der esp8266 webserver-Klasse (IIRC), die du gefunden hast, und das nützt uns hier in der WifiClient-Klasse oder der String-Klasse nichts.
Also kannst du damit keinen String weiter verarbeiten, den ein WiFiClient erhalten hat, sondern nur einen, den ein esp8266 webserver erhalten hat
- genau deswegen habe ich nämlich cstringarg() geschrieben 8)
PS: ich habe diese esp8266 webserver-Methoden bei den esp-Leuten auch schon vor langer Zeit als Verbesserung für die webclient-Klasse als Erweiterung vorgeschlagen, aber sie haben es als nicht unterstützenswert abgelehnt.
Genau das meint ich übrigens u.a. auch als ich schrieb: "komisch drauf".
DAs ist einer der GRünde warum ich mit den Methoden von den unterschiedlichen Libs eigentlich garnicht erst anfange wollte, wir werden hier zu Hardwarespezifisch und das sind alles irgendwie nur "proprietäre" Lösungen
ICh bin auch nciht schlau geworden in welchem Modul aus welcher Version nur welche Implementation steckt, daher hatte ich auch einne externe Lib vorgeschlagen, auch wenn man die erst wieder einbinden muss, scheint sie zumindest gereift und stabil von dem was ich im Bugtracker lese
der Grund ist eigentlich eher, dass die esp Entwickler manche Methoden in manchen Klassen implementiert haben und in anderen nicht.
Das hat nichts mit hardwarespezifisch zu tun, denn ALLES ist ja für ESP8266, nur einmal für die Kommunikation mit anderen esp (.args enthalten), und das andere mal für die Kommunikation mit selber aufgebauten html-websites (.args NICHT enthalten).
Ähnliches gilt für den TextFinder, der nur *streams akzeptiert, aber keine Strings und keine cstrings.
Meine cstringarg() Funktion samt ststrpos() ist ja nun quasi eine Funktion einer externen lib, nur ist sie offenbar in dieser Kürze und Würze noch nicht für Arduino-user allgemein verfügbar. 8)
Damit können wir dann aber auch dieses Thema schließen, denke ich.
Hallo,
ich wollte mich nicht wiederholen, was auch unnötig war, aber mach ich es - zu Lasten des Servers, auf dem das Forum sein Dasein fristet - eben nochmal:
Zitat von Ceos
der Wifiserver und der WifiESPServer und der ESP8266Server scheinen da wohl eine art Unterstützung zu haben, aber das waren sehr diffuse Diskussionen in englisch bei denen es nicht exakt um dein Problem ging, daher kann ichd a auch nichts genaueres dazu sagen, aber es hat mich auch stark gewundert dass man mit µPython-Flask so umfangreiche Unterstützung bekommt aber der Arduino WifiServer so spärlich bestückt ist
Darauf schrieb ich:
Die ESP8266WebServer-Klasse stellt bessere Methoden zur Verfügung, mit denen sich viele dieser Sachen erledigen lassen, wie Daten aus dem Header auslesen etc.. So weit ich - kurz überflogen - gesehen habe, ist dort einiges enthalten, um das Handling mit Webseiten zu vereinfachen.
Nach einem kurzen Einwand HaWe's schrieb ich dann:
.args(): liefert Zahl der Parameter, im Query-String
.argName(x): liefert den Namen des Arguments x, vom Query-String
.arg(x): liefert den Parameter, des Arguments x, vom Query-String
.arg(String name): liefert den Wert des Parameters name
Wir führen doch eine Diskussion(?). Mit "verstehe ich nicht" meinerseits war gemeint, dass ich nicht verstehe, warum man sich nicht erinnern kann, was zwei/drei Sätze vorher gesagt / geschrieben wurde; es könnte auch nachgelesen werden; obwohl ich es nochmals verlinkt habe, wo die Antwort zu finden ist, wird es trotzdem nicht gelesen. - Macht nichts!
Bin auch nur drauf gestoßen, weil ich mich gerade mal etwas näher damit befasse.
MfG
- - - Aktualisiert - - -
Bevor es jetzt noch absurder wird, bin ich mal raus aus dem Thread.
ach so, das mit den "besseren Funktionen" war nur ganz allgemein auf andere esp Libs bezogen - das hatte ich nicht verstanden.
Ja, das stimmt.
Ich dachte, es war gemeint in Bezug auf den WiFiClient Code aus dem TOP, quasi als Lösung, um dessen Funktionen zu ersetzen
- aber darauf kann man seine Methoden ja nicht anwenden, und daher meine Antwort, dass es nicht ginge
- aber das war ja dann auch genau das, was du ebenfalls meintest.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.