Community. Driven. Weather. Data. | Always Ad-Free | Developer FriendlyChecking statusDiscord
Support us
Sign in
Weather stations

One-command SDR to APRS installer

Turn a Raspberry Pi and a $30 RTL-SDR dongle into an APRS-IS weather beacon for the 433 MHz station already in your yard. One command, a few questions, and your callsign is on aprs.fi.


Most cheap consumer weather stations, AcuRite, La Crosse, Fine Offset and their many rebadges, talk to their indoor console over 433 MHz. An RTL-SDR dongle can hear those same transmissions, which means the console is optional and the station can go straight onto APRS-IS without a vendor gateway.

The installer sets that whole chain up on a Raspberry Pi with one command:

curl -fsSL https://wxalerts.org/install-sdr-aprs.sh | sudo bash

It is interactive. It will ask you which station to publish, your callsign, and where the sensors are, and then it starts a beacon that runs on its own from then on.

What you need

A Raspberry Pi Any model that runs Raspberry Pi OS; a Zero 2 W is enough. Debian and Ubuntu also work. It needs to be on the internet.
An RTL-SDR dongle RTL2832U based: RTL-SDR Blog V3 or V4, Nooelec NESDR, or a generic “DVB-T” stick.
A 433 MHz station Anything rtl_433 decodes. The installer has the best support for the AcuRite 5-in-1.
A callsign Your own, as a licensed ham.
Your station’s coordinates In decimal degrees, and ideally the altitude too.
About 20 minutes Most of it is the system update at the start.

Have the station running and within range when you start, because part of the install is a live scan of the airwaves.

Running it

Run the one-line command above in a terminal on the Pi, over SSH or with a keyboard and screen. If you would rather read the script before running it, which is a good habit with anything piped into sudo bash, download it first:

curl -fsSL https://wxalerts.org/install-sdr-aprs.sh -o /tmp/wxalerts-install.sh
less /tmp/wxalerts-install.sh
sudo bash /tmp/wxalerts-install.sh

The installer needs a terminal to ask its questions. Over SSH that is the default. If you are driving it from another script, use ssh -t.

What it asks you, in order

  1. License confirmation. Type YES. Anything else stops the install.

  2. Plug in the dongle, if it is not already. The installer waits until the dongle shows up on USB.

  3. Which station to publish. After a 60-second scan it lists every sensor it decoded, strongest signal first, with the latest readings from each:

      [1] Acurite-5n1  id=2002  signal -6.2 dB  packets=12
          60.2°F (15.7°C), 91% RH, wind 2.2 mph from 45°, rain counter 1.04 in
      [2] Acurite-5n1  id=1862  signal -14.0 dB  packets=9
          60.4°F (15.8°C), 99% RH, wind 3.2 mph from 202°, rain counter 96.42 in
      [0] Enter model/id manually

    Type the number in brackets, not the ID. See Picking your station for how to tell which one is yours. If the scan found nothing, you can type the rtl_433 model name and ID by hand.

  4. Callsign, for example W1AW or W1AW-13. If you leave off the SSID it asks for one, and suggests 13, the usual SSID for a weather station. The installer works out your APRS-IS passcode from the callsign and shows it to you.

  5. Location. Latitude and longitude in decimal degrees, north and east positive. You can paste a 33.4484, -112.0740 pair straight from Google Maps. Then the altitude in feet above sea level, which can be left at 0. Use the position of the sensors, not your house’s street address and not the Pi’s.

  6. Comment, the text shown after the weather on aprs.fi. It defaults to WXAlerts RTL-SDR and is trimmed to 43 characters.

After the last answer it starts the beacon and prints a summary with your callsign, passcode, station and the commands to watch it.

Picking your station

433 MHz carries a long way. In a neighborhood the scan will often find other people’s weather stations, and sometimes car tire pressure sensors and wireless thermometers too. Two stations of the same model, like the two AcuRite 5-in-1s above, are completely separate units: different IDs, different readings, and only one of them is yours. Picking the wrong one puts your callsign on your neighbor’s weather.

Ways to tell them apart, most reliable first:

  • Match the readings to your own console. Temperature, humidity and wind direction are the easiest to compare. In the example above the two stations agree on temperature within a few tenths but disagree on humidity by 8% and on wind direction by 150°, so the console settles it at a glance.
  • Make your station do something. Spin the anemometer by hand, or turn the wind vane to point a known way, and re-run the scan. The station whose wind changed is yours.
  • Signal strength. The list is sorted strongest first, and the nearest station is usually the strongest. It is a hint, not proof: a station on your roof can read weaker than one on a neighbor’s pole with a clear line of sight.

The packet count is not a good guide. It depends on distance, antenna and where the 60-second window happened to fall in each station’s transmit cycle, and says little about whose station it is.

What it does, step by step

Updates the system and installs rtl_433. It runs a full apt-get dist-upgrade, then installs rtl-sdr and rtl-433 from the distribution. If the distribution has no rtl_433 package, it builds rtl_433 from source.

Keeps the TV driver off the dongle. Linux treats these dongles as TV tuners and loads a driver that grabs the device, which blocks rtl_433. The installer blacklists that driver in /etc/modprobe.d/wxalerts-rtl-sdr-blacklist.conf and unloads it.

Installs WeeWX and the weewx-sdr driver. WeeWX comes from its own apt repository, and the installer writes an [SDR] sensor map for your station into /etc/weewx/weewx.conf, keeping a copy of the original as weewx.conf.bak-wxalerts. WeeWX is then left stopped; see WeeWX or the beacon, not both.

Frees the dongle. Before scanning, it stops anything that could be holding the SDR: WeeWX, an earlier beacon, stray rtl_433 or rtl_tcp processes, and the TV driver. It then checks that the dongle actually opens. If something still has it, the installer names the process and stops rather than carrying on with a dead radio.

Scans, asks, and writes the config. The scan output is kept in /opt/wxalerts/scan.jsonl, and your answers go to /opt/wxalerts/station.conf, which is readable by root only.

Starts the beacon. It installs /opt/wxalerts/aprs_beacon.py as the systemd service wxalerts-aprs, enabled so it starts at every boot.

How the beacon works

The beacon runs its own rtl_433 in the background and reads every decoded packet. It keeps only packets whose model and ID match exactly the ones you picked, and remembers the latest temperature, humidity, wind speed, gust, wind direction and rain counter from them.

Every five minutes it logs in to rotate.aprs2.net on port 14580 and sends one weather packet. A typical one looks like this:

W1AW-13>APZWXA,TCPIP*:@241430z3326.90N/11204.44W_225/004g009t072r000p012h45WXAlerts RTL-SDR

Read left to right: your callsign, the time in UTC, the position, then wind direction 225°, sustained 4 mph, gusting 9 mph, 72 °F, no rain in the last hour, 0.12 in since midnight, and 45% humidity. The APRS weather packet explains every field.

A few rules keep what it sends honest:

  • Unknown is sent as unknown. Any field the station does not report goes out as dots (g...), which is how APRS says “no data”. These stations have no outdoor barometer, so the packet never carries pressure.
  • Stale readings expire. A value that has not been updated for 15 minutes is sent as unknown. If the temperature itself goes stale, for example because the sensor’s batteries died, the beacon stops sending until it hears the sensor again.
  • Rain totals need history. The sensor only reports a running rain counter, so the beacon works out the totals itself. Rain in the last hour is sent once the beacon has an hour of readings. Rain since midnight is sent only after the beacon has run through a midnight, so the first day’s total is never a partial guess. A counter that jumps back to zero, which is what happens when the batteries are changed, is handled without losing the running total.
  • A failed login is an error, not a silent drop. If APRS-IS does not accept the passcode, the beacon logs it and retries 30 seconds later, instead of sending packets the server would throw away.
  • If the radio stops, the beacon restarts. If rtl_433 dies, for example because the dongle was unplugged, the beacon exits and systemd starts it again 10 seconds later.

Packets carry the tocall APZWXA, the prefix the APRS tocall registry sets aside for experimental software.

After it is running

Watch the beacon work:

journalctl -u wxalerts-aprs -f

You should see update lines as the station transmits, roughly every half minute for most sensors, and a TX line with the full packet every five minutes. A few minutes after the first TX, look your callsign up on aprs.fi. Then register the station with CWOP, as described in Getting an ID. Registering is what gets a ham callsign’s data quality-controlled by MADIS and passed on to the NWS.

Other commands you will want:

systemctl status wxalerts-aprs      # is it running?
sudo systemctl restart wxalerts-aprs    # after editing station.conf
sudo systemctl stop wxalerts-aprs       # stop beaconing

Changing things later

Re-run the installer to pick a different sensor, callsign or location. It is safe to run again: it rewrites station.conf, keeps the original WeeWX backup, and restarts the beacon. It also runs the full system update again, so allow the time.

Or edit /opt/wxalerts/station.conf directly and restart the service. The file is plain KEY=value lines:

Key What it is
CALL Callsign and SSID the packets are sent as
PASS APRS-IS passcode for the callsign
LAT, LON Position in decimal degrees
ALT Altitude in feet
COMMENT Text after the weather data
FREQ Frequency rtl_433 listens on
MODEL, SENSOR_ID The station to publish, exactly as rtl_433 names it
SENSOR_HEX The same ID in the form weewx-sdr uses

Three optional keys are not written by the installer but are honored if you add them: BEACON_SEC, the seconds between packets (300 minimum, which is also the default), and APRS_HOST and APRS_PORT to use a particular APRS-IS server.

Settings you can change

Two environment variables change how the installer runs. Because of sudo, they go after it:

curl -fsSL https://wxalerts.org/install-sdr-aprs.sh | sudo WXALERTS_FREQ=915M WXALERTS_SCAN_SECONDS=120 bash
Variable Default What it does
WXALERTS_FREQ 433.92M Frequency to scan and listen on. Use 915M for 915 MHz AcuRite gear, 868M in Europe.
WXALERTS_SCAN_SECONDS 60 How long the station scan lasts. Raise it if your station transmits rarely.

WeeWX or the beacon, not both

One RTL-SDR can be opened by one program at a time. The installer configures WeeWX for your station but runs the beacon, so WeeWX stays stopped. To run WeeWX instead, for its web pages, archive and its own uploads:

sudo systemctl disable --now wxalerts-aprs
sudo systemctl enable --now weewx

and the reverse to switch back. Running both needs a second dongle, and editing the cmd line in the [SDR] section of weewx.conf so WeeWX uses it.

Troubleshooting

“usb_claim_interface error -6” or “The SDR is in use by something else”. Another program or the kernel TV driver has the dongle. The installer names the process if it can find it. Stop it, or simply reboot: the blacklist is already in place, so after a reboot the TV driver stays away. Then run the installer again.

“No packets” from the scan. Check that the station is powered and transmitting, and that you have the right frequency (433 or 915 MHz; the label on the sensor usually says). Move the dongle away from the Pi and any USB 3 ports, which put out enough noise to drown a weak sensor, and give it a proper antenna rather than the stub in the box. Try a longer scan with WXALERTS_SCAN_SECONDS=180. The raw rtl_433 errors are in /opt/wxalerts/scan.err.

The beacon is running but nothing appears on aprs.fi. Look in the journal first. APRS-IS did not verify the login means the callsign and passcode do not match; re-run the installer or fix PASS. No TX lines at all means the beacon has not heard your sensor; check for update lines and see the battery-change tip above. APRS send failed with a network error means the Pi cannot reach rotate.aprs2.net on port 14580.

Wind or rain is always dots. Your sensor does not report that value, or reports it in a unit the beacon does not recognize. Run rtl_433 by hand and look at the field names. Rain in the last hour and since midnight are dots at first by design; see How the beacon works.

“No terminal to prompt on”. The installer was started without an interactive terminal, for example from cron or ssh host 'command'. Use ssh -t, or run it from a normal login.

SyntaxWarning: invalid escape sequence lines during the install. These come from the weewx-sdr driver’s own code on newer Python versions. They are harmless and can be ignored.

Uninstalling

sudo systemctl disable --now wxalerts-aprs
sudo rm /etc/systemd/system/wxalerts-aprs.service
sudo systemctl daemon-reload
sudo rm -rf /opt/wxalerts
sudo rm /etc/modprobe.d/wxalerts-rtl-sdr-blacklist.conf

That removes everything the installer created. WeeWX, rtl_433 and the other packages stay installed; remove them with apt if you do not want them, and delete /etc/apt/sources.list.d/weewx.list to drop the WeeWX repository.

Where to go next

May we use Microsoft Clarity to see how pages are used (clicks, scrolling and replays of a visit, with anything you type hidden), plus a random ID linking that to crash reports? Only to find bugs and confusing screens. Never advertising, never sold.