I have a Mebus Weather station from a discounter in my kitchen and an wireless sensor outside the kitchen window. It operates at 433.92MHz and it's blips and bits are not yet analyzed (at least by me). So lets try to read it.
I will use my crappy rtl2832 DVB Dongle (Rafael Micro R820T) for that. I'd buyed it some time ago for 1€. I'ts a little bit whiny about everything. Touch it – määää. Use it without an Powered HUB wäääää. But even that crappy thing is useful ;-)
I have some clue what to expect, so I don't start at zero. I assume the data is modulated as OOK. (On Off Keying) and I have an progam rtl_443 which can help me decode it.
I have:
- Linux laptop with USB 2.0 Ports
- Powered USB 2.0 Hub
- rtl2832 Dongle connected via powered USB hub up and running
- rtl-sdr up und running
- rtl_433 @merbanan https://github.com/merbanan/rtl_433.git compiled
- kalibrate-rtl https://github.com/asdil12/kalibrate-rtl.git compiled
Let's use GSM 900 Base stations to get the frequency offset. First get some used GSM-Channels:
kal -s GSM900
I'll get:
GSM-900:
chan: 12 (937.4MHz - 32.716kHz) power: 30360.56
chan: 45 (944.0MHz - 32.768kHz) power: 26204.70
chan: 54 (945.8MHz - 32.858kHz) power: 163754.18
chan: 55 (946.0MHz - 32.372kHz) power: 73929.50
chan: 64 (947.8MHz - 32.557kHz) power: 32899.73
chan: 80 (951.0MHz - 11.769kHz) power: 27637.33
chan: 82 (951.4MHz - 32.652kHz) power: 30945.31
chan: 86 (952.2MHz - 33.397kHz) power: 27386.02
So channel 54 is the strongest one, let's use it as calibration source.
kal -c 54
Exact sample rate is: 270833.002142 Hz
kal: Calculating clock frequency offset.
Using GSM-900 channel 54 (945.8MHz)
average [min, max] (range, stddev)
- 33.053kHz [-33070, -33034] (35, 8.445596)
overruns: 0
not found: 0
average absolute error: 34.947 ppm
The 34.947 (35) is my current frequency offset (parts per million).
We use rtl_433 to log some data we tell rtl_433 the frequency offset we measured above with the parameter -p35.
rtl_433 -a -p35 -t 2>&1 | tee -a 433.log
I'll get lots of signals over the time. Some of them are crap but let's look for my sensor.
After some Seconds:
*** signal_start = 7039944, signal_end = 7287168
signal_len = 247224, pulses = 445
Iteration 1. t: 184 min: 124 (444) max: 245 (1) delta 3969
Iteration 2. t: 184 min: 124 (444) max: 245 (1) delta 0
Distance coding: Pulse length 184
Short distance: 241, long distance: 485, packet distance: 973
p_limit: 184
[00] {0} 00 : 00000000
[01] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[02] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[03] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[04] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[05] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[06] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[07] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[08] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[09] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[10] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[11] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
[12] {36} 63 00 f5 f3 d0 : 01100011 00000000 11110101 11110011 11010000
OK, wonderful, the display reads 24.5°C 61%. Now dive into the values. Let's be very naive first. Humidity 61%: 61 = b111101. Just after some seconds this pattern is identifieable at position 30.
01100011 00000000 11110101 11110 011 1101
Since this is humidity values from 0-99 are likely to appear. So we need 7 Bits and I assume that 7 Bits are used to encode that data.
Oh my god, that was fast. Lets proof that later.
We are naive, aren't we? So lets look up the other values. Looking backwards we find some more interesting patterns. There is the bit pattern 11110101 which reads 245 which is 24.5 * 10 HoooHooo. Could this be true?
So we have a hyptothesis by one sample.
01100011 00000000 11110101 11110 011 1101
Let's try to proof it.
We apply a temperature and humidity change to the sensor by just putting it outside. By doing so we also be blind since we don't see the display (assume we don't have the base station).
01100011 00000000 111100 01 1111 00 11 1111
241 and 63 Let's look at the display and we find 24.1°C and 63% which is what we expected. Whoot.
The missing pulses could be a preamble and possibly other data like: "low battery indicator", "°C/°F" bit, and "channel indicator".
As it turns out the setting "°C/°F" at the sensor only affects the display of the data at the sensor side. The over the air data seems to be identical, the transmitted data is always °C. Who needs °F anyway? The first 8 Bit are different after a power cycle so it looks like a dynamic generated ID.
Our dumps above are all done with channel setting 1.
Now repeat this with channel setting 2.
01100011 00 01 0000 11111101 11110011 1101
And channel 3.
01100011 00 10 0001 00000010 11110011 1101
Negative values:
-0.8°C:
01100010 0000 1111 11110111 11110100 1011
As it turns out this was quite easy. We have the important part of our Protocol:
- 3 Bit Pramble 011
- 5 Bit Address
- 1 Bit Low battery indicator 0 = LOW, 1 = OK
- 1 Bit unknown (always 0?)
- 2 Bit Channel (00,01,10)
- 12 Bit Temperature Signed in °C * 10
- 4 Bit unknown (always 1?)
- 8 Bit Humidity
No CRC but 12 times repetition of data.
Code for reading this sensor data is here: https://github.com/toke/rtl_433/blob/master/src/rtl_433.c#L203 https://github.com/toke/rtl_433
The funny part is from my living room I get a reading if the sensor is in the fridge but not if it is outside the kitchen window :-(