Reading weather data with software-defined radio


To find interesting signals in the ether, a spot of listening is now in order. The command I used previously for listening to the radio delivers noise on other frequencies if nothing is transmitting. Digital signals sound different from noise and thus provide input for further analysis. (Keep in mind that some jurisdictions limit the frequency ranges authorized for casual listening and might prohibit intercepting police and emergency broadcasts.)

To scan larger frequency ranges, you will need a program like Gqrx [4], which offers a practical front end, visually processing the data to create line and waterfall charts (Figure 2).

Figure 2: Representing frequency data with Gqrx.

And Now for the Weather

Because the right frequency is printed on my weather station, luckily, there was no need to search. When I set the frequency to 868MHz, I could hear pops every few seconds; I recorded and then analyzed these transmissions with the Audacity audio editor. Importing the data resulted in the test image from Figure 3.

Figure 3: Zooming in on one of the peaks in the data with Audacity revealed the chart shown in Figure 4.
Figure 4: Use a script to decode the bit pattern shown in Audacity.

In fact, the magnified view revealed a pattern. I now had to decode the signal in order to read the data (temperature and humidity). An Internet search showed that someone had already done this work [5] [6].

Christophe Jacquet's pydemod package assumes a 16-bit preamble, consisting of 1010101010101010. Following this, a sensor (see the Pydemod website [7]) sends 17200 baud signal using on-off keying. For a rising curve, as shown of Figure 5, 1 is transmitted, while a 0 is sent for a drop. To discover whether the values are rising, evaluate the ratio of the numerical values of the samples compared with the baud rate.

Figure 5: Finally, the correctly demodulated signal.

My initial tests, which evaluated data from rtl_fm using [8], remained inconclusive. Unfortunately, Christophe's records did not indicate how he called rtl_fm to obtain the raw data for the analysis. Also, the screenshot of the received data in his blog looked very different from mine.

Luckily, Christophe helped me out and expanded his script so that it also works with the data from my weather sensor. We discovered the following problems:

  • My samples were created with the wrong modulation method. The transmitter modulates the amplitude not the frequency. It is therefore necessary to run rtl_fm with the -M parameter.
  • My transmitter sends the data at 9600 instead of 17200 baud.
  • The data preamble was not 1010101010101010, but 101010101010101010101010, so it was actually 24 bits instead of 16.

I found another difference between my test system and Christophe's data: His radio reception system, a FUNcube dongle, supplied the data in big-endian format; the DVB-T stick used in my test, however, used little-endian format. Christophe had to adjust the section code that transforms the raw samples to numbers for further processing.

The temperature coding remained the same in both scenarios. Three nibbles (4 bits) encode a temperature digit in BCD (Binary Coded Decimal), where the third digit shows tenths of a degree. My temperature sensor added 40 to the temperature reading, presumably to handle degrees below zero. The next 8 bits then encode the humidity.

The first version of the script also assumed that the input was a WAV file that contained exactly the bits with the information and no noise. The script, which Christophe has now significantly revised and expanded, includes a few more new features, such as:

  • It detects a data peak when the numerical value of the sample exceeds a limit. This currently limit is set to 4000, but you can change it – depending on the transmitter output.
  • The data can also be present in raw mode, that is, without a WAV header, but at the moment, the rate must be 160,000 per second.
  • The length of the preamble is managed by a separate parameter.
  • You can adjust the baud rate for the data transfer.

The following call generates a stream of temperature measurements:

rtl_fm -M -f 868.4M -s 160k - | python --raw - --bitrate 9600 --synclen 24

Listing 3 shows the output from the command. From time to time, the measurement data is faulty. You can detect a problem because a checksum is included, and its expected value and determined value are output. If the expected and determined values deviate from each other, a measurement error has occurred. Extreme temperature jumps are actually impossible; however, two measurements can differ by more than 1 degree Celsius.

Listing 3

Output from rtl_fm


In practical tests, we found that the antenna should not be too far from the receiver. Even at a distance of 5 meters, the peak value dropped significantly in my tests. If the value is too close to the noise, the script cannot detect the beginning of the data.

The Python script outputs the minimum, maximum, and average values at runtime. However, in a practice test, it happened again and again that the deflection returned by the stick was too weak. This problem might be due to automatic signal amplification. You can either fix the value using the -g value parameter or unplug the stick and plug it back into the computer.

Easy Weather

With very little financial outlay and, ultimately, very little software, you can solve the problem of reading data from a weather station and converting into a digitally processable format. The base station of my test device also receives data with weather and pollen forecasts via the legacy pager network. You can receive and decode this pager data using the multimode-ng tool. The pager data is sent in plain text, but the string encoding is still undocumented.

A big thank you goes to Christophe Jacquet for the modifications to his script that allowed for real-time streaming.


  1. RTL-SDR project:
  2. Reddit thread with SDR hardware recommendations:
  3. GNU radio:
  4. Gqrx GUI for spectral analysis:
  5. Christophe Jacquet's blog with protocol analysis (French):
  6. The initial analysis of the protocol by Fred Bossard:
  7. Pydemod package:
  8. Code for

The Author

Konstantin Agouros works for N. Runs AG as a consultant for network security. His focus is on cellular networks. His book DNS/DHCP is published by Open Source Press.

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Pi FM Radio

    Low-cost RTL-SDR dongles can read frequencies between 24 and 1,766MHz. We built a simple FM radio with a Raspberry Pi, a USB dongle based on the RTL2832U chipset, an LCD HAT, and some Python code.

  • Charly's Column: Air Traffic Control

    When he sees vapor trails in the skies above the Lower Rhine area, sys admin Charly Kühnast doesn't just dream of faraway places. With a Linux system and a DVB-T stick, he grabs the signals from jets flying overhead and tracks their courses on a map.

  • FOSSPicks

    Graham looks at Graphite, retrogram~rtlsdr, Piano Forte, OneTrick SIMIAN, The Command Line Murders, and more!

  • Linksys Says Yes to Open Source Firmware

    Home routers will give room for custom firmware but still comply with FCC rules

  • Internet Radio Guide

    Take a tour of some favorite Internet radio sites from the experts at Linux New Media.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More