Forum: Mikrocontroller und Digitale Elektronik ESP8226 mit Bad Request


von P. F. (pfuhsy)


Angehängte Dateien:

Lesenswert?

Hallo zusammen,

ich hoffe Ihr hattet oder habt ein schönen Weihnachtsfest.

Ich beschäftige mich zur Zeit mit den WLAN-Modul ESP8266, welche mir 
eine PHP auf meinen Server mit Übergabewerten aufruft und diese PHP dann 
in eine XML schreibt. Der Code der PHP funktioniert tadellos. Die 
gesendeten Werte des ESP8266 wurden wochenlang sauber in die XML 
geschrieben. Nur seit ein paar Tagen, sendet mir der Server "Bad 
Request" zurück (siehe Bild), obwohl der Code der selbe ist.

Die GET-Anfrage sieht ungefähr so aus:
1
putString("GET /esp8266/haawrite.php?b0=0&b0=1&b0=2&b0=3&b4=4&b5=5&b6=6&b7=7 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n");

Ich bin mir ziemlich sicher, dass das nicht an meiner Anfrage liegt, 
weil sie ja schliesslich immer so funktioniert hat. Ich gehe eher davon 
aus, dass in der Zeit neue Update des Servers daran schuld sind. Was die 
Sache noch verwirrender macht ist, dass wenn ich manchmal die komplette 
Schaltung neu starte, ein einziger Request erfolgreich gesendet wird, 
dannach kommt wieder nur noch der Bad Request. Leider konnte kann ich 
das nicht reproduzieren, mal geht es mit dem Neustart, mal nicht.

Infos zum Server:
Synology DS 413j
PHP 5.6 läuft
PHP 7.0 läuft
WebStation läuft
Apache HTTP Server 2.2 läuft
Apache HTTP Server 2.4 läuft

Hat jemand eine Idee woran das liegen kann ?

Gruss
Peter

von Stefan F. (Gast)


Lesenswert?

Untersuche den Netzwerk-Verkehr mit Wireshark, insbesondere den HTTP 
Request.

von Jim M. (turboj)


Lesenswert?

Das ist ein HTTP/1.0 Request. Für HTTP 1.1 muss da IMO noch ein 
"Connection: close" Header mit rein, siehe Kapitel 6.1 in RFC 7230.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

P. F. schrieb:
> b0=0&b0=1&b0=2&b0=3&b4=4

Kommt mir irgendwie komisch vor. viermal wird b0 ein unterschiedlicher 
Wert zugewiesen. Soll das so sein?

von Stefan F. (Gast)


Lesenswert?

>> b0=0&b0=1&b0=2&b0=3&b4=4
>Kommt mir irgendwie komisch vor.

Das man komisch sein, ist aber sicher nicht die Problemursache. Es ist 
sogar offiziell erlaubt, einen Parameter mehrmals zu wiederholen. Ich 
würde es allerdings nicht tun.

von Jürgen K. (Gast)


Lesenswert?

P. F. schrieb:
> Die GET-Anfrage sieht ungefähr so aus:
> ...

Und wie sieht sie wirklich aus?

Lass dir die URL doch mal ausgeben oder schau in den Logfiles vom 
Server, vermutlich wird die einfach nur falsch zusammengebaut weil eine 
der Variablen aus denen sie wohl besteht leer ist (irgend ein sensor 
ausgestiegen?).

In etwa so:
> b0=&b0=1&b0=2&b0=3&b4=4

von A.. P. (arnonym)


Lesenswert?

Ich würde auch ganz stark auf einen kaputten GET-Request tippen. Der 
Server wird sicherlich ausgereifter sein, als dein Code, und mit 
Sicherheit würde ein Server nicht über ein Update kaputt gepatcht. Lass 
dir den vom ESP zusammengebauten GET-Request über's Terminal ausgeben 
oder sieh dir die Kommunikation in Wireshark an, da wirst du sicher 
schnell fündig.

Gruß

von Jan L. (ranzcopter)


Lesenswert?

Was sagt denn das nginx error Log? Wenn es nichts sagt, dann aktiviere 
es, am besten mit Loglevel ‚debug‘ (falls möglich), oder zumindest 
‚info‘.

von A.. P. (arnonym)


Lesenswert?

Jim M. schrieb:
> Das ist ein HTTP/1.0 Request.

Wo siehst du das? Er schickt doch klar HTTP/1.1 im Request mit.

Jim M. schrieb:
> Für HTTP 1.1 muss da IMO noch ein "Connection: close" Header mit rein,
> siehe Kapitel 6.1 in RFC 7230

Nein, braucht es nicht. HTTP/1.1 geht grundsätzlich von persistenten 
Verbindungen aus, siehe Kapitel 6.3 im RFC 7230.

Abgesehen davon wäre das überhaupt unlogisch, da es ja wochenlang 
funktioniert hat. Wieso sollte sich daher der Server jetzt plötzlich an 
einem fehlenden Header-Feld stören, welches vorher auch schon gefehlt 
hat?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

> HTTP/1.1 geht grundsätzlich von persistenten Verbindungen aus

Eben das könnte der Haken sein. Wenn jetzt weder der Server noch der 
Client die Verbindung nach der Response schließt, dann wird der zweite 
Request nicht richtig erkannt, denn es gibt auch keinen Content-Length 
Header und keinen Chunked-Mode.

von A.. P. (arnonym)


Lesenswert?

P. F. schrieb:
> Die GET-Anfrage sieht ungefähr so aus:

Zeig uns doch einfach den Teil Code, der deine Anfrage konkret 
zusammenbaut.

P. F. schrieb:
> Ich bin mir ziemlich sicher, dass das nicht an meiner Anfrage liegt,
> weil sie ja schliesslich immer so funktioniert hat.

Häufig ist es dann aber so, dass es ziemlich sicher am eigenen Code 
liegt :)

P. F. schrieb:
> Was die Sache noch verwirrender macht ist, dass wenn ich manchmal die
> komplette Schaltung neu starte, ein einziger Request erfolgreich
> gesendet wird, dannach kommt wieder nur noch der Bad Request.

Das untermauert meine Aussage noch.

von A.. P. (arnonym)


Lesenswert?

Stefan U. schrieb:
>> HTTP/1.1 geht grundsätzlich von persistenten Verbindungen aus
>
> Eben das könnte der Haken sein. Wenn jetzt weder der Server noch der
> Client die Verbindung nach der Response schließt, dann wird der zweite
> Request nicht richtig erkannt, denn es gibt auch keinen Content-Length
> Header und keinen Chunked-Mode.

Das könnte es natürlich sein und war auch eine meiner Ideen. Ich würde 
immer einen sauberen Request mit zumindest einem Content-Length- und 
einem Connection-Header mitsenden.

Aber die Ideen hier widersprechen der Aussage des TO, wonach es ja 
anfänglich problemlos funktioniert hat. Entweder stimmt es, was wir 
vermuten, dann dürfte es aber noch nie sauber funktioniert haben. Oder 
der TO hat uns nicht alles erzählt und es hat sich zwischendurch noch 
etwas mehr getan.

Es wäre daher gut, wenn der TO sich wieder einklinken würde und neuen 
Input lieferte, was denn in der Zwischenzeit geschehen ist.

: Bearbeitet durch User
von P. F. (pfuhsy)


Lesenswert?

Stefan U. schrieb:
> Untersuche den Netzwerk-Verkehr mit Wireshark, insbesondere den HTTP
> Request.

Danke, teste ich mal aus.

Jim M. schrieb:
> Das ist ein HTTP/1.0 Request. Für HTTP 1.1 muss da IMO noch ein
> "Connection: close" Header mit rein, siehe Kapitel 6.1 in RFC 7230.

Sobald ich ein "OK" empfange, schliesse ich auc die Verbindung, siehe 
Bild.

Rufus Τ. F. schrieb:
> P. F. schrieb:
>> b0=0&b0=1&b0=2&b0=3&b4=4
>
> Kommt mir irgendwie komisch vor. viermal wird b0 ein unterschiedlicher
> Wert zugewiesen. Soll das so sein?

Kopierfehler. Soll b0, b1, b2, usw heissen.

Jürgen K. schrieb:
> P. F. schrieb:
>> Die GET-Anfrage sieht ungefähr so aus:
>> ...
>
> Und wie sieht sie wirklich aus?
>
> Lass dir die URL doch mal ausgeben oder schau in den Logfiles vom
> Server, vermutlich wird die einfach nur falsch zusammengebaut weil eine
> der Variablen aus denen sie wohl besteht leer ist (irgend ein sensor
> ausgestiegen?).

Hmm, ich hab auch testeweise die URL nicht zusammen gesetzt sondern 
direkt in die "putString" geschrieben. Da hab ich das selbe Problem.

Jan L. schrieb:
> Was sagt denn das nginx error Log? Wenn es nichts sagt, dann aktiviere
> es, am besten mit Loglevel ‚debug‘ (falls möglich), oder zumindest
> ‚info‘.

Uii....wie kann ich die denn auslesen ?

A.. P. schrieb:
> P. F. schrieb:
>> Die GET-Anfrage sieht ungefähr so aus:
>
> Zeig uns doch einfach den Teil Code, der deine Anfrage konkret
> zusammenbaut.

Hier baue ich den Request zusammen, zähle ich Zeichenlänge und sende 
dann:
Unter "TCP_senden" gibt es noch die auskommentierte Zeile die ioch 
testweise sende und damit das zusammenbauen umgehe. Geht aber auch 
nicht.
1
void TCP_Laenge(uint8_t var0, uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4, uint8_t var5, uint8_t var6, uint8_t var7)    //Zeichenzählen für Anfrage ermitteln
2
{
3
   char wert_chr[3];          //Variable zum wandeln
4
5
  /*Komplette GET-Anfrage, Beispiel: 
6
  GET /esp8266/haawrite.php?b0=333 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n
7
  */
8
  
9
  //Array zusammensetzten
10
  char get[GET_GROESSE] = "GET ";      //Array beginnen
11
  strcat(get, PHP_ZIEL);          //an Array anhängen  
12
  
13
//   strcat(get, "?b0=");          //an Array anhängen  
14
//  itoa(byte, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
15
//   strcat(get, wert_chr);          //an Array anhängen    
16
//   strcat(get, "=");            //an Array anhängen  
17
  
18
  strcat(get, "?b0=");          //an Array anhängen    
19
  itoa(var0, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt  
20
  strcat(get, wert_chr);          //an Array anhängen
21
  strcat(get, "&");
22
23
  strcat(get, "b1=");            //an Array anhängen      
24
  itoa(var1, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
25
  strcat(get, wert_chr);          //an Array anhängen
26
  strcat(get, "&");
27
  
28
  strcat(get, "b2=");            //an Array anhängen  
29
  itoa(var2, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
30
  strcat(get, wert_chr);          //an Array anhängen
31
  strcat(get, "&");
32
33
  strcat(get, "b3=");            //an Array anhängen    
34
  itoa(var3, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
35
  strcat(get, wert_chr);          //an Array anhängen
36
  strcat(get, "&");
37
38
  strcat(get, "b4=");            //an Array anhängen    
39
  itoa(var4, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
40
  strcat(get, wert_chr);          //an Array anhängen
41
  strcat(get, "&");
42
  
43
  strcat(get, "b5=");            //an Array anhängen    
44
  itoa(var5, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
45
  strcat(get, wert_chr);          //an Array anhängen
46
  strcat(get, "&");
47
  
48
  strcat(get, "b6=");            //an Array anhängen    
49
  itoa(var6, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
50
  strcat(get, wert_chr);          //an Array anhängen
51
  strcat(get, "&");
52
  
53
  strcat(get, "b7=");            //an Array anhängen    
54
  itoa(var7, wert_chr, 10);        //Variable wandeln sonst wird die Länge der Zeichen falsch gezählt
55
  strcat(get, wert_chr);          //an Array anhängen
56
                
57
  strcat(get, " HTTP/1.1\r\nHost: ");    //an Array anhängen
58
  strcat(get, SERVER_IP);          //an Array anhängen
59
  strcat(get, "\r\n\r\n");        //an Array anhängen
60
  
61
  memcpy(_get, get, strlen(get));      //Zusammengesetzten Befehl zum senden global speichern
62
63
  size_t i = strlen(get);        //Stringlänge von Array ermitteln
64
  itoa(i, wert_chr, 10);        //Variable wandeln
65
66
  //Array zusammensetzten
67
  char cipsend[] = "AT+CIPSEND=";  //Array beginnen
68
  strcat(cipsend, wert_chr);    //an Array anhängen
69
  strcat(cipsend, "\r\n");    //an Array anhängen
70
  
71
  //zusammengesetztes CIPSEND senden
72
  putString(cipsend);
73
  //putString("AT+CIPSEND=96\r\n");  //Array beginnen
74
}
75
void TCP_Senden()      //
76
{
77
//  putString("GET /esp8266/haawrite.php?b0=0&b1=1&b2=2&b3=3&b4=4&b5=5&b6=6&b7=7 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n");
78
  putString(_get);    //globales, kopiertes Array senden
79
}

Das eigentlich Senden des Protokolls sieht so aus:
1
void Protokoll_senden()    //Ausgabe des Protokolls
2
{    
3
  static int anfrage_i = 0;    //Laufvariable welche Anfrage gesendet wurde
4
      
5
  if (_t_Status_s >= T_STATUS_S)    //Ausgabe erst nach angegebener Zeit
6
  {
7
    
8
    if(!_ESP_Busy)  //ESP steht zur Verfügung und kann angefragt werden
9
    {      
10
        //Welches Protkoll soll gesendet werden
11
        switch(anfrage_i)
12
        {
13
          //Anfragen senden
14
          case 0:
15
            ESP_Query(TCP_START, "OK");  //mit Empfänger verbinden
16
          break;
17
18
          case 1:
19
            TCP_Laenge(BAS, SIR, REE, AKL, AKN, SWP, SWB, SWS);    //Zeichenlänge ermitteln
20
            _ESP_Timeout_s = 0;    //Timeout-Zeit zurücksetzten
21
            _ESP_Busy = true;    //Flag ESP ist beschäftigt
22
          break;
23
24
          case 2:
25
            TCP_Senden();      //Eigentliche Daten senden
26
            _ESP_Timeout_s = 0;    //Timeout-Zeit zurücksetzten
27
            _ESP_Busy = true;    //Flag ESP ist beschäftigt            
28
          break;
29
30
          case 3:
31
            ESP_Query(TCP_DISCONNECT, "OK");  //Verbindung schliessen
32
          break;        
33
        
34
          //alle Anfragen wurden gesendet
35
          default:
36
            _t_Status_s = 0;    //Timer zurücksetzten, damit in angegebener Zeit wieder gesenet wird
37
            anfrage_i = 0;      //Laufvariable zurücksetzten, damit die Funktion nochmal aufgerufen werden kann
38
          break;        
39
        }      
40
     }
41
     
42
    else
43
    {
44
       //prüfen ob erwartete Antwort vorhanden ist
45
       if(ESP_Response())
46
       {
47
         anfrage_i++;      //variable für nächste Anfrage
48
       }  
49
    }
50
  }
51
}
52
void ESP_Query (char *anfrage, char *antwort)
53
{
54
  strcpy(_gesuchte_antw, antwort);  //erwartete Antwort abspeichern
55
  putString(anfrage);          //Anfrage senden
56
  _ESP_Timeout_s = 0;          //Timeout-Zeit zurücksetzten
57
  _ESP_Busy = true;          //Flag ESP ist beschäftigt
58
}
59
bool ESP_Response()
60
{
61
  bool rueckgabe = false;
62
63
  //Abfrage ob Antwort vorhanden ist
64
  if(_uart_str_complete)
65
  {
66
    //prüfen ob die gesuchte Antwort vorhanden ist
67
    if(strstr(_uart_string, _gesuchte_antw))  //nach einzelnen Wörtern suchen (ohne Leerzeichen)
68
    {
69
      _ESP_Busy = false;    //ESP wieder freigeben        
70
      rueckgabe = true;    //Rückgabewert positiv
71
    }
72
        
73
    //Unabhängig der Antwort, alles zurücksetzten
74
    memset(_uart_string, '\0', sizeof(_uart_string));  //Inhalte vom Array löschen
75
    _uart_str_complete = false;              //String komplett zurücksetzten    
76
  }
77
78
  return rueckgabe;
79
}

Das ist die esp8266.h:
1
#ifndef _ESP_8266_H_
2
#define _ESP_8266_H_
3
//-----------------------Konstanten / Variablen-------------------------
4
//WLAN-Daten
5
#define SSID      "Fxxxx-WLAN"      //WLAN Netzwerk
6
#define WLAN_PASS    "Mxxxxxxxxxxxxxxxxx."  //WLAN Passwort
7
#define SERVER_IP    "192.168.1.100"      //IP-Adresse des Servers
8
#define SERVER_PORT    "80"          //Port des Servers
9
#define PHP_ZIEL    "/esp8266/haawrite.php"  //Ziel PHP die die gesendeten Daten in XML schreibt
10
11
//AT-Befehle
12
#define WORKS      ("AT\r\n")                      //Esp arbeitet
13
#define RESET      ("AT+RST\r\n")                    //ESP Software-Reset  
14
#define WIFI_AUTO_DIS  ("AT+CWAUTOCONN=0\r\n")                //Automatisches WiFi-Connect ausschalten
15
#define WIFI_AUTO_CON  ("AT+CWAUTOCONN=1\r\n")                //Automatisches WiFi-Connect einschalten
16
#define WIFI_LISTING  ("AT+CWLAP\r\n")                  //Verfügbare SSID's
17
#define WIFI_STA    ("AT+CWMODE=1\r\n")                  //WiFi-Verbindungsmodus Stand alone  
18
#define WIFI_JOIN    ("AT+CWJAP=\"" SSID "\",\"" WLAN_PASS "\"\r\n")    //Mit Router verbinden TODO "Fail" auswerten
19
#define TCP_SINGLE_CON  ("AT+CIPMUX=0\r\n")                  //TCP/UDP Connetion Single
20
#define TCP_START    ("AT+CIPSTART=\"TCP\",\"" SERVER_IP "\"," SERVER_PORT "\r\n")    //Mit Empfänger verbinden TODO "ERROR" auswerten
21
#define TCP_DISCONNECT  ("AT+CIPCLOSE\r\n")                  //TCP-Verbindung schliessen
22
23
#define GET_GROESSE    120  //Größe der Zeichen im get-Befehl definieren (max. Zeichen bei Wert 7x 255)
24
char _get [GET_GROESSE];  //globales Array für den GET-Befehl
25
char _gesuchte_antw[10];      //Stringbuffer für für die ESP-Antwort
26
//----------------------------------------------------------------------
27
28
//------------------------------Prototypen------------------------------                
29
void TCP_Laenge(uint8_t var0, uint8_t var1, uint8_t var2, uint8_t var3, uint8_t var4, uint8_t var5, uint8_t var6, uint8_t var7);
30
void TCP_Senden();
31
//----------------------------------------------------------------------
32
33
#endif

von Stefan F. (Gast)


Lesenswert?

> char wert_chr[3];          //Variable zum wandeln

Das ist ein Byte zu wenig. Du brauchst 4 Bytes wegen dem abschließenden 
Null-Byte das den String terminiert.

von Jan L. (ranzcopter)


Lesenswert?

P. F. schrieb:
>> Was sagt denn das nginx error Log? Wenn es nichts sagt, dann aktiviere
>> es, am besten mit Loglevel ‚debug‘ (falls möglich), oder zumindest
>> ‚info‘.
>
> Uii....wie kann ich die denn auslesen ?

?? du hast irgendwo ("Server"?) einen nginx laufen. Dieser liefert Error 
400. Recherchiert man da mal ein paar Sekunden im Netz erfährt man, dass 
nginx üblicherweise bei einem Error 400 die (vielfältigen) Ursachen 
dafür in sein Error-Log schreibt. Das Error-Log muss man *evtl.* 
aktivieren - dafür gibt es auf dem "Server" die Datei nginx.conf - oder 
vermutlich eher sowas wie /etc/nginx/conf.d/meinserver.conf o.ä.

Da sollte sowas wie hier stehen:
1
http {
2
    server {
3
        error_log /path/to/log debug;

"debug" wird nicht überall vorgesehen sein, dann einfach "info" nehmen. 
Die Fehlermeldungen stehen dann in "/path/to/log"...

Google Treffer 1:
1
When nginx returns 400 (Bad Request) it will log the reason into error log, at "info" level. Hence an obvious way to find out what's going on is to configure error_log to log messages at "info" level and take a look into error log when testing.

von P. F. (pfuhsy)


Lesenswert?

Stefan U. schrieb:
> Das ist ein Byte zu wenig. Du brauchst 4 Bytes wegen dem abschließenden
> Null-Byte das den String terminiert.

Ok, danke. Habs angepasst.

Jan L. schrieb:
> ?? du hast irgendwo ("Server"?) einen nginx laufen. Dieser liefert Error
> 400. Recherchiert man da mal ein paar Sekunden im Netz erfährt man, dass
> nginx üblicherweise bei einem Error 400 die (vielfältigen) Ursachen
> dafür in sein Error-Log schreibt. Das Error-Log muss man *evtl.*
> aktivieren - dafür gibt es auf dem "Server" die Datei nginx.conf - oder
> vermutlich eher sowas wie /etc/nginx/conf.d/meinserver.conf o.ä.
>
> Da sollte sowas wie hier stehen:http {
>     server {
>         error_log /path/to/log debug;
>
> "debug" wird nicht überall vorgesehen sein, dann einfach "info" nehmen.
> Die Fehlermeldungen stehen dann in "/path/to/log"...

Oh man, das scheint kompliziert zu sein. Ich kenne mich damit nicht aus.
Also, ich hab unter /etc/nginx eine "nginx.conf" gefunden. Ist das die 
richtige ?
1
admin@DiskStation:/etc/nginx$ dir
2
total 60
3
drwxr-xr-x  2 root root 4096 Dec 27 07:04 .
4
drwxr-xr-x 47 root root 4096 Dec 27 13:38 ..
5
lrwxrwxrwx  1 root root   20 Nov  8 07:03 app.d -> /var/tmp/nginx/app.d
6
lrwxrwxrwx  1 root root   27 Nov  8 07:03 conf.d -> /usr/local/etc/nginx/conf.d
7
-rw-r--r--  1 root root 1077 Nov  2 23:13 fastcgi.conf
8
-rw-r--r--  1 root root 1007 Nov  2 23:13 fastcgi_params
9
-rw-r--r--  1 root root 2837 Nov  2 23:13 koi-utf
10
-rw-r--r--  1 root root 2223 Nov  2 23:13 koi-win
11
-rw-r--r--  1 root root 3957 Nov  2 23:13 mime.types
12
-rw-r--r--  1 root root 9149 Dec 27 07:04 nginx.conf
13
-rw-r--r--  1 root root 3491 Nov  2 23:07 nginx.conf.default
14
-rw-r--r--  1 root root  277 Nov  2 23:07 proxy.conf
15
-rw-r--r--  1 root root 1204 Nov  2 23:13 scgi_params
16
lrwxrwxrwx  1 root root   34 Nov  8 07:03 sites-enabled -> /usr/local/etc/nginx/sites-enabled
17
-rw-r--r--  1 root root  664 Nov  2 23:13 uwsgi_params
18
-rw-r--r--  1 root root 3610 Nov  2 23:13 win-utf

Im Inhalt steht aber nichts über "error_log":
1
 server {
2
        listen 80 default_server;
3
        listen [::]:80 default_server;
4
5
        gzip on;
6
7
        server_name _;
8
9
        location ~ ^/volume(?:X|USB|SATA|Gluster)?\d+/ {
10
            internal;
11
12
            root /;
13
14
            include app.d/x-accel.*.conf;
15
            include conf.d/x-accel.*.conf;
16
        }
17
18
        include app.d/www.*.conf;
19
        include app.d/alias.*.conf;
20
        include /usr/syno/share/nginx/conf.d/www.*.conf;
21
        include conf.d/www.*.conf;
22
23
        location = /webdefault/images/logo.jpg {
24
            alias /usr/syno/share/nginx/logo.jpg;
25
        }
26
27
        error_page 403 404 500 502 503 504 @error_page;
28
29
        location @error_page {
30
            root /usr/syno/share/nginx;
31
            rewrite (.*) /error.html break;
32
        }
33
34
        location ^~ /.well-known/acme-challenge {
35
            root /var/lib/letsencrypt;
36
            default_type text/plain;
37
        }
38
39
        include app.d/.location.webstation.conf*;
40
41
        location / {
42
            rewrite ^ / redirect;
43
        }
44
45
        location ~ ^/$ {
46
            rewrite / http://$host:5000/ redirect;
47
        }
48
    }

An welcher Stelle muss das denn reingeschrieben werden ?

Einen Pfad "/path...." gibt es beimir nicht:
1
admin@DiskStation:/$ dir
2
total 76
3
drwxr-xr-x  24 root root 4096 Dec 27 07:01 .
4
drwxr-xr-x  24 root root 4096 Dec 27 07:01 ..
5
lrwxrwxrwx   1 root root    7 Nov  8 07:01 bin -> usr/bin
6
drwxr-xr-x   4 root root    0 Dec 27 07:02 config
7
drwxr-xr-x  11 root root 3800 Dec 27 07:03 dev
8
drwxr-xr-x  47 root root 4096 Dec 27 13:38 etc
9
drwxr-xr-x  39 root root 4096 Dec 22 00:03 etc.defaults
10
drwxr-xr-x   2 root root 4096 Nov  2 23:19 initrd
11
lrwxrwxrwx   1 root root    7 Nov  8 07:01 lib -> usr/lib
12
drwx------   2 root root 4096 Nov  2 23:19 lost+found
13
drwxr-xr-x   2 root root 4096 Nov  2 23:19 mnt
14
drwxr-xr-x   3 root root 4096 Nov  8 07:01 .old_patch_info
15
dr-xr-xr-x 224 root root    0 Jan  1  1970 proc
16
-rw-------   1 root root 1024 Mar 14  2011 .rnd
17
drwx------   5 root root 4096 Nov 14 03:00 root
18
drwxr-xr-x  23 root root 1780 Dec 27 13:38 run
19
lrwxrwxrwx   1 root root    8 Nov  8 07:01 sbin -> usr/sbin
20
drwxrwxrwx   4 root root 4096 Dec 22 00:03 .syno
21
drwxr-xr-x  11 root root    0 Jan  1  1970 sys
22
drwxr-xr-x   2 root root 4096 Mar 14  2011 .system_info
23
drwxrwxrwt  15 root root 1500 Dec 27 14:49 tmp
24
drwxr-xr-x   2 root root 4096 Dec 16 03:03 tmpRoot
25
drwxr-xr-x   9 root root 4096 Nov  2 22:29 usr
26
drwxr-xr-x  18 root root 4096 Dec 27 07:01 var
27
drwxr-xr-x  14 root root 4096 Nov  8 07:02 var.defaults
28
drwxr-xr-x  21 root root 4096 Dec 27 07:02 volume1
29
drwxr-xr-x  11 root root 4096 Dec 27 07:02 volume2
30
drwxr-xr-x  10 root root 4096 Dec 27 07:02 volume4

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

P. F. schrieb:
> Einen Pfad "/path...." gibt es beimir nicht:

Natürlich nicht. "/path/to/log" ist ein Platzhalter mit offenkundigem 
Namen.

von Jan L. (ranzcopter)


Lesenswert?

>
> Oh man, das scheint kompliziert zu sein. Ich kenne mich damit nicht aus.
> Also, ich hab unter /etc/nginx eine "nginx.conf" gefunden. Ist das die
> richtige ?

Jein; das ist zwar die "Startconfig", die Config deiner Domain liegt 
aber in einem dieser Verzeichnisse:

        include app.d/www.*.conf;
        include app.d/alias.*.conf;
        include /usr/syno/share/nginx/conf.d/www.*.conf;
        include conf.d/www.*.conf;

Ist aber egal, die nginx.conf tut's hierfür erstmal auch - einfach z.B. 
unter "server_name" noch reinschreiben:
1
error_log  /var/log/nginx/error.log info;

und nginx neu starten. Danach liegt unter /var/log/nginx ein 
"error.log".

Falls es /var/log/nginx noch nicht geben sollte, und du dich vermutlich 
mit Dateirechten nicht recht auskennst :), kannst du einfach auch 
"/tmp/nginx_error.log" nehmen:
1
error_log  /tmp/nginx_error.log info;

da "darf" nginx immer reinschreiben.

von Stefan F. (Gast)


Lesenswert?

Mit Wireshark kommst du vielleicht doch schneller voran. Da klickt man 
sich durch.

von Joachim S. (oyo)


Lesenswert?

A.. P. schrieb:
> Jim M. schrieb:
>> Das ist ein HTTP/1.0 Request.
>
> Wo siehst du das? Er schickt doch klar HTTP/1.1 im Request mit.
>
> Jim M. schrieb:
>> Für HTTP 1.1 muss da IMO noch ein "Connection: close" Header mit rein,
>> siehe Kapitel 6.1 in RFC 7230
>
> Nein, braucht es nicht. HTTP/1.1 geht grundsätzlich von persistenten
> Verbindungen aus, siehe Kapitel 6.3 im RFC 7230.

Letztlich habt ihr doch beide Recht:
Laut 6.3 der besagten Spec ist das "Connection: close" bei HTTP/1.1 
nicht zwingend nötig, der Server geht in diesem Fall dann eben von einer 
persistenten Verbindung aus.
Wenn der Client (wie im vorliegenden Fall) aber eben keine persistenten 
Verbindungen unterstützt, dann MUSS er nach Kapitel 6.1 eben doch einen 
"Connection: close"-Header senden.
So gesehen sind die von Arduino-Code erzeugten HTTP-Requests 
strenggenommen ja tatsächlich nicht HTTP/1.1-konform, und die "Bad 
request"-Fehlermeldung somit im Grunde berechtigt.

@Threadstarter: Ich würde an Deiner Stelle wirklich einfach mal 
ausprobieren, was passiert, wenn Du das wahlweise als HTTP 1.0-Request 
sendest, oder eben zusätzlich einfach noch ein "Connection: 
close"-Header-Feld mit einfügst.
Die von stefanus genannte mögliche Erklärung für das Phänomen, warum es 
direkt nach einem Neustart genau einmal funktioniert, klingt für mich 
ziemlich plausibel.

: Bearbeitet durch User
von A.. P. (arnonym)


Lesenswert?

Joachim S. schrieb:
> Letztlich habt ihr doch beide Recht

Nicht ganz. Hätte Jim M. geschrieben es "kann" noch ein Connection: 
close rein, dann hätte ich dem zugestimmt. Aber er meinte es "muss" eins 
rein - und das ist eben falsch ;)

Joachim S. schrieb:
> So gesehen sind die von Arduino-Code erzeugten HTTP-Requests
> strenggenommen ja tatsächlich nicht HTTP/1.1-konform, und die "Bad
> request"-Fehlermeldung somit im Grunde berechtigt.

Strenggenommen ist es eben doch ein konformer Request und die Antwort 
des Servers in so einem Fall (sofern der fehlende Connection-Header eben 
der einzige Grund wäre) nicht berechtigt. In dem Moment, wo der Sender 
kein "Connection: close" mitsendet, nimmt der Server automatisch eine 
dauerhafte Verbindung an. Soweit ist doch alles konform. Sobald nun der 
Request vollständig und korrekt beim Server ankommt und dieser seine 
Antwort verschickt hat, bleibt die Verbindung einfach bestehen. Nun 
schließt der Client irgendwann die TCP-Verbindung und alles ist immer 
noch korrekt.

Ich würde aber an Stelle des TO doch einfach als ersten Ansatz einen 
korrekten Content-Length Header setzen, um ein eventuelles Problem mit 
dem Request-Body - welcher ja leer ist - auszuschließen.

: Bearbeitet durch User
von Joachim S. (oyo)


Lesenswert?

A.. P. schrieb:
> Joachim S. schrieb:
>> Letztlich habt ihr doch beide Recht
>
> Nicht ganz. Hätte Jim M. geschrieben es "kann" noch ein Connection:
> close rein, dann hätte ich dem zugestimmt. Aber er meinte es "muss" eins
> rein - und das ist eben falsch ;)

Och, das kann man so oder so sehen, denn im konkreten Fall "muss" laut 
Kapitel 6.1 der Spec doch tatsächlich ein solcher Header rein:
> A client that does not support persistent connections MUST send the
> "close" connection option in every request message.

;)

von A.. P. (arnonym)


Lesenswert?

Joachim S. schrieb:
> Och, das kann man so oder so sehen, denn im konkreten Fall "muss" laut
> Kapitel 6.1 der Spec doch tatsächlich ein solcher Header rein:
>> A client that does not support persistent connections MUST send the
>> "close" connection option in every request message.
>
> ;)

Und woher kommt deine Annahme, dass der TO mit seinem Code keine 
persistente Verbindung unterstützt? Die Eigenschaft, eine persistente 
Verbindung zu unterstützen, wird doch nicht durch höhere Gewalt 
bestimmt, sondern einzig vom Entwickler vorgegeben und von der Weise, 
wie er seinen HTTP-Code implemetiert hat. Somit signalisiert der TO 
automatisch mit dem fehlenden Header, dass er eine dauerhafte Verbindung 
möchte. Dass er diese vielleicht 200 ms nachdem er die Antwort des 
Servers erhalten hat wieder schließt, ist kein Indiz dafür, dass er 
keine persistente Verbindungen unterstützt. Eine persistente Verbindung 
ist eben alles, was nach Erhalt der Server-Antwort noch offen gehalten 
wird, unabhängig davon, ob es nur 10 ms sind oder bis morgen Mittag 12 
Uhr.

Im Übrigen ziehe ich meine vorherige Aussage bzgl. Content-Length 
zurück, da dies bei einem GET, wie in diesem Fall, nicht das Problem 
sein kann, da es dazu auch im RFC 7230, Kapitel 3.3.2 heißt:

"A user agent SHOULD NOT send a Content-Length header field when the 
request message does not contain a payload body and the method semantics 
do not anticipate such a body."

Gruß

: Bearbeitet durch User
von Jan L. (ranzcopter)


Lesenswert?

Joachim S. schrieb:
> Och, das kann man so oder so sehen, denn im konkreten Fall "muss" laut

...im "konkreten Fall" ist das in der Praxis völlig unerheblich, wie 
eigentlich jeder jederzeit höchst simpel mit irgendeinem nginx (oder 
apache etc.) nachprüfen kann: Ein einfacher Telnet auf Port 80 eines 
Webservers liefert einwandfreie Antworten, einziger "mandatory header" 
bei HTTP/1.1 ist der Host:-Header, der allerdings halbwegs stimmen 
sollte:
1
# telnet www.spiegel.de 80
2
Trying 128.65.210.182...
3
Connected to www.spiegel.de (128.65.210.182).
4
Escape character is '^]'.
5
HEAD / HTTP/1.1
6
HOST: www.spiegel.de
7
8
HTTP/1.1 200 OK
9
Date: Wed, 27 Dec 2017 17:10:01 GMT
10
Cache-Control: max-age=45
11
Expires: Wed, 27 Dec 2017 17:10:46 GMT
12
X-SP-TE: 6151
13
X-Robots-Tag: index, follow, noarchive, noodp
14
Content-Type: text/html;charset=UTF-8
15
X-SP-AP: 6128
16
Vary: Accept-Encoding, isssl
17
Age: 32
18
X-SP-PR: 6128
19
Connection: keep-alive

von Stefan F. (Gast)


Lesenswert?

> Und woher kommt deine Annahme, dass der TO mit seinem Code keine
> persistente Verbindung unterstützt?

Weil er weder den Content-Length Header noch den Chunked-Transfer 
verwendet hat. Habe ich doch oben geschrieben. Ohne das kann er keinen 
2. Request senden.

von Stefan F. (Gast)


Lesenswert?

> "A user agent SHOULD NOT send a Content-Length header field when the
> request message does not contain a payload body and the method semantics
> do not anticipate such a body."

Ich vermute, dieser Satz stammt aus HTTP 1.0 Zeiten. Get Requests können 
einen Body enthalten (auch wenn das unüblich ist). Und deswegen darf man 
bei GET nicht von der Länge 0 ausgehen. Macht auch kein Server.

Der nächste Request beginnt, nachdem der vorherige beendet ist. Ein 
Request endet wahlweise
a) nach Erreichen der Content-Length,
b) beim Schließen der Verbindung,
c) bei der Ende-Markierung vom Chunked Transfer (nur HTTP 1.1)

von A.. P. (arnonym)


Lesenswert?

Unabhängig von diesen ganzen Erörterungen, wie der HTTP-Standard denn 
nun aussieht, denke ich, dass der TO nur weiterkommt, wenn er sich mal 
vor sein System setzt und sich ein paar dieser fehlerhaften Anfragen 
ansieht. Ob das nun seriell über das Terminal, über das nginx-Log oder 
mittels Wireshark erfolgt - irgendwas davon wird ihn sicher weiter 
bringen, als alle Diskussionen über den korrekten Aufbau einer Anfrage 
:)

Ich gehe stark davon aus, dass der Server schon richtig arbeitet und der 
Fehler sicher in dem (m.M.n. etwas ungelenken) Zusammenbau der Anfrage 
steckt. Es wird dem TO sicher selbst schnell auffallen, an welcher 
Stelle sein Code unvollständige Anfragen erzeugt, wenn er sich mal ein 
paar davon ansieht.

von Joachim S. (oyo)


Lesenswert?

Was mir übrigens gerade eben noch aufgefallen ist:
1
//Array zusammensetzten
2
  char cipsend[] = "AT+CIPSEND=";  //Array beginnen
3
  strcat(cipsend, wert_chr);    //an Array anhängen
4
  strcat(cipsend, "\r\n");    //an Array anhängen

Meine C/C++-Kenntnisse sind zugegebenermassen äusserst gering, aber ist 
obiges Code-Fragment wirklich okay so? Ich hätte jetzt instinktiv 
vermutet, dass durch ein
1
char cipsend[] = "AT+CIPSEND="
nur 12 Bytes reserviert werden (also genau so viele, um den String 
"AT+CIPSEND=" sowie ein abschliessenden 0-Byte zu speichern). Und es 
durch die anschliessenden beiden strcat-Befehle dann zu einer Art 
Pufferüberlauf kommt, bei dem möglicherweise unbeabsichtigt etwas ganz 
anderes überschrieben wird, mit möglicherweise unvorhergesehenen Folgen.

Ist obiges Codefragment wirklich okay so?

: Bearbeitet durch User
von Stefan F. (Gast)


Lesenswert?

Das hast du richtig erkannt, du überfüllst das Array und das kann 
allerlei Fehlfunktionen auslösen.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Joachim S. schrieb:
> Ist obiges Codefragment wirklich okay so?

Nee, das ist definitiv kaputt, das hast Du richtig erkannt.

von P. F. (pfuhsy)


Angehängte Dateien:

Lesenswert?

Joachim S. schrieb:
> @Threadstarter: Ich würde an Deiner Stelle wirklich einfach mal
> ausprobieren, was passiert, wenn Du das wahlweise als HTTP 1.0-Request
> sendest

Mit den funktioniert das auch nicht:
1
  putString("GET /esp8266/haawrite.php?b0=0&b1=1&b2=2&b3=3&b4=4&b5=5&b6=6&b7=7 HTTP/1.0\r\nHost: 
2
3
192.168.1.100\r\n\r\n");

Joachim S. schrieb:
> zusätzlich einfach noch ein "Connection:
> close"-Header-Feld mit einfügst.

Ist das nicht hiermit schon geschehen ?
1
#define TCP_DISCONNECT  ("AT+CIPCLOSE\r\n")                  
2
3
//TCP-Verbindung schliessen

A.. P. schrieb:
> Ich würde aber an Stelle des TO doch einfach als ersten Ansatz einen
> korrekten Content-Length Header setzen, um ein eventuelles Problem mit
> dem Request-Body - welcher ja leer ist - auszuschließen.

Das verstehe ich nicht ganz. Wie kann ich das realisieren ?

Stefan U. schrieb:
> Weil er weder den Content-Length Header noch den Chunked-Transfer
> verwendet hat. Habe ich doch oben geschrieben. Ohne das kann er keinen
> 2. Request senden.

Ich verstehe nur Bahnhof :-(

A.. P. schrieb:
> Ob das nun seriell über das Terminal, über das nginx-Log oder
> mittels Wireshark erfolgt - irgendwas davon wird ihn sicher weiter
> bringen, als alle Diskussionen über den korrekten Aufbau einer Anfrage
> :)

Über den Terminal sieht die Zeichenlängeermittlung und die eigentliche 
GET-Anfrage wie auf dem Bild aus.

Das Wireshark hab ich ausprobiert. Wenn ich das richtig verstanden habe, 
brauche ich dafür WLAN am PC,

was ich nicht habe. Bleibt noch der nginx-log übrig. Da bin ich dran und 
werde berichten.

Das ist echt frustierend. Ich kann den Fehler immernoch nicht richtig 
reproduzieren. An einen Abend geht es nicht, am nächsten Tag 
funktioniert die Übermittlung wieder. Aber auch nur bis ich die 
Schaltung wieder aus- und einschalte.

Joachim S. schrieb:
> Meine C/C++-Kenntnisse sind zugegebenermassen äusserst gering, aber ist
> obiges Code-Fragment wirklich okay so? Ich hätte jetzt instinktiv
> vermutet, dass durch einchar cipsend[] = "AT+CIPSEND="nur 12 Bytes
> reserviert werden (also genau so viele, um den String
> "AT+CIPSEND=" sowie ein abschliessenden 0-Byte zu speichern). Und es
> durch die anschliessenden beiden strcat-Befehle dann zu einer Art
> Pufferüberlauf kommt, bei dem möglicherweise unbeabsichtigt etwas ganz
> anderes überschrieben wird, mit möglicherweise unvorhergesehenen Folgen.

Gute Adleraugen. Danke. Hab eine feste Größe zugewiesen:
1
char cipsend[15] = "AT+CIPSEND=";

von P. F. (pfuhsy)


Angehängte Dateien:

Lesenswert?

Jan L. schrieb:
> Falls es /var/log/nginx noch nicht geben sollte, und du dich vermutlich
> mit Dateirechten nicht recht auskennst :), kannst du einfach auch
> "/tmp/nginx_error.log" nehmen:
> error_log  /tmp/nginx_error.log info;

Ich kann die Datei nicht abspeichern. Was mache ich falsch ?

von P. F. (pfuhsy)


Lesenswert?

So, ich hab mir Root-Rechte gegeben und konnte die Datei abspeichern. 
Ein Haken hab ich bei der Sache. Ich hab den ganzen Server neu gestartet 
und die Datei wurde dann anscheinend neu geschrieben.
In welcher Datei dann ich das den reinschreiben was auch dann beim 
neustart erhalten bleibt ?

von P. F. (pfuhsy)


Angehängte Dateien:

Lesenswert?

Schwere Geburt, ich habs aber hinbekommen eine error_log zu schreiben.
Ich weiß nur nicht genau was Sie zu bedeuten habe. Kann jemand helfen ?

: Bearbeitet durch User
von Jan L. (ranzcopter)


Lesenswert?

...ein GET, HEAD oder PUT fehlt, der Request enthält nur eine URL...

von P. F. (pfuhsy)


Lesenswert?

Jan L. schrieb:
> ...ein GET, HEAD oder PUT fehlt, der Request enthält nur eine URL...

Na gut da hätte ich auch drauf kommen können. Ich dachte das "GET" wird 
wie die Zeilenumbrüche einfach nur nicht mit angezeigt.

Mittlerweile funktioniert es auch wieder, wenn ich zum einen die 
Funktion "TCP_Laenge" durch einen festen String ersetzte und zum anderen 
die Zählung der Länge anpasse. Mir ist echt schleierhaft, wie es dann 
vorher funktionieren konnte. Vielleicht hab ich etwas rausgelöscht ohne 
es zu merken. Naja aufjedenfall liegt es an der Zusammensetztung inkl. 
Längenermittlung.

In der Funktion zählt er immer 97 Bytes. Ich hab mit den Werten die er 
immer sendet die Zeichen gezählt und bin auf 102 gekommen, siehe unten. 
Selbst wenn ich das fehlende "GET " lösche komme ich nicht auf 97. Dabei 
habe ich immer "\r\n" als 2 Zeichen gezählt. Im kompletten String sind 
das dann 108-6.

So geht's:
1
putString("AT+CIPSEND=102\r\n");
2
putString("GET /esp8266/haawrite.php?b0=8&b1=50&b2=0&b3=0&b4=0&b5=17&b6=80&b7=0 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n")

Wenn jemand Lust hat, kann mir nen Tipp geben was an der 
zusammensetztung verkehrt ist.

Gruss und danke Männer.

von A.. P. (arnonym)


Lesenswert?

P. F. schrieb:
> Joachim S. schrieb:
>> zusätzlich einfach noch ein "Connection:
>> close"-Header-Feld mit einfügst.
>
> Ist das nicht hiermit schon geschehen ?

Nein. Der Befehl AT+CIPCLOSE weist den ESP an die TCP-Verbindung zu 
schließen. Wenn du deiner Anfrage aber noch ein "Connection: close" 
hinzufügst, so teilst du dem Server mit, dass dieser die Verbindung 
schließen soll, wenn die Antwort versendet wurde. Der Header ist dabei 
ein Teil des HTTP-Protokolls, welches über dem TCP-Protokoll liegt.

P. F. schrieb:
> A.. P. schrieb:
>> Ich würde aber an Stelle des TO doch einfach als ersten Ansatz einen
>> korrekten Content-Length Header setzen, um ein eventuelles Problem mit
>> dem Request-Body - welcher ja leer ist - auszuschließen.
>
> Das verstehe ich nicht ganz. Wie kann ich das realisieren ?

Genauso, wie du es doch schon mit dem Host Header gemacht hast. Einfach 
eine zusätzliche Zeile einfügen und die Content-Length angeben.

P. F. schrieb:
> Stefan U. schrieb:
>> Weil er weder den Content-Length Header noch den Chunked-Transfer
>> verwendet hat. Habe ich doch oben geschrieben. Ohne das kann er keinen
>> 2. Request senden.
>
> Ich verstehe nur Bahnhof :-(

Vielleicht solltest du dir nochmal ansehen, wie HTTP grundlegend 
funktioniert bzw. was so die wichtigsten Header sind. Das solltest du 
schon wissen, wenn du versuchst, selbstgestrickte Anfragen an deinen 
Server zu senden.

Gruß

: Bearbeitet durch User
von A.. P. (arnonym)


Lesenswert?

P. F. schrieb:
> Gute Adleraugen. Danke. Hab eine feste Größe zugewiesen:char cipsend[15]
> = "AT+CIPSEND=";

Das reicht aber immer noch nicht. Für den String "AT+CIPSEND=" (11 
Zeichen), eine dreistellige Zahl, das abschließende CRLF und das 
Null-Byte brauchst du 17 Zeichen Platz.

von Stefan F. (Gast)


Lesenswert?

Wartest du nach dem "AT+CIPSEND" Befehl eigentlich, bis der ESP die 
Eingabeaufforderung ">" für die Daten zurück gibt?

Wenn nicht ist kein Wunder, daß die Übertragung unvollständig ist.

Offensichtlich wartest du nicht, aber wer weiß wie der aktuelle 
Quelltext inzwischen aussieht.

von A.. P. (arnonym)


Lesenswert?

Stefan U. schrieb:
> Wartest du nach dem "AT+CIPSEND" Befehl eigentlich, bis der ESP die
> Eingabeaufforderung ">" für die Daten zurück gibt?

Mir ist auch schon aufgefallen, dass im obigen Code-Auszug das ">" 
nirgends auftaucht.

Stefan U. schrieb:
> Wenn nicht ist kein Wunder, daß die Übertragung unvollständig ist.

Das würde dann aber nicht zum Fehlerbild passen. Ich weiß gerade nicht 
genau, wie sich der ESP verhält, wenn er noch auf fehlende Zeichen 
wartet, aber ich glaube, dass er dann ewig wartet. Und weil er ewig 
wartet, werden die Daten gar nicht erst verschickt und es kommt erst gar 
keine Anfrage an den Server zustande. Und wo keine Anfrage kommt, kann 
ja auch kein Server antworten (die Antwort könnte ja sowieso nicht 
empfangen werden, da der ESP ja noch auf Zeichen wartet ;) )

von A.. P. (arnonym)


Lesenswert?

An den TO:

Woran lag's denn nun? Hat sich zwischenzeitlich was an deinem Problem 
getan? Wäre super, wenn du mit der Gemeinschaft auch deine Erfahrungen 
und Lösungen teilen würdest, damit auch andere davon profitieren können.

Gruß

von P. F. (pfuhsy)


Angehängte Dateien:

Lesenswert?

A.. P. schrieb:
> "Connection: close"
Sende ich das in der nächsten Schleife, kommt nur "Error" zurück. Das 
ist aber das Error vom ESP8266 und nicht vom Server, Bild 1.
1
case 2:
2
//TCP_Senden();      //Eigentliche Daten senden
3
putString("GET /esp8266/haawrite.php?b0=8&b1=50&b2=0&b3=0&b4=0&b5=17&b6=80&b7=0 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n");
4
//putString("Connection: close\r\n"); 
5
_ESP_Timeout_s = 0;    //Timeout-Zeit zurücksetzten
6
_ESP_Busy = true;    //Flag ESP ist beschäftigt      
7
break;
8
9
case 3:
10
ESP_Query("Connection: close\r\n", "OK");  //Verbindung schliessen
11
break;


Wenn ich den das direkt hinter dem Request sende, kommt ein "busy s..." 
Bild 2, übernimmt aber die Daten:
1
case 2:
2
//TCP_Senden();      //Eigentliche Daten senden
3
putString("GET /esp8266/haawrite.php?b0=8&b1=50&b2=0&b3=0&b4=0&b5=17&b6=80&b7=0 HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n");
4
putString("Connection: close\r\n"); 
5
_ESP_Timeout_s = 0;    //Timeout-Zeit zurücksetzten
6
_ESP_Busy = true;    //Flag ESP ist beschäftigt            
7
break;

So eine ähliche Anfrage hatte ich in einen Youtube-Video schonmal 
gesehen (https://www.youtube.com/watch?v=xZePXRjQOe8), jedoch 
funktioniert das "Connenction: close" bei mir an der selben Stelle nicht 
so richtig.

A.. P. schrieb:
> Vielleicht solltest du dir nochmal ansehen, wie HTTP grundlegend
> funktioniert bzw. was so die wichtigsten Header sind. Das solltest du
> schon wissen, wenn du versuchst, selbstgestrickte Anfragen an deinen
> Server zu senden.

Ja, ich werde mich mal einlesen.

A.. P. schrieb:
> Das reicht aber immer noch nicht. Für den String "AT+CIPSEND=" (11
> Zeichen), eine dreistellige Zahl, das abschließende CRLF und das
> Null-Byte brauchst du 17 Zeichen Platz.

Danke. Geändert.

Stefan U. schrieb:
> Wartest du nach dem "AT+CIPSEND" Befehl eigentlich, bis der ESP die
> Eingabeaufforderung ">" für die Daten zurück gibt?

Ne, ich such nach einem "OK". Danke für den Tip, werde ich mit 
einpflegen.

A.. P. schrieb:
> Woran lag's denn nun? Hat sich zwischenzeitlich was an deinem Problem
> getan? Wäre super, wenn du mit der Gemeinschaft auch deine Erfahrungen
> und Lösungen teilen würdest, damit auch andere davon profitieren können.

Wie schon ober geschrieben, klappt es ja jetzt nachdem ich den 
zusammengesetzten Request durch einen festen String ersetzt habe, weil 
dort anscheinend laut Server das "GET " gefehlt hat. Ich hatte mir den 
zusammengesetzten String ausgeben lassen, doch der war vollstädig. Warum 
die Zusammensetztung nicht geklappt hat und warum die dazu gehörige 
Ausgabe trotzdem richtig aussah, hab ich noch nicht feststellen können, 
dafür brauche ich noch etwas Zeit. Jetzt läuft es erstmal wieder und die 
nächsten Schritte wären, den Code aus Euren Hinweißen zu verbessern und 
die Zusammensetztung der Anfrage nochmal Schritt für Schritt neu 
aufzubauen. Wenn es soweit ist, werde ich natürlich berichten.

von Joachim S. (oyo)


Lesenswert?

P. F. schrieb:
>
1
> putString("GET 
2
> /esp8266/haawrite.php?b0=8&b1=50&b2=0&b3=0&b4=0&b5=17&b6=80&b7=0 
3
> HTTP/1.1\r\nHost: 192.168.1.100\r\n\r\n");
4
> putString("Connection: close\r\n");
5
>

"Connection: close" gehört in den Header Deines http-Requests und muss 
daher VOR der Zeichenfolge "\r\n\r\n" gesendet werden.
Schon aus diesem Grund würde ich übrigens empfehlen, in Deinen 
putString-Aufrufen nicht gleich den gesamten Request als langen 
mehrzeiligen String zu senden, sondern für jede Zeile einen eigenen 
Aufruf zu machen. z.B. so:
1
void putLine(char *line) {
2
  putString(line);
3
  putString("\r\n");
4
}
5
6
[...]
7
putLine("GET /esp8266/haawrite.php?b0=8&b1=50&b2=0&b3=0&b4=0&b5=17&b6=80&b7=0 HTTP/1.1");
8
putLine("Host: 192.168.1.100");
9
putLine("Connection: close");
10
putLine("");
11
[...]
Mittlerweile glaube ich allerdings nicht mehr, dass das Problem 
überhaupt mit dem "Connection: close" zusammenhängt. Ich tippe derzeit 
eher auf irgendwelche versehentlichen Pufferüberläufe - der ganze Code 
erscheint mir ehrlich gesagt ein wenig umständlich und fehleranfällig... 
:(

von P. F. (pfuhsy)


Lesenswert?

Joachim S. schrieb:
> void putLine(char *line) {
>   putString(line);
>   putString("\r\n");
> }

Ich hab es ausgetestet. Es macht kein Unterschied zu meinen Request von 
oben: "Wenn ich den das direkt hinter dem Request sende, kommt ein "busy 
s..."
Bild 2, übernimmt aber die Daten:"

Joachim S. schrieb:
> Mittlerweile glaube ich allerdings nicht mehr, dass das Problem
> überhaupt mit dem "Connection: close" zusammenhängt. Ich tippe derzeit
> eher auf irgendwelche versehentlichen Pufferüberläufe - der ganze Code
> erscheint mir ehrlich gesagt ein wenig umständlich und fehleranfällig...
> :(

Recht hast du. Es ist gerade die v1.0 welche stetig verbessert wird. 
Natürlich versuche ich schon da den Code so gut wie möglich zu 
gestalten, jedoch sollen die hauptsächlichen Dinge, wie erfolgreiches 
Senden der Daten, funktionieren. In der Zeit hänge ich die Schaltung an 
meine Alarmanlage während der Code damit getestet und verbessert werden 
soll. Ich bin eigentlich ganz froh, wenn jemand einen Fehler entdeckt 
während ich den Wald vor lauter Bäumen nicht sehe.

von P. F. (pfuhsy)


Lesenswert?

Hallo zusammen,

nach stundenlanger suche bin ich jetzt doch fündig geworden. Ich habe 
ein Array für empfangene UART-Daten "_uart_string[50]". Anscheindend war 
der reserierte Speicherplatz nicht ausreichend und ist beim überlauf auf 
den Speicherbreich der Variable des zusammengesetzten GET-Request 
gefallen. Dabei wurde mal die erste 4 Zeichen "GET " überschrieben und 
mal wieder nicht, was die Fehlersuche deutlich erschwert hat. Ich hatte 
zwar ein Überlaufschutz eingebaut, nur leider war der fehlerhaft:
1
ISR (USART_RXC_vect)    //Interrupt wird ausgelöst sobald neue Daten im USART-Empfangspuffer liegen
2
{
3
  volatile static uint8_t count = 0;    //Char-Zähler
4
  
5
  //String ist noch nicht komplett
6
  if (!_uart_str_complete)
7
  {
8
    if(UDR != '\n' && count < 50)    //kein Abschlusszeichen vorhanden oder Arraylänge erreicht TODO Länge selbst ermitteln
9
    {
10
      _uart_string[count] = UDR;        //in Array schreiben
11
      count++;                //Array-Zähler inkrementieren
12
    }
13
    else
14
    {
15
      _uart_string[count]='\0';        //String abschliessen
16
      count = 0;                //Zähler zurücksetzten
17
      _uart_str_complete = true;        //String komplett
18
    }
19
  }    
20
  
21
}

Jetzt sieht er besser aus und der Fehler ist bis jetzt nicht mehr 
aufgetaucht:
1
ISR (USART_RXC_vect)    //Interrupt wird ausgelöst sobald neue Daten im USART-Empfangspuffer liegen
2
{
3
  volatile static uint8_t count = 0;    //Char-Zähler
4
  
5
  //String ist noch nicht komplett
6
  if (!_uart_str_complete)
7
  {
8
    //kein Abschlusszeichen vorhanden
9
    if(UDR != '\n')    
10
    {
11
      _uart_string[count] = UDR;        //in Array schreiben
12
      count++;                //Array-Zähler inkrementieren
13
    }
14
    else
15
    {
16
      _uart_string[count]='\0';        //String abschliessen
17
      count = 0;                //Zähler zurücksetzten
18
      _uart_str_complete = true;        //String komplett
19
    }
20
    
21
    //Arraylänge erreicht
22
    if (count >= sizeof(_uart_string) - 1)    
23
    {
24
      count = 0;                //Zähler zurücksetzten
25
    }
26
  }    
27
  
28
}

von Stefan F. (Gast)


Lesenswert?

Danke für die Rückmeldung. So können andere noch was daraus lernen.

von A.. P. (arnonym)


Lesenswert?

Und bei diesem Beispiel zeigt sich wieder, dass es nur hilfreich ist, 
den gesamten Code zu posten und nicht nur Teile, von denen man selbst 
"denkt", dass da der Fehler drin steckt. Wie nun deutlich zu erkennen 
war, haben alle Beteiligten die ganze Zeit an der falschen Stelle 
gesucht und die wildesten Annahmen getroffen, ohne zu wissen, dass 
irgendwo in diesem Spaghetti-Code noch die ominöse Variable 
"_uart_string" auf eigenartige Weise zusammengesetzt wird -_-

: Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.