-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
WiFi-DensePose: Windows WiFi Sensing Quick Start (ADR-013)
Zero-cost presence and motion detection using your existing Windows WiFi — no special hardware needed.
This tutorial walks through setting up the ADR-013 commodity sensing pipeline on a Windows laptop. The full pipeline reads real RSSI from your WiFi adapter via netsh, extracts spectral and statistical features, and classifies presence/motion in real-time.
What You Need
| Item | Notes |
|---|---|
| Windows 10/11 laptop | Any WiFi adapter works |
| Connected WiFi network | Must be associated with an AP |
| Python 3.10+ | With pip |
| ~5 minutes | No hardware mods, no drivers, no root |
What You'll Get
| Capability | Works? | How |
|---|---|---|
| Presence detection | ✅ Yes | RSSI variance threshold |
| Motion detection (still/active) | ✅ Yes | Spectral band power |
| Breathing detection | ❌ No | RSSI resolution too coarse |
| Heartbeat | ❌ No | Not possible with RSSI |
| Pose estimation | ❌ No | Requires CSI (see issue #34) |
Step 1: Clone and Install
git clone https://github.com/ruvnet/wifi-densepose.git
cd wifi-densepose
pip install numpy scipyStep 2: Verify WiFi is Connected
netsh wlan show interfacesYou should see State: connected and an Rssi value (e.g., -39). If disconnected:
netsh wlan connect name="YourNetworkName"Step 3: Run a Single RSSI Sample
# Quick test — run from the repo root
python -c "
import sys; sys.path.insert(0, '.')
from v1.src.sensing.rssi_collector import WindowsWifiCollector
c = WindowsWifiCollector(interface='Wi-Fi')
s = c.collect_once()
print(f'RSSI: {s.rssi_dbm} dBm, Quality: {s.link_quality:.0%}')
"Expected output:
RSSI: -39.0 dBm, Quality: 94%
Step 4: Run the Full Pipeline (Feature Extraction + Classification)
python -c "
import sys, time; sys.path.insert(0, '.')
from v1.src.sensing.rssi_collector import WindowsWifiCollector
from v1.src.sensing.feature_extractor import RssiFeatureExtractor
from v1.src.sensing.classifier import PresenceClassifier
collector = WindowsWifiCollector(interface='Wi-Fi', sample_rate_hz=2.0)
extractor = RssiFeatureExtractor(window_seconds=15.0)
classifier = PresenceClassifier(presence_variance_threshold=0.3)
collector.start()
print('Collecting 15 seconds of RSSI data...')
time.sleep(15)
collector.stop()
samples = collector.get_samples()
features = extractor.extract(samples)
result = classifier.classify(features)
print(f'Samples: {len(samples)}')
print(f'RSSI mean: {features.mean:.1f} dBm')
print(f'Variance: {features.variance:.4f}')
print(f'Motion: {features.motion_band_power:.4f}')
print(f'Verdict: {result.motion_level.value} ({result.confidence:.0%})')
"Step 5: Live Monitoring (Walk Around to Test)
# From repo root
set PYTHONPATH=. && python v1/tests/integration/live_sense_monitor.pyThis prints a live dashboard every 3 seconds:
[14:00:05] RSSI= -37.0dBm var=0.000 motion_e=0.0000 => absent (100%)
[14:00:08] RSSI= -37.0dBm var=0.000 motion_e=0.0000 => absent (100%)
[14:00:26] RSSI= -37.1dBm var=0.120 motion_e=0.0016 => absent (76%) ← RSSI changing!
[14:00:32] RSSI= -41.3dBm var=4.850 motion_e=1.2300 => active (95%) ← MOTION DETECTED
To trigger detection: Walk between your laptop and the WiFi router. This causes 3-10+ dBm RSSI swings that the classifier picks up as ACTIVE motion.
Press Ctrl+C to stop and see a summary.
Step 6: Use the CommodityBackend API
from v1.src.sensing.backend import CommodityBackend, Capability
from v1.src.sensing.rssi_collector import WindowsWifiCollector
collector = WindowsWifiCollector(interface="Wi-Fi", sample_rate_hz=2.0)
backend = CommodityBackend(collector=collector)
print(backend.get_capabilities())
# {<Capability.PRESENCE>, <Capability.MOTION>}
backend.start()
# ... wait for data collection ...
result = backend.get_result()
print(result.motion_level) # MotionLevel.ABSENT / PRESENT_STILL / ACTIVE
print(result.confidence) # 0.0 to 1.0
backend.stop()Step 7: Run the Tests
# Unit tests (36 tests, no WiFi needed — uses SimulatedCollector)
python -m pytest v1/tests/unit/test_sensing.py -v -o "addopts="
# Live integration tests (5 tests, requires connected WiFi)
python -m pytest v1/tests/integration/test_windows_live_sensing.py -v -o "addopts=" -sHow It Works
Windows WiFi (netsh) Feature Extraction Classification
┌─────────────────┐ ┌───────────────────────┐ ┌──────────────────┐
│ netsh wlan show │ │ Hann-windowed FFT │ │ Variance > 0.3? │
│ interfaces │────▶│ Band power analysis │────▶│ → PRESENT │
│ │ │ CUSUM change-point │ │ Motion energy? │
│ RSSI: -39 dBm │ │ Rolling statistics │ │ → STILL/ACTIVE │
└─────────────────┘ └───────────────────────┘ └──────────────────┘
Pipeline: WindowsWifiCollector → RssiFeatureExtractor (FFT, CUSUM, spectral bands) → PresenceClassifier (rule-based, interpretable)
Limitations (Honest Assessment)
| Limitation | Why |
|---|---|
| RSSI quantized to 1 dBm | netsh reports integers; sub-dBm variation invisible |
| ~2 Hz max sample rate | netsh takes 200-400ms per call |
| No breathing/heartbeat | Requires sub-dBm resolution (use ESP32 CSI instead) |
| Best for coarse motion | Person must cross the WiFi signal path for large RSSI swings |
| Single receiver only | Multi-receiver fusion requires multiple machines |
Upgrade Path
For higher-fidelity sensing (respiration, fine motion, multi-person):
- ESP32 CSI mesh (ADR-012): $54 starter kit, 56 subcarrier amplitudes, 20+ Hz → Tutorial #34
- Pre-built firmware: Release v0.1.0-esp32
Verified On
- OS: Windows 11 Home 10.0.26200
- Adapter: Intel Wi-Fi 7 BE201 320MHz
- Network: WPA2-Personal, 5 GHz 802.11ax
- RSSI observed: -37 to -40 dBm
- Tests: 36 unit + 5 integration = 41 passed
- Python: 3.13, numpy, scipy