⭐ If you find this project useful, please consider giving it a star. Thank you.
📢 Now available in the Arduino IDE!
You can install AyresWiFiManager directly from the Arduino IDE Library Manager.
Just search for “AyresWiFiManager” and click “Install”.
AWM — Pro Wi‑Fi manager for ESP32/ESP8266 featuring a real captive portal (AP+DNS), modern UI served from LittleFS, secure credential storage, fallback policies, provisioning button, status LED, NTP, Internet reachability check, and configurable logging.
Project: https://github.com/AyresNet/AyresWiFiManager
License: MIT — (c) 2025 AyresNet
🇪🇸 ¿Español? Lee el README.es.md.
- Real captive portal: DNS catch‑all + OS connectivity routes (Android/iOS/Windows) to force open
http://192.168.4.1. - Lightweight UI (no external deps) served from
/data(LittleFS): search, rescan, signal bars, and an option to erase credentials from the portal. - Clear, cross‑platform API for ESP32/ESP8266 with explicit policies.
- Smart fallbacks:
NO_CREDENTIALS_ONLY(default),ON_FAIL,SMART_RETRIES,BUTTON_ONLY,NEVER. - Integrated Button & LED:
- Button (LOW): 2–5 s opens portal · ≥5 s erases JSON and restarts.
- LED:
ONconnected ·BLINK_SLOWportal ·BLINK_FASTscanning ·OFFidle (+ double/triple patterns for feedback).
- Safe JSON erase with whitelist, recursive on ESP32.
- Professional logging (
AWM_LOG*macros) with level set viabuild_flags. - Utilities: NTP (pool.ntp.org/time.nist.gov),
hayInternet()(Google204), RSSI, timestamp, auto‑reconnect.
- Credential storage at
/wifi.json(LittleFS). - Portal routes
GET /→index.htmlPOST /save→ stores{ssid,password}and restartsGET /scanor/scan.json→[{ssid,rssi,secure}]POST /erase→ deletes.json(respects whitelist) and restarts
- Example HTML/JS/CSS included:
data/index.html,data/success.html,data/error.html - ESP32:
esp_wifi_set_ps(WIFI_PS_NONE),LittleFS.begin(true)(auto‑format)
ESP8266:WiFi.setSleepMode(WIFI_NONE_SLEEP), non‑recursive LittleFS iteration
Minimal platformio.ini:
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 115200
board_build.filesystem = littlefs
; Optional: logging
build_flags =
-D AWM_ENABLE_LOG=1 ; 0=off, 1=on
-D AWM_LOG_LEVEL=3 ; 1=E, 2=W, 3=I, 4=D, 5=V- Place your portal files in
data/(e.g.index.html). - Upload FS:
pio run -t uploadfs. - Flash the sketch and open the serial monitor.
- Install the official ESP32/ESP8266 cores.
- Install the appropriate LittleFS uploader (ESP32/ESP8266).
- Upload the
data/folder to the FS with the “Data Upload” tool. - Build and upload the sketch.
#include <AyresWiFiManager.h>
AyresWiFiManager wifi;
void setup() {
Serial.begin(115200);
wifi.setAPCredentials("ayreswifimanager","123456789");
wifi.setPortalTimeout(300); // 5 min of inactivity
wifi.setAPClientCheck(true); // don't close if clients connected
wifi.setWebClientCheck(true); // each HTTP request resets the timer
// wifi.setCaptivePortal(false); // disable redirections if you prefer
wifi.begin(); // mounts FS, loads /wifi.json if present
wifi.run(); // tries STA; if it fails applies the fallback policy
}
void loop() {
wifi.update(); // serves HTTP/DNS and handles timeouts/LED
}The example examples/30sVentana/src/main.cpp does:
- If credentials exist → opens portal with 30 s inactivity timeout; if unused, it closes and continues automatically.
- If no credentials → opens a “normal” portal (e.g. 5 min inactivity timeout).
- In both cases, while the portal is in use (AP clients or HTTP requests), it won’t close until usage stops.
// Portal / AP
void setHtmlPathPrefix(const String& prefix); // e.g.: "/wifimanager"
void setHostname(const String& host);
void setAPCredentials(const String& ssid, const String& pass);
void setCaptivePortal(bool enabled); // DNS + captive routes
void setPortalTimeout(uint32_t seconds); // 0 = no timeout
void setAPClientCheck(bool enabled); // keep open if clients connected
void setWebClientCheck(bool enabled); // each request resets timer
void openPortal();
void closePortal();
bool isPortalActive() const;
// Fallback
enum class FallbackPolicy { ON_FAIL, NO_CREDENTIALS_ONLY, SMART_RETRIES, BUTTON_ONLY, NEVER };
void setFallbackPolicy(FallbackPolicy p);
void setSmartRetries(uint8_t maxRetries, uint32_t windowMs);
void enableButtonPortal(bool enable);
void setAutoReconnect(bool enabled);
// Status / utilities
bool tieneCredenciales() const;
bool connectToWiFi();
bool isConnected();
int getSignalStrength(); // RSSI
uint64_t getTimestamp(); // ms (0 if no NTP)
bool hayInternet(); // generate_204
bool scanRedDetectada();
void forzarReconexion();
// LED
enum class LedPattern { OFF, ON, BLINK_SLOW, BLINK_FAST, BLINK_DOUBLE, BLINK_TRIPLE };
void setLedAuto(bool enable);
void setLedPatternManual(LedPattern p);
// FS safety (.json whitelist)
void setProtectedJsons(std::initializer_list<const char*> names); // e.g.: {"/wifi.json","license.json"}- Button (default pin 0,
INPUT_PULLUP, active LOW):- 2–5 s → open portal (if
enableButtonPortal(true)) - ≥5 s → erase
.json(respectssetProtectedJsons) and restart
- 2–5 s → open portal (if
- LED (default pin 2):
ONconnected to Wi‑FiBLINK_SLOWportal activeBLINK_FASTscanningBLINK_DOUBLE / TRIPLEfeedback while holding the buttonOFFno link/portal
You can set the pattern manually (
setLedPatternManual) or leave it automatic (setLedAuto(true)).
Include include/AWM_Logging.h and use the macros:
AWM_LOGE("error: %d", code); // Error
AWM_LOGW("warning...");
AWM_LOGI("info...");
AWM_LOGD("debug x=%d", x);
AWM_LOGV("verbose...");Enable via compile flags (PlatformIO):
build_flags =
-D AWM_ENABLE_LOG=1
-D AWM_LOG_LEVEL=3 ; 1=ERROR, 2=WARN, 3=INFO, 4=DEBUG, 5=VERBOSE- Set
AWM_ENABLE_LOG=0to turn all logs off (no‑ops). - Raise/lower
AWM_LOG_LEVELto control verbosity.
data/index.html– scan, filter, SSID selection, save form, advanced optionsdata/success.html– saved confirmation (SVG with pulse; the device restarts)data/error.html– save error (SVG with subtle shake + “Back” link)
Change the root with
setHtmlPathPrefix("/wifimanager")if you prefer another folder.
Upload FS
- PlatformIO:
pio run -t uploadfs - Arduino IDE: “Data Upload” tool
AyresWiFiManager aims to be simple and explicit:
- No configuration auto‑magic: you decide when to open the portal and for how long.
- A truly captive portal (DNS + routes), not just AP + webserver.
- Modern UI without CDNs, tailored for low RAM/flash ESPs.
- Safe erase of
.jsonwith whitelist and (on ESP32) recursive. - Logging with adjustable levels.
examples/AWM_Minimal/AWM_Minimal.ino– minimal usage (begin(),update(),isConnected()).examples/AWM_Advanced/AWM_Advanced.ino– status LED, short-press button → portal, NTP, reconnect.examples/standard/main.cpp– simple reference flow.examples/30sVentana/main.cpp– 30-second “boot window” portal if credentials exist.examples/usedExample/usedExample.ino– legacy usage example.
AyresWiFiManager/
├─ data/ # Captive-portal HTML/CSS/JS (LittleFS examples)
│ ├─ index.html # Main portal page
│ ├─ success.html # Confirmation after saving credentials
│ └─ error.html # Error page
│
├─ examples/ # Example sketches (Arduino IDE & PlatformIO)
│ ├─ AWM_Minimal/
│ │ └─ AWM_Minimal.ino # Minimal usage (begin + update + isConnected)
│ ├─ AWM_Advanced/
│ │ └─ AWM_Advanced.ino # Advanced: LED, button, NTP, reconnect
│ ├─ standard/
│ │ └─ main.cpp # Simple reference flow
│ ├─ 30sVentana/
│ │ └─ main.cpp # 30s "boot window" captive portal
│ └─ usedExample/
│ └─ usedExample.ino # Legacy usage example
│
├─ src/ # Core library sources
│ ├─ AyresWiFiManager.h # Main header (public API)
│ ├─ AyresWiFiManager.cpp # Implementation
│ └─ AWM_Logging.h # Optional lightweight logging macros
│
├─ library.properties # Arduino Library Manager metadata
├─ library.json # PlatformIO metadata
├─ platformio.ini # Example PIO project config
├─ LICENSE # MIT License
├─ README.md # Main documentation (English)
└─ README.es.md # Documentation in Spanish
To keep local libs out of the repo, add paths to
.gitignore(e.g.lib/AyresShell/).
The portal files (index.html, success.html, error.html) must be uploaded
to the LittleFS of your own sketch:
- Copy the files from this library’s
data/folder into thedata/folder of your sketch. - Upload them to the device:
- Arduino IDE: menu → ESP32 LittleFS Data Upload
- PlatformIO:
pio run --target uploadfs
⚠️ Important note:
Thedata/folder in the root of this library is for reference/example only.
It is not automatically uploaded when compiling a sketch.
- Protect critical files:
wifi.setProtectedJsons({"/wifi.json","license.json"}); - Set coherent inactivity timeouts (
setPortalTimeout) and enablesetAPClientCheck(true)+setWebClientCheck(true)so it doesn’t close while in use. - For remote installs,
setFallbackPolicy(SMART_RETRIES)+setAutoReconnect(true)usually gives a great UX. - If you need fewer logs in production:
-D AWM_ENABLE_LOG=0.
- ESP32 (Arduino core)
- ESP8266 (Arduino core)
Requires LittleFS. On ESP32 it auto‑formats if
begin(true)fails.
PRs & issues are welcome!
Ideas: more examples, translations, portal UI/UX tweaks, new fallback policies.
MIT — see LICENSE (or SPDX headers in source files).
Questions or ideas? Open an issue. Thanks for trying AyresWiFiManager! 🚀


