Skip to content

HTTPClient setTimeout hasn't any effect #1433

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
fabianoriccardi opened this issue May 24, 2018 · 34 comments
Closed

HTTPClient setTimeout hasn't any effect #1433

fabianoriccardi opened this issue May 24, 2018 · 34 comments
Assignees
Labels
Area: BT&Wifi BT & Wifi related issues Status: Solved
Milestone

Comments

@fabianoriccardi
Copy link

Hardware:

Board: Lolin D32
Core Installation/update date: 24/May/2018
IDE name: Arduino IDE
Flash Frequency: 40Mhz
Upload Speed: 921600

Description:

While using the WiFiClient library, the method setTimeout() does't work. I mean, it seems always fixed to certain among (around 18seconds). The code is showed below...You can see that I call setTimeout twice to be sure to set the proper value, but still doesn't work.

The code below is reporting the library example, enriched with setTimeout() method.

Sketch:

void loop(){
// wait for WiFi connection
    if((wifiMulti.run() == WL_CONNECTED)) {

        HTTPClient http;
        http.setTimeout(1000);
        USE_SERIAL.print("[HTTP] begin...\n");
        // configure traged server and url
        
        http.begin("http://192.168.0.101/index.html"); //HTTP
        http.setTimeout(1000);
        USE_SERIAL.print("[HTTP] GET...\n");
        // start connection and send HTTP header
        int start=millis();
        int httpCode = http.GET();
        int end =millis();
        Serial.println(String("Effective timeout: ") + (end-start));
        // httpCode will be negative on error
        if(httpCode > 0) {
            // HTTP header has been send and Server response header has been handled
            USE_SERIAL.printf("[HTTP] GET... code: %d\n", httpCode);

            // file found at server
            if(httpCode == HTTP_CODE_OK) {
                String payload = http.getString();
                USE_SERIAL.println(payload);
            }
        } else {
            USE_SERIAL.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
        }

        http.end();
    }

    delay(5000);
}

Debug Messages:

[HTTP] begin...
[HTTP] GET...
Effective timeout: 18242
[HTTP] GET... failed, error: connection refused
[HTTP] begin...
[HTTP] GET...
Effective timeout: 18498
[HTTP] GET... failed, error: connection refused
@pcbtborges
Copy link

You are using a method that I tried and did not work and it does not seem to be a timeout problem.
Try something like the following:
`//#include <WiFi.h>
#include <HTTPClient.h>

const char* ssid = "Skynet";
const char* password = "xxx";
const char* host = "192.168.66.104";
const char* protStr = "http://";

int jd = 1234567;
char *area = "Area01";
char type = 'h';
int value = 1;
boolean okFlag = true;
int counter=0,httpCode;

String url, payload;

void setup(){
Serial.begin(115200);
// Start by connecting to a WiFi network
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());
zap();

for (int i=0;i<1001;i++){
if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
url = protStr;
url += host;
url += "/esp32/insert.php?";
url += "jd=";
url += jd;
url += "&area=";
url += area;
url += "&type=";
url += 'h';
url += "&value=";
url += value;
value++;

HTTPClient http;
http.begin(url);                                              //Specify the URL
httpCode = http.GET();
payload = http.getString();      
Serial.print(httpCode);
Serial.print(", ");
Serial.print(value);
Serial.print(", ");
Serial.println(payload);                                        //Make the request
if (httpCode > 0) { //Check for the returning code
  counter++;
} else {
  okFlag = false;
}    
http.end(); //Free the resources    

if(counter>1000 && okFlag == true){
  zap();
}

}
}
}

void zap(){
HTTPClient http;
url = protStr;
url += host;
url += "/esp32/delete.php";
http.begin(url); //Specify the URL
httpCode = http.GET();
counter = 0;
okFlag = true;
Serial.println("Todos registros eliminados com sucesso");
http.end(); //Free the resources
}

void loop(){

}
`

@lbernstone
Copy link
Contributor

lbernstone commented Sep 2, 2018

The timeout is in seconds. I don't think you mean 1000 seconds.

@fabianoriccardi
Copy link
Author

I've just updated the esp32 firmware to the last version and still not working... Are you sure about measurement unit? In the esp8266 environment it should be in millisecond

@lbernstone
Copy link
Contributor

lbernstone commented Sep 4, 2018

I am certain it is seconds, but you are correct that it is not working. That timeout can only be set once a connection is established. Chicken and egg problem.

@JonSilver
Copy link

JonSilver commented Sep 4, 2018

@lbernstone are you sure about HTTPClient::setTimeout being specified in seconds? In the code, it's used to set _tcpTimeout which is elsewhere compared to (millis() - lastDataTime) as well as being used to set the TCP timeout in _tcp->setTimeout(timeout)

Unless I'm very much mistaken (which is entirely possible) it looks like milliseconds to me. And if you set timeout as if in seconds, for example to 10, then http operations don't ever have a chance to complete, returning with a HTTPC_ERROR_READ_TIMEOUT error every time because it only waits 10ms.

@lbernstone
Copy link
Contributor

https://github.com/espressif/arduino-esp32/blob/master/libraries/WiFi/src/WiFiClient.h#L83
I'm not saying it is the right thing, just what is in the code. Since it doesn't work for the most typical case, I think it probably needs a rewrite.

@JonSilver
Copy link

@mrcodetastic
Copy link

mrcodetastic commented Jan 16, 2019

The setTimeOut function in both WiFiClient AND HTTPClient is in SECONDS.

Also, the setTimeOut can only be performed after a xxx.connect(). Not before!

I learned this the hard way.

@pcbtborges
Copy link

pcbtborges commented Mar 15, 2019

Time out is in miliseconds and it works 100%.
I use like this:
http.setTimeout(5000);
httpResponseCode = http.GET(); //Make the request

Means if httpResponseCode arrives promptly, httpResponseCode = 1, the code moves on.
Otherwise it will wait up to 5000ms before giving up and setting httpResponseCode = -1 and continue the code sequence.

That is my understanding and it works precisely like that, I tested.
Hope it helps
Paulo

@fabianoriccardi
Copy link
Author

fabianoriccardi commented Mar 16, 2019

I've jus tried again:

EDIT: Maybe this is the fix addressed by #2383 and already fixed

@boarchuz
Copy link
Contributor

No, that's a little different. The setTimeout here is only for the maximum connection time when you're already connected to the server. That's why it has no effect when the server is offline and you're stuck waiting 18+ seconds for that impossible connection to be established.

The PR you linked is to set this connection timeout for WiFiClient. I just made a simple little PR to let you access this functionality via HTTPClient: #2606

Usage might be something like:

//Prepare the request
http.begin("http://192.168.0.44/index.html");
//It's a local IP so tell it to abandon after 100ms if no connection
http.setConnectTimeout(100);
//Do it
int httpCode = http.GET();
if(httpCode < 0)
{
  //This will be the code you get on connect timeout:
  if(httpCode == HTTPC_ERROR_CONNECTION_REFUSED) 
    Serial.println("Server offline :(");
}

@fabianoriccardi
Copy link
Author

Now it is clear, thanks!

@hdsxjtu
Copy link

hdsxjtu commented Jun 25, 2019

@boardchuz it works.

@stale
Copy link

stale bot commented Aug 24, 2019

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 24, 2019
@stale
Copy link

stale bot commented Sep 7, 2019

This stale issue has been automatically closed. Thank you for your contributions.

@stale stale bot closed this as completed Sep 7, 2019
@YordanYanakiev
Copy link

The issue is still on, and it's quite serious and randomly occurring.

@Kromtar
Copy link

Kromtar commented Sep 4, 2021

any news ?

@garageeks
Copy link

garageeks commented Oct 23, 2021

set.Timeout still not having any effect on latest release (2.0.0), The timeout appears to be stuck at 30 seconds.
HOWEVER setConnectTimeout works as intended by @boarchuz .
As I have a use case where need to connect to 4 devices 2 times, if they are offline it takes 4 minutes to go through all the connections.
I tried to place setTimeout before begin or before GET and still getting 30 s timeout instead of the expected 10s
Remember to replace it with setConnectTimeout with time in milliseconds.

		http.begin(hostName);
		http.setTimeout(10);
		// Send HTTP GET request
		int httpResponseCode = http.GET();

THIS WORKS

		http.begin(hostName);
		http.setConnectTimeout(10000);
		// Send HTTP GET request
		int httpResponseCode = http.GET();

@YordanYanakiev
Copy link

not sure if it works. I am keep getting it working on randomly basis.
I think there is a bigger issue, and this is a great shame to the ESP's, since their main usage is just because of the WiFi functionality, which is supposed to be absolutely flawless, but here we are - 3 years the WiFi's have absurdly big issue, and no one care.
All redirecting to some examples, and if it works - them everything is fine, but it isnt.

@garageeks
Copy link

garageeks commented Oct 25, 2021

I agree that the Wi-Fi stack is really flaky and prone to crashes. In my previous experience, even a simple periodic HTTP client connection randomly crashed the whole thing, mainly due to bad exceptions management. However they have been constantly and massively improving it. Additionally it is running on bare metal microcontroller, there is no operating system with a kernel and protected mode.
I've been testing the setConnectTimeout parameter, so far it worked for 38 hours straight, I will get back once I tested it for longer. You may give it a try on the latest 2.0.0 release.

@VojtechBartoska VojtechBartoska added the Status: Awaiting triage Issue is waiting for triage label Oct 25, 2021
@YordanYanakiev
Copy link

YordanYanakiev commented Oct 25, 2021

I am on 2.0.0. There is not much difference from 1.0.6.
If the controller passed from wake state to light sleep state in a thread with lower priority where Wifi is working, then wake up, and then connect to a wifi, and then try to make a http get - it will work randomly or not working at all with a great chance for practically even the wifi to fail to connect, or the client to fail to resolve, or just not do anything at all.
It's an absurd as I said above.
Especially notable with LilyGO TWatch 2020 v1.

@garageeks
Copy link

I see. In the current test I'm doing there is no light sleep as it has a AsyncWebServer running and must be available at any time. I have another firmware where there is only a HttpClient and light sleep would save some power, will test it there as well.
Sometimes it's a matter of getting the right sequence of instructions, like WiFi.config before WiFi.mode
Anyway I share your frustration, it should be more robust.

@VojtechBartoska VojtechBartoska removed Status: Stale Issue is stale stage (outdated/stuck) Status: Awaiting triage Issue is waiting for triage labels Apr 6, 2022
@VojtechBartoska VojtechBartoska added Area: BT&Wifi BT & Wifi related issues Resolution: Awaiting response Waiting for response of author labels Apr 6, 2022
@VojtechBartoska
Copy link
Contributor

Hello, are you able to test your issue on development version 2.0.3-RC1 to check if this is still valid? You can take a look on Docs where is explained how to choose development release version in Arduino IDE.

@fabianoriccardi
Copy link
Author

Tested 2.0.3-RC1, timeout is now stuck to 30sec.

I looked into your commit and it regards only secure connection, so it doesn't seem relevant to this issue.

@VojtechBartoska
Copy link
Contributor

Thanks for testing, issue added to our Roadmap and we will investigate this further.

@VojtechBartoska VojtechBartoska moved this from Todo to Under investigation in Arduino ESP32 Core Project Roadmap Apr 21, 2022
@VojtechBartoska VojtechBartoska added the Status: Test needed Issue needs testing label May 4, 2022
@VojtechBartoska VojtechBartoska added this to the 2.0.4 milestone May 4, 2022
@P-R-O-C-H-Y
Copy link
Member

Hi @fabianoriccardi.
Can you run your sketch on 2.0.3 stable version with "Core debug level: DEBUG" and paste here the debug message?
Thanks!!

@fabianoriccardi
Copy link
Author

The timeout is reduced to 5seconds instead of >15seconds, but the timeout should be 1 seconds.. Here the report of a couple of iterations:

[HTTP] begin...
[ 10332][D][HTTPClient.cpp:303] beginInternal(): protocol: http, host: 192.168.0.156 port: 80 url: /index.html
[HTTP] GET...
[ 10342][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0

[ 15346][I][WiFiClient.cpp:253] connect(): select returned due to timeout 5000 ms for fd 48
[ 15347][D][HTTPClient.cpp:1149] connect(): failed connect to 192.168.0.156:80
[ 15350][W][HTTPClient.cpp:1469] returnError(): error(-1): connection refused
Effective timeout: 5015
[HTTP] GET... failed, error: connection refused
[ 15368][D][HTTPClient.cpp:408] disconnect(): tcp is closed

[HTTP] begin...
[ 20370][D][HTTPClient.cpp:303] beginInternal(): protocol: http, host: 192.168.0.156 port: 80 url: /index.html
[HTTP] GET...
[ 20380][D][HTTPClient.cpp:598] sendRequest(): request type: 'GET' redirCount: 0

[ 25383][I][WiFiClient.cpp:253] connect(): select returned due to timeout 5000 ms for fd 48
[ 25384][D][HTTPClient.cpp:1149] connect(): failed connect to 192.168.0.156:80
[ 25387][W][HTTPClient.cpp:1469] returnError(): error(-1): connection refused
Effective timeout: 5014
[HTTP] GET... failed, error: connection refused
[ 25405][D][HTTPClient.cpp:408] disconnect(): tcp is closed

@P-R-O-C-H-Y
Copy link
Member

P-R-O-C-H-Y commented May 12, 2022

Can you try calling http.setConnectTimeout(1000); after http.begin() please?

For what i see, its failing (timeouting) in connection, and not for data read. For Reading data you set 1000ms by setTimeout, but to set connection timeout use setConnectTimeout :)

Let us know, if that helps.

@fabianoriccardi
Copy link
Author

fabianoriccardi commented May 12, 2022

I didn't know the existence of setConnectTimeout.. forgive me the issue was opened 4 years ago, I forget few details :)

I tested both the functions with a proper API and they work as expected. setTimeout works fine even if it placed after http.begin()!

However, the last issue is about http.setConnectTimeout(2800): it truncates the timeout to the "second", ignoring the "decimal part" (i.e. timeout 2800ms will last 2000ms).

EDIT: Instead setTimeout is precise (i.e. subsecond timeouts are met)

@P-R-O-C-H-Y
Copy link
Member

I am glad its working :)
I will check what we can do about the ms -> seconds, it should be at least rounded from 2800ms to 3000ms the same as the httpclient.setTimeout is. In future, it will be changed to stop rounding and sets the timeout in ms as it is :)

@P-R-O-C-H-Y
Copy link
Member

setConnectTimeout is in ms, but when passed to WifiClient:connect its converted to seconds by /1000. This may be changed in next minor version 2.1.0, you can take a look on prepared PR #6676 and checkout the changes manually for now. Maybe we can at least add the rounding as it is in HTTPClient:setTimeout before the PR get merged.

@fabianoriccardi
Copy link
Author

Actually, I can continue to use the current stable version, but I was wondering why this unexpected behaviour is happening and I wanted to inform you.

Thanks for your work and the patience!

I think we can close the issue :)

@P-R-O-C-H-Y
Copy link
Member

Thanks for you reports and quick answers :)

So I am closing the issue, it can be always reopened ;)

Repository owner moved this from Under investigation to Done in Arduino ESP32 Core Project Roadmap May 13, 2022
@P-R-O-C-H-Y P-R-O-C-H-Y self-assigned this May 13, 2022
@garageeks
Copy link

garageeks commented May 13, 2022

I have noticed that a couple of weeks ago some, but not all, of our deployed nodes stopped calling home once we took down the server for maintenance for a couple of hours. I don't know if setConnectTimeout() is at play or not. Will perform tests and if related will reopen the issue.

@VojtechBartoska VojtechBartoska added Status: Solved and removed Status: Test needed Issue needs testing labels May 13, 2022
@VojtechBartoska VojtechBartoska removed the Resolution: Awaiting response Waiting for response of author label May 26, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: BT&Wifi BT & Wifi related issues Status: Solved
Projects
Development

No branches or pull requests