Non-blocking connection to a server

Hello everyone! :slightly_smiling_face:

TL;DR

How can I initiate a non-blocking connection to a server (e.g., Telegram) so the code doesn't freeze while waiting for the result, and I can check later if the connection was successful?


I'm working on a project where I use an ESP32 to communicate with Telegram through a bot. This part works fine: I can exchange messages without problems.

However, the ESP32 also controls some temperature sensors and applies a filter to the data, which requires a constant sampling period.

Here’s the issue:
When the Telegram server is not reachable (ESP connected to the WiFi without internet for eg.), calling:

Serv_Telegram.connect(Serveur_Telegram, 443);

can block the code for up to 20 seconds before it times out.
I’ve already tried using:

Serv_Telegram.setHandshakeTimeout(3);

which reduces the blocking time, but it’s still blocking nonetheless.

What I’m trying to achieve is something like how the WiFi connection works:

WiFi.begin(SSID, PASS);  // Initiates connection
// Later in the loop:
if (WiFi.status() == WL_CONNECTED) { ... }

This way the connection the WiFi could take 20sec but it doesn't matter because in the meantime the ESP is free to do something else.

But with WiFiClientSecure, the .connect() call is blocking.
So:

Is there a way to start the connection without blocking, and later check if the connection succeeded?

If needed, I can give more details.
Thanks a lot for any ideas or tips!

In general, it does not. Please explain why you think so in this particular case.

Well it's some filters of n orders which means I have to take a sample every XX seconds and use a formula to get the new filtered value. For a first order:

y = alpha * newValue + (1 - alpha) * oldValue;

If the period isn't correct then the filtered value isn't either.

But even without this, the ESP32 doesn't do only this. So let's say that I just don't want it to be blocked over several seconds. I'd rather ask for the connection to iniciate, then come back later to see if there is a response from the server to confirm the connection status.

Here is what I've tried so far:

  • Trying to resolve host by name with WiFi.hostByName("https://api.telegram.org", Serveur_Telegram). When the server is reachable, it's really fast but if not then it takes up 7 sec.
  • Tried to ping the server but it is the same. When it's not reachable then it takes time

What could be a solution if the connection cannot be done in a non-blocking way is:

  • Finding a way to have a non-blocking function hostByname()
  • Finding a way to have a non-blocking function ping(). I saw it exists for ESP8266 but didn't find anything for ESP32

You can use a timer interrupt to collect a data point and apply the filter.

However, I think you are putting too much emphasis on the importance of a constant sample interval.

If the sample interval is not constant, the filter won't perform exactly as the design specifications predict, but what are those specifications? How did you choose the period and the value of alpha?

How do you decide when a filtered average is "correct" and why is it important for temperature?

Thanks for replying

However, I think you are focusing on the wrong part of my request
Yes I could use an interrupt to get the temperature values from the sensors.

So as I mentionned in my last reply, let's just say that I don't want the ESP to be blocked at trying to connect to the server while it could do a lot of other stuff.

The ESP also retrieves the consumption of several devices, control the heating of the house, get the status of valve and so on.

So the point here is not how I could get the temperature in time (which a small part of the program) but more on how to connect in a non-blocking way (asynchronously) to a server.

It exists some library to make AsyncServer, so it must be possible no?

Yes, your problem is the internet connection, which is inherently unstable and unreliable.

The obvious solution is to do the data collection and analysis off line.

Try running the data collection in a different FreeRTOS task.

Why are you all trying to modify the way I get my data?

Please. The question here is how to connect to a server without having to wait for the connection to be done and just get the status of it whenever I need to use it.

If it helps you then just think that there could be other people willing to do it also with a complete different system around the https connection.

Either find a library that does so, or write your own.

Arduino forum members are not likely to do either for you, but you can post on the Jobs and Paid Collaboration forum section.

If data collection is running a separate FreeRTOS task, it won't matter whether the server connection is blocking or not.

Alright this I get it and what about the rest of the tasks?

If you're asking me what car to buy to go offroad you expect me to give you some details on several models of car right? You don't expect me to tell you to search for a road that access the location you want to go and use your feet right?

So here instead of trying to change the philosophy of my code, why not just tell me how to perform a connection to a server in a non-blocking way?

Or just let the others respond; if you don't know it's not a shame; because obviously I don't know either otherwise I wouldn't be asking.

Here are ten replies on the same subject that is not the one I came for, which could demotivate some people to read everything to finally give me some hints.

What happens when you "need to use it" and the server is down?

Well, you haven't bothered to tell us which telegram library you're using. So, we have no way of knowing how it currently connects to the server or what might be done differently. What you get back in answers depends a lot on how much info and effort you put into your questions.

If I "need to use it" when it's down then I try to perform a reconnection which block the ESP32.

If you're asking if it's a problem not reaching the server then; yes and no.
Yes it is because I won't be able to receive the message (and commands) from the users.
No it's not a problem because the rest is supposed to continue working. But it's not since the ESP32 is blocked

Then you must change the design of your code. It is as simple as that.

Good luck with the project, I'm out.

Depends on your experience and knowledge of programming in a multi-tasking environment. Which, from the way this conversation is going, I take to be nil.

Yes, in the first post of the topic I said I use the WiFiClientSecure object (so WiFiClientSecure.h library) to connect to the server.

The method used to connect is (still from the first post) Serv_Telegram.connect(Serveur_Telegram, 443)

Which is the method bothering me.

But which library is that? GitHub link please, I'd like to look at the source code.

Here it is:
Library WiFiClientSecure

And to communication with the Telegram server I just use first the method .connect(...) and then the .print(...) & .read() the send or get the data.