wifi-controller
A cross-platform Wi-Fi controller for Python with a pluggable provider architecture.
Supports macOS and Linux out of the box, with an optional Swift-based scanner for macOS 15+ where Apple redacts SSIDs without Location Services authorization.
Why wifi-controller?
Most existing Wi-Fi libraries:
- Are OS-specific or inconsistent across platforms
- Depend heavily on fragile system tools
- Are difficult to extend or test
wifi-controller provides:
- A unified API across platforms
- A pluggable provider system
- Clean abstractions suitable for automation and QA workflows
Platform Support
| Platform | Status | Notes |
|---|---|---|
| macOS | ✅ Supported | Full support; SSID redaction workaround available |
| Linux | ⚠️ Partial | Requires nmcli or iwgetid |
| Windows | ❌ Not yet implemented |
Features
- Cross-platform — built-in providers for macOS (
networksetup,ipconfig,system_profiler) and Linux (nmcli,iwgetid) - Pluggable providers — register your own scan/connect/disconnect implementations with priority-based resolution
- macOS SSID redaction workaround — optional Swift scanner (see below)
- Zero Python dependencies — uses only the standard library (relies on native system tools where applicable)
Installation
pip install wifi-controller
Or with Poetry:
poetry add wifi-controller
⚠️ macOS 15+ (Sequoia) Users
Apple redacts SSID information unless the process has Location Services authorization.
👉 This means default Python providers will return redacted SSIDs.
See macOS 15+ SSID Redaction below for the workaround.
Quick Start
Get current network
from wifi_controller import WiFiController
wifi = WiFiController()
ssid = wifi.get_current_ssid()
print(f"Connected to: {ssid}")
Scan nearby networks
networks = wifi.scan()
for net in networks:
print(f"{net.ssid} (RSSI={net.rssi}, CH={net.channel})")
Connect to a network
wifi.connect("MyNetwork", "hunter2")
Wait for a network to appear
found = wifi.scan_for_ssid("MyNetwork", timeout_sec=30)
Disconnect
wifi.disconnect()
Specify interface (optional)
wifi = WiFiController(interface="wlan0")
Handling connection errors
from wifi_controller import WiFiController, WiFiConnectionError
wifi = WiFiController()
try:
wifi.connect("MyNetwork", "wrong-password")
except WiFiConnectionError as e:
print(f"Failed to connect: {e}")
Use Cases
- Automated Wi-Fi testing
- Embedded device validation
- Network orchestration in CI pipelines
macOS 15+ SSID Redaction
Starting with macOS 15 (Sequoia), Apple redacts SSID information from system APIs unless the calling process has Location Services authorization via a signed app bundle.
The built-in Python providers cannot work around this limitation.
Workaround: Swift Scanner
Build the Swift scanner from extras/ssid_scanner/:
# Prerequisites: Xcode Command Line Tools + Apple Development certificate
make -C extras/ssid_scanner check
make -C extras/ssid_scanner all
Then register the Swift providers:
from wifi_controller import WiFiController
from wifi_controller.swift import (
SwiftSsidScannerCurrentSSID,
SwiftSsidScannerScan,
SwiftSsidScannerConnect,
SwiftSsidScannerDisconnect,
)
wifi = WiFiController()
binary = "extras/ssid_scanner/ssid_scanner"
wifi.register_scan_provider(SwiftSsidScannerScan(binary), priority=10)
wifi.register_current_ssid_provider(SwiftSsidScannerCurrentSSID(binary), priority=10)
wifi.register_connect_provider(SwiftSsidScannerConnect(binary), priority=10)
wifi.register_disconnect_provider(SwiftSsidScannerDisconnect(binary), priority=10)
networks = wifi.scan()
Custom Providers
Providers are resolved by priority. The first available provider is selected and cached for reuse.
Implement any of the provider ABCs:
from wifi_controller import WiFiController, SSIDScanProvider, SSIDInfo
class MyCustomScanner(SSIDScanProvider):
@property
def name(self) -> str:
return "my_scanner"
def is_available(self) -> bool:
return True
def scan_ssids(self, interface: str, timeout: int = 15) -> list[SSIDInfo]:
return [
SSIDInfo(
ssid="Example",
bssid="00:11:22:33:44:55",
rssi=-42,
channel=6,
)
]
wifi = WiFiController()
wifi.register_scan_provider(MyCustomScanner(), priority=20)
Provider Types
| ABC | Operation |
|---|---|
CurrentSSIDProvider |
Get current SSID |
SSIDScanProvider |
Scan networks |
SSIDConnectProvider |
Connect |
SSIDDisconnectProvider |
Disconnect |
Caveats
- macOS 15+ requires Location Services authorization for real SSIDs
- Linux requires
nmclioriwgetid - Interface names may vary (
en0,wlan0, etc.) - Behavior depends on underlying OS capabilities and drivers
Architecture
See docs/ for PlantUML diagrams:
- Class diagram — provider abstractions
- Sequence diagram — resolution flow
- Component diagram — platform boundaries
Development
poetry install
poetry run pytest
poetry run ruff check src/ tests/
poetry run ruff format src/ tests/
Status
Early development (v0.x).
APIs may change between releases.
License
MIT — see LICENSE.
Metadata
Release files for wifi-controller 0.1.7
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| wifi_controller-0.1.7.tar.gz | 13.6 kB | Without provenance | Details for wifi_controller-0.1.7.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| wifi_controller-0.1.7-py3-none-any.whl | Python 3 | none | any | Details for wifi_controller-0.1.7-py3-none-any.whl |
Total release size: 30.0 kB
Release files / wifi_controller-0.1.7.tar.gz
| Download URL | wifi_controller-0.1.7.tar.gz |
|---|---|
| Size | 13.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
fcbca7c31b10646c4c58e022c89da3e889c17fc8909c3ab13adc4d8467c716ee
|
|
BLAKE2b-256 checksum How to use checksums |
589bdb4a78abd74c11a0a708703b370ce265ba57167227c8658a6ce55860b0fd
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.10.14 Darwin/25.6.0
|
Release files / wifi_controller-0.1.7-py3-none-any.whl
| Download URL | wifi_controller-0.1.7-py3-none-any.whl |
|---|---|
| Size | 16.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7416dea0119e3fee35326e608e5cb50c00ddb8e3558348a7c8bd675a5df9e58a
|
|
BLAKE2b-256 checksum How to use checksums |
f9c2f800744a95830608703c7623da77d6e4bad56efc1664a271684269a36bb4
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
poetry/2.1.3 CPython/3.10.14 Darwin/25.6.0
|
Security for wifi-controller 0.1.7
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.