Skip to main content

wifi-densepose

PyPI version Python License: MIT

Detect human presence, count people, read breathing and heart rate, and estimate skeletal pose — using only the WiFi signal already in your home.

No cameras. No wearables. Works through walls and in the dark.

wifi-densepose is the Python binding for the RuView sensing stack: a Rust core that turns the Channel State Information (CSI) emitted by ordinary WiFi chips into ambient-intelligence signals. The wheel ships compiled DSP for fast offline analysis, plus an opt-in Python client for talking to a live RuView sensing-server over WebSocket or MQTT.

Features

In the compiled wheel (runs offline, no server needed):

  • Vital signs — the Rust 3-stage pipeline: CsiVitalPreprocessor (static-component suppression), BreathingExtractor (6–30 BPM) and HeartRateExtractor (40–120 BPM), each estimate carrying a confidence score and a valid / degraded / unreliable status
  • Pose types — Keypoint, PoseEstimate, PersonPose, BoundingBox for the 17-keypoint skeletons a RuView sensing-server produces
  • Beamforming Feedback (BFLD) support — 802.11ac/ax/be compressed feedback matrices on top of the receiver-side CSI path
  • Witness check — wifi_densepose.verify_witness() re-runs the published deterministic pipeline proof (ADR-117 §11.3)
  • GIL-releasing DSP — extract loops run with the GIL released, so a tokio-backed web server can call into the pipeline without stalling its event loop
  • Small wheel — under 400 KB compiled (one binary per OS/arch covers Python 3.10+ via the stable ABI)

With the [client] extra, from a live RuView sensing-server:

  • Pose, presence, person count, fall detection, motion — streamed over WebSocket (SensingClient) or MQTT (RuViewMqttClient)
  • 10 semantic primitives (HA-MIND) — someone-sleeping, possible-distress, room-active, bathroom-occupied, fall-risk-elevated, bed-exit, … — ready to wire into Home Assistant automations

Install

pip install wifi-densepose                 # core DSP only
pip install "wifi-densepose[client]"       # + WebSocket/MQTT clients

Wheels are published for Linux (x86_64, aarch64), macOS (x86_64, arm64), and Windows (amd64).

SOTA extras (ADR-185)

Three optional subsystems bind the Rust SOTA modules as compiled-feature wheels. Each raises a clear ImportError if you import it without the extra:

Extra Module What it adds
[aether] wifi_densepose.aether Contrastive CSI embeddings / re-identification (ADR-024) — EmbeddingExtractor, cosine_similarity, info_nce_loss
[meridian] wifi_densepose.meridian Cross-environment domain generalization (ADR-027) — HardwareNormalizer, GeometryEncoder, RapidAdaptation, CrossDomainEvaluator
[mat] wifi_densepose.mat Mass-Casualty Assessment disaster-survivor detection + START triage — DisasterResponse, Survivor, TriageStatus
[sota] all three Convenience superset
pip install "wifi-densepose[aether]"       # re-identification embeddings
pip install "wifi-densepose[meridian]"     # cross-room calibration
pip install "wifi-densepose[mat]"          # disaster triage
pip install "wifi-densepose[sota]"         # all three

Runnable examples: examples/reid_from_csi.py, examples/cross_room_calibrate.py, examples/mat_triage.py.

Quickstart

Runs as-is after pip install wifi-densepose. It feeds 30 seconds of synthetic CSI through the Rust pipeline and prints the recovered rates (about 15 breaths/min and 72 beats/min):

import math

from wifi_densepose import BreathingExtractor, CsiVitalPreprocessor, HeartRateExtractor

pre = CsiVitalPreprocessor.esp32_default()  # 56 subcarriers, EMA static suppression
br = BreathingExtractor.esp32_default()     # 0.1-0.5 Hz band, 30 s window
hr = HeartRateExtractor.esp32_default()     # 0.8-2.0 Hz band, 15 s window

# 30 s of synthetic CSI at 100 Hz: 15 breaths/min (0.25 Hz) + 72 beats/min (1.2 Hz).
for i in range(3000):
    t = i / 100.0
    a = 10.0 + 0.5 * math.sin(2 * math.pi * 0.25 * t) + 0.05 * math.sin(2 * math.pi * 1.2 * t)
    residuals = pre.process([a] * 56)
    breathing = br.extract(residuals, [])
    heart = hr.extract(residuals, [])

print("breathing:", breathing)
print("heart:    ", heart)

The signal is synthetic; this shows the API, not accuracy on real CSI.

Usage

Extract breathing rate from a CSI stream

from wifi_densepose import BreathingExtractor

br = BreathingExtractor.esp32_default()     # 56 subcarriers @ 100 Hz, 30s window

for residuals, weights in your_csi_source:  # one frame at a time
    est = br.extract(residuals=residuals, weights=weights)
    if est is not None:
        print(f"{est.value_bpm:.1f} BPM  (confidence={est.confidence:.2f})")

For heart rate, use HeartRateExtractor.esp32_default() with a 0.8–2.0 Hz bandpass and a 15-second window. Its second argument is phases, not the breathing extractor's weights:

hr = HeartRateExtractor.esp32_default()
est = hr.extract(residuals=residuals, phases=phases)
# If phase measurements are unavailable, phases=[] uses equal weighting.

The current binding rejects the old weights keyword with TypeError. Heart-rate estimation requires a local autocorrelation peak; a declining breathing-only correlation is not treated as a pulse at the band edge. Additional filtering reduces respiratory leakage, while confidence remains capped by evidence from the original filter stage. Synthetic regression tests cover these cases; they do not establish accuracy on real CSI or medical use.

Subscribe to a live sensing-server

import asyncio
from wifi_densepose.client import SensingClient, EdgeVitalsMessage

async def main():
    async with SensingClient("ws://your-ruview-node:8765/ws/sensing") as c:
        async for msg in c.stream():
            if isinstance(msg, EdgeVitalsMessage):
                print(msg.presence, msg.breathing_rate_bpm, msg.heartrate_bpm)

asyncio.run(main())

React to Home Assistant semantic primitives

from wifi_densepose.client import (
    RuViewMqttClient, SemanticPrimitive, SemanticPrimitiveListener,
)

listener = SemanticPrimitiveListener()
listener.on(SemanticPrimitive.BedExit, lambda e: print("bed exit:", e.node_id))
listener.on(SemanticPrimitive.PossibleDistress, lambda e: alert(e))

client = RuViewMqttClient(broker_host="homeassistant.local")
client.on_message(
    # MQTT `+` must fill a whole topic level; the listener skips non-RuView topics.
    "homeassistant/+/+/+/state",
    listener.handle_mqtt_message,
)
client.start()
client.wait_connected()

Decode 802.11ax beamforming feedback

import numpy as np
from wifi_densepose import BfldFrame, BfldKind

# Parse compressed BFR from a Wireshark capture into a complex128 ndarray ...
fb = np.zeros((2, 1, 996), dtype=np.complex128)  # Nr=2 Nc=1 Nsc=996 for HE80

frame = BfldFrame.from_compressed_feedback(
    timestamp_ms=ts,
    sounding_index=seq,
    sta_mac="aa:bb:cc:dd:ee:ff",
    kind=BfldKind.CompressedHE80,
    feedback_matrix=fb,
)
print(frame.n_subcarriers, frame.mean_amplitude)

Hardware

Works with any WiFi chip that exposes CSI. Reference setups (ESP-IDF firmware, build scripts, witness-verified test bundles) are in the RuView repo:

Device Cost Role
ESP32-S3 (8MB flash) ~$9 WiFi CSI sensing node
ESP32-S3 SuperMini (4MB) ~$6 WiFi CSI (compact)
ESP32-C6 + Seeed MR60BHA2 ~$15 mmWave HR/BR/presence add-on

The legacy v1 line (Wi-Pose-style FastAPI server) is end-of-life; wifi-densepose==1.99.0 is a tombstone that raises ImportError pointing to v2 with a migration URL.

License

MIT.

Metadata

Release files for wifi-densepose 2.0.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for wifi-densepose 2.0.0
File Size Uploaded Provenance Actions
wifi_densepose-2.0.0.tar.gz 1.2 MB Without provenance Details for wifi_densepose-2.0.0.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for wifi-densepose 2.0.0
File Actions
wifi_densepose-2.0.0-cp310-abi3-win_amd64.whl CPython 3.10 abi3 Windows x86-64 Details for wifi_densepose-2.0.0-cp310-abi3-win_amd64.whl
wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_x86_64.whl CPython 3.10 abi3 Linux musl 1.2+ x86-64 Details for wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_x86_64.whl
wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_aarch64.whl CPython 3.10 abi3 Linux musl 1.2+ ARM64 Details for wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_aarch64.whl
wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl CPython 3.10 abi3 Linux glibc 2.17+ x86-64 Details for wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl CPython 3.10 abi3 Linux glibc 2.17+ ARM64 Details for wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
wifi_densepose-2.0.0-cp310-abi3-macosx_11_0_arm64.whl CPython 3.10 abi3 macOS 11.0+ ARM64 Details for wifi_densepose-2.0.0-cp310-abi3-macosx_11_0_arm64.whl
wifi_densepose-2.0.0-cp310-abi3-macosx_10_12_x86_64.whl CPython 3.10 abi3 macOS 10.12+ x86-64 Details for wifi_densepose-2.0.0-cp310-abi3-macosx_10_12_x86_64.whl

Total release size: 3.8 MB

Release files / wifi_densepose-2.0.0.tar.gz

Download URL wifi_densepose-2.0.0.tar.gz
Size 1.2 MB
Tags Source
SHA-256 checksum
How to use checksums
e9a0ac8edd859d4367354859f02ea02eca1a278ed67269dd94f7b7e7dfaf8fe0
BLAKE2b-256 checksum
How to use checksums
a094ce613b2478a2f9ea3f19c9937a5e14bbefed374cff92fb89c1f4e42afd2f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-win_amd64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-win_amd64.whl
Size 284.9 kB
Tags CPython 3.10 Windows x86-64 abi3
SHA-256 checksum
How to use checksums
ab976f12bde15b9675fbc0e086347f6dff7ef849ffa53780c76ac545fd80651b
BLAKE2b-256 checksum
How to use checksums
9f7433b10245fc570e68b56966e5259e36c3ac901f212e265cbc7191b0189c93
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_x86_64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_x86_64.whl
Size 439.8 kB
Tags CPython 3.10 Linux musl 1.2+ x86-64 abi3
SHA-256 checksum
How to use checksums
bd08595380d670ac746aa17ad9c5809e28d4feea6d3b2ba0d3484833066b47ef
BLAKE2b-256 checksum
How to use checksums
df8b90f8b2c478bb510eea858bd56a858a26b184a5b56a98d0bf8065e9e3c5bb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_aarch64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-musllinux_1_2_aarch64.whl
Size 408.6 kB
Tags CPython 3.10 Linux musl 1.2+ ARM64 abi3
SHA-256 checksum
How to use checksums
6d6ffe75391865004b0ed315b5c6002368023a58d29b52b8e01927b9f0685955
BLAKE2b-256 checksum
How to use checksums
1d2939719dd4a18ba5c48275e37de84bf918dca829c106b4e9dbe6a91b474f26
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Size 377.9 kB
Tags CPython 3.10 Linux glibc 2.17+ x86-64 abi3
SHA-256 checksum
How to use checksums
6f5f30fdc4f88dd2427a7b1d5f7ece7cf0d36cf0bfa353fe28c6cdd571b9716a
BLAKE2b-256 checksum
How to use checksums
7a27dd4b5bb26999cb92e8bef5595184fc92a37d4bf552e6ff1f1f9de6c23626
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Size 360.3 kB
Tags CPython 3.10 Linux glibc 2.17+ ARM64 abi3
SHA-256 checksum
How to use checksums
92b4fc6b694d902e2165109ac1f12e29801576862dcbab821b484b153cfdab1e
BLAKE2b-256 checksum
How to use checksums
b1f5c81effe9153c19d35b00ae6fa9c28d9e43eddaf00eca5d9de22ca17826af
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-macosx_11_0_arm64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-macosx_11_0_arm64.whl
Size 342.6 kB
Tags CPython 3.10 abi3 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
9510139b67643be8e32f8aeb2fcb1f9050bfe66e270f6141ef3885bbad15729b
BLAKE2b-256 checksum
How to use checksums
4739a72f8135450e4e466fe6ce0dcda51ba41cfa32c3e91c0e732fef19e64a77
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Release files / wifi_densepose-2.0.0-cp310-abi3-macosx_10_12_x86_64.whl

Download URL wifi_densepose-2.0.0-cp310-abi3-macosx_10_12_x86_64.whl
Size 352.8 kB
Tags CPython 3.10 abi3 macOS 10.12+ x86-64
SHA-256 checksum
How to use checksums
188654a5ce22d666800bf73867e504587f275323ad51af6692288320fcbe3e21
BLAKE2b-256 checksum
How to use checksums
9589b5ec9d08b28b71e065bb4605b68d1ee75ba4e0040c07ecc882b95a612774
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.13.14

Security for wifi-densepose 2.0.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page