Common abstraction for SDR sources used by the main orchestrator. One
trait, a few shared types, no third-party SDR dependencies. Every
backend (USRP, HackRF, ADALM-Pluto, file / SigMF,
Aaronia HTTP / SDK / RTSA) implements SdrSource
and emits the same IqPacket shape so the orchestrator can dispatch
detection uniformly.
pub trait SdrSource: Send {
fn start(
self: Box<Self>,
config: SourceConfig,
advice: Arc<dyn DwellAdvice>,
) -> Result<SdrHandle, SdrError>;
}start consumes the builder (Box<Self>), spawns whatever capture
threads the backend needs, and returns an SdrHandle:
pub struct SdrHandle {
pub receiver: Receiver<IqPacket>,
pub stop: Box<dyn FnOnce() + Send>,
}receiver is a crossbeam::channel::Receiver<IqPacket>. Every
backend, regardless of how it got the data, emits the same shape:
pub struct IqPacket {
pub samples: PooledIqBuffer, // Deref<Target = [Complex32]>
pub center_frequency_hz: f64,
pub sample_rate_hz: f32,
pub overrun: bool,
}samples is a PooledIqBuffer — a smart wrapper around Vec<Complex32>
that automatically returns the vector to a recycling pool when dropped.
It implements Deref<Target = [Complex32]>, so consumers treat it
exactly like a &[Complex32] slice.
sample_rate_hz is f32 rather than f64 because the downstream
DSP (FFT, polyphase resampler) is single-precision — keeping the
rate at the same width avoids silent narrowings at the boundary.
stop is the shutdown hook; calling it (or dropping the handle and
letting receiver disconnect on the next iteration) winds the capture
thread down.
tests/contract.rs exercises a minimal mock implementation to verify
the basic shape: start returns a non-empty receiver, dropping the
handle releases the receiver, stop() is idempotent.
Tiny on purpose:
crossbeam = "0.8" # channel
num-complex = "0.4" # Complex32
thiserror = "2.0" # SdrError
anyhow = "1.0" # SdrError::Backend pass-throughNo SDR hardware dependencies — those live in the implementation crates.
- Architecture & Design — internal architecture and execution flow.
This project is licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later) - see the LICENSE file for details.
- 🐛 Issues: GitHub Issues