v0.1.13 · 253 tests · multi-SDR + Orchestrator

The quiet watcher of the airwaves.

An SDR-based RF baseline and anomaly detector. riotduck learns what's normal on your spectrum — and tells you the moment something appears or disappears.

Quick start View on GitHub →

Appearance

A new transmitter pops up where the band was quiet — a rogue beacon, a covert implant, an FPV drone, a wireless camera that wasn't there last week. riotduck flags it within sweeps.

Disappearance

The other half no one watches for. An emitter you've been tracking goes silent. A persistent signal loses power. A covert transmitter you placed gets removed. You hear about it.

Four-stage ID

On appearance, riotduck captures I/Q and runs it through rtl_433 (~250 protocols) → URH (file-mode demod on rtl_433 miss) → unknown-signal analyzer (CW/OOK/FSK/FM/BPSK/QPSK + symbol rate) → your curated library.

Try it without an SDR

A synthetic SDR backend ships with the project — real complex64 I/Q, real detections, no hardware. The full scanner → baseline → dedup → capture → fingerprint pipeline runs end-to-end.

git clone https://github.com/haxorthematrix/riotduck.git
cd riotduck
pip install -e .
riotduck scan --fake 1 --config config/default.yaml

A real 433.92 MHz transmitter that rtl_433 can't decode. URH recovers the bits; the analyzer characterizes the signal independently. Add a library entry and the next burst publishes Identification(source="library") with your name on it. Repeat detections share an event id — the dedup tracker working, including across two SDRs sharing a range.

How it works

Async agents on an in-process pub/sub bus. Each stage is its own module, unit-tested without hardware. 253 tests, ~7 s.

Sweep Baseline Detect Capture rtl_433 URH Analyze Library

Hardware

SoapySDR-first with a pyrtlsdr fallback. Two RTL-SDRs sweeping in parallel works (libusb darwin threading handled). The synthetic backend is built in for hardware-free testing. See the README for the BOM and wiring diagrams.

Validated

  • RTL-SDR Blog V3/V4 (R820T2)
  • Two RTL-SDRs in parallel (shared dedup)
  • Duplicate factory serials auto-disambiguated
  • Synthetic SDR (built-in)

Next up

  • HackRF One (streaming path in, not yet hardware-tested)
  • hackrf_sweep fast path for multi-GHz ranges
  • Orchestrator + CaptureAgent split (one SDR sweeps while another captures)
  • Airspy / SDRplay / LimeSDR / USRP via SoapySDR

Sinks & storage

  • stdout — terminal events
  • jsonl — durable, line-oriented
  • sqlite — indexed, queryable via events
  • webhook — POST JSON to anything
  • Persistent baselines · sweep recorder · capture sidecars