Welcome to pyrtlsdr’s documentation!
Overview
Description
pyrtlsdr is a simple Python interface to devices supported by the RTL-SDR project, which turns certain USB DVB-T dongles employing the Realtek RTL2832U chipset into low-cost, general purpose software-defined radio receivers. It wraps many of the functions in the librtlsdr library including asynchronous read support and also provides a more Pythonic API.
Links
Documentation:
Releases:
Source code and project home:
Releases for
librtlsdr
:
Usage
pyrtlsdr can be installed by downloading the source files and running python setup.py install
, or using pip and
pip install pyrtlsdr
.
All functions in librtlsdr are accessible via librtlsdr.py and a Pythonic interface is available in rtlsdr.py (recommended). Some documentation can be found in docstrings in the latter file.
Examples
Simple way to read and print some samples:
from rtlsdr import RtlSdr
sdr = RtlSdr()
# configure device
sdr.sample_rate = 2.048e6 # Hz
sdr.center_freq = 70e6 # Hz
sdr.freq_correction = 60 # PPM
sdr.gain = 'auto'
print(sdr.read_samples(512))
Plotting the PSD with matplotlib:
from pylab import *
from rtlsdr import *
sdr = RtlSdr()
# configure device
sdr.sample_rate = 2.4e6
sdr.center_freq = 95e6
sdr.gain = 4
samples = sdr.read_samples(256*1024)
sdr.close()
# use matplotlib to estimate and plot the PSD
psd(samples, NFFT=1024, Fs=sdr.sample_rate/1e6, Fc=sdr.center_freq/1e6)
xlabel('Frequency (MHz)')
ylabel('Relative power (dB)')
show()
Resulting Plot:
See the files ‘demo_waterfall.py’ and ‘test.py’ for more examples.
Handling multiple devices:
(added in v2.5.6)
from rtlsdr import RtlSdr
# Get a list of detected device serial numbers (str)
serial_numbers = RtlSdr.get_device_serial_addresses()
# Find the device index for a given serial number
device_index = RtlSdr.get_device_index_by_serial('00000001')
sdr = RtlSdr(device_index)
# Or pass the serial number directly:
sdr = RtlSdr(serial_number='00000001')
Note
Most devices by default have the same serial number: ‘0000001’. This can be set
to a custom value by using the rtl_eeprom utility packaged with librtlsdr
.
Experimental features
Two new submodules are available for testing: rtlsdraio, which adds native Python 3 asynchronous support (asyncio module), and rtlsdrtcp which adds a TCP server/client for accessing a device over the network. See the respective modules in the rtlsdr folder for more details and feel free to test and report any bugs!
rtlsdraio
Note that the rtlsdraio module is automatically imported and adds stream()
and stop()
methods to the normal RtlSdr
class. It also requires the new async
/await
syntax introduced in Python 3.5+.
The syntax is basically:
import asyncio
from rtlsdr import RtlSdr
async def streaming():
sdr = RtlSdr()
async for samples in sdr.stream():
# do something with samples
# ...
# to stop streaming:
await sdr.stop()
# done
sdr.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(streaming())
rtlsdrtcp
The RtlSdrTcpServer
class is meant to be connected physically to an SDR dongle and communicate with an instance of RtlSdrTcpClient
. The client is intended to function as closely as possible to the base RtlSdr class (as if it had a physical dongle attached to it).
Both of these classes have the same arguments as the base RtlSdr
class with the addition of hostname
and port
:
server = RtlSdrTcpServer(hostname='192.168.1.100', port=12345)
server.run_forever()
# Will listen for clients until Ctrl-C is pressed
# On another machine (typically)
client = RtlSdrTcpClient(hostname='192.168.1.100', port=12345)
client.center_freq = 2e6
data = client.read_samples()
TCP Client Mode
On platforms where the librtlsdr
library cannot be installed/compiled, it is possible to import the RtlSdrTcpClient
only by setting the environment variable "RTLSDR_CLIENT_MODE"
to "true"
. If this is set, no other modules will be available.
Feature added in v0.2.4
Dependencies
Windows/Linux/OSX
Python 2.7.x/3.3+
Optional: NumPy (wraps samples in a more convenient form)
matplotlib is also useful for plotting data. The librtlsdr binaries (rtlsdr.dll in Windows and librtlsdr.so in Linux) should be in the pyrtlsdr directory, or a system path. Note that these binaries may have additional dependencies.
Todo
There are a few remaining functions in librtlsdr that haven’t been wrapped yet. It’s a simple process if there’s an additional function you need to add support for, and please send a pull request if you’d like to share your changes.
Troubleshooting
Some operating systems (Linux, OS X) seem to result in libusb buffer issues when performing small reads. Try reading 1024 (or higher powers of two) samples at a time if you have problems.
If you’re having librtlsdr import errors:
Windows: Make sure all the librtlsdr DLL files (librtlsdr.dll, libusb-1.0.dll) are in your system path, or the same folder as this README file. Also make sure you have all of their dependencies (e.g. libgcc_s_dw2-1.dll or possibly the Visual Studio runtime files). If rtl_sdr.exe works, then you should be okay. Also note that you can’t mix the 64 bit version of Python with 32 bit builds of librtlsdr, and vice versa.
Linux: Make sure your LD_LIBRARY_PATH environment variable contains the directory where the librtlsdr.so.0 library is located. You can do this in a shell with (for example):
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/lib
. See this issue for more details.
License
All of the code contained here is licensed by the GNU General Public License v3.
Credit
Credit to dbasden for his earlier wrapper python-librtlsdr and all the contributers on GitHub.
Copyright (C) 2013 by Roger https://github.com/roger-
Reference
rtlsdr.rtlsdr
- class rtlsdr.rtlsdr.BaseRtlSdr(device_index=0, test_mode_enabled=False, serial_number=None)[source]
Bases:
object
Core interface for most API functionality
- Parameters
device_index (
int
, optional) – The device index to use if there are multiple dongles attached. If only one is being used, the default value (0) will be used.test_mode_enabled (
bool
, optional) – If True, enables a special test mode, which will return the value of an internal RTL2832 8-bit counter with calls toread_bytes()
.serial_number (
str
, optional) – If not None, the device will be searched for by the given serial_number byget_device_index_by_serial()
and thedevice_index
returned will be used automatically.
- DEFAULT_FC
Default
center_freq
value used on initialization:80e6
(80 Mhz)- Type
- DEFAULT_RS
Default
sample_rate
value used on initialization:1.024e6
(1024 Msps)- Type
- DEFAULT_READ_SIZE
Default number of samples or bytes to read if no arguments are supplied for
read_bytes()
orread_samples()
. Default value is1024
- Type
- gain_values
The valid gain parameters supported by the device (in tenths of dB). These are stored as returned by
librtlsdr
.
- static get_device_index_by_serial(serial)[source]
Retrieves the device index for a device matching the given serial number
- Parameters
serial (str) – The serial number to search for
- Returns
The device_index as reported by
librtlsdr
- Return type
Notes
Most devices by default have the same serial number: ‘0000001’. This can be set to a custom value by using the rtl_eeprom utility packaged with
librtlsdr
.
- get_tuner_type()[source]
Get the tuner type.
- Returns
The tuner type as reported by the driver. See the tuner enum definition for more information.
- Return type
- init_device_values()[source]
Retrieves information from the device
This method acquires the values for
gain_values
. Also sets the device to the defaultcenter frequency
, thesample rate
andgain
- open(device_index=0, test_mode_enabled=False, serial_number=None)[source]
Connect to the device through the underlying wrapper library
Initializes communication with the device and retrieves information from it with a call to
init_device_values()
.- Parameters
device_index (
int
, optional) – The device index to use if there are multiple dongles attached. If only one is being used, the default value (0) will be used.test_mode_enabled (
bool
, optional) – If True, enables a special test mode, which will return the value of an internal RTL2832 8-bit counter with calls toread_bytes()
.serial_number (
str
, optional) – If not None, the device will be searched for by the given serial_number byget_device_index_by_serial()
and thedevice_index
returned will be used automatically.
Notes
The arguments used here are passed directly from object initialization.
- Raises
IOError – If communication with the device could not be established.
- packed_bytes_to_iq(bytes)[source]
Unpack a sequence of bytes to a sequence of normalized complex numbers
This is called automatically by
read_samples()
.- Returns
The unpacked iq values as either a
list
ornumpy.ndarray
(if available).
- read_bytes(num_bytes=1024)[source]
Read specified number of bytes from tuner.
Does not attempt to unpack complex samples (see
read_samples()
), and data may be unsafe as buffer is reused.- Parameters
num_bytes (
int
, optional) – The number of bytes to read. Defaults toDEFAULT_READ_SIZE
.- Returns
A buffer of len(num_bytes) containing the raw samples read.
- Return type
ctypes.Array[c_ubyte]
- read_samples(num_samples=1024)[source]
Read specified number of complex samples from tuner.
Real and imaginary parts are normalized to be in the range [-1, 1]. Data is safe after this call (will not get overwritten by another one).
- Parameters
num_samples (
int
, optional) – Number of samples to read. Defaults toDEFAULT_READ_SIZE
.- Returns
The samples read as either a
list
ornumpy.ndarray
(if available).
- set_direct_sampling(direct)[source]
Enable direct sampling.
- Parameters
direct – If False or 0, disable direct sampling. If ‘i’ or 1, use ADC I input. If ‘q’ or 2, use ADC Q input.
- set_manual_gain_enabled(enabled)[source]
Enable or disable manual gain control of tuner.
- Parameters
enabled (bool) –
Notes
If
enabled
is False, then AGC should also be used by callingset_agc_mode()
. It is recommended to useset_gain()
instead of calling this method directly.
- property bandwidth
Get/Set bandwidth value (in Hz)
Set value to 0 (default) for automatic bandwidth selection.
Notes
This value is stored locally and may not reflect the real tuner bandwidth
- Type
- property gain
Get/Set gain of the tuner (in dB)
Notes
If set to ‘auto’, AGC mode is enabled; otherwise gain is in dB. The actual gain used is rounded to the nearest value supported by the device (see the values in
valid_gains_db
).
- class rtlsdr.rtlsdr.RtlSdr(device_index=0, test_mode_enabled=False, serial_number=None)[source]
Bases:
rtlsdr.rtlsdr.BaseRtlSdr
This adds async read support to
BaseRtlSdr
- _bytes_converter_callback(raw_buffer, num_bytes, context)[source]
Converts the raw buffer used in
rtlsdr_read_async
to a usable typeThis method is used internally by
read_bytes_async()
to convert the raw data fromrtlsdr_read_async
into a memory-safe array.The callback given in
read_bytes_async()
will then be called with the signature:callback(values, context)
- Parameters
Notes
This method is not meant to be called directly or overridden by subclasses.
- _samples_converter_callback(buffer, context)[source]
Converts the raw buffer used in
rtlsdr_read_async
to a usable typeThis method is used internally by
read_samples_async()
to convert the data into a sequence of complex numbers.The callback given in
read_samples_async()
will then be called with the signature:callback(samples, context)
- Parameters
buffer – Buffer of type
unsigned char
context – User-defined value passed to
rtlsdr_read_async
. In most cases, will be a reference to theRtlSdr
instance
Notes
This method is not meant to be called directly or overridden by subclasses.
- cancel_read_async()[source]
Cancel async read. This should be called eventually when using async reads (
read_bytes_async()
orread_samples_async()
), or callbacks will never stop.See also
- read_bytes_async(callback, num_bytes=1024, context=None)[source]
Continuously read bytes from tuner
- Parameters
callback – A function or method that will be called with the result. See
_bytes_converter_callback()
for the signature.num_bytes (int) – Number of bytes to read for each callback. Defaults to
DEFAULT_READ_SIZE
.context (Optional) – Object to be passed as an argument to the callback. If not supplied or None, the
RtlSdr
instance will be used.
Notes
As with
read_bytes()
, the data passed to the callback may by overwritten.
- read_samples_async(callback, num_samples=1024, context=None)[source]
Continuously read ‘samples’ from the tuner
This is a combination of
read_samples()
andread_bytes_async()
- Parameters
callback – A function or method that will be called with the result. See
_samples_converter_callback()
for the signature.num_samples (int) – The number of samples read into each callback. Defaults to
DEFAULT_READ_SIZE
.context (Optional) – Object to be passed as an argument to the callback. If not supplied or None, the
RtlSdr
instance will be used.
rtlsdr.rtlsdraio
This module adds asyncio
support for reading samples from the device.
The main functionality can be found in the stream()
method of rtlsdr.rtlsdraio.RtlSdrAio
.
Example
import asyncio
from rtlsdr import RtlSdr
async def streaming():
sdr = RtlSdr()
async for samples in sdr.stream():
# do something with samples
# ...
# to stop streaming:
await sdr.stop()
# done
sdr.close()
loop = asyncio.get_event_loop()
loop.run_until_complete(streaming())
- class rtlsdr.rtlsdraio.AsyncCallbackIter(func_start, func_stop=None, queue_size=20, *, loop=None)
Bases:
object
Convert a callback-based legacy async function into one supporting asyncio and Python 3.5+
The queued data can be iterated using
async for
- Parameters
func_start – A callable which should take a single callback that will be passed data. Will be run in a seperate thread in case it blocks.
func_stop (optional) – A callable to stop
func_start
from calling the callback. Will be run in a seperate thread in case it blocks.queue_size (
int
, optional) – The maximum amount of data that will be buffered.loop (optional) – The
asyncio.event_loop
to use. If not supplied,asyncio.get_event_loop()
will be used.
- async add_to_queue(*args)
Add items to the queue
- Parameters
*args – Arguments to be added
This method is a
coroutine
- class rtlsdr.rtlsdraio.RtlSdrAio(device_index=0, test_mode_enabled=False, serial_number=None)[source]
Bases:
rtlsdr.rtlsdr.RtlSdr
- stop()[source]
Stop async stream
Stops the
read_samples_async
andExcecutor
task created bystream()
.
- stream(num_samples_or_bytes=131072, format='samples', loop=None)[source]
Start async streaming from SDR and return an async iterator (Python 3.5+).
The
read_samples_async()
method is called in anExcecutor
instance usingasyncio.AbstractEventLoop.run_in_executor()
.The returned asynchronous iterable can then used to retrieve sample data using
async for
syntax.Calling the
stop()
method will stop theread_samples_async
session and close theExcecutor
task.- Parameters
- Returns
An
asynchronous iterator
to yield sample data
rtlsdr.rtlsdrtcp
This module allows client/server communication.
The RtlSdrTcpServer
class is meant to be
connected physically to an SDR dongle and communicate with an instance of
RtlSdrTcpClient
.
The client is intended to function as closely as possible to the base
RtlSdr
class (as if it had a physical dongle
attached to it).
Both of these classes have the same arguments as the base
RtlSdr
class with the addition of hostname
and port
.
Examples
server = RtlSdrTcpServer(hostname='192.168.1.100', port=12345)
server.run_forever()
# Will listen for clients until Ctrl-C is pressed
# On another machine (typically)
client = RtlSdrTcpClient(hostname='192.168.1.100', port=12345)
client.center_freq = 2e6
data = client.read_samples()
Note
On platforms where the librtlsdr
library cannot be installed/compiled,
it is possible to import RtlSdrTcpClient
only by
setting the environment variable "RTLSDR_CLIENT_MODE"
to "true"
.
If this is set, no other modules will be available.
Feature added in v0.2.4
rtlsdr.rtlsdrtcp.server
- class rtlsdr.rtlsdrtcp.server.RtlSdrTcpServer(device_index=0, test_mode_enabled=False, serial_number=None, hostname='127.0.0.1', port=None)[source]
Bases:
rtlsdr.rtlsdr.RtlSdr
,rtlsdr.rtlsdrtcp.base.RtlSdrTcpBase
Server that connects to a physical dongle to allow client connections.
- open(device_index=0, test_mode_enabled=False, serial_number=None)[source]
Connect to the device through the underlying wrapper library
Initializes communication with the device and retrieves information from it with a call to
init_device_values()
.- Parameters
device_index (
int
, optional) – The device index to use if there are multiple dongles attached. If only one is being used, the default value (0) will be used.test_mode_enabled (
bool
, optional) – If True, enables a special test mode, which will return the value of an internal RTL2832 8-bit counter with calls toread_bytes()
.serial_number (
str
, optional) – If not None, the device will be searched for by the given serial_number byget_device_index_by_serial()
and thedevice_index
returned will be used automatically.
Notes
The arguments used here are passed directly from object initialization.
- Raises
IOError – If communication with the device could not be established.
- read_samples(num_samples=1024)[source]
This overrides the base implementation so that the raw data is sent. It will be unpacked to I/Q samples on the client side.
- class rtlsdr.rtlsdrtcp.server.Server(rtl_sdr)[source]
Bases:
socketserver.TCPServer
- REQUEST_RECV_SIZE = 1024
- class rtlsdr.rtlsdrtcp.server.ServerThread(rtl_sdr)[source]
Bases:
threading.Thread
- run()[source]
Method representing the thread’s activity.
You may override this method in a subclass. The standard run() method invokes the callable object passed to the object’s constructor as the target argument, if any, with sequential and keyword arguments taken from the args and kwargs arguments, respectively.
rtlsdr.rtlsdrtcp.client
- class rtlsdr.rtlsdrtcp.client.RtlSdrTcpClient(device_index=0, test_mode_enabled=False, hostname='127.0.0.1', port=None)[source]
Bases:
rtlsdr.rtlsdrtcp.base.RtlSdrTcpBase
Client object that connects to a remote server.
Exposes most of the methods and descriptors that are available in the RtlSdr class in a transparent manner allowing an interface that is nearly identical to the core API.
- property bandwidth
- property center_freq
- property fc
- property freq_correction
- property gain
- property rs
- property sample_rate
rtlsdr.rtlsdrtcp.base
- class rtlsdr.rtlsdrtcp.base.AckMessage(**kwargs)[source]
Bases:
rtlsdr.rtlsdrtcp.base.MessageBase
Simple message type meant for ACKnolegemnt of message receipt
- class rtlsdr.rtlsdrtcp.base.ClientMessage(**kwargs)[source]
- class rtlsdr.rtlsdrtcp.base.MessageBase(**kwargs)[source]
Bases:
object
Base class for messages sent between clients and servers.
Hanldes serialization/deserialization and communication with socket type objects.
- timestamp
Timestamp given from
time.time()
- Type
- data
The payload containing either the request or response data
- classmethod from_remote(sock)[source]
Reads data from the socket and parses an instance of
MessageBase
- Parameters
sock – The
socket
object to read from
- get_header(**kwargs)[source]
Builds the header data for the message
The
timestamp
is added to the header if not already present.- Returns
- Return type
- get_response(sock)[source]
Waits for a specific response message
The message class returned from
get_response_class()
is used to parse the message (called fromfrom_remote()
)- Parameters
sock – The
socket
object to read from
- class rtlsdr.rtlsdrtcp.base.RtlSdrTcpBase(device_index=0, test_mode_enabled=False, hostname='127.0.0.1', port=None)[source]
Bases:
object
Base class for all
rtlsdrtcp
functionality- Parameters
- DEFAULT_PORT = 1235
- class rtlsdr.rtlsdrtcp.base.ServerMessage(**kwargs)[source]
Bases:
rtlsdr.rtlsdrtcp.base.MessageBase
- classmethod from_remote(sock)[source]
Reads data for the socket buffer and reconstructs the appropriate message that was sent by the other end.
This method is used by clients to reconstruct ServerMessage objects and if necessary, use multiple read calls to get the entire message (if the message size is greater than the buffer length)
rtlsdr.helpers
- rtlsdr.helpers.limit_calls(max_calls)[source]
Decorator to cancel async reads after the given number of calls.
- Parameters
max_calls (int) – Number of calls to wait for before cancelling
Examples
- Stop reading after 10 calls:
>>> @limit_calls(10) >>> def read_callback(data, context): >>> print('signal mean:', sum(data)/len(data)) >>> sdr = RtlSdr() >>> sdr.read_samples_async(read_callback)
Notes
See notes in
limit_time()
- rtlsdr.helpers.limit_time(max_seconds)[source]
Decorator to cancel async reads after a specified time period.
- Parameters
max_seconds – Number of seconds to wait before cancelling
Examples
- Stop reading after 10 seconds:
>>> @limit_time(10) >>> def read_callback(data, context): >>> print('signal mean:', sum(data)/len(data)) >>> sdr = RtlSdr() >>> sdr.read_samples_async(read_callback)
Notes
The context in either
read_bytes_async()
orread_samples_async()
is relied upon and must use the default value (theRtlSdr
instance)