Ghostvisor

A local-only room-presence radar. It listens to Wi-Fi, two mmWave sensors, a PIR and a phone counter, and turns them into one answer: is someone here?

no cloud needed Raspberry Pi 400 ESP32 C3 / C6 / CYD Zigbee mmWave + PIR

THE IDEAOne sensor is easy to fool

A PIR cannot see someone sitting still. A radar sees a ceiling fan. Wi-Fi sensing gets confused by a microwave. A phone counter thinks the neighbour is in your living room.

Ghostvisor asks a simpler question of all of them at once: how many of my sensors agree that someone is here? The answer is one 0–100 % score with four named levels, hysteresis so it does not flicker, and a plain-English reason for every change.

INPUT

Wi-Fi CSI

Several ESP32 nodes feel how a person disturbs the radio path to the router. Each node learns its own empty-room baseline.

INPUT

mmWave A and B

5.8 GHz and 24 GHz Zigbee radars. They see movement and breathing in a cone, and report occupied / clear.

INPUT

PIR

Warm movement across its view. Quick, but blind to someone sitting still.

INPUT

PAX counter

Counts nearby phones and Bluetooth gadgets. Only a hint, never one of the core sensors.

BIG PICTUREHow it fits together

Everything runs on one Raspberry Pi. Worker threads feed one queue; the screen thread never waits on I/O.

Wi-Fi CSI nodes mmWave A + B PIR PAX counter Raspberry Pi 400 Fusion engine score 0–100 + level room zone + direction history (SQLite) Pi screen CYD displays Web page Phone push (ntfy) MQTT / alarm / LED

The three SONOFF sensors reach the Pi through a Zigbee dongle. The ESP32 nodes are polled over Wi-Fi as small JSON, and the PAX counter talks over USB serial.

THE SCOREHow a single number is made

The fusion engine turns each sensor's reading into evidence, adds it up, and then applies a few rules so one noisy device cannot decide alone.

LevelMeaningEnters atLeaves below
CLEARNothing detected––
POSSIBLEOne sensor thinks so25 %15 %
LIKELYSeveral agree50 %35 %
CONFIRMEDStrong agreement82 %68 %

A level must hold for 0.5 s before it rises and 5 s before it falls. There are three presets: Balanced, Fewer false alarms and Catch everything.

WI-FI SENSINGCSI, in plain words

Wi-Fi signals bounce around a room. A person standing or walking in the path changes how they arrive. Channel State Information (CSI) is the fine-grained measurement the radio chip already has. No camera, no wearable.

ON EACH NODE

Ping and measure

The ESP32 pings the router about 25 times a second and measures the subcarrier amplitudes of each reply. The motion score is how much that wobbles over the last ~2 s.

ON THE PI

One baseline per link

Each node learns what an empty room looks like. Motion means its score rose well above that. A spike guard keeps a bursty link quiet.

POWER

Cooler nodes

As more nodes run, the Pi lowers their transmit power, but only for nodes with a strong, healthy link. A weak node stays at full power.

Rule of thumb: a node senses the straight line between itself and the router. Put it across the room from the router so the walking route crosses that line. A node right next to the router senses almost nothing.

WHERE YOU SEE ITScreens everywhere

The same answer shows up on the Pi, on small ESP32 displays, in a browser and on your phone.

The Pi screen

Radar scope with feet rings, the fused level, one panel per sensor, an event log. Keys: A arm, H history, R room, P replay, O settings.

CYD displays

Small touch screens. One shows its own CSI waterfall and score; another is a mini radar fed by the Pi.

Web page

A phone-friendly dashboard at http://<pi-ip>:8470, a replay page, and a PIN-protected live copy of the Pi's screen.

A CYD node showing live Wi-Fi CSI motion
A CYD running the CSI firmware, caught mid-motion: score, signal bars, packets per second, a subcarrier waterfall and a 60 s trace.

WHERE AND WHENRoom view, ghost and replay

None of the sensors report a real distance, so the room view is built from which sensors overlap. It is coarse on purpose.

WHEN IT MATTERSAlarm, arming and alerts

Arm it when you leave. If the fused level reaches your alert level, you get an alarm after a short grace period.

Armed mode

60 s to leave, 20 s grace to disarm, weekly schedules. Disarm in time and nothing fires.

Phone push

Pushes go to your own private ntfy topic, with per-event switches and cooldowns.

Soft sounds

Gentle chimes on the Pi, with quiet hours that mute sound but still push to your phone.

Integrations

Optional MQTT with Home Assistant discovery, and Meshtastic LoRa text alerts.

THE PARTSHardware

PartRole
Raspberry Pi 400The brain: app, web server, history database
SONOFF Zigbee dongle (MG24)Zigbee coordinator for the three SONOFF sensors
SONOFF SNZB-06P (5.8 GHz) and SNZB-06P24 (24 GHz)mmWave A and B, occupied / clear only
SONOFF SNZB-03PIR motion sensor
ESP32-C3, ESP32-C6, CYD boardsWi-Fi CSI nodes (the CYD also shows a live panel)
ESP32 PAX counterCounts nearby phones, close ones only
Sense HAT (optional)LED scope that dims when idle, joystick mute, room climate

HONESTLYWhat it cannot do

The radars only say “someone / no one”. The sweep and blips on screen are a visual style. Zones come from which sensors overlap, not from a measured distance, and the ghost is a guess. Expect about a metre or two of fuzziness.

More detail: placement guide · measured sensor findings · security.