Skip to main content

Cross-platform Wi-Fi controller with pluggable providers for macOS, Linux, and Windows.

Project description

wifi-controller

A cross-platform Wi-Fi controller for Python with 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.

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 (extras/ssid_scanner/) uses CoreWLAN + CoreLocation to return real SSIDs on macOS 15+
  • Zero dependencies -- pure Python, stdlib only

Installation

pip install wifi-controller

Or with Poetry:

poetry add wifi-controller

Quick Start

from wifi_controller import WiFiController

wifi = WiFiController()

# Get current network
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")

# Poll for a specific SSID
found = wifi.scan_for_ssid("MyNetwork", timeout_sec=30)

# Disconnect
wifi.disconnect()

macOS 15+ SSID Redaction

Starting with macOS 15 (Sequoia), Apple redacts SSID information from system_profiler, CoreWLAN, and other 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. To get real SSIDs on macOS 15+, build the Swift scanner from extras/ssid_scanner/:

# Prerequisites: Xcode Command Line Tools + Apple Development certificate
make -C extras/ssid_scanner check   # verify prerequisites
make -C extras/ssid_scanner all     # build and sign

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"  # path to built binary

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)

# Now scan() returns real SSIDs on macOS 15+
networks = wifi.scan()

Custom Providers

Implement any of the four provider ABCs to add support for additional tools:

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  # check if your tool is installed

    def scan_ssids(self, interface: str, timeout: int = 15) -> list[SSIDInfo]:
        # ... your implementation ...
        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 ABCs:

ABC Operation
CurrentSSIDProvider Get the currently-connected SSID
SSIDScanProvider Scan for nearby networks
SSIDConnectProvider Connect to a network (SSID + password)
SSIDDisconnectProvider Disconnect from the current network

Higher priority providers are tried first. The first provider whose is_available() returns True is used and cached for subsequent calls.

Project Layout

wifi_controller/
├── src/wifi_controller/       # Python package (ships on PyPI)
│   ├── __init__.py            # WiFiController orchestrator
│   ├── _types.py              # SSIDInfo, WiFiConnectionError
│   ├── _abc.py                # Four provider ABCs
│   ├── _macos.py              # Built-in macOS providers
│   ├── _linux.py              # Built-in Linux providers
│   └── _swift.py              # Python wrappers for Swift binary
├── extras/ssid_scanner/       # Swift source (not on PyPI, clone to use)
│   ├── scan.swift             # CoreWLAN + CoreLocation scanner
│   ├── Makefile               # Build, sign, test
│   └── *.plist                # App bundle configuration
├── docs/                      # Architecture diagrams (PlantUML)
└── tests/                     # Unit tests

Architecture

See docs/ for PlantUML diagrams covering:

  • Class diagram -- provider ABCs, WiFiController, built-in implementations
  • Sequence diagram -- provider resolution and operation flow
  • Component diagram -- package structure and platform boundaries

Development

# Install dev dependencies
poetry install

# Run tests
poetry run pytest

# Lint
poetry run ruff check src/ tests/

# Format
poetry run ruff format src/ tests/

License

MIT -- see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

wifi_controller-0.1.0.tar.gz (12.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

wifi_controller-0.1.0-py3-none-any.whl (14.7 kB view details)

Uploaded Python 3

File details

Details for the file wifi_controller-0.1.0.tar.gz.

File metadata

  • Download URL: wifi_controller-0.1.0.tar.gz
  • Upload date:
  • Size: 12.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.10.14 Darwin/25.3.0

File hashes

Hashes for wifi_controller-0.1.0.tar.gz
Algorithm Hash digest
SHA256 20eec083030f47281be12b69aac11068254c5baed11d801999cd8b1054ecaafa
MD5 b10cdfec01a60048078c75e9066c1d27
BLAKE2b-256 1d6ac3163111322ffe4fd1feb24659e220451226bccbb45a24791dd4be4a9609

See more details on using hashes here.

File details

Details for the file wifi_controller-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: wifi_controller-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 14.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.1.3 CPython/3.10.14 Darwin/25.3.0

File hashes

Hashes for wifi_controller-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4e1838f47b6b029e3d71f07d1a5c310b2f1b22f4bdbcb2a95aba0d941fed1991
MD5 ae3c025c813134e8d58aaefa815e458a
BLAKE2b-256 e6be474a3cad541dbcb4c4994153a5a59d831c481ad549e4b1af9eb781256acb

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page