Skip to content

http.GET() randomly exits with error -1 (connection refused) -> issue with function WiFiGenericClass::hostByName() [proposal of changes in library] #3722

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
asier70 opened this issue Feb 7, 2020 · 55 comments · Fixed by #3731

Comments

@asier70
Copy link
Contributor

asier70 commented Feb 7, 2020

Hardware:

Board: ESP32 Dev Module
Core Installation version: 1.0.4
IDE name: Arduino IDE

Description:

Because issue #2778 Getting [E][WiFiGeneric.cpp:658] hostByName(): DNS Failed randomly is closed and this problem still exists I decided to open new one.
From time to time function http.GET() immediatelly exits with error -1 which means "connection refused". This problem was observed by many other programmers, especially when internet connection was slow or function was used very often.
I investigated this problem for very long time. In this situation "connection refused" doesn't mean that remote server refused our connection. Problematic was function WiFiGenericClass::hostByName(), which resolves host name and translates it to IP address.

Analysis:

Tree of functions use is as follows:

int HTTPClient::GET()
{
    return sendRequest("GET");
} 

int HTTPClient::sendRequest(const char * type, String payload)
{
    return sendRequest(type, (uint8_t *) payload.c_str(), payload.length());
} 

int HTTPClient::sendRequest(const char * type, uint8_t * payload, size_t size)
{
    // connect to server
    if(!connect()) {
        return returnError(HTTPC_ERROR_CONNECTION_REFUSED);
    }
    [...]
} 

bool HTTPClient::connect(void)
{
    [...]
    if(!_client->connect(_host.c_str(), _port, _connectTimeout)) {
        log_d("failed connect to %s:%u", _host.c_str(), _port);
        return false;
    }
    [...]
} 

int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout)
{
    IPAddress srv((uint32_t)0);
    if(!WiFiGenericClass::hostByName(host, srv)){
        return 0;
    }
    return connect(srv, port, timeout);
} 

After investigation error is caused by WiFiGenericClass::hostByName() function:

/**
 * Resolve the given hostname to an IP address.
 * @param aHostname     Name to be resolved
 * @param aResult       IPAddress structure to store the returned IP address
 * @return 1 if aIPAddrString was successfully converted to an IP address,
 *          else error code
 */
int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult)
{
    ip_addr_t addr;
    aResult = static_cast<uint32_t>(0);
    waitStatusBits(WIFI_DNS_IDLE_BIT, 5000);
    clearStatusBits(WIFI_DNS_IDLE_BIT);
    err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
    if(err == ERR_OK && addr.u_addr.ip4.addr) {
        aResult = addr.u_addr.ip4.addr;
    } else if(err == ERR_INPROGRESS) {
        waitStatusBits(WIFI_DNS_DONE_BIT, 4000);
        clearStatusBits(WIFI_DNS_DONE_BIT);
    }
    setStatusBits(WIFI_DNS_IDLE_BIT);
    if((uint32_t)aResult == 0){
        log_e("DNS Failed for %s", aHostname);
    }
    return (uint32_t)aResult != 0;
} 

/**
 * DNS callback
 * @param name
 * @param ipaddr
 * @param callback_arg
 */
static void wifi_dns_found_callback(const char *name, const ip_addr_t *ipaddr, void *callback_arg)
{
    if(ipaddr) {
        (*reinterpret_cast<IPAddress*>(callback_arg)) = ipaddr->u_addr.ip4.addr;
    }
    xEventGroupSetBits(_network_event_group, WIFI_DNS_DONE_BIT);
} 

Real problem lies in timeout value used in above function. This function uses DNS functionality of lwip library. How it works? When domain name is in local cache lwip library returns immediately resolved IP address from cache. If not it starts working in backgroud checking IP address in external DNS servers. Function waits only 4000[ms] for this. If resolving procedure lasts more time than 4[s] function returns with error, but background process still lives. When it finishes, callback function is called, WIFI_DNS_DONE_BIT is set and result variable is filled with resolved IP address. This situation is very dangerous for whole application! There are two big problems connected with it.
When next time we use hostByName() function it returns immediately with error because WIFI_DNS_DONE_BIT is set (look at wait for status bit function). Background callback remains alive so abnormal situation will be repeated over and over again (till DNS cache use).
Second problem is more dangerous in my opinion. Object srv of IPAddress class in fuction WiFiClient::connect() is declared locally on stack. It is passed by reference to callback function. When callback ends it writes resolved IP address to this stack memory area, but after 4[s] this area is probably used by other function so it may result in application crash...

Solution

I tried to find timeout value of DNS resolving procedure in lwip library. I found that internal timer has default 1[s] period and there are 4 retries. So deducing external DNS IP address resolving procecedure should have 4 seconds timeout. But nothing could be more wrong.
I did a test. I manually set both DNS serwers as some IPs that aren't DNS servers. I measured that real timeout occurs after 13-14 seconds! So timeout value used in hostByName() function should be more than 14000[ms].
I thought about the solution for a long time.
I suggest to make three changes in WiFiGenericClass::hostByName() function:

int WiFiGenericClass::hostByName(const char* aHostname, IPAddress& aResult)
{
    ip_addr_t addr;
    aResult = static_cast<uint32_t>(0);
    waitStatusBits(WIFI_DNS_IDLE_BIT, 16000);  //* CHANGED FROM 5000 to 16000
    clearStatusBits(WIFI_DNS_IDLE_BIT);
    clearStatusBits(WIFI_DNS_DONE_BIT);  //* NEW
    err_t err = dns_gethostbyname(aHostname, &addr, &wifi_dns_found_callback, &aResult);
    if(err == ERR_OK && addr.u_addr.ip4.addr) {
        aResult = addr.u_addr.ip4.addr;
    } else if(err == ERR_INPROGRESS) {
        waitStatusBits(WIFI_DNS_DONE_BIT, 15000);  //* CHANGED FROM 4000 to 15000
        clearStatusBits(WIFI_DNS_DONE_BIT);
    }
    setStatusBits(WIFI_DNS_IDLE_BIT);
    if((uint32_t)aResult == 0){
        log_e("DNS Failed for %s", aHostname);
    }
    return (uint32_t)aResult != 0;
} 

What do you think about this solution?
Can anyone verify my logical reasoning about it?

@atanisoft
Copy link
Collaborator

Perhaps move the timeout to be configurable via a default parameter on the function, ie:

class WiFiGeneric {
...
int hostByName(const char* aHostname, IPAddress& aResult, uint32_t timeout=4000);
...
}

And in the usage you would reference it as timeout (without the default value in WiFiGeneric.cpp) that way people can override it dynamically and not have a hardcoded timeout value.

@asier70
Copy link
Contributor Author

asier70 commented Feb 7, 2020

Now timeout is "hardcoded" with 4 seconds. Wrongly hardcoded. This valued should never be lower than real timeout value used by lwip library. If it is lower sometimes we can observe strange behaviors.
Typically DNS answer I measured is about 100-200[ms]. Using poor or stressed internet connection I catched many DNS timeouts in projected device. Also when DNS server will be unawailable for few seconds timeout will be longer and application may crash.

@ajyta
Copy link

ajyta commented Feb 7, 2020

Hi asier70,
I think your solution helps a lot, but from my opinion it's not bulletproof to save the stack in rough conditions, right? Would it be a better idea, to declare the ip_addr_t addr; outside of the method as a class attribute? So it is as long in the memory as long the object is existing.

For "int start_ssl_client ...", which is no member function, "IPAddress srv((uint32_t)0);" could be declared as static.

I know, that this solution has a problem with overlapping requests, but this could only solved by a completely different design, which need to introduce something like a lock mechanism.
BR

@asier70
Copy link
Contributor Author

asier70 commented Feb 7, 2020

I also thinked about static declaration, but as you said there is possibility of overlapping - improper assigning IP to domain name. Finally I decided to use timeout longer than maximal timeout generated by lwip library (7[s] for DNS1 + 7[s] for DNS2 = 14[s]). It will work fine until someone change default configuration of this library. BTW I don't know why very old version of lwip library is used.
Generally esp32 arduino library functions are written to work as single threaded. Using http functions in parallel threads result in much more troubles. DNS resolving function from used lwip library can resolve up to 4 domain names at once, but esp32 library can not use this functionality.
Probably esp8266 library is written much better and issue we are talking about does not apply to it.

@ajyta
Copy link

ajyta commented Feb 7, 2020

Yes, you are right. But the design at all is ... if you have to rely, that someone does not change the standard configuration (sic!).

@asier70 asier70 changed the title http.GET() randomly exits with error -1 (connection refused) -> issue with function WiFiGenericClass::hostByName() http.GET() randomly exits with error -1 (connection refused) -> issue with function WiFiGenericClass::hostByName() [proposal of changes in library] Feb 10, 2020
@asier70
Copy link
Contributor Author

asier70 commented Feb 10, 2020

This library is for arduino, so it is for hobbists, who don't change internal config files. Professionals are able to find and fix software errors themselves :)

asier70 added a commit to asier70/arduino-esp32 that referenced this issue Feb 11, 2020
Real DNS resolving timeout used by lwip library is 14[s] (7[s] for DNS1 + 7[s] for DNS2). Function WiFiGenericClass::hostByName() has timeout set to lower value (only 4[s]), so callback function may be called after this low timeout and it may overlappe stack memory used now by other function.
Fixes espressif#3722
@ajyta
Copy link

ajyta commented Feb 11, 2020

This library is for arduino, so it is for hobbists, who don't change internal config files. Professionals are able to find and fix software errors themselves :)

Touché :-)

@drmpf
Copy link
Contributor

drmpf commented Feb 14, 2020

The change suggested by asier70 above did not fix my
[E][WiFiGeneric.cpp:653] hostByName(): DNS Failed for ...
problem
I tried replacing the host name with the ip in the
WiFiClientSecure client;
client.setCACert(getRootCert());
IPAddress hostAddress(d,d,d,d);
client.connect(hostAddress, 443)
gives
[E][ssl_client.cpp:33] handle_error(): UNKNOWN ERROR CODE (0050)
[E][ssl_client.cpp:35] handle_error(): MbedTLS message code: -80
[E][WiFiClientSecure.cpp:132] connect(): start_ssl_client: -80

So I am now ditching the ESP32 as it is not reliable.
The commercial product I am designing will have to use some other micro for WiFi
p.s. the secure connection did work sometimes, so nothing wrong with the certificate

@asier70
Copy link
Contributor Author

asier70 commented Feb 14, 2020

I tried replacing the host name with the ip in the
WiFiClientSecure client;
client.setCACert(getRootCert());
IPAddress hostAddress(d,d,d,d);
client.connect(hostAddress, 443)

Not all servers allow SSL connection that uses IP address directly. I think that domain name must be sent to verify certificate and check how secure is the connection.

@drmpf
Copy link
Contributor

drmpf commented Feb 14, 2020

Thanks for the tip. So without reliable DNS no go.
The UNKNOWN ERROR CODE (0050) is still worrying, but not for me as I am dropping ESP32

@thefatmoop
Copy link

thefatmoop commented Mar 15, 2020

I've been testing this fix for the past week - I've got 12 esp32 modules running https and http calls every ~30 seconds. I was running into this same issue and it would not recover for a long time unless wifi was restarted. This behavior was consistent on all the modules. My esp8266 modules (10 of them) would not have this issue. Anyway this fix resolved all [E] dns erros i've been having. Thanks! Wish this would get merged into the main branch.

Edit: I have seen some DNS errors, but the error rate is about 100x lower and wifi does not need restarting. Does it make sense that the wifi needed restarting before?

@asier70
Copy link
Contributor Author

asier70 commented Mar 15, 2020

Anyway this fix resolved all [E] dns erros i've been having.

Thank you for testing. I don't know who can merge my fix. I can't..

@AlfonsoAlejandre
Copy link

Hi
I have the same problem, well, not really the same but very similar. I use some code to perform some GETs and to update with OTA. I did a small program that is working fine 100% of the runs. Lately y copied this code to my main program and I got the error 'arduino [E][WiFiGeneric.cpp:654] hostByName(): DNS Failed for ...' If I call the OTA code at the program beginning it works ok, if I setup the camera (I'm using a ESP32-CAM by AI Thinker) the OTA code fails 100% of the times, so it's not a DNS issue, it's a library problem, the communications library isn't reliable.

@chegewara
Copy link
Contributor

chegewara commented May 6, 2020

Recently i have http.Get() error -1 too. What is strange it is working to get certificates from client server (one subdomain) bur retrieving data from another subdomain its giving error -1.

I tested server with curl, postman and web browser and all seems to work fine, but esp32.
I stuck at the moment with my code.

@giobauermeister
Copy link

Also having this issue. [E][WiFiGeneric.cpp:657] hostByName(): DNS Failed for myHostNameHere. But it happens all the time not randomly.
If I use IP address it works.
#3731 did not work for me though.

@chegewara
Copy link
Contributor

In my case it was server problem most likely, because after some time error just disappeared.

@AlfonsoAlejandre
Copy link

I get problems many times. The only way to pass over the problem for me is to prepare the job, restart the esp32 and do the http work. Then the esp is working fine until the next communication job, then I restart the micro again and so on. The DNS problem cames because the DNS search it's the first step to establish communication. I get problems also using the final Ip address. Check if it's working ok after the restart and before to initialize all the resources.

@everthu
Copy link

everthu commented Jun 9, 2020

I got the problem also many times. Installed the patch. This reduces the problem a lot. However, this issue is not completely resolved yet for me. Once in a few days the problem pops up and a reboot is required. With the patch I got next message:
19:40:24.314 -> [E][WiFiGeneric.cpp:724] hostByName(): DNS Failed for nl.pool.ntp.org
19:40:25.814 -> No NTP Response :-(
Wifi.status() == WL_CONNECTED at this moment

@stale
Copy link

stale bot commented Aug 8, 2020

[STALE_SET] This issue has been automatically marked as stale because it has not had recent activity. It will be closed in 14 days if no further activity occurs. Thank you for your contributions.

@stale stale bot added the Status: Stale Issue is stale stage (outdated/stuck) label Aug 8, 2020
@drmpf
Copy link
Contributor

drmpf commented Aug 8, 2020

how about a fix in stead of just ignoring this issue until it drops off

@stale
Copy link

stale bot commented Aug 8, 2020

[STALE_CLR] This issue has been removed from the stale queue. Please ensure activity to keep it openin the future.

@stale stale bot removed the Status: Stale Issue is stale stage (outdated/stuck) label Aug 8, 2020
@Sys64736
Copy link

Sys64736 commented Sep 1, 2020

Andrzej, have you received any further information on this error? You're right, the ESP32 does not recover from a long delay waiting for a DNS reply, especially when making multiple quick requests. Perhaps this error isn't noticed as much because most on this thread seems to be making requests ~30seconds intervals.

I can reliably reproduce this error on a running chip by changing the DNS settings in the router, applying the change and watching the serial monitor. The first 4 or 5 DNS errors start...slow at first (approx 4s apart) and then it's a continues procession of errors (~1s apart), most likely because the WIFI_DNS_DONE_BIT bit was set as you stated. BTW, only blocked the DNS servers for about 20 seconds then reinstated them. Everything else on the network resumed as usual except the ESP32.

If no fix is available I might try and halt my GET requests when DNS fails once, clear the done bit, wait 1 min and try again. I'm not even sure if this is feasible by modifying the class but something must be changed.

I haven't tired your modifications yet but I think I'll first try clearing the DONE bit before the DNS lookup and seeing if it makes a difference when I 'block' the DNS servers.

@asier70
Copy link
Contributor Author

asier70 commented Sep 1, 2020

Andrzej, have you received any further information on this error?

I don't have any new news. My devices work stable for a long time with this library update.

I haven't tired your modifications yet but I think I'll first try clearing the DONE bit before the DNS lookup and seeing if it makes a difference when I 'block' the DNS servers.

That was my first try to solve the problem, but this is only the one problematic point in this issue.

@TD-er
Copy link
Contributor

TD-er commented Sep 1, 2020

I lost track a bit on this, but has there been a proposed PR for this fix you mention?

@Sys64736
Copy link

Sys64736 commented Sep 2, 2020

Looking at the latest upcoming release, it has quite a bit of changes for provisioning wifi credentials using a BT app. I didn't see any change in the Wifigeneric class releated to this issue although I could be wrong. I'm only slightly familiar with the git process.

I did make some changes and they seem to be helping recover from shorter DNS resolving delays without a restart.

I added a counter in the WiFiGenericClass::hostByName function, greater than 4 retries with an extended delay in between tries only if DNS fails first and then restart if nothing resolves. I tried catching a flag in my main loop as an alternative but this only worked some of the times as others the err loop would be in a WiFiClientSecure.cpp function but eventually after many err logs would return to hostByName and then count up to a restart. It's not a fix by any means but it'll have to do for me with no manual rebooting at least.

I did find these links which may be helpful
https://www.nongnu.org/lwip/2_0_x/group__dns.html

and

https://tools.ietf.org/html/rfc6762#section-5 (In regards to one-shot queries)

  _"but this is only the one problematic point in this issue."_ 

Andrzej, I've read your info on the other issues and I'm hoping someone that can fix these, will attempt at some point. Unfortunately, I don't have the skill to do so.

@DAVIDBETAN2000
Copy link

compilando con arduino funciona normal

me-no-dev pushed a commit that referenced this issue Sep 30, 2020
Real DNS resolving timeout used by lwip library is 14[s] (7[s] for DNS1 + 7[s] for DNS2). Function WiFiGenericClass::hostByName() has timeout set to lower value (only 4[s]), so callback function may be called after this low timeout and it may overlappe stack memory used now by other function.
Fixes #3722
@dralisz82
Copy link

dralisz82 commented Dec 8, 2020

Hi Andrzej,

First of all, thank you so much for your efforts put into this! True professional attitude and analysis! ;)

Hereby I share my experiences, maybe useful for someone:
I've been struggling with the exact same problem recently.
My software sends HTTP GET requests to a certain server each minute. I have multiple devices deployed.
There is a test device close to the Wifi router, and it is working quite stable.
There is another device deployed remotely, and it connects to a router via a Xiaomi Wifi Repeater.
With this latter device I've observed that connections are OK for many hours, but after ~21 hours (~65k seconds - strange), the hostByName(): DNS Failed error comes.
When these failures appear, at the beginning it succeeds sporadically, but mostly fails, then a bit later it always fails.
By using arduino-esp32 1.0.4 sooner or later the device is restarted by an unexpected TG1WDT_SYS_RESET (very rarely the device completely halts instead, till power is tripped - hint: I suggest to utilize RTC WDT to recover from such situations).

I've upgraded to arduino-esp32 1.0.5-rc2, and now finally the software doesn't crash, but the failing requests remained.

My software checks for an OTA software update once in each 24 hours, so this is now performed ~3 hours after the problem starts. Luckily the update site is on another server, so hostByName() is called with another domain. Interestingly this new (and not served from cache) DNS request kicks back everything to normal. (And everything starts over on the next day: 3 hours "outage", and back to normal.) UPDATE: I have another device, not having the fw update functionality and connected to the same repeater, and after 3 hours of mess, it also continues normal operation. This device also produced the 3 hours long DNS disturbance (at least it was not completely silent, but many requests succeeded during the period). The 2 devices were not started at the same time, hence the disturbances are not at the same time, but in both cases ~21 hours after the devices are started.

Glad to see that in 1.0.5-rc2 your solution is included!
I think it is the reason that TG1WDT_SYS_RESETs and rare system halts are eliminated (the interrupt watchdog may be triggered by stack corruption, so this absolutely supports your conclusion).
So my software is rock stable (I mean no crashes, survive connection disturbances) now, thanks to your contribution!
Cannot say the same for the Wifi connections, as DNS still fails for me after ~21 hours / ~65k seconds for the same hostname. As I have another device connected to an Asus router, not showing this symptom, I think it is an interworking issue between ESPs and the Xiaomi WiFi repeater, although I could not conclude which device is the culprit, yet.

So thanks, again for rolling up this hostByName() fault and glad that your solution is included in 1.0.5!

Greetings from Hungary! :)

BR,
Szilárd

@evanmiller29
Copy link

This seems to be such a good improvement. I've been using PlatformIO and to get the new version of esp32 working there to stop the timeout. Add this to your platform.ini and it'll pull the newest version of ESP32.

framework = arduino
platform_packages =
    platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git

@me-no-dev
Copy link
Member

@evanmiller29 you should use instead use the latest release (1.0.6). Git master will move to 2.0 and many things could stop working (that would be mostly to some changes in the API). PIO might also need some time to adjust.

@YordanYanakiev
Copy link

YordanYanakiev commented Apr 3, 2021

I have the same problem with 1.0.5.
I made a test server to which each 15 second the ESP32 were connecting and getting data, then go to light sleep.
The result was that after a while - i've started randomly getting -1 as result.
Now with 1.0.6 this seems to be better ( at least with the initial tests ), but now I got disconnected from the wifi after a while of this test.
Is there a some specific thing or best practice to follow when I go to light sleep and wake up from it to connect/disconnect from wifi. Note that I am using WiFiMulti.
Thank You in advance guys ! :)

@Nischal-Poudel
Copy link

Hey, I have been experiencing the same issue with my esp 32. It connects to a https every 2 sec to get a API request and then closes the connection with the server with client.stop(). I am adding this to a function and the function is called every 2 sec.

The code works fine for 10-15 minutes then the infamous error pups out and there is no-improvements thereafter.
I have been reading this thread since #2778. so, has anyone found a rock solid fix-to this?
I am using platform Io so, can I modify my library there or do I have to use my Arduino?
Has the problem fixed or not? I am sctraching my head around for more than a week now

@YordanYanakiev
Copy link

Rock-solid ? - the short answer is "No", disregarding that the best part of ESP's is the WiFi as a controller - it is one of the worse as a software.
There is a fix, which did most of it if You trace my suggestion for it.
Yet, they implemented it, it worked, but then scratched out, and then again did other changes, which I am not sure if it is good at the moment.
So, first of all -did you try with the latest SDK ?

@Nischal-Poudel
Copy link

Nischal-Poudel commented Mar 30, 2022 via email

@YordanYanakiev
Copy link

So, You are on 2.0.2 ?

@YordanYanakiev
Copy link

YordanYanakiev commented Mar 30, 2022

Also You can try the dev version of it https://github.com/espressif/arduino-esp32/releases/
I am not platform IO fan. I'm under Visual Studio + Visual Micro, so I can't suggest in Your case.

@Nischal-Poudel
Copy link

Nischal-Poudel commented Mar 30, 2022 via email

@han173
Copy link

han173 commented Oct 15, 2022

I am working on this part to establish a get request from ESP32 but still the same problem
ror code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
How can i fix it please?
This is my code:
#include <WiFi.h>
#include <HTTPClient.h>
//Setting your network credentials
Modify the next lines with your network credentials: SSID and password. The code is well commented on where you should make the changes.

const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

//Setting your serverName
You also need to type your domain name or Node-RED IP address, so the ESP publishes the readings to your own server.

//Your Domain name with URL path or IP address with path
String serverName = "http://127.0.0.1:1880/update-sensor";

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastTime = 0;
// Timer set to 10 minutes (600000)
//unsigned long timerDelay = 600000;
// Set timer to 5 seconds (5000)
unsigned long timerDelay = 5000;

void setup() {
Serial.begin(115200);

WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());

Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}
//In the loop() is where you actually make the HTTP GET request every 5 seconds with sample data:
void loop() {
//Send an HTTP POST request every 10 minutes
if ((millis() - lastTime) > timerDelay) {
//Check WiFi connection status
if(WiFi.status()== WL_CONNECTED){
HTTPClient http;
//The ESP32 makes a new request in the following URL to update the sensor field with a new temperature

  String serverPath = serverName + "?temperature=24.37";
  // Your Domain name with URL path or IP address with path
  http.begin(serverPath.c_str());
  
  // Send HTTP GET request
  int httpResponseCode = http.GET();

//Then, the following lines of code save the HTTP response from the server.
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}
// Free resources
http.end();
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}

@TD-er
Copy link
Contributor

TD-er commented Oct 15, 2022

Can you please wrap your code in 3 back quotes?

Something like this:

'''
My code
'''

But then using the back-quote (left from the "1" on the keyboard)

@han173
Copy link

han173 commented Oct 15, 2022

........
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
String serverName = "http://127.0.0.1:1880/update-sensor";
unsigned long lastTime = 0;
unsigned long timerDelay = 5000;

void setup() {
Serial.begin(115200);

WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());

Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {

if ((millis() - lastTime) > timerDelay) {

if(WiFi.status()== WL_CONNECTED){
HTTPClient http;

String serverPath = serverName + "?temperature=24.37";

http.begin(serverPath.c_str());

int httpResponseCode = http.GET();
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}

http.end();
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
..........

@TD-er
Copy link
Contributor

TD-er commented Oct 15, 2022

Nope, I meant these

` ` `
Your code
` ` `

But then without the spaces.
You're now using 10x a dot.

@han173
Copy link

han173 commented Oct 15, 2022

`
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
String serverName = "http://127.0.0.1:1880/update-sensor";
unsigned long lastTime = 0;
unsigned long timerDelay = 5000;

void setup() {
Serial.begin(115200);

WiFi.begin(ssid, password);
Serial.println("Connecting");
while(WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.print("Connected to WiFi network with IP Address: ");
Serial.println(WiFi.localIP());

Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {

if ((millis() - lastTime) > timerDelay) {

if(WiFi.status()== WL_CONNECTED){
HTTPClient http;

String serverPath = serverName + "?temperature=24.37";

http.begin(serverPath.c_str());

int httpResponseCode = http.GET();
if (httpResponseCode>0) {
Serial.print("HTTP Response code: ");
Serial.println(httpResponseCode);
String payload = http.getString();
Serial.println(payload);
}
else {
Serial.print("Error code: ");
Serial.println(httpResponseCode);
}

http.end();
}
else {
Serial.println("WiFi Disconnected");
}
lastTime = millis();
}
}
`

Is that ok right now?

@TD-er
Copy link
Contributor

TD-er commented Oct 15, 2022

Nope, but anyway let's not clutter the thread with multiple attempts (as you can edit your posts too)

I am working on this part to establish a get request from ESP32 but still the same problem
ror code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
Error code: -1
How can i fix it please?

#include <WiFi.h>

#include <HTTPClient.h>

const char * ssid = "REPLACE_WITH_YOUR_SSID";
const char * password = "REPLACE_WITH_YOUR_PASSWORD";
String serverName = "http://127.0.0.1:1880/update-sensor";
unsigned long lastTime = 0;
unsigned long timerDelay = 5000;

void setup() {
  Serial.begin(115200);

  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  Serial.println("Timer set to 5 seconds (timerDelay variable), it will take 5 seconds before publishing the first reading.");
}

void loop() {

  if ((millis() - lastTime) > timerDelay) {

    if (WiFi.status() == WL_CONNECTED) {
      HTTPClient http;

      String serverPath = serverName + "?temperature=24.37";

      http.begin(serverPath.c_str());

      int httpResponseCode = http.GET();
      if (httpResponseCode > 0) {
        Serial.print("HTTP Response code: ");
        Serial.println(httpResponseCode);
        String payload = http.getString();
        Serial.println(payload);
      } else {
        Serial.print("Error code: ");
        Serial.println(httpResponseCode);
      }

      http.end();
    } else {
      Serial.println("WiFi Disconnected");
    }
    lastTime = millis();
  }
}

If you look at the text in this post, when quoting it, you will see what I meant.
But let's now look at the code first instead of further polluting the thread.

@TD-er
Copy link
Contributor

TD-er commented Oct 15, 2022

I think I found the issue in your code:

String serverName = "http://127.0.0.1:1880/update-sensor";

The ESP will try to access itself. (127.0.0.1 is localhost)
However you're not running a webserver on it and even if you did, it would not be possible to make a client call and serve it at the same time.
This code is running as a single thread, so you cannot use it to connect to something also running on the same node.

@han173
Copy link

han173 commented Oct 15, 2022

the clie

I think I found the issue in your code:

String serverName = "http://127.0.0.1:1880/update-sensor";

The ESP will try to access itself. (127.0.0.1 is localhost) However you're not running a webserver on it and even if you did, it would not be possible to make a client call and serve it at the same time. This code is running as a single thread, so you cannot use it to connect to something also running on the same node.

I want to configure the ESP32 as a client and the node red application running locally on my PC as server that's why i put the server name like in the code. ESP32 is connected to wifi with IP adress 192.168.1.17

@TD-er
Copy link
Contributor

TD-er commented Oct 15, 2022

But still, 127.0.0.1 is always (!!!) localhost.
So it will try to connect to port 1880 on the ESP itself, not your Windows PC.

If you try to access another host, you must use the IP of that machine and also make sure the service running on that port is accessible from another host in your network.

@han173
Copy link

han173 commented Oct 15, 2022

But still, 127.0.0.1 is always (!!!) localhost. So it will try to connect to port 1880 on the ESP itself, not your Windows PC.

If you try to access another host, you must use the IP of that machine and also make sure the service running on that port is accessible from another host in your network.

Many thanks :)
it is ok right now i changed to the ipv4 of my station and it works perfectly.
Again, great thanks !!!!

@iammyur
Copy link

iammyur commented Jul 21, 2024

I just resolved this issue, I know it is not proper solution for this but workable for small project.

String hostnameIP "IPAddress" //Which_You_Find_from_ https://whatismyipaddress.com/hostname-ip entering hotsname(e.g. google.com/// IP = 142.250.68.78)

void setup()
{

// your other entire code..........................

IPAddress ip;
if(WiFi.hostByName(hostnameIP, ip))
{
Serial.print("IP address of ");
Serial.print("google.com"); // your domain
Serial.print(" is ");
Serial.println(ip);
}
else
{
Serial.println("Hostname resolution failed.");
}
}

Screenshot 2024-07-21 091244

Hope I bring usefull solution.

@emmby
Copy link

emmby commented Oct 6, 2024

Like others, I am still seeing my ESP32 work for awhile, but then start failing with DNS Failed consistently after that.

My code checks an https url once an hour. Within about a day, it almost always gets into a state where almost none of the http requests are working anymore. Some of them work, but most of them do not, all to the same server.

06:19:02.768 -> [47466011][D][HTTPClient.cpp:303] beginInternal(): protocol: https, host: api.openweathermap.org port: 443 url: /data/3.0/onecall?...
06:19:02.810 -> [47466022][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0
06:19:02.810 -> 
06:19:02.810 -> [47466029][E][WiFiGeneric.cpp:1582] hostByName(): DNS Failed for api.openweathermap.org
06:19:02.810 -> [47466037][D][HTTPClient.cpp:1163] connect(): failed connect to api.openweathermap.org:443
06:19:02.834 -> [47466045][W][HTTPClient.cpp:1483] returnError(): error(-1): connection refused
06:19:02.834 -> http status: -1 connection refused

I'm using esp32 2.0.13 for arduino. On 3.1.0-RC1 the error is somewhat different:

18:14:01.071 -> [36455382][D][HTTPClient.cpp:303] beginInternal(): protocol: https, host: api.openweathermap.org port: 443 url: /data/3.0/onecall?...
18:14:01.112 -> [36455397][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0
18:14:01.112 -> 
18:14:03.588 -> [36457884][D][WiFiGeneric.cpp:1039] _eventCallback(): Arduino Event: 5 - STA_DISCONNECTED
18:14:03.588 -> [36457885][W][WiFiGeneric.cpp:1061] _eventCallback(): Reason: 200 - BEACON_TIMEOUT
18:14:03.588 -> [36457889][D][WiFiGeneric.cpp:1085] _eventCallback(): WiFi AutoReconnect Running
18:14:03.620 -> [36457897][E][ssl_client.cpp:129] start_ssl_client(): socket error on fd 48, errno: 113, "Software caused connection abort"
18:14:03.620 -> [36457907][E][WiFiClientSecure.cpp:144] connect(): start_ssl_client: -1
18:14:03.620 -> [36457913][D][HTTPClient.cpp:1163] connect(): failed connect to api.openweathermap.org:443
18:14:03.620 -> [36457921][W][HTTPClient.cpp:1483] returnError(): error(-1): connection refused
18:14:03.620 -> http status: -1 connection refused

which seems related to #3686

Code is:

#include <HTTPClient.h>

WiFiClientSecure client;
HTTPClient http;
...

  http.begin(client, forecastUrl);
  int code = http.GET();
  String json = http.getString();

@me-no-dev
Copy link
Member

@emmby how about 3.0.x versions? On 3.1 you got disconnected from the WiFi, so it is normal for the request to fail. Maybe something is keeping your ESP so busy that it can not handle the WiFi on time (thus you got BEACON_TIMEOUT)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet