Skip to content

mac-os support stopped #56

@bencium

Description

@bencium

The wifi-densepose sensing server's --source wifi path only works on Windows (uses
netsh commands). On macOS, --source auto silently falls back to simulation. The user
wants real WiFi RSSI sensing on their M2 Pro MacBook — no simulated data.

macOS 26.3 has removed the legacy airport CLI. CoreWLAN (via Swift) is the working
API and provides real RSSI, channel, SSID, and noise data for all visible networks.
BSSIDs are redacted by macOS privacy policy, but SSID+channel uniquely identifies
each AP for the pipeline.

Goal: Add a macOS CoreWLAN adapter so --source wifi works on macOS with real RSSI
data flowing through the 8-stage sensing pipeline (motion detection, breathing
extraction, presence).

Approach

  1. Create Swift helper binary: macos-wifi-scan

A small Swift CLI that calls CoreWLAN and outputs JSON to stdout. The Rust adapter
calls this via Command::new() — same pattern as netsh on Windows.

File: rust-port/wifi-densepose-rs/tools/macos-wifi-scan/main.swift

// Calls CWWiFiClient.shared().interface().scanForNetworks()
// Outputs JSON array: [{ssid, rssi, noise, channel, band, phy_mode}, ...]
// Also includes connected network info

Build with: swiftc -framework CoreWLAN -framework Foundation -o macos-wifi-scan
main.swift

  1. Create Rust macOS adapter: MacosCoreWlanScanner

File: rust-port/wifi-densepose-rs/crates/wifi-densepose-wifiscan/src/adapter/macos_sc
anner.rs

Implements the WlanScanPort trait:

  • scan() — calls the Swift helper, parses JSON output, returns Vec
  • connected() — returns the connected network's observation
  • Uses SSID:channel as a synthetic BSSID (since macOS redacts real BSSIDs)
  • Converts RSSI dBm to amplitude via existing rssi_to_amplitude()
  • Maps channel to BandType via existing BandType::from_channel()
  • Maps PHY mode string to RadioType
  1. Register adapter in module

File: rust-port/wifi-densepose-rs/crates/wifi-densepose-wifiscan/src/adapter/mod.rs

Add pub mod macos_scanner; and re-export MacosCoreWlanScanner.

File: rust-port/wifi-densepose-rs/crates/wifi-densepose-wifiscan/src/lib.rs

Add re-export at crate root.

  1. Add macOS WiFi probe + task to sensing server

File: rust-port/wifi-densepose-rs/crates/wifi-densepose-sensing-server/src/main.rs

Changes:

  • Add probe_macos_wifi() — runs the Swift helper with --probe flag, returns true if
    it outputs valid JSON
  • Add macos_wifi_task() — same structure as windows_wifi_task() but calls the Swift
    helper instead of netsh. Feeds results into the same BssidRegistry +
    WindowsWifiPipeline (rename internally to RssiPipeline is optional but these work
    as-is)
  • Update auto-detection (line ~1697): add probe_macos_wifi() check between ESP32 and
    simulation fallback
  • Update --source wifi match (line ~1806): dispatch to macos_wifi_task() on macOS,
    windows_wifi_task() on Windows
  1. Build integration

File: rust-port/wifi-densepose-rs/crates/wifi-densepose-sensing-server/Cargo.toml

No new Rust dependencies needed — std::process::Command + serde_json (already
available) handle the Swift subprocess.

The Swift binary is built separately and expected at a known path relative to the
server binary or in $PATH.

Files to Create
File: rust-port/wifi-densepose-rs/tools/macos-wifi-scan/main.swift
Purpose: Swift CoreWLAN helper binary
────────────────────────────────────────
File: rust-port/wifi-densepose-rs/tools/macos-wifi-scan/build.sh
Purpose: Build script for the Swift binary
────────────────────────────────────────
File: rust-port/wifi-densepose-rs/crates/wifi-densepose-wifiscan/src/adapter/macos_sc
anner.rs
Purpose: Rust macOS adapter
Files to Modify
File: crates/wifi-densepose-wifiscan/src/adapter/mod.rs
Change: Add macos_scanner module + exports
────────────────────────────────────────
File: crates/wifi-densepose-wifiscan/src/lib.rs
Change: Add MacosCoreWlanScanner re-export
────────────────────────────────────────
File: crates/wifi-densepose-sensing-server/src/main.rs
Change: Add probe_macos_wifi(), macos_wifi_task(), update auto-detect + source
dispatch
Existing Code to Reuse

  • WlanScanPort trait — crates/wifi-densepose-wifiscan/src/port/scan_port.rs
  • BssidObservation, BssidId, BandType, RadioType —
    crates/wifi-densepose-wifiscan/src/domain/bssid.rs
  • BssidRegistry — crates/wifi-densepose-wifiscan/src/domain/registry.rs
  • WindowsWifiPipeline — crates/wifi-densepose-wifiscan/src/pipeline/orchestrator.rs
  • MultiApFrame — crates/wifi-densepose-wifiscan/src/domain/frame.rs
  • WifiScanError — crates/wifi-densepose-wifiscan/src/error.rs
  • windows_wifi_task() as template —
    crates/wifi-densepose-sensing-server/src/main.rs:486-663
  • rssi_to_amplitude(), pseudo_phase() —
    crates/wifi-densepose-wifiscan/src/domain/bssid.rs:191-217

Verification

  1. Build the Swift helper: cd tools/macos-wifi-scan && ./build.sh
  2. Test it standalone: ./macos-wifi-scan — should print JSON with real RSSI values
  3. Build the Rust workspace: cargo build --release
  4. Run tests: cargo test --workspace
  5. Start server: ./target/release/sensing-server --source wifi --ui-path ../../ui
  6. Verify real data: curl http://localhost:8080/api/v1/sensing/latest — should show
    source: "wifi:" with real RSSI values, not simulated
  7. Open UI: http://localhost:8080/ui/index.html — signal field should respond to
    physical movement near the Mac
  8. Verify vitals: curl http://localhost:8080/api/v1/vital-signs — breathing/motion
    from real RSSI variance

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions