Sziasztok!
Csináltam egy ESP8266 alapon egy 5 csatornás hőmérsékletmérő eszközt, ami WiFi-n HTTP POST-al tolná
föl az adatokat egy szerverre. (Arduino framework, Platform.IO)
Nem értem, a válasz a POST kérésnek:
"HTTP Response code: 400" - tehát valami szintaktikai hiba lehet?! Már a szemem kifolyik, nem találom
a hibám.
Ez a programrész:
bool puthttp() { bool result = false; long rssi = WiFi.RSSI(); String localip = WiFi.localIP().toString(); WiFiClient client; HTTPClient http; char jsonstr[400]; char jsonstr2[100]; char jsonstr3[30]; Serial.println(serverstr); snprintf(jsonstr, sizeof(jsonstr), "{\"device_id\":%d, \"ip_address\":\"%s\", \"ssid\":\"%s\", \"rssi\":%d, ",didx,localip.c_str(),ssidstr,rssi); snprintf(jsonstr2, sizeof(jsonstr2), "\"value_1\":%.1f, \"value_2\":%.1f, \"value_3\":%.1f, \"value_4\":%.1f, \"value_5\":%.1f, ",hom1,hom2,hom3,hom4,hom5); snprintf(jsonstr3, sizeof(jsonstr3), "\"timestamp\":%ld}", helyiUTC); strncat(jsonstr, jsonstr2, sizeof(jsonstr2)); strncat(jsonstr, jsonstr3, sizeof(jsonstr3)); Serial.println(jsonstr); // Your Domain name with URL path or IP address with path Serial.print("http.begin:"); bool mi = http.begin(client, serverstr); Serial.println(mi); http.addHeader("Content-Type", "application/json"); int httpResponseCode = http.POST(jsonstr); //int httpResponseCode = http.POST("{\"value\": 20 }"); Serial.print("HTTP Response code: "); Serial.println(httpResponseCode); http.end(); if (httpResponseCode == 200) result = true; return result; }
És ez a készített "jsonstr":
{"device_id":10170, "ip_address":"192.168.3.162", "ssid":"gentoom", "rssi":-62, "value_1":22.8, "value_2":-100.0,
"value_3":-100.0, "value_4":-100.0, "value_5":-100.0, "timestamp":1709045163}
Köszönöm!
Roland
- 905 megtekintés
Hozzászólások
Maga amit küldesz, az valid JSON. A kérdés az, hogy a szerveroldal ugyanilyen struktúrájú JSON-t vár-e el, vagy esetleg valamelyik mező neve vagy típusa eltérő, esetleg van hiányzó kötelező mező stb. A szerver logjában mi látszik? Azt is el tudom képzelni, hogy a value az egy tömb, azaz nem value_1, value_2, value_3, value_4, value_5 mező kéne neki külön-külön, hanem egy ilyen json:
{
"device_id": 10170,
"ip_address": "192.168.3.162",
"ssid": "gentoom",
"rssi": -62,
"value": [22.8, -100.0, -100.0, -100.0, -100.0],
"timestamp": 1709045163
}
De ezt csak a fogadóoldali kód ismeretében tudjuk eldönteni, hiszen ő mondja azt, hogy nem megfelelő a kérés.
- A hozzászóláshoz be kell jelentkezni
A szerverig el sem jut.
Egyébként a szervert nem én használom/csináltam.
Ennyit kaptam az ottani gazditól (így várja az adatokat):
> A végpont:
> https://xxxxx.xx:8080
>
> A kérés:
> POST
> headers: {
> 'Content-Type': 'application/json'
> }
>
> Body data:
>
> {
> "device_id": 1,
> "ip_address": "192.168.1.123",
> "ssid": "Sample_SSID",
> "rssi": -41,
> "value_1": 18.1,
> "value_2": 18.2,
> "value_3": 18.3,
> "value_4": 18.4,
> "value_5": 18.5,
> "timestamp": 1708478505
> }
- A hozzászóláshoz be kell jelentkezni
A szerverig el sem jut.
Hát, oedig 400as responseot az szokott adni szóval gyanusan de.
- A hozzászóláshoz be kell jelentkezni
A szerverig el sem jut.
Ez butaság, ami visszaadja neked a HTTP 400-as választ, az csak a szerver lehet.
- A hozzászóláshoz be kell jelentkezni
Gyanús, hogy te sima httpt küldesz.
- A hozzászóláshoz be kell jelentkezni
Ha `curl` parancssorból meghívod ugyanezt, ugyanígy, akkor az mit ír? Egyszerűbb kitapasztalni a kommunikációs hibákat CLI-ben, mint ESP8266-on.
- A hozzászóláshoz be kell jelentkezni
jó ötlet. teszt.
- A hozzászóláshoz be kell jelentkezni
Ez lett:
domo@domo2:~$ curl -X POST https://xxxxxxx.hu:8080 -H "Content-Type: application/json" -d '{"device_id":10170, "ip_address":"192.168.3.162", "ssid":"gentoom", "rssi":-62, "value_1":22.8, "value_2":-100.0,
"value_3":-100.0, "value_4":-100.0, "value_5":-100.0, "timestamp":1709045163}'
curl: (60) SSL certificate problem: self signed certificate
More details here: https://curl.se/docs/sslcerts.html
curl failed to verify the legitimacy of the server and therefore could not
establish a secure connection to it. To learn more about this situation and
how to fix it, please visit the web page mentioned above.
domo@domo2:~$
Érdekes, mert ESPHome-ban így megy:
- http_request.post:
url: https://xxxxxx.hu:8080
headers:
Content-Type: application/json
verify_ssl: false
json: |-
//root["device_id"] = 10000 + id(vegeIP);
root["device_id"] = id(deviceid).state;
root["ip_address"] = WiFi.localIP().toString();
root["ssid"] = WiFi.SSID();
root["rssi"] = int(id(wifiero).state);
root["value_1"] = (!isnan(id(hom1).state) ? id(hom1).state : 0.0);
root["value_2"] = (!isnan(id(hom2).state) ? id(hom2).state : 0.0);
root["value_3"] = (!isnan(id(hom3).state) ? id(hom3).state : 0.0);
root["value_4"] = (!isnan(id(hom4).state) ? id(hom4).state : 0.0);
root["value_5"] = (!isnan(id(hom5).state) ? id(hom5).state : 0.0);
root["timestamp"] = id(idosntp).now().timestamp;
- A hozzászóláshoz be kell jelentkezni
curl ... -k ... -ezzel megy!
curl -X POST https://xxxxxxxxx.hu:8080 -k -H "Content-Type: application/json" -d '{"device_id":10170, "ip_address":"192.168.3.162", "ssid":"gentoom", "rssi":-62, "value_1":22.8, "value_2":-100.0,
"value_3":-100.0, "value_4":-100.0, "value_5":-100.0, "timestamp":1709066827}'
Na, csak ezt kell az ESP8266-ra átírni ...-k...
- A hozzászóláshoz be kell jelentkezni
Mi a serverstr
?
- A hozzászóláshoz be kell jelentkezni
String serverstr = "https://xxxxx.xx:8080"
- A hozzászóláshoz be kell jelentkezni
Azt vedd figyelembe, hogy ESP8266-ról a https nem fog ilyen egyszerűen menni.
- A hozzászóláshoz be kell jelentkezni
Faék egyszerű
WiFiClientSecure client;
client.setInsecure();
httpClient.begin(client, URL);
- A hozzászóláshoz be kell jelentkezni
Köszönöm!
Ezzel megy!
- A hozzászóláshoz be kell jelentkezni
egyszerűen működik :) Utólag. Az itteni segítséggel.
- A hozzászóláshoz be kell jelentkezni
Nem, úgy megkerülöd az egész értelmét, ami miatt https-t használnál.
- A hozzászóláshoz be kell jelentkezni
Jelen feladatnál szerintem tök felesleges hülyére titkosítani a kommunikációt. Egyébként jogos.
- A hozzászóláshoz be kell jelentkezni
Szerintem is. Sajna a szerver üzemeltetője így kéri.
- A hozzászóláshoz be kell jelentkezni
Lehetne egy http.getString()
a történetben, hátha van valami hibaüzenet.
- A hozzászóláshoz be kell jelentkezni
Érdekes jelenség - most látom.
A rutin első lefutásakor 200 a válasz (jó!), aztán utána x percre rá már -1! és így már nem megy. Nyomozom, hogy mitől lehet, ha ugyanazt hívom meg.
- A hozzászóláshoz be kell jelentkezni
Ez amugy netes kommunikacio vagy helyi?
En ugy tudom, lehet hasznalni a WiFiClientSecure-t self signed-el is.
https://github.com/espressif/arduino-esp32/issues/265
Vagy az uzemeltetonek kene szolni hogy dobjon ra egy Let's Encrypt-et..
- A hozzászóláshoz be kell jelentkezni
Netes.
Amúgy meg pont l.. Nekem így ok. Ha neki ez jó...
- A hozzászóláshoz be kell jelentkezni
ezt hogy érted? Ez így nem tetszik a fordítónak.
- A hozzászóláshoz be kell jelentkezni
Nekem ez müxik:
void sendpost() {
String purl = posts.substring(0, posts.indexOf(")"));
String pdata = addvalstr(posts.substring(posts.indexOf("@") + 1, posts.length()));
if (purl.substring(0, 4) != "http") { purl = F("http://") + purl; }
HTTPClient httpClient;
WiFiClient *client = nullptr;
WiFiClientSecure *clients = nullptr;
if (purl.substring(0, 5) == "https") {
clients = new WiFiClientSecure;
clients->setInsecure();
httpClient.begin(*clients, purl);
} else {
client = new WiFiClient;
httpClient.begin(*client, purl);
}
httpClient.addHeader(F("Content-Type"), F("application/x-www-form-urlencoded"));
poste = httpClient.POST(pdata);
postg = httpClient.getString();
httpClient.end();
delete client;
delete clients;
}
- A hozzászóláshoz be kell jelentkezni
én ezt kapom (ESP8266, platform.io - arduino framework)
"include/httppost.h:55:12: error: type 'class BearSSL::WiFiClientSecure' argument given to 'delete', expected pointer
55 | delete client;"
- A hozzászóláshoz be kell jelentkezni
HTTPClient http;
WiFiClientSecure *client = new WiFiClientSecure;
client->setInsecure();
http.begin(*client, URL);
//
//
//
delete client;
- A hozzászóláshoz be kell jelentkezni
Valamit nagyon elbökök:
Exception (29):
epc1=0x4000df64 epc2=0x00000000 epc3=0x00000000 excvaddr=0x00000000 depc=0x00000000
StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores
>>>stack>>>
ctx: sys
- A hozzászóláshoz be kell jelentkezni
lehet amiatt, hogy bent hagytam a http.end(); utasítást? Azaz, most látom 2x volt... Nem elmaradt
- A hozzászóláshoz be kell jelentkezni
bár lefordult, hogy nem volt:
#include <WiFiClientSecure.h>
Kivételt dob, ha a http.POST-ra fut...
- A hozzászóláshoz be kell jelentkezni
Az URL https://napiszar.com ?
Ha hiányzik a https:// az URL elejéről, akkor crash. A müxik hsz nálam működik.
- A hozzászóláshoz be kell jelentkezni
A szerver elejében van a "https://
úja ideteszem a kódot, ami kivételt okoz:
bool puthttp() {
bool result = false;
long rssi = WiFi.RSSI();
String localip = WiFi.localIP().toString();
HTTPClient http;
//WiFiClientSecure client;
WiFiClientSecure *client = new WiFiClientSecure;
char jsonstr[400];
char jsonstr2[100];
char jsonstr3[30];
Serial.println(serverstr);
snprintf(jsonstr, sizeof(jsonstr), "{\"device_id\":%d, \"ip_address\":\"%s\", \"ssid\":\"%s\", \"rssi\":%d, ",didx,localip.c_str(),ssidstr,rssi);
snprintf(jsonstr2, sizeof(jsonstr2), "\"value_1\":%.1f, \"value_2\":%.1f, \"value_3\":%.1f, \"value_4\":%.1f, \"value_5\":%.1f, ",hom1,hom2,hom3,hom4,hom5);
snprintf(jsonstr3, sizeof(jsonstr3), "\"timestamp\":%ld}", helyiUTC);
strncat(jsonstr, jsonstr2, sizeof(jsonstr2));
strncat(jsonstr, jsonstr3, sizeof(jsonstr3));
Serial.println(jsonstr);
// Your Domain name with URL path or IP address with path
Serial.print("http.begin:");
//client.setInsecure();
client->setInsecure();
bool mi = http.begin(*client, serverstr);
Serial.println(mi);
http.addHeader("Content-Type", "application/json");
int httpResponseCode = http.POST(jsonstr);
//int httpResponseCode = http.POST("{\"value\": 20 }");
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
http.end();
delete client;
if (httpResponseCode == 200) result = true;
return result;
}
Ja, és a "new - delete" nélküli változat simán lefut - mondjuk, csak először, majd a második hívásra -1 a response
Hogy lehetne a http.POST(...)-ból http.print(...)-et csinálni?
- A hozzászóláshoz be kell jelentkezni
Én nem értem. Ez a változat megy 1x meghívva a puthttp függvény. Többször meghívva -1 a "httpResponseCode".
Viszont, ha kívül - nem a függvény törzsében - van a "http" és "client" deklarálva, ismét nem fut, kivételt okoz.
#ifndef HTTPPOST
#define HTTPOST
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
#include "config.h"
extern String serverstr, ssidstr;
extern long helyiUTC;
extern float hom1, hom2, hom3, hom4, hom5;
extern int didx;
//HTTPClient http;
//WiFiClientSecure client;
bool puthttp() {
bool result = false;
long rssi = WiFi.RSSI();
String localip = WiFi.localIP().toString();
HTTPClient http;
WiFiClientSecure client;
//WiFiClientSecure *client = new WiFiClientSecure;
char jsonstr[400];
char jsonstr2[100];
char jsonstr3[30];
Serial.println(serverstr);
snprintf(jsonstr, sizeof(jsonstr), "{\"device_id\":%d, \"ip_address\":\"%s\", \"ssid\":\"%s\", \"rssi\":%d, ",didx,localip.c_str(),ssidstr,rssi);
snprintf(jsonstr2, sizeof(jsonstr2), "\"value_1\":%.1f, \"value_2\":%.1f, \"value_3\":%.1f, \"value_4\":%.1f, \"value_5\":%.1f, ",hom1,hom2,hom3,hom4,hom5);
snprintf(jsonstr3, sizeof(jsonstr3), "\"timestamp\":%ld}", helyiUTC);
strncat(jsonstr, jsonstr2, sizeof(jsonstr2));
strncat(jsonstr, jsonstr3, sizeof(jsonstr3));
Serial.println(jsonstr);
// Your Domain name with URL path or IP address with path
Serial.print("http.begin:");
client.setInsecure();
//client->setInsecure();
bool mi = http.begin(client, serverstr);
Serial.println(mi);
http.addHeader("Content-Type", "application/json");
int httpResponseCode = http.POST(jsonstr);
//int httpResponseCode = http.POST("{\"value\": 20 }");
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
http.end();
//delete client;
if (httpResponseCode == 200) result = true;
return result;
}
#endif
- A hozzászóláshoz be kell jelentkezni
Emlékszem már. Csak a loop-ból meghívva működik.
loop() {
if (post == true) {
post = false;
puthttp();
}
}
- A hozzászóláshoz be kell jelentkezni
Így volt.
Basszus most megy, tesztelem.
Két dolgot csináltam, az SPIFFS -> LittleFS átcsere, ill. volt egy változó ami "long" volt, snprintf-ben int-ként kezeltem. Javítottam. Lehet nincs közük hozzá, de most úgy nézem megy...
- A hozzászóláshoz be kell jelentkezni
Ez így gányolás, de nem tudtam rájönni a hiba okára. Van több ilyen könyvtár, pl https://github.com/ThingPulse/esp8266-oled-ssd1306 ami csak loop/setup függvényből hívva működik. Egy profi (pl: Teve) elmagyarázhatná hogy ez mitől van.
- A hozzászóláshoz be kell jelentkezni
Igen, gányolás. Most annak örülök, hogy megy.
- A hozzászóláshoz be kell jelentkezni
(Apró hátrányban vagyok: nem értek a C++-hoz, és az Arduinóhoz.)
- A hozzászóláshoz be kell jelentkezni
Pedig https://github.com/lzsiga/untarArduino szép munka volt. Nem akarod befejezni? A debug üzeneteket F() formába kéne hozni, a végéről a
if (source!=NULL && source->isOpen()) {
source->close();
}
sort kivenni. Mehetne a hivatalos Arduino könyvtárak közé, hiánypótlás. Köszönöm hogy nekem megcsináltad, de szerintem ezt közkinccsé kéne tenni.
- A hozzászóláshoz be kell jelentkezni