Skip to content

⭐ Tutorial: Windows WiFi Sensing Quick Start (ADR-013) #36

@ruvnet

Description

@ruvnet

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 scipy

Step 2: Verify WiFi is Connected

netsh wlan show interfaces

You 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.py

This 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=" -s

How 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: WindowsWifiCollectorRssiFeatureExtractor (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):


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

Related

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentation

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions