sdr rpi recipe - weewx/weewx GitHub Wiki
Use software-defined radio (SDR) to collect data
This is a guide to build a low-cost system that will collect data from any number of wireless sensors. The recipes in this guide use a USB software-defined radio (SDR) plugged in to a raspberry pi, collecting data from Acurite temperature and temperature/humidity sensors. This approach will work with many other types of sensors from other manufacturers, and it will run on other types of computers and operating systems.
Each sensor uses 2 AA batteries, and the batteries typically last a couple of years under normal temperature ranges. The raspberry pi has a real-time clock and is connected to a home router via ethernet (an old ASUS running tomatoUSB). A network connection is not required to run the system, but it is necessary to download the software.
It took me about 2 hours to build this system. That includes the time to remove all of the hardware from its packaging, place the sensors around the house, take the dog for a walk, and take a short break to eat some freshly baked cookies.
What does it look like?
What do you need?
cost | description | example model | source |
---|---|---|---|
$20 | USB SDR | NooElec | https://www.amazon.com/NooElec-NESDR-Mini-Compatible-Packages/dp/B009U7WZCA/ |
$40 | RPi | 3B+ | https://www.amazon.com/ELEMENT-Element14-Raspberry-Pi-Motherboard/dp/B07BDR5PDW/ |
$12 | SD card | SanDisk Ultra 64 | https://www.amazon.com/dp/B073JYVKNX/ |
$6 | Case | https://www.amazon.com/Raspberry-Case-Black-Compatible-Model/dp/B00UW2G1BS/ | |
$10 | Power supply | https://www.amazon.com/CanaKit-Raspberry-Supply-Adapter-Listed/dp/B00MARDJZ4/ | |
$13 | temperature/humidity sensor | Acurite 06002M | https://www.amazon.com/AcuRite-06002M-Wireless-Temperature-Humidity/dp/B00T0K8NXC/ |
$13 | temperature sensor | Acurite 606TX | https://www.amazon.com/AcuRite-606TX-Wireless-Temperature-Sensor/dp/B00V4R5EUO/ |
$13 | temperature/humidity sensor | FineOffset WH31 | https://www.amazon.com/ECOWITT-Multi-Channel-Temperature-Humidity-Sensor/dp/B07JLRJRLM/ |
The prices are US$ as of January 2019. I have seen the temperature sensors on sale at Walmart for as little as $5 each.
Beware of the Acurite 606TX! The identifier for that sensor changes when the sensor is power-cycled. So if you use that sensor, you will have to reconfigure WeeWX each time you change the batteries.
Recipes
Configure the raspberry pi
There are many guides available for bootstrapping a raspberry pi. There are also many guides available for installing and configuring a real-time clock in the raspberry pi. Do it!
The rest of this guide requires only command-line access to the pi. So you can do the steps below remotely logged in via ssh, or in a terminal window with a keyboard and monitor plugged in to the pi.
# install operating system on sdcard, use it to boot the rpi
# install a real-time clock and enable it
# configure the rpi for remote access and headless operation
# get rid of fake clock
sudo apt-get remove --purge fake-hwclock
# ensure the correct timezone
sudo dpkg-reconfigure tzdata
Install pre-requisites for building rtl-sdr and rtl_433
sudo apt-get install cmake libusb-1.0-0-dev build-essential autoconf libtool pkg-config
Install rtl-sdr
git clone git://git.osmocom.org/rtl-sdr.git
cd rtl-sdr
mkdir build
cd build
cmake -DINSTALL_UDEV_RULES=ON ..
make
sudo make install
sudo ldconfig
Install rtl_433
git clone https://github.com/merbanan/rtl_433
cd rtl_433
mkdir build
cd build
cmake ..
make
sudo make install
Install weeWX
When you install weeWX, select Simulator
when prompted for the station type. You will change it later to SDR
when you run the weectl station reconfigure
command.
# install weeWX
wget -qO - http://weewx.com/keys.html | sudo apt-key add -
wget -qO - http://weewx.com/apt/weewx.list | sudo tee /etc/apt/sources.list.d/weewx.list
sudo apt-get update
sudo apt-get install weewx
# shut down weeWX
sudo systemctl stop weewx
# install weewx-sdr extension and enable the driver
git clone https://github.com/matthewwall/weewx-sdr.git
sudo weectl extension install weewx-sdr
sudo weectl station reconfigure
Configure
Now that all the pieces are installed, it is time to tell weeWX which data to collect. This is done by starting at the lowest level, rtl_433
, then working up to weewxd
. You will first run rtl_433
to verify that it works and to see what signals it picks up. You might be surprised by how many devices in your house (or your neighbors' house!) are sending radio signals that you can detect. Then the next step is to identify which of those signals you care about. Finally, you will create a sensor_map
in your weeWX configuration that maps names and values from rtl_433
into the database fields that are used in weeWX
.
# see what devices are broadcasting data - let this run for awhile
sudo rtl_433
# or run it like this to see the output in JSON format
sudo rtl_433 -M utc -F json
Deploy the sensors one at a time. Put the batteries into the first sensor, then watch it show up in the rtl_433
output. Put a piece of tape on the sensor then label that sensor with the hardware identifier - the hardware identifier is typically called id
in the output. Then put batteries in the next sensor, and watch it show up. You will end up with a pile of sensors, each with its hardware identifier clearly marked. Then you can easily keep track of sensors when you map the hardware identifiers to the database fields and the actual sensor locations.
Next you should run the weewx-sdr
driver directly. This will verify that the driver can capture the output from rtl_433
, and it will show you the fully-qualified names for each observation. You will need these to tell weeWX how to capture the data. Notice the --cmd
option. If you had to specify other options to rtl_433
, be sure to add those to the --cmd
option when you invoke sdr.py
.
# see how the sensor data from rtl_433 are mapped to fully-qualified names
sudo PYTHONPATH=/usr/share/weewx python /usr/share/weewx/user/sdr.py --cmd="rtl_433 -M utc -F json"
# in particular, look at the 'out' and 'parsed' lines like this:
out: ['{"time" : "2019-01-16 11:45:33", "model" : "Acurite tower sensor", "id" : 2453, "sensor_id" : 2453, "channel" : "A", "temperature_C" : 16.700, "humidity" : 31, "battery_low" : 0}\n']
parsed: {'temperature.0995.AcuriteTowerPacket': 16.7, 'dateTime': 1547639133, 'humidity.0995.AcuriteTowerPacket': 31.0, 'status.0995.AcuriteTowerPacket': None, 'battery.0995.AcuriteTowerPacket': 0, 'channel.0995.AcuriteTowerPacket': u'A', 'usUnits': 16}
Now you can tell weeWX the full names of the observations from each sensor. In this example, the full names are temperature.0995.AcuriteTowerPacket
or humidity.0995.AcuriteTowerPacket
. You must tell weeWX how to map those names to the database fields it uses to store the data. This is done in the sensor_map
section of the SDR
section in the weeWX configuration file.
Here is an example showing 4 sensors that I installed. The sensor identifiers are -102
, 0995
, 16B9
, and 0ED5
, but of course yours will have other values. The database field names are inTemp
, outTemp
, outHumidity
, etc.
# using these names, create the sensor_map in /etc/weewx/weewx.conf
[SDR]
...
[sensor_map](/weewx/weewx/wiki/sensor_map)
inTemp = temperature.-102.Acurite606TXPacket # mud room
inTempBatteryStatus = battery.-102.Acurite606TXPacket
outTemp = temperature.0995.AcuriteTowerPacket # back porch
outHumidity = humidity.0995.AcuriteTowerPacket
outHumidity = battery.0995.AcuriteTowerPacket
extraTemp1 = temperature.16B9.AcuriteTowerPacket # bathroom
extraHumidity1 = humidity.16B9.AcuriteTowerPacket
batteryStatus1 = battery.16B9.AcuriteTowerPacket
extraTemp2 = temperature.0ED5.AcuriteTowerPacket # kitchen
extraHumidity2 = humidity.0ED5.AcuriteTowerPacket
batteryStatus2 = battery.0ED5.AcuriteTowerPacket
You can see the full list of database field names in the archive types section of the weeWX customization guide.
Start weewx
First run weeWX directly to ensure that the data collection is working properly, and that data are getting into the database and reports. A minute or two after you start it, you should see LOOP
packets that contain the data from the sensors, associated with database field names as defined in your sensor_map
. Every 5 minutes you should see an archive RECORD
reported.
# run weewx directly to verify the data collection (ctrl-c to stop)
weewxd /etc/weewx/weewx.conf
After you have verified it is working properly, kill weewxd
. Now you can run it as a daemon so that it will continue to run, even after you log out of the raspberry pi.
# run weewx as a daemon and forget about it!
sudo systemctl start weewx
Viewing the data and customizing the reports
WeeWX saves the data to a sqlite database at /var/lib/weewx.sdb
on the raspberry pi. You can browse the data directly by invoking the sqlite command-line tool on the raspberry pi:
sqlite3 /var/lib/weewx.sdb
In its default configuration, weeWX will put data into a report located at /var/www/html
on the raspberry pi. If you have a keyboard and monitor plugged into the pi, you can view the report directly in any web browser on the pi.
You can view the report remotely by installing a web server on the pi, such as nginx
, lighttpd
, or apache
. I highly recommend using nginx
or lighttpd
on the pi, since they use significantly less memory than apache
.
sudo apt-get install nginx
Then you can view the reports using a web browser on any computer/tablet/phone that can see the pi:
http://<name-or-addr-of-pi>/weewx
To customize the report or add other reports, see the weeWX customization guide:
http://weewx.com/docs/customizing.htm
Troubleshooting
kernel module already loaded
When you run rtl_433
, you might get a warning about a kernel module already being loaded. If so, you can try explicitly unloading the kernel module, then blacklisting it so that it is not accidentally loaded.
# ensure that the rtl kernel module is not running inappropriately
sudo modprobe -r dvb_usb_rtl28xxu
echo 'blacklist dvb_usb_rtl28xxu' | sudo tee -a /etc/modprobe.d/blacklist.conf
kernel module is in use
If you get an error that dvb_usb_rtl28xxu
is in use, unplug your SDR device, then try again.
rtl-sdr build fails to find libusb
When compiling rtl-sdr
, you might encounter problems linking to libusb. If so, try running pkg-config
as explained here: