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
thanks @ScruffR
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