Skip to content

Fix esp32 timeout #842

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
wants to merge 1 commit into from
Closed

Fix esp32 timeout #842

wants to merge 1 commit into from

Conversation

cziter15
Copy link

No description provided.

@knolleary
Copy link
Owner

Please try to put something in the description, otherwise I have to read through all the changes to understand what the PR is about.

Given this library doesn't place any requirements on which network client it is used with it, is it really true to say that if ESP32 is defined then the client passed into this library will definitely by a WiFiClient instance? Aren't there cases where someone may need to use a different client on the ESP32 - such as WifiClientSecure?

@cziter15
Copy link
Author

cziter15 commented Mar 19, 2021 via email

@cziter15
Copy link
Author

cziter15 commented Aug 2, 2021

FYI: espressif/arduino-esp32#5487

Will be fixed on arduino-esp32 side.

@cziter15 cziter15 closed this Aug 2, 2021
@ArminPP
Copy link

ArminPP commented Nov 10, 2021

This problem is not fixed on the arduino-esp side as I suspect.

Since I will use both - WIFI and Ethernet in my application, I have expanded the solution from above (@cziter15) a little bit.

It is interesting that if no host is reachable ETH comes to a timeout very quickly, and the WiFi variant takes between 15-29 seconds. Since this is a blocking solution, the entire application is of course not available during this time.
By the way - the EthernetClient does not support the timeout parameter
int EthernetClient::connect(const char * host, uint16_t port)
vs. WifiClient:
int WiFiClient::connect(const char *host, uint16_t port, int32_t timeout)

If someone wants to use ETH and WiFi together with a shorter timeout than this might be helpful:

// on top of PubSubClient.cpp add:
#ifdef ESP32
#include <WiFi.h>
#endif

// then search for 'boolean PubSubClient::connect(const char *id, const char *user, const char *pass, const char *willTopic, uint8_t willQos, boolean willRetain, const char *willMessage, boolean cleanSession)' 
// and add/change following lines:
#ifdef ESP32
                if (WiFi.status() == WL_CONNECTED) // first test WiFi
                {
                    WiFiClient *wfc = (WiFiClient *)_client;
                    result = wfc->connect(this->domain, this->port, ((int32_t)this->socketTimeout));  // set timeout in ms
                }
                else // go on with original solution and no timeout setting...
                {
                    result = _client->connect(this->domain, this->port);
                }
#else
                result = _client->connect(this->domain, this->port);
#endif
            }
            else
            {
#ifdef ESP32
                if (WiFi.status() == WL_CONNECTED) // first test WiFi
                {
                    WiFiClient *wfc = (WiFiClient *)_client;
                    result = wfc->connect(this->ip, this->port, ((int32_t)this->socketTimeout));  // set timeout in ms
                }
                else // go on with original solution and no timeout setting...
                {
                   result = _client->connect(this->ip, this->port);
                }
#else
                result = _client->connect(this->ip, this->port);
#endif

In the program code the WiFi timeout now can be set, and it also works with ETH:

#define PubSubClientWiFiTimeout 1500 // ms
(..)
    EthernetClient ETHclient;
    WiFiClient WIFIclient;
(..)
 PubSubClient PubSubclientW(WIFIclient);
 PubSubclientW.setSocketTimeout(PubSubClientWiFiTimeout);
 connectMQTTclient(PubSubclientW)  // use PubSubClient with WiFi
(..)
 PubSubClient PubSubclientE(ETHclient);
 connectMQTTclient(PubSubclientE)   // use PubSubClient with ETH
(..)
bool connectMQTTclient(PubSubClient &client)
{
  client.setServer(...);
  client.connect(...);
// and so on...
}

@cziter15
Copy link
Author

cziter15 commented Nov 10, 2021

ArminPP, which arduino-esp32 version are you using?

No problems on my side anyway, since updated to 2.0.0 (no more device resets), but these fixes were targeting only WiFiClient library, no Ethernet one. Maybe something similar should be introduced in EthernetClient.

espressif/arduino-esp32#5496

If you want to control timeout in a clean-code manner, without digging into PubSubClient library, you should create your own Client based on WiFiClient or EthernetClient. Then you can override connect method used by PubSubClient (variant w/o timeout) and call timeout accepting variant instead, then simply instantiate your client and pass it to the PubSubClient library.

@ArminPP
Copy link

ArminPP commented Nov 10, 2021

@cziter15
I use an M5Stack board, and PIO says:

PLATFORM: Espressif 32 (3.3.2) > M5Stack Core ESP32
(..)
PACKAGES:
  framework-arduinoespressif32 3.10006.210326 (1.0.6)

I never had the reset issue, but the timeout via WiFi was way too long (about 15-29s) .
Since my programming skills in C ++ are limited, I used your solution to fix this (for me) ...

@cziter15
Copy link
Author

cziter15 commented Nov 10, 2021

Okay, it seems you're on 1.0.6 version, which doesn't include these fixes :)
See release history for reference: https://github.com/espressif/arduino-esp32/releases/

Device reset is handled by watchdog, when your device hangs. Maybe you have watchdog disabled or something else is preventing device from hang on connect method. In my case disabling LTE/4G network, but keeping up WiFi leads to reset on versions earlier than 2.0.0.

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

Successfully merging this pull request may close these issues.

3 participants