Skip to content

Add secondary WiFi adapter (wlan1) support#907

Open
PanGalactic wants to merge 1 commit into
pollen-robotics:mainfrom
PanGalactic:feat/secondary-wifi-wlan1
Open

Add secondary WiFi adapter (wlan1) support#907
PanGalactic wants to merge 1 commit into
pollen-robotics:mainfrom
PanGalactic:feat/secondary-wifi-wlan1

Conversation

@PanGalactic
Copy link
Copy Markdown

Summary

Add dashboard support for managing a secondary WiFi adapter (wlan1) on boards with Broadcom chips that support virtual interfaces. This enables simultaneous connections — e.g. wlan0 for home WiFi and wlan1 for a robot's point-to-point hotspot.

  • 5 new API endpoints for wlan1: status, scan, connect, disconnect, create interface
  • New dashboard section mirroring the primary WiFi UI
  • Fix: primary status now correctly filters to wlan0 only (previously, wlan1 connections could mask wlan0 state)
  • Add IP address display to both primary and secondary status

Changes to existing code

Only 3 lines of existing code were modified (all in wifi_config.py):

1. get_current_wifi_mode() — mode detection

# Before:
elif any(c.device != "--" for c in conn):
# After:
elif any(c.device == "wlan0" for c in conn):

Fixes latent bug where wlan1 connection could prevent wlan0 hotspot creation.

2. get_wifi_status() — known_networks filter

# Before:
known_networks = [c.name for c in connections if c.name != "Hotspot"]
# After:
known_networks = [c.name for c in connections if c.name != "Hotspot" and not c.name.endswith("-wlan1")]

Hides secondary adapter connection profiles (suffixed -wlan1) from primary UI.

3. get_wifi_status() — connected_network filter

# Before:
connected_network = next((c.name for c in connections if c.device != "--"), None)
# After:
connected_network = next((c.name for c in connections if c.device == "wlan0"), None)

Primary status now correctly reports only wlan0 connection.

New API endpoints

Method Path Description
GET /wifi/status2 Secondary adapter status (exists, connected, ssid, ip, known_networks, busy)
POST /wifi/scan2 Scan for networks visible from wlan1
POST /wifi/connect2 Connect wlan1 to a network
POST /wifi/disconnect2 Disconnect wlan1
POST /wifi/create_interface Create wlan1 virtual interface via iw if missing

Design notes

  • Why raw subprocess for wlan1: The nmcli Python library doesn't support ifname targeting for virtual interfaces. Primary adapter continues using the nmcli library.
  • Connection naming: Secondary connections are named {ssid}-wlan1 to keep NM profiles distinct per interface.
  • Interface creation: Uses iw dev wlan0 interface add wlan1 type managed via sudo. Requires passwordless sudo (standard on Reachy — daemon runs as pollen with sudo).
  • Subprocess patterns: All subprocess calls use timeout=NMCLI_COMMAND_TIMEOUT and exception handling matching volume.py patterns.

Backward compatibility

  • GET /wifi/status — same fields + new ip_address (additive, non-breaking)
  • All existing endpoints completely untouched
  • All new endpoints use distinct paths — no collisions
  • Hotspot fallback logic fully preserved

Test plan

  • Primary WiFi section works as before (status, scan, connect)
  • Secondary WiFi section shows wlan1 status correctly
  • Can disconnect wlan1 and reconnect
  • Hotspot fallback still works when wlan0 disconnects
  • Daemon restarts cleanly with new code
  • Both endpoints return correct JSON
  • Test on board without wlan1 — should show "WiFi adapter not available" with Create Interface button

🤖 Generated with Claude Code

Add dashboard support for managing a secondary WiFi adapter (wlan1) on
boards with Broadcom chips that support virtual interfaces. This enables
simultaneous connections — e.g. wlan0 for home WiFi and wlan1 for a
robot's point-to-point hotspot.

Backend (wifi_config.py):
- 5 new endpoints: GET /status2, POST /scan2, POST /connect2,
  POST /disconnect2, POST /create_interface
- SecondaryWifiStatus Pydantic model
- Helper functions for wlan1 operations using subprocess (nmcli
  library doesn't support ifname targeting for virtual interfaces)
- All subprocess calls use timeout and exception handling matching
  volume.py patterns
- Fix: primary status filters to wlan0 only (previously wlan1
  connections could mask wlan0 state and prevent hotspot creation)
- Add ip_address field to primary WifiStatus (additive, non-breaking)

Frontend (wifi.html + wifi.js):
- Secondary WiFi section mirroring primary UI structure
- Network/IP display for both adapters
- Status polling for both adapters at 1s interval
- Disconnect button and Create Interface fallback for missing wlan1

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@FabienDanieau FabienDanieau changed the base branch from develop to main March 3, 2026 14:21
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.

1 participant