Mit ESP8266 Daten via POST senden

  • Hallo zusammen,

    mein Ziel ist es mit dem ESP Daten via POST zu senden. In der Grundform wie z.B hier beschrieben (hierauf basiert auch mein Code) funktioniert es auch. Allerdings (sofern ich richtig informiert bin) kann man doch auch bei POST den Daten "Felder" zuordnen und hierbei habe ich Probleme dies zu realisieren.

    Als Server der die Daten entgegennimmt hab ich zum Testen einen kleinen Flask Server im Betrieb - dies kommt später aber so nicht in Verwendung:

    Mein Problem ist, dass er mir sagt das bei der Übertragung kein Text Feld existiert, somit vermute ich mal das ich einen Fehler im ESP Code habe.

    Fehlermeldung:

    In Zeile Nummer 27, wo so denke ich der Schlüssel liegt, habe ich auch schon mehrere Variationen versucht wie:

    int httpCode = http.POST("&text=Message from ESP8266&test=Testmassage");

    Wo liegt mein Fehler?

  • Schau mal hier: https://stackoverflow.com/a/14551320/5952681

    Zeile 25, in deinem ESP-Code - da kommt flask gar nicht auf die Idee, da ein dict o.ä. aus dem POST-Body zu machen, du sagst ja, es sei einfach nur Text. Der passende Content-Type ist in dem Fall application/x-www-form-urlencoded. IMHO macht es, wenn der Inhalt vielseitiger/komplexer wird, schnell Sinn, JSON zu verwenden.

  • Gerade getestet .... funktioniert wie gewüscht.

    Das kommt wohl davon wenn man mehrere Anleitungen miteinander verschmelzt. Hier wäre es sogar auch verwendet worden, nur da konzentrierte ich mich mehr darauf wie die die einzelenen Felder zusammensetzen.

    Vielen Dank für die schnelle Hilfe :danke_ATDE:

  • > Gerade getestet .... funktioniert wie gewüscht.

    Das mag zwar jetzt funktionieren, aber sauber ist es nicht. Die Spaces im Text sind eigentlich nicht erlaubt und sollten codiert werden:

    http.POST("text=Message%20from%20ESP8266&test=Testmassage");

    Ich habe im Kopf dass das Space auch durch ein '+' codiert werden kann, finde aber gerade keine Referenz...

  • Ich werfe euch mal einen Haufen Links an den Kopf, TL; DR - ich denke, Tell hat Recht (es heißt ja "x-www-form-urlencoded")


    https://www.w3.org/TR/html401/interact/forms.html ist offiziell, da sind wir uns hoffentlich alle einig. Dort heißt es:

    Zitat

    application/x-www-form-urlencoded

    This is the default content type. Forms submitted with this content type must be encoded as follows:

    1. Control names and values are escaped. Space characters are replaced by `+', and then reserved characters are escaped as described in [RFC1738], section 2.2: Non-alphanumeric characters are replaced by `%HH', a percent sign and two hexadecimal digits representing the ASCII code of the character. Line breaks are represented as "CR LF" pairs (i.e., `%0D%0A').
    2. The control names/values are listed in the order they appear in the document. The name is separated from the value by `=' and name/value pairs are separated from each other by `&'.

    Im MDN hingegen heißt es (keine rede von Spaces durch + ersetzen, sondern percent-encoded, wie alles andere):

    Zitat

    application/x-www-form-urlencoded: the keys and values are encoded in key-value tuples separated by '&', with a '=' between the key and the value. Non-alphanumeric characters in both keys and values are percent encoded: this is the reason why this type is not suitable to use with binary data (use multipart/form-data instead)

    Wikipedia sagt Spaces durch + ersetzen, dort wird als Quelle aber vermutlich ein W3C Dokument genannt ;)

  • Hallo,

    ok, Korrektur: wenn man `application/x-www-form-urlencoded` nimmt, dann wird wirklich das Percent Encoding angewendet.

    Wobei dann noch die Frage offen bleibt, wer sich darum kümmert. Bei Formularen im Browser macht's der Browser, bei Programmen wie HTTPie kümmer sich das Programm darum, beim Klassiker cURL auch das Programm mit dem passenden Parameter

    Andere mit bekannte Python Frameworks machen da auch automatisch. Keine Ahnung, wie sich `ESP8266HTTPClient.h` verhält. Wenn, wie Hofei sagt, alles wie gewünscht funktioniert, dann wird das automatische Encoding (und Decoding seitens Flask) IMHO richtig durchgeführt.

    Gruß, noisefloor

  • Experiment: das macht Chromium aus Text mit Spaces:

    Code
    Content-Type: application/x-www-form-urlencoded
    
    0000   74 65 78 74 3d 74 65 78 74 2b 6d 69 74 2b 73 70  text=text+mit+sp
    0010   61 63 65 73 26 73 65 6c 65 63 74 3d 31           aces&select=1

    Klar, das muss nicht unbedingt der Norm entsprechen, aber bisher verstanden alle Server was Chromium geschickt hat.

    • Offizieller Beitrag

    Hallo,

    also erstmal sorry Leute! Ich frage mich nur gerade: Weshalb sollte der Inhalt des mit Post gesendeten Datenblocks direkt etwas mit urlencode zu tun haben? Wenn ich z.B. ein Bild auf einen Webserver lade, dann wird dieser doch auch nicht urlencodiert oder? Weshalb sollte das bei Text (Variablen) anders sein? :conf:

    Bei einem Request per GET ist das schon etwas völlig anderes, da bei diesem quasi nur eine URL gesendet wird. URI != URL

    Ich lerne auch gerne dazu und habe evtl. falsch, dann bitte ich um Aufklärung. ;)

    • Offizieller Beitrag

    Imho ganz im Gegenteil. Er hat "Content-Type", "text/plain" mit der Methode Post gewählt. Das macht doch das Codieren der Spaces erst recht unnötig.;) Oder habe ich gerade einen Denkfehler oder / und das Thema verfehlt? :conf:

  • Hallo,

    Zitat

    Wenn ich z.B. ein Bild auf einen Webserver lade, dann wird dieser doch auch nicht urlencodiert oder?

    Nein, das funktioniert nicht. Wenn du binäre Daten hochlädst, dann brauchst du einen anderen MIME-Typ, nämlich `form/multipart`.

    Zitat

    Oder habe ich gerade einen Denkfehler oder / und das Thema verfehlt?

    So halb. Das Problem was, dass Flask die POST-Daten nicht geparst hat. Was wiederum am falschen MIME-Typ im Ausgangspost lag :)

    Tell meinte aber, dass auch nach Änderung des MIME-Typs die Leerzeichen als `+` schon im String im ESP8266 C-Code "kodiert" sein müssten.

    Flask kann, BTW, ootb keinen Text bei `text/plain` aus dem Body eines POST-Request parsen, dazu muss man einen eigenen (sehr simplen) Parser schreiben: Link

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!