Add Wi-Fi commissioning: SoftAP captive portal with IPv6 support
Implements first-boot Wi-Fi setup with no companion app required: a SoftAP + captive portal (DNS wildcard redirect, DHCP option 114, HTTP form) lets the user submit Wi-Fi credentials from any browser. On submit, credentials are saved to NVS and the device switches to STA mode; on subsequent boots it reconnects automatically via stored credentials. dns_server.c/.h are vendored from ESP-IDF's official captive_portal example (Unlicense/CC0). Requests both link-local and global IPv6 addresses once the STA connection has an IPv4 address (not on WIFI_EVENT_STA_CONNECTED -- esp_netif_create_ip6_linklocal() reliably fails there because esp-netif's own handler, which marks the lwIP netif "up", hasn't run yet due to event-handler registration order). Verified end-to-end on real ESP32-C6 hardware: SoftAP comes up, credential submission works, STA reconnects on reboot, and both a link-local and a router-assigned global IPv6 address are obtained via SLAAC. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,17 @@ Also owns Wi-Fi/MQTT configuration storage for now (not broken out into its own
|
||||
|
||||
Future transports (Zigbee, Thread, Matter) should implement the same publish API as alternate backends behind this component's interface, without changing callers.
|
||||
|
||||
## Wi-Fi commissioning
|
||||
|
||||
`include/commissioning.h` / `src/commissioning.cpp` implement first-time Wi-Fi setup, no companion app required:
|
||||
|
||||
- On boot, `try_stored_credentials()` attempts to connect using credentials saved in NVS from a previous session.
|
||||
- If none exist (or the caller chooses to), `start_commissioning()` opens a SoftAP (`Kvida-XXXXXX`, derived from the MAC) with a captive portal: a DNS server (`src/dns_server.c`/`.h`, vendored from ESP-IDF's official `captive_portal` example, Unlicense/CC0) answers every query with the AP's own IP, and DHCP option 114 plus a 404-redirects-to-`/` HTTP handler get most phones/laptops to auto-open the setup page (`src/portal.html`) in a plain browser.
|
||||
- Submitting the form (`POST /connect`) saves the credentials to NVS and switches Wi-Fi to STA mode. The AP is open (no password) by design -- see the comment above `ap_config.ap.authmode` in `commissioning.cpp` for the reasoning and the tradeoff.
|
||||
- A 5-minute `esp_timer` closes the commissioning window automatically if nobody submits credentials.
|
||||
- **IPv6**: once STA gets its IPv4 address (`IP_EVENT_STA_GOT_IP` -- not `WIFI_EVENT_STA_CONNECTED`, see the comment in `commissioning.cpp` for why that timing matters), `esp_netif_create_ip6_linklocal()` requests a link-local address (`CONFIG_LWIP_IPV6=y` is set explicitly in `sdkconfig.defaults`); `IP_EVENT_GOT_IP6` is logged when it arrives. Verified end-to-end on real ESP32-C6 hardware.
|
||||
- Not yet wired up: re-entering commissioning on an already-configured device needs a physical trigger (the user button) per AGENTS.md's "configuration mode requires physical user interaction" principle -- blocked on `drivers` having a real button implementation. Network scanning (SSID dropdown instead of free text) was left out of this first pass to keep scope tight.
|
||||
|
||||
TODO: built on ESP-IDF's own `esp_wifi` and `mqtt_client` (`esp-mqtt`) components once real code lands — both ship with ESP-IDF, no extra registry dependency needed.
|
||||
|
||||
TODO: A/B OTA update-checking belongs here, driven by ESP-IDF's native `esp_ota_ops` against the `ota_0`/`ota_1` partitions in `partitions.csv` — no extra dependency needed either.
|
||||
|
||||
Reference in New Issue
Block a user