Skip to content

[1.4] core: services: wifi: WifiManager: Start without a wlan interface - #4445

Merged
joaoantoniocardoso merged 7 commits into
bluerobotics:1.4-devfrom
patrickelectric:start-without-wlan-14
Sep 14, 2026
Merged

joaoantoniocardoso merged 7 commits into
bluerobotics:1.4-devfrom
patrickelectric:start-without-wlan-14

Conversation

@patrickelectric

Copy link
Copy Markdown
Member

wpa_supplicant fails when there is no wlan adapter.

Cherry-pick of #4215
Fix #4210

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
…s gone

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
…dapter

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
The attribute was only created inside connect, which never runs when
there is no socket to talk to, so the hotspot property raised
AttributeError instead of building the manager.

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
…ects

It was set before the connection was attempted, so the udp fallback
working was reported to the frontend as no wifi adapter.

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
Both handlers use the same state now, the frontend says there is no
adapter on bookworm as well.

Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
Signed-off-by: Patrick José Pereira <patrickelectric@gmail.com>
@github-actions

Copy link
Copy Markdown

Automated PR Review

0. Summary

  • Verdict: MINOR SUGGESTIONS ✏️

Cherry-pick of #4215 to 1.4-dev making the wifi service survive startup on hosts without a wlan interface: adds wpa_path is None guards on the wpa_supplicant handler paths (status, get_wifi_available, get_saved_wifi_network, supports_hotspot, hotspot_is_running, hotspot_credentials, set_hotspot_credentials), makes start() early-return instead of raising when the UDP fallback also fails, aligns the networkmanager handler to return state="unavailable", adds pytest coverage, and surfaces the unavailable state in the frontend WifiManager card / WifiUpdater polling loop.

1. Correctness & Implementation Bugs

  • 1.1 [minor] core/services/wifi/wifi_handlers/wpa_supplicant/WifiManager.py:585 — when the UDP fallback fails inside start(), the service silently returns and auto_reconnect / start_hotspot_watchdog are never scheduled. The device is then locked in the unavailable state for the whole process lifetime even if a USB wifi adapter is later plugged in. Consider scheduling a periodic retry of start() (or at least logging that recovery requires a restart) so the "no wlan at boot" case isn't permanent.
  • 1.2 [minor] core/services/wifi/wifi_handlers/wpa_supplicant/WifiManager.py:99self.wpa_path = str(path) stores "('127.0.0.1', 6664)" when path is the UDP fallback tuple. wpa_path is now overloaded as both a filesystem socket path and a truthy sentinel; anything that later interprets it as an actual path (logs, error strings, future consumers) will get a confusing value. A dedicated self._connected: bool (or storing the raw path and computing str(...) only for display) would be clearer.
  • 1.3 [minor] core/services/wifi/wifi_handlers/wpa_supplicant/WifiManager.py:494 — the new wpa_path is None branch in hotspot_credentials() reads from self._settings_manager.settings directly, but every other guarded method returns an empty/false placeholder. That means the frontend can display credentials for a hotspot that physically cannot exist. Consider returning WifiCredentials(ssid="", password="") (or an explicit "unavailable" signal) to stay consistent with the rest of the guards.

3. Security

  • No findings.

6. Code Quality & Style

  • 6.1 [minor] "unavailable" is now a magic string duplicated across networkmanager.py:420, WifiManager.py:341, WifiUpdater.vue:43, and WifiManager.vue:83. Given it is now part of the backend/frontend contract, promote it to a shared constant (e.g. extend ConnectionStatus in typedefs.py, or add a WifiState enum) rather than relying on string equality in two languages.
  • 6.2 [nit] core/services/wifi/wifi_handlers/wpa_supplicant/WifiManager.py:98 — the comment ("run only returns when the socket is connected...") is genuinely useful; nothing to change. Noted only to say: keep it.

7. Tests

  • 7.1 [minor] core/services/wifi/test_wifi_manager.py:34test_reports_available_after_connecting doesn't actually exercise the fallback the comment claims. It calls WifiManager.connect(("127.0.0.1", 6664)) directly on a bare __new__ instance and relies on the try/except Exception inside connect() swallowing the AttributeError from the missing _settings_manager. That means the test passes even if the fallback logic in start() regressed. Consider driving WifiManager.start() with args.socket_name unset and os.scandir mocked to return no sockets, so the actual fallback path is covered.
  • 7.2 [minor] core/services/wifi/test_wifi_manager.py:36monkeypatch.setattr(manager.wpa, "run", ...) patches the class-level WPASupplicant instance shared with any other test running under pytest-xdist. monkeypatch unpatches at teardown, but during the test the shared object is mutated. Prefer patching WifiManager.wpa (or injecting a fresh mock instance) to keep the test isolated.
  • 7.3 [nit] No test covers the new hotspot_credentials() / set_hotspot_credentials() guards or the WifiStatus(state="unavailable") shape returned by status(). A quick round-trip on those would prevent silent contract drift with the frontend.

8. Documentation

  • 8.1 [nit] core/services/wifi/test_wifi_manager.py:39 — the comment "The udp socket is the fallback when there is no wpa_supplicant socket, it still means wifi works" is misleading given the test doesn't verify that path (see 7.1). Either delete the comment or restructure the test so the comment is true.

Generated by PR Review Bot. This is advisory, a human reviewer must still approve.

@patrickelectric
patrickelectric requested a review from a team September 14, 2026 17:20
@joaoantoniocardoso
joaoantoniocardoso merged commit ee4826e into bluerobotics:1.4-dev Sep 14, 2026
7 checks passed
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.

2 participants