Forum: Mikrocontroller und Digitale Elektronik Hilfe - ESP8266 mittels HTTPClient Daten an ESP32 senden


von Adrian S. (adrians)


Lesenswert?

Guten Tag liebes Forum

Ich habe folgendes Problem:
Gerne möchte ich von einem bestehenden Projekt ( www.iSpindel.de ) Daten 
an einen ESP32 senden und diese ausgeben.
Der ESP8266 sendet daten mittels HTTPClient an eine IP die ich mit dem 
ESP32 als einem Access Point stelle, somit die Idee. Im quellcode des 
iSpindel-Projektes fans ich auch die Sende-Funktion, nur habe ich weiter 
keine ahnung wie ich die Daten nun angezeigt bekomme...

Die Sender-Funktion:
1
bool SenderClass::sendGenericPost(String server, String uri, uint16_t port)
2
{
3
    serializeJson(_doc, Serial);
4
    HTTPClient http;
5
6
    CONSOLELN(F("HTTPAPI: posting"));
7
    // configure traged server and uri
8
    http.begin(_client, server, port, uri);
9
    http.addHeader("User-Agent", "iSpindel");
10
    http.addHeader("Connection", "close");
11
    http.addHeader("Content-Type", "application/json");
12
13
    String json;
14
    serializeJson(_doc, json);
15
    auto httpCode = http.POST(json);
16
    CONSOLELN(String(F("code: ")) + httpCode);
17
18
    // httpCode will be negative on error
19
    if (httpCode > 0)
20
    {
21
        if (httpCode == HTTP_CODE_OK)
22
        {
23
            CONSOLELN(http.getString());
24
        }
25
    }
26
    else
27
    {
28
        CONSOLE(F("[HTTP] POST... failed, error: "));
29
        CONSOLELN(http.errorToString(httpCode));
30
    }
31
32
    http.end();
33
    stopclient();
34
    return true;
35
}

Den Client für die Verbindung zum AP kann ich über einen Config-Modus 
des ESP8266 eingeben (Dieser fungiert dann als AP um die 
verbindungsdaten wie SSID, Passwort, Port, Server, etc.)

Die SerialMonitor ausgabe des ESP8266 sieht folgendermassen aus:
1
FW 6.5.1
2
2.2.2-dev(38a443e)
3
Worker run!
4
mounting FS... mounted!
5
reading config file
6
parsed config:
7
{"Name":"iSpindel000","Token":"","Sleep":60,"Server":"192.168.4.1","API":3,"Port":80,"Channel":0,"URI":"","DB":"ispindel","Username":"","Password":"","Job":"ispindel","Instance":"000","Vfact":191.8,"TS":0,"OWpin":12,"POLY":"-0.00031*tilt^2+0.557*tilt-14.054","SSID":"ServerAP","PSK":"ServerAP","Offset":[0,0,0,0,0,0]}
8
offsets not available
9
Boot-Mode: Deep-Sleep Wake
10
11
woken from deepsleep, normal mode
12
Samples:42 min:86.71 max:87.23 time:756
13
x: 3218 y: 14818 z: 734
14
Tilt: 86.93
15
Tacc: 25.50
16
Volt: 4.11
17
Temp: 22.88
18
Gravity: 32.02
19
IP: 192.168.4.2
20
21
calling HTTP
22
{"name":"iSpindel000","ID":4962171,"angle":86.92661,"temperature":22.875,"temp_units":"C","battery":4.108446,"gravity":32.02169,"interval":60,"RSSI":-45}HTTPAPI: posting
23
code: 500
24
25
Final-sleep: 60s; RT: 1237

Der HTTP_CODE 500 ist doch ein Interner Server Error des Access Point, 
oder? Was mache ich falsch?

Der code des ESP32 sieht so aus (zeigt momentan nur die IP-Adresse am 
Display):
1
#include <Arduino.h>
2
#include <TFT_eSPI.h> 
3
#include <SPI.h>
4
#include <WiFi.h>
5
#include <AsyncTCP.h>
6
#include <ESPAsyncWebServer.h>
7
8
9
10
const char* ssid = "ServerAP";
11
const char* password = "ServerAP";
12
13
AsyncWebServer server(80);
14
15
#define COLOR_BLUE 0x001F
16
#define COLOR_GREEN 0x07E0
17
18
TFT_eSPI tft = TFT_eSPI(); 
19
int rotation = 0;
20
21
22
23
void initAP() {
24
 WiFi.mode(WIFI_AP);
25
 WiFi.softAP(ssid, password);
26
}
27
28
void setup() {
29
  Serial.begin(115200);
30
  
31
  initAP();
32
  server.begin();
33
  IPAddress IP = WiFi.softAPIP();
34
  
35
  tft.init();
36
  tft.setRotation(rotation);
37
  tft.setTextSize(1);
38
  tft.fillScreen(TFT_BLACK); 
39
  tft.setCursor(5, 10);
40
  tft.setTextColor(TFT_WHITE);
41
  tft.print("AP-IP:");
42
  tft.print(IP);
43
44
}
45
46
void loop() {
47
48
}

von Brain 2.0 (Gast)


Lesenswert?

Warum verwendest du nicht UDP zur Datenübertragung?
Damit ist das einfach gelöst.

von Adrian S. (adrians)


Lesenswert?

Brain 2.0 schrieb:
> Warum verwendest du nicht UDP zur Datenübertragung?
> Damit ist das einfach gelöst.

Dies wird soweit ich das sehe von der iSpindel leider nicht unterstützt.

von Stefan F. (Gast)


Lesenswert?

Ich sehe in deinem ESP32 Quelltext nur zwei relevante Zeilen:
1
AsyncWebServer server(80);
2
server.begin();

Was denkst du denn, welche Funktionen dieser Webserver so von Hause aus 
mit bringt?

Ich kenne den AsyncWebServer nicht. Aber ich bin mir ziemlich sicher, 
dass du selbst programmieren musst, wie der Webserver auf bestimmte HTTP 
requests antworten soll. Solange du das nicht tust, wird er einfach alle 
Requests mit einem Fehlercode beantworten, da er mit keinem Request 
etwas anfangen kann.

Schau dir mal dieses Projekt an: 
https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/

Und achte dort darauf, was der Autor mit "server.on(...)" angestellt 
hat.

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> Dies (UDP) wird soweit ich das sehe von der iSpindel leider nicht unterstützt.

Kann nicht sein, UDP wird vom Firmware-Kern des ESP8266 und Arduino 
unterstützt. Siehe dazu 
http://stefanfrings.de/esp8266/index.html#udpsketch

Mit UDP geht das wirklich viel einfacher.

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> Schau dir mal dieses Projekt an:
> 
https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/
>
> Und achte dort darauf, was der Autor mit "server.on(...)" angestellt
> hat.

Vielen Dank, werde mich da mal reinlesen. Habe bis jetzt nur Beispiele 
gefunden wo die Sensordaten von einem Server an den Client via GET 
gesendet werden.
Da ich nicht weiss wie ich die Daten die als POST von nem Client an den 
Server gesendet werden ausgelesen werden, suchte ich hier Hilfe^^

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> Mit UDP geht das wirklich viel einfacher.

Leider kann ich den Code der iSpindel nicht ändern und auf den ESP 
flashen da ich den in VSC nicht Compiliert kriege.

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> Habe bis jetzt nur Beispiele
> gefunden wo die Sensordaten von einem Server an den Client via GET
> gesendet werden.

Du meinst vom Client an den Server. HTTP Server können nichts 
irgendwohin senden, nur Anfragen von Clients beantworten.

HTTP POST Request haben (im Gegensatz zu GET) nach den Headern eine 
Leerzeile und dann Nutzdaten in beliebigem Format. Typischerweise JSON.

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> HTTP POST Request haben (im Gegensatz zu GET) nach den Headern eine
> Leerzeile und dann Nutzdaten in beliebigem Format. Typischerweise JSON.

Die Daten des ESP8266 werden doch als JSON mittels Post an den 
AccesPoint gesendet?
1
    String json;
2
    serializeJson(_doc, json);
3
    auto httpCode = http.POST(json);

Danach geht der Client 60s in DeepSleep Modus und kann doch via GET vom 
Server nicht angesprochen werden?

von Stefan F. (Gast)


Lesenswert?

Du kannst auf deinem PC HTTP requests mit Netcat empfangen/darstellen. 
Beispiel für einen HTTP-GET Request auf http://localhost:8080
1
nc -l -p 8080
2
3
GET / HTTP/1.1
4
Host: localhost:8080
5
Connection: keep-alive
6
sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="90"
7
sec-ch-ua-mobile: ?0
8
DNT: 1
9
Upgrade-Insecure-Requests: 1
10
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36
11
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
12
Sec-Fetch-Site: none
13
Sec-Fetch-Mode: navigate
14
Sec-Fetch-User: ?1
15
Sec-Fetch-Dest: document
16
Accept-Encoding: gzip, deflate, br
17
Accept-Language: de-DE,de;q=0.9,en-US;q=0.8,en;q=0.7

Drücke dann Strg-C.

http://stefanfrings.de/avr_tools/netcat-win32-1.12.zip

Das ist kein Virus, auch wenn Windows das meint.

von Stefan F. (Gast)


Lesenswert?

So sieht ein minimaler POST Request aus, wenn ich ihn mit curl an 
http://localhost:8080 sende:
1
nc -l -p 8080
2
3
POST / HTTP/1.1
4
Host: localhost:8080
5
User-Agent: curl/7.74.0
6
Accept: */*
7
Content-Length: 11
8
Content-Type: application/x-www-form-urlencoded
9
10
Halli Hallo

In diesem Fall ist "Halli Hallo" die Payload (die Nutzdaten).

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> Danach geht der Client 60s in DeepSleep Modus und kann doch via GET vom
> Server nicht angesprochen werden?

Nur HTTP Server sind ansprechbar. Clients nicht.

HTTP Clients senden Requests an HTTP Server. HTTP Server müssen sie 
beantworten.

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> Schau dir mal dieses Projekt an:
> 
https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/

Verstehe nicht wie ich das für mein Projekt nutzen kann... Sorry falls 
es für dich logisch ist, für mich jedoch nicht.

von Irgend W. (Firma: egal) (irgendwer)


Lesenswert?

Adrian S. schrieb:
> ,"URI":"",

Da scheint schomal was zu fehlen.

Normalerweise fragt der Client ja den Server z.B. mit sowas an:
- (wenn GET verwendet wird) 
http://192.0.0.1/committemp.php?param1=10&param2=50
- (wenn POST verwendet wird) http://192.0.0.1/committemp.php und die 
Parameter werden in entsprechenden Feldern übertragen

Das setzt aber auch vorraus das der Web-Server "committemp.php" 
überhaupt kennt und das script auch in der Lage ist die gesendeten 
Parameter zu verarbeiten. Denn Web-Server interessieren die Daten 
erstmal recht wenig, der reicht die einfach nur an die Aufgerufenen 
Seite (die natürlich im request angegen sein muss und auch vorhanden 
sein muss) weiter und diese muss sich darum kümmern.

Da scheint bei dir auf beiden Seiten so einiges zu fehlen...

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> 
https://randomnerdtutorials.com/esp32-async-web-server-espasyncwebserver-library/
>
> Verstehe nicht wie ich das für mein Projekt nutzen kann... Sorry falls
> es für dich logisch ist, für mich jedoch nicht.

Das Projekt nutzt die server.on() Funktion, die auch du nutzen muss. 
Lies die Dokumentation von der Arduino Bibliothek. Ich kann das nicht 
für dich erledigen. Ich kann dir nur versichern dass ich in diesem 
Quelltext nichts überraschendes sehe. Mit Arduino habe ich auch keine 
Erfahrung, ich programmiere Java EE Server, welche allerdings auf dem 
selben Prinzip beruhen.

Hier ist die Doku: https://github.com/me-no-dev/ESPAsyncWebServer

von Adrian S. (adrians)


Lesenswert?

ich bin mittlerweile ein ganzes Stück weiter (für mich jedenfalls^^).

Den Code am ESP32 hab ich um das Snipsel
1
  server.on("/", HTTP_POST, [](AsyncWebServerRequest *request) {
2
    Serial.println(request->contentType());
3
    Serial.println(request->contentLength());
4
    request->send(200);
5
  });
erweitert.

Nun habe ich am Serial Monitor die Ausgabe

application/json
154

was nun das nächste Problem bringt die Daten in Variabeln zu 
speichern...

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> was nun das nächste Problem bringt die Daten in Variabeln zu
> speichern...

Du hast ja JSON, dafür gibt es einen extra handler, der den Zugriff 
vereinfacht: 
https://github.com/me-no-dev/ESPAsyncWebServer/blob/master/src/AsyncJson.h

Als nächstes schau dir die Doku oder den Quelltext von JsonObject an, um 
herauszufinden wie du auf die Inhalte des Objektes zugreifen kannst.

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> Als nächstes schau dir die Doku oder den Quelltext von JsonObject an, um
> herauszufinden wie du auf die Inhalte des Objektes zugreifen kannst.

Kannst du mir nen Tip geben? Bliche da nicht durch den Quellcode...

von Stefan F. (Gast)


Lesenswert?

Adrian S. schrieb:
> Kannst du mir nen Tip geben?

Nein tut mir leid, ich habe das noch nie benutzt.

von Adrian S. (adrians)


Lesenswert?

Stefan ⛄ F. schrieb:
> Adrian S. schrieb:
>> Kannst du mir nen Tip geben?
>
> Nein tut mir leid, ich habe das noch nie benutzt.

Werde da wohl einen eigenen Post zu dem Thema machen, Danke dir vielmals 
für deine Hilfe :)

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.