Skip to content

Persist ESP32 Wi-Fi networks and WebConfig in NVS - #61

Closed
swinp wants to merge 1 commit into
thinger-io:masterfrom
swinp:esp32-nvs-wifi-config
Closed

swinp wants to merge 1 commit into
thinger-io:masterfrom
swinp:esp32-nvs-wifi-config

Conversation

@swinp

@swinp swinp commented Oct 19, 2026

Copy link
Copy Markdown
Contributor

ESP32 WebConfig currently keeps its PSON configuration in SPIFFS, while the WiFiMulti list populated by add_wifi() lives only in RAM. Persist both in NVS so configuration and the complete registered network list survive a reboot.

WiFiManager's native saved AP already uses the ESP32 core's persistence; this change adds an explicit registry for multiple personal networks and migrates the entire WebConfig object rather than assuming that the upstream PSON schema contains Wi-Fi credentials.

Changes

  • Store the full, versioned PSON object in thinger/config, preserving custom, nested, binary and unknown fields. Subsequent portal saves update the loaded object instead of discarding unregistered fields.
  • Import legacy /config.pson only when the NVS record is absent. Validate the file, commit and verify the NVS bytes, reload from NVS, then remove the file. Mount errors never trigger formatting; existing, cleared or invalid NVS records never fall back to a stale file.
  • Persist the complete add_wifi() registry in thinger/wifi. Own credential strings, update existing SSIDs without duplicates, avoid unchanged writes, and lazily reconstruct WiFiMulti before connecting after reboot.
  • Have WebConfig recognize restored networks and persist successful portal submissions in the same registry.
  • Add ESP32 list_wifi(ssids), remove_wifi(ssid) and clear_wifi(). Listing returns independent SSID snapshots without passwords. Deletion and clearing commit the remaining list before rebuilding WiFiMulti. An empty saved list blocks native-driver fallback across restarts.
  • Preserve the separate PSON configuration and RAM enterprise settings when managing personal networks. clean_credentials() writes a PSON tombstone to prevent stale-file reimport.

Compatibility and recovery

  • add_wifi() retains its void signature; wifi_storage_ok() reports errors. Explicit restore_wifi_networks() is available.
  • SPIFFS is the default legacy source. Define THINGER_ESP32_CONFIG_USE_LITTLEFS for ESP32 deployments that used LittleFS. New devices without a legacy filesystem must define THINGER_ESP32_CONFIG_SKIP_LEGACY_MIGRATION; an unreadable legacy volume otherwise stops loading to preserve its data.
  • Retain the old filesystem and NVS partitions during the firmware update. The PSON payload limit is configurable (16 KiB by default). Credential limits match the tested WiFiMulti implementations: 1–31 SSID bytes and up to 63 password bytes.
  • ESP8266 keeps its existing backend. add_wifi_enterprise() remains RAM-only. Explicit later add_wifi() calls, including unconditional setup calls, register networks again after removal/clearing.
  • Storage errors are reported rather than silently replacing data. A failed readback can follow a successful commit; reloading determines the surviving complete record. Explicit clear_wifi() can recover a malformed Wi-Fi registry without erasing other NVS settings.

Validation

  • Passed all six host integration variants: unmodified WiFiMulti from ESP32 cores 2.0.17 and 3.3.12, each with SPIFFS, LittleFS and no legacy filesystem.
  • Tests use the real ThingerWifi, ESP32 WebConfig and PSON code, with simulated radio/NVS/filesystem operations. Coverage includes reboot without new registration calls, selection/fallback, open/hidden networks, password updates, list/delete/clear, failed writes/commits/readbacks, stale-driver suppression, enterprise coexistence, complete PSON migration and preservation of unrelated settings.
  • Compiled the API integration sketch for esp32:esp32:esp32 with core 3.3.12 and WiFiManager 2.0.17 (87% flash, 14% static RAM).
  • Added the host matrix to CI and the API sketch to ESP32/Nano ESP32 compilation coverage. Vendored test fixtures retain source references and LGPL licenses.
  • Physical-board and physical power-loss validation remain pending.

Fixes #58.

Migrate the complete legacy PSON configuration and add persistent WiFiMulti
restoration plus list_wifi, remove_wifi, and clear_wifi management APIs.

Add host integration tests for ESP32 cores 2.x/3.x and board compilation coverage.

Refs thinger-io#58
@alvarolb

Copy link
Copy Markdown
Member

@swinp thanks for this PR! Most of it is already covered by 2.46.0 (#58): ThingerESP32WebConfig stores its configuration in NVS, migrating the SPIFFS file of previous versions on the first boot, and without formatting SPIFFS. We also found the real cause of the "lost" WiFi credentials (WiFiManager checked the saved network before the WiFi driver was initialized), and the config portal now opens again when the saved network is not available (#49).

The remaining part, persisting the networks added with add_wifi() in NVS (with list_wifi()/remove_wifi()), is a bigger change (+3300 lines, including copies of WiFiMulti) that we'd rather not maintain for now: networks set in the sketch are already in the firmware, so it only helps when networks are added at runtime. If you have a use case for that, please open an issue and we'll look for a smaller approach.

Closing it, thanks again for all the contributions these days!

@alvarolb alvarolb closed this Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

On the ESP32, use NVS to store Wi-Fi SSIDs and passwords.

2 participants