Giter Club home page Giter Club logo

khoih-prog / espasync_wifimanager Goto Github PK

View Code? Open in Web Editor NEW
289.0 20.0 73.0 2.68 MB

This is an ESP32 (including ESP32-S2 and ESP32-C3) / ESP8266 WiFi Connection Manager, using ESPAsyncWebServer, with fallback web configuration portal. Use this library for configuring ESP32, ESP8266 modules' WiFi, etc. Credentials at runtime. You can also specify static DNS servers, personalized HostName, fixed or random AP WiFi channel. With examples supporting ArduinoJson 6.0.0+ as well as 5.13.5- . Using AsyncDNSServer instead of DNSServer now.

License: MIT License

C++ 68.85% C 30.50% Shell 0.64%
espasync-wifimanager esp-wifimanager wifi config-portal async esp8266 esp32 staticip hostname wifi-credentials

espasync_wifimanager's Introduction

ESPAsync_WiFiManager Library

arduino-library-badge GitHub release GitHub contributions welcome GitHub issues

Donate to my libraries using BuyMeACoffee



Table of Contents



Important Breaking Change from v1.10.0

For v1.14.0 and up

ESP32 chipID is now correct and unique. The previous releases' 32-bit wrong chipID is mainly the 24-bit Organizational Unique Identifier (OUI) plus 8 bits from the correct chipID. That's why ESP_getChipId() function can return duplicated values if the boards are from the same batch.

For example

Chip_ID_64 : 0x98F4AB085288
chipOUI    : 0x98F4AB
chipId     : 0x85288
getEfuseMac: 0x885208ABF498

For v1.11.0 and up

Please have a look at HOWTO Fix Multiple Definitions Linker Error

From v1.11.0, you just use

#include <ESPAsync_WiFiManager.h>               //https://github.com/khoih-prog/ESPAsync_WiFiManager

instead of both

#include <ESPAsync_WiFiManager.h>               //https://github.com/khoih-prog/ESPAsync_WiFiManager

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <ESPAsync_WiFiManager-Impl.h>          //https://github.com/khoih-prog/ESPAsync_WiFiManager

For complex project having Multiple Definitions Linker Error issue, you can use in many files (Be careful: .hpp, not .h)

#include <ESPAsync_WiFiManager.hpp>             //https://github.com/khoih-prog/ESPAsync_WiFiManager

but only in main(), .ino with setup() to avoid Multiple Definitions Linker Error

#include <ESPAsync_WiFiManager.h>               //https://github.com/khoih-prog/ESPAsync_WiFiManager

For v1.10.0 only

It's advisable to use v1.11.0+

Please have a look at HOWTO Fix Multiple Definitions Linker Error

From v1.10.0, you must use

#include <ESPAsync_WiFiManager.h>               //https://github.com/khoih-prog/ESPAsync_WiFiManager

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <ESPAsync_WiFiManager-Impl.h>          //https://github.com/khoih-prog/ESPAsync_WiFiManager

instead of only

#include <ESPAsync_WiFiManager.h>               //https://github.com/khoih-prog/ESPAsync_WiFiManager


Why do we need this Async ESPAsync_WiFiManager library

Features

This is an ESP32 / ESP8266 WiFi Connection Manager with fallback Web ConfigPortal. This Library is used for configuring ESP32, ESP8266 modules' (WiFi / Dynamic) Credentials at runtime. You can also specify static DNS servers, personalized HostName, fixed or random AP channel. Now with CORS feature.

This library is based on, modified, bug-fixed and improved from:

  1. Tzapu's WiFiManager
  2. Ken Taylor's WiFiManager
  3. Alan Steremberg's ESPAsyncWiFiManager
  4. Khoi Hoang's ESP_WiFiManager

to use the better and faster asynchronous ESPAsyncWebServer instead of (ESP8266)WebServer.

Thanks to this ESPAsync_WiFiManager library is based on and sync'ed with ESP_WiFiManager, all the features currently supported by ESP_WiFiManager will be available. Please have a look at ESP_WiFiManager for those too-many-to-list features.

Why Async is better

  • Using asynchronous network means that you can handle more than one connection at the same time
  • You are called once the request is ready and parsed
  • When you send the response, you are immediately ready to handle other connections while the server is taking care of sending the response in the background
  • Speed is OMG
  • Easy to use API, HTTP Basic and Digest MD5 Authentication (default), ChunkedResponse
  • Easily extensible to handle any type of content
  • Supports Continue 100
  • Async WebSocket plugin offering different locations without extra servers or ports
  • Async EventSource (Server-Sent Events) plugin to send events to the browser
  • URL Rewrite plugin for conditional and permanent url rewrites
  • ServeStatic plugin that supports cache, Last-Modified, default index and more
  • Simple template processing engine to handle templates

To appreciate the power of the ESPAsyncWebServer and underlying Async libraries, please compare the more efficient Async_ESP32_FSWebServer example example with the complicated twin ESP32_FSWebServer.

Currently supported Boards

This ESPAsync_WiFiManager library currently supports these following boards:

  1. ESP8266 and ESP32-based boards using EEPROM, SPIFFS or LittleFS.
  2. ESP32-S2 (ESP32-S2 Saola, AI-Thinker ESP-12K, etc.) using EEPROM, SPIFFS or LittleFS.
  3. ESP32-C3 (ARDUINO_ESP32C3_DEV) using EEPROM, SPIFFS or LittleFS.
  4. ESP32-S3 (ESP32S3_DEV, ESP32_S3_BOX, UM TINYS3, UM PROS3, UM FEATHERS3, etc.) using EEPROM, SPIFFS or LittleFS.


Prerequisites

  1. Arduino IDE 1.8.19+ for Arduino. GitHub release
  2. ESP8266 Core 3.0.2+ for ESP8266-based boards. Latest release
  3. ESP32 Core 2.0.5+ for ESP32-based boards. Latest release
  4. ESPAsyncWebServer v1.2.3+ for all ESP32/ESP8266-based boards. You have to use the latest KH_Forked ESPAsyncWebServer if the PR Fix compiler error for ESP32-C3 and mbed TLS v2.7.0+ #970 hasn't been merged. To install manually for Arduino IDE
  5. ESPAsyncDNSServer v1.0.0+ or KH_Forked ESPAsyncDNSServer v1.0.0+ for all ESP32/ESP8266-based boards.
  6. ESPAsyncTCP v1.2.2+ for ESP8266-based boards. To install manually for Arduino IDE
  7. AsyncTCP v1.1.1+ for ESP32-based boards. To install manually for Arduino IDE
  8. ESP_DoubleResetDetector v1.3.2+ if using DRD feature. To install, check arduino-library-badge. Use v1.1.0+ if using LittleFS for ESP32 v1.0.6+.
  9. LittleFS_esp32 v1.0.6+ for ESP32-based boards using LittleFS with ESP32 core v1.0.5-. To install, check arduino-library-badge. Notice: This LittleFS_esp32 library has been integrated to Arduino ESP32 core v1.0.6+ and you don't need to install it if using ESP32 core v1.0.6+


Installation

Use Arduino Library Manager

The best and easiest way is to use Arduino Library Manager. Search for ESPAsync_WiFiManager, then select / install the latest version. You can also use this link arduino-library-badge for more detailed instructions.

Manual Install

  1. Navigate to ESPAsync_WiFiManager page.
  2. Download the latest release ESPAsync_WiFiManager-master.zip.
  3. Extract the zip file to ESPAsync_WiFiManager-master directory
  4. Copy the whole ESPAsync_WiFiManager-master folder to Arduino libraries' directory such as ~/Arduino/libraries/.

VS Code & PlatformIO:

  1. Install VS Code
  2. Install PlatformIO
  3. Install ESPAsync_WiFiManager library by using Library Manager. Search for ESPAsync_WiFiManager in Platform.io Author's Libraries
  4. Use included platformio.ini file from examples to ensure that all dependent libraries will installed automatically. Please visit documentation for the other options and examples at Project Configuration File


Libraries' Patches

1. For ESPAsyncWebServer library

If you don't use the Forked ESPAsyncWebServer, to fix ESPAsyncWebServer library compile errors, just copy these following files into the ESPAsyncWebServer library directory to overwrite the old files:

Check the PR Fix compiler error for ESP32-C3 and mbed TLS v2.7.0+ #970



Note for Platform IO using ESP32 LittleFS

Necessary only for esp32 core v1.0.6-

From esp32 core v1.0.6+, LittleFS_esp32 v1.0.6 has been included and this step is not necessary anymore.

In Platform IO, to fix the error when using LittleFS_esp32 v1.0 for ESP32-based boards with ESP32 core v1.0.4- (ESP-IDF v3.2-), uncomment the following line

from

//#define CONFIG_LITTLEFS_FOR_IDF_3_2   /* For old IDF - like in release 1.0.4 */

to

#define CONFIG_LITTLEFS_FOR_IDF_3_2   /* For old IDF - like in release 1.0.4 */

It's advisable to use the latest LittleFS_esp32 v1.0.6+ to avoid the issue.

Thanks to Roshan to report the issue in Error esp_littlefs.c 'utime_p'



HOWTO Fix Multiple Definitions Linker Error

The current library implementation, using xyz-Impl.h instead of standard xyz.cpp, possibly creates certain Multiple Definitions Linker error in certain use cases.

You can use

#include <ESPAsync_WiFiManager.hpp>               //https://github.com/khoih-prog/ESPAsync_WiFiManager

in many files. But be sure to use the following #include <ESPAsync_WiFiManager.h> in just 1 .h, .cpp or .ino file, which must not be included in any other file, to avoid Multiple Definitions Linker Error

// To be included only in main(), .ino with setup() to avoid `Multiple Definitions` Linker Error
#include <ESPAsync_WiFiManager.h>          //https://github.com/khoih-prog/ESPAsync_WiFiManager

Check Async_ConfigOnDoubleReset_Multi for an example how and where to do so.

Have a look at the discussion in Different behaviour using the src_cpp or src_h lib #80



HOWTO Use analogRead() with ESP32 running WiFi and/or BlueTooth (BT/BLE)

Please have a look at ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example to have more detailed description and solution of the issue.

1. ESP32 has 2 ADCs, named ADC1 and ADC2

2. ESP32 ADCs functions

  • ADC1 controls ADC function for pins GPIO32-GPIO39
  • ADC2 controls ADC function for pins GPIO0, 2, 4, 12-15, 25-27

3.. ESP32 WiFi uses ADC2 for WiFi functions

Look in file adc_common.c

In ADC2, there're two locks used for different cases:

  1. lock shared with app and Wi-Fi: ESP32: When Wi-Fi using the ADC2, we assume it will never stop, so app checks the lock and returns immediately if failed. ESP32S2: The controller's control over the ADC is determined by the arbiter. There is no need to control by lock.

  2. lock shared between tasks: when several tasks sharing the ADC2, we want to guarantee all the requests will be handled. Since conversions are short (about 31us), app returns the lock very soon, we use a spinlock to stand there waiting to do conversions one by one.

adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.

  • In order to use ADC2 for other functions, we have to acquire complicated firmware locks and very difficult to do
  • So, it's not advisable to use ADC2 with WiFi/BlueTooth (BT/BLE).
  • Use ADC1, and pins GPIO32-GPIO39
  • If somehow it's a must to use those pins serviced by ADC2 (GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27), use the fix mentioned at the end of ESP_WiFiManager Issue 39: Not able to read analog port when using the autoconnect example to work with ESP32 WiFi/BlueTooth (BT/BLE).


How It Works

  • The Async_ConfigOnSwitch example shows how it works and should be used as the basis for a sketch that uses this library.
  • The concept of Async_ConfigOnSwitch is that a new ESP32 / ESP8266 will start a WiFi ConfigPortal when powered up and save the configuration data in non volatile memory. Thereafter, the ConfigPortal will only be started again if a button is pushed on the ESP32 / ESP8266 module.
  • Using any WiFi enabled device with a browser (computer, phone, tablet) connect to the newly created Access Point (AP) using configurable SSID and Password (specified in sketch)
// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
const char* password = "your_password";

then connect WebBrowser to configurable ConfigPortal IP address, default is 192.168.4.1

  • Choose one of the access points scanned, enter password, click Save.
  • ESP will restart, then try to connect to the WiFi netwotk using STA-only mode, without running the ConfigPortal WebServer and WiFi AP. See Accessing manager after connection.


HOWTO Basic configurations

1. Using default for every configurable parameter

  • Include in your sketch
#ifdef ESP32
  #include <esp_wifi.h>
  #include <WiFi.h>
  #include <WiFiClient.h>

  // From v1.1.1
  #include <WiFiMulti.h>
  WiFiMulti wifiMulti;

  // LittleFS has higher priority than SPIFFS
  #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
    #define USE_LITTLEFS    true
    #define USE_SPIFFS      false
  #elif defined(ARDUINO_ESP32C3_DEV)
    // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS
    #define USE_LITTLEFS          false
    #define USE_SPIFFS            true
  #endif

  #if USE_LITTLEFS
    // Use LittleFS
    #include "FS.h"

    // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
    //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) )  //(ESP_ARDUINO_VERSION_MAJOR >= 2)
    #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
      #warning Using ESP32 Core 1.0.6 or 2.0.0+
      // The library has been merged into esp32 core from release 1.0.6
      #include <LittleFS.h>       // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
      
      FS* filesystem =      &LittleFS;
      #define FileFS        LittleFS
      #define FS_Name       "LittleFS"
    #else
      #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
      // The library has been merged into esp32 core from release 1.0.6
      #include <LITTLEFS.h>       // https://github.com/lorol/LITTLEFS
      
      FS* filesystem =      &LITTLEFS;
      #define FileFS        LITTLEFS
      #define FS_Name       "LittleFS"
    #endif
    
  #elif USE_SPIFFS
    #include <SPIFFS.h>
    FS* filesystem =      &SPIFFS;
    #define FileFS        SPIFFS
    #define FS_Name       "SPIFFS"
  #else
    // +Use FFat
    #include <FFat.h>
    FS* filesystem =      &FFat;
    #define FileFS        FFat
    #define FS_Name       "FFat"
  #endif
  //////

  #define LED_BUILTIN       2
  #define LED_ON            HIGH
  #define LED_OFF           LOW

#else

  #include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
  //needed for library
  #include <ESPAsyncDNSServer.h>

  // From v1.1.1
  #include <ESP8266WiFiMulti.h>
  ESP8266WiFiMulti wifiMulti;

  #define USE_LITTLEFS      true
  
  #if USE_LITTLEFS
    #include <LittleFS.h>
    FS* filesystem =      &LittleFS;
    #define FileFS        LittleFS
    #define FS_Name       "LittleFS"
  #else
    FS* filesystem =      &SPIFFS;
    #define FileFS        SPIFFS
    #define FS_Name       "SPIFFS"
  #endif
  //////
  
  #define ESP_getChipId()   (ESP.getChipId())
  
  #define LED_ON      LOW
  #define LED_OFF     HIGH
#endif

// From v1.1.0
// You only need to format the filesystem once
//#define FORMAT_FILESYSTEM       true
#define FORMAT_FILESYSTEM         false

#define MIN_AP_PASSWORD_SIZE    8

#define SSID_MAX_LEN            32
//From v1.0.10, WPA2 passwords can be up to 63 characters long.
#define PASS_MAX_LEN            64

typedef struct
{
  char wifi_ssid[SSID_MAX_LEN];
  char wifi_pw  [PASS_MAX_LEN];
}  WiFi_Credentials;

typedef struct
{
  String wifi_ssid;
  String wifi_pw;
}  WiFi_Credentials_String;

#define NUM_WIFI_CREDENTIALS      2

typedef struct
{
  WiFi_Credentials  WiFi_Creds [NUM_WIFI_CREDENTIALS];
} WM_Config;

WM_Config         WM_config;

#define  CONFIG_FILENAME              F("/wifi_cred.dat")
//////

#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager


// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
const char* password = "your_password";

// SSID and PW for your Router
String Router_SSID;
String Router_Pass;

#define HTTP_PORT           80

2. Using many configurable parameters

  • Include in your sketch
#ifdef ESP32
  #include <esp_wifi.h>
  #include <WiFi.h>
  #include <WiFiClient.h>

  // From v1.1.1
  #include <WiFiMulti.h>
  WiFiMulti wifiMulti;

  // LittleFS has higher priority than SPIFFS
  #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
    #define USE_LITTLEFS    true
    #define USE_SPIFFS      false
  #elif defined(ARDUINO_ESP32C3_DEV)
    // For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS
    #define USE_LITTLEFS          false
    #define USE_SPIFFS            true
  #endif

  #if USE_LITTLEFS
    // Use LittleFS
    #include "FS.h"

    // Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
    //#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) )  //(ESP_ARDUINO_VERSION_MAJOR >= 2)
    #if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
      #warning Using ESP32 Core 1.0.6 or 2.0.0+
      // The library has been merged into esp32 core from release 1.0.6
      #include <LittleFS.h>       // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
      
      FS* filesystem =      &LittleFS;
      #define FileFS        LittleFS
      #define FS_Name       "LittleFS"
    #else
      #warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
      // The library has been merged into esp32 core from release 1.0.6
      #include <LITTLEFS.h>       // https://github.com/lorol/LITTLEFS
      
      FS* filesystem =      &LITTLEFS;
      #define FileFS        LITTLEFS
      #define FS_Name       "LittleFS"
    #endif
    
  #elif USE_SPIFFS
    #include <SPIFFS.h>
    FS* filesystem =      &SPIFFS;
    #define FileFS        SPIFFS
    #define FS_Name       "SPIFFS"
  #else
    // +Use FFat
    #include <FFat.h>
    FS* filesystem =      &FFat;
    #define FileFS        FFat
    #define FS_Name       "FFat"
  #endif
  //////

  #define LED_BUILTIN       2
  #define LED_ON            HIGH
  #define LED_OFF           LOW

#else

  #include <ESP8266WiFi.h>          //https://github.com/esp8266/Arduino
  //needed for library
  #include <ESPAsyncDNSServer.h>

  // From v1.1.1
  #include <ESP8266WiFiMulti.h>
  ESP8266WiFiMulti wifiMulti;

  #define USE_LITTLEFS      true
  
  #if USE_LITTLEFS
    #include <LittleFS.h>
    FS* filesystem =      &LittleFS;
    #define FileFS        LittleFS
    #define FS_Name       "LittleFS"
  #else
    FS* filesystem =      &SPIFFS;
    #define FileFS        SPIFFS
    #define FS_Name       "SPIFFS"
  #endif
  //////
  
  #define ESP_getChipId()   (ESP.getChipId())
  
  #define LED_ON      LOW
  #define LED_OFF     HIGH
#endif

// From v1.1.0
// You only need to format the filesystem once
//#define FORMAT_FILESYSTEM       true
#define FORMAT_FILESYSTEM         false

#define MIN_AP_PASSWORD_SIZE    8

#define SSID_MAX_LEN            32
//From v1.0.10, WPA2 passwords can be up to 63 characters long.
#define PASS_MAX_LEN            64

typedef struct
{
  char wifi_ssid[SSID_MAX_LEN];
  char wifi_pw  [PASS_MAX_LEN];
}  WiFi_Credentials;

typedef struct
{
  String wifi_ssid;
  String wifi_pw;
}  WiFi_Credentials_String;

#define NUM_WIFI_CREDENTIALS      2

typedef struct
{
  WiFi_Credentials  WiFi_Creds [NUM_WIFI_CREDENTIALS];
} WM_Config;

WM_Config         WM_config;

#define  CONFIG_FILENAME              F("/wifi_cred.dat")
//////

// Use false if you don't like to display Available Pages in Information Page of Config Portal
// Comment out or use true to display Available Pages in Information Page of Config Portal
// Must be placed before #include <ESPAsync_WiFiManager.h>
#define USE_AVAILABLE_PAGES     true

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     false

// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
#define USE_CLOUDFLARE_NTP          false

// New in v1.0.11
#define USING_CORS_FEATURE          true
//////

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
// Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  //#define USE_DHCP_IP     true
  #define USE_DHCP_IP     false
#endif

#if ( USE_DHCP_IP || ( defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP ) )
  // Use DHCP
  #warning Using DHCP IP
  IPAddress stationIP   = IPAddress(0, 0, 0, 0);
  IPAddress gatewayIP   = IPAddress(192, 168, 2, 1);
  IPAddress netMask     = IPAddress(255, 255, 255, 0);
#else
  // Use static IP
  #warning Using static IP
  
  #ifdef ESP32
    IPAddress stationIP   = IPAddress(192, 168, 2, 232);
  #else
    IPAddress stationIP   = IPAddress(192, 168, 2, 186);
  #endif
  
  IPAddress gatewayIP   = IPAddress(192, 168, 2, 1);
  IPAddress netMask     = IPAddress(255, 255, 255, 0);
#endif

#define USE_CONFIGURABLE_DNS      true

IPAddress dns1IP      = gatewayIP;
IPAddress dns2IP      = IPAddress(8, 8, 8, 8);

IPAddress APStaticIP  = IPAddress(192, 168, 100, 1);
IPAddress APStaticGW  = IPAddress(192, 168, 100, 1);
IPAddress APStaticSN  = IPAddress(255, 255, 255, 0);

#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager


// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
const char* password = "your_password";

// SSID and PW for your Router
String Router_SSID;
String Router_Pass;

#define HTTP_PORT           80

AsyncWebServer webServer(HTTP_PORT);
AsyncDNSServer dnsServer;

///////////////////////////////////////////
// New in v1.4.0
/******************************************
 * // Defined in ESPAsync_WiFiManager.h
typedef struct
{
  IPAddress _ap_static_ip;
  IPAddress _ap_static_gw;
  IPAddress _ap_static_sn;

}  WiFi_AP_IPConfig;

typedef struct
{
  IPAddress _sta_static_ip;
  IPAddress _sta_static_gw;
  IPAddress _sta_static_sn;
#if USE_CONFIGURABLE_DNS  
  IPAddress _sta_static_dns1;
  IPAddress _sta_static_dns2;
#endif
}  WiFi_STA_IPConfig;
******************************************/

WiFi_AP_IPConfig  WM_AP_IPconfig;
WiFi_STA_IPConfig WM_STA_IPconfig;

3. Using STA-mode DHCP, but don't like to change to static IP or display in Config Portal

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
#define USE_STATIC_IP_CONFIG_IN_CP          false

4. Using STA-mode DHCP, but permit to change to static IP and display in Config Portal

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
  // Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  #define USE_DHCP_IP     true
#endif

5. Using STA-mode StaticIP, and be able to change to DHCP IP and display in Config Portal

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
// Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  #define USE_DHCP_IP     false
#endif

6. Using STA-mode StaticIP and configurable DNS, and be able to change to DHCP IP and display in Config Portal

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
  // Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  #define USE_DHCP_IP     false
#endif

#define USE_CONFIGURABLE_DNS      true

IPAddress dns1IP      = gatewayIP;
IPAddress dns2IP      = IPAddress(8, 8, 8, 8);

7. Using STA-mode StaticIP and auto DNS, and be able to change to DHCP IP and display in Config Portal

// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP          false

// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
  // Force DHCP to be true
  #if defined(USE_DHCP_IP)
    #undef USE_DHCP_IP
  #endif
  #define USE_DHCP_IP     true
#else
  // You can select DHCP or Static IP here
  #define USE_DHCP_IP     false
#endif

#define USE_CONFIGURABLE_DNS      false

8. Not using NTP to avoid issue with some WebBrowsers, especially in CellPhone or Tablets.

// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     false

9. Using NTP feature with CloudFlare. System can hang until you have Internet access for CloudFlare.

// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     true

// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
#define USE_CLOUDFLARE_NTP          true

10. Using NTP feature without CloudFlare to avoid system hang if no Internet access for CloudFlare.

// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     true

// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
#define USE_CLOUDFLARE_NTP          false

11. Using random AP-mode channel to avoid conflict

// From v1.0.10 only
// Set config portal channel, default = 1. Use 0 => random channel from 1-13
ESPAsync_wifiManager.setConfigPortalChannel(0);
//////

12. Using fixed AP-mode channel, for example channel 3

// From v1.0.10 only
// Set config portal channel, default = 1. Use 0 => random channel from 1-13
ESPAsync_wifiManager.setConfigPortalChannel(3);
//////

13. Setting STA-mode static IP

// Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
//ESPAsync_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask, dns1IP, dns2IP);
ESPAsync_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig);

14. Using AUTOCONNECT_NO_INVALIDATE feature

  1. Don't invalidate WiFi SSID/PW when calling autoConnect() (default)
#define AUTOCONNECT_NO_INVALIDATE     true
  1. To invalidate WiFi SSID/PW when calling autoConnect()
#define AUTOCONNECT_NO_INVALIDATE     false

15. Using CORS (Cross-Origin Resource Sharing) feature

  1. To use CORS feature with default CORS Header "". Some WebBrowsers won't accept this allowing-all "" CORS Header.
// Default false for using only whenever necessary to avoid security issue
#define USING_CORS_FEATURE     true
  1. To use CORS feature with specific CORS Header "Your Access-Control-Allow-Origin". To be modified according to your specific Allowed-Origin.
// Default false for using only whenever necessary to avoid security issue
#define USING_CORS_FEATURE     true

...

  // New from v1.1.1
#if USING_CORS_FEATURE
  ESP_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
#endif
  1. Not use CORS feature (default)
// Default false for using only whenever necessary to avoid security issue
#define USING_CORS_FEATURE     false

16. Using MultiWiFi auto(Re)connect feature

  1. In loop()
void check_WiFi(void)
{
  if ( (WiFi.status() != WL_CONNECTED) )
  {
    Serial.println("\nWiFi lost. Call connectMultiWiFi in loop");
    connectMultiWiFi();
  }
}

void check_status(void)
{
  static ulong checkwifi_timeout    = 0;

  static ulong current_millis;

#define WIFICHECK_INTERVAL    1000L

  current_millis = millis();
  
  // Check WiFi every WIFICHECK_INTERVAL (1) seconds.
  if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
  {
    check_WiFi();
    checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
  }
}

void loop()
{
  // put your main code here, to run repeatedly
  check_status();
}

17. How to auto getting _timezoneName

  1. Turn on auto NTP configuration by
// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP     true
  1. The _timezoneName, in the format similar to America/New_York, America/Toronto, Europe/London, etc., can be retrieved by using
String tempTZ = ESPAsync_wifiManager.getTimezoneName();

18. How to get TZ variable to configure Timezone

  1. ESP32 and ESP8266 TZ can be configured, using the similar to EST5EDT,M3.2.0,M11.1.0 (for America/New_York) , as follows:
// EST5EDT,M3.2.0,M11.1.0 (for America/New_York)
// EST5EDT is the name of the time zone
// EST is the abbreviation used when DST is off
// 6 hours is the time difference from GMT
// EDT is the abbreviation used when DST is on
// ,M3 is the third month
// .2 is the second occurrence of the day in the month
// .0 is Sunday
// ,M11 is the eleventh month
// .1 is the first occurrence of the day in the month
// .0 is Sunday

#if ESP8266
  configTime(WM_config.TZ, "pool.ntp.org"); 
#else
  //configTzTime(WM_config.TZ, "pool.ntp.org" );
  configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
#endif
  1. To convert from _timezoneName to TZ, use the function getTZ() as follows:
const char * TZ_Result = ESPAsync_wifiManager.getTZ(_timezoneName);

The conversion depends on the stored TZs, which is using some memory, and can cause issue for ESP8266 in certain cases. Therefore, enable just the region you're interested.

For example, your application is used in America continent, you need just

#define USING_AMERICA       true

Hereafter is the regions' list

// Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen
// if using too much memory
#define USING_AFRICA        false
#define USING_AMERICA       true
#define USING_ANTARCTICA    false
#define USING_ASIA          false
#define USING_ATLANTIC      false
#define USING_AUSTRALIA     false
#define USING_EUROPE        false
#define USING_INDIAN        false
#define USING_PACIFIC       false
#define USING_ETC_GMT       false

19. How to use the TZ variable to configure Timezone

#if ESP8266
      configTime(WM_config.TZ, "pool.ntp.org");
#else
      //configTzTime(WM_config.TZ, "pool.ntp.org" );
      configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
#endif

then to print local time

void printLocalTime()
{
#if ESP8266
  static time_t now;
  
  now = time(nullptr);
  
  if ( now > 1000000 )
  {
    Serial.print("Local Date/Time: ");
    Serial.print(ctime(&now));
  }
#else
  struct tm timeinfo;

  getLocalTime( &timeinfo );
  Serial.print("Local Date/Time: ");
  Serial.print( asctime( &timeinfo ) );
#endif
}


HOWTO Open Config Portal

  • When you want to open a config portal, with default DHCP hostname ESP8266-XXXXXX or ESP32-XXXXXX, just add
#include <ESPAsync_WiFiManager.h>              //https://github.com/khoih-prog/ESPAsync_WiFiManager

#define HTTP_PORT           80

AsyncWebServer webServer(HTTP_PORT);
AsyncDNSServer dnsServer;

ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer);

If you'd like to have a personalized hostname (RFC952-conformed,- 24 chars max,- only a..z A..Z 0..9 '-' and no '-' as last char)

add

ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "Personalized-HostName");

then later call

ESPAsync_wifiManager.startConfigPortal()

While in AP mode, connect to it using its SSID (ESP_XXXXXX) / Password ("your_password"), then open a browser to the AP IP, default 192.168.4.1, configure wifi then save. The WiFi connection information will be saved in non volatile memory. It will then reboot and autoconnect.

You can also change the AP IP by:

//set custom ip for portal
//ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
ESPAsync_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig);

and use fixed / dynamic / random AP channel by:

// Set config portal channel, default = 1. Use 0 => random channel from 1-13
ESPAsync_wifiManager.setConfigPortalChannel(0);

Once WiFi network information is saved in the ESP32 / ESP8266, it will try to autoconnect to WiFi every time it is started, without requiring any function calls in the sketch.



HOWTO Add Dynamic Parameters

These illustrating steps is based on the example Async_ConfigOnSwitchFS

1. Determine the variables to be configured via Config Portal (CP)

The application will:

  • use DHT sensor (either DHT11 or DHT22) and
  • need to connect to ThingSpeak with unique user's API Key.

The DHT sensor is connected to the ESP boards using SDA/SCL pins which also need to be configurable.

So this is the list of variables to be dynamically configured using CP

1. `thingspeakApiKey`,  type `char array`, max length 17 chars, and just arbitrarily selected default value to be "" or "ThingSpeak-APIKey"
2. `sensorDht22`,       type `bool`, default to be `true` (DHT22)
3. `pinSda`,            type `int`,  default to be `PIN_D2`
4. `pinScl`,            type `int`,  default to be `PIN_D1`

The Label can be any arbitrary string that help you identify the variable, but must be unique in your application

The initial code will be

#define API_KEY_LEN                 17

// Default configuration values
char thingspeakApiKey[API_KEY_LEN]  = "";
bool sensorDht22                    = true;
int pinSda                          = PIN_D2;     // Pin D2 mapped to pin GPIO4 of ESP8266
int pinScl                          = PIN_D1;     // Pin D1 mapped to pin GPIO5 of ESP8266

// Any unique string helping you identify the vars
#define ThingSpeakAPI_Label         "thingspeakApiKey"
#define SensorDht22_Label           "SensorDHT22"
#define PinSDA_Label                "PinSda"
#define PinSCL_Label                "PinScl"

2. Initialize the variables to prepare for Config Portal (CP)

The example Async_ConfigOnSwitchFS will open the CP whenever a SW press is detected in loop(). So the code to add dynamic variables will be there, just after the CP ESPAsync_WiFiManager class initialization to create ESPAsync_wifiManager object.

void loop()
{
// is configuration portal requested?
  if ((digitalRead(TRIGGER_PIN) == LOW) || (digitalRead(TRIGGER_PIN2) == LOW))
  {
    Serial.println("\nConfiguration portal requested.");
    digitalWrite(LED_BUILTIN, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.

    //Local initialization. Once its business is done, there is no need to keep it around
    ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "ConfigOnSwitchFS");

    //Check if there is stored WiFi router/password credentials.
    //If not found, device will remain in configuration mode until switched off via webserver.
    Serial.print("Opening configuration portal. ");
    
    ...
    
    // The addition of dynamic vars will be somewhere here
    
}    

The ESPAsync_WMParameter class constructor will be used to initialize each newly-added parameter object.

2.1 Use the following simple constructor for simple variables such as thingspeakApiKey, pinSda and pinScl :

ESPAsync_WMParameter(const char *id, const char *placeholder, const char *defaultValue, int length);

2.2 For example, to create a new ESPAsync_WMParameter object p_thingspeakApiKey for thingspeakApiKey,

The command to use will be

ESPAsync_WMParameter p_thingspeakApiKey(ThingSpeakAPI_Label, "Thingspeak API Key", thingspeakApiKey, API_KEY_LEN);

where

- p_thingspeakApiKey                  : ESPAsync_WMParameter class object reference that stores the new Custom Parameter
- id => ThingSpeakAPI_Label           : var ref to Json associative name and HTML element ID for the new Custom Paramerter you just defined in step 1
- placeholder => "Thingspeak API Key" : HTML input placeholder and/or label element text the user sees in the configuration interface for this Custom Parameter
- defaultValue => thingspeakApiKey    : variable for storing the value of your Custom Parameter in the file system or default value when no data is entered
- length  => API_KEY_LEN              : max allowed length you want for this Custom Parameter to have

For pinSda and pinScl, the command will be similar

// I2C SCL and SDA parameters are integers so we need to convert them to char array but
// no other special considerations
char convertedValue[3];
sprintf(convertedValue, "%d", pinSda);
ESPAsync_WMParameter p_pinSda(PinSDA_Label, "I2C SDA pin", convertedValue, 3);

sprintf(convertedValue, "%d", pinScl);
ESPAsync_WMParameter p_pinScl(PinSCL_Label, "I2C SCL pin", convertedValue, 3);

where

- p_pinSda / p_pinScl                         : ESPAsync_WMParameter class object reference that stores the new Custom Parameter
- id => PinSDA_Label/PinSCL_Label             : var ref to Json associative name and HTML element ID for the new Custom Paramerter you just defined in step 1
- placeholder => "I2C SDA pin"/"I2C SCL pin"  : HTML input placeholder and/or label element text the user sees in the configuration interface for this Custom Parameter
- defaultValue => convertedValue              : variable for storing the value of your Custom Parameter in the file system or default value when no data is entered
- length  => 3                                : max allowed length you want for this Custom Parameter to have

2.3 Use the more complex following constructor for variables such as sensorDht22:

ESPAsync_WMParameter(const char *id, const char *placeholder, const char *defaultValue, int length, const char *custom, int labelPlacement);

2.4 For example, to create a new ESPAsync_WMParameter object p_sensorDht22 for sensorDht22,

The command to use will be

ESPAsync_WMParameter p_sensorDht22(SensorDht22_Label, "DHT-22 Sensor", "T", 2, customhtml, WFM_LABEL_AFTER);

where

- p_sensorDht22                       : ESPAsync_WMParameter class object reference that stores the new Custom Parameter
- id => SensorDht22_Label             : var ref to Json associative name and HTML element ID for the new Custom Paramerter you just defined in step 1
- placeholder => "DHT-22 Sensor"      : HTML input placeholder and/or label element text the user sees in the configuration interface for this Custom Parameter
- defaultValue => "T"                 : variable for storing the value of your Custom Parameter in the file system or default value when no data is entered ("T" means `true`)
- length  => 2                        : max allowed length you want for this Custom Parameter to have
- custom => customhtml                : custom HTML code to add element type, e.g. `checkbox`, and `checked` when `sensorDht22 == true`
- labelPlacement => WFM_LABEL_AFTER   : to place label after

and customhtml Code is:

char customhtml[24] = "type=\"checkbox\"";

if (sensorDht22)
{
  strcat(customhtml, " checked");
}

3. Add the variables to Config Portal (CP)

Adding those ESPAsync_WMParameter objects created in Step 2 using the function addParameter() of object ESPAsync_wifiManager

3.1 addParameter() function Prototype:

//adds a custom parameter
bool addParameter(ESPAsync_WMParameter *p);

3.2 Code to add variables to CP

Add parameter objects, previously created in Step 2, such as : p_thingspeakApiKey, p_sensorDht22, p_pinSda and p_pinScl

//add all parameters here

ESPAsync_wifiManager.addParameter(&p_thingspeakApiKey);
ESPAsync_wifiManager.addParameter(&p_sensorDht22);
ESPAsync_wifiManager.addParameter(&p_pinSda);
ESPAsync_wifiManager.addParameter(&p_pinScl);

4. Save the variables configured in Config Portal (CP)

When the CP exits, we have to store the parameters' values that users input via CP to use later.

For ESP32, that can be EEPROM or SPIFFS. While on ESP8266, LittleFS can be used besides EEPROM or deprecated SPIFFS.

We can write directly to a well-defined structure of our choice, but the current example is using JSON to be portable but much more complicated and not advised for new users.

4.1 Getting variables' data from CP

After users select Save, the CP ESPAsync_wifiManager object will save the user input data into related ESPAsync_WMParameter objects.

We can now retrieve the data, using getValue() function, for each ESPAsync_WMParameter object. Then we can utilize the data for our purpose, such as thingspeakApiKey to log in, sensorDht22 type to know how to handle the sensor, pinSda and pinSda to know which pins to use to communicate with the DHT sensor.

The code is as follows:

// Getting posted form values and overriding local variables parameters
// Config file is written regardless the connection state
strcpy(thingspeakApiKey, p_thingspeakApiKey.getValue());
sensorDht22 = (strncmp(p_sensorDht22.getValue(), "T", 1) == 0);
pinSda = atoi(p_pinSda.getValue());
pinScl = atoi(p_pinScl.getValue());

We can also save to FS file to use later in next boot.

// Writing JSON config file to flash for next boot
writeConfigFile();

5. Write to FS (SPIFFS, LittleFS, etc.) using JSON format

First, you have to familiarize yourself with ArduinoJson library, its functions, the disruptive differences between ArduinoJson version 5.x.x- and v6.0.0+. The best documentation can be found at The best JSON library for embedded C++.

This documentation will discuss only ArduinoJson v6.x.x+ (ARDUINOJSON_VERSION_MAJOR >= 6)

Then have a look at the code snippet of writeConfigFile() function and the following step-by-step explanations.

bool writeConfigFile()
{
  Serial.println("Saving config file");

#if (ARDUINOJSON_VERSION_MAJOR >= 6)
  DynamicJsonDocument json(1024);
#else
  DynamicJsonBuffer jsonBuffer;
  JsonObject& json = jsonBuffer.createObject();
#endif

  // JSONify local configuration parameters
  json[ThingSpeakAPI_Label] = thingspeakApiKey;
  json[SensorDht22_Label] = sensorDht22;
  json[PinSDA_Label] = pinSda;
  json[PinSCL_Label] = pinScl;

  // Open file for writing
  File f = FileFS.open(CONFIG_FILE, "w");

  if (!f)
  {
    Serial.println("Failed to open config file for writing");
    return false;
  }

#if (ARDUINOJSON_VERSION_MAJOR >= 6)
  serializeJsonPretty(json, Serial);
  // Write data to file and close it
  serializeJson(json, f);
#else
  json.prettyPrintTo(Serial);
  // Write data to file and close it
  json.printTo(f);
#endif

  f.close();

  Serial.println("\nConfig file was successfully saved");
  return true;
}

5.1 Create a DynamicJsonDocument Object

We'll create an object with size 1024 bytes, enough to hold our data:

DynamicJsonDocument json(1024);

5.2 Fill the DynamicJsonDocument Object with data got from Config Portal

Then JSONify all local parameters we've just received from CP and wish to store into FS by using the function prototype:

json[Unique_Label] = Value_For_Unique_Label;

as follows:

// JSONify local configuration parameters
json[ThingSpeakAPI_Label] = thingspeakApiKey;
json[SensorDht22_Label]   = sensorDht22;
json[PinSDA_Label]        = pinSda;
json[PinSCL_Label]        = pinScl;

5.3 Open file to write the Jsonified data

This is the CONFIG_FILE file name we already declared at the beginning of the sketch (for ESP32):

#include <SPIFFS.h>
FS* filesystem =      &SPIFFS;
#define FileFS        SPIFFS
    
const char* CONFIG_FILE = "/ConfigSW.json";

Now just open the file for writing, and abort if open-for-writing error:

// Open file for writing
File f = FileFS.open(CONFIG_FILE, "w");

if (!f)
{
  Serial.println("Failed to open config file for writing");
  return false;
}

5.4 Write the Jsonified data to CONFIG_FILE

As simple as this single command to write the whole json object we declared then filled with data in steps 5.1 and 5.2

// Write data to file and close it
serializeJson(json, f);

5.5 Close CONFIG_FILE to flush and save the data

Soooo simple !!! Now everybody can do it.

f.close();

But HOWTO use the saved data in the next startup ???? That's in next step 6.

6. Read from FS using JSON format

Now, you have familiarized yourself with ArduinoJson library, its functions. We'll discuss HOWTO read data from the CONFIG_FILE in Jsonified format, then HOWTO parse the to use.

The documentation will discuss only ArduinoJson v6.x.x+ (ARDUINOJSON_VERSION_MAJOR >= 6)

First, have a look at the code snippet of readConfigFile() function.

bool readConfigFile()
{
  // this opens the config file in read-mode
  File f = FileFS.open(CONFIG_FILE, "r");

  if (!f)
  {
    Serial.println("Configuration file not found");
    return false;
  }
  else
  {
    // we could open the file
    size_t size = f.size();
    // Allocate a buffer to store contents of the file.
    std::unique_ptr<char[]> buf(new char[size + 1]);

    // Read and store file contents in buf
    f.readBytes(buf.get(), size);
    // Closing file
    f.close();
    // Using dynamic JSON buffer which is not the recommended memory model, but anyway
    // See https://github.com/bblanchon/ArduinoJson/wiki/Memory%20model

#if (ARDUINOJSON_VERSION_MAJOR >= 6)
    DynamicJsonDocument json(1024);
    auto deserializeError = deserializeJson(json, buf.get());
    if ( deserializeError )
    {
      Serial.println("JSON parseObject() failed");
      return false;
    }
    serializeJson(json, Serial);
#else
    DynamicJsonBuffer jsonBuffer;
    // Parse JSON string
    JsonObject& json = jsonBuffer.parseObject(buf.get());
    // Test if parsing succeeds.
    if (!json.success())
    {
      Serial.println("JSON parseObject() failed");
      return false;
    }
    json.printTo(Serial);
#endif

    // Parse all config file parameters, override
    // local config variables with parsed values
    if (json.containsKey(ThingSpeakAPI_Label))
    {
      strcpy(thingspeakApiKey, json[ThingSpeakAPI_Label]);
    }

    if (json.containsKey(SensorDht22_Label))
    {
      sensorDht22 = json[SensorDht22_Label];
    }

    if (json.containsKey(PinSDA_Label))
    {
      pinSda = json[PinSDA_Label];
    }

    if (json.containsKey(PinSCL_Label))
    {
      pinScl = json[PinSCL_Label];
    }
  }
  Serial.println("\nConfig file was successfully parsed");
  return true;
}

and the following step-by-step explanations.

6.1 Open CONFIG_FILE to read

As simple as this

// this opens the config file in read-mode
File f = FileFS.open(CONFIG_FILE, "r");

We'll inform and abort if the CONFIG_FILE can't be opened (file not found, can't be opened, etc.)

if (!f)
{
  Serial.println("Configuration file not found");
  return false;
}

6.2 Open CONFIG_FILE to read

Now we have to determine the file size to create a buffer large enough to store the to-be-read data

// we could open the file
size_t size = f.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size + 1]);

Remember always add 1 to the buffer length to store the terminating 0.

Then just read the file into the buffer, and close the file to be safe

// Read and store file contents in buf
f.readBytes(buf.get(), size);
// Closing file
f.close();

6.3 Populate the just-read Jsonified data into the DynamicJsonDocument json object

We again use the same DynamicJsonDocument json object to store the data we've just read from CONFIG_FILE.

Why the same complicated DynamicJsonDocument json object ?? Because in steps 5, we did store Jsonified data using the same DynamicJsonDocument json object. It's much easier we now use it again to facilitate the parsing of Jsonified data back to the data we can use easily.

We first create the object with enough size

DynamicJsonDocument json(1024);

then populate it with data from buffer we read from CONFIG_FILE in step 6.2, pre-parse and check for error. All is done just by one command deserializeJson()

auto deserializeError = deserializeJson(json, buf.get());

Abort if there is any data error in the process of writing, storing, reading back. If OK, just nicely print out to the Debug Terminal

if ( deserializeError )
{
  Serial.println("JSON parseObject() failed");
  return false;
}

serializeJson(json, Serial);

6.4 Parse the Jsonified data from the DynamicJsonDocument json object to store into corresponding parameters

This is as simple as in the step 5.2, but in reverse direction.

To be sure there is good corresponding data, not garbage, for each variable, we have to perform sanity checks by verifying the DynamicJsonDocument json object still contains the correct keys we passed to it when we wrote into CONFIG_FILE.

For example:

if (json.containsKey(ThingSpeakAPI_Label))

Then proceed to get every parameter we know we stored there from last CP Save.

// Parse all config file parameters, override
// local config variables with parsed values
if (json.containsKey(ThingSpeakAPI_Label))
{
  strcpy(thingspeakApiKey, json[ThingSpeakAPI_Label]);
}

if (json.containsKey(SensorDht22_Label))
{
  sensorDht22 = json[SensorDht22_Label];
}

if (json.containsKey(PinSDA_Label))
{
  pinSda = json[PinSDA_Label];
}

if (json.containsKey(PinSCL_Label))
{
  pinScl = json[PinSCL_Label];
}

6.5 Then what to do now

Just use those parameters for whatever purpose you designed them for in step 1:

The application will use DHT sensor (either DHT11 or DHT22) and need to connect to ThingSpeak with unique user's API Key. The DHT sensor is connected to the ESP boards using SDA/SCL pins which also need to be configurable.


So, how it works?

In ConfigPortal Mode, it starts an access point called ESP_XXXXXX. Connect to it using the configurable password you can define in the code. For example, your_password (see examples):

// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
const char* password = "your_password";

After you connected, please, go to http://192.168.4.1, you'll see this Main page:

Select Information to enter the Info page where the board info will be shown (long page)

or short page (default)

Select Configuration to enter this page where you can select an AP and specify its WiFi Credentials

Enter your credentials, then click Save. The WiFi Credentials will be saved and the board reboots to connect to the selected WiFi AP.

If you're already connected to a listed WiFi AP and don't want to change anything, just select Exit Portal from the Main page to reboot the board and connect to the previously-stored AP. The WiFi Credentials are still intact.



Documentation

Password protect the configuration Access Point

You can password protect the ConfigPortal AP. Simply add an SSID as the first parameter and the password as a second parameter to startConfigPortal. See the above examples.

A short password seems to have unpredictable results so use one that's around 8 characters or more in length. The guidelines are that a wifi password must consist of 8 to 63 ASCII-encoded characters in the range of 32 to 126 (decimal)

ESPAsync_wifiManager.startConfigPortal( SSID , password )

Callbacks

Save settings

This gets called when custom parameters have been set AND a connection has been established. Use it to set a flag, so when all the configuration finishes, you can save the extra parameters somewhere.

See Async_ConfigOnSwitchFS Example.

ESPAsync_wifiManager.setSaveConfigCallback(saveConfigCallback);

saveConfigCallback declaration and example

//flag for saving data
bool shouldSaveConfig = false;

//callback notifying us of the need to save config
void saveConfigCallback () 
{
  Serial.println("Should save config");
  shouldSaveConfig = true;
}

ConfigPortal Timeout

If you need to set a timeout so the ESP32 / ESP8266 doesn't hang waiting to be configured for ever.

ESPAsync_wifiManager.setConfigPortalTimeout(120);

which will wait 2 minutes (120 seconds). When the time passes, the startConfigPortal() function will return and continue the sketch, unless you're accessing the Config Portal. In this case, the startConfigPortal() function will stay until you save config data or exit the Config Portal.

On Demand ConfigPortal

Example usage

void loop()
{
  // is configuration portal requested?
  if ((digitalRead(TRIGGER_PIN) == LOW) || (digitalRead(TRIGGER_PIN2) == LOW))
  {
    Serial.println(F("\nConfiguration portal requested."));
    digitalWrite(LED_BUILTIN, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.

    //Local initialization. Once its business is done, there is no need to keep it around
    ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "ConfigOnSwitch");

    ESPAsync_wifiManager.setMinimumSignalQuality(-1);

    // From v1.0.10 only
    // Set config portal channel, default = 1. Use 0 => random channel from 1-13
    ESPAsync_wifiManager.setConfigPortalChannel(0);
    //////

    //set custom ip for portal
    //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255, 255, 255, 0));

#if !USE_DHCP_IP    
  #if USE_CONFIGURABLE_DNS  
    // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
    ESPAsync_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask, dns1IP, dns2IP);  
  #else
    // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
    ESPAsync_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask);
  #endif 
#endif       

  // New from v1.1.1
#if USING_CORS_FEATURE
  ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
#endif

    //Check if there is stored WiFi router/password credentials.
    //If not found, device will remain in configuration mode until switched off via webserver.
    Serial.println(F("Opening configuration portal. "));
    
    Router_SSID = ESPAsync_wifiManager.WiFi_SSID();
    Router_Pass = ESPAsync_wifiManager.WiFi_Pass();

    //Remove this line if you do not want to see WiFi password printed
    Serial.println("ESP Self-Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);
   
    // From v1.1.0, Don't permit NULL password
    if ( (Router_SSID != "") && (Router_Pass != "") )
    {
      LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass);
      wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
      
      ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
      Serial.println(F("Got ESP Self-Stored Credentials. Timeout 120s for Config Portal"));
    }
    else if (loadConfigData())
    {      
      ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
      Serial.println(F("Got stored Credentials. Timeout 120s for Config Portal")); 
    }
    else
    {
      // Enter CP only if no stored SSID on flash and file 
      Serial.println(F("Open Config Portal without Timeout: No stored Credentials."));
      initialConfig = true;
    }

    //Starts an access point
    //and goes into a blocking loop awaiting configuration
    if (!ESPAsync_wifiManager.startConfigPortal((const char *) ssid.c_str(), password))
    {
      Serial.println(F("Not connected to WiFi but continuing anyway."));
    }
    else
    {
      //if you get here you have connected to the WiFi
      Serial.println(F("connected...yeey :)"));
      Serial.print(F("Local IP: "));
      Serial.println(WiFi.localIP());
    }

    // Only clear then save data if CP entered and with new valid Credentials
    // No CP => stored getSSID() = ""
    if ( String(ESPAsync_wifiManager.getSSID(0)) != "" && String(ESPAsync_wifiManager.getSSID(1)) != "" )
    {
      // Stored  for later usage, from v1.1.0, but clear first
      memset(&WM_config, 0, sizeof(WM_config));
      
      for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
      {
        String tempSSID = ESPAsync_wifiManager.getSSID(i);
        String tempPW   = ESPAsync_wifiManager.getPW(i);
    
        if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
          strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
        else
          strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
    
        if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
          strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
        else
          strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);  
    
        // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
        if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
        {
          LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
          wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
        }
      }
    
      saveConfigData();
    }

    digitalWrite(LED_BUILTIN, LED_OFF); // Turn led off as we are not in configuration mode.
  }

  // put your main code here, to run repeatedly
  check_status();
}

See Async_ConfigOnSwitch example for a more complex version.



Custom Parameters

Many applications need configuration parameters like MQTT host and port, Blynk or emoncms tokens, etc. While it is possible to use ESPAsync_WiFiManager to collect additional parameters, it is better to read these parameters from a web service once ESPAsync_WiFiManager has been used to connect to the Internet.

To capture other parameters with ESPAsync_WiFiManager is a little bit more complicated than all the other features. This requires adding custom HTML to your form.

If you want to do it with ESPAsync_WiFiManager see the example Async_ConfigOnSwitchFS

Custom IP Configuration

You can set a custom IP for both AP (access point, config mode) and STA (station mode, client mode, normal project state)

Custom Access Point IP Configuration

This will set your captive portal to a specific IP should you need/want such a feature. Add the following snippet before startConfigPortal()

//set custom ip for portal
ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(10,0,1,1), IPAddress(10,0,1,1), IPAddress(255,255,255,0));
Custom Station (client) Static IP Configuration

This will use the specified IP configuration instead of using DHCP in station mode.

ESPAsync_wifiManager.setSTAStaticIPConfig(IPAddress(192,168,0,99), IPAddress(192,168,0,1), IPAddress(255,255,255,0));

Custom HTML, CSS, Javascript

There are various ways in which you can inject custom HTML, CSS or Javascript into the ConfigPortal.

The options are:

  • inject custom head element

You can use this to any html bit to the head of the ConfigPortal. If you add a <style> element, bare in mind it overwrites the included css, not replaces.

ESPAsync_wifiManager.setCustomHeadElement("<style>html{filter: invert(100%); -webkit-filter: invert(100%);}</style>");
  • inject a custom bit of html in the configuration form
ESPAsync_WMParameter custom_text("<p>This is just a text paragraph</p>");
ESPAsync_wifiManager.addParameter(&custom_text);
  • inject a custom bit of html in a configuration form element Just add the bit you want added as the last parameter to the custom parameter constructor.
ESPAsync_WMParameter custom_mqtt_server("server", "mqtt server", "iot.eclipse", 40, " readonly");

Filter Networks

You can filter networks based on signal quality and show/hide duplicate networks.

  • If you would like to filter low signal quality networks you can tell WiFiManager to not show networks below an arbitrary quality %;
ESPAsync_wifiManager.setMinimumSignalQuality(10);

will not show networks under 10% signal quality. If you omit the parameter it defaults to 8%;

  • You can also remove or show duplicate networks (default is remove). Use this function to show (or hide) all networks.
ESPAsync_wifiManager.setRemoveDuplicateAPs(false);


Examples

Medium Complexity

  1. Async_ConfigOnSwitch
  2. Async_ConfigOnSwitchFS
  3. Async_ConfigOnStartup
  4. Async_ConfigOnDoubleReset (now support ArduinoJson 6.0.0+ as well as 5.13.5-)
  5. Async_ConfigPortalParamsOnSwitch (now support ArduinoJson 6.0.0+ as well as 5.13.5-)
  6. Async_AutoConnect
  7. Async_AutoConnectWithFeedback
  8. Async_AutoConnectWithFeedbackLED
  9. Async_AutoConnectWithFSParameters
  10. Async_ConfigOnSwitchFS_MQTT_Ptr
  11. Async_AutoConnectWithFSParametersAndCustomIP
  12. Async_ESP32_FSWebServer
  13. Async_ESP32_FSWebServer_DRD
  14. Async_ESP_FSWebServer
  15. Async_ESP_FSWebServer_DRD
  16. Async_ConfigOnDRD_FS_MQTT_Ptr
  17. Async_ConfigOnDoubleReset_TZ (now support ArduinoJson 6.0.0+ as well as 5.13.5-)

High Complexity

  1. Async_ConfigOnDRD_FS_MQTT_Ptr_Complex
  2. Async_ConfigOnDRD_FS_MQTT_Ptr_Medium

Multiple-Definitions-Linker-Error demo

  1. Async_ConfigOnDoubleReset_Multi


/****************************************************************************************************************************
This example will open a Config Portal when there is no stored WiFi Credentials or when a DRD is detected.
You can reconfigure to use another pin, such as the convenience FLASH / BOOT button @ PIN_D0;.
A password is required to connect to the Config Portal so that only who know the password can access the Config Portal.
The Credentials, being input via Config Portal, will then be saved into LittleFS / SPIFFS file, and be used to connect to
Adafruit MQTT Server at "io.adafruit.com" and publish a Temperature Topic
Based on original sketch posted by "Marko"(https://github.com/wackoo-arduino) on https://forum.arduino.cc/index.php?topic=692108
*****************************************************************************************************************************/
#if !( defined(ESP8266) || defined(ESP32) )
#error This code is intended to run on the ESP8266 or ESP32 platform! Please check your Tools->Board setting.
#endif
#define ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET "ESPAsync_WiFiManager v1.15.0"
#define ESP_ASYNC_WIFIMANAGER_VERSION_MIN 1015000
// Use from 0 to 4. Higher number, more debugging messages and memory usage.
#define _ESPASYNC_WIFIMGR_LOGLEVEL_ 3
// To not display stored SSIDs and PWDs on Config Portal, select false. Default is true
// Even the stored Credentials are not display, just leave them all blank to reconnect and reuse the stored Credentials
//#define DISPLAY_STORED_CREDENTIALS_IN_CP false
#include <FS.h>
// Now support ArduinoJson 6.0.0+ ( tested with v6.15.2 to v6.16.1 )
#include <ArduinoJson.h> // get it from https://arduinojson.org/ or install via Arduino library manager
//For ESP32, To use ESP32 Dev Module, QIO, Flash 4MB/80MHz, Upload 921600
//Ported to ESP32
#ifdef ESP32
#include <esp_wifi.h>
#include <WiFi.h>
#include <WiFiClient.h>
// From v1.1.1
#include <WiFiMulti.h>
WiFiMulti wifiMulti;
// LittleFS has higher priority than SPIFFS
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
#define USE_LITTLEFS true
#define USE_SPIFFS false
#elif defined(ARDUINO_ESP32C3_DEV)
// For core v1.0.6-, ESP32-C3 only supporting SPIFFS and EEPROM. To use v2.0.0+ for LittleFS
#define USE_LITTLEFS false
#define USE_SPIFFS true
#endif
#if USE_LITTLEFS
// Use LittleFS
#include "FS.h"
// Check cores/esp32/esp_arduino_version.h and cores/esp32/core_version.h
//#if ( ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(2, 0, 0) ) //(ESP_ARDUINO_VERSION_MAJOR >= 2)
#if ( defined(ESP_ARDUINO_VERSION_MAJOR) && (ESP_ARDUINO_VERSION_MAJOR >= 2) )
#if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3)
#warning Using ESP32 Core 1.0.6 or 2.0.0+
#endif
// The library has been merged into esp32 core from release 1.0.6
#include <LittleFS.h> // https://github.com/espressif/arduino-esp32/tree/master/libraries/LittleFS
FS* filesystem = &LittleFS;
#define FileFS LittleFS
#define FS_Name "LittleFS"
#else
#if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3)
#warning Using ESP32 Core 1.0.5-. You must install LITTLEFS library
#endif
// The library has been merged into esp32 core from release 1.0.6
#include <LITTLEFS.h> // https://github.com/lorol/LITTLEFS
FS* filesystem = &LITTLEFS;
#define FileFS LITTLEFS
#define FS_Name "LittleFS"
#endif
#elif USE_SPIFFS
#include <SPIFFS.h>
FS* filesystem = &SPIFFS;
#define FileFS SPIFFS
#define FS_Name "SPIFFS"
#else
// +Use FFat
#include <FFat.h>
FS* filesystem = &FFat;
#define FileFS FFat
#define FS_Name "FFat"
#endif
//////
#define LED_BUILTIN 2
#define LED_ON HIGH
#define LED_OFF LOW
#else
#include <ESP8266WiFi.h> //https://github.com/esp8266/Arduino
//needed for library
#include <ESPAsyncDNSServer.h>
// From v1.1.1
#include <ESP8266WiFiMulti.h>
ESP8266WiFiMulti wifiMulti;
#define USE_LITTLEFS true
#if USE_LITTLEFS
#include <LittleFS.h>
FS* filesystem = &LittleFS;
#define FileFS LittleFS
#define FS_Name "LittleFS"
#else
FS* filesystem = &SPIFFS;
#define FileFS SPIFFS
#define FS_Name "SPIFFS"
#endif
//////
#define ESP_getChipId() (ESP.getChipId())
#define LED_ON LOW
#define LED_OFF HIGH
#endif
// These defines must be put before #include <ESP_DoubleResetDetector.h>
// to select where to store DoubleResetDetector's variable.
// For ESP32, You must select one to be true (EEPROM or SPIFFS)
// For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS)
// Otherwise, library will use default EEPROM storage
#ifdef ESP32
// These defines must be put before #include <ESP_DoubleResetDetector.h>
// to select where to store DoubleResetDetector's variable.
// For ESP32, You must select one to be true (EEPROM or SPIFFS)
// Otherwise, library will use default EEPROM storage
#if USE_LITTLEFS
#define ESP_DRD_USE_LITTLEFS true
#define ESP_DRD_USE_SPIFFS false
#define ESP_DRD_USE_EEPROM false
#elif USE_SPIFFS
#define ESP_DRD_USE_LITTLEFS false
#define ESP_DRD_USE_SPIFFS true
#define ESP_DRD_USE_EEPROM false
#else
#define ESP_DRD_USE_LITTLEFS false
#define ESP_DRD_USE_SPIFFS false
#define ESP_DRD_USE_EEPROM true
#endif
#else //ESP8266
// For DRD
// These defines must be put before #include <ESP_DoubleResetDetector.h>
// to select where to store DoubleResetDetector's variable.
// For ESP8266, You must select one to be true (RTC, EEPROM, SPIFFS or LITTLEFS)
// Otherwise, library will use default EEPROM storage
#if USE_LITTLEFS
#define ESP_DRD_USE_LITTLEFS true
#define ESP_DRD_USE_SPIFFS false
#else
#define ESP_DRD_USE_LITTLEFS false
#define ESP_DRD_USE_SPIFFS true
#endif
#define ESP_DRD_USE_EEPROM false
#define ESP8266_DRD_USE_RTC false
#endif
#define DOUBLERESETDETECTOR_DEBUG true //false
#include <ESP_DoubleResetDetector.h> //https://github.com/khoih-prog/ESP_DoubleResetDetector
// Number of seconds after reset during which a
// subseqent reset will be considered a double reset.
#define DRD_TIMEOUT 10
// RTC Memory Address for the DoubleResetDetector to use
#define DRD_ADDRESS 0
DoubleResetDetector* drd = NULL;
#include "Adafruit_MQTT.h" //https://github.com/adafruit/Adafruit_MQTT_Library
#include "Adafruit_MQTT_Client.h" //https://github.com/adafruit/Adafruit_MQTT_Library
const char* CONFIG_FILE = "/ConfigMQTT.json";
// Default configuration values for Adafruit IO MQTT
// This actually works
#define AIO_SERVER "io.adafruit.com"
#define AIO_SERVERPORT "1883" //1883, or 8883 for SSL
#define AIO_USERNAME "private" //Adafruit IO
#define AIO_KEY "private"
// Labels for custom parameters in WiFi manager
#define AIO_SERVER_Label "AIO_SERVER_Label"
#define AIO_SERVERPORT_Label "AIO_SERVERPORT_Label"
#define AIO_USERNAME_Label "AIO_USERNAME_Label"
#define AIO_KEY_Label "AIO_KEY_Label"
// Just dummy topics. To be updated later when got valid data from FS or Config Portal
String MQTT_Pub_Topic = "private/feeds/Temperature";
// Variables to save custom parameters to...
// I would like to use these instead of #defines
#define custom_AIO_SERVER_LEN 20
#define custom_AIO_PORT_LEN 5
#define custom_AIO_USERNAME_LEN 20
#define custom_AIO_KEY_LEN 40
char custom_AIO_SERVER[custom_AIO_SERVER_LEN];
char custom_AIO_SERVERPORT[custom_AIO_PORT_LEN];
char custom_AIO_USERNAME[custom_AIO_USERNAME_LEN];
char custom_AIO_KEY[custom_AIO_KEY_LEN];
// Function Prototypes
void MQTT_connect();
bool readConfigFile();
bool writeConfigFile();
// From v1.1.1
// You only need to format the filesystem once
//#define FORMAT_FILESYSTEM true
#define FORMAT_FILESYSTEM false
#define MIN_AP_PASSWORD_SIZE 8
#define SSID_MAX_LEN 32
//From v1.0.10, WPA2 passwords can be up to 63 characters long.
#define PASS_MAX_LEN 64
typedef struct
{
char wifi_ssid[SSID_MAX_LEN];
char wifi_pw [PASS_MAX_LEN];
} WiFi_Credentials;
typedef struct
{
String wifi_ssid;
String wifi_pw;
} WiFi_Credentials_String;
#define NUM_WIFI_CREDENTIALS 2
// Assuming max 49 chars
#define TZNAME_MAX_LEN 50
#define TIMEZONE_MAX_LEN 50
typedef struct
{
WiFi_Credentials WiFi_Creds [NUM_WIFI_CREDENTIALS];
char TZ_Name[TZNAME_MAX_LEN]; // "America/Toronto"
char TZ[TIMEZONE_MAX_LEN]; // "EST5EDT,M3.2.0,M11.1.0"
uint16_t checksum;
} WM_Config;
WM_Config WM_config;
#define CONFIG_FILENAME F("/wifi_cred.dat")
//////
// Indicates whether ESP has WiFi credentials saved from previous session, or double reset detected
bool initialConfig = false;
// Use false if you don't like to display Available Pages in Information Page of Config Portal
// Comment out or use true to display Available Pages in Information Page of Config Portal
// Must be placed before #include <ESPAsync_WiFiManager.h>
#define USE_AVAILABLE_PAGES false
// From v1.0.10 to permit disable/enable StaticIP configuration in Config Portal from sketch. Valid only if DHCP is used.
// You'll loose the feature of dynamically changing from DHCP to static IP, or vice versa
// You have to explicitly specify false to disable the feature.
//#define USE_STATIC_IP_CONFIG_IN_CP false
// Use false to disable NTP config. Advisable when using Cellphone, Tablet to access Config Portal.
// See Issue 23: On Android phone ConfigPortal is unresponsive (https://github.com/khoih-prog/ESP_WiFiManager/issues/23)
#define USE_ESP_WIFIMANAGER_NTP true
// Just use enough to save memory. On ESP8266, can cause blank ConfigPortal screen
// if using too much memory
#define USING_AFRICA false
#define USING_AMERICA true
#define USING_ANTARCTICA false
#define USING_ASIA false
#define USING_ATLANTIC false
#define USING_AUSTRALIA false
#define USING_EUROPE false
#define USING_INDIAN false
#define USING_PACIFIC false
#define USING_ETC_GMT false
// Use true to enable CloudFlare NTP service. System can hang if you don't have Internet access while accessing CloudFlare
// See Issue #21: CloudFlare link in the default portal (https://github.com/khoih-prog/ESP_WiFiManager/issues/21)
#define USE_CLOUDFLARE_NTP false
// New in v1.0.11
#define USING_CORS_FEATURE true
////////////////////////////////////////////
// Use USE_DHCP_IP == true for dynamic DHCP IP, false to use static IP which you have to change accordingly to your network
#if (defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP)
// Force DHCP to be true
#if defined(USE_DHCP_IP)
#undef USE_DHCP_IP
#endif
#define USE_DHCP_IP true
#else
// You can select DHCP or Static IP here
#define USE_DHCP_IP true
//#define USE_DHCP_IP false
#endif
#if ( USE_DHCP_IP )
// Use DHCP
#if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3)
#warning Using DHCP IP
#endif
IPAddress stationIP = IPAddress(0, 0, 0, 0);
IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
IPAddress netMask = IPAddress(255, 255, 255, 0);
#else
// Use static IP
#if (_ESPASYNC_WIFIMGR_LOGLEVEL_ > 3)
#warning Using static IP
#endif
#ifdef ESP32
IPAddress stationIP = IPAddress(192, 168, 2, 232);
#else
IPAddress stationIP = IPAddress(192, 168, 2, 186);
#endif
IPAddress gatewayIP = IPAddress(192, 168, 2, 1);
IPAddress netMask = IPAddress(255, 255, 255, 0);
#endif
////////////////////////////////////////////
#define USE_CONFIGURABLE_DNS true
IPAddress dns1IP = gatewayIP;
IPAddress dns2IP = IPAddress(8, 8, 8, 8);
#define USE_CUSTOM_AP_IP false
IPAddress APStaticIP = IPAddress(192, 168, 100, 1);
IPAddress APStaticGW = IPAddress(192, 168, 100, 1);
IPAddress APStaticSN = IPAddress(255, 255, 255, 0);
#include <ESPAsync_WiFiManager.h> //https://github.com/khoih-prog/ESPAsync_WiFiManager
// Redundant, for v1.10.0 only
//#include <ESPAsync_WiFiManager-Impl.h> //https://github.com/khoih-prog/ESPAsync_WiFiManager
// For Config Portal
// SSID and PW for Config Portal
String ssid = "ESP_" + String(ESP_getChipId(), HEX);
String password;
// SSID and PW for your Router
String Router_SSID;
String Router_Pass;
#define HTTP_PORT 80
// Create an ESP32 WiFiClient class to connect to the MQTT server
WiFiClient *client = NULL;
Adafruit_MQTT_Client *mqtt = NULL;
Adafruit_MQTT_Publish *Temperature = NULL;
// Forward Declaration
///////////////////////////////////////////
// New in v1.4.0
/******************************************
typedef struct
{
IPAddress _ap_static_ip;
IPAddress _ap_static_gw;
IPAddress _ap_static_sn;
} WiFi_AP_IPConfig;
typedef struct
{
IPAddress _sta_static_ip;
IPAddress _sta_static_gw;
IPAddress _sta_static_sn;
#if USE_CONFIGURABLE_DNS
IPAddress _sta_static_dns1;
IPAddress _sta_static_dns2;
#endif
} WiFi_STA_IPConfig;
******************************************/
WiFi_AP_IPConfig WM_AP_IPconfig;
WiFi_STA_IPConfig WM_STA_IPconfig;
void initAPIPConfigStruct(WiFi_AP_IPConfig &in_WM_AP_IPconfig)
{
in_WM_AP_IPconfig._ap_static_ip = APStaticIP;
in_WM_AP_IPconfig._ap_static_gw = APStaticGW;
in_WM_AP_IPconfig._ap_static_sn = APStaticSN;
}
void initSTAIPConfigStruct(WiFi_STA_IPConfig &in_WM_STA_IPconfig)
{
in_WM_STA_IPconfig._sta_static_ip = stationIP;
in_WM_STA_IPconfig._sta_static_gw = gatewayIP;
in_WM_STA_IPconfig._sta_static_sn = netMask;
#if USE_CONFIGURABLE_DNS
in_WM_STA_IPconfig._sta_static_dns1 = dns1IP;
in_WM_STA_IPconfig._sta_static_dns2 = dns2IP;
#endif
}
void displayIPConfigStruct(WiFi_STA_IPConfig in_WM_STA_IPconfig)
{
LOGERROR3(F("stationIP ="), in_WM_STA_IPconfig._sta_static_ip, ", gatewayIP =", in_WM_STA_IPconfig._sta_static_gw);
LOGERROR1(F("netMask ="), in_WM_STA_IPconfig._sta_static_sn);
#if USE_CONFIGURABLE_DNS
LOGERROR3(F("dns1IP ="), in_WM_STA_IPconfig._sta_static_dns1, ", dns2IP =", in_WM_STA_IPconfig._sta_static_dns2);
#endif
}
void configWiFi(WiFi_STA_IPConfig in_WM_STA_IPconfig)
{
#if USE_CONFIGURABLE_DNS
// Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn, in_WM_STA_IPconfig._sta_static_dns1, in_WM_STA_IPconfig._sta_static_dns2);
#else
// Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
WiFi.config(in_WM_STA_IPconfig._sta_static_ip, in_WM_STA_IPconfig._sta_static_gw, in_WM_STA_IPconfig._sta_static_sn);
#endif
}
///////////////////////////////////////////
uint8_t connectMultiWiFi()
{
#if ESP32
// For ESP32, this better be 0 to shorten the connect time.
// For ESP32-S2/C3, must be > 500
#if ( USING_ESP32_S2 || USING_ESP32_C3 )
#define WIFI_MULTI_1ST_CONNECT_WAITING_MS 500L
#else
// For ESP32 core v1.0.6, must be >= 500
#define WIFI_MULTI_1ST_CONNECT_WAITING_MS 800L
#endif
#else
// For ESP8266, this better be 2200 to enable connect the 1st time
#define WIFI_MULTI_1ST_CONNECT_WAITING_MS 2200L
#endif
#define WIFI_MULTI_CONNECT_WAITING_MS 500L
uint8_t status;
//WiFi.mode(WIFI_STA);
LOGERROR(F("ConnectMultiWiFi with :"));
if ( (Router_SSID != "") && (Router_Pass != "") )
{
LOGERROR3(F("* Flash-stored Router_SSID = "), Router_SSID, F(", Router_Pass = "), Router_Pass );
LOGERROR3(F("* Add SSID = "), Router_SSID, F(", PW = "), Router_Pass );
wifiMulti.addAP(Router_SSID.c_str(), Router_Pass.c_str());
}
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
{
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
{
LOGERROR3(F("* Additional SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
}
}
LOGERROR(F("Connecting MultiWifi..."));
//WiFi.mode(WIFI_STA);
#if !USE_DHCP_IP
// New in v1.4.0
configWiFi(WM_STA_IPconfig);
//////
#endif
int i = 0;
status = wifiMulti.run();
delay(WIFI_MULTI_1ST_CONNECT_WAITING_MS);
while ( ( i++ < 20 ) && ( status != WL_CONNECTED ) )
{
status = WiFi.status();
if ( status == WL_CONNECTED )
break;
else
delay(WIFI_MULTI_CONNECT_WAITING_MS);
}
if ( status == WL_CONNECTED )
{
LOGERROR1(F("WiFi connected after time: "), i);
LOGERROR3(F("SSID:"), WiFi.SSID(), F(",RSSI="), WiFi.RSSI());
LOGERROR3(F("Channel:"), WiFi.channel(), F(",IP address:"), WiFi.localIP() );
}
else
{
LOGERROR(F("WiFi not connected"));
// To avoid unnecessary DRD
drd->loop();
#if ESP8266
ESP.reset();
#else
ESP.restart();
#endif
}
return status;
}
void toggleLED()
{
//toggle state
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
#if USE_ESP_WIFIMANAGER_NTP
void printLocalTime()
{
#if ESP8266
static time_t now;
now = time(nullptr);
if ( now > 1451602800 )
{
Serial.print("Local Date/Time: ");
Serial.print(ctime(&now));
}
#else
struct tm timeinfo;
getLocalTime( &timeinfo );
// Valid only if year > 2000.
// You can get from timeinfo : tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec
if (timeinfo.tm_year > 100 )
{
Serial.print("Local Date/Time: ");
Serial.print( asctime( &timeinfo ) );
}
#endif
}
#endif
void heartBeatPrint()
{
#if USE_ESP_WIFIMANAGER_NTP
printLocalTime();
#else
static int num = 1;
if (WiFi.status() == WL_CONNECTED)
Serial.print(F("H")); // H means connected to WiFi
else
Serial.print(F("F")); // F means not connected to WiFi
if (num == 80)
{
Serial.println();
num = 1;
}
else if (num++ % 10 == 0)
{
Serial.print(F(" "));
}
#endif
}
void publishMQTT()
{
float some_number = 25.0 + (float) ( millis() % 100 ) / 100;
// For debug only
//Serial.print(F("Published Temp = "));
//Serial.println(some_number);
MQTT_connect();
if (Temperature->publish(some_number))
{
Serial.print(F("T")); // T means publishing OK
}
else
{
Serial.print(F("F")); // F means publishing failure
}
}
void check_WiFi()
{
if ( (WiFi.status() != WL_CONNECTED) )
{
Serial.println(F("\nWiFi lost. Call connectMultiWiFi in loop"));
connectMultiWiFi();
}
}
void check_status()
{
static ulong checkstatus_timeout = 0;
static ulong LEDstatus_timeout = 0;
static ulong checkwifi_timeout = 0;
static ulong mqtt_publish_timeout = 0;
ulong current_millis = millis();
#define WIFICHECK_INTERVAL 1000L
#if USE_ESP_WIFIMANAGER_NTP
#define HEARTBEAT_INTERVAL 60000L
#else
#define HEARTBEAT_INTERVAL 10000L
#endif
#define LED_INTERVAL 2000L
#define PUBLISH_INTERVAL 70000L
// Check WiFi every WIFICHECK_INTERVAL (1) seconds.
if ((current_millis > checkwifi_timeout) || (checkwifi_timeout == 0))
{
check_WiFi();
checkwifi_timeout = current_millis + WIFICHECK_INTERVAL;
}
if ((current_millis > LEDstatus_timeout) || (LEDstatus_timeout == 0))
{
// Toggle LED at LED_INTERVAL = 2s
toggleLED();
LEDstatus_timeout = current_millis + LED_INTERVAL;
}
// Print hearbeat every HEARTBEAT_INTERVAL (10) seconds.
if ((current_millis > checkstatus_timeout) || (checkstatus_timeout == 0))
{
heartBeatPrint();
checkstatus_timeout = current_millis + HEARTBEAT_INTERVAL;
}
// Check every PUBLISH_INTERVAL (60) seconds.
if ((current_millis > mqtt_publish_timeout) || (mqtt_publish_timeout == 0))
{
if (WiFi.status() == WL_CONNECTED)
{
publishMQTT();
}
mqtt_publish_timeout = current_millis + PUBLISH_INTERVAL;
}
}
int calcChecksum(uint8_t* address, uint16_t sizeToCalc)
{
uint16_t checkSum = 0;
for (uint16_t index = 0; index < sizeToCalc; index++)
{
checkSum += * ( ( (byte*) address ) + index);
}
return checkSum;
}
bool loadConfigData()
{
File file = FileFS.open(CONFIG_FILENAME, "r");
LOGERROR(F("LoadWiFiCfgFile "));
memset((void *) &WM_config, 0, sizeof(WM_config));
// New in v1.4.0
memset((void *) &WM_STA_IPconfig, 0, sizeof(WM_STA_IPconfig));
//////
if (file)
{
file.readBytes((char *) &WM_config, sizeof(WM_config));
// New in v1.4.0
file.readBytes((char *) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
//////
file.close();
LOGERROR(F("OK"));
if ( WM_config.checksum != calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) ) )
{
LOGERROR(F("WM_config checksum wrong"));
return false;
}
// New in v1.4.0
displayIPConfigStruct(WM_STA_IPconfig);
//////
return true;
}
else
{
LOGERROR(F("failed"));
return false;
}
}
void saveConfigData()
{
File file = FileFS.open(CONFIG_FILENAME, "w");
LOGERROR(F("SaveWiFiCfgFile "));
if (file)
{
WM_config.checksum = calcChecksum( (uint8_t*) &WM_config, sizeof(WM_config) - sizeof(WM_config.checksum) );
file.write((uint8_t*) &WM_config, sizeof(WM_config));
displayIPConfigStruct(WM_STA_IPconfig);
// New in v1.4.0
file.write((uint8_t*) &WM_STA_IPconfig, sizeof(WM_STA_IPconfig));
//////
file.close();
LOGERROR(F("OK"));
}
else
{
LOGERROR(F("failed"));
}
}
void deleteOldInstances()
{
// Delete previous instances
if (mqtt)
{
delete mqtt;
mqtt = NULL;
Serial.println(F("Deleting old MQTT object"));
}
if (Temperature)
{
delete Temperature;
Temperature = NULL;
Serial.println(F("Deleting old Temperature object"));
}
}
void createNewInstances()
{
if (!client)
{
client = new WiFiClient;
Serial.print(F("\nCreating new WiFi client object : "));
Serial.println(client? F("OK") : F("failed"));
}
// Create new instances from new data
if (!mqtt)
{
// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
mqtt = new Adafruit_MQTT_Client(client, custom_AIO_SERVER, atoi(custom_AIO_SERVERPORT), custom_AIO_USERNAME, custom_AIO_KEY);
Serial.print(F("Creating new MQTT object : "));
if (mqtt)
{
Serial.println(F("OK"));
Serial.println(String("AIO_SERVER = ") + custom_AIO_SERVER + ", AIO_SERVERPORT = " + custom_AIO_SERVERPORT);
Serial.println(String("AIO_USERNAME = ") + custom_AIO_USERNAME + ", AIO_KEY = " + custom_AIO_KEY);
}
else
Serial.println(F("Failed"));
}
if (!Temperature)
{
Serial.print(F("Creating new MQTT_Pub_Topic, Temperature = "));
Serial.println(MQTT_Pub_Topic);
Temperature = new Adafruit_MQTT_Publish(mqtt, MQTT_Pub_Topic.c_str());
Serial.print(F("Creating new Temperature object : "));
if (Temperature)
{
Serial.println(F("OK"));
Serial.println(String("Temperature MQTT_Pub_Topic = ") + MQTT_Pub_Topic);
}
else
Serial.println(F("Failed"));
}
}
void wifi_manager()
{
Serial.println(F("\nConfig Portal requested."));
digitalWrite(LED_BUILTIN, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.
//Local intialization. Once its business is done, there is no need to keep it around
// Use this to default DHCP hostname to ESP8266-XXXXXX or ESP32-XXXXXX
//ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer);
// Use this to personalize DHCP hostname (RFC952 conformed)
AsyncWebServer webServer(HTTP_PORT);
#if ( USING_ESP32_S2 || USING_ESP32_C3 )
ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, NULL, "ConfigOnDRD-FS-MQTT");
#else
AsyncDNSServer dnsServer;
ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "ConfigOnDRD-FS-MQTT");
#endif
//Check if there is stored WiFi router/password credentials.
//If not found, device will remain in configuration mode until switched off via webserver.
Serial.print(F("Opening Configuration Portal. "));
Router_SSID = ESPAsync_wifiManager.WiFi_SSID();
Router_Pass = ESPAsync_wifiManager.WiFi_Pass();
// From v1.1.1, Don't permit NULL password
if ( !initialConfig && (Router_SSID != "") && (Router_Pass != "") )
{
//If valid AP credential and not DRD, set timeout 120s.
ESPAsync_wifiManager.setConfigPortalTimeout(120);
Serial.println("Got stored Credentials. Timeout 120s");
}
else
{
ESPAsync_wifiManager.setConfigPortalTimeout(0);
Serial.print(F("No timeout : "));
if (initialConfig)
{
Serial.println(F("DRD or No stored Credentials.."));
}
else
{
Serial.println(F("No stored Credentials."));
}
}
// Extra parameters to be configured
// After connecting, parameter.getValue() will get you the configured value
// Format: <ID> <Placeholder text> <default value> <length> <custom HTML> <label placement>
// (*** we are not using <custom HTML> and <label placement> ***)
// AIO_SERVER
ESPAsync_WMParameter AIO_SERVER_FIELD(AIO_SERVER_Label, "AIO SERVER", custom_AIO_SERVER, custom_AIO_SERVER_LEN + 1);
// AIO_SERVERPORT
ESPAsync_WMParameter AIO_SERVERPORT_FIELD(AIO_SERVERPORT_Label, "AIO SERVER PORT", custom_AIO_SERVERPORT, custom_AIO_PORT_LEN + 1);
// AIO_USERNAME
ESPAsync_WMParameter AIO_USERNAME_FIELD(AIO_USERNAME_Label, "AIO USERNAME", custom_AIO_USERNAME, custom_AIO_USERNAME_LEN + 1);
// AIO_KEY
ESPAsync_WMParameter AIO_KEY_FIELD(AIO_KEY_Label, "AIO KEY", custom_AIO_KEY, custom_AIO_KEY_LEN + 1);
// add all parameters here
// order of adding is not important
ESPAsync_wifiManager.addParameter(&AIO_SERVER_FIELD);
ESPAsync_wifiManager.addParameter(&AIO_SERVERPORT_FIELD);
ESPAsync_wifiManager.addParameter(&AIO_USERNAME_FIELD);
ESPAsync_wifiManager.addParameter(&AIO_KEY_FIELD);
// Sets timeout in seconds until configuration portal gets turned off.
// If not specified device will remain in configuration mode until
// switched off via webserver or device is restarted.
//ESPAsync_wifiManager.setConfigPortalTimeout(120);
ESPAsync_wifiManager.setMinimumSignalQuality(-1);
// From v1.0.10 only
// Set config portal channel, default = 1. Use 0 => random channel from 1-13
ESPAsync_wifiManager.setConfigPortalChannel(0);
//////
#if USE_CUSTOM_AP_IP
//set custom ip for portal
// New in v1.4.0
ESPAsync_wifiManager.setAPStaticIPConfig(WM_AP_IPconfig);
//////
#endif
#if !USE_DHCP_IP
// Set (static IP, Gateway, Subnetmask, DNS1 and DNS2) or (IP, Gateway, Subnetmask). New in v1.0.5
// New in v1.4.0
ESPAsync_wifiManager.setSTAStaticIPConfig(WM_STA_IPconfig);
//////
#endif
// New from v1.1.1
#if USING_CORS_FEATURE
ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
#endif
// Start an access point
// and goes into a blocking loop awaiting configuration.
// Once the user leaves the portal with the exit button
// processing will continue
// SSID to uppercase
ssid.toUpperCase();
password = "My" + ssid;
Serial.print(F("Starting configuration portal @ "));
#if USE_CUSTOM_AP_IP
Serial.print(APStaticIP);
#else
Serial.print(F("192.168.4.1"));
#endif
Serial.print(F(", SSID = "));
Serial.print(ssid);
Serial.print(F(", PWD = "));
Serial.println(password);
#if DISPLAY_STORED_CREDENTIALS_IN_CP
// New. Update Credentials, got from loadConfigData(), to display on CP
ESPAsync_wifiManager.setCredentials(WM_config.WiFi_Creds[0].wifi_ssid, WM_config.WiFi_Creds[0].wifi_pw,
WM_config.WiFi_Creds[1].wifi_ssid, WM_config.WiFi_Creds[1].wifi_pw);
#endif
if (!ESPAsync_wifiManager.startConfigPortal((const char *) ssid.c_str(), password.c_str()))
{
Serial.println(F("Not connected to WiFi but continuing anyway."));
}
else
{
// If you get here you have connected to the WiFi
Serial.println(F("Connected...yeey :)"));
Serial.print(F("Local IP: "));
Serial.println(WiFi.localIP());
}
// Only clear then save data if CP entered and with new valid Credentials
// No CP => stored getSSID() = ""
if ( String(ESPAsync_wifiManager.getSSID(0)) != "" && String(ESPAsync_wifiManager.getSSID(1)) != "" )
{
// Stored for later usage, from v1.1.0, but clear first
memset(&WM_config, 0, sizeof(WM_config));
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
{
String tempSSID = ESPAsync_wifiManager.getSSID(i);
String tempPW = ESPAsync_wifiManager.getPW(i);
if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
else
strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
else
strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
{
LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
}
}
#if USE_ESP_WIFIMANAGER_NTP
String tempTZ = ESPAsync_wifiManager.getTimezoneName();
if (strlen(tempTZ.c_str()) < sizeof(WM_config.TZ_Name) - 1)
strcpy(WM_config.TZ_Name, tempTZ.c_str());
else
strncpy(WM_config.TZ_Name, tempTZ.c_str(), sizeof(WM_config.TZ_Name) - 1);
const char * TZ_Result = ESPAsync_wifiManager.getTZ(WM_config.TZ_Name);
if (strlen(TZ_Result) < sizeof(WM_config.TZ) - 1)
strcpy(WM_config.TZ, TZ_Result);
else
strncpy(WM_config.TZ, TZ_Result, sizeof(WM_config.TZ_Name) - 1);
if ( strlen(WM_config.TZ_Name) > 0 )
{
LOGERROR3(F("Saving current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
#if ESP8266
configTime(WM_config.TZ, "pool.ntp.org");
#else
//configTzTime(WM_config.TZ, "pool.ntp.org" );
configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
#endif
}
else
{
LOGERROR(F("Current Timezone Name is not set. Enter Config Portal to set."));
}
#endif
// New in v1.4.0
ESPAsync_wifiManager.getSTAStaticIPConfig(WM_STA_IPconfig);
//////
saveConfigData();
}
// Getting posted form values and overriding local variables parameters
// Config file is written regardless the connection state
strcpy(custom_AIO_SERVER, AIO_SERVER_FIELD.getValue());
strcpy(custom_AIO_SERVERPORT, AIO_SERVERPORT_FIELD.getValue());
strcpy(custom_AIO_USERNAME, AIO_USERNAME_FIELD.getValue());
strcpy(custom_AIO_KEY, AIO_KEY_FIELD.getValue());
// Writing JSON config file to flash for next boot
writeConfigFile();
digitalWrite(LED_BUILTIN, LED_OFF); // Turn LED off as we are not in configuration mode.
deleteOldInstances();
MQTT_Pub_Topic = String(custom_AIO_USERNAME) + "/feeds/Temperature";
createNewInstances();
}
bool readConfigFile()
{
// this opens the config file in read-mode
File f = FileFS.open(CONFIG_FILE, "r");
if (!f)
{
Serial.println(F("Config File not found"));
return false;
}
else
{
// we could open the file
size_t size = f.size();
// Allocate a buffer to store contents of the file.
std::unique_ptr<char[]> buf(new char[size + 1]);
// Read and store file contents in buf
f.readBytes(buf.get(), size);
// Closing file
f.close();
// Using dynamic JSON buffer which is not the recommended memory model, but anyway
// See https://github.com/bblanchon/ArduinoJson/wiki/Memory%20model
#if (ARDUINOJSON_VERSION_MAJOR >= 6)
DynamicJsonDocument json(1024);
auto deserializeError = deserializeJson(json, buf.get());
if ( deserializeError )
{
Serial.println(F("JSON parseObject() failed"));
return false;
}
serializeJson(json, Serial);
#else
DynamicJsonBuffer jsonBuffer;
// Parse JSON string
JsonObject& json = jsonBuffer.parseObject(buf.get());
// Test if parsing succeeds.
if (!json.success())
{
Serial.println(F("JSON parseObject() failed"));
return false;
}
json.printTo(Serial);
#endif
// Parse all config file parameters, override
// local config variables with parsed values
if (json.containsKey(AIO_SERVER_Label))
{
strcpy(custom_AIO_SERVER, json[AIO_SERVER_Label]);
}
if (json.containsKey(AIO_SERVERPORT_Label))
{
strcpy(custom_AIO_SERVERPORT, json[AIO_SERVERPORT_Label]);
}
if (json.containsKey(AIO_USERNAME_Label))
{
strcpy(custom_AIO_USERNAME, json[AIO_USERNAME_Label]);
}
if (json.containsKey(AIO_KEY_Label))
{
strcpy(custom_AIO_KEY, json[AIO_KEY_Label]);
}
}
Serial.println(F("\nConfig File successfully parsed"));
return true;
}
bool writeConfigFile()
{
Serial.println(F("Saving Config File"));
#if (ARDUINOJSON_VERSION_MAJOR >= 6)
DynamicJsonDocument json(1024);
#else
DynamicJsonBuffer jsonBuffer;
JsonObject& json = jsonBuffer.createObject();
#endif
// JSONify local configuration parameters
json[AIO_SERVER_Label] = custom_AIO_SERVER;
json[AIO_SERVERPORT_Label] = custom_AIO_SERVERPORT;
json[AIO_USERNAME_Label] = custom_AIO_USERNAME;
json[AIO_KEY_Label] = custom_AIO_KEY;
// Open file for writing
File f = FileFS.open(CONFIG_FILE, "w");
if (!f)
{
Serial.println(F("Failed to open Config File for writing"));
return false;
}
#if (ARDUINOJSON_VERSION_MAJOR >= 6)
serializeJsonPretty(json, Serial);
// Write data to file and close it
serializeJson(json, f);
#else
json.prettyPrintTo(Serial);
// Write data to file and close it
json.printTo(f);
#endif
f.close();
Serial.println(F("\nConfig File successfully saved"));
return true;
}
// this function is just to display newly saved data,
// it is not necessary though, because data is displayed
// after WiFi manager resets ESP32
void newConfigData()
{
Serial.println();
Serial.print(F("custom_AIO_SERVER: "));
Serial.println(custom_AIO_SERVER);
Serial.print(F("custom_SERVERPORT: "));
Serial.println(custom_AIO_SERVERPORT);
Serial.print(F("custom_USERNAME_KEY: "));
Serial.println(custom_AIO_USERNAME);
Serial.print(F("custom_KEY: "));
Serial.println(custom_AIO_KEY);
Serial.println();
}
void MQTT_connect()
{
int8_t ret;
MQTT_Pub_Topic = String(custom_AIO_USERNAME) + "/feeds/Temperature";
createNewInstances();
// Return if already connected
if (mqtt->connected())
{
return;
}
Serial.println(F("Connecting to MQTT (3 attempts)..."));
uint8_t attempt = 3;
while ((ret = mqtt->connect()) != 0)
{
// connect will return 0 for connected
Serial.println(mqtt->connectErrorString(ret));
Serial.println(F("Another attemtpt to connect to MQTT in 2 seconds..."));
mqtt->disconnect();
delay(2000); // wait 2 seconds
attempt--;
if (attempt == 0)
{
Serial.println(F("MQTT connection failed. Continuing with program..."));
return;
}
}
Serial.println(F("MQTT connection successful!"));
}
// Setup function
void setup()
{
// Initialize the LED digital pin as an output.
pinMode(LED_BUILTIN, OUTPUT);
// Put your setup code here, to run once
Serial.begin(115200);
while (!Serial);
delay(200);
Serial.print(F("\nStarting Async_ConfigOnDRD_FS_MQTT_Ptr using ")); Serial.print(FS_Name);
Serial.print(F(" on ")); Serial.println(ARDUINO_BOARD);
Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
Serial.println(ESP_DOUBLE_RESET_DETECTOR_VERSION);
#if defined(ESP_ASYNC_WIFIMANAGER_VERSION_INT)
if (ESP_ASYNC_WIFIMANAGER_VERSION_INT < ESP_ASYNC_WIFIMANAGER_VERSION_MIN)
{
Serial.print("Warning. Must use this example on Version later than : ");
Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION_MIN_TARGET);
}
#endif
Serial.setDebugOutput(false);
// Mount the filesystem
if (FORMAT_FILESYSTEM)
{
Serial.println(F("Forced Formatting."));
FileFS.format();
}
// Format FileFS if not yet
#ifdef ESP32
if (!FileFS.begin(true))
#else
if (!FileFS.begin())
#endif
{
#ifdef ESP8266
FileFS.format();
#endif
Serial.println(F("SPIFFS/LittleFS failed! Already tried formatting."));
if (!FileFS.begin())
{
// prevents debug info from the library to hide err message.
delay(100);
#if USE_LITTLEFS
Serial.println(F("LittleFS failed!. Please use SPIFFS or EEPROM. Stay forever"));
#else
Serial.println(F("SPIFFS failed!. Please use LittleFS or EEPROM. Stay forever"));
#endif
while (true)
{
delay(1);
}
}
}
// New in v1.4.0
initAPIPConfigStruct(WM_AP_IPconfig);
initSTAIPConfigStruct(WM_STA_IPconfig);
//////
if (!readConfigFile())
{
Serial.println(F("Can't read Config File, using default values"));
}
drd = new DoubleResetDetector(DRD_TIMEOUT, DRD_ADDRESS);
if (!drd)
{
Serial.println(F("Can't instantiate. Disable DRD feature"));
}
else if (drd->detectDoubleReset())
{
// DRD, disable timeout.
//ESPAsync_wifiManager.setConfigPortalTimeout(0);
Serial.println(F("Open Config Portal without Timeout: Double Reset Detected"));
initialConfig = true;
}
if (initialConfig)
{
loadConfigData();
wifi_manager();
}
else
{
// Pretend CP is necessary as we have no AP Credentials
initialConfig = true;
// Load stored data, the addAP ready for MultiWiFi reconnection
if (loadConfigData())
{
#if USE_ESP_WIFIMANAGER_NTP
if ( strlen(WM_config.TZ_Name) > 0 )
{
LOGERROR3(F("Current TZ_Name ="), WM_config.TZ_Name, F(", TZ = "), WM_config.TZ);
#if ESP8266
configTime(WM_config.TZ, "pool.ntp.org");
#else
//configTzTime(WM_config.TZ, "pool.ntp.org" );
configTzTime(WM_config.TZ, "time.nist.gov", "0.pool.ntp.org", "1.pool.ntp.org");
#endif
}
else
{
Serial.println(F("Current Timezone is not set. Enter Config Portal to set."));
}
#endif
for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
{
// Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
{
LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
initialConfig = false;
}
}
}
if (initialConfig)
{
Serial.println(F("Open Config Portal without Timeout: No stored WiFi Credentials"));
wifi_manager();
}
else if ( WiFi.status() != WL_CONNECTED )
{
Serial.println("ConnectMultiWiFi in setup");
connectMultiWiFi();
}
}
digitalWrite(LED_BUILTIN, LED_OFF); // Turn led off as we are not in configuration mode.
}
// Loop function
void loop()
{
// Call the double reset detector loop method every so often,
// so that it can recognise when the timeout expires.
// You can also call drd.stop() when you wish to no longer
// consider the next reset as a double reset.
if (drd)
drd->loop();
// this is just for checking if we are connected to WiFi
check_status();
}



Debug Terminal Output Samples

1.1 No Config Data => Config Portal

This is terminal debug output when running Async_ConfigOnDRD_FS_MQTT_Ptr_Medium on ESP32 ESP32_DEV.. Config Portal was requested by DRD to input and save MQTT Credentials. The boards then connected to Adafruit MQTT Server successfully.

Starting Async_ConfigOnDRD_FS_MQTT_Ptr_Medium using LittleFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
Config File not found
Can't read Config File, using default values
LittleFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected

Config Portal requested.
Opening Configuration Portal. No timeout : DRD or No stored Credentials..
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
1.2. Config Portal Done
Starting Async_ConfigOnDRD_FS_MQTT_Ptr_Medium using LittleFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
Config File not found
Can't read Config File, using default values
LittleFS Flag read = 0xd0d04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] LoadWiFiCfgFile 
[WM] failed
Open Config Portal without Timeout: No stored WiFi Credentials

Config Portal requested.
[WM] RFC925 Hostname = ConfigOnSwichFS-MQTT
Opening Configuration Portal. No timeout : DRD or No stored Credentials..
[WM] Adding parameter AIO_SERVER_Label
[WM] Adding parameter AIO_SERVERPORT_Label
[WM] Adding parameter AIO_USERNAME_Label
[WM] Adding parameter AIO_KEY_Label
[WM] setAPStaticIPConfig
[WM] setSTAStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
[WM] WiFi.waitForConnectResult Done
[WM] SET AP
[WM] 
Configuring AP SSID = ESP_85288
[WM] AP PWD = your_password
[WM] AP Channel = 9
[WM] Custom AP IP/GW/Subnet =  192.168.100.1 192.168.100.1 255.255.255.0
[WM] AP IP address = 192.168.100.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Connecting to new AP
[WM] Previous settings invalidated
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.235
[WM] Connect to new WiFi using new IP parameters
[WM] Connected after waiting (s) : 0.60
[WM] Local ip = 192.168.2.235
[WM] Connection result:  WL_CONNECTED
Connected...yeey :)
Local IP: 192.168.2.235
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] getSTAStaticIPConfig
[WM] stationIP = 192.168.2.235 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] SaveWiFiCfgFile 
[WM] OK
Saving Config File
{
  "AIO_SERVER_Label": "io.adafruit.com",
  "AIO_SERVERPORT_Label": "1883",
  "AIO_USERNAME_Label": "user_name",
  "AIO_KEY_Label": "aio_key"
}
Config File successfully saved

Creating new WiFi client object : OK
Creating new MQTT object : OK
AIO_SERVER = io.adafruit.com, AIO_SERVERPORT = 1883
AIO_USERNAME = user_name, AIO_KEY = aio_key
Creating new MQTT_Pub_Topic,  Temperature = user_name/feeds/Temperature
Creating new Temperature object : OK
Temperature MQTT_Pub_Topic = user_name/feeds/Temperature
[WM] freeing allocated params!
Stop doubleResetDetecting
Saving config file...
Saving config file OK
WConnecting to MQTT (3 attempts)...
MQTT connection successful!
TWWWW 

2. Async_ConfigOnDRD_FS_MQTT_Ptr_Complex on ESP8266_NODEMCU_ESP12E

This is terminal debug output when running Async_ConfigOnDRD_FS_MQTT_Ptr_Complex on ESP8266_NODEMCU_ESP12E 1.0.. Config Portal was requested to input and save MQTT Credentials. The boards then connected to Adafruit MQTT Server successfully.

2.1 With Config Data => Run normally
Starting Async_ConfigOnDRD_FS_MQTT_Ptr_Complex using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
{"AIO_SERVER_Label":"io.adafruit.com","AIO_SERVERPORT_Label":"1883","AIO_USERNAME_Label":"user_name","AIO_KEY_Label":"aio_key"}
Config File successfully parsed
LittleFS Flag read = 0xd0d04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 192.168.2.188 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet2 , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -32
[WM] Channel: 2 ,IP address: 192.168.2.188
W
Creating new WiFi client object : OK
Creating new MQTT object : OK
AIO_SERVER = io.adafruit.com, AIO_SERVERPORT = 1883
AIO_USERNAME = user_name, AIO_KEY = aio_key
Creating new MQTT_Pub_Topic,  Temperature = user_name/feeds/Temperature
Creating new Temperature object : OK
Temperature MQTT_Pub_Topic = user_name/feeds/Temperature
Connecting to MQTT (3 attempts)...
MQTT connection successful!
TWWWW WTWWW
2.2. DRD => Config Portal
Starting Async_ConfigOnDRD_FS_MQTT_Ptr_Complex using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
{"AIO_SERVER_Label":"io.adafruit.com","AIO_SERVERPORT_Label":"1883","AIO_USERNAME_Label":"user_name","AIO_KEY_Label":"aio_key"}
Config File successfully parsed
LittleFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected

Config Portal requested.
[WM] RFC925 Hostname = ConfigOnSwichFS-MQTT
Opening Configuration Portal. No timeout : DRD or No stored Credentials..
[WM] Adding parameter AIO_KEY_Label
[WM] Adding parameter AIO_SERVER_Label
[WM] Adding parameter AIO_SERVERPORT_Label
[WM] Adding parameter AIO_USERNAME_Label
[WM] setAPStaticIPConfig
[WM] setSTAStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
[WM] WiFi.waitForConnectResult Done
[WM] SET AP
[WM] 
Configuring AP SSID = ESP_702FF3
[WM] AP PWD = your_password
[WM] AP Channel = 1
[WM] Custom AP IP/GW/Subnet =  192.168.100.1 192.168.100.1 255.255.255.0
[WM] AP IP address = 192.168.100.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
2.3. Config Portal Done
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.188
[WM] Connected after waiting (s) : 0.00
[WM] Local ip = 192.168.2.188
[WM] Timed out connection result: WL_IDLE_STATUS
Not connected to WiFi but continuing anyway.
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] getSTAStaticIPConfig
[WM] stationIP = 192.168.2.188 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] SaveWiFiCfgFile 
[WM] OK
Saving Config File
{
  "AIO_KEY_Label": "aio_key",
  "AIO_SERVER_Label": "io.adafruit.com",
  "AIO_SERVERPORT_Label": "1883",
  "AIO_USERNAME_Label": "user_name"
}
Config File successfully saved

Creating new WiFi client object : OK
Creating new MQTT object : OK
AIO_SERVER = io.adafruit.com, AIO_SERVERPORT = 1883
AIO_USERNAME = user_name, AIO_KEY = aio_key
Creating new MQTT_Pub_Topic,  Temperature = user_name/feeds/Temperature
Creating new Temperature object : OK
Temperature MQTT_Pub_Topic = user_name/feeds/Temperature
[WM] freeing allocated params!

WiFi lost. Call connectMultiWiFi in loop
[WM] ConnectMultiWiFi with :
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet2 , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -34
[WM] Channel: 2 ,IP address: 192.168.2.188
WConnecting to MQTT (3 attempts)...
MQTT connection successful!
TWW

This is terminal debug output when running Async_ConfigOnDoubleReset on ESP32 ESP32_DEV.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully. WiFi AP HueNet1 is then lost, and board autoreconnects itself to backup WiFi AP HueNet2.

Starting Async_ConfigOnDoubleReset with DoubleResetDetect using SPIFFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
[WM] RFC925 Hostname = ConfigOnDoubleReset
[WM] setSTAStaticIPConfig for USE_CONFIGURABLE_DNS
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got stored Credentials. Timeout 120s for Config Portal
SPIFFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
Starting configuration portal.
[WM] WiFi.waitForConnectResult Done
[WM] SET AP
[WM] 
Configuring AP SSID = ESP_E92DE6B4
[WM] AP PWD = your_password
[WM] AP Channel = 3
[WM] AP IP address = 192.168.4.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Connecting to new AP
[WM] Previous settings invalidated
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.232
[WM] Connect to new WiFi using new IP parameters
[WM] Connected after waiting (s) : 0.60
[WM] Local ip = 192.168.2.232
[WM] Connection result:  WL_CONNECTED
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] SaveWiFiCfgFile 
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.232
[WM] freeing allocated params!
HH
WiFi lost. Call connectMultiWiFi in loop
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  12345678
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet2 , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  2
[WM] SSID: HueNet2 ,RSSI= -51
[WM] Channel: 4 ,IP address: 192.168.2.232
HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH

4. Async_ConfigOnDoubleReset on ESP8266_NODEMCU_ESP12E

This is terminal debug output when running Async_ConfigOnDoubleReset on ESP8266_NODEMCU_ESP12E.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully. WiFi AP HueNet1 is then lost, and board autoreconnects itself to backup WiFi AP HueNet2.

Starting Async_ConfigOnDoubleReset with DoubleResetDetect using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
[WM] RFC925 Hostname = ConfigOnDoubleReset
[WM] setSTAStaticIPConfig for USE_CONFIGURABLE_DNS
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
Starting configuration portal.
[WM] WiFi.waitForConnectResult Done
[WM] SET AP_STA
[WM] 
Configuring AP SSID = ESP_119055
[WM] AP PWD = your_password
[WM] AP Channel = 5
[WM] AP IP address = 192.168.4.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Connecting to new AP
[WM] Previous settings invalidated
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.186
[WM] Connect to new WiFi using new IP parameters
[WM] Connected after waiting (s) : 3.23
[WM] Local ip = 192.168.2.186
[WM] Connection result:  WL_CONNECTED
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] SaveWiFiCfgFile 
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.186
[WM] freeing allocated params!
HHH
WiFi lost. Call connectMultiWiFi in loop
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  12345678
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet2 , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet2 ,RSSI= -50
[WM] Channel: 4 ,IP address: 192.168.2.186
HHHHHHHHHH HHHHHHHHHH HHH

5. Async_ESP_FSWebServer_DRD on ESP8266_NODEMCU_ESP12E

This is terminal debug output when running Async_ESP_FSWebServer_DRD on ESP8266_NODEMCU_ESP12E.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully.

Starting Async_ESP_FSWebServer_DRD using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
Opening / directory
FS File: CanadaFlag_1.png, size: 40.25KB
FS File: CanadaFlag_2.png, size: 8.12KB
FS File: CanadaFlag_3.jpg, size: 10.89KB
FS File: ConfigMQTT.json, size: 151B
FS File: ConfigSW.json, size: 53B
FS File: drd.dat, size: 4B
FS File: edit.htm.gz, size: 4.02KB
FS File: favicon.ico, size: 1.12KB
FS File: graphs.js.gz, size: 1.92KB
FS File: index.htm, size: 3.63KB
FS File: wifi_cred.dat, size: 192B

[WM] RFC925 Hostname = AsyncESP-FSWebServer
[WM] setAPStaticIPConfig
[WM] setSTAStaticIPConfig for USE_CONFIGURABLE_DNS
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
[WM] WiFi.waitForConnectResult Done
[WM] SET AP_STA
[WM] 
Configuring AP SSID = ESP_119055
[WM] AP PWD = your_password
[WM] AP Channel = 11
[WM] Custom AP IP/GW/Subnet =  192.168.100.1 192.168.100.1 255.255.255.0
[WM] AP IP address = 192.168.100.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.186
[WM] Connected after waiting (s) : 0.19
[WM] Local ip = 192.168.2.186
[WM] Timed out connection result: WL_CONNECTED
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] SaveWiFiCfgFile 
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.186
HTTP server started @ 192.168.2.186
===============================================================
Open http://async-esp8266fs.local/edit to see the file browser
Using username = admin and password = admin
===============================================================
[WM] freeing allocated params!
HHHHHH

You can access using the HTTP server IP (http://192.168.2.186) or its mDNS hostname (http://async-esp8266fs.local)

By going to http://192.168.2.186/edit or http://async-esp8266fs.local/edit, you can edit / delete / upload / download any file in the folder


This is terminal debug output when running Async_ESP32_FSWebServer_DRD on ESP32_DEV using newly-supported LittleFS.. Config Portal was requested by DRD (also using LittleFS) to input and save Credentials. The boards then connected to WiFi successfully.

Starting Async_ESP32_FSWebServer_DRD using LittleFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
FS File: /CanadaFlag_1.png, size: 40.25KB
FS File: /CanadaFlag_2.png, size: 8.12KB
FS File: /CanadaFlag_3.jpg, size: 10.89KB
FS File: /Credentials.txt, size: 192B
FS File: /drd.dat, size: 4B
FS File: /edit.htm.gz, size: 4.02KB
FS File: /favicon.ico, size: 1.12KB
FS File: /graphs.js.gz, size: 1.92KB
FS File: /index.htm, size: 3.63KB
FS File: /wifi_cred.dat, size: 192B

[WM] RFC925 Hostname = AsyncESP32-FSWebServer
[WM] setAPStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xd0d04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  12345678
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet2 , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -39
[WM] Channel: 2 ,IP address: 192.168.2.101
After waiting 3.75 secs more in setup(), connection result is connected. Local IP: 192.168.2.101
HTTP server started @ 192.168.2.101
===============================================================
Open http://async-esp32fs.local/edit to see the file browser
Using username = admin and password = admin
===============================================================
[WM] freeing allocated params!
HStop doubleResetDetecting
Saving config file...
Saving config file OK
HHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH
...
Starting ESP32_FSWebServer_DRD using LittleFS on ESP32_DEV
ESPAsync_WiFiManager Version v1.3.0
ESP_DoubleResetDetector Version v1.1.0
FS File: /CanadaFlag_1.png, size: 40.25KB
FS File: /CanadaFlag_2.png, size: 8.12KB
FS File: /CanadaFlag_3.jpg, size: 10.89KB
FS File: /Credentials.txt, size: 192B
FS File: /drd.dat, size: 4B
FS File: /edit.htm.gz, size: 4.02KB
FS File: /favicon.ico, size: 1.12KB
FS File: /graphs.js.gz, size: 1.92KB
FS File: /index.htm, size: 3.63KB
FS File: /wifi_cred.dat, size: 192B

[WM] RFC925 Hostname = AsyncESP32-FSWebServer
[WM] setAPStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  87654321
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xd0d01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
[WM] WiFi.waitForConnectResult Done
[WM] SET AP
[WM] 
Configuring AP SSID = ESP_85288
[WM] AP PWD = your_password
[WM] AP Channel = 8
[WM] Custom AP IP/GW/Subnet =  192.168.100.1 192.168.100.1 255.255.255.0
[WM] AP IP address = 192.168.100.1
[WM] HTTP server started
[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Can't use Custom STA IP/GW/Subnet
[WM] Connected after waiting (s) : 1.50
[WM] Local ip = 192.168.2.101
[WM] Timed out connection result: WL_CONNECTED
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] SaveWiFiCfgFile 
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.101
HTTP server started @ 192.168.2.101
===============================================================
Open http://async-esp32fs.local/edit to see the file browser
Using username = admin and password = admin
===============================================================
[WM] freeing allocated params!
HH

7. Async_ConfigOnDoubleReset on ESP32S2_DEV

This is terminal debug output when running Async_ConfigOnDoubleReset on ESP32S2_DEV.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully.

Starting Async_ConfigOnDoubleReset using LittleFS on ESP32S2_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xD0D01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
Starting configuration portal.
[WM] Connecting to new AP
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet2 , PW =  12345678
[WM] SaveWiFiCfgFile 
[WM] stationIP = 192.168.2.232 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.232
HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH
HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHH

This is terminal debug output when running Async_ConfigOnDoubleReset_TZ on ESP32_DEV.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully, with correct local time, TZ set and using NTP

8.1 DRD => Config Portal

Starting Async_ConfigOnDoubleReset_TZ using LittleFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 192.168.2.232 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
[WM] Current TZ_Name = America/New_York , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
LittleFS Flag read = 0xD0D01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
Starting configuration portal @ 192.168.4.1, SSID = ESP_85288, PWD = MyESP_85288

8.2 Data Saved => Connect to WiFi with correct local time, TZ set and using NTP

[WM] Connecting to new AP
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet2 , PW =  password
[WM] Saving current TZ_Name = America/New_York , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
[WM] SaveWiFiCfgFile 
[WM] stationIP = 192.168.2.232 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.232
Local Date/Time: Fri Oct  7 16:16:03 2022
Local Date/Time: Fri Oct  7 16:17:03 2022
Local Date/Time: Fri Oct  7 16:18:03 2022
Local Date/Time: Fri Oct  7 16:19:03 2022

8.3 Normal running with correct local time, TZ set and using NTP

Starting Async_ConfigOnDoubleReset_TZ using LittleFS on ESP32_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 192.168.2.232 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
[WM] Current TZ_Name = America/New_York , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
LittleFS Flag read = 0xD0D04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet2 , PW =  password
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  password
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet2 , PW =  password
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -40
[WM] Channel: 2 ,IP address: 192.168.2.232
After waiting 10.95 secs more in setup(), connection result is connected. Local IP: 192.168.2.232
Stop doubleResetDetecting
Saving config file...
Saving config file OK
Local Date/Time: Fri Oct  7 16:20:03 2022
Local Date/Time: Fri Oct  7 16:21:03 2022
Local Date/Time: Fri Oct  7 16:22:03 2022

9. Async_ESP_FSWebServer_DRD on ESP8266_NODEMCU_ESP12E

This is terminal debug output when running Async_ESP_FSWebServer_DRD on ESP8266_NODEMCU_ESP12E.. Config Portal was requested by DRD to input and save Credentials. The boards then connected to WiFi using new Static IP successfully, with correct local time, TZ set and using NTP

9.1 DRD => Config Portal

Starting Async_ESP_FSWebServer_DRD using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
Opening / directory
FS File: drd.dat, size: 4B
FS File: wifi_cred.dat, size: 334B

[WM] RFC925 Hostname = AsyncESP-FSWebServer
[WM] setSTAStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 192.168.2.188 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
[WM] Current TZ_Name = America/Toronto , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
LittleFS Flag read = 0xD0D01234
doubleResetDetected
Saving config file...
Saving config file OK
Open Config Portal without Timeout: Double Reset Detected
Starting configuration portal @ 192.168.4.1, SSID = ESP_AB1481, PWD = MyESP_AB1481
[WM] 
Configuring AP SSID = ESP_AB1481
[WM] AP PWD = MyESP_AB1481
[WM] AP Channel = 5
[WM] AP IP address = 192.168.4.1
[WM] HTTP server started
[WM] startConfigPortal : Enter loop

9.2 Data Saved => Connect to WiFi with correct local time, TZ set and using NTP

[WM] Connecting to new AP
[WM] Previous settings invalidated
[WM] Custom STA IP/GW/Subnet
[WM] DNS1 and DNS2 set
[WM] setWifiStaticIP IP = 192.168.2.186
[WM] Connect to new WiFi using new IP parameters
[WM] Connected after waiting (s) : 3.18
[WM] Local ip = 192.168.2.186
[WM] Connection result:  WL_CONNECTED
WiFi connected...yeey :)
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet2 , PW =  password
[WM] Saving current TZ_Name = America/Toronto , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
[WM] getSTAStaticIPConfig
[WM] SaveWiFiCfgFile 
[WM] stationIP = 192.168.2.186 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
[WM] OK
After waiting 0.00 secs more in setup(), connection result is connected. Local IP: 192.168.2.186
HTTP server started @ 192.168.2.186
===============================================================
Open http://192.168.2.186/edit to see the file browser
Using username = admin and password = admin
===============================================================
[WM] freeing allocated params!
Local Date/Time: Fri Oct  7 16:16:03 2022
Local Date/Time: Fri Oct  7 16:17:03 2022
Local Date/Time: Fri Oct  7 16:18:03 2022

9.3 Normal running with correct local time, TZ set and using NTP

Starting Async_ESP_FSWebServer_DRD using LittleFS on ESP8266_NODEMCU_ESP12E
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
Opening / directory
FS File: drd.dat, size: 4B
FS File: wifi_cred.dat, size: 334B

[WM] RFC925 Hostname = AsyncESP-FSWebServer
[WM] setSTAStaticIPConfig
[WM] Set CORS Header to :  Your Access-Control-Allow-Origin
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 192.168.2.186 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
[WM] Current TZ_Name = America/Toronto , TZ =  EST5EDT,M3.2.0,M11.1.0   <======= TZ set
LittleFS Flag read = 0xD0D04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet2 , PW =  password
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  password
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet2 , PW =  password
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -36
[WM] Channel: 2 ,IP address: 192.168.2.186
After waiting 3.48 secs more in setup(), connection result is connected. Local IP: 192.168.2.186
HTTP server started @ 192.168.2.186
===============================================================
Open http://192.168.2.186/edit to see the file browser
Using username = admin and password = admin
===============================================================
[WM] freeing allocated params!
Stop doubleResetDetecting
Saving config file...
Saving config file OK
Local Date/Time: Fri Oct  7 16:19:03 2022
Local Date/Time: Fri Oct  7 16:20:03 2022
Local Date/Time: Fri Oct  7 16:21:03 2022
Local Date/Time: Fri Oct  7 16:22:03 2022

10. Async_ConfigOnDoubleReset_TZ on ESP32C3_DEV using SPIFFS

This is terminal debug output when running Async_ConfigOnDoubleReset_TZ on ESP32C3_DEV using SPIFFS and ESP32 core v2.0.0.

Starting Async_ConfigOnDoubleReset_TZ using SPIFFS on ESP32C3_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = 12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 0.0.0.0 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
[WM] Current TZ_Name = America/New_York , TZ =  EST5EDT,M3.2.0,M11.1.0
SPIFFS Flag read = 0xD0D04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Add SSID =  HueNet , PW =  12345678
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  12345678
[WM] * Add SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet1 , PW =  12345678
[WM] * Additional SSID =  HueNet , PW =  12345678
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  3
[WM] SSID: HueNet ,RSSI= -27
[WM] Channel: 10 ,IP address: 192.168.2.99
After waiting 11.85 secs more in setup(), connection result is connected. Local IP: 192.168.2.99
Stop doubleResetDetecting
Saving config file...
Saving config file OK
Local Date/Time: Fri Oct  7 16:19:03 2022
Local Date/Time: Fri Oct  7 16:20:03 2022
Local Date/Time: Fri Oct  7 16:21:03 2022
Local Date/Time: Fri Oct  7 16:22:03 2022

11. Async_ConfigOnDoubleReset on ESP32S3_DEV using LittleFS

This is terminal debug output when running Async_ConfigOnDoubleReset on ESP32S3_DEV using LittleFS and ESP32 core v2.0.2.

Starting Async_ConfigOnDoubleReset using LittleFS on ESP32S3_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 0.0.0.0 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xD0D04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet , PW =  password
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  password
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet , PW =  password
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -22
[WM] Channel: 2 ,IP address: 192.168.2.83
After waiting 7.70 secs more in setup(), connection result is connected. Local IP: 192.168.2.83
HStop doubleResetDetecting
Saving config file...
Saving config file OK
HHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH HHHHHHHHHH
HHHHHHHHHH HHHHHHHHHH HHH

12. Async_ConfigOnDoubleReset on ESP32C3_DEV using LittleFS

This is terminal debug output when running Async_ConfigOnDoubleReset on ESP32C3_DEV using LittleFS and ESP32 core v2.0.2.

Starting Async_ConfigOnDoubleReset using LittleFS on ESP32C3_DEV
ESPAsync_WiFiManager v1.15.1
ESP_DoubleResetDetector v1.3.2
ESP Self-Stored: SSID = HueNet1, Pass = password
[WM] * Add SSID =  HueNet1 , PW =  password
Got ESP Self-Stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] OK
[WM] stationIP = 0.0.0.0 , gatewayIP = 192.168.2.1
[WM] netMask = 255.255.255.0
[WM] dns1IP = 192.168.2.1 , dns2IP = 8.8.8.8
Got stored Credentials. Timeout 120s for Config Portal
LittleFS Flag read = 0xD0D04321
No doubleResetDetected
Saving config file...
Saving config file OK
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Add SSID =  HueNet2 , PW =  password
ConnectMultiWiFi in setup
[WM] ConnectMultiWiFi with :
[WM] * Flash-stored Router_SSID =  HueNet1 , Router_Pass =  password
[WM] * Add SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet1 , PW =  password
[WM] * Additional SSID =  HueNet2 , PW =  password
[WM] Connecting MultiWifi...
[WM] WiFi connected after time:  1
[WM] SSID: HueNet1 ,RSSI= -19
[WM] Channel: 2 ,IP address: 192.168.2.85
After waiting 8.41 secs more in setup(), connection result is connected. Local IP: 192.168.2.85
HStop doubleResetDetecting
Saving config file...
Saving config file OK
HHH


Debug

Debug is enabled by default on Serial. To disable, add before startConfigPortal()

ESPAsync_wifiManager.setDebugOutput(false);

You can also change the debugging level from 0 to 4

// Use from 0 to 4. Higher number, more debugging messages and memory usage.
#define _ESPASYNC_WIFIMGR_LOGLEVEL_    3

Troubleshooting

If you get compilation errors, more often than not, you may need to install a newer version of the ESP32 / ESP8266 core for Arduino.

Sometimes, the library will only work if you update the ESP32 / ESP8266 core to the latest version because I am using some newly added function.

If you connect to the created configuration Access Point but the ConfigPortal does not show up, just open a browser and type in the IP of the web portal, by default 192.168.4.1.


Issues

Submit issues to: ESPAsync_WiFiManager issues



Contributions and Thanks

  1. Based on and modified from Tzapu, KenTaylor's version, Alan Steremberg's ESPAsyncWiFiManager and Khoi Hoang's ESP_WiFiManager.
  2. Thanks to Hristo Gochkov for great ESPAsyncWebServer Library
  3. Thanks to good work of Miguel Alexandre Wisintainer for working with, developing, debugging and testing.
  4. Thanks to cancodr for requesting an enhancement in Issue #29: Is it possible to use AsyncWebServer.h instead of WebServer.h?, leading to this ESPAsync_WiFiManager Library.
  5. Thanks to Marcel Stör for reporting /close does not close the config portal bug which is fixed in v1.2.0.
  6. Thanks to Vague Rabbit for requesting, collarborating in creating the HOWTO Add Dynamic Parameters.
  7. Thanks to krupis for reporting ESP32 static IP not saved after restarting the device bug which is fixed in v1.4.0.
  8. Thanks to Roshan to report the issue in Error esp_littlefs.c 'utime_p' to fix PIO error in using ESP32 LittleFS with old LittleFS_esp32 v1.0
  9. Thanks to Manuel Capilla for reporting ESP8266 Clear SSID and Pass bug which is fixed and leading to v1.4.2.
  10. Thanks to David Gunzinger for creating merged PR It should be possible to start the ConfigPortal without connecting to WiFI #38.
  11. Thanks to Russell Jahn for reporting ESPAsync_WiFiManager::startConfigPortal() will cause a watchdog timeout when called from a higher-priority task. #39 leading to v1.5.0 and v1.6.0
  12. Thanks to robcazzaro for reporting Minor: examples/Async_ESP32_FSWebServer/ wrongly uses FileFS.begin(true) #47 leading to v1.6.2
  13. Thanks to mattbradford83 for identify, impressively locate, fix the bug and issue PR Allow captive portal to run more than once by closing dnsServer cleanly. #49 leading to v1.6.3
  14. Thanks to yiancar to report the issue and propose a fix in In AP, DNS server always redirects to 192.168.4.1 no matter what APStaticIP is set to. #58 leading to v1.7.1
  15. Thanks to Stephen Lavelle and Ben Peart for requesting enhancement in _timezoneName never getting set? #51 and How to retrieve timezone? #51 leading to new v1.8.0
  16. Thanks to eth0up to make the PR Add support for Wifi hidden SSID scanning. #66 leading to v1.7.4
  17. Thanks to Francisco Trillo for reporting Not working with ESP32 and Core 2.0.1 (or 2.0.0+) #74 leading to v1.9.5
  18. Thanks to Dean Ott for reporting WiFiManager works only on port 80 #75 and providing the solution leading to v1.9.7
  19. Thanks to Twaste for initiate the discussion in Different behaviour using the src_cpp or src_h lib #80 and providing the idea to the solution, to fix multiple-definitions linker error, leading to v1.10.0
  20. Thanks to Zongyi Yang for creating merged PR Fixes Captive Portal hanging depending on active core for AsyncTCP #100 #104.
  21. Thanks to MattiaCC93 for open discussion Help for storing variables in memory (non-volatile) #87 and report the ESP32 chipID bug, leading to v1.14.0
  22. Thanks to slaesh for creating merged PRs
me-no-dev
⭐️⭐️ Hristo Gochkov

Tzapu
⭐️ Tzapu

kentaylor
⭐️ Ken Taylor

alanswx
⭐️ Alan Steremberg

tcpipchip
Miguel Wisintainer

cancodr
cancodr

marcelstoer
Marcel Stör

thewhiterabbit
Vague Rabbit

krupis
krupis

solroshan
Roshan

molillo
Manuel Capilla

pfy
David Gunzinger

russelljahn
Russell Jahn

robcazzaro
robcazzaro

mattbradford83
Matt Bradford

yiancar
yiancar

increpare
Stephen Lavelle

benpeart
Ben Peart

eth0up
eth0up

Frtrillo
Francisco Trillo

deanjott
Dean Ott

Twaste
Twaste

ZongyiYang
Zongyi Yang

MattiaCC93
MattiaCC93

slaesh
slaesh


Contributing

If you want to contribute to this project:

  • Report bugs and errors
  • Ask for enhancements
  • Create issues and pull requests
  • Tell other people about this library

License and credits

  • The library is licensed under MIT

Copyright

Copyright (c) 2020- Khoi Hoang

espasync_wifimanager's People

Contributors

4nd2in avatar khoih-prog avatar marcelstoer avatar mattbradford83 avatar pfy avatar slaesh avatar zongyiyang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

espasync_wifimanager's Issues

connectMultiWifi not declared in this scope...

Good afternoon.

Please check the below log to see full error. None of the examples in this library work.

Removing the "connectMultiWifi" function does indeed fix the error and allows compile but it breaks the program as the WiFi hangs and does not connect.

erbose mode can be enabled via -v, --verbose option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif8266/esp12e.html
PLATFORM: Espressif 8266 (2.6.2) > Espressif ESP8266 ESP-12E
HARDWARE: ESP8266 80MHz, 80KB RAM, 4MB Flash
PACKAGES:
 - framework-arduinoespressif8266 3.20704.0 (2.7.4)
 - tool-esptool 1.413.0 (4.13)
 - tool-esptoolpy 1.20800.0 (2.8.0)
 - toolchain-xtensa 2.40802.200502 (4.8.2)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 35 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <ESP Async WebServer> 1.2.3
|   |-- <ESPAsyncTCP> 1.2.2
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <Hash> 1.0
|   |-- <ESP8266WiFi> 1.0
|-- <ESPAsyncTCP> 1.2.2
|   |-- <ESP8266WiFi> 1.0
|-- <ESPAsyncTCP-esphome> 1.2.3
|   |-- <ESP8266WiFi> 1.0
|-- <ESPAsyncWebServer-esphome> 1.2.7
|   |-- <ESPAsyncTCP-esphome> 1.2.3
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <Hash> 1.0
|   |-- <ESPAsyncTCP> 1.2.2
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <ESP8266WiFi> 1.0
|-- <ESP_WifiManager> 1.1.1
|   |-- <DNSServer> 1.1.1
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <ESP8266WiFi> 1.0
|-- <ESPAsync_WifiManager> 1.1.1
|   |-- <DNSServer> 1.1.1
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <ESP8266WiFi> 1.0
|   |-- <ESP Async WebServer> 1.2.3
|   |   |-- <ESPAsyncTCP> 1.2.2
|   |   |   |-- <ESP8266WiFi> 1.0
|   |   |-- <Hash> 1.0
|   |   |-- <ESP8266WiFi> 1.0
|-- <DNSServer> 1.1.1
|   |-- <ESP8266WiFi> 1.0
|-- <ESP8266mDNS> 1.2
|   |-- <ESP8266WiFi> 1.0
|-- <ESP8266WiFi> 1.0
|-- <LittleFS(esp8266)> 0.1.0
Building in release mode
Compiling .pio\build\esp12e\src\main.cpp.o
src\main.cpp:182:4: warning: #warning Using static IP [-Wcpp]
   #warning Using static IP
    ^
In file included from .pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager.h:592:0,
                 from src\main.cpp:199:
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h:992:3: warning: multi-line comment [-Wcomment]
   // Add option if didn't input/update SSID/PW => Use the previous saved Credentials. \
   ^
In file included from src\main.cpp:82:0:
.pio\libdeps\esp12e\ESPAsyncWebServer-esphome\src/SPIFFSEditor.h:16:101: warning: 'SPIFFS' is deprecated (declared at C:\Users\Tyler\.platformio\packages\framework-arduinoespressif8266\cores\esp8266/FS.h:269): SPIFFS has been deprecated. Please consider moving to LittleFS or other filesystems. [-Wdeprecated-declarations]
     SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
                                                                                                     ^
In file included from .pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager.h:592:0,
                 from src\main.cpp:199:
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h: In member function 'void ESPAsync_WiFiManager::scan()':
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h:557:16: warning: unused variable 'res' [-Wunused-variable]
           bool res=WiFi.getNetworkInfo(i, wifiSSIDs[i].SSID, wifiSSIDs[i].encryptionType, wifiSSIDs[i].RSSI, wifiSSIDs[i].BSSID, wifiSSIDs[i].channel, wifiSSIDs[i].isHidden);
                ^
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h: In member function 'void ESPAsync_WiFiManager::criticalLoop()':
src\main.cpp:48:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define TIME_BETWEEN_MODELESS_SCANS       30000
                                           ^
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h:668:47: note: in expansion of macro 'TIME_BETWEEN_MODELESS_SCANS'
     if (scannow == -1 || millis() > scannow + TIME_BETWEEN_MODELESS_SCANS)
                                               ^
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h: In member function 'boolean ESPAsync_WiFiManager::startConfigPortal(const char*, const char*)':
src\main.cpp:45:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define TIME_BETWEEN_MODAL_SCANS          20000
                                           ^
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h:798:48: note: in expansion of macro 'TIME_BETWEEN_MODAL_SCANS'
     if ( scannow == -1 || millis() > scannow + TIME_BETWEEN_MODAL_SCANS)
                                                ^
In file included from .pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager.h:592:0,
                 from src\main.cpp:199:
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h: In member function 'boolean ESPAsync_WiFiManager::isIp(String)':
.pio\libdeps\esp12e\ESPAsync_WifiManager\src/ESPAsync_WiFiManager-Impl.h:2164:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < str.length(); i++)
                                  ^
src\main.cpp: In function 'void check_WiFi()':
src\main.cpp:267:22: error: 'connectMultiWiFi' was not declared in this scope
     connectMultiWiFi();
                      ^
*** [.pio\build\esp12e\src\main.cpp.o] Error 1  

Single SSID instead of multiple SSIDs

Is it possible to show only single SSID on config portal instead of SSID1 and SSID2 on config portal? Is there any to disable it or we need to make change in src files?

File Not Found error when accessing the config portal the second time

HI ,
When i first connected to a network using the wifi portal it worked as it should when i wanted to change the network credentials for another network (when the first network is not available and esp32 is in AP mode) i get the following response in the static ip address
`File Not Found

URI: /
Method: GET
Arguments: 0`

load config file issue with ESP8266 (LittleFS and SPIFFS)

Hello, I'm using this board, which I can't perfectly identify. I believe the flash size is 1-2MB, based on the Sketch size %, and since using 4MB flash partitions results in failure to begin either format.
esptool.py says Auto-detected Flash size: 2MB.

When I run the example code from Async_ConfigOnSwitch, I see a few things. I've manually censored SSID and password in this serial output:

Stored: SSID = ssid , Pass = password
[WM] * Add SSID =  ssid , PW =  password
Got stored Credentials. Timeout 120s for Config Portal
[WM] LoadWiFiCfgFile 
[WM] failed

So it appears that the last known working configuration is recovered from the esp8266 flash. (As detailed here)
The file system begins correctly, but FileFS.open(CONFIG_FILENAME, "r") returns false.

Then, I run the config portal and input the wifi info! It saves correctly!

[WM] SaveWiFiCfgFile 
[WM] OK

However, if I reset the device, I get the same input for LoadWifiCfgFile as before. file is false, and the load fails. I can't figure out why this is.

I wrote this separate small sketch which simply reads the config file. If I flash this sketch, instead of resetting the Async_ConfigOnSwitch sketch, it properly loads the file and prints it with no issue.

So it appears to only run into this problem only occurs somewhere during Async_ConfigOnSwitch when starting, strangely. It reproduces on both SPIFFS and LittleFS. I'm not entirely convinced it's not my hardware, to be honest.

How to automatics reconnect to the WiFi network if restart the WiFi router?

Is your feature request related to a problem? Please describe.

I getting started to use with "Async_ConfigOnDRD_ESP32_minimal.ino" and it works fine but while ESP32 DevModule(ESP32-WROOM-32) connected to WiFi router but getting the some problem and restart WiFi router, then ESP32 doesn't know it loss connection.

Describe the solution you'd like

I not sure may you already have solution, with my opinion I like to ESP32 automatic disconnect after heartbeat timeout then automatic try to reconnect with some timeout period to the previous connect WiFi AP.

Describe alternatives you've considered

Alternative way is using Asynchronous event on("disconnect") to call some function to re-connect to WiFi router

Additional context

NOTE: If you have any solution for this ideas please suggest me.

Thank you

ESPAsync_WiFiManager::startConfigPortal() will cause a watchdog timeout when called from a higher-priority task.

Hi, first I want to say thank you for this library. It's fantastically well documented. I've also compared the old version of this library to this newer async version, and the improved snappiness of the experience is night & day.

I'm working on fairly complex firmware for a sensor-based project, and can consistently repro a watchdog timeout crash that only happens when startConfigPortal() is called from a task with a priority above the default of 0.

Debugging my firmware, I've simplified the code down to these 2 tasks:

  1. Network Task (Priority of 1). This fires ESPAsync_WiFiManager::startConfigPortal() inside of a task.
  2. Idle Task (Priority of 0). This is the default implicit FreeRTOS task for that feeds the Task watchdog: https://gitdemo.readthedocs.io/en/latest/api/system/wdts.html

I noted that if I decrease the Network Task's priority to 0, the watchdog crash will not happen. This is intuitive if I examine the source code:

  • On line 887 of ESPAsync_WiFiManager.cpp, there's a yield() statement in the spin loop waiting for the ESPAsync_WiFiManager config portal to timeout or be closed.
  • Unlike delay(milliseconds)/vTaskDelay(ticks), which suspends the currently running Task and triggers the Task scheduler to schedule the next available Task, yield() doesn't necessarily suspend the current Task.
  • This would naturally cause a watchdog crash - in my case, the Network Task with a priority of 1 never yields time to the Idle Task do to the yield() in startConfigPortal(). This starves the watchdog and eventually triggering a crash.
  • Decreasing the Network Task's priority to 0 allows the Idle Task to get yielded time and feed the watchdog.
  • And lastly, replacing that yield() with delay() fixes the crash(!)

I'd suggest using delay() in line 887 instead, as that will allow yielding processing time to lower priority tasks. This allows using the library without modifications for more complex projects like mine, which require different task priorities. If you'd like to keep the same default behaviour for existing users, this would be easy to #ifdef with a flag like your other opt-in features.

I'm more than happy to create a PR with the fix if you'd review it. 😃

Portal configuration window not opening

I have been using the ESPAsync_WiFiManager 1.7.1 library on a ESP32 without issues. I then tried using the library on a Wemos D1, the portal opens, information page loads, but the configuration (wifi selection) page is blank.

I tried several different examples from the GitHub. Tried accessing the Portal from another computer, on 192,168.4.1 getting the same result, a blank Configuration page. I tried your ESP_WifiManager and the code/library works.

Boards using:
esp32doit-devkit-v1
d1_mini 8266

Visual Code Studio
Version: 1.55.2
Commit: 3c4e3df9e89829dce27b7b5c24508306b151f30d
Date: 2021-04-13T09:36:32.643Z
Electron: 11.3.0
Chrome: 87.0.4280.141
Node.js: 12.18.3
V8: 8.7.220.31-electron.0
OS: Darwin x64 20.3.0

Thank you for your help.
Glen

Minor: examples/Async_ESP32_FSWebServer/ wrongly uses FileFS.begin(true)

(please also see lorol/LITTLEFS#27 for more context)

I'm using your library and your examples as a starting point for my project. Thanks for sharing this!

I noticed that the following code

// Format SPIFFS if not yet
  if (!FileFS.begin(true))
  {
    Serial.print(FS_Name);
    Serial.println(F(" failed! AutoFormatting."));
  }

seems to assume that FileFS.begin(true) returns false if the SPIFFS was un-initialized and needed to be formatted. In reality that call returns true if the mount has been successful, even if that required an auto-format, false only when the mount fails for whatever reason.

If the debug output is enabled, the LittleFS library debug messages overwrite any debug print from the Arduino thread, causing additional comprehension problems

If the call FileFS.begin(true) fails, that means that there is no SPIFFS, and your example should abort

The above applies to all your examples using SPIFFS for ESP32

Extremely long response time / connection timeouts

Hello!
I would like to share a problem which I have been experiencing now for roughly a week. On my ESP8266, the AsyncWebServer is often responding at a rate which is extremely slow (25s - up to 3 minutes). The sketch being used is a modified example (specifically, the DRD-Esp8266 Webserver). Here is the relevant code for webserver setup:

    webServer.on("/", HTTP_GET, [](AsyncWebServerRequest * request) {
       request->send(200, "text/plain", "hello there!");
    });

    webServer.on("/all", [](AsyncWebServerRequest * request)
    {
      String json('{');
      json += "\"heap\":" + String(ESP.getFreeHeap());
      json += ", \"analog\":" + String(analogRead(A0));
      json += ", \"gpio\":" + String((uint32_t)(((GPI | GPO) & 0xFFFF) | ((GP16I & 0x01) << 16)));
      json += "}";
      request->send(200, "text/json", json);
      json.clear();
    });
    webServer.begin();

When connecting to either "/" or "/all", sometimes the response is extremely quick (3ms) or incredibly slow / times out.
Here are the request headers (they are the same for both pages, and do not change if the response is slow/fast)

GET / HTTP/1.1
Host: 192.168.1.69
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-cache
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Accept-Encoding: gzip, deflate
Accept-Language: en-US,en;q=0.9

Similarily, here is the respone:

HTTP/1.1 200 OK
Content-Length: 12
Content-Type: text/plain
Connection: close
Accept-Ranges: none

The timing console shows that the initial connection hangs (anywhere from instant to 10+ seconds), and then the Waiting(TTFB) hangs for a long time too (10ms --- 5+ minutes).

This happens randomly, and there is no indication that it is caused by memory. The heap available when making requests is consistently at ~32872, and at lowest drops to about 2.9.

If the request does not got through, this is the error:
(failed)net::ERR_CONNECTION_TIMED_OUT

There are no files being served, nothing.
Interestingly, the captive portal almost always works and is always pretty quick to respond.
I'm really confused what could be causing this. Iv'e tested on 2 seperate ESP8266 and both share similar results. As always, I am loving the library.

Trying to install inside Arduino IDE but get error...

Hi, got Arduino IDE 1.8.13 and are using ESP_WiFiManager today with success.
Wanted to update to ESPAsync_WiFiManager but at library install I get following error in A-IDE:

no protocol: java.lang.RuntimeException: java.net.MalformedURLException: no protocol: at cc.arduino.contributions.libraries.ui.LibraryManagerUI.lambda$onInstallPressed$4(LibraryManagerUI.java:248) at java.lang.Thread.run(Thread.java:748) Caused by: java.net.MalformedURLException: no protocol: at java.net.URL.<init>(URL.java:593) at java.net.URL.<init>(URL.java:490) at java.net.URL.<init>(URL.java:439) at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:64) at cc.arduino.contributions.DownloadableContributionsDownloader.download(DownloadableContributionsDownloader.java:60) at cc.arduino.contributions.libraries.LibraryInstaller.performInstall(LibraryInstaller.java:155) at cc.arduino.contributions.libraries.LibraryInstaller.install(LibraryInstaller.java:125) at cc.arduino.contributions.libraries.ui.LibraryManagerUI.lambda$onInstallPressed$4(LibraryManagerUI.java:237) ... 1 more
Any idea what is wrong or how to resolve this ?

Open configuration page when connected to a wifi

Hello,
After connecting to an outside wifi network, I got the IP address of my ESP-32 board.
Can I open the configuration page when my ESP has been connected to a Wifi (not in access point mode)? How can I do that?
Thank you!

Compile Error on Platformio

Hello,

I try to compile the Async_ESP_FSWebServer example. On compiling I get this error:
image

My platformio.ini looks like:

[env:wemos_d1_mini32]
platform = espressif8266
board = d1_mini
board_build.filesystem = littlefs
framework = arduino
monitor_speed = 115200
lib_deps =
ESP Async WebServer
ESPAsyncTCP

What I am missing?

kind regards

DHCP Autoassign hangs and does not properly connect network.

Hello.
I have encountered an issue with this library with the DHCP not automatically assigning an IP/Gateway when the ESP82666 enters Station mode.

Here is a quick rundown of the logs I am receiving:

[WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop
[WM] Connecting to new AP
[WM] Previous settings invalidated
[WM] Can't use Custom STA IP/GW/Subnet
[WM] Connect to new WiFi using new IP parameters
[WM] Connected after waiting (s) : 6.75
[WM] Local ip = (IP unset)
[WM] Connection result:  WL_NO_SSID_AVAIL
[WM] Failed to connect
Not connected to WiFi but continuing anyway.
[WM] * Add SSID =  SSIDNAMEHERE , PW =  networkPW
[WM] SaveWiFiCfgFile
[WM] OK
After waiting 0.00 secs more in setup(), connection result is WL_IDLE_STATUS
HTTP server started @ (IP unset)

After displaying this, it enters a loop without ever managing to gain a connection to the network.

WiFi lost. Call connectMultiWiFi in loop
[WM] ConnectMultiWiFi with :
[WM] * Additional SSID =  SSIDNAMEHERE, PW =  networkPW
[WM] Connecting MultiWifi...
[WM] WiFi not connected
F

Some notable configuration settings:

#define USER_DHCP_IP true

#if ( USE_DHCP_IP || ( defined(USE_STATIC_IP_CONFIG_IN_CP) && !USE_STATIC_IP_CONFIG_IN_CP ) )
  // Use DHCP
  #warning Using DHCP IP
  IPAddress stationIP   = IPAddress(0, 0, 0, 0);
  IPAddress gatewayIP   = IPAddress(192, 168, 1, 0);
  IPAddress netMask     = IPAddress(255, 255, 255, 0);

I have tried many times to re-upload the sketch, wipe the flash, etc. Oddly enough, I had it working at one point and made some modifications to sketch then reuploaded, and it stopped working.

Great library BTW! It's incredibly useful and feature filled.

/close does not close the config portal

I'm using Async_ConfigOnSwitch (1.1.2) unchanged on ESP32.

When I click "Exit Portal" (i.e. request /close) the WiFi Manager remains in config mode until timeout is reached. This is unexpected to me. I expected the config portal to close and for the WiFi Manager to go back to station mode.

In order to exit the config portal I have to hit "Configuration" and then "Save" without entering any values.

Does this work as designed?

Help with example DRD MQTT Medium

First of all, thanks for the work done. I'm not a programmer, so I ask for help.

How to add a subscription and topic poll to example?

Server Connection timeouts on FSWebserver

Hello there.

I have finally got most of this library working.

I'm currently using the "FSWebserver" sketch, pretty much exact. However one thing I have consistently noticed is that the server is often taking too long to respond, thus giving the "ERR_CONNECTION_TIMED_OUT" message on browser (tried IE, chrome, firefox).

I do not have any strange logs, and the heart-beat in the serial monitor remains active even when the server times out.

Another consistent thing that I notice is that it takes a very long time for the files stored in flash to load. I am wondering if maybe littleFS is taking too long to load this data? And if so, how can you increase the keep-alive timeout to allow the files to be rendered? Often times, the HTML and CSS won't load. Or if they do, the images won't. Nothing is cached either, so refreshing the page will often either timeout or something won't load properly.

However... even routes that do-not use littleFS or stuff stored on flash, such as "/heap" timeout as well... no weird logs, nothing comes up in Serial monitor.

Thanks! Keep up the great library. It is so useful.

In which mode ist the WiFiManager?

One question which would help me to make my things easier.
Is there a way to find out it the WiFiManager is:

  • initalizing
  • in AP mode
  • connected to a WiFi network
    (- or maybe doing other weird things)
    ?

ESP 8266 - ConfigPortal in white after few seconds (out of memory)

Before all thanks for this great library!.

### Describe the bug

When board turns on and connects any device, the config portal begin and can be configured a wifi access point but portal close quickly (in a few seconds, less than a minute) because an oom - out of memory (checked with arduino ide debugger), this only occurs when I store a byte variable in RTC memory.

A clear and concise description of what the bug is.

ESP8266-12E board starts in AP, I try to connect to a wifi using the config portal and it works but in a few seconds navigation through pages go blank (unusable) and configportal breaks.. I have checked with Arduino debugger tool and get the following:

16:44:42.468 -> wifi evt: 5
16:44:42.739 -> wifi evt: 9
16:44:42.977 -> wifi evt: 7
16:44:43.011 -> wifi evt: 7
16:44:43.113 -> wifi evt: 7
16:44:43.246 -> :urn 56
16:44:43.246 -> :urd 56, 56, 0
16:44:43.279 -> :urn 60
16:44:43.279 -> :urd 60, 60, 0
16:44:43.756 -> :urn 34
16:44:43.756 -> :urch 62, 53
16:44:43.756 -> :urch 143, 45
16:44:43.756 -> :urd 34, 34, 0
16:44:43.756 -> :urd 53, 53, 0
16:44:43.756 -> :ust rc=-13
16:44:43.791 -> :urd 45, 45, 0
16:44:43.791 -> :ust rc=-13
16:44:44.634 -> :urn 30
16:44:44.634 -> :urd 30, 30, 0
16:44:44.634 -> :ust rc=-13
16:44:44.838 -> :urn 40
16:44:44.838 -> :urd 40, 40, 0
16:44:45.009 -> :urn 38
16:44:45.009 -> :urd 38, 38, 0
16:44:46.625 -> :urn 39
16:44:46.625 -> :urd 39, 39, 0
16:44:47.402 -> :urn 53
16:44:47.402 -> :urd 53, 53, 0
16:44:47.470 -> :urn 45
16:44:47.470 -> :urd 45, 45, 0
16:44:47.604 -> :urn 50
16:44:47.604 -> :urd 50, 50, 0
16:44:48.619 -> :urn 30
16:44:48.619 -> :urd 30, 30, 0
16:44:49.742 -> :urn 36
16:44:49.742 -> :urd 36, 36, 0
16:44:50.449 -> wifi evt: 7
16:44:50.483 -> wifi evt: 7
16:44:50.621 -> :urn 43
16:44:50.621 -> :urd 43, 43, 0
16:44:50.824 -> :urn 31
16:44:50.824 -> :urd 31, 31, 0
16:44:52.750 -> :oom(8784)@WString.cpp:182
16:44:55.118 -> :urn 38
16:44:55.118 -> :urd 38, 38, 0
16:44:56.686 -> :urn 39
16:44:56.686 -> :urd 39, 39, 0
16:45:02.579 -> :oom(8464)@WString.cpp:182
16:45:02.579 -> :oom(8464)@WString.cpp:182
16:45:02.579 -> :oom(8464)@WString.cpp:182
16:45:02.579 -> :oom(8368)@WString.cpp:182
16:45:02.579 -> :oom(8432)@WString.cpp:182

### Steps to Reproduce

Adding to Async_AutoConnect_ESP8266_minimal example sketch a RTC variable with RTCMemory library:

Sketch code:

/****************************************************************************************************************************
Async_AutoConnect_ESP8266_minimal.ino
For ESP8266 / ESP32 boards
Built by Khoi Hoang https://github.com/khoih-prog/ESPAsync_WiFiManager
Licensed under MIT license
*****************************************************************************************************************************/
#if !( defined(ESP8266) )
#error This code is intended to run on ESP8266 platform! Please check your Tools->Board setting.
#endif
#include <ESPAsync_WiFiManager.h> //https://github.com/khoih-prog/ESPAsync_WiFiManager
#include <rtc_memory.h>
AsyncWebServer webServer(80);
DNSServer dnsServer;
#define SERIAL_BAUDRATE 115200
#define LED_1 LED_BUILTIN //Cambiar por pin 4 o el que quiera

typedef struct {
byte estado; //Con esto sabremos si ejecutar estado 1 (servidor OTA) o estado 2 (borra wifis y resetea ESP8266). Este dato está dentro de la estructura de variables que se guarda en la memoria RTC
} MyData;

RtcMemory rtcMemory;
// -----------------------------------------------------------------------------

void setup()
{
// LEDs y Botón
pinMode(LED_1, OUTPUT);
digitalWrite(LED_1, LOW);

// put your setup code here, to run once:
Serial.begin(115200); while (!Serial); delay(200);
Serial.print("\nStarting Async_AutoConnect_ESP8266_minimal on " + String(ARDUINO_BOARD)); Serial.println(ESP_ASYNC_WIFIMANAGER_VERSION);
//RTC Memory
if(rtcMemory.begin()){
Serial.println("RTC initialization done!");
}
else {
Serial.println("No previous data found. The memory is reset to zeros!");
}
// Get the data
MyData* data = rtcMemory.getData();
Serial.println(String("En RTC hay guardado: ") + data->estado);
ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
if (data->estado == 2) {
ESPAsync_wifiManager.resetSettings(); //reset saved settings
data->estado = 0; //Modificamos el contador en RTC
rtcMemory.save(); //Guarda el nuevo estado en memoria RTC
}
//ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192,168,186,1), IPAddress(192,168,186,1), IPAddress(255,255,255,0));
ESPAsync_wifiManager.autoConnect("AutoConnectAP");
if (WiFi.status() == WL_CONNECTED) { Serial.print(F("Connected. Local IP: ")); Serial.println(WiFi.localIP()); }
else { Serial.println(ESPAsync_wifiManager.getStatus(WiFi.status())); }
}

void loop() {

}

### Expected behavior

Espasync_WifiManager config portal doesn't close until a wifi was configured and saved.

### Actual behavior

Configuration portal close fast, it's difficult to to navigate between info page or configure a wifi access successfully (something I've noticed is that even when oom occurs if I was writing my wifi password (doen't update the config page) and save, the connection is successful.

A clear and concise description of what you expected to happen.

Spent the needed time to navigate through the config portal.

### Information

Please ensure to specify the following:

  • Arduino IDE version: 1.8.13
  • ESP8266 core v2.7.3-3-g2843a5ac=20703003
  • Contextual information: Im trying to store a variable in RTC memory to reboot and reset wifi setting when a button is pressed.
  • Operating system: Windows 10 Versión 10.0.18363 compilation 18363
  • EspaSync:WifiManager library version: 1.6.1

Not working when not connected to Serial

The WiFi Manager doesn't work when powering the ESP32 over its VIN Port, but does when powering it through USB. I'm simply using the Code from the Async_AutoConnect_ESP32_minimal.ino example. I already remove the while (!Serial); delay(200); line. Is there a simple fix for this?

Documentation lacking minimal example

Hello and thanks for the library.

The original ESP8266 WifiManager library can be used with default settings using 3 lines of code: 1 include and 2 lines in setup(). (See example: https://github.com/tzapu/WiFiManager/tree/master/examples/AutoConnect). The example with same name in ESPAsync_WiFiManager has whooping 500 lines of code, and it's not immediately clear what it does and what to pull in my code to have default functionality, e.g. start captive portal and connect the board to WiFi without having to hardcode the ESSID/password.
Please, provide a minimal example of this typical usecase, if one is possible.

Non-blocking mode

Any chance the non-blocking option will be available soon?
I was just added to the development branch of the original WiFiManager: https://github.com/tzapu/WiFiManager/tree/development

I think this would be very useful for everyone running devices that should be able to fully operate in STA and AP mode but give the user the ability to switch between those 2 modes on demand.

My programming skills are limited, but if I can help/support to implement this feature I'd be happy to help.

ConfigOnSwitch example flawed?

I think your ConfigOnSwitch example might be flawed but I cannot be exactly sure (yet). The issue is that if the device cannot connect to one of the configured WiFi networks it keeps looping ignoring that pressed button to start the config portal.

I took your example and simplified it for my needs:

  • remove the ESP8266/ESP32 if-defs as I only need ESP32
  • remove the features I don't need
  • refactored duplicated code into dedicated functions
  • put all code into a wifimanager.h that I can use from my main setup()/loop()

-> see Gist https://gist.github.com/marcelstoer/914ff2ac58a42a957dfa071c9c5c8acd
-> use as below

void setup() {
  Serial.begin(115200);

  initWifiManager(String(deviceId));
  log_i("WiFi manager initialized.");
}

void loop() {
  // check button status here (to see if to start config portal)

  // internally checks WiFi connectivity in an interval i.e. not necessarily every time you call
  // this function
  checkWifiStatus();

  // app functions go here
}

As far as I understand the problem is the while-loop in connectMultiWiFi() at https://github.com/khoih-prog/ESPAsync_WiFiManager/blob/master/examples/Async_ConfigOnSwitch/Async_ConfigOnSwitch.ino#L388.

The function sequence is like this: loop() -> check_status() -> check_WiFi() -> connectMultiWiFi(). While trying to connect to one of the WiFis in that while-loop pressing the button to start the config portal has no effect! You would have to press the button for a really long time until the loop ends, the sequence above returns to loop() and the button status is evaluated again.

Connection problem

Hello friend, I would first like to congratulate you on all content shared and always updated with us.

I carried out tests using the Async_ConfigOnSwitch with version 1.4.2 modifying only the type of connection in the code and realized the following problems:
1- Using STA-mode DHCP the station ip is always 255.255.255.255
2 Using STA-mode StaticIP the first connection works fine as DHCP, it also works fine after setting a static IP using the config in AP, but when rebooting it goes back to DHCP. The station ip is changed to default Station IP just by opening and closing the AP.

A tip: I noticed that the original loop is stopped when the wifi is disconnected, to solve this I used multitasking where I put a task for connections and another task for reading sensors.

typedef declaration conflicts

Khoih,

Please be patient, I'm new on platformio and github, so this is probably a very dumb question and not a real issue.

I started experimenting with ESPAsync_WiFiManager. I am having conflicting typedef declaration when trying to build the example Async_ConfigOnSwitch.ino (renamed it main.cpp on vscode). The declarations are on the underlying libraries, please see the build output below.

Do you see anything that I might have missed? Any hints?

Thank you

malves61


> Executing task in folder ESPbrute-digital-sensor-relay-MQTT: pio run <

Processing ESP8266 (platform: espressif8266; framework: arduino; board: d1_mini_pro)

Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif8266/d1_mini_pro.html
PLATFORM: Espressif 8266 (2.6.2) > WeMos D1 mini Pro
HARDWARE: ESP8266 80MHz, 80KB RAM, 16MB Flash
PACKAGES: 
 - framework-arduinoespressif8266 3.20704.7 (2.7.4) 
 - tool-esptool 1.413.0 (4.13) 
 - tool-esptoolpy 1.20800.0 (2.8.0) 
 - toolchain-xtensa 2.40802.200502 (4.8.2)
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 40 compatible libraries
Scanning dependencies...
Dependency Graph
|-- <ESP Async WebServer> 1.2.3
|   |-- <ESPAsyncTCP> 1.2.2
|   |   |-- <ESP8266WiFi> 1.0
|   |-- <Hash> 1.0
|   |-- <ESP8266WiFi> 1.0
|   |-- <ArduinoJson> 6.17.2
|-- <ESPAsyncTCP> 1.2.2
|   |-- <ESP8266WiFi> 1.0
|-- <ESP_DoubleResetDetector> 1.0.3
|   |-- <LittleFS(esp8266)> 0.1.0
|-- <OneButton> 0.0.0-alpha+sha.eb583d713a
|-- <ArduinoJson> 6.17.2
|-- <Adafruit MQTT Library> 2.1.0
|-- <ESPAsync_WiFiManager> 1.3.0
|   |-- <ESP Async WebServer> 1.2.3
|   |   |-- <ESPAsyncTCP> 1.2.2
|   |   |   |-- <ESP8266WiFi> 1.0
|   |   |-- <Hash> 1.0
|   |   |-- <ESP8266WiFi> 1.0
|   |   |-- <ArduinoJson> 6.17.2
|   |-- <ESP_DoubleResetDetector> 1.0.3
|   |   |-- <LittleFS(esp8266)> 0.1.0
|   |-- <DNSServer> 1.1.1
|   |   |-- <WiFi101> 0.16.1
|   |-- <ESP8266WiFi> 1.0
|-- <DNSServer> 1.1.1
|   |-- <WiFi101> 0.16.1
|-- <ESP8266WiFi> 1.0
|-- <LittleFS(esp8266)> 0.1.0
|-- <WiFi101> 0.16.1
Building in release mode
Compiling .pio/build/ESP8266/src/main.cpp.o
src/main.cpp:324:4: warning: #warning Using DHCP IP [-Wcpp]
   #warning Using DHCP IP
    ^
Compiling .pio/build/ESP8266/libb94/ESP8266WiFi/WiFiServerSecureAxTLS.cpp.o
In file included from .pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager.h:597:0,
                 from src/main.cpp:347:
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h:994:3: warning: multi-line comment [-Wcomment]
   // Add option if didn't input/update SSID/PW => Use the previous saved Credentials. \
   ^
Compiling .pio/build/ESP8266/libb94/ESP8266WiFi/WiFiServerSecureBearSSL.cpp.o
Compiling .pio/build/ESP8266/libb94/ESP8266WiFi/WiFiUdp.cpp.o
Compiling .pio/build/ESP8266/libe61/ESPAsyncTCP/AsyncPrinter.cpp.o
Compiling .pio/build/ESP8266/libe61/ESPAsyncTCP/ESPAsyncTCP.cpp.o
Compiling .pio/build/ESP8266/libe61/ESPAsyncTCP/ESPAsyncTCPbuffer.cpp.o
Compiling .pio/build/ESP8266/libe61/ESPAsyncTCP/SyncClient.cpp.o
In file included from .pio/libdeps/ESP8266/WiFi101/src/common/include/nm_common.h:45:0,
                 from .pio/libdeps/ESP8266/WiFi101/src/socket/include/socket.h:60,
                 from .pio/libdeps/ESP8266/WiFi101/src/WiFiUdp.h:24,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/libraries/DNSServer/src/DNSServer.h:3,
                 from src/main.cpp:103:
.pio/libdeps/ESP8266/WiFi101/src/bsp/include/nm_bsp.h:110:23: error: conflicting declaration 'typedef long unsigned int uint32'
 typedef unsigned long uint32;
                       ^
In file included from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include/ets_sys.h:28:0,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/pgmspace.h:11,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/WString.h:29,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/IPAddress.h:24,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h:31,
                 from src/main.cpp:101:
/home/marcelo/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include/c_types.h:49:29: error: 'uint32' has a previous declaration as 'typedef unsigned int uint32'
 typedef unsigned int        uint32;
                             ^
In file included from .pio/libdeps/ESP8266/WiFi101/src/common/include/nm_common.h:45:0,
                 from .pio/libdeps/ESP8266/WiFi101/src/socket/include/socket.h:60,
                 from .pio/libdeps/ESP8266/WiFi101/src/WiFiUdp.h:24,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/libraries/DNSServer/src/DNSServer.h:3,
                 from src/main.cpp:103:
.pio/libdeps/ESP8266/WiFi101/src/bsp/include/nm_bsp.h:133:22: error: conflicting declaration 'typedef long int sint32'
 typedef signed long  sint32;
                      ^
In file included from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include/ets_sys.h:28:0,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/pgmspace.h:11,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/WString.h:29,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/IPAddress.h:24,
                 from /home/marcelo/.platformio/packages/framework-arduinoespressif8266/libraries/ESP8266WiFi/src/ESP8266WiFi.h:31,
                 from src/main.cpp:101:
/home/marcelo/.platformio/packages/framework-arduinoespressif8266/tools/sdk/include/c_types.h:52:29: error: 'sint32' has a previous declaration as 'typedef int sint32'
 typedef signed int          sint32;
                             ^
Compiling .pio/build/ESP8266/libe61/ESPAsyncTCP/tcp_axtls.c.o
Compiling .pio/build/ESP8266/lib607/Hash/Hash.cpp.o
Archiving .pio/build/ESP8266/libb51/libArduinoJson.a
Indexing .pio/build/ESP8266/libb51/libArduinoJson.a
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/AsyncEventSource.cpp.o
In file included from .pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager.h:597:0,
                 from src/main.cpp:347:
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h: In member function 'void ESPAsync_WiFiManager::scan()':
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h:559:16: warning: unused variable 'res' [-Wunused-variable]
           bool res=WiFi.getNetworkInfo(i, wifiSSIDs[i].SSID, wifiSSIDs[i].encryptionType, wifiSSIDs[i].RSSI, wifiSSIDs[i].BSSID, wifiSSIDs[i].channel, wifiSSIDs[i].isHidden);
                ^
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h: In member function 'void ESPAsync_WiFiManager::criticalLoop()':
src/main.cpp:51:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define TIME_BETWEEN_MODELESS_SCANS       30000
                                           ^
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h:670:47: note: in expansion of macro 'TIME_BETWEEN_MODELESS_SCANS'
     if (scannow == -1 || millis() > scannow + TIME_BETWEEN_MODELESS_SCANS)
                                               ^
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h: In member function 'boolean ESPAsync_WiFiManager::startConfigPortal(const char*, const char*)':
src/main.cpp:48:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
 #define TIME_BETWEEN_MODAL_SCANS          20000
                                           ^
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h:800:48: note: in expansion of macro 'TIME_BETWEEN_MODAL_SCANS'
     if ( scannow == -1 || millis() > scannow + TIME_BETWEEN_MODAL_SCANS)
                                                ^
Archiving .pio/build/ESP8266/libb94/libESP8266WiFi.a
In file included from .pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager.h:597:0,
                 from src/main.cpp:347:
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h: In member function 'boolean ESPAsync_WiFiManager::isIp(String)':
.pio/libdeps/ESP8266/ESPAsync_WiFiManager/src/ESPAsync_WiFiManager-Impl.h:2166:34: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for (int i = 0; i < str.length(); i++)
                                  ^
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/AsyncWebSocket.cpp.o
Indexing .pio/build/ESP8266/libb94/libESP8266WiFi.a
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/SPIFFSEditor.cpp.o
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/WebAuthentication.cpp.o
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/WebHandlers.cpp.o
Archiving .pio/build/ESP8266/libe61/libESPAsyncTCP.a
Indexing .pio/build/ESP8266/libe61/libESPAsyncTCP.a
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/WebRequest.cpp.o
Archiving .pio/build/ESP8266/lib607/libHash.a
Indexing .pio/build/ESP8266/lib607/libHash.a
Compiling .pio/build/ESP8266/lib8af/ESP Async WebServer/WebResponses.cpp.o
*** [.pio/build/ESP8266/src/main.cpp.o] Error 1
In file included from .pio/libdeps/ESP8266/ESP Async WebServer/src/SPIFFSEditor.cpp:1:0:
.pio/libdeps/ESP8266/ESP Async WebServer/src/SPIFFSEditor.h:16:101: warning: 'SPIFFS' is deprecated (declared at /home/marcelo/.platformio/packages/framework-arduinoespressif8266/cores/esp8266/FS.h:269): SPIFFS has been deprecated. Please consider moving to LittleFS or other filesystems. [-Wdeprecated-declarations]
     SPIFFSEditor(const String& username=String(), const String& password=String(), const fs::FS& fs=SPIFFS);
                                                                                                     ^
====================================================================== [FAILED] Took 3.89 seconds ======================================================================

Environment    Status    Duration
-------------  --------  ------------
ESP8266        FAILED    00:00:03.886
================================================================ 1 failed, 0 succeeded in 00:00:03.886 ================================================================
The terminal process "pio 'run'" terminated with exit code: 1.

Terminal will be reused by tasks, press any key to close it.

SyncClient.cpp: fatal error: interrupts.h: No such file

...\Arduino\libraries\ESPAsyncWebServer-master\src\SyncClient.cpp:25:24: fatal error: interrupts.h: No such file or directory

Hello. Help me understand what's going on. All your websocket-related projects have stopped compiling in the Arduino IDE for ESP 32. The same error always appears:
"SyncClient.cpp: fatal error: interrupt. h: No such file..."
My project with your libraries stopped compiling because of this error. I tried to take your example "Async_ESP 32_Webserver", which my project is based on, but compiling your example also ends up with the same error. I tried reinstalling the Arduino IDE, but the result is the same. What could be the problem. The request goes to the ESP8266 library, right? What and where to fix, so that the compiler does not access this library. I read that this bug is fixed in platformio, but I'm not a programmer and it's a complicated thing for me. Thank you in advance.

use AsyncElegantOTA

Hi,
I used AsyncElegantOTA (https://github.com/ayushsharma82/AsyncElegantOTA) successfully in other projects, but in combination with ESPAsync_WiFiManager it won't compile.
I started from your example Async_ESP_FSWebServer_DRD.ino
Normally 3 lines of code are sufficient to setup AsyncElegantOTA in the code:

  1. at the top: #include <AsyncElegantOTA.h>
  2. just before line server.begin(); in setup(): AsyncElegantOTA.begin(&server);
  3. somewhere in loop(): AsyncElegantOTA.loop();
    Now after applying these 3 lines to your example the AsyncElegantOTA type is not recognized:

sketch_apr07a:229:1: error: 'AsyncElegantOTA' does not name a type
AsyncElegantOTA.begin(&server); // Start ElegantOTA (reach out to http://{ip-address}/update)
^
Is this my fault? Or can you explain this behavior?

Call to ESPAsync_wifiManager.getTimezoneName() only works during initial config

I'm trying to use the new ESPAsync_wifiManager.getTimezoneName() function to set the timezone via configTzTime() on every boot. In my testing it only returns a result when I am in the initial config code path.

For example, if I trigger the initial config path by calling ESPAsync_wifiManager.resetSettings(), my call to ESPAsync_wifiManager.getTimezoneName(); correctly returns my time zone. If I just do a 'normal' boot, it returns an empty string.

I looked at the 20+ samples and all of them only call getTimezoneName when they are in their initialConfig state as well. Is this a known limitation? It seems like you should be able to set the timezone on 'regular' boots as well.

I may just be calling things incorrectly. My code is based on the Async_AutoConnect_ESP32_minimal sample - how should I be modifying it to correctly get the timezone?

  // connect to wifi or enter AP mode so it can be configured
  DB_PRINT("\nStarting Kaleidoscope on " + String(ARDUINO_BOARD));
  DB_PRINTLN(ESP_ASYNC_WIFIMANAGER_VERSION);
  ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "Kaleidoscope");
  //ESPAsync_wifiManager.resetSettings();   //reset saved settings
  ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 132, 1), IPAddress(192, 168, 132, 1), IPAddress(255, 255, 255, 0));
  ESPAsync_wifiManager.autoConnect("KaleidoscopeAP");
  if (WiFi.status() == WL_CONNECTED)
  {
    DB_PRINT(F("Connected. Local IP: "));
    DB_PRINTLN(WiFi.localIP());
  }
  else
  {
    DB_PRINTLN(ESPAsync_wifiManager.getStatus(WiFi.status()));
  }
  String tempTZ = ESPAsync_wifiManager.getTimezoneName();
  if (tempTZ.length())
    configTzTime(tempTZ.c_str(), "us.pool.ntp.org", "time.nist.gov", "0.pool.ntp.org");
  DB_PRINTF("Current timezone is %s\r\n", tempTZ.c_str());

Captive portal is not triggered on IOS

On my iPhone running IOS version 14.3 the captive portal is not triggered. When I connect to the AP the first time I have to explicitly go to 192.168.100.1 in a browser to get to the config screen. I tried other frameworks, e.g. AutoConnect, and there the captive portal is automatically triggered.

DHCP mode not working properly

I am using Async_ConfigOnSwitch example but instead of static ip configuration I am using DHCP mode. Thus for this I am using following settings #define USE_STATIC_IP_CONFIG_IN_CP false in modified code but the device always gets 255.255.255.255 ip on connection to router. The router address or gateway address is 192.168.0.1. The device is thus connected to router but I am still not able to access remote tcp server. This is happening with different router also.

Error esp_littlefs.c 'utime_p'

Hello Khoih,
First of all thank you for this great library shared with us.
If i can, i'll gonna use your library for my home project but i could not build any examples. Checked closed issues for fix by myself but im newbie little bit, maybe you know the way to fix.
Im using PlatformIO on Atom in ubuntu.

This is my platformio.ini;
env

Im not writing all this 665 lines for not to pollute the post //And dont know how can I write beautiful yet.
Example is Async_AutoConnect.ino under the "examples" i just copied and pasted with any changes.
Build is giving this results;
build
I can see something wrong with all littlefs but don't know how to fix.
I want to autoconnect my iot and watching online sensor data am I on right way? :))

When using custom parameters root config page is available but all other config pages are blank.

I am willing to contribute. I just need to know where to add the custom parameters. In your documentation you don't say where to add them. I tried to add them in the same place as your example (loop, after the instantiation of ESPAsync_wifiManager), however the web page /wifi becomes blank after adding the custom parameter via copy paste exactly as it is in the example file.

So, if you will elaborate I will amend the documentation and pull request. I will also amend any other parts that were difficult for me to figure out and make it clear in the documentation where to add and why.

    //
    // START WEB SERVER LOOP
    //
    // is configuration portal requested?
    if ((digitalRead(TRIGGER_PIN) == LOW))
    {
        Serial.println("\nConfiguration portal requested.");
        digitalWrite(LED_BUILTIN, LED_ON); // turn the LED on by making the voltage LOW to tell us we are in configuration mode.

        //Local intialization. Once its business is done, there is no need to keep it around
        ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AsyncCP-ParamsOnSW");

        char customhtml[24] = "type=\"checkbox\""; //<--This is where I copied from
        bool sensorDht22 = true;
        if (sensorDht22)
        {
            strcat(customhtml, " checked");
        }
        ESPAsync_WMParameter p_sensorDht22("DHT-22", "DHT-22 Sensor", "T", 2, customhtml, WFM_LABEL_AFTER);
        ESPAsync_wifiManager.addParameter(&p_sensorDht22); //<-- This is the end of the copy/paste

        //Check if there is stored WiFi router/password credentials.
        //If not found, device will remain in configuration mode until switched off via webserver.
        Serial.print("Opening configuration portal. ");
        
        Router_SSID = ESPAsync_wifiManager.WiFi_SSID();
        Router_Pass = ESPAsync_wifiManager.WiFi_Pass();
        
        // From v1.1.0, Don't permit NULL password
        if ( (Router_SSID != "") && (Router_Pass != "") )
        {
        ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
        Serial.println("Got stored Credentials. Timeout 120s");
        }
        else
        Serial.println("No stored Credentials. No timeout");

        // Extra parameters to be configured
        // After connecting, parameter.getValue() will get you the configured value
        // Format: <ID> <Placeholder text> <default value> <length> <custom HTML> <label placement>

        // Config Portal SSID - this is a straight forward string parameter
        ESPAsync_WMParameter p_PortalSSID(PortalSSID_Label, "Portal_SSID", PortalSSID, SSID_MAX_LENGTH + 1);

        // Config Portal SSID - this is a straight forward string parameter
        ESPAsync_WMParameter p_PortalPassword(PortalPassword_Label, "Portal_Password", PortalPassword, PASSWORD_MAX_LENGTH + 1);

        //add all parameters here
        ESPAsync_wifiManager.addParameter(&p_PortalSSID);
        ESPAsync_wifiManager.addParameter(&p_PortalPassword);

        // Sets timeout in seconds until configuration portal gets turned off.
        // If not specified device will remain in configuration mode until
        // switched off via webserver or device is restarted.
        //ESPAsync_wifiManager.setConfigPortalTimeout(120);

        ESPAsync_wifiManager.setMinimumSignalQuality(-1);

        // From v1.0.10 only
        // Set config portal channel, default = 1. Use 0 => random channel from 1-13
        ESPAsync_wifiManager.setConfigPortalChannel(0);
        //////

        //set custom ip for portal
        //ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255, 255, 255, 0));
        
    #if !USE_DHCP_IP    
    #if USE_CONFIGURABLE_DNS  
        // Set static IP, Gateway, Subnetmask, DNS1 and DNS2. New in v1.0.5
        ESPAsync_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask, dns1IP, dns2IP);  
    #else
        // Set static IP, Gateway, Subnetmask, Use auto DNS1 and DNS2.
        ESPAsync_wifiManager.setSTAStaticIPConfig(stationIP, gatewayIP, netMask);
    #endif 
    #endif  

    // New from v1.1.0
    #if USING_CORS_FEATURE
    ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
    #endif

        // Start an access point and goes into a blocking loop awaiting configuration.
        // Once the user leaves the portal with the exit button
        // processing will continue

        static bool resultConfigPortal;
        if ( (PortalSSID[0] == 0) || (PortalPassword[0] == 0) )
        {
        resultConfigPortal = ESPAsync_wifiManager.startConfigPortal((const char *) DefaultPortalSSID.c_str(), DefaultPortalPassword.c_str());
        }
        else
        {
        resultConfigPortal = ESPAsync_wifiManager.startConfigPortal((const char *) PortalSSID, PortalPassword);
        }

        if (resultConfigPortal)
        {
        Serial.println("WiFi connected...yeey :)");
        Serial.print("Local IP: ");
        Serial.println(WiFi.localIP());
        }
        else
        Serial.println("Not connected to WiFi but continuing anyway.");

        // Only clear then save data if CP entered and with new valid Credentials
        // No CP => stored getSSID() = ""
        if ( String(ESPAsync_wifiManager.getSSID(0)) != "" && String(ESPAsync_wifiManager.getSSID(1)) != "" )
        {
        // Stored  for later usage, from v1.1.0, but clear first
        memset(&WM_config, 0, sizeof(WM_config));
        
        for (uint8_t i = 0; i < NUM_WIFI_CREDENTIALS; i++)
        {
            String tempSSID = ESPAsync_wifiManager.getSSID(i);
            String tempPW   = ESPAsync_wifiManager.getPW(i);
        
            if (strlen(tempSSID.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1)
            strcpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str());
            else
            strncpy(WM_config.WiFi_Creds[i].wifi_ssid, tempSSID.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_ssid) - 1);
        
            if (strlen(tempPW.c_str()) < sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1)
            strcpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str());
            else
            strncpy(WM_config.WiFi_Creds[i].wifi_pw, tempPW.c_str(), sizeof(WM_config.WiFi_Creds[i].wifi_pw) - 1);  
        
            // Don't permit NULL SSID and password len < MIN_AP_PASSWORD_SIZE (8)
            if ( (String(WM_config.WiFi_Creds[i].wifi_ssid) != "") && (strlen(WM_config.WiFi_Creds[i].wifi_pw) >= MIN_AP_PASSWORD_SIZE) )
            {
            LOGERROR3(F("* Add SSID = "), WM_config.WiFi_Creds[i].wifi_ssid, F(", PW = "), WM_config.WiFi_Creds[i].wifi_pw );
            wifiMulti.addAP(WM_config.WiFi_Creds[i].wifi_ssid, WM_config.WiFi_Creds[i].wifi_pw);
            }
        }
        
        saveConfigData();
        }

        // Getting posted form values and overriding local variables parameters
        // Config file is written regardless the connection state
        strcpy(PortalSSID, p_PortalSSID.getValue());
        strcpy(PortalPassword, p_PortalPassword.getValue());

        // Writing JSON config file to flash for next boot
        writeConfigFile();

        digitalWrite(LED_BUILTIN, LED_OFF); // Turn LED off as we are not in configuration mode.
    }
    check_status();
    //
    // END WEB SERVER LOOP
    //

When using the above code the root config page is available but all other pages are blank.

Where do the custom parameters need to be located in the loop to function properly?

question ModelessConnect & WiFiServer

hi.
(sorry. poor english.)

I am testing the ModelessConnect example.

In addition, an FTP server (using WiFiServer) is used together.

ModelessConnect cannot connect to the router after rebooting after configuring the router in the portal.

Can't I use it with WifiServer(FTP server)?

Please help.


  • device: ESP32

  • IDE : platformIO/Arduino

  • simple example

void setup()
{
	Serial.begin(115200);
	Serial.flush();
	delay(50);

	setupModelessConnect();  // ESPAsync_WiFiManager
	setupFTPServer();  // using WifiServer
}

void loop()
{
	loopModelessConnect();
	loopFTPServer();
}

Feature request: Provide example using espidf framework

All the examples provided are using the arduino framework.

An example using the espidf framework would be desirable, particularly a non-C++ example.

According to the GitHub tags and the platformio/platformio.ini file, the espidf framework is supported for the espressif32 platform. If this actually isn't the case, perhaps those tags should be removed?

Exception 9: LoadStoreAlignmentCause: Load or store to an unaligned address

Hi, I'm trying to use this useful library with "Dynamic Params". I defined the struct as reported at end, but when I try to Serial print the value value of SENSOR_TYPE (Serial.print("TIPO SENSORE ");Serial.println(SENSOR_TYPE);) I get the exception as in subject.
Can you help me?
Thank you.

#define INFLUXDB_URL_LEN 251
char INFLUXDB_URL[INFLUXDB_URL_LEN + 1] = "http://influx.sapacasa.it:8086";

#define INFLUXDB_NAME_LEN 31
char INFLUXDB_NAME[INFLUXDB_NAME_LEN + 1] = "domus";

#define INFLUXDB_USER_LEN 31
char INFLUXDB_USER[INFLUXDB_USER_LEN + 1] = "usor";

#define INFLUXDB_PASS_LEN 31
char INFLUXDB_PASS[INFLUXDB_PASS_LEN + 1] = "usor";

#define SENSOR_NAME_LEN 31
char SENSOR_NAME[SENSOR_NAME_LEN + 1] = "SonOff";

#define SENSOR_TYPE_LEN 11
char SENSOR_TYPE[SENSOR_TYPE_LEN + 1] = "UNKNOW";

#define SENSOR_LOCATION_LEN 31
char SENSOR_LOCATION[SENSOR_LOCATION_LEN + 1] = "stanza letto";

#define SENSOR_BOOT_STATE_LEN 12
char SENSOR_BOOT_STATE[SENSOR_BOOT_STATE_LEN + 1]   = "ultimo";

MenuItem myMenuItems [] = {
  { "ixul", "Url InfluxDb",      INFLUXDB_URL,  INFLUXDB_URL_LEN  },
  { "ixdb", "Schema Influx",     INFLUXDB_NAME, INFLUXDB_NAME_LEN },
  { "ixun", "Utente Influx",     INFLUXDB_USER, INFLUXDB_USER_LEN },
  { "ixup", "Password Influx",   INFLUXDB_PASS, INFLUXDB_PASS_LEN },
  { "snnm", "Nome Sensore",      SENSOR_NAME,   SENSOR_NAME_LEN },
  { "sndv", "Tipo Sensore",      SENSOR_TYPE,   SENSOR_TYPE_LEN },
  { "ubic", "Ubicazione",        SENSOR_LOCATION, SENSOR_LOCATION_LEN },
  { "bste", "Stato iniziale",    SENSOR_BOOT_STATE, SENSOR_BOOT_STATE_LEN },
};

uint16_t NUM_MENU_ITEMS = sizeof(myMenuItems) / sizeof(MenuItem);  //MenuItemSize;

Holy shit my friend! You are the wizard of oz

Sorry for "Missusing" the issue tracker - but there is no other way to say thank you somehow! THANK YOU!!!! I want to spent you some beer - or some more, so please contact me via github for your paypal.

Mike.

Can I use this?

Using a library should be simple, but this thing has gotten so complicated with the number of configuration variables, etc that it's hard to see the forest for the trees.

What I want to do is to add something like wifimanager to my existing app where I have a 9 page asyc web server with jquery and style sheets, etc, with my own NTP time server, etc. I found it much easier to start with a simple auto-connect to my local LAN for development. But I want the product to be user configured for his/her local network and/or for it to work in stand-along AP mode.

From what I've read it looks like what I need to do is add another IP address for my site, but I think yours may be overly complicated.

So what I need:

  1. Start in AP mode, display available networks and capture login info. Try to connect and remember the connection, possibly adding to other connections.
  2. If logged in, switch to my webserver.
  3. Provide an option in AP mode to bypass the login stuff, and operate stand-alone, for example, if not in range of a LAN., but also connect to my web server.
  4. There's a lot of presumption in your code about file systems, etc. I already have SPIFFS set up, And as I mentioned, NTP. You are not the center of the universe, just the wifi configuration manager. I think it would be better if you had separate examples for SPIFF and LF than all the ifdefs etc.
  5. It also has to operate on cell-phones, why do I have to specifically configure for this?

ESP32 static IP not saved after restarting the device

Hello. I am learning about esp32 and trying your library. I am using the example program:
Async_ESP32_FSWebServer_DRD

I have not modified the code yet. When I run the program. A new network appeared
image

I am able to connect to my device by typing the ip address :
192.168.1.100
and change some configurataion:

image

Now I can see that the device connects with the new parameters: (I have set a new static ip 192.168.4.210)

image

However, the thing that I do not fully understand, when i restart my esp32 device, it goes changes my static ip (192.168.4.210) to:
192.168.2.232
image

Is that normal? Should it not save my configuration even after I restart the device?

Also, I am unsure about:
Open http://async-esp32fs.local/edit to see the file browser
Using username = admin and password = admin

Opening this webpage in a browswer fails everytime. How do i use it?
image

Appreciate any sort of advice. Thanks in advance.

Auto(re)connect by using multiwifi problem

Describe the bug

I using multiwifi to auto(re)connect wifi router as link below:-
https://github.com/khoih-prog/ESPAsync_WiFiManager#16-using-multiwifi-autoreconnect-feature

The problem after restart wifi router, then ESP32 with ESPAsync_WiFiManager library is try to reconnect to wifi router correctly, BUT when WiFi router ready to use, the ESP32 not connect to WiFi until push RESET button and debugging message on serial port shown as below:-

[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:187] run(): [WIFI] Connecting Failed (0).

Then no debugging message any more

Steps to Reproduce

  1. Run library example Async_AutoConnect.ino
  2. Turn-OFF Wifi Router
  3. Serial port debugging message shown below message every 500 mSec (default on example code: "Async_AutoConnect.ino" -- LINE 321
    Debugging message:

WiFi lost. Call connectMultiWiFi in loop
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!

  1. Turn-ON WiFi router and waiting ESP32 reconnect, when the WiFi router ready then ESP32 not connect to WiFi until push RESET button and stop debugging message as below:-

[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:187] run(): [WIFI] Connecting Failed (0).

sometime like this:-

[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:187] run(): [WIFI] Connecting Failed (0).

Expected behavior

Expected ESP32 auto(re)connect to WiFi router and debugging message status like example source code, it look like below:-

SSID: ......, RSSI= ......
Channel: ......., IP Addresss: .......

Actual behavior (Debugging log)

  1. ESP32 not connect to WiFi until push RESET button
  2. No debugging message any more and stop like below:-

WiFi lost. Call connectMultiWiFi in loop
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:191] run(): [WIFI] no matching wifi found!
[E][WiFiMulti.cpp:187] run(): [WIFI] Connecting Failed (0).

Information

Please ensure to specify the following:

  • Platform.io version 1.57.0
  • ESP32 DevModule (ESP32-WROOM-32) with ESPAsync_WiFiManager 1.9.1
  • Run library example "Async_AutoConnect.ino" then Turn-Off and Turn-On WiFi router (As in ### Step to Reproduce)
  • Anything that might be relevant in your opinion, such as:
    • MacOS BigSur 11.4
    • WPA/WPA2, Home networks WiFi 2.4GHz

Add support to ESP32-S2. Help with an example.

Hi,

This is my first try with this wifi manager.

ESP32-S2 board.
fresh arduino IDE 1.8.13
I have tested that board works.

Tested with 2 boards. Same results.

Added your lib: ESPAsync_WiFiManager

Example: Async_AutoConnect.ino (no changes!)

Compile:
image

I have connected to AutoConnectAP.
I have opened tab with 192.168.100.1

My Serial:
image

Starting Async_AutoConnectAP using LittleFS on ESP32S2_DEV ESPAsync_WiFiManager v1.4.1 [WM] RFC925 Hostname = AutoConnectAP [WM] setAPStaticIPConfig [WM] setSTAStaticIPConfig [WM] Set CORS Header to : Your Access-Control-Allow-Origin Stored: SSID = espressif, Pass = Got stored Credentials. Timeout 120s We haven't got any access point credentials, so get them now [WM] WiFi.waitForConnectResult Done [WM] SET AP [WM] Configuring AP SSID = ESP_5A1DF7C_AutoConnectAP [WM] AP PWD = MyESP_5A1DF7C [WM] AP Channel = 7 [WM] Custom AP IP/GW/Subnet = 192.168.100.1 192.168.100.1 255.255.255.0 [WM] AP IP address = 192.168.100.1 [WM] HTTP server started [WM] ESPAsync_WiFiManager::startConfigPortal : Enter loop

My chrome inspector for 192.168.100.1
Most of the time Pending ...
image

Problem:

PC Windows 10
99% of the time i get white blank page on 192.168.100.1
1% i get menu page. If i am lucky with that i can click buttons but nothing happens ... i am redirected for example to 192.168.100.1/i .. which stays white blank as any other page

Android: 100% i get white blank page

What i am doing wrong?

Captive portal instead of static ip portal

Hi I am using following code for wifi manger picked from examples.
`ESPAsync_WiFiManager ESPAsync_wifiManager(&webServer, &dnsServer, "AutoConnectAP");
ESPAsync_wifiManager.setDebugOutput(true);
ESPAsync_wifiManager.setAPStaticIPConfig(IPAddress(192, 168, 100, 1), IPAddress(192, 168, 100, 1), IPAddress(255, 255, 255, 0));

ESPAsync_wifiManager.setMinimumSignalQuality(-1);
ESPAsync_wifiManager.setConfigPortalChannel(0);

#if USING_CORS_FEATURE
	ESPAsync_wifiManager.setCORSHeader("Your Access-Control-Allow-Origin");
#endif

Router_SSID = ESPAsync_wifiManager.WiFi_SSID();
Router_Pass = ESPAsync_wifiManager.WiFi_Pass();

//Remove this line if you do not want to see WiFi password printed
Serial.println("Stored: SSID = " + Router_SSID + ", Pass = " + Router_Pass);

if (Router_SSID != "")
{
	ESPAsync_wifiManager.setConfigPortalTimeout(120); //If no access point name has been previously entered disable timeout.
	Serial.println("Got stored Credentials. Timeout 120s");
}
else
{
	Serial.println("No stored Credentials. No timeout");
}

String chipID = String(ESP_getChipId(), HEX);
chipID.toUpperCase();

// SSID and PW for Config Portal
String AP_SSID = "ESP_" + chipID + "_AutoConnectAP";
String AP_PASS = "12345678";

if ( !ESPAsync_wifiManager.startConfigPortal(AP_SSID.c_str(), AP_PASS.c_str()) )
	Serial.println("Not connected to WiFi but continuing anyway.");
else
	Serial.println("WiFi connected...yeey :)");`

The portal at 192.168.100.1 works fine when this code is called first time but if I call this code again in loop or setup function then it switches to captive portal which opens automatically when I connect to esp32 AP instead of portal at 192.168.100.1. What is the reason for this behaviour?

Delete Stored SSID and Pass

Hi, good job!
I have a trouble, with ESPAsync_WiFiManager:
1.- Start Captive portal, and I config SSID and Password for mi mobile wifi AP.
2.- Save data OK.
3.- manual Reset ESP8266 and start Config Portal for 30sg (I configure), and next connect with my mobile AP perfect.
4.- If I switch off my mobile AP, and reset ESP8266, then:

ESPAsync_WiFiManager Version v1.3.0
[WM] RFC925 Hostname = ConfigOnStartup
Stored: SSID = , Pass =
Opening configuration portal.Open Config Portal without Timeout: No stored Credentials

And no Stored SSID and no Pass !!!

Can you help me ?
Thanks

Config portal in client mode

I have an application where i am happy to user the WiFiManager.
Since I added some config parameters I wondered if it is
possible to access the Portal also in Client mode, when I
am connected to a hotspot.
These would easy the process of changing parameters here.

VERSION 1.4.2 NO MULTIWIFI

Hi, good job !! The las Issue in 1.4.1 it´s now Ok, but ... ...
At the moment, not remember stored SSID and Pass, and only use the last pair used for connection.
I use the Async_ConfigOnStartup.ino 1.4.2, and change #define NUM_WIFI_CREDENTIALS from 2 to 4

My ESP8266 connect and remember perfectly my mobile AP, in all the test, but if I switch off my mobile AP, and config SSID and Password for use my fixed router AP, ESP8266 remember only my fixed AP, and not connect with mobile AP. (don´t store data)

thanks

ESP8266 Clear SSID and Pass

Hi, good job!
I have a trouble, with ESPAsync_WiFiManager:
1.- Start Captive portal, and I config SSID and Password for mi mobile wifi AP.
2.- Save data OK.
3.- manual Reset ESP8266 and start Config Portal for 30sg (I configure), and next connect with my mobile AP perfect.
4.- If I switch off my mobile AP, and reset ESP8266, then:

ESPAsync_WiFiManager Version v1.3.0
[WM] RFC925 Hostname = ConfigOnStartup
Stored: SSID = , Pass =
Opening configuration portal.Open Config Portal without Timeout: No stored Credentials

And no Stored SSID and no Pass !!!

Can you help me ?
Thanks

fatal error: ESPAsyncWebServer.h: No such file or directory

Describe the bug

Hello, I'm getting only this error when compile sketch:

C:\Users\flavi\Documents\Arduino\libraries\ESPAsync_WiFiManager\src/ESPAsync_WiFiManager.h:73:33: fatal error: ESPAsyncWebServer.h: No such file or directory

Information

Please ensure to specify the following:

  • Arduino IDE version: 1.8.13
  • ESP32
  • OS: Windows 10 x64

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.