This has been solved by adding WiFi.on() and a check to ensure Particle.connect() is only called once when the Wifi is ready.This has been tested for about 3 days.
#include "application.h"
SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);
#define CLOUD_CONNECTION_TIMEOUT 30000
#define CLOUD_CONNECTION_INTERVAL 60000
long _startedConnecting = 0;
bool _particleConnecting = false;
long _lastConnectionTime = -CLOUD_CONNECTION_INTERVAL; //Causes code to run on startup, otherwise we would need to wait 60 secs before a connection
void setup()
{
Serial.begin(115200);
}
void loop()
{
if(abs(millis() - _lastConnectionTime) > CLOUD_CONNECTION_INTERVAL)
{
bool timedOut = connect();
if(timedOut == false)
{
Serial.printf("Connecting FAILED\r\n");
_lastConnectionTime = millis();
//Do some offline stuff i.e. save data I was trying to send to EEPROM
}
if(Particle.connected())
{
Serial.printf("Connecting SUCCESS\r\n");
_lastConnectionTime = millis();
//Do some online stuff i.e. send data
disconnect();
}
}
//Do lots of other stuff that cannot be blocked whilst connecting/disconnecting
}
bool connect()
{
if(_startedConnecting == 0) //Not already connecting
{
Serial.printf("Enabling WIFI\r\n");
WiFi.on();
WiFi.connect();
_startedConnecting = millis();
return true;
}
else if(WiFi.ready() && !_particleConnecting)
{
Serial.printf("Connecting to Particle cloud\r\n");
Particle.connect();
_particleConnecting = true;
}
else if((millis() - _startedConnecting) >= CLOUD_CONNECTION_TIMEOUT) //Already connecting - check for time out
{
Serial.printf("Connecting timed out\r\n");
disconnect();
return false;
}
else return true;
}
void disconnect()
{
Serial.printf("Disconnecting\r\n");
Particle.disconnect();
WiFi.disconnect();
WiFi.off();
_startedConnecting = 0;
_particleConnecting = false;
}