Timer callback method calling HttpClient crashes on Electron

Phew, finally figured out why some code of mine is crashing on Electron and thought I’d share since I didn’t find any articles that helped me.

I had a fair sized application developed for Photon. Worked great. I use the Photon for developing and then push to Electron for my real use. Everything was working fine on Photon, but guaranteed SOS on Electron… I stripped my app back to complete basis and figured it out.

My app uses a Timer to initiate sending some data using the HttpClient. On Photon I use the Timer Callback to directly call the HttpClient, works fine… on Electron the call takes some 8s, for some reason this is a big problem and is gauranteed to get me an SOS.

So the solution was to set a flag in a very small method from the Timer and then in the main loop, check the flag and send from there…

#include "HttpClient/HttpClient.h"

unsigned int nextTime =0;
Timer send_timer(30000, apiDataDummy);      //send Something every 30s...   <=== This fails on Electron
//Timer send_timer(30000, dosend);      //send Something every 30s...   <=== this works
bool send=false;

const char server[] = "anywebsite.co.uk";
const char dataUri[] = "/v1/data";
HttpClient http;
http_request_t request;
http_response_t response;
http_header_t headers[] = {                 // Headers currently need to be set at init, useful for API keys etc.
    { "Accept" , "*/*"},
    { NULL, NULL }                          // NOTE: Always terminate headers with NULL
};

String data; 
    
void setup() {
    send_timer.start();
    Serial.begin(115200);
}

void loop() {
    if (send)
    {
        apiDataDummy();
        send=false;
    }
    
    if (nextTime > millis()) {
        return;
    }
    debugOutLn("Been alive for "+ String(millis()/1000));
    nextTime = millis() + 1000;
}

void debugOutLn(String output)
{
    Serial.println(output);
}

void dosend()
{
    send=true;
}

void apiDataDummy()
{
    
    // Request path and body can be set at runtime or at setup.
    request.hostname = server;
    request.port = 80;
    request.path = dataUri;

    // The library also supports sending a body with your request:
    //request.body = data;

    // Get request
    http.get(request, response, headers);
}
2 Likes

And I have the same problem and have it resolved in the same way as you have stated. So the problem exists only on Electron?

I suspect if you had some super-slow wifi or poor website you could see the same on Photon - its a function of the response time I suspect…

That's pretty much how it's supposed to be done. Timers, as well as function calls and interrupts should be kept as short as possible. Calling functions from an interrup is generally a bad idea. Rather, use the loop to check for flags, which should ensure things don't get 'stuck'.

3 Likes

Yeah, I guess, just takes some figuring out when its perfect on Photon… missing my java stack dumps :-). I can’t decide if an async http client would be good…

I also found another issue I’m struggling to recreate that seemed Electron specific. I have a scenario where I (re)start a timer (from inside the time callback method) and it crashes religiously too, but can’t seem to recreate it outside a pile of my code… as soon as I can I’ll post that!