Setup & flashing · the real workflow

From a box of parts
to a sensing room.

Buying the sensors is the easy part. This page is the part that actually matters: the tools you need, how to flash a sensor on your Mac or PC, get it on WiFi, have it talk to your Cognitum One Seed, and then bring in RuView to make sense of the data. Honest, step-by-step, no hand-waving.

← back to the sensor primer

00 — THE BIG PICTURE

The order of operations

Every WiFi sensor follows the same five-step path. Get this mental model first and nothing below is confusing.

1 · Buythe kit 2 · Flashon Mac / PC 3 · Set WiFi+ the Seed's address 4 · Power itnear the Seed 5 · It streamsto the Seed
The LD2450 USB kit skips steps 2–3 entirely — it just plugs into the Seed. The WiFi sensors need all five.

The easy way: let Claude Code do the fiddly parts

This guide assumes you're working in VS Code with Claude Code. The simplest path: open your project, add RuView as a git submodule (next section), install the RuView plugin, and then mostly just tell Claude Code in plain English what you want — it flashes the nodes, sets their WiFi, and helps wire up the dashboard for you. (Having Ruflo installed adds extra orchestration, but it's not required.)

The exact commands below are "under the hood" — handy if you want to understand them or do it by hand, but you usually won't need to type them yourself.

01 — WHAT YOU NEED ON THE BENCH

Cables & tools — get these first

Missing one of these is the #1 reason a beginner stalls for an evening.

ToolWhat it's forDon't get this wrong
USB-C data cableConnecting an ESP32 to your Mac/PC to flash itMany cables are charge-only — they power the board but carry no data, so flashing silently fails. Buy one labelled "data".
A Mac or PCRunning the flashing toolYou flash once per node, then it runs on its own.
Your Cognitum One Seed (the host)Receives the sensor streams — this is the brainGive it the power supply specified for your model. Underpowering causes random dropouts that look like sensor failures.
Your WiFi name + passwordThe sensor needs to join your network2.4 GHz for ESP32-S3 & the MR60; 5 GHz for the ESP32-C5. They are not interchangeable.
The Seed's IP addressSo the sensor knows where to send dataIf the Seed's IP changes (DHCP), sensors "disappear" — reserve the Seed's address in your router.
02 — FLASHING

Getting firmware onto each sensor

"Flashing" just means copying the sensor's program onto its chip over USB. Each of the three sensors is different — and one needs no flashing at all.

LD2450 radar — no flashing needed ✓

The USB kit is the simplest device here. There is nothing to flash. Plug its USB adapter into the Cognitum One Seed (or your Mac to test). The Seed reads its position data over a serial port at 256000 baud. Done. This is why it's the recommended first sensor.

MR60BHA2 vitals — ships ready, configure over WiFi

It comes pre-loaded with ESPHome firmware, so you don't flash it — it just needs your WiFi credentials. The simplest way: ask Claude Code to provision its WiFi (ESPHome is what's running under the hood). Then the Seed connects out to it and pulls heart rate & breathing over TCP 6053.

The trap: the XIAO has two USB-C ports. The one on the case edge is power only. To configure it, open the case and use the XIAO's own inner USB-C port. ESPHome docs ↗

The MR60BHA2 XIAO case opened into three parts, exposing the inner USB-C data/flash port and the 60 GHz radar module
Good to know: the case pops apart easily. The middle carrier holds the XIAO with its inner USB-C (the data/flash port) plus the 60 GHz radar module — that inner port is the one you plug into, not the power-only port on the case edge.

ESP32 CSI nodes — these get flashed (once)

Easiest: with the RuView plugin loaded in Claude Code, just plug a node into your Mac/PC and ask. Type something like:

"Flash this ESP32-S3 as CSI node #1, join WiFi 'MyNetwork' / 'mypassword',
and stream to my Seed at 10.0.0.50 on UDP 5005."

Claude Code (driving RuView) handles the toolchain, the config and the flash. Repeat for each node, bumping the number to 2, 3 … 7. Prefer to do it by hand? Here's exactly what's happening under the hood (Espressif's free ESP-IDF / esptool):

1

Install the toolchain (once)

Install ESP-IDF 5.5.2 by following Espressif's official get-started guide. It brings the build tool idf.py and the flasher esptool. ESP-IDF Get Started ↗

2

Plug the board into your computer

Use a real USB-C data cable. It appears as a serial port (e.g. /dev/cu.usbmodem… on a Mac).

3

Set four things, then build & flash

Open menuconfig and set: a node ID (1, 2, 3… one per board), your WiFi SSID + password, the Seed's IP, and the UDP port (5005). Then:

# for an ESP32-C5 node (5 GHz); use esp32s3 for S3 (2.4 GHz)
cd firmware/esp32c5-csi-node
idf.py set-target esp32c5
idf.py menuconfig        # node ID, WiFi SSID/password, Seed IP, port 5005
idf.py build
idf.py -p /dev/cu.usbmodemXXXX flash monitor
4

Confirm it's sending

On the Seed, watch for its packets:

tcpdump -ni any udp port 5005   # expect ~10 packets/sec from the node

Flash each node with a different node ID. Repeat for 3+ nodes — a single CSI node can't locate anything.

M5StickS3 (motion) — same idea, it's an ESP32-S3

If you added the M5StickS3, it's an ESP32-S3 board, so you flash it the same way (ESP-IDF / esptool) — or use M5's own no-code tool, UIFlow. Set your WiFi + the Seed's address, and it streams its IMU (motion/vibration) to the Seed over WiFi. It's the in-stock successor to the discontinued M5StickC PLUS2.

03 — WIFI → SEED

How the data actually reaches the Seed

A point that confuses everyone: there are different ports for different jobs. Don't mix them up.

SensorHow it reaches the SeedPort
ESP32 CSI nodesStream UDP over WiFi to the SeedUDP 5005
MR60BHA2 vitalsThe Seed connects out and pulls from itTCP 6053
LD2450 radarUSB cable straight into the Seed (serial)USB · 256000 baud

Don't confuse the ports. Sensors send their data to the Seed — CSI on UDP 5005, vitals on TCP 6053. What the Seed sends back out to a dashboard is a separate connection — don't mix up the inbound sensor ports with the outbound one. Bands matter too: 2.4 GHz for the S3 & MR60, 5 GHz for the C5.

04 — RUVIEW

Bring in RuView to read the WiFi

RuView (Ruv's open-source project) is the software that turns raw WiFi-CSI into presence, breathing, and the anonymous identity "fingerprint." Here's how to pull it in and build it. github.com/ruvnet/RuView ↗

π RuView — Ambient Intelligence: turning invisible WiFi signals into real-time human insights, no cameras or wearables
RuView WiFi DensePose Sensing Observatory — live body figure, heart rate, respiration and presence from WiFi CSI
What RuView is (left) and what it shows once running (right): WiFi-only sensing — presence, breathing, heart rate and a live body figure, no camera, no wearable. (Images from the RuView project.)

So what is it? RuView is Ruv's open-source "ambient intelligence" software. It takes the raw WiFi-CSI your ESP32 nodes stream in and turns it into a live read of the room — presence, breathing, heart rate, a rough body pose, and an anonymous identity "fingerprint" — all on-device, no cloud. It's the brain-software that makes your sensor array actually mean something.

1

Bring in RuView & build it

Clone it (simplest), or — if you're building your own project around it — add it as a git submodule so it's pinned inside your repo. Then build the Rust core:

# simplest — just clone it:
git clone https://github.com/ruvnet/RuView

# …or pin it inside your own project as a submodule:
git submodule add https://github.com/ruvnet/RuView vendor/RuView
git submodule update --init --recursive

# then build it:
cd RuView/v2 && cargo build --release

For the Python path, follow the repo's README rather than guessing a package name.

2

Just want to peek first? (no hardware — optional)

Optional: spin up the demo in Docker to see the interface on simulated data before you wire anything up.

docker pull ruvnet/wifi-densepose:latest
docker run -p 3000:3000 ruvnet/wifi-densepose:latest   # open http://localhost:3000
3

Use the RuView plugin (in Claude Code)

"The RuView plugin" is a Claude Code plugin — it gives an AI agent the skills and commands to drive RuView. Install it:

/plugin marketplace add ruvnet/RuView
/plugin install ruview@ruview

(There's also a separate MCP server, @ruvnet/rvagent, and on-device "cogs" — those are different things; the plugin is the Claude Code one above.)

4

Point it at your CSI nodes

RuView's aggregator listens for the same CSI stream your nodes send (UDP 5005). It turns the WiFi into presence, breathing/heart rate, and a 128-number fingerprint of who/what is in the room.

Be honest with yourself about what ships today

  • No pretrained weights. The --model flag is optional — the server runs fine without it, but the encoder produces random vectors until you train it (contrastive learning). There's no ready-made model to load yet.
  • Identity is anonymous. The fingerprint re-identifies the same body across sessions; it does not put a name to anyone.
  • Pose is rough. Camera-free pose accuracy is low today; presence & breathing are the solid wins.

Start here: README.md, then docs/user-guide.md and install.sh in the repo. Live demo: ruvnet.github.io/RuView ↗

05 — WHEN IT WON'T WORK

The checklist that fixes 90% of stalls

  • Flashing fails silently. Your USB-C cable is charge-only — swap for a data cable. (MR60: you're on the case-edge power-only port; use the inner one.)
  • Board won't join WiFi. Wrong band: an S3/C6 can't see 5 GHz; a C5 may be set to the 5 GHz network. Match the band.
  • Flashed, but no data on the Seed. Open UDP 5005 on the Seed's firewall; check you set the correct Seed IP in menuconfig.
  • LD2450 reads zeros. Baud must be 256000, not the usual 115200.
  • A sensor "disappeared". Its DHCP IP changed — reserve sensor + Seed MACs in your router.
  • MR60 shows null. It's still warming up — wait ~60 seconds after power-on.

← Back to the sensor primer