Keep getting HTTP 400 errors using ESP8266HTTPClient - firebase

I'm trying to POST data to a URL using the ESP8266HTTPClient library, but I keep getting 400 errors. I verified that I can POST to that URL via Postman, so I'm not sure why it keeps failing with this sketch.
The output is:
Sending data to https://my-project.firebaseio.com/users/MY_USER_ID.json
{"timestamp":"2021-10-28 14:20:00","duration":"1"}
HTTP Response code: 400
Full code below:
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
// WiFi configuration
const char *ssid = "MY_SSID";
const char *password = "MY_PASSWORD";
// Database configuration
const String userId = "MY_USER_ID";
const String baseUrl = "https://my-project.firebaseio.com";
void setup()
{
delay(1000);
Serial.begin(9600);
Serial.print("Configuring access point...");
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());
}
bool shouldSendData = true;
void loop()
{
if (shouldSendData)
{
Serial.println("Attempting to send data...");
if (WiFi.status() == WL_CONNECTED)
{
WiFiClient client;
HTTPClient http;
String url = baseUrl + "/users/" + userId + ".json";
http.begin(client, url);
http.addHeader("Content-Type", "application/json");
String data = "{\"timestamp\":\"2021-10-28 14:20:00\",\"duration\":\"1\"}";
int httpResponseCode = http.POST(data);
Serial.print("Sending data to ");
Serial.println(url);
Serial.println(data);
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
http.end();
}
else
{
Serial.println("Unable to send data. WiFi is not connected.");
}
shouldSendData = false;
}
}

Related

HTTP get Request using ESP8266

Why I am unable to send get request. It always response 400.The URL are okay there is no problem in it. Actually I need to send data using get request. I have tried my best to find the solution but I didn't get any idea about it. Please anyone can help me with the code
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>//this header is used to send get request and see response
#include <WiFiClient.h>
const char* ssid = "myssid";
const char* password = "mypswd";
String host_url="https://api-test.technofield.net";
String url1="/api/data?token=TEST_TOKEN_123&data=";
int httpPort=80;
void setup() {
Serial.begin(9600);
WiFi.begin(ssid, password); //Connect to my WiFi router
Serial.println("");
Serial.print("Connecting"); //initiall step just displaying connecting
// Wait for connection
while (WiFi.status() != WL_CONNECTED) { //the llop wiil execute till wifi is not connected
delay(500);
Serial.print(".");
}
//If connection successful show IP address in serial monitor
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);// connected to given ssid
Serial.print("IP address: ");
Serial.println(WiFi.localIP()); //IP address assigned to your ESP
}
void loop(){
if(WiFi.status()==WL_CONNECTED){ //we will perform action if wifi is connected
HTTPClient http; //intialize object of HTTPclient which is importent
String data="Sunil Kumar Yadav";
//String token="TEST_TOKEN_123";
url1=url1+data;
//full APi url is created you can manipulate those above data and token vaiable.
http.begin(host_url,httpPort,url1);//specify the request,begin the request
int httpCode=http.GET(); //Send the request
// if (httpCode>0){ //lets see the response from server
// String payload = http.getString();//store response on payload variable
// Serial.print("==============");//just for seperating the wifi connection status and server response
// Serial.println(payload);//print the response payload
// }
Serial.print(httpCode);
http.end();//if there is begin there will be end ,it will Close the connection
}
delay(500); //send the request in every 2sec, you can change it according to your need
//you can also specify the time so that it will be easy to identify on which time data is send
}
Following is the output:
301
==============<html>
<head><title>301 Moved Permanently</title></head>
<body>
<center><h1>301 Moved Permanently</h1></center>
<hr><center>nginx</center>
</body>
</html>
I dont know how to solve this.
There's one (of several) example how to do this with HTTPs here: https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266HTTPClient/examples/BasicHttpsClient/BasicHttpsClient.ino
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClientSecure.h>
const char* ssid = "myssid";
const char* password = "mypswd";
String url = "https://api-test.technofield.net/api/data?token=TEST_TOKEN_123&data=";
void setup() {
Serial.begin(115200);
WiFi.begin(ssid, password);
Serial.println("");
Serial.print("Connecting");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to ");
Serial.println(ssid);
Serial.print("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
WiFiClientSecure client;
client.setInsecure();
HTTPClient https;
String data = "Sunil%20Kumar%20Yadav";
String fullUrl = url + data;
Serial.println("Requesting " + fullUrl);
if (https.begin(client, fullUrl)) {
int httpCode = https.GET();
Serial.println("============== Response code: " + String(httpCode));
if (httpCode > 0) {
Serial.println(https.getString());
}
https.end();
} else {
Serial.printf("[HTTPS] Unable to connect\n");
}
}
delay(5000);
}
import WiFiClientSecure.h
note how I set client.setInsecure(); which you shouldn't in your real code, rather us the root certificate of your end point as shown here https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/examples/HTTPSRequest/HTTPSRequest.ino#L29
you should URL-encode the data parameter like so String data = "Sunil%20Kumar%20Yadav"

I have a JSON problem with HTTPClient library's POST request

I can't use the POST() function properly or don't know how to
I get this error message
no matching function for call to 'HTTPClient::POST(ArduinoJson::JsonObject&)
When I try to send a JSON object inside the POST() function, I get the following return message:
{
"error": "ParseError",
"description": "Errors found in incoming JSON buffer"
}
When I try to simply write JSON as string in POST() function and try to send it that way
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h> //v5.13.5
const char* ssid = "**";
const char* password = "**";
void setup() {
Serial.begin(115200);
delay(4000);
WiFi.begin(ssid,password);
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connection established!");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
Serial.println("Connected to the WiFi network");
}
void loop() {
if(WiFi.status() == WL_CONNECTED){
HTTPClient http;
http.begin("http://172.20.10.13:1026/v2/entities"); //My docker
http.addHeader("Content-Type", "application/json");
StaticJsonBuffer<200> jsonBuffer;
JsonObject& root = jsonBuffer.createObject();
root["id"] = "urn:ngsi-ld:Sensor:001";
root["type"] = "motion";
root["value"] = "No";
root.printTo(Serial);
/*int httpResponseCode = http.POST("{\n\t\"id\":\"urn:ngsi-ld:Sensor:001\", \"type\":\"MotionSensor\",\n\t\"value\":\"NO\"\n}"); */
int httpResponseCode = http.POST(root);
if(httpResponseCode > 0){
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else{
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end();
}
else{
Serial.println("Error in WiFi connection");
}
delay(300000);
}
Result should be a functioning POST request into docker and data stored, while i can read that data with GET command in terminal on my VM
The argument for HTTPClient.POST is Arduino String (or a C string) and you can't simply pass your JSON object. You need to use prettyPrintTo to convert your json object to a standard JSON string and next pass it to the POST function.
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h> //v5.13.5
const char *ssid = "**";
const char *password = "**";
void setup()
{
Serial.begin(115200);
delay(4000);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED)
{ //Check for the connection
delay(1000);
Serial.println("Connecting to WiFi..");
}
Serial.println("Connection established!");
Serial.print("IP address:\t");
Serial.println(WiFi.localIP());
Serial.println("Connected to the WiFi network");
}
void loop()
{
if (WiFi.status() == WL_CONNECTED)
{
HTTPClient http;
http.begin("http://172.20.10.13:1026/v2/entities"); //My docker
http.addHeader("Content-Type", "application/json");
StaticJsonBuffer<200> jsonBuffer;
JsonObject &root = jsonBuffer.createObject();
root["id"] = "urn:ngsi-ld:Sensor:001";
root["type"] = "motion";
root["value"] = "No";
root.printTo(Serial);
/*int httpResponseCode = http.POST("{\n\t\"id\":\"urn:ngsi-ld:Sensor:001\", \"type\":\"MotionSensor\",\n\t\"value\":\"NO\"\n}"); */
char json_str[100];
root.prettyPrintTo(json_str, sizeof(json_str));
int httpResponseCode = http.POST(json_str);
if (httpResponseCode > 0)
{
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
}
else
{
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end();
}
else
{
Serial.println("Error in WiFi connection");
}
delay(300000);
}

ESP8266 Using wifimanager with onSoftAPModeProbeRequestReceived

I would like to use https://github.com/tzapu/WiFiManager in conjunction with onSoftAPModeProbeRequestReceived. The end goal is to config the wifi with WifiMaager then "switch over" and send probe request information via the wifi.
I get this to work without wifi manager using the following
#include <ESP8266httpUpdate.h>
#include <ESP8266WiFi.h>
#include <esp8266httpclient.h>
#include <stdio.h>
const char* ssid = "someap"; // The SSID (name) of the Wi-Fi
network you want to connect to
const char* password = ""; // The password of the Wi-Fi network
int status = WL_IDLE_STATUS;
String macAddr = "";
WiFiEventHandler probeRequestPrintHandler;
WiFiEventHandler probeRequestBlinkHandler;
bool blinkFlag;
void setup() {
Serial.begin(115200);
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, HIGH);
Serial.print("Starting");
WiFi.persistent(false);
WiFi.mode(WIFI_AP);
WiFi.softAP(ssid, password);
probeRequestPrintHandler =
WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestPrint);
probeRequestBlinkHandler =
WiFi.onSoftAPModeProbeRequestReceived(&onProbeRequestBlink);
while ( status != 3)
{
Serial.print("Attempting to connect to network, SSID: ");
Serial.println(ssid);
status = WiFi.status();
WiFi.begin(ssid, password);
// wait 10 seconds for connection:
delay(10000);
}
Serial.println(WiFi.localIP());
}
void onProbeRequestPrint(const WiFiEventSoftAPModeProbeRequestReceived& evt)
{
if (macAddr != macToString(evt.mac))
{
macAddr = macToString(evt.mac);
Serial.print("Probe request from: ");
Serial.print(macToString(evt.mac));
Serial.print(" RSSI: ");
Serial.println(evt.rssi);
}
}
void onProbeRequestBlink(const WiFiEventSoftAPModeProbeRequestReceived&) {
blinkFlag = true;
}
void loop() {
if (blinkFlag) {
HTTPClient http; //Declare an object of class HTTPClient
http.begin("http://requestbin.fullcontact.com/110f1ss6a1?test=true");
//Specify request destination
int httpCode = http.GET();
Serial.println(httpCode);
if (httpCode > 0) { //Check the returning code
String payload = http.getString(); //Get the request response payload
Serial.println(payload); //Print the response payload
}
http.end(); //Close connection
macAddr="";
blinkFlag = false;
digitalWrite(LED_BUILTIN, LOW);
delay(100);
digitalWrite(LED_BUILTIN, HIGH);
status = 0;
}
delay(1000);
}
String macToString(const unsigned char* mac) {
char buf[20];
snprintf(buf, sizeof(buf), "%02x:%02x:%02x:%02x:%02x:%02x",
mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
return String(buf);
}
When the connection is established we rely on WiFiEventHandler probeRequestPrintHandler; and WiFiEventHandler probeRequestBlinkHandler; This does work and does collect the mac address, how ever it can not connect to the AP. Do I need to close the current wifi mode open the connection then close it?
Seems all I needed to do is add WiFi.begin(); before void loop()

Firebase cloud function POST HTTPS Request from ESP8266

I want to connect to an url of a cloud function but isn´t working. someone can see the error? I´m working with an ESP8266 from arduino IDE. I try sending a POST request by postman and it function perfectly, I don´t understan what is the problem with the conection, i always try to connect with out the https and only with http and again in the esp8266 didn´t wotk but in postman does works fine, I do not understant why is this problem
#include <ESP8266WiFi.h>
#include <WiFiClientSecure.h>
const char* ssid = "My wifi";
const char* password = "My Password";
const char* host = "https://us-central1-sensores4bad6.cloudfunctions.net/actualizar";
void setup() {
Serial.begin(9600);
delay(10);
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
int value = 0;
void loop() {
delay(5000);
++value;
Serial.print("connecting to ");
Serial.println(host);
WiFiClientSecure client;
const int httpPort = 443;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
client.print(String("POST ") + host + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n\r\n");
unsigned long timeout = millis();
while (client.available() == 0) {
if (millis() - timeout > 5000) {
Serial.println(">>> Client Timeout !");
client.stop();
return;
}
}
while (client.available()) {
String line = client.readStringUntil('\r');
Serial.print(line);
}
Serial.println();
Serial.println("closing connection");
}
Try removing the s in https. So:
const char* host = "http://us-central1-sensores4bad6.cloudfunctions.net/actualizar";
instead of
const char* host = "https://us-central1-sensores4bad6.cloudfunctions.net/actualizar";

Validating the return of an HTTP GET request with arduino IDE and nodemcu-esp-12e

Using the Arduino IDE with the Nodemcu-esp12e module, I created a program which makes an HTTP GET request.
However, I do not know how it would be the right way to deal with the return of this consultation.
I am validating the return with the 'indexOf' function to find out if the return is false/off or true/on.
This is the correct way to validate the return?
Any suggestions for how to improve this code?
#include <ESP8266WiFi.h>
const char* ssid = "mywifiid";
const char* password = "mypassword";
IPAddress host(192,168,0,11);
void setup() {
Serial.begin(115200);
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
//
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
//
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void loop() {
//
Serial.print("connecting to ");
Serial.println(host);
//
WiFiClient client;
const int httpPort = 80;
if (!client.connect(host, httpPort)) {
Serial.println("connection failed");
return;
}
else{
Serial.println("connection success");
}
//
String get = "http://localhost/Test/GetStatusSensor?idsensor=2";
Serial.println(get);
//
client.print("GET " + get + "\r\nHTTP/1.1\r\nHost: localhost\Test\r\nConnection: keep-alive\r\n\r\n");
//
while(client.available()){
String line = client.readStringUntil('\r');
//
int iret= line.indexOf('on');
//
Serial.print(line);
Serial.println(String(iret));
//
if (iret> 0) {
//
Serial.println("On");
}
else {
Serial.println("Off");
}
}
//
Serial.println();
Serial.println("closing connection");
delay(20000); // 20 sec
}
My suggestion is to use JSON to switch to more structured way of comm. You can define custom data names and types and easily cover them. Take a look it at :
https://github.com/bblanchon/ArduinoJson
Here some JSON example from the HTTPClient example :
DynamicJsonBuffer jsonBuffer(BUFFER_SIZE);
JsonObject& root = jsonBuffer.parseObject(client);
if (!root.success()) {
Serial.println("JSON parsing failed!");
return false;
}
// Here were copy the strings we're interested in
strcpy(userData->name, root["name"]);
strcpy(userData->company, root["company"]["name"]);

Resources