Fastest way to test if particle.connect() is necessary

Use case:
A Photon is used to report data from a sensor but the Photon moves in and out of wifi connectivity. The requirement is to automatically re-connect when the photon comes back into range. Note that the Photon is also displaying sensor data to an LCD when offline, hence need to minimize blocking (see below).

Question:
At the moment I test for particle.connected() and a delay based on failed attempts to send data which works reasonably well (although I will probably make this time based) but I want to minimise the blocking from attempting to re-connect when there is no wifi available. I understand that particle.connect() takes approx 30 seconds, so was looking for some clever idea about how to quickly determine whether the last connected wifi network is available before performing particle.connect(). My idea at is to use wifi.scan() and see if the last connected SSID is present but was wondering whether this would save much time as I assume that this is possibly what is taking a good portion of the time in particle.connect().

I am using the following code (note have not pasted full code as it runs to +1000 lines

SYSTEM_MODE(SEMI_AUTOMATIC);
SYSTEM_THREAD(ENABLED);

void setup() {
  if (Particle.connected())
  {
    Particle.process();
  } 
  // ''''''
} 

void loop() {
  if (!Particle.connected()  && ((wifiOff % 6) == 0)) Particle.connect();  // See note
  if (Particle.connected())
  {
    Particle.process();
  } 
  // .....
}

Thanks in advance
John

I don’t claim for this to be the best practices on the subject, but I played around with this code, moving stuff around and turning off the Wi-Fi or Internet and I found that this combination of things doesn’t hold up the loop for more than 100 milliseconds. Well, maybe even less than that, but that’s all I measured down to.

For example, if you call Particle.connect() you can call Particle.variable() immediately and it works even if Wi-Fi is not yet connected, but if it’s not available, it takes 6 to 10 seconds to do both. If you wait until Particle.connected() before calling Particle.variable(), everything works immediately.

SYSTEM_MODE(MANUAL);
SYSTEM_THREAD(ENABLED);

const unsigned long loopWarnMs = 100;
const unsigned long connectFailMs = 60000;
const unsigned long sendIntervalMs = 15000;

UDP udp;
IPAddress remoteIP(192,168,2,4);
int remotePort = 7123;
const size_t bufferSize = 512;
unsigned char buffer[bufferSize];
unsigned char startValue = 0;
int cloudVal = 0;

enum State { CHECK_CONNECT, CONNECT_WAIT, CONNECTED };
State state;
unsigned long lastTime;
unsigned long lastLoop;


void setup() {
    Serial.begin(9600);
}

void loop() {
    unsigned long now = millis();

    if ((now - lastLoop) >= loopWarnMs) {
        Serial.printlnf("between loop time %lu", now - lastLoop);
    }

    switch(state) {
        case CHECK_CONNECT:
            if (!Particle.connected()) {
                Serial.println("Doing Particle.connect()");
                Particle.connect();

                state = CONNECT_WAIT;
                lastTime = now;
            }
            else {
                Serial.println("already connected");
                state = CONNECTED;
                lastTime = now;
            }
            break;

        case CONNECT_WAIT:
            if (Particle.connected()) {
                Serial.println("Registering variables");
                int varRes = Particle.variable("val", cloudVal);
                Serial.printlnf("Particle.variable returned %d", varRes);

                Serial.println("Connected");
                udp.begin(0);
                state = CONNECTED;
                lastTime = now;
            }
            else
            if ((now - lastTime) >= connectFailMs) {
                Serial.println("Connection failed, will retry");
                state = CHECK_CONNECT;
            }
            break;

        case CONNECTED:
            if ((now - lastTime) >= sendIntervalMs) {
                lastTime = now;
                if (!Particle.connected()) {
                    Serial.println("disconnected");
                    state = CHECK_CONNECT;
                }
                else {
                    // Already connected
                    unsigned char value = startValue++;
                    cloudVal = (int)startValue;

                    for(int ii = 0; ii < bufferSize; ii++) {
                        buffer[ii] = value++;
                    }
                    int result = udp.sendPacket(buffer, bufferSize, remoteIP, remotePort);
                    if (result == bufferSize) {
                        Serial.printlnf("sent %d", (int)buffer[0]);
                    }
                    else {
                        Serial.printlnf("error %d", result);
                        udp.begin(0);
                    }
                }
            }
            break;

    }


    Particle.process();

    if ((millis() - now) >= loopWarnMs) {
        Serial.printlnf("inside loop time %lu", millis() - now);
    }
    lastLoop = millis();
}

@rickkas7 interesting, many thanks for this. Will make some changes based on your code. Thanks again.

Per docs Particle.connect

After you call Particle.connect(), your loop will not be called again until the device finishes connecting to the Cloud. Typically, you can expect a delay of approximately one second.

Can someone comment what happens if there is no valid SSID in the vicinity - does it block for approx 30 seconds - see comment re wifi.connect here starting-spark-core-without-wifi-solved?

Many thanks
John

I believe that comment applies to SEMI_AUTOMATIC mode only. I have the test Photon associated with only one SSID and I turned the access point off. In MANUAL mode Particle.connect() returns in less than 100 milliseconds in all cases.

@rickkas7 :smiley: thanks for that - also just realised that I am using SYSTEM_MODE(SEMI_AUTOMATIC) and you are using MANUAL.