soapyremote

package
v1.0.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 4, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Overview

Package soapyremote implements an sdr.Driver that talks to a remote SoapySDRServer (from pothosware/SoapyRemote) in pure Go, with no CGO and no SoapySDR C libraries. SoapySDRServer exposes any SoapySDR-supported radio — USRP, LimeSDR, bladeRF, HackRF, Airspy, RTL-SDR, SDRplay and more — over the network with a real control plane, so GopherTrunk can demodulate trunked systems from high-dynamic-range hardware that rtl_tcp's hardcoded 8-bit stream cannot carry (issue #536).

Two channels are used, mirroring SoapyRemote itself:

  • A TCP RPC control socket (default port 55132) carries device creation, tuning, gain and stream setup as length-framed, type-tagged packets (see rpc.go).
  • A separate stream socket carries 24-byte-framed IQ datagrams (see stream.go), plus a second "status" socket the server requires alongside it. This driver implements the TCP stream transport, which is in-order and needs no UDP flow-control; the operator selects it with `stream_protocol: tcp` (the default). UDP streaming is a future addition (issue #536 phase 2).

The wire format was reverse-engineered from SoapyRemote@master and the RPC, datagram framing, and TCP stream setup choreography are byte-matched to the source (client/Streaming.cpp + server/ClientHandler.cpp). It is exercised by a fake server in the tests; validate against live hardware before release.

Limitations:

  • Receive only. One RX channel (channel 0) by default; `diversity: mrc` opens channels 0 and 1 and combines them into one stream (see mrc.go). Every per-channel setting (frequency, rate, gain, frequency correction) is programmed on both — an unconfigured second receiver is a branch that contributes nothing (issue #1062).
  • SetPPM / SetBiasTee are best-effort: SoapySDR has no universal call for either, so they map to setFrequencyCorrection / writeSetting and silently no-op when the underlying driver doesn't support them.
  • Plaintext, like rtl_tcp. Use on trusted networks or through a tunnel.

Index

Constants

View Source
const DefaultConnectTimeout = 3 * time.Second

DefaultConnectTimeout caps RPC dials and per-call round-trips.

View Source
const DefaultServicePort = "55132"

DefaultServicePort is SoapyRemote's default RPC port (SOAPY_REMOTE_DEFAULT_SERVICE).

View Source
const DriverName = "soapyremote"

DriverName is the sdr.Driver name registered with the pool.

Variables

This section is empty.

Functions

This section is empty.

Types

type Driver

type Driver struct {
	// contains filtered or unexported fields
}

Driver implements sdr.Driver over a set of SoapySDRServer endpoints.

func New

func New(specs []Spec, log *slog.Logger) *Driver

New builds a Driver over the given endpoints.

func (*Driver) Enumerate

func (d *Driver) Enumerate() ([]sdr.Info, error)

Enumerate returns one Info per configured endpoint without probing — a remote that's momentarily down stays in the pool and surfaces its error at Open, matching the rtltcp driver's behaviour.

func (*Driver) Name

func (d *Driver) Name() string

Name implements sdr.Driver.

func (*Driver) Open

func (d *Driver) Open(idx int) (sdr.Device, error)

Open dials the SoapySDRServer at spec[idx], makes the device, and returns a Device ready for setters and StreamIQ.

type Spec

type Spec struct {
	// Addr is the server host:port, e.g. "192.168.1.60:55132". A bare host
	// gets DefaultServicePort appended. Required.
	Addr string
	// Serial is the virtual device serial the pool reports. Empty generates
	// one from Addr so multi-endpoint configs stay unique.
	Serial string
	// Role hints the pool's role assignment: "control" | "voice" | "auto".
	Role string
	// DeviceArgs are the SoapySDR device-selection kwargs passed to MAKE,
	// e.g. {"driver":"lime"} or {"serial":"..."}. Empty selects the server's
	// first/only device.
	DeviceArgs map[string]string
	// Format is the requested wire sample format: "CS16" (default) or "CF32".
	Format string
	// StreamProtocol selects the stream transport: "tcp" (default/only).
	StreamProtocol string
	// StreamMTU sets the stream endpoint MTU in bytes, sent to the server as
	// the "remote:mtu" setupStream arg and used to size the client's
	// flow-control window. Zero (or <=0) uses SoapyRemote's default (1500).
	StreamMTU int
	// StreamWindow sets the stream flow-control window in bytes, sent to the
	// server as the "remote:window" setupStream arg and used as the client's
	// in-flight credit ceiling (advertised as window/StreamMTU sequences).
	// Zero (or <=0) uses the client default (streamWindowBytes, 8 MiB).
	StreamWindow int
	// ConnectTimeout overrides DefaultConnectTimeout when non-zero.
	ConnectTimeout time.Duration
	// Diversity selects a spatial-diversity combiner over a multi-channel RX
	// stream. "" / "none" (default) is the ordinary single-channel stream.
	// "mrc" opens RX channels 0 and 1 and phase-coherently combines them into
	// one stream (shared-LO front-ends only, e.g. USRP B210 / AD9361). See
	// mrc.go. EXPERIMENTAL — issue #1062.
	Diversity string
	// Antennas selects the RX antenna port per channel (SoapySDR setAntenna),
	// applied in channel order after MAKE: Antennas[0] to RX channel 0,
	// Antennas[1] to channel 1 (the diversity second receiver). Empty leaves the
	// device default. A comma-separated multi-antenna value cannot be expressed
	// in the flat DeviceArgs kwargs string, so per-channel antenna routing (e.g.
	// an X310's RX1/RX2 under MRC) goes here instead of args.
	Antennas []string
	// DiversityCapture is a path prefix under which the driver dumps the
	// PRE-COMBINE per-branch IQ once per stream (see branchcapture.go). Empty
	// disables it. Only meaningful with Diversity set.
	DiversityCapture string
	// DiversityCaptureSeconds bounds that dump; <=0 selects
	// defaultDiversityCaptureSeconds.
	DiversityCaptureSeconds int
	// DiversityCaptureFormat selects the branch container: "" / "cs16"
	// (headerless int16 pairs) or "flac" (lossless compressed twin; falls back
	// to cs16 above flacCaptureMaxRateHz).
	DiversityCaptureFormat string
	// VerboseDebug logs every control-channel RPC request and response —
	// decoded arguments plus a hex dump of the frame — at DEBUG. Off by
	// default; the trace is per endpoint so a multi-radio config can follow
	// one server. See rpcdebug.go.
	VerboseDebug bool
}

Spec names one SoapySDRServer endpoint to expose as a virtual tuner.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL