rtl_433 on a Raspberry Pi made bulletproof

Like I’ve mentioned before, I am using rtl_433 on my Raspberry Pi to receive the outside temperature and humidity from the sensor of my little weather station and store the values in a RRDtool database. Afterwards, I use the gathered data to make some graphs for  different periods in the past.



In general, this works very well, but every now and then, after one or even after a couple of months, something in the RTL-SDR starts to hang, presumably the USB-controller itself, and you are only able to get it running again by disconnecting and reconnecting the stick physically. Least to say that I was not very happy with this circumstance, especially since I’ve tried different sticks, always with the same disappointing result. But like always, at least someone else was dealing with this kind of problem before and luckily already found a solution for it. The name of the solution is usbreset.c, a small C-program that can be build and used within just a few moments.

I am using a small Bash script to determine where the RTL-USB is located on the bus by using lsusb and to afterwards call the executable of usbreset.

LSUSB=$(lsusb | grep --ignore-case $USBNAME)
DEVICE="/dev/bus/usb/"$(echo $LSUSB | cut --delimiter=' ' --fields='2')"/"$(echo $LSUSB | cut --delimiter=' ' --fields='4' | tr --delete ":")
usbreset $DEVICE 2>&1 >/dev/null

Below is the Python script which I use for calling rtl_433. If everything went fine with the call, I write the received values to the database, otherwise I call the Bash script from above to force an USB reset of the RTL-SDR (instead of a physical reconnect).


import sys
import os
import rrdtool

# read the current weather data
process = os.popen('rtl_433 -g 42.1 -f 868250000 -q -R 8 -T 65')
str = process.read()

if not str:
	os.system('sudo ./reset_rtlsdr.sh')

str = str.strip()
str = str.replace('\t', '')
str = str.replace('\n', ' ')
data = str.split(' ')

# check the order of the two messages and act accordingly
if data[6] == 'Temperature:' and data[15] == 'Humidity:':
	update = 'N:' + data[7] + ':' + data[16]
	# insert data into database
	rrdtool.update("%s/weather.rrd" % (os.path.dirname(os.path.abspath(__file__))), update)
elif data[6] == 'Humidity:' and data[15] == 'Temperature:':
	update = 'N:' + data[16] + ':' + data[7]
	# insert data into database
	rrdtool.update("%s/weather.rrd" % (os.path.dirname(os.path.abspath(__file__))), update)

4 thoughts on “rtl_433 on a Raspberry Pi made bulletproof”

  1. Thanks for this! I rewrote the device find shell script and usbreset C code into a single python script.

    #!/usr/bin/env python3

    import sys, os
    import subprocess
    import fcntl

    USBDEVFS_RESET = ord('U') < & 1 > / dev / null

    for line in subprocess.check_output(["lsusb"]).decode().split('\n'):
    if USBNAME in line: break
    usbbus = line.split(' ')[1]
    usbdevice = line.split(' ')[3].strip(':')
    device = '/dev/bus/usb/{}/{}'.format(usbbus, usbdevice)

    return device

    filename = find_rtl433_usb()
    fd = os.open(filename, os.O_WRONLY)
    fcntl.ioctl(fd, USBDEVFS_RESET, 0)
    except Exception as err:



  2. Once you know the vendor ID of your rtl stick you can condense the reset script down to one line:

    /usr/sbin/usb_modeswitch -v 0x0bda -p 0x2838 –reset-usb

    and you can find the vendor ID by running lsusb on the command line.

    I’ve had the rtl_sdr stick lock up on me so often that I placed a call to this in crontab to run every day at 1 AM.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.