Hieromon / AutoConnect

An Arduino library for ESP8266/ESP32 WLAN configuration at runtime with the Web interface
https://hieromon.github.io/AutoConnect/
MIT License
908 stars 190 forks source link

AutoReconnect not works #251

Closed infiums closed 3 years ago

infiums commented 4 years ago

Cant find a reason for a following problem:

In captive portal already saved credentials for my router's AP and device works as AP_STA.

After some time it disconnects from my router and works as AP. AutoReconnect is set to true, but it doesn't connect to saved routers credentials, while AP available in "Configure new AP" with signal about 80%, and the same time this AP is shown in "Open SSID's" as unavailable.

Anybody have suggestions?

eCyber commented 4 years ago

Hello, I have the same error as you, but have not figured out the solution yet. Has anyone found it yet?

Hieromon commented 4 years ago

Open SSID uses known access points validation by BSSID instead of SSID. If the SSID is the same but the BSSID is different, it will be treated as a different AP. Do you have any idea that this can cause problems in your environment? (For example, using the WIFI signal repeater with the same SSID)

plusmartin commented 4 years ago

I have resubmitted the issue, it is not working despite all possible configurations tested. I am using a hotspot to change the wifi names and it does not work. please help. thanks

Hieromon commented 4 years ago

@plusmartin If you encounter this phenomenon, you can isolate the cause by following the steps below:

  1. Confirm AutoConnect debug log

    Turn on AC_DEBUG with AutoConnectDefs.h, and recompile it. Then You should be able to see a message like the below on the serial monitor:

    [AC] WiFi.config(IP=0.0.0.0, Gateway=0.0.0.0, Subnetmask=0.0.0.0, DNS1=0.0.0.0, DNS2=0.0.0.0)
    [AC] WiFi.begin()
    [AC] Connecting........................time out IP:0.0.0.0
    [AC] 4 network(s) found
    [AC] autoReconnect loaded:YOUR_SSID(RECENT)
    [AC] WiFi.config(IP=0.0.0.0, Gateway=0.0.0.0, Subnetmask=0.0.0.0, DNS1=0.0.0.0, DNS2=0.0.0.0)
    [AC] WiFi.begin(YOUR_SSID,YOUR_PASSWORD)
    [AC] Connecting....

    If autoReconnect is enabled, networks(s) found will be logged after the first timeout. And if the autoReconnect loaded message appears, your ESP32 is correctly capturing the most recently established SSID. But on the contrary, if you can't find the autoReconnect loaded message, the ESP32 could not find for a recent SSID as well. It means that none of the credentials stored in the recent AutoConnect Credential can be found in the BSSIDs broadcast by the ESP32's receivable WiFi radio signal. Refer to https://hieromon.github.io/AutoConnect/faq.html#still-not-stable-with-my-sketch

  2. Check the proper behavior of WiFi.begin

    If your ESP32 succeeds in loading the expected SSID but the connection fails with the secondary WiFi.begin with the loaded SSID and password, check the module's behavior with AutoConnect excepted. Compile the code below with Core Debug Level: Verbose and observe the output of the serial monitor.

    #include <Arduino.h>
    #include <WiFi.h>
    
    #define YOUR_SSID     "YOUR_SSID"      // replace it you wish
    #define YOUR_PASSWORD "YOUR_PASSWORD"  // replace it you wish
    
    void setup() {
      delay(1000);
      Serial.begin(115200);
      Serial.println();
    
      WiFi.softAPdisconnect(true);
      WiFi.mode(WIFI_STA);
      WiFi.begin(YOUR_SSID, YOUR_PASSWORD);
      unsigned long tm = millis();
      unsigned long pd = tm;
      while (millis() - tm < 30000) {
        if (WiFi.status() == WL_CONNECTED) {
          Serial.printf("Connected:%s\n", WiFi.localIP().toString().c_str());
          break;
        }
        if (millis() - pd > 1000) {
          pd = millis();
          Serial.print('.');
        }
      }
      if (millis() - tm >= 30000)
        Serial.println("Timeout\n");
      // put your setup code here, to run once:
    }
    
    void loop() {
      // put your main code here, to run repeatedly:
    }

    The log of Arduino core is as follows:

    [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 0 - WIFI_READY
    [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 2 - STA_START
    [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 5 - STA_DISCONNECTED
    ...[W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 201 - NO_AP_FOUND
    ...[W][WiFiGeneric.cpp:353] _eventCallback(): Reason: 201 - NO_AP_FOUND
    [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 4 - STA_CONNECTED
    [D][WiFiGeneric.cpp:337] _eventCallback(): Event: 7 - STA_GOT_IP
    [D][WiFiGeneric.cpp:381] _eventCallback(): STA IP: ***.***.***.***, MASK: 255.255.255.0, GW: ***.***.***.***
    Connected: ***.***.***.***

    If the timeout occurs after NO_AP_FOUND continues, the access point may not be found or its WiFi signal channel may be different.

plusmartin commented 4 years ago

Hello @Hieromon , Thank you for your reply.

  1. I added:

    include

    define AC_DEBUG

what else should I add in order for the serial output to print the status? how do I turn on AC_DEBUG? I am using VS Code with the arduino framework.

2.I tried your second point on arduino IDE and got this:

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:1 load:0x3fff0018,len:4 load:0x3fff001c,len:1100 load:0x40078000,len:10088 load:0x40080400,len:6380 entry 0x400806a4

[D][WiFiGeneric.cpp:342] _eventCallback(): Event: 0 - WIFI_READY [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 2 - STA_START [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 4 - STA_CONNECTED [D][WiFiGeneric.cpp:342] _eventCallback(): Event: 7 - STA_GOT_IP [D][WiFiGeneric.cpp:385] _eventCallback(): STA IP: 172.20.10.3, MASK: 255.255.255.240, GW: 172.20.10.1 Connected:172.20.10.3

So apparently my hotspot is working ok.

Hieromon commented 4 years ago

@plusmartin

how do I turn on AC_DEBUG?

Edit the library source below directly and comment it out. https://hieromon.github.io/AutoConnect/faq.html#3-turn-on-the-debug-log-options

https://github.com/Hieromon/AutoConnect/blob/d39545ce13c12c3e8fddef599b7325b276707ac9/src/AutoConnectDefs.h#L14

I don't know how to give the external compile flags in vscode-arduino extension without modifying the source code. Its possibility with passing the build.extra_clags but you'd have to build the project from the command line as the arduino-cli.

plusmartin commented 4 years ago

@Hieromon

I enabled AC_DEBUG,

this is what it reported: [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/hotspot-detect.html,ignored [E][WebServer.cpp:617] _handleRequest(): request handler not found [AC] Host:captive.apple.com,URI:/_ac,generated:/_ac, allocated [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/_ac/config,generated:/_ac/config, allocated [AC] Host:172.217.28.1,URI:/_ac/config,already allocated [AC] 6 network(s) found

[AC] Host:172.217.28.1,URI:/hotspot-detect.html,ignored [E][WebServer.cpp:617] _handleRequest(): request handler not found [AC] Detected application, captive.apple.com, 0.0.0.0 [AC] Host:captive.apple.com,URI:/_ac,generated:/_ac, allocated [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/_ac/open,generated:/_ac/open, allocated [AC] Host:172.217.28.1,URI:/_ac/open,already allocated [AC] A credential #0 loaded [AC] A credential #1 loaded [AC] Host:172.217.28.1,URI:/hotspot-detect.html,ignored [E][WebServer.cpp:617] _handleRequest(): request handler not found [AC] Detected application, captive.apple.com, 0.0.0.0 [AC] Host:captive.apple.com,URI:/_ac,generated:/_ac, allocated [AC] Host:172.217.28.1,URI:/_ac,already allocated [AC] Host:172.217.28.1,URI:/_ac/connect,generated:/_ac/connect, allocated [AC] Host:172.217.28.1,URI:/_ac/connect,already allocated [AC] Credential loaded:Mm(DHCP) [AC] WiFi.config(IP=0.0.0.0, Gateway=0.0.0.0, Subnetmask=0.0.0.0, DNS1=0.0.0.0, DNS2=0.0.0.0) [AC] Attempt:Mm Ch(1) [AC] Connecting............................................established IP:172.20.10.2 [AC] Mm credential saved [AC] Event<17> handler registered [AC] DNS server stopped WiFi connected: 172.20.10.2 ping: 455

[INFO]: Connected to internet. IP: 172.20.10.2, SSID: Mm, RSSI: -45pinging.. 112updatecurrentTime.. updatecurrentTime:::::: [AC] Host:172.217.28.1,URI:/hotspot-detect.html,ignored [E][WebServer.cpp:617] _handleRequest(): request handler not found [AC] Detected application, captive.apple.com, 172.20.10.2

In this case it connected successfully because I had to select it manually from the BSSID list, but it did not reconnect automatically.

My intention is to have the ESP32 connect to a wifi and stay connected forever. If the wifi changes or disappears , the ESP generates a portal so that I can provide a new wifi, however if the old wifi returns I want it to connect back to it. Therefore I am giving the portal a timeout of 60000ms and then it will try to connect to any stored wifi during 30 seconds and then create the portal again and so on. If the wifi comes back during the portal I dont know if it can connect to the wifi but in any case after the 60000ms timeout it should connect, but it doesnt. The captive portal is showing the stored wifis in the BSSID list but it does not connect to any despite that the wifi is there.

The wifi credentials are stored: image

How can I extract the list of stored wifis? maybe I can try to store them in the EEPROM manually and do a WiFi.begin(WIFI_SSID, WIFI_PASSWORD); for each...

Hieromon commented 4 years ago

@plusmartin Thank you reports.

You can dump the nvs allocated to the AutoConnect credentials as the following sketch:

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <AutoConnect.h>

Preferences pref;
struct  DumpFormat {
  char  hex[8][3];
  char  sep;
  char  asc[8];
} dumpRec;

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println();

  if (pref.begin(AC_CREDENTIAL_NVSNAME)) {
    size_t  psz = pref.getBytesLength(AC_CREDENTIAL_NVSKEY);
    Serial.printf(AC_CREDENTIAL_NVSNAME ":" AC_CREDENTIAL_NVSKEY " %d bytes allocated", psz);
    if (psz) {
      uint8_t*  prefPool = (uint8_t*)malloc(psz);
      size_t  rsz = pref.getBytes(AC_CREDENTIAL_NVSKEY, static_cast<void*>(prefPool), psz);
      Serial.printf(", %d bytes read\n", rsz);
      uint16_t  dp = 0;
      Serial.printf("Entries: %d, size: %d\n", prefPool[0], prefPool[1] + (prefPool[2] << 8));
      do {
        memset(&dumpRec, ' ', sizeof(struct DumpFormat));
        for (uint8_t ui = 0; ui < 8; ui++) {
          sprintf(dumpRec.hex[ui], "%02x", prefPool[dp]);
          dumpRec.hex[ui][2] = ' ';
          dumpRec.asc[ui] = isprint(prefPool[dp]) ? prefPool[dp] : '.';
          if (++dp >= rsz)
            break;
        }
        Serial.printf("%s\n", (char*)&dumpRec);
      } while (dp < rsz);
      free(prefPool);
    }
    pref.end();
  }
  else
    Serial.println("Preferences(" AC_CREDENTIAL_NVSNAME ") initiation failed");
}

void loop() {
}

Also, the credential data structure is documented in here.

My intention is to have the ESP32 connect to a wifi and stay connected forever. If the wifi changes or disappears , the ESP generates a portal so that I can provide a new wifi, however if the old wifi returns I want it to connect back to it.

Your requirement simular as #153, and I wish the sample I commented will help you.

Further, I designed AutoConnect to replace WiFI.begin. Since its release, I've seen many posts about WiFi connection persistence. It's similar to your request and is similar to the automatic connection to a known WiFi network that a typical cell phone's operating system has.

To achieve this, at least the following processing must be implemented:

  1. WiFi connection alive monitoring (should be done asynchronously)
  2. Scans nearby SSIDs when WiFi connection is lost and automatically tries to connect to it if it is known. (ie if it is stored in AutoConnect Credentials already)

At first glance, this seems to be possible without much of a problem. The reference case I mentioned above will be the basis for implementing asynchronous scanning at the WiFi disconnection events occurrence.

However, at this time, a sudden change in the IP address occurs by switching to another SSID. The WebServer class instance bound to the old IP address is unaware of its happening. I think it loses HTTP requests, but does it work? I'm not sure.

Hieromon commented 4 years ago

@infiums An autoReconnect is not a feature that detects WiFi disconnection and automatically tries to reconnect even while the loop function (ie. AutoConnect::handleClient) is running. It is only valid while AutoConnect::begin is running. The Arduino core, which is based on Espressif-IDF, already has the ability to continue reconnecting to the access point.

If you want to keep the WiFi connection to one of the known APs without resetting the ESP module, its functionality must be realized in Sketch's own as I mentioned above.

plusmartin commented 4 years ago

@plusmartin Thank you reports.

You can dump the nvs allocated to the AutoConnect credentials as the following sketch:

#include <Arduino.h>
#include <WiFi.h>
#include <WebServer.h>
#include <AutoConnect.h>

Preferences pref;
struct  DumpFormat {
  char  hex[8][3];
  char  sep;
  char  asc[8];
} dumpRec;

void setup() {
  delay(1000);
  Serial.begin(115200);
  Serial.println();

  if (pref.begin(AC_CREDENTIAL_NVSNAME)) {
    size_t  psz = pref.getBytesLength(AC_CREDENTIAL_NVSKEY);
    Serial.printf(AC_CREDENTIAL_NVSNAME ":" AC_CREDENTIAL_NVSKEY " %d bytes allocated", psz);
    if (psz) {
      uint8_t*  prefPool = (uint8_t*)malloc(psz);
      size_t  rsz = pref.getBytes(AC_CREDENTIAL_NVSKEY, static_cast<void*>(prefPool), psz);
      Serial.printf(", %d bytes read\n", rsz);
      uint16_t  dp = 0;
      Serial.printf("Entries: %d, size: %d\n", prefPool[0], prefPool[1] + (prefPool[2] << 8));
      do {
        memset(&dumpRec, ' ', sizeof(struct DumpFormat));
        for (uint8_t ui = 0; ui < 8; ui++) {
          sprintf(dumpRec.hex[ui], "%02x", prefPool[dp]);
          dumpRec.hex[ui][2] = ' ';
          dumpRec.asc[ui] = isprint(prefPool[dp]) ? prefPool[dp] : '.';
          if (++dp >= rsz)
            break;
        }
        Serial.printf("%s\n", (char*)&dumpRec);
      } while (dp < rsz);
      free(prefPool);
    }
    pref.end();
  }
  else
    Serial.println("Preferences(" AC_CREDENTIAL_NVSNAME ") initiation failed");
}

void loop() {
}

Also, the credential data structure is documented in here.

My intention is to have the ESP32 connect to a wifi and stay connected forever. If the wifi changes or disappears , the ESP generates a portal so that I can provide a new wifi, however if the old wifi returns I want it to connect back to it.

Your requirement simular as #153, and I wish the sample I commented will help you.

Further, I designed AutoConnect to replace WiFI.begin. Since its release, I've seen many posts about WiFi connection persistence. It's similar to your request and is similar to the automatic connection to a known WiFi network that a typical cell phone's operating system has.

To achieve this, at least the following processing must be implemented:

  1. WiFi connection alive monitoring (should be done asynchronously)
  2. Scans nearby SSIDs when WiFi connection is lost and automatically tries to connect to it if it is known. (ie if it is stored in AutoConnect Credentials already)

At first glance, this seems to be possible without much of a problem. The reference case I mentioned above will be the basis for implementing asynchronous scanning at the WiFi disconnection events occurrence.

However, at this time, a sudden change in the IP address occurs by switching to another SSID. The WebServer class instance bound to the old IP address is unaware of its happening. I think it loses HTTP requests, but does it work? I'm not sure.

Hi,

I added two wifi credentials, one is Mm1 with password: 12481632, the other is Mm2 with password 11111111. this is the result>

AC_CREDT:AC_CREDT 44 bytes allocated, 44 bytes read Entries: 2, size: 44 02 2c 00 4d 6d 31 00 31 .,.Mm1.1 32 34 38 31 36 33 32 00 2481632. 42 a6 45 88 9f 5b 00 4d B.E..[.M 6d 32 00 31 31 31 31 31 m2.11111 31 31 31 00 ae 8a 43 4d 111...CM 69 70 00 00 ip..

The credentials are there but I have no idea what the rest means or how to extract them and use them since the Autoconnect reconnect feature is not working.

here is the simplified code that I am using:

`#include

const char WIFI_SSID = "Mm"; const char WIFI_PASSWORD = "12481632";

include //updatetime

include

if defined(ARDUINO_ARCH_ESP8266)

include

include

elif defined(ARDUINO_ARCH_ESP32)

include

include

endif

include

include

//#include "helpers/OTAClient.h" //OTAClient OTA;

include //to check if there is internet, not only wifi

include //para guardar la fecha si se traba

define EEPROM_SIZE 10

byte timebackup=0;

WiFiUDP ntpUDP;

NTPClient timeClient(ntpUDP);

static const char AUX_TIMEZONE[] PROGMEM = R"( { "title": "TimeZone", "uri": "/timezone", "menu": true, "element": [ { "name": "caption", "type": "ACText", "value": "Sets the time zone to get the current local time.", "style": "font-family:Arial;font-weight:bold;text-align:center;margin-bottom:10px;color:DarkSlateBlue" }, { "name": "timezone", "type": "ACSelect", "label": "Select TZ name", "option": [], "selected": 10 }, { "name": "newline", "type": "ACElement", "value": "
" }, { "name": "start", "type": "ACSubmit", "value": "OK", "uri": "/start" } ] } )";

typedef struct { const char zone; const char ntpServer; int8_t tzoff; } Timezone_t;

static const Timezone_t TZ[] = {

{ "America/Chicago", "north-america.pool.ntp.org", -6 }, { "America/Denver", "north-america.pool.ntp.org", -7 },

};

if defined(ARDUINO_ARCH_ESP8266)

ESP8266WebServer Server;

elif defined(ARDUINO_ARCH_ESP32)

WebServer Server;

endif

AutoConnect Portal(Server); AutoConnectConfig Config; // Enable autoReconnect supported on v0.9.4 AutoConnectAux Timezone;

void rootPage() { String content = "" "" "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">" "<script type=\"text/javascript\">" "setTimeout(\"location.reload()\", 1000);" "" "" "" "<h2 align=\"center\" style=\"color:blue;margin:20px;\">Hello, world" "<h3 align=\"center\" style=\"color:gray;margin:10px;\">{{DateTime}}" "<p style=\"text-align:center;\">Reload the page to update the time.

" "

<p style=\"padding-top:15px;text-align:center\">" AUTOCONNECT_LINK(COG_24) "

" "" ""; static const char wd[7] = { "Sun","Mon","Tue","Wed","Thr","Fri","Sat" }; struct tm tm; time_t t; char dateTime[26];

t = time(NULL); tm = localtime(&t); sprintf(dateTime, "%04d/%02d/%02d(%s) %02d:%02d:%02d.", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, wd[tm->tm_wday], tm->tm_hour, tm->tm_min, tm->tm_sec); content.replace("{{DateTime}}", String(dateTime)); Server.send(200, "text/html", content); }

void startPage() { // Retrieve the value of AutoConnectElement with arg function of WebServer class. // Values are accessible with the element name. String tz = Server.arg("timezone");

for (uint8_t n = 0; n < sizeof(TZ) / sizeof(Timezone_t); n++) { String tzName = String(TZ[n].zone); if (tz.equalsIgnoreCase(tzName)) { configTime(TZ[n].tzoff * 3600, 0, TZ[n].ntpServer); Serial.println("Time zone: " + tz); Serial.println("ntp server: " + String(TZ[n].ntpServer)); break; } }

// The /start page just constitutes timezone, // it redirects to the root page without the content response. Server.sendHeader("Location", String("http://") + Server.client().localIP().toString() + String("/")); Server.send(302, "text/plain", ""); Server.client().flush(); Server.client().stop(); }

TaskHandle_t Task1; TaskHandle_t Task2;

define ledgreen 33

define ledred 32

long currentTime; long backupcurrentTime; int flagonline=0; long zeit2=0; int avg_time_ms; bool acEnable;

void APmode(){

Serial.println("AP mode"); Serial.println("Creating portal and trying to connect...");

Config.immediateStart = true; Config.autoReconnect = true; Config.hostName = "Mysensor";///////////Config.hostName = "M3TR " + String(M3TRid); Config.portalTimeout = 60000; Config.apid = "Mysensor";////////Config.apid = "M3TR " + String(M3TRid); //Config.apip = 192.168.0.1; Config.retainPortal = false;
Portal.config(Config); // Establish a connection with an autoReconnect option. bool acEnable; acEnable = Portal.begin();

if (acEnable) { Serial.println("WiFi connected: " + WiFi.localIP().toString()); Portal.handleClient(); }

if (!acEnable) { Serial.println("portal end"); delay(100); WiFi.mode(WIFI_STA); WiFi.begin(WIFI_SSID, WIFI_PASSWORD); } }// end AP mode

void connectToWiFi(int x) { // esp_task_wdt_reset(); //Serial.println("Connect to Wifi"); if (x == 1) { zeit2 = 0; x = 0; }

if (WiFi.status() == WL_CONNECTED && millis() > zeit2) { Serial.print("pinging.. "); if (Ping.ping("www.google.com", 2) == 1) //bool ret = Ping.ping("www.google.com",10); //repeticiones { avg_time_ms = Ping.averageTime(); Serial.print(avg_time_ms); zeit2 = 10000 + millis(); if (avg_time_ms > 1000) { digitalWrite(ledred, HIGH); digitalWrite(ledgreen, LOW); flagonline = 0; } else { digitalWrite(ledred, LOW); digitalWrite(ledgreen, HIGH);

    if (flagonline==0){
     // publishnow=0;//si antes estaba offline publica de una vez
    }
    flagonline = 1;
    Serial.print("updatecurrentTime.. ");
    //updatecurrentTime();
  }
}
else
{
 // disableCore0WDT();
  Serial.print("no pong");
  flagonline = 0;
  digitalWrite(ledred, HIGH);
  digitalWrite(ledgreen, LOW);
}

}

if (WiFi.status() != WL_CONNECTED) { //WiFi.mode( WIFI_MODE_NULL ); WiFi.disconnect(); delay(100); Serial.println("no wifi "); digitalWrite(ledred, HIGH); digitalWrite(ledgreen, LOW); flagonline = 0; Serial.print("[INFO]: Start setup to internet connection "); //WiFi.mode(WIFI_STA); WiFi.setHostname("M3TR"); WiFi.mode(WIFI_STA);

WiFi.begin();
//WiFi.begin(WIFI_SSID, WIFI_PASSWORD);

// Try 30 times to connect to WiFi
int retries = 5;
while (WiFi.status() != WL_CONNECTED && retries > 1)
{
  Serial.print("wifi reconnecting...");

  //WiFi.setAutoReconnect(true);
  //WiFi.persistent(true);
  //WiFi.begin();
  WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
  //esp_task_wdt_reset();
  WiFi.reconnect();
  delay(1000);
  Serial.print(retries);
  retries--;
 // giveup--;
 // if(giveup==0){
  //  esp_restart();
 // }
}

if (WiFi.status() != WL_CONNECTED)
{
  flagonline=0;
  Serial.println("[ERROR]: Could not connect to WiFi");
  APmode();
}

if (WiFi.status() == WL_CONNECTED)
{
  //giveup=20;
  ///////////WiFi.setAutoReconnect(true);
  /////////////WiFi.persistent(true);
  // bool ret = Ping.ping("www.google.com", 10);
  //float avg_time_ms = Ping.averageTime();
  if (avg_time_ms < 1000)
  {
    Serial.print("ping: ");Serial.println(avg_time_ms);
    digitalWrite(ledred, LOW);
    digitalWrite(ledgreen, HIGH);
    Serial.println();
    Serial.print("[INFO]: Connected to internet. IP: ");
    Serial.print(WiFi.localIP());
    Serial.print(", SSID: ");
    Serial.print(WiFi.SSID());
    Serial.print(", RSSI: ");
    Serial.print(WiFi.RSSI());

    flagonline = 1;
  }
}

} }//end connectToWifi

void Task2code( void * pvParameters ){ Serial.print("Task2 running on core "); Serial.println(xPortGetCoreID()); delay(3000); Serial.println("Configuring WDT core 1..."); //esp_task_wdt_init(3, true); //enable panic so ESP32 restarts //esp_task_wdt_add(NULL); //add current thread to WDT watch //esp_task_wdt_reset(); for(;;){ // Serial.println("----------core 1-----------"); // vbatcheck(); // zeit=millis(); //timer para guardar dato o publicar // flowread(); // empaquetador(); // buttoncheck(); //////esp_task_wdt_reset(); } }

void setup() ///////////////// SETUP /////////////////// {

Serial.begin(9600); delay(1000); Serial.print("\n\n"); Serial.println("Bienvenido a M3TR!");

EEPROM.begin(EEPROM_SIZE);

delay(100); Serial.println("-----------SETUP-----------");

//create a task that will be executed in the Task2code() function, with priority 1 and executed on core 1 Serial.println("Configuring Task2Core..."); xTaskCreatePinnedToCore( Task2code, / Task function. / "Task2", / name of task. / 10000, / Stack size of task / NULL, / parameter of the task / 1, / priority of the task / &Task2, / Task handle to keep track of created task / 1); / pin task to core 1 / delay(500);

Serial.println("wifi begin setup");

connectToWiFi(1);

Serial.println("Configurando timeClient..."); timeClient.begin(); timeClient.setTimeOffset(0); timeClient.update(); Serial.print(timeClient.getEpochTime()); } //end setup

void loop() { //Serial.print("."); connectToWiFi(0); if (flagonline == 1) { // looppublisher(); } delay(300); Portal.handleClient(); } //end loop `

plusmartin commented 4 years ago

I just want the ESP32 to automatically connect to any of the stored credentials.

If I reboot the ESP32 it must scan the SSID available and look for that SSID in the stored credentials. I thought that autoconnect did this automatically, how do I enable this?

I have Config.autoReconnect = true; but it does not work. The SSID appears in the stored wifi list but it wont try to connect unless I click on the name manually, and I want it to do it automatically.

thank you

plusmartin commented 4 years ago

Also, the Config.retainPortal = false; does not seem to work. When I enter the portal and provide a new credential (or connect to the previous one), teh ESP connects to the wifi but the AP stays there and wont turn off. Why? This is my AP code that I use when the ESP cannot connect to the default wifi:

`void APmode(){

Serial.println("AP mode"); Serial.println("Creating portal and trying to connect...");

Config.immediateStart = true; Config.autoReconnect = true; Config.hostName = "mysensor" + String(sensorid); Config.portalTimeout = 60000; Config.apid = "mysensor " + String(sensorid); Config.retainPortal = false;
Portal.config(Config);

// Establish a connection with an autoReconnect option. bool acEnable; acEnable = Portal.begin();

if (acEnable) { Serial.println("WiFi connected: " + WiFi.localIP().toString()); Portal.handleClient(); }

if (!acEnable) { Serial.println("portal end"); delay(100); WiFi.reconnect(); } }// end AP mode `

Hieromon commented 4 years ago

AutoConnectConfig::autoReconnect works correctly within the specifications. Whether it works as you expect. (Matches the known access point by BSSID, not SSID) If you can reconnect to the AP using the sketch below in your environment, autoReconnect is working fine. The phenomenon you mentioned involves a sequence of WiFi handling that your sketch contains, other than the below Sketch.

AutoConnect portal;
AutoConnectConfig config;

void setup() {
  config.autoReconnect = true;
  portal.config(config)
  portal.begin();
}

void loop() {
  portal.handleClient();
}

Note:

If you want to keep the ESP32 AP always and reconnect to the previous automatically, try the v120 branch as RC of the next release. AutoConnectConfig::reconnectInterval as a new option specifies the interval in units of time to attempt auto-reconnect when WiFi disconnects. (1 unit default is 30 seconds).

AutoConnectConfig config;
...
config.retainPortal = true;
config.autoReconnect = true;
config.reconnectInterval = 1; // WiFi network scan interval is 30[s]
...
WiFi.disconnect(false);
portal.config(config);
portal.begin();
...
portal.handleClient();

Also, to change the key to determine which is a known access point by SSID, uncomment //#define AUTOCONNECT_APKEY_SSID in AutoConnectDefs.h. (To achieve, you need to edit the library source directly unless you use a build system such as the PlatformIO that can pass macro definitions from outside.)

However, if you choose to search for known access points by SSID, you will not be able to automatically reconnect to the hidden SSID.

Commit: https://github.com/Hieromon/AutoConnect/commit/093bb22f34b2271b34622903820b7c8328dc4acc

plusmartin commented 4 years ago

Thank you, I am using PlatformIO, I opened AutoConnectDefs.h but I could not find //#define AUTOCONNECT_APKEY_SSID

I removed immediateStart but it still does not autoreconnect to BSSIDs.

My goal is very simple:

  1. If wifi is available and it matches any of the given SSIDs or BSSIDs connect to it.
  2. If there is no know wifi available for 30 seconds, then launch AP (captive portal)
  3. User will connect to the portal to provide the new credentials.
  4. Once connected, store the new credential and close the portal (turn off AP mode) and connect to the new wifi same as step1.
  5. If user did not connect to the portal, close the portal after 60 seconds and start over from step1.

This is my method so that the ESP keeps searching for known wifis but also let the user provide a new in case it changed. 30 seconds looking for wifis and 60 seconds at captive portal, 30, 60, 30, 60, etc.

However, if you choose to search for known access points by SSID, you will not be able to automatically reconnect to the hidden SSID.

How can I connect to the stored wifis if I reset the ESP?

Hieromon commented 4 years ago

I opened AutoConnectDefs.h but I could not find //#define AUTOCONNECT_APKEY_SSID

As mentioned, Try the enhance/v120 branch as RC of the next release.

My goal is very simple:

  1. If wifi is available and it matches any of the given SSIDs or BSSIDs connect to it.
  2. If there is no know wifi available for 30 seconds, then launch AP (captive portal)
  3. User will connect to the portal to provide the new credentials.
  4. Once connected, store the new credential and close the portal (turn off AP mode) and connect to the new wifi same as step1.
  5. If user did not connect to the portal, close the portal after 60 seconds and start over from step1.

This request is ambiguous. Which function block in the Arduino framework do you want to achieve that behavior? setup() or loop()?

So, I can't quite understand your requirements (it's ambiguous, as I mentioned above), but I think the following Sketch will help you. Note that you need v.1.20 RC staged on enhance/v120 branch to evaluate it.

...

AutoConnect       portal;
AutoConnectConfig config;

bool behindCP() {
 // Here, it should be executed process even in the captive portal loop.
 // Returning false will force the captive portal loop to terminate.
 return true;
}

void setup() {
  config.autoReset = false; // It's no need if you do not allow disconnect from the AutoConnect menu.
  config.autoReconnect = true;
  config.portalTimeout = 60000;
  portal.config(config);
  portal.whileCaptivePortal(behindCP);
}

void loop() {
  if (WiFi.status() != WL_CONNECTED)
    portal.begin();

  if (WiFi.status() == WL_CONNECTED) {
    // Here to do when WiFi is connected.
  }
  else {
    // Here to do when WiFi is not connected.
  }

  portal.handleClient();
}
plusmartin commented 3 years ago

I found the problem... the ESP32 will NOT connect to any stored SSID after portal generates the AP wifi.

I used your code in the your last reply, only without the portal.whileCaptivePortal(behindCP); To replicate the error simply connect the ESP32 to a wifi, then turn off the wifi and wait... After 22 seconds the ESP realizes that the wifi is gone and runs portal begin. If I turn the wifi on now it will reconnect, but if I wait about 30 more seconds the AP "esp32ap" will appear and then It wont connect to the wifi again, not with reset nor power down, nothing.

This is why I want the config.portalTimeout = 60000; to stop the portal and try to connect to any wifi again, but it wont.

wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
wifi ok
portal begin
[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
portal begin
[E][WiFiSTA.cpp:219] begin(): connect failed!

after a while it started printing over and over:


[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
[E][WiFiUdp.cpp:219] parsePacket(): could not receive data: 9
...
...

The only way to connect to a SSID is to connect to the "esp32ap" wifi and click on the stored SSID tab and manually select the BSSID. Then it can connect back even after power down or RESET , however, if the wifi is removed for longer and the captive portal starts then it wont reconnect never again .

This is the problem: Autoconnect should connect to any stored SSID at startup or reset and it wont do it unless I do it manually. So if the wifi disappears for long time it will ignore it and never reconnect even if the wifi returns.

Hieromon commented 3 years ago

Your phenomenon does not reproduce in my environment. Also, the error you presented is related to the DNS server and has been fixed in the latest commit. Which commit hash are you using?

I'll present you the AutoConnect specs here. (These are described in the AutoConnect documentation) This specification may not match your requirements. It is your sketch's job to fill that gap.

  1. SoftAP does not stop automatically once you start the captive portal with AutoConnect::begin.
  2. If you want to stop SoftAP after AutoConnect::begin exiting with WL_CONNECTED, you need stop it using WiFi.enableAP of ESP32 arduino core API expressly.
  3. Since v1.2.0, AutoConnectConfig::autoReconnect will start SoftAP again with AutoConnect::handleClient loop if it has been shutted down.

I have already tested the above behaviors.

Hieromon commented 3 years ago

Merged #280