SYSTEM_MODE, SYSTEM_THREADING and loop(), waitFor(), waitUntil()

Is there a table anywhere that describes how the functions loop(), waitFor() and waitUntil() (possibly also the particle.*() functions) are affected by the SYSTEM_MODE and whether SYSTEM_THREADING is on or not? It might be that there is no effect but there are so many permutations and I seem to be seeing effects (possibly of my own making) that a table in one place would be really useful.

Exactly that’s a reason why a table would be hard to set up - and even more to understand.
It’d be more like a hypercubic table.

But when you understand what each of the terms you refered to actually does, the picture does clear up even without such a table.

In that case, let me be more specific. What I’m trying to do is time-out an attempt to connect to the network [on my Electron board] at 60 seconds, allowing me to do other things that have nothing to do with a connection in the mean time.

I have the following code:

// How long to wait for a network connection
#define WAIT_FOR_CONNECTION_SECONDS 60

// Only connect when it is required
SYSTEM_MODE(SEMI_AUTOMATIC);

// Connect to the network
static void connect() {
    time_t timeStarted = Time.now();
    
    if (!Particle.connected()) {
        Serial.printf("Connecting to network at %s (Time.now() %d seconds), waiting for up to %d seconds...\n", Time.timeStr().c_str(), Time.now(), WAIT_FOR_CONNECTION_SECONDS);
        Particle.connect();
        if (waitFor(Particle.connected, WAIT_FOR_CONNECTION_SECONDS)) {
            Serial.printf("Connected at %s (Time.now() %d seconds, connection process took %d seconds).\n", Time.timeStr().c_str(), Time.now(), Time.now() - timeStarted);
        } else {
            Serial.printf("WARNING: connection failed at %s (Time.now() %d seconds, timeout was %d seconds).\n", Time.timeStr().c_str(), Time.now(), Time.now() - timeStarted);
        }
    } else {
        Serial.println("Already connected to network.");
    }
}

void setup() {
    // Set time to zero when we start so that we know if time
    // is synchronised or not later on
    Time.setTime(0);
    
    // Opens up a Serial port so you can listen over USB
    Serial.begin(9600);
    
    // After a reset of the Electron board it takes a Windows PC several seconds
    // to sort out what's happened to its USB interface, hence you need this
    // delay if you're going to capture the serial output from here.
    delay (5000);
    
    // Connect to the network so as to establish time
    connect();
}

What I’m hoping for is that if the connection cannot be established within 60 seconds during setup() then the code continues into loop() where I can do the other stuff and then call connect() again later. If I run this code with the antenna disconnected to cause a failure, I get the following output:

Connecting to network at Thu Jan  1 00:00:05 1970 (Time.now() 5 seconds), waiting for up to 60 seconds... 
WARNING: connection failed at Thu Jan  1 00:05:27 1970 (Time.now() 327 seconds, timeout was 322 seconds).

So waitFor() is only getting back to me after 327 seconds and not 60. If I put the antenna on, I get the expected:

Connecting to network at Thu Jan  1 00:00:05 1970 (Time.now() 5 seconds), waiting for up to 60 seconds...
Connected at Thu Jan  1 00:00:55 1970 (Time.now() 55 seconds, connection process took 50 seconds).

If I enable threading then waitFor() doesn’t do any waiting at all and so I get:

Connecting to network at Thu Jan  1 00:00:05 1970 (Time.now() 5 seconds), waiting for up to 60 seconds...
WARNING: connection failed at Thu Jan  1 00:00:05 1970 (Time.now() 5 seconds, timeout was 0 seconds).

Question is: how do I achieve the effect I’m after? I’ve tried changing to SYSTEM_MODE(MANUAL) but that doesn’t make any difference to the behaviours.

1 Like

Now I hear you go :bulb:
I think this is a bug.
The code you’ve got there should in fact do what you expect it to do, but doesn’t (confirmed on my own device too).
I’ll open a GitHub issue about this. One sign that this wasn’t completely pulled through to the Electrons is that the docs still talk about WiFi although it should be Cellular for the Electron
https://docs.particle.io/reference/firmware/electron/#waiting-for-the-system

Phew. I’m not going completely mad then. I noticed the doc thing too but assumed that was an oversight.

Here is the issue I’ve just opened

1 Like

Thanks!

@RobMeades, it’s a while, but finally there was another response from Particle that pointed out something I completely missed.
waitFor() takes milliseconds, but your WAIT_FOR_CONNECTION_SECONDS in waitFor(Particle.connected, WAIT_FOR_CONNECTION_SECONDS) is only 60 instead of 60000.
Have you got any chance to retest this with that alteration?

1 Like

Aaaah, ye olde units problem. I usually work in a world that has wait() and wait_ms(), so was thinking the wrong way up about things with ‘wait’ in the title that don’t specify units. This is why I always include the units in me labels, though it didn’t help me this time. Thanks very much for noticing, I will fix…

Rob

1 Like