I looked up WiFi.scan() and if I understood correctly it will only list the wifis but not connect to them. Id have to list them and compare each to the ones I have stored in my credentials, correct?
My idea is to WiFi.scan() and then for each wifi found do a getCredentials() and compare them. If there is a match then attempt to connect.
If I let it run to the end of loop it will blink green and “freeze” for a few seconds until it gives up, so I have to prevent this from happening. If no wifis found and I reach the end of the loop should I turn WiFi.off() and then back on once the loop started over?
Im not sure if all this is too complicated and there is a simpler way that lets me:
keep the device responsive and sensing for as long as possible
if wifi goes away, keep sensing and look for wifis (this is where the thread enable was handy, now I have to do it sequentially, right?)
wifi scan takes only about 1 or 2 seconds, that is ok, but trying to connect takes about 20 or 30 seconds, this is not ok.
once wifi is back, simply connect and upload the backed up messages.
Below is a code I intend to run if Particle.disconnected(), which I briefly check every second after reading my sensors.
The problem is that I dont know how to compare the sanned wifis with my credentials:
void wificheck(){
Serial.println("wificheck()");
flagwifi=1; //to be used in other routines and prevent from being called too often
if (!WiFi.ready())
{ //if no wifi, then scan every minute or (x minutes) and compare to credentials, if match found connect
WiFi.disconnect();
Serial.print("No wifi ");
WiFiAccessPoint aps[20];
int found = WiFi.scan(aps, 20); //list available wifis
for (int i=0; i<found; i++) { //for each found, check if it is known and connect
WiFiAccessPoint& ap = aps[i]; //no idea what this is
Serial.print("SSID found: ");
Serial.println(ap.ssid); //this is taken from https://docs.particle.io/reference/device-os/firmware/photon/#scan-)
//// get credentials and compare them /////
// WiFiAccessPoint ap[5]; //list all credentials and compare to the current ssid found
// int creds = WiFi.getCredentials(ap, 5);
// for (int j = 0; j < creds; j++) {
// Serial.print("ssid: ");
//>>>this does not work if(ap.ssid==ap[j].ssid){Serial.print(" and it is known! Connecting...");
// WiFi.connect();
// }
// else
// {
// Serial.println(" not known");
// }
//}
}
}
if (WiFi.ready()){
Particle.connect();
if (Particle.connected()) {Particle.process();flagwifi=0;}
}
}
Uhm, no! You can do a WiFi.getCredentials() and WiFi.scan()once and then compare each found entry in one list with each found entry in the other list - WiFi.getCredentials() will only give you a list of up to 5 credentials on a Photon, the five SSIDs for that can easily be remembered in a local array for all networks the scan will return.
And only try to connect when you found a match. If not, I'd call WiFi.off().
C/C++ strings (aka char arrays) cannot be compared via the == equality check. You should rather use strcmp().
BTW, I'd use the callback version of WiFi.scan() in case you find yourself in a crowded area with an unknown number of possible networks around you. For that you can keep your stored WiFi credentials in a global array (or local to the calling function an passing in via the void* data parameter).
I have successfully implemented a Wifi checking code that does not block my code without the need for thread enable. =)
void getcreds(){
WiFiAccessPoint ap[5];
int found = WiFi.getCredentials(ap, 5);
for (int i = 0; i < found; i++) {
Serial.println("wifi credentials: ");
Serial.print(i);Serial.print(". ");
Serial.println(ap[i].ssid);
cred[i]=String(ap[i].ssid);
}
}
void wificheck(){
Serial.print("wificheck...");
//Serial.println("wifi ON");
WiFi.on();
if (Particle.connected())
{
Particle.process();
if(flagwifi==2) //this is for publishing backups asap
{
publishnow=0; Serial.println(" force publish now");
flagwifi=0;
}
}
else
{
flagwifi=1;
Serial.println("Scanning wifis...");
WiFiAccessPoint aps[20];
int found = WiFi.scan(aps, 20); //list available wifis
for (int i=0; i<found; i++) { //for each found, check if it is known and connect
WiFiAccessPoint& ap = aps[i]; //no idea what this is
Serial.print("SSID ");Serial.print(i);Serial.print(": ");
Serial.println(ap.ssid); //this is taken from https://docs.particle.io/reference/device-os/firmware/photon/#scan-)
for(int j=0;j<5;j++){
if(cred[i].equals(String(ap.ssid))) //from https://community.particle.io/t/how-to-compare-string-with-char/3929
{
Serial.println (" ^ match!! connecting...");
j=5;
i=found;
WiFi.connect();
Particle.connect();
publishnow=0; flagwifi=2;
}
}
}
}//end if !wifi.ready
if (WiFi.ready()){
Particle.connect();//Serial.println("particle connect");
if (Particle.connected()) {Particle.process();Serial.println("System online");flagwifi=0;}
}
else
{
WiFi.off();
}
}//end wificheck
The next step is to optimize the backup section so that it consumes less memory and makes the use of softAP more reliable.
This is what I have now:
#define ARRAYSIZE 200
String backup[ARRAYSIZE];
String payload;
void onlinecheck()
{
if (Particle.connected()) { //if internet, send backups every delay until finished
Particle.process();
Serial.println("INTERNET OK!!");
digitalWrite(ledred,LOW);
digitalWrite(ledgreen,HIGH); //green
counterstatus++;
if (counterstatus>9999){counterstatus=0;}
unsigned int intcounterstatus=counterstatus;
counterstatus=intcounterstatus;
if(backupcounter>0){
for(int o=0;o<ARRAYSIZE;o++){
if(backup[o] != "x"){ //previously the entire array was set to "x"
delay(200);
String id = System.deviceID();
Particle.publish(String(id.c_str()), backup[o] , PRIVATE);
Serial.println("");Serial.print("backup: ");Serial.print(o);Serial.print(" sent! Remaining: "); Serial.print(backupcounter-1); //sorry for bad style, will fix it later
freemem = System.freeMemory();
Serial.print(" free memory: "); //checking ram
Serial.println(freemem);
Serial.println(backup[o]);
backup[o]="x";
Particle.process();
backupcounter--;
delay(200); //is it too fast to send backups every 400ms?
}
}
}
}
else { //if no internet store backup
Serial.println("");
Serial.println("NO INTERNET!!");
updatecurrentTime(); //get time in epoch format
counterstatus++;
if (counterstatus>9999){counterstatus=0;}
unsigned int intcounterstatus=counterstatus;
counterstatus=intcounterstatus+0.1;
for(int o=0;o<=ARRAYSIZE-1;o++){
if(backup[o]=="x")
{
String id = System.deviceID();
payload = String::format( "{\"Timestamp_Device\":\"" + String(currentTime) + "\",\"device_id\":\"" + String(id.c_str()) + "\",\"temp\":\"" + String(flowtemp1) + "\",\"flowshort\":\"" + String(flowtotal) + "\",\"flowacum\":\"" + String(flowacum) + "\",\"vbat\":\"" + String(vbat) + "\",\"counterstatus\":\"" + String(counterstatus)+"\"}");
backup[o] = payload;
backup[o+1]="x";
Serial.print("backup: ");Serial.print(o);Serial.print(" saved: ");
Serial.print(backup[o]); Serial.println(" ");
if(o==ARRAYSIZE-3){ //if array full, delete it. this should only replace first entry and so on
cleanbackup(); //this sets the entire array to "x"
backupcounter=0;
}
else { o=ARRAYSIZE+1; }
backupcounter++;
freemem = System.freeMemory();
Serial.print("free memory: ");
Serial.println(freemem);
}
}
}//end else
}//end onlinecheck
So I want to implement your recommendations from: Photon working both online and offline but the coding level is a bit too advanced for me, so I will try it but I will most probably get stuck. Any recommendations on how to proceed? The idea is to have as many backups available as possible without risking the stability of the system.
thanks