Esp8266 Post Request returns error code 415 - post

I am currently developing a project where I want esp8266 to send data to Blazor Server App which is hosted on server, but the problem is the Post request to Blazor's server app api keeps returning error code 415.
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
const String ssid="";
const String password="";
const String url="http://raspberrypiproject.com/api/values/1";
void setup()
{
Serial.begin(115200);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid,password);
Serial.println();
Serial.print("Connecting");
while(WiFi.status()!=WL_CONNECTED)
{
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("Connected to ");
Serial.print(WiFi.SSID());
}
void loop() {
if(WiFi.status()==WL_CONNECTED)
{
WiFiClient client;
HTTPClient http;
if(http.begin(client,url))
{
int code=http.GET();
if(code>0)
{
Serial.println(http.getString());
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
Serial.println(http.POST("hellofromEsp8266"));
}
}
}
}
This is my esp8266 code. In the net I found that the cause of the problem is the Content-Type of "http.addHeader("Content-Type", "application/x-www-form-urlencoded")" and the only change in the response code is when I change it to "multipart/form-data" and it returns error code 400. Is my problem in the client or in Blazor Server.

Related

http.GET() sends false (-1) in esp8266 (arduino)

I am trying to fetch some details from an API endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc). But everytime it is returning false (-1). When I GET the endpoint on my browser it is just workign fin, returning 200.
http.GET() returns -1
serial monitor putput
#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
#include <Wire.h>
WiFiClient wifiClient;
void setup() {
Serial.begin(9600);
WiFi.begin("56", "emayush56");
while(WiFi.status() != WL_CONNECTED)
{
delay(200);
Serial.print("..");
}
Serial.println();
Serial.println("NodeMCU is connected!");
Serial.println(WiFi.localIP());
}
void loop() {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(wifiClient, "https://bitcoin-ethereum-price-test.vercel.app/btc");
int httpCode = http.GET();
Serial.println("*** RESPONSE STATUS ***");
Serial.println(httpCode);
if (httpCode > 0) {
String payload = http.getString();
Serial.println(payload);
}
http.end();
}
delay(3000);
}
I think either I am doing something wrong with http.begin() or something else. http.begin() can be called in two different ways:
type1:
bool begin(WiFiClient &client, const String& url);
type2:
bool begin(WiFiClient &client, const String& host, uint16_t port, const String& uri = "/", bool https = false);
I have tried with both of them - first by passing directly the WifiClient object and the URL (type 1), and then (type2) by passing the WiFiClient object and other parameters.
If my main api endpoint (https://bitcoin-ethereum-price-test.vercel.app/btc) is returnig 200 then why http.GET() is returning false? Please help me identify the issue.
You're making an HTTP request to an HTTPS API. You will need to use a certificate's sha1 fingerprint. You can get the fingerprint in chrome by clicking on the little lock by the beginning of the URL, go to "Connection is secure" option then "Certificate is valid" and it'll show you some info about the certificate with the keys at the bottom.
Here is some example code I found which uses HTTPS with the HTTPClient library:\
void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
HTTPClient http;
Serial.print("[HTTPS] begin...\n");
http.begin("https://some.secure_server.com/auth/authorise", "2F 2A BB 23 6B 03 89 76 E6 4C B8 36 E4 A6 BF 84 3D DA D3 9F");
http.addHeader("Content-Type", "application/x-www-form-urlencoded");
int httpCode = http.POST("user_id=mylogin&user_password=this%20is%20my%20%24ecret%20pa%24%24word");
if (httpCode > 0) {
http.writeToStream(&Serial);
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] ... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
}
delay(10000);
}

ESP8266 crashes after simple http request

I am working with the NodeMCU V3 module. Whenever I try to make an http request to my server, the module crashes.
Here's the code:
void setup() {
WiFi.begin("wifi-name", "wifi-password");
while (WiFi.status() != WL_CONNECTED) { //Wait for the WiFI to connect }
}
void loop() {
HTTPClient http;
WiFiClient client;
http.begin( client, "server-address" );
int httpCode = http.GET();
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
delay( 1000 );
}
Here's the result, as seen in the serial monitor:
200
["JSON response from the server"]
Exception (28):
epc1=0x40212e82 epc2=0x00000000 epc3=0x00000000 excvaddr=0x000001b6 depc=0x00000000
>>>stack>>>
ctx: cont
sp: 3ffffc90 end: 3fffffc0 offset: 01a0
3ffffe30: 00000000 4bc6a7f0 0000333f 3ffee5f8
3ffffe40: 00000000 00000000 4bc6a7f0 00000000
[...]
3fffffb0: feefeffe feefeffe 3ffe84e8 40100c41
<<<stack<<<
The strange thing is that it retrieves the response from the server correctly, but then, about one second later, it spits out the exception to the serial monitor and resets. At first I thought it could be because I am running ESP8266WebServer at the same time, but it still crashes even when I run the most basic example I could find on the internet. I tried compiling the same code on the Arduino IDE instead of PlatformIO, or even using a different NodeMCU, to no avail.
EDIT: After playing around a bit more, it seems like setting the delay to at least 10 seconds makes the NodeMCU crash after 3 requests instead of after the first one. Could it be that it's memory overflows after a few requests? Am I missing a crucial part that should prepare the ESP8266 for a new request?
There is no need to re-create the WiFi and HTTP clients in the loop() over and over again. You can declare them once globally. Here's a stable version of this simple sketch:
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESPHTTPClient.h>
HTTPClient http;
WiFiClient client;
void setup() {
Serial.begin(115200);
Serial.println();
WiFi.begin("****", "****");
Serial.print("Connecting to WiFi");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("done.");
}
void loop() {
http.begin(client, "http://httpbin.org/get"); // <1KB payload
// http.begin(client, "http://www.geekstips.com/esp8266-arduino-tutorial-iot-code-example/"); // 30KB payload
int httpCode = http.GET();
String payload = http.getString(); //Get the response payload
Serial.println(httpCode); //Print HTTP return code
Serial.println(payload); //Print request response payload
http.end(); //Close connection
Serial.printf("Free heap: %d\n", ESP.getFreeHeap());
delay(1000);
}
The reported free heap is very stable over time.
Please take note of the second URL I added for testing in the commented line. That http.getString() is convenient and works well for small resources but yields unexpected i.e. wrong results for larger resources - you only see a small fraction of the body printed to the console.
For larger payloads you should use the low-level WiFiClient directly and read/parse the response line-by-line or character-by-character. See the documentation at https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/client-examples.html for a template.
void loop()
{
WiFiClient client;
Serial.printf("\n[Connecting to %s ... ", host);
if (client.connect(host, 80))
{
Serial.println("connected]");
Serial.println("[Sending a request]");
client.print(String("GET /") + " HTTP/1.1\r\n" +
"Host: " + host + "\r\n" +
"Connection: close\r\n" +
"\r\n"
);
Serial.println("[Response:]");
while (client.connected() || client.available())
{
if (client.available())
{
String line = client.readStringUntil('\n');
Serial.println(line);
}
}
client.stop();
Serial.println("\n[Disconnected]");
}
else
{
Serial.println("connection failed!]");
client.stop();
}
delay(5000);
}

ESP8266 Subscribe to AWS IOT topic

Hi I need to create a lambda function which will access the AWS thing and publish MQTT message, I'd like to get the published message on the ESP8266 which was connected to the thing as well, and controlled turn on/off the LED on ESP8266. So far I have uploaded the private.der, cert.der and ca.der to the ESP8266 absolutely, but it couldn't subscribed AWS IOT, please point me in the right tips then please share.
Code:
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <NTPClient.h>
#include <WiFiUdp.h>
#include <ArduinoJson.h>
#define OUT_TOPIC "$aws/things/devices/shadow/update"
#define IN_TOPIC "$aws/things/devices/shadow/update/delta"
const char* ssid = "sid";
const char* password = "password";
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP, "pool.ntp.org");
const char* AWS_endpoint = "endpoint.amazonaws.com";//MQTT broker ip
const char* json = "{\"state\":{\"reported\":{\"led\":\"off\"}}}";
StaticJsonDocument<1024> doc;
WiFiClientSecure espClient;
PubSubClient mqttClient(espClient);//set MQTT port number to 8883 as per standard
PubSubClient client(AWS_endpoint, 8883, espClient);
long lastMsg = 0;
char msg[50];
int value = 0;
void setup_wifi() {
delay(10);// We start by connecting to a WiFi network
espClient.setBufferSizes(512, 512);
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());
timeClient.begin();
while(!timeClient.update()){
timeClient.forceUpdate();
}
espClient.setX509Time(timeClient.getEpochTime());
int qos = 0;//Maximum size of data that can be communicated
Serial.println(MQTT_MAX_PACKET_SIZE);
if(mqttClient.subscribe(IN_TOPIC, qos)){
Serial.println("Subscribed.");
Serial.println("Success!!");
}
deserializeJson(doc, json);
JsonObject obj = doc.as<JsonObject>();
if(mqttClient.publish(OUT_TOPIC, json)){
Serial.println("Published!!");
}
}
void setup() {
Serial.begin(115200);
Serial.setDebugOutput(true);
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
setup_wifi();
delay(1000);
if (!SPIFFS.begin()) {
Serial.println("Failed to mount file system");
return;
}
Serial.print("Heap: "); Serial.println(ESP.getFreeHeap());
//replace cert.crt eith your uploaded file name
File cert = SPIFFS.open("/cert.der", "r");
if (!cert) {
Serial.println("Failed to open cert file");
}
else
Serial.println("Success to open cert file");
delay(1000);
if (espClient.loadCertificate(cert))
Serial.println("cert loaded");
else
Serial.println("cert not loaded");
// Load private key file
File private_key = SPIFFS.open("/private.der", "r");//replace private eith your uploaded file name
if (!private_key) {
Serial.println("Failed to open private cert file");
}
else
Serial.println("Success to open private cert file");
delay(1000);
if (espClient.loadPrivateKey(private_key))
Serial.println("private key loaded");
else
Serial.println("private key not loaded");
// Load CA file
File ca = SPIFFS.open("/ca.der", "r");
//replace ca eith your uploaded file name
if (!ca) {
Serial.println("Failed to open ca ");
}
else
Serial.println("Success to open ca");
delay(1000);
if(espClient.loadCACert(ca))
Serial.println("ca loaded");
else
Serial.println("ca failed");
Serial.print("Heap: ");
Serial.println(ESP.getFreeHeap());
}
void callback (char* topic, byte* payload, unsigned int length) {
Serial.println("Received. topic=");
Serial.println(topic);
char subsc[length];
for(int i=0; i<length; i++){
subsc [i]=(char)payload[i];
subsc [length]='\0';
Serial.print(subsc);
}
Serial.print("\n");
digitalWrite(LED_BUILTIN, HIGH);
}
void mqttLoop() {
mqttClient.loop();
delay(100);
//digitalWrite(LED_pin, LOW);
digitalWrite(LED_BUILTIN, LOW);
Serial.print(".");
}
void loop() {
It looks like you're using the older forms of WiFiClientSecure certificate handling. I'll assume that's working OK and you're able to establish an SSL connection.
Your IN_TOPIC needs to be updated slightly to: $aws/things/<name-of-your-thing>/shadow/update/accepted (where hopefully you know what <name-of-your-thing> is). You can get this from the thing shadow on your AWS console.
Similarly AWS_endpoint needs updating: it should be of the form <random-stuff-specific-to-you>.iot.<region>.amazonaws.com. You can also find it from the same place as the MQTT topics.
You only want one instance of PubSubClient. I'll assume you delete client and keep mqttClient. You'll need to update the instantiation to include the AWS endpoint and port as you have done for client.
Before calling mqttClient.subscribe(...) you need to register the callback:
mqttClient.setCallback(::callback);
then connect to AWS:
mqttClient.connect("some-unique-name");
Finally, you need to edit PubSubClient.h (look for it in Arduino/libraries/PubSubClient/src) to update MQTT_MAX_PACKET_SIZE. The default is 128 and I've found that too small with AWS's messages. I've made mine 1024:
#define MQTT_MAX_PACKET_SIZE 1024
and that appears ample.
Once that compiles and runs you'll start seeing callback(...) called with the topics you've subscribed to and you can implement the function to do whatever you need.
The PubSubClient doesn't do much error reporting to help diagnose what's going on. I'm currently refactoring it a bit and including more diagnostic information and will eventually issue a pull request. Let me know if you'd like my hacked version before I get that far.

Always get -1 connection refused response from server

I am making a alert device on my node mcu board to report any orders made by customers on my application. The nodemcu should access the network using wifi and call the rest api. I tried researching many sites and modified the code several times, but the response is always -1, connection refused.
tried doing
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>
#include <ESP8266HTTPClient.h>
#include <WiFiClient.h>
ESP8266WiFiMulti WiFiMulti;
void setup() {
Serial.begin(9600);
// Serial.setDebugOutput(true);
Serial.println();
Serial.println();
Serial.println();
for (uint8_t t = 4; t > 0; t--) {
Serial.printf("[SETUP] WAIT %d...\n", t);
Serial.flush();
delay(1000);
}
WiFi.mode(WIFI_STA);
WiFiMulti.addAP("----", "----");
}
void loop() {
// wait for WiFi connection
if ((WiFiMulti.run() == WL_CONNECTED)) {
WiFiClient client;
HTTPClient http;
Serial.print("[HTTP] begin...\n");
if (http.begin(client, "http://34.87.116.113:80/api/v1/iot/Notify/poll")) { // HTTP
http.setAuthorization("admin", "admin123!");
Serial.print("[HTTP] GET...\n");
// start connection and send HTTP header
int httpCode = http.GET();
// httpCode will be negative on error
if (httpCode > 0) {
// HTTP header has been send and Server response header has been handled
Serial.printf("[HTTP] GET... code: %d\n", httpCode);
// file found at server
if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
String payload = http.getString();
Serial.println(payload);
}
} else {
Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
}
http.end();
} else {
Serial.printf("[HTTP} Unable to connect\n");
}
}
delay(5000);
}

Node MCU failed to connect with firebase but does not return any error code

I need to send my data to firebase via NODE MCU. I've created an application that is used to turn on and off led in node mcu. My node mcu connects with the wifi network but does not send data to firebase. The if(firebase.failed()) executes, but does not return an error code. In the serial monitor it just prints setting/number failed:. How can I fix this?
#include <ESP8266WiFi.h>
#include <FirebaseArduino.h>
#include <ArduinoJson.h>
#define FIREBASE_HOST "http://temphu*****.firebaseio.com/"
#define FIREBASE_AUTH "VblTNS************OmWTW6n"
#define WIFI_SSID "A****"
#define WIFI_PASSWORD "9*****"
#define LED 2
void setup() {
pinMode(LED,OUTPUT);
digitalWrite(LED,0);
Serial.begin(9600);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("connecting");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(500);
}
Serial.println();
Serial.print("connected: ");
Serial.println(WiFi.localIP());
Firebase.begin(FIREBASE_HOST,FIREBASE_AUTH);
Firebase.setInt("LEDStatus",0);
}
void loop() {
if(Firebase.getInt("LEDStatus")) {
digitalWrite(LED,HIGH);
}
else {
digitalWrite(LED,LOW);
}
if (Firebase.failed()) { // Check for errors
Serial.print("setting /number failed:");
Serial.println(Firebase.error());
return;
}
delay(1000);
}
In the source code it clearly says that (https://raw.githubusercontent.com/FirebaseExtended/firebase-arduino/master/src/FirebaseError.h) two error codes are used in addition to regular HTTP error codes. Therefore Firebase rejection might not raise an error even though it fails.
So check the firebase rules and change read/write to true.

Resources