ESP32-based 433 MHz RF analyzer with a live web dashboard.
Captures every OOK/ASK transmission in the 433 MHz band — remote controls, weather stations, door sensors, custom nodes — decodes them in real time, and presents the results in a browser-based dashboard served directly from the ESP32. No cloud, no app, no router required.
- Raw OOK burst capture — pin-change ISR timestamps every edge; bursts are assembled, quality-filtered, and stored in a ring buffer
- PWM/OOK decode — automatically identifies short/long pulse elements and decodes up to 64 bits per burst
- RadioHead RH_ASK decode — receives RadioHead-framed packets at 2000 bps (matches the companion prototype nodes); a 12-byte payload is interpreted as
{float x, float y, float z}accelerometer data - Live noise floor — continuous edge-rate measurement shows ambient RF activity even when no packets arrive
- Web dashboard — single-page app served from flash; auto-refreshes every second; no external assets or internet required
- Serial interface — single-key commands for stats, packet dumps, and noise readings at 115200 baud
- Dual WiFi modes — standalone access point (no router needed) or joins your existing network
| Part | Notes |
|---|---|
| ESP32 dev board | Any standard 38-pin devkit works |
| 433 MHz OOK receiver module | XY-MK-5V, RXB6, or similar |
| ~17.3 cm wire antenna | Quarter-wave for 433 MHz; solder to the ANT pad |
433 MHz Receiver ESP32
┌──────────────┐ ┌───────────┐
│ VCC ─────────────── 5V │
│ GND ─────────────── GND │
│ DATA ─────────────── GPIO 4 │
└──────────────┘ │ GPIO 2 ──── onboard LED (activity)
└───────────┘
The onboard LED on GPIO 2 blinks on each decoded RadioHead packet.
git clone https://github.com/mabushi-lab/NetworkSniffer.git
cd NetworkSnifferpio run -t uploadPlatformIO downloads the single dependency (RadioHead) automatically. WiFi and WebServer are part of the ESP32 Arduino core.
If the upload fails with a baud-rate error, lower
upload_speedinplatformio.inito460800or115200.
Default — standalone access point (no router needed):
- On your phone or laptop, connect to WiFi:
RF-Analyzer/rfanalyzer-433 - Open
http://192.168.4.1/
Alternative — join your existing WiFi:
- Copy
src/credentials.h.example→src/credentials.h - Fill in your SSID and password, set
WIFI_USE_STA 1 - Re-flash — the serial monitor prints the assigned IP
The dashboard polls the ESP32 every second and requires no internet connection.
| Section | What it shows |
|---|---|
| RadioHead link | Packet count, CRC pass/fail rate, throughput, last-seen time |
| Recent RadioHead packets | Per-packet headers, payload (ASCII + hex, or x/y/z for accelerometer) |
| Distinct payloads | Unique payload fingerprints with repeat counts — useful for spotting repeating nodes |
| Noise floor | Live edges/second gauge + 60-second sparkline |
| Raw OOK bursts | Every captured burst: pulse count, duration, decoded value; click a row to expand the full pulse-train waveform |
Controls: pause/resume, refresh rate selector (0.5 s – 5 s), payload filter, and a clear all stats button.
Connect at 115200 baud (pio device monitor).
| Key | Action |
|---|---|
s |
Full stats snapshot |
r |
Last 12 RadioHead packets (newest first) |
g |
Distinct payload groups |
p |
Last 10 raw bursts with full pulse trains |
n |
Current noise floor (edges/second) |
c |
Clear all counters and packet history |
h |
Help |
A heartbeat line is printed every 10 seconds so you can confirm the board is alive even when no RF is present.
src/
├── main.cpp # Setup, loop, serial interface, LED blink
├── rf_capture.h/cpp # Raw OOK burst capture (pin-change ISR + PWM decode)
├── rh_decode.h/cpp # RadioHead RH_ASK receive-only decoder
├── web_ui.h/cpp # WiFi, HTTP server, dashboard HTML, JSON API
└── credentials.h # WiFi credentials for STA mode (gitignored — see .example)
| Endpoint | Description |
|---|---|
GET / |
Dashboard HTML (served from PROGMEM) |
GET /api/all |
Full JSON snapshot — stats, packets, groups |
GET /api/raw?id=N |
Pulse-width array for burst N (lazy-loaded on row expand) |
GET /api/clear |
Reset all counters |
All tuneable constants are at the top of each source file:
| Constant | File | Default | Description |
|---|---|---|---|
PIN_RX |
main.cpp |
4 |
GPIO for the receiver DATA pin |
RF_MAX_PULSES |
rf_capture.h |
300 |
Max pulse-train length kept per burst |
GAP_US |
rf_capture.cpp |
4000 |
Silence (µs) that ends a burst |
MIN_PULSES |
rf_capture.cpp |
16 |
Minimum pulses to keep a burst |
RH_SPEED |
rh_decode.cpp |
2000 |
RadioHead bit rate (must match transmitter) |
JSON_RAW_MAX |
web_ui.cpp |
180 |
Max pulse values returned per /api/raw call |
MIT — see LICENSE.