Wi-Fi AP Provisioning Recovery: Design and Acceptance Tests
A Wi-Fi provisioning flow is ready for a product when a user can recover from wrong credentials, missing routers, interrupted setup and power loss without a firmware reflash. Design provisioning as a bounded state machine with a visible result, protected credentials and a deliberate way back into setup. A successful HTTP submission to the device is only one step in that process.
This article covers a device-hosted setup access point followed by connection to a customer router. It applies to Linux and MCU products, while API details depend on the selected driver and SDK. All timing examples and tests are proposed design inputs, not measured product claims.
Define success before designing the screen
Separate four milestones: the phone submitted a candidate configuration; the device associated and authenticated; it obtained a usable IP configuration; and the required application service was reached. For a local controller, the final requirement may be local discovery. For a cloud product, it may be an authenticated registration or health exchange. Write down which milestone commits the new settings.
Do not treat a cloud outage as proof of a wrong Wi-Fi password. If Wi-Fi and DHCP succeeded but the application backend is unavailable, retain a distinct “network configured, service unavailable” state. Let the product’s policy decide whether that state is acceptable for installation, rather than sending the user through the password form repeatedly.
Specify the supported router bands, security modes, SSID encoding/length, hidden-network workflow and enterprise-network requirements. A 2.4 GHz-only module cannot be fixed by retrying a 5 GHz-only network. WPA-Enterprise, captive upstream portals and managed corporate networks need explicit support or a clear exclusion.

Make configuration changes transactional
Keep the last known-good configuration separate from the candidate under test. Assign each attempt an identifier. A repeated submission with the same identifier should return the same attempt state rather than launch concurrent connect operations. A new attempt should cancel or supersede the old one in a controlled way.
On a platform that supports the design, test candidate credentials without immediately replacing the durable known-good record. Commit a versioned record atomically after the agreed success condition. Record integrity and schema version, and define startup behavior if power fails during the commit. Encryption at rest is useful only with an appropriate key-storage design; it does not replace authenticated provisioning.
Some SDK managers persist credentials before the application has completed its own validation. ESP-IDF 5.2.6, for example, documents a stored-credential provisioning check and failure/restart behavior in its Wi-Fi provisioning guide. Treat this as a version-specific integration constraint. Verify the chosen manager’s reset/reprovision APIs and implement the product state model around them; do not assume “credentials exist” means “installation succeeded.”
Keep an intentional recovery entrance
Define what reopens setup: an authenticated command, a physical button sequence or an installer tool. Specify hold duration, LED feedback and whether an accidental short press can change anything. A network-reset action should normally preserve calibration, device identity and unrelated application settings. Factory reset is a separate, clearly signalled operation.
A proposed policy might allow a ten-minute commissioning window, bound one router-join attempt to a configurable deadline, then offer a retry or restore the previous configuration. These numbers must be selected for the supported routers and installation workflow. Do not leave an unrestricted setup network permanently exposed simply because the first attempt failed.
If setup closes automatically, the phone needs an unambiguous way to learn the result. Offer status polling while reachable, a success token displayed before transition, an LED state or rediscovery on the destination network. A dropped TCP connection alone cannot distinguish success from a crash.
Design for the phone losing its path
Phones may prefer mobile data, leave a no-Internet Wi-Fi network or show a limited captive-portal browser. Test the supported Android/iOS versions with mobile data both enabled and disabled. Provide a documented local URL or app flow that works when automatic portal detection does not. Avoid requiring Internet-hosted scripts or fonts in a setup page that must work offline.
AP and station coexistence has radio-specific limits. On ESP32, the documented station/AP mode shares the home channel, with the station taking priority; joining a router on another channel can therefore affect the setup connection. See the vendor’s Wi-Fi driver guide, then verify behavior against the actual SDK and module revision. Linux chipsets likewise need driver-supported interface combinations; AP+STA must be tested rather than inferred from separate AP and STA demonstrations.
Keep the status endpoint resilient to reconnects. Store the latest attempt result beyond the HTTP connection and include the attempt ID, phase and a safe reason code. Ensure a stale browser tab cannot overwrite a newer successful attempt.
Protect the credential transfer and diagnostics
Use a per-device onboarding secret or other authenticated enrollment design suitable for the product. An open AP plus an unauthenticated password form exposes a sensitive setup path. Evaluate transport security and device identity verification together; a random self-signed certificate without a trust/discovery plan may only train installers to ignore warnings.
Do not copy sample logging that prints the Wi-Fi password. Log phase, elapsed time, SDK disconnect reason, retry count, firmware version and a redacted network identifier. Restrict diagnostic export and erase ephemeral candidate credentials when they are no longer needed. Limit attempts and concurrent sessions, and specify ownership when two phones try to configure the same unit.
Different failure reasons require different actions. Authentication rejection suggests checking credentials or security mode. No matching AP suggests band, range, hidden SSID or scan policy. DHCP timeout suggests the address service or local network. TLS or registration failures belong to the application path and can involve clock, certificates or account policy.
Make the acceptance matrix prove recovery
| Test | Expected recovery | Evidence to retain |
|---|---|---|
| Wrong password, then corrected password | New attempt accepted without reflashing or erasing identity | Attempt IDs, failure reason and final connection state |
| Router disappears during joining | Bounded timeout; known-good settings or setup remain recoverable | Phase timeline and retry/resource counters |
| Association succeeds; DHCP blocked | Address failure shown separately from authentication | Wi-Fi events and DHCP capture |
| Network works; cloud endpoint unavailable | Service failure identified; valid Wi-Fi configuration retained per policy | IP, DNS and application status without credentials |
| Power cut during receive, test and commit | Boot into a valid old/new configuration or deliberate recovery mode | Boot log, record version and integrity check |
| Phone leaves AP; second phone joins | Attempt ownership preserved; latest result recoverable | Client-visible status and concurrent-request behavior |
| Setup timeout and physical network reset | Access closes on schedule; authorized entry reopens it without losing calibration | Radio scan, button/LED record and settings comparison |
Repeat failures around the state transitions, not only at arbitrary times. Include router channel changes, weak signal and concurrent radio/application load. Count successful recoveries out of attempted trials, record all failures, and measure time to a usable state. Do not report only the average; a small tail of unbounded attempts can dominate support costs.
Expose a compact diagnostic contract
This illustrative status document is an application contract, not an SDK API. The reason and phase vocabularies should be versioned alongside the phone app:
{
"schema": 1,
"attempt_id": "setup-0042",
"phase": "waiting_for_ip",
"result": "pending",
"elapsed_ms": 12400,
"reason": null,
"can_retry": false
}
Choose monotonic time for attempt deadlines so a clock correction cannot lengthen or shorten a retry unexpectedly. A watchdog should detect a stuck worker without rebooting a healthy device just because the external router is absent. Track memory and socket use through repeated failed attempts to catch leaks that a one-time demonstration misses.
Agree on the complete commissioning deliverable
Obeita’s device connectivity service can frame the device, phone and router integration scope. The delivered ESP32 Wi-Fi and Bluetooth gateway project describes AP/STA-related project directions; its separate Mesh role is not evidence that this provisioning flow has already been implemented or qualified.
Provide the module and SDK versions, target phone list, supported router/security modes, current failure logs and required installer journey. The delivery package should include state definitions, phone-visible errors, credential handling, reset semantics and repeatable failure tests as well as the happy-path setup screen.