Wi-Fi operations for Improv provisioning: scan for networks, apply submitted
credentials, and derive the post-provisioning redirect URL. The seam the
Improv manager calls into.
All VintageNet access is guarded (Code.ensure_loaded?) so the module loads on
host, and is injectable (:scan_trigger / :vintage_get / :configure_fn) so
the pure shaping — the configure map, the AP→network mapping, the secured? rule —
is host-tested without a radio. The Wi-Fi interface defaults to "wlan0";
pass ifname: in each call's opts to target another interface.
scan_networks/1 reads the live access_points property (kept fresh by
wpa_supplicant) rather than VintageNetWiFi.quick_scan/1, whose fresh-scan +
2 s sleep read an empty list mid-scan on hardware. It also kicks an async
VintageNet.scan/1 to refresh the property for the next call.
Summary
Functions
Apply submitted credentials to the Wi-Fi interface. :configure_fn (2-arity
(ifname, config) -> term) is injectable for tests.
VintageNet config map for a submitted SSID/password. An empty password yields
an open (key_mgmt: :none) network; otherwise WPA-PSK. Pure.
Map a VintageNetWiFi.AccessPoint-shaped value to a network/0. Pure.
The web-UI URL to hand back to the provisioner once joined, or nil if no
IPv4 address is bound yet. :vintage_get injectable for tests.
Nearby networks → {:ok, [network]} (empty SSIDs dropped, deduped by SSID
keeping the strongest signal), or {:error, reason}.
Whether an AP's :flags indicate a secured network. Pure.
Types
Functions
Apply submitted credentials to the Wi-Fi interface. :configure_fn (2-arity
(ifname, config) -> term) is injectable for tests.
VintageNet config map for a submitted SSID/password. An empty password yields
an open (key_mgmt: :none) network; otherwise WPA-PSK. Pure.
Map a VintageNetWiFi.AccessPoint-shaped value to a network/0. Pure.
The web-UI URL to hand back to the provisioner once joined, or nil if no
IPv4 address is bound yet. :vintage_get injectable for tests.
Nearby networks → {:ok, [network]} (empty SSIDs dropped, deduped by SSID
keeping the strongest signal), or {:error, reason}.
Reads the live ["interface", ifname, "wifi", "access_points"] property that
wpa_supplicant keeps refreshed via periodic background scans — NOT
VintageNetWiFi.quick_scan/1, which triggers a fresh ioctl scan and only waits
2s, so it lands in the empty window mid-scan (HW-found: returned 0 while the
property held 31 APs). We also kick an async VintageNet.scan/1 to keep the
property fresh for the next request. :vintage_get/:scan_trigger injectable.
Whether an AP's :flags indicate a secured network. Pure.