People
Breathing
Heart rate
Mean RSSI
Frames
Signal history
RSSI motion band breathing bandSignal field
—Subcarrier waterfall
—Nodes
| Node | RSSI | Subcarriers | CSI fps | Sync |
|---|---|---|---|---|
| No frames yet | ||||
Event log
Last raw frame
—
How the pieces connect
All sensing data stays on your network. This page is static; it only connects to 127.0.0.1 on the computer you open it on. Nothing is sent to Cloudflare.
0 · Try it with no hardware
Choose Demo data on the Live tab. Or run the real server in simulated mode (step 2 without an ESP32) to test the full chain.
1 · Flash and provision an ESP32-S3
An ESP32-S3 (~$9) is the supported CSI source. ESP32-C3 and the original ESP32 are not supported. A plain laptop gives RSSI-only, coarse presence. Flash the firmware from the RuView repo, then point it at your PC's LAN IP:
python firmware/esp32-csi-node/provision.py --port COM5 \ --ssid "YourWiFi" --password "YourWiFiPassword" \ --target-ip 192.168.1.20
Replace COM5, the network name, and 192.168.1.20 (your PC's IP, from ipconfig).
2 · Run the sensing-server (Docker)
PowerShell:
$env:RUVIEW_API_TOKEN = -join ((1..32) | % { '{0:x2}' -f (Get-Random -Max 256) })
docker run --rm -e RUVIEW_API_TOKEN -e CSI_SOURCE=esp32 `
-e RUVIEW_UDP_ALLOW=192.168.1.0/24 `
-p 127.0.0.1:3000:3000 -p 5005:5005/udp `
ruvnet/wifi-densepose:latestDrop -e CSI_SOURCE=esp32, the UDP allow-list and -p 5005:5005/udp to run on simulated data. Adjust the subnet to your LAN. Allow UDP 5005 through Windows Firewall when prompted. If the node never appears, Docker Desktop may be rewriting the source address to its own gateway; as a test-only fallback, replace the allow-list with -e RUVIEW_UDP_INSECURE_LAN=true.
3 · Start the bridge (same PowerShell window)
Needs Node 18+. It reads the token from the environment, so the token never touches the browser.
node bridge/ruview-bridge.mjs
The file is in the coledtouch/tracker repo under bridge/. Or download it here.
4 · Connect
On the Live tab choose Local bridge and press Connect. Chrome may ask to allow access to devices on your local network; allow it for this site.
Phones and other devices
An https page can reach 127.0.0.1 but browsers block it from reaching plain http://192.168.x.x. To watch from a phone, open RuView's own UI on your LAN (set SENSING_ALLOWED_HOSTS and publish port 3000 on 0.0.0.0) or put the bridge behind a Cloudflare Tunnel with Cloudflare Access in front of it.
Direct mode
For an older server, or one started with RUVIEW_WS_LEGACY_UNAUTHENTICATED=1, choose Direct WebSocket and use ws://localhost:3000/ws/sensing. That flag turns off WebSocket auth, so only use it on a server bound to 127.0.0.1.
What this bench is testing
WiFi signals bend and reflect off bodies. A receiver that reads the fine-grained channel data can infer presence, motion and breathing without a camera.
RuView (what you run)
Open-source sensing from WiFi Channel State Information (CSI) captured by ESP32-S3 nodes. It reports presence, occupancy, motion, breathing and a heart-rate proxy, and runs locally with no cloud.
Per its README: the live single-node pose model is first-cut, named-person identification is not shipped, and vitals are not medical-grade.
github.com/ruvnet/ruview ↗BFId (the privacy warning)
KIT researchers showed at ACM CCS 2025 that people can be identified from beamforming feedback, which devices send to routers unencrypted. In a 197-person test they reported near-100% accuracy, even for people carrying no phone.
They frame it as a risk and call for safeguards in the upcoming IEEE 802.11bf standard.
ScienceDaily article ↗Use it responsibly
- Sense only spaces you control, and tell the people in them.
- Keep the server bound to
127.0.0.1and the API token set. - Recordings of breathing and movement are sensitive personal data. Delete what you don't need.