Sample Streaming API

Note

The Sample Streaming API is provided on TCP port 5308. This API is only available on the GRX3X.

The Sample Streaming API provides continuous raw I/Q sample streaming from a specific radio channel. Unlike the per-detection I/Q samples available through the Receiver API, this API delivers a continuous, uninterrupted stream of samples – similar to an SDR (Software Defined Radio) data source.

This is useful for:

  • Generic frequency monitoring

  • Custom signal processing and decoding

  • Recording raw I/Q data to disk

  • Feeding external signal processing pipelines

Service Methods

// Query stream properties (center frequency, sample rate, calibration)
rpc GetStreamProperties (GetStreamPropertiesRequest) returns (StreamProperties);

// Start streaming I/Q sample blocks
rpc StartStream (StartStreamRequest) returns (stream StartStreamReply);

Stream Properties

Before starting a stream, call GetStreamProperties to retrieve:

  • Center frequency (Hz): The frequency the radio is tuned to.

  • Sample rate (Hz): The I/Q sample rate.

  • Calibration value (dB): Used to convert raw sample magnitudes to absolute power levels in dBm:

    signal_level [dBm] = calibration_value + 10 * log10(I² + Q²)
    

Note

When channel parameters (e.g. center frequency or hardware gain) are changed through the Tunable Channel API, GetStreamProperties should be called again after a few seconds to obtain updated values. If frequent changes are expected, it is also possible to poll this method periodically.

Starting a Stream

Call StartStream with a StartStreamRequest specifying:

  • radio_identification: The radio channel to stream from (band + per-band index). Use BAND_1090_MHZ, BAND_1030_MHZ, BAND_978_MHZ, BAND_TUNABLE, etc.

  • requested_blocks: Number of sample blocks to receive. Set to 0 for indefinite streaming.

Each StartStreamReply in the stream contains:

  • block_timestamp: Timestamp for this block of samples.

  • samples: Raw I/Q data as bytes (signed 16-bit interleaved: I0, Q0, I1, Q1, …). Each I/Q pair is 4 bytes.

  • lost_blocks: Counter for lost blocks. If this value increases between consecutive replies, blocks were dropped.

Warning

Continuous I/Q streaming produces very high data rates. At 12 MHz sample rate with 16-bit I/Q, the raw data rate is approximately 48 MB/s per daughterboard. Ensure your network link and processing pipeline can handle the throughput. Monitor the lost_blocks counter to detect data loss.

Identifying Radio Channels

The RadioIdentification message (defined in Common.proto) identifies a radio channel by its frequency band and per-band index:

message RadioIdentification {
  Band band = 1;        // e.g., BAND_1090_MHZ, BAND_TUNABLE
  int32 per_band_index = 2;  // 0 for the first radio of that band
}

Use the Tunable Channel API to discover and configure tunable channels before streaming.

Protocol Buffer Definition

syntax = "proto3";

package serosystems.proto.v3.grx.samplestreamingd;
option java_package = "de.serosystems.proto.v3.grx.samplestreamingd";
option java_outer_classname = "SamplestreamingDProto";

import "Common.proto";

/**
 * Message describing the properties of a stream.
 */
message StreamProperties {

	/* Center Frequency [Hz]. */
	uint32 center_frequency = 1;

	/* Sample rate [Hz]. */
	uint32 sample_rate = 2;

	/* Calibration value to convert from sample values to signal level in dBm.
	 * Use the following formula to convert the squared magnitude (i.e. I^2 + Q^2) to a signal level in dBm:
	 * signal_level [dBm] = calibration_value + 10 * log10(I^2 + Q^2)
	 */
	float calibration_value = 3;

}

/* Request type for GetStreamProperties call */
message GetStreamPropertiesRequest {

	/* Radio identification of the chosen RX channel */
	RadioIdentification radio_identification = 1;

}

/* Request type for StartStream call */
message StartStreamRequest {

	/* Radio identification of the chosen RX channel */
	RadioIdentification radio_identification = 1;

	/* The number of blocks that are requested, set to zero for indefinite streaming */
	uint32 requested_blocks = 2;
}

/* Reply type for StartStream call */
message StartStreamReply {

	/* data is streamed in blocks, each block has a timestamp */
	uint64 block_timestamp = 1;

	/* the samples */
	bytes samples = 2;

	/* counter for lost blocks, can be used to find out a) if blocks have been lost and b) where exactly */
	uint32 lost_blocks = 3;

}

/* Sample streaming daemon service definition. Port 5308. */
service Samplestreamingd {

	/* Request the stream properties. They usually do not change over time
	 * (unless the radio front-end allows retuning/changing settings, see TunableChanneld).
	 * Returns INVALID_ARGUMENT if chosen RX channel is not available.
	 */
	rpc GetStreamProperties (GetStreamPropertiesRequest) returns (StreamProperties);

	/*
	 * Request a stream of samples.
	 * Returns INVALID_ARGUMENT if chosen RX channel is not available
	 */
	rpc StartStream(StartStreamRequest) returns (stream StartStreamReply) {}
	
}