feat(sensing): native macOS CoreWLAN WiFi sensing adapter #64

Merged
zqyhimself merged 2 commits from feature/macos-corewlan into main 2026-03-01 23:59:11 +08:00
zqyhimself commented 2026-03-01 21:12:05 +08:00 (Migrated from github.com)

Add native macOS LiDAR / WiFi sensing support via CoreWLAN:

  • mac_wifi.swift: Swift helper to poll RSSI/Noise at 10Hz
  • MacosWifiCollector: Python adapter for the sensing pipeline
  • Auto-detect Darwin platform in ws_server.py
    image
Add native macOS LiDAR / WiFi sensing support via CoreWLAN: - mac_wifi.swift: Swift helper to poll RSSI/Noise at 10Hz - MacosWifiCollector: Python adapter for the sensing pipeline - Auto-detect Darwin platform in ws_server.py <img width="734" height="729" alt="image" src="https://github.com/user-attachments/assets/77973ef4-d05e-4e6e-8e5e-7778b92e84e6" />
ruvnet (Migrated from github.com) reviewed 2026-03-01 23:42:48 +08:00
ruvnet (Migrated from github.com) left a comment

Review

Nice contribution — this adds macOS CoreWLAN support to the Python v1 pipeline, which complements ADR-025 (targeting the Rust v2 pipeline). The approach is solid: Swift helper binary + Python subprocess consumer, same pattern as the existing collectors.

What works well

  1. Swift helper is cleanmac_wifi.swift is minimal (~34 lines), polls rssiValue() / noiseMeasurement() at 10 Hz, outputs JSON lines. Good use of setbuf(stdout, nil) to prevent buffering issues.

  2. Auto-compile on first runMacosWifiCollector.start() compiles the Swift binary if missing. Smart for developer experience.

  3. Docker-on-Mac fix — The /proc/net/wireless check in the Linux branch prevents Docker containers on macOS from incorrectly trying LinuxWifiCollector. Good defensive fix.

  4. Fits existing patterns — Produces WifiSample dataclass, uses RingBuffer, follows the same start()/stop()/get_samples() API as other collectors.

Issues to address

1. Single-AP RSSI only (not multi-BSSID)

The Swift helper polls only the connected interface (CWWiFiClient.shared().interface()), returning one RSSI value at a time. The Windows collector (WindowsWifiCollector) and the Rust ADR-022 pipeline scan all visible BSSIDs (10-30+) to create multi-AP spatial diversity.

Consider adding a --scan mode that calls interface.scanForNetworks(withSSID: nil) to get all visible networks. This would match the multi-BSSID approach and significantly improve motion detection quality. Can be a follow-up PR.

2. Synthetic tx_bytes / rx_bytes counters

synth_tx += 1500
synth_rx += 3000

These increment monotonically at fixed values regardless of actual traffic. If any downstream code uses TX/RX bytes for feature extraction, this will produce misleading data. Consider either:

  • Pulling real counters from netstat or /usr/sbin/nettop
  • Setting them to 0 and documenting that byte counters are unavailable on macOS

3. Missing __init__.py / module export

MacosWifiCollector is imported in ws_server.py from rssi_collector, but the diff doesn't update any __init__.py if one exists. Verify the import path works.

4. No cleanup of compiled binary

The auto-compiled mac_wifi binary ends up in v1/src/sensing/ alongside source code. Consider adding it to .gitignore to prevent accidental commits, or building to a build/ subdirectory.

5. PR title says "LiDAR"

The description mentions "native macOS LiDAR / WiFi sensing" but there's no LiDAR code — this is WiFi RSSI only. Minor, but should be corrected to avoid confusion.

Summary

Aspect Status
Swift helper Good — clean, minimal, correct CoreWLAN usage
Python adapter Good — follows existing collector pattern
Platform detection Good — fixes Docker-on-Mac false positive
Multi-BSSID support Missing — single connected AP only
Synthetic byte counters Should be documented or removed
Tests None included — consider adding a unit test for JSON parsing

Good first step. The single-AP limitation is the main gap vs. the ADR-022/025 approach, but this is still useful for basic presence/motion detection on macOS. Would be mergeable after addressing the synthetic counters and the PR title.

## Review Nice contribution — this adds macOS CoreWLAN support to the **Python v1 pipeline**, which complements ADR-025 (targeting the Rust v2 pipeline). The approach is solid: Swift helper binary + Python subprocess consumer, same pattern as the existing collectors. ### What works well 1. **Swift helper is clean** — `mac_wifi.swift` is minimal (~34 lines), polls `rssiValue()` / `noiseMeasurement()` at 10 Hz, outputs JSON lines. Good use of `setbuf(stdout, nil)` to prevent buffering issues. 2. **Auto-compile on first run** — `MacosWifiCollector.start()` compiles the Swift binary if missing. Smart for developer experience. 3. **Docker-on-Mac fix** — The `/proc/net/wireless` check in the Linux branch prevents Docker containers on macOS from incorrectly trying `LinuxWifiCollector`. Good defensive fix. 4. **Fits existing patterns** — Produces `WifiSample` dataclass, uses `RingBuffer`, follows the same `start()`/`stop()`/`get_samples()` API as other collectors. ### Issues to address **1. Single-AP RSSI only (not multi-BSSID)** The Swift helper polls only the **connected** interface (`CWWiFiClient.shared().interface()`), returning one RSSI value at a time. The Windows collector (`WindowsWifiCollector`) and the Rust ADR-022 pipeline scan **all visible BSSIDs** (10-30+) to create multi-AP spatial diversity. Consider adding a `--scan` mode that calls `interface.scanForNetworks(withSSID: nil)` to get all visible networks. This would match the multi-BSSID approach and significantly improve motion detection quality. Can be a follow-up PR. **2. Synthetic `tx_bytes` / `rx_bytes` counters** ```python synth_tx += 1500 synth_rx += 3000 ``` These increment monotonically at fixed values regardless of actual traffic. If any downstream code uses TX/RX bytes for feature extraction, this will produce misleading data. Consider either: - Pulling real counters from `netstat` or `/usr/sbin/nettop` - Setting them to 0 and documenting that byte counters are unavailable on macOS **3. Missing `__init__.py` / module export** `MacosWifiCollector` is imported in `ws_server.py` from `rssi_collector`, but the diff doesn't update any `__init__.py` if one exists. Verify the import path works. **4. No cleanup of compiled binary** The auto-compiled `mac_wifi` binary ends up in `v1/src/sensing/` alongside source code. Consider adding it to `.gitignore` to prevent accidental commits, or building to a `build/` subdirectory. **5. PR title says "LiDAR"** The description mentions "native macOS LiDAR / WiFi sensing" but there's no LiDAR code — this is WiFi RSSI only. Minor, but should be corrected to avoid confusion. ### Summary | Aspect | Status | |--------|--------| | Swift helper | Good — clean, minimal, correct CoreWLAN usage | | Python adapter | Good — follows existing collector pattern | | Platform detection | Good — fixes Docker-on-Mac false positive | | Multi-BSSID support | Missing — single connected AP only | | Synthetic byte counters | Should be documented or removed | | Tests | None included — consider adding a unit test for JSON parsing | Good first step. The single-AP limitation is the main gap vs. the ADR-022/025 approach, but this is still useful for basic presence/motion detection on macOS. Would be mergeable after addressing the synthetic counters and the PR title.
ruvnet commented 2026-03-01 23:52:48 +08:00 (Migrated from github.com)

Changes pushed to your branch

I've pushed fixes and enhancements directly to your feature/macos-corewlan branch so you retain full contribution credit. Here's what was added:

Python fixes

  • Removed synthetic byte counterssynth_tx += 1500 / synth_rx += 3000 produced misleading data. Now reports tx_bytes=0, rx_bytes=0 (honest: macOS CoreWLAN doesn't expose per-interface byte counts)
  • Added v1/src/sensing/mac_wifi to .gitignore to prevent the compiled Swift binary from being committed

New Rust platform adapters

Both follow the same Command::new() → parse → Vec<BssidObservation> pattern as the existing NetshBssidScanner:

  1. macos_scanner.rsMacosCoreWlanScanner

    • Invokes the mac_wifi Swift helper binary
    • Lightweight JSON parser (no serde_json dependency)
    • Handles macOS Sonoma+ BSSID redaction: generates deterministic synthetic MACs via FNV-1a hash with locally-administered bit set
    • Platform-gated with #[cfg(target_os = "macos")]
    • 8 unit tests for parsing, synthetic BSSID determinism, and edge cases
  2. linux_scanner.rsLinuxIwScanner

    • Parses iw dev <iface> scan output (BSS stanza format)
    • Supports both scan (requires root) and scan dump (cached, no root needed)
    • Frequency-to-channel conversion for 2.4/5/6 GHz bands
    • Configurable interface name (default: wlan0)
    • Platform-gated with #[cfg(target_os = "linux")]
    • 6 unit tests covering multi-BSS parsing, freq conversion, and edge cases

Module updates

  • adapter/mod.rs and lib.rs updated with #[cfg(target_os)]-gated module declarations and re-exports
  • All 87 existing tests still pass

This addresses the review feedback from earlier. The PR should be ready for another review round.

## Changes pushed to your branch I've pushed fixes and enhancements directly to your `feature/macos-corewlan` branch so you retain full contribution credit. Here's what was added: ### Python fixes - **Removed synthetic byte counters** — `synth_tx += 1500` / `synth_rx += 3000` produced misleading data. Now reports `tx_bytes=0, rx_bytes=0` (honest: macOS CoreWLAN doesn't expose per-interface byte counts) - **Added `v1/src/sensing/mac_wifi`** to `.gitignore` to prevent the compiled Swift binary from being committed ### New Rust platform adapters Both follow the same `Command::new()` → parse → `Vec<BssidObservation>` pattern as the existing `NetshBssidScanner`: 1. **`macos_scanner.rs`** — `MacosCoreWlanScanner` - Invokes the `mac_wifi` Swift helper binary - Lightweight JSON parser (no `serde_json` dependency) - Handles macOS Sonoma+ BSSID redaction: generates deterministic synthetic MACs via FNV-1a hash with locally-administered bit set - Platform-gated with `#[cfg(target_os = "macos")]` - 8 unit tests for parsing, synthetic BSSID determinism, and edge cases 2. **`linux_scanner.rs`** — `LinuxIwScanner` - Parses `iw dev <iface> scan` output (BSS stanza format) - Supports both `scan` (requires root) and `scan dump` (cached, no root needed) - Frequency-to-channel conversion for 2.4/5/6 GHz bands - Configurable interface name (default: `wlan0`) - Platform-gated with `#[cfg(target_os = "linux")]` - 6 unit tests covering multi-BSS parsing, freq conversion, and edge cases ### Module updates - `adapter/mod.rs` and `lib.rs` updated with `#[cfg(target_os)]`-gated module declarations and re-exports - All 87 existing tests still pass ✅ This addresses the review feedback from earlier. The PR should be ready for another review round.
ruvnet commented 2026-03-01 23:59:25 +08:00 (Migrated from github.com)

Thank you @zqyhimself for the macOS CoreWLAN contribution! 🎉

Your Swift helper + Python adapter laid the foundation. We built on top of it with:

  • Rust MacosCoreWlanScanner and LinuxIwScanner adapters
  • Synthetic BSSID handling for macOS Sonoma+ redaction
  • Python byte counter fix

Great first contribution — welcome to the project!

Thank you @zqyhimself for the macOS CoreWLAN contribution! 🎉 Your Swift helper + Python adapter laid the foundation. We built on top of it with: - Rust `MacosCoreWlanScanner` and `LinuxIwScanner` adapters - Synthetic BSSID handling for macOS Sonoma+ redaction - Python byte counter fix Great first contribution — welcome to the project!
Sign in to join this conversation.