feat: refine portal flow and examples

This commit is contained in:
2026-09-03 18:54:41 +10:00
parent f8b87f7865
commit 2fec33b952
42 changed files with 870 additions and 212 deletions
+3 -7
View File
@@ -27,15 +27,11 @@ void loop() {
```ini
lib_deps =
WiFiManager=https://github.com/alexhopeoconnor/WiFiManager.git#v3.1.0
WiFiManager=https://github.com/alexhopeoconnor/WiFiManager.git#v3.2.0
```
The package manifest resolves DFTE, ESPAsyncWebServer, and the correct TCP transport for ESP8266 or ESP32. A consuming project should not duplicate those dependencies unless it is deliberately testing an unreleased stack change.
The package includes the asynchronous web and TCP dependencies required by the selected ESP8266 or ESP32 target. Add WiFiManager as the application’s direct dependency; do not copy its internal dependency list into your project.
## DeviceFramework applications
DeviceFramework creates and configures WiFiManager for its normal lifecycle. Use DeviceFramework’s persistent shared device-password API instead of separately configuring an AP, OTA, HTTP, and WebSerial password.
Next: [portal UI](PORTAL_UI.md) or [portal API](PORTAL_API.md).
Next: build [Basic Portal](../examples/BasicPortal/), then explore [portal UI](PORTAL_UI.md) or [portal API](PORTAL_API.md).
Back to [documentation](README.md) · [project overview](../README.md).
+8 -2
View File
@@ -2,6 +2,8 @@
The portal uses JSON endpoints under `/api/...` for WiFi scans and saves, parameters, information, status, restart/erase/exit actions, captive-portal closure, and station-connect status. Consumers should treat the documented response shapes as the contract; portal HTML is not an API.
The current bootstrap contract is version 3. It includes `brand.tagline`, the short product tagline rendered in the portal header.
## Profile-mode WiFi metadata
When an application supplies a `WiFiManagerStationProfileStore`, `GET /api/wifi/meta` reports a primary profile and optional fallback without returning passwords. `POST /api/wifi/save` verifies a submitted candidate before committing it; see [station profiles](STATION_PROFILES.md) for fields and lifecycle.
@@ -20,9 +22,13 @@ When `portalSetBehaviorConnectOnSave(true)` is enabled, saving credentials queue
}
```
`stationIp` and `redirectUrl` are present only after a successful join. If the portal server is not on port 80, `redirectUrl` includes that port.
`stationIp` and `redirectUrl` are present only after a successful join. If the portal server is not on port 80, `redirectUrl` includes that port. When connect-on-save is disabled, a saved configuration has no station address and the built-in portal remains open.
On success, WiFiManager keeps the portal alive briefly so the client can read the final status and navigate before the AP is shut down. Captive-portal helpers, DHCP timing, browser behaviour, and network isolation can still prevent an automatic redirect, so clients must handle a visible address as well.
On success, the SPA first reads the station address, then POSTs `/api/wifi/connect-complete`. WiFiManager keeps the portal available for a fallback period while it waits for that acknowledgement, then closes it after a short grace delay so the normal device web server can start. This removes the old client-side race where the portal could disappear before the final status arrived. Captive-portal helpers, DHCP timing, browser behaviour, and network isolation can still prevent an automatic redirect, so clients must retain the visible address as a fallback.
## Portal timeout
When a configuration-portal timeout is enabled, `POST /api/portal/timeout-reset` restarts the countdown and returns `{ "ok": true, "timeoutSecondsRemaining": N }`. The built-in overview exposes this as an explicit reset control; custom clients may use the documented endpoint too.
## API design rules
+5 -6
View File
@@ -15,7 +15,7 @@ WiFiManager wifi;
namespace {
const char kTitle[] PROGMEM = "Set up Temperature Monitor";
const char kIdentity[] PROGMEM = "Example Devices";
const char kIntro[] PROGMEM = "Connect this device to Wi-Fi.";
const char kTagline[] PROGMEM = "Reliable setup for connected devices.";
const char kLogoAlt[] PROGMEM = "Example Devices";
const char kLogo[] PROGMEM = R"svg(<svg viewBox="0 0 64 64"><circle cx="32" cy="32" r="28"/></svg>)svg";
const char kPage[] PROGMEM = "#f4f7f3";
@@ -26,7 +26,7 @@ const char kAccentText[] PROGMEM = "#ffffff";
const WiFiManagerPortalConfig kPortalUI = {
WiFiManagerPortalText::progmem(kTitle),
WiFiManagerPortalText::progmem(kIdentity),
WiFiManagerPortalText::progmem(kIntro),
WiFiManagerPortalText::progmem(kTagline),
WiFiManagerPortalAsset::svgFromProgmem(kLogo),
WiFiManagerPortalText::progmem(kLogoAlt),
{
@@ -58,9 +58,9 @@ Leave a text or colour value empty, or a radius at `0`, to retain the built-in s
| Field | Used by |
| --- | --- |
| `title` | Document title and portal heading |
| `identityText` | Product/device line below the heading |
| `homeIntro` | Introductory text on the home view |
| `title` | Document title and concise setup-page heading |
| `identityText` | Company or product name in the header above navigation |
| `tagline` | Short tagline in the header above navigation |
| `logo.svg`, `logoAltText` | Optional trusted inline SVG and its accessible label |
| `pageBackground`, `surface`, `text`, `mutedText`, `border` | Portal surfaces and text |
| `accent`, `accentHover`, `accentText` | Primary links and actions |
@@ -75,6 +75,5 @@ Presentation uses one configuration route: `setPortalConfig()`. Existing structu
There is no arbitrary HTML shell, route replacement, navigation injection, raw stylesheet, or script hook. If a product needs a new portal capability, add a narrow WiFiManager contract and test it on both supported targets.
For a DeviceFramework device, use `DeviceFrameworkUIConfig`; DeviceFramework maps its product-level configuration into this portal API. See [DeviceFramework web UI](https://github.com/alexhopeoconnor/DeviceFramework/blob/main/docs/WEB_UI.md).
Back to the [documentation index](README.md) or [project overview](../README.md).
+1 -9
View File
@@ -1,20 +1,12 @@
# WiFiManager documentation
This maintained fork intentionally has a narrower, explicit customisation boundary than upstream WiFiManager.
| I want to… | Read |
| --- | --- |
| Start a basic portal or install a released dependency | [Getting started](GETTING_STARTED.md) |
| Brand the portal or add structured built-in content | [Portal UI](PORTAL_UI.md) |
| Configure primary/fallback station profiles or their portal workflow | [Station profiles](STATION_PROFILES.md) |
| Consume JSON endpoints or station-connect status | [Portal API](PORTAL_API.md) |
| Build a clean consumer | [Testing](TESTING.md) |
| Build or flash a complete example | [Examples](../examples/README.md) |
| Work on this fork or make a release | [Development and releases](DEVELOPMENT.md) |
## Documentation rules
- Portal UI owns branding, semantic theming, and the supported `portal*` surface.
- Portal API owns HTTP response contracts.
- The root README is a short onboarding page, not an API reference.
Back to the [project overview](../README.md).
+2 -2
View File
@@ -2,7 +2,7 @@
WiFiManager 3.1.0 adds an opt-in station-profile controller for applications that need a primary Wi-Fi network and one fallback. It is independent of the legacy `autoConnect()` flow: existing WiFiManager consumers do not need to change.
DeviceFramework enables this controller and supplies its CRC-protected storage. A direct WiFiManager consumer supplies its own durable store, or can use the controller only for the current process.
A WiFiManager application supplies its own durable store. The controller can also be used with an in-memory store for a temporary session, but credentials will not survive a restart.
## Lifecycle
@@ -57,6 +57,6 @@ In profile mode, the existing Wi-Fi page becomes a two-profile form. It remains
The portal requires a non-empty primary SSID. Its API never returns a password; it only reports whether one is set.
See [Portal API](PORTAL_API.md) for the shared connection-status response and [DeviceFramework configuration](https://github.com/alexhopeoconnor/DeviceFramework/blob/main/docs/CONFIGURATION.md) for the local-profile JSON that supplies these slots.
See [Portal API](PORTAL_API.md) for the shared connection-status response. The buildable [Station Profiles](../examples/StationProfiles/) example contains a compact EEPROM-backed store for both supported ESP targets.
Back to [documentation](README.md) · [project overview](../README.md).
+1 -1
View File
@@ -9,6 +9,6 @@ check, so dependency resolution uses the current manifest rather than a stale
./scripts/test.sh compile --platform esp32
```
CI runs both checks for pushes to the maintained branch and pull requests. They compile only; hardware portals remain a local integration concern for an application or DeviceFramework’s connected-device suite.
CI runs both checks for pushes to the maintained branch and pull requests. They compile only; hardware portals remain a local integration concern for the consuming application.
Back to [documentation](README.md) · [project overview](../README.md).
Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 109 KiB