back to projects
focus project

Xora WiFi Motion Tracking

A camera-free human motion tracking system that uses WiFi Channel State Information (CSI) to detect and locate movement within a room - visualized through a live 2D heatmap and 3D room reconstruction.

2026Sensing / Machine LearningPythonTensorFlowESP32FlaskWebSocketWiFi CSICNN+LSTM
4
ESP32 nodes
30s
Calibration window
x,y position
Output
0
Cameras used
Demo
Walk through video
mp4

Live walkthrough of the dashboard tracking movement across my room.

Overview

What it is

Every WiFi packet that travels through a room arrives slightly altered by what it passed through - human bodies, being mostly water, disrupt the signal far more than walls or furniture. Xora exploits this: one ESP32 transmits constantly while three others, placed in the room's corners, measure how the incoming signal's amplitude shifts. Those shifts get triangulated into an estimated position and pushed live to a dashboard.

Four ESP32 boards form a sensing layer, while Python and TensorFlow handle signal processing and position regression - no cameras, no privacy tradeoffs.

Pipeline

Signal → position

01
Transmit

One ESP32 (TX) blasts WiFi packets continuously, flooding the room with a steady signal carrier.

02
Sense

Three ESP32 receivers in the room corners read CSI amplitude per packet using esp_wifi_set_csi_rx_cb.

03
Stream

Raw CSI data is pushed over UDP to a Flask backend running on the same local WiFi network.

04
Baseline

A 30-second empty-room calibration is subtracted live - walls and furniture become invisible to the system.

05
Model

A CNN+LSTM model regresses x,y position from the remaining signal variance across subcarriers.

06
Render

Live 2D heatmap + interactive 3D room reconstruction, pushed to the dashboard over WebSocket.

Tracking output
Live XY grid view
mp4

Me moving around the room while the dashboard plots my position as an x, y point on a grid.

Work in progress

Still prototyping — more updates coming.

I'm actively building and iterating on Xora in my free time. Getting WiFi CSI sensing reliable across different rooms, calibrations, and edge cases is slow, experimental work. I'll keep updating this page as I make progress — expect experiments, dead ends, and the occasional breakthrough.

Features

What it can do

Behind the build

Challenges & learnings

Port conflicts / Architecture
Architecture

The data collection script originally opened its own UDP socket on the same port the main server was already listening on, causing collection to hang silently with no error.

fixRefactored it to read from the shared CSI buffer the server already maintains, instead of competing for the same port.
Position vs. classification / ML
ML

The first trained model only classified motion as present/absent - it never learned where in the room someone was. Position tracking needed a fundamentally different approach.

fixSwitched to zone-labeled regression training - stand at known coordinates, train the model to regress x,y instead of a binary class.
Variable packet length / Firmware
Firmware

Real CSI readings don't arrive with a perfectly consistent subcarrier count packet to packet, which broke numpy's array stacking with shape mismatches.

fixEvery reading now gets padded or truncated to a fixed length before buffering.
Network drift / Infrastructure
Infra

The laptop's local IP changed after a WiFi reconnect, silently breaking all UDP delivery from the boards with no obvious error - just nothing arriving.

fixIP re-verification before each firmware flash; diagnosed by checking active port bindings.
Use cases

Where it fits

Privacy-first smart home

Know when someone enters a room without putting cameras or microphones inside it.

Elderly fall detection

Detect unusual stillness or sudden floor-level position without wearables or cameras in the bathroom.

Security & intrusion

Pick up motion through walls in spaces where camera coverage is impractical or unwanted.

Software & hardware

Tech stack

Hardware
ESP32-WROOM-32 x4LoR Core v3 (TX)esp_wifi_set_csi_rx_cb
Backend
PythonFlaskFlask-SocketIOUDPTensorFlow / Keras
Frontend
Vanilla JSCanvas 2D + 3DWebSocket

Backend in Flask + Flask-SocketIO for real-time push updates. TensorFlow/Keras handles the CNN+LSTM training pipeline. The frontend is a single-page dashboard built with vanilla JS and Canvas - no framework - rendering both the 2D heatmap and a hand-rolled 3D projection engine for the room view.