Wireless doorbell hacking
Well, attempting to hack anyway.
I bought a wireless doorbell from B&M and the doorbell works great. I have always been interested in decoding radio, so this gave me a chance to try this out. My end goal here is to be able to press the doorbell and have home assistant act on the button press. Yes, I could swap the doorbell for a known working one. Yes, I could swap the button for an aqara zigbee button. But neither of those options are as cheap or challenging as getting the door bell to work.
Prerequisites
In order to get this working I needed:
A working home assistant server with notification options set up.
An MQTT server and home assistant talking to the server.
A 433MHz Doorbell.
The process
The first stage of trying this out was to use the flipper zero to record and reproduce the doorbell pushed waveform. Why not use the doorbell directly? Well, my office is the other side of the house from the frontdoor. It's also cold and well, effort. For your own sanity's sake, once you have verified that the signal is captured, you can unplug the doorbell.
Now I had the signal (*) I can replay it multiple times and build a decoder for it. The first bit of software I use is RTL 433. This is used in combination with a SDR device, normally a RTL chipset (hence the project name) DVB-T dongle. The software supports decoding certain detections and making of custom "Flex decoders". The command I ran was:
# rtl_433 -f 433920000 -w doorbell.iq
The signal that was captured was then replayed in to rtl_433 for decoding. This was done with the command:
rtl_433 -r doorbell.iq -A
This gave me the following output.
rtl_433 version 23.11-29-g10bd337d branch master at 202401052308 inputs file rtl_tcp RTL-SDR with TLS
Reading conf from "/usr/local/etc/rtl_433/rtl_433.conf".
Use "-F log" if you want any messages, warnings, and errors in the console.
Detected OOK package 2024-01-18 19:11:47.350985
Analyzing pulses...
Total count: 625, width: 1375.06 ms (343765 S)
Pulse width distribution:
[ 0] count: 247, width: 512 us [460;568] ( 128 S)
[ 1] count: 378, width: 1532 us [1476;1584] ( 383 S)
Gap width distribution:
[ 0] count: 378, width: 508 us [456;560] ( 127 S)
[ 1] count: 228, width: 1524 us [1476;1580] ( 381 S)
[ 2] count: 18, width: 7116 us [7084;7152] (1779 S)
Pulse period distribution:
[ 0] count: 1, width: 1052 us [1052;1052] ( 263 S)
[ 1] count: 605, width: 2040 us [2004;2112] ( 510 S)
[ 2] count: 18, width: 7632 us [7608;7680] (1908 S)
Pulse timing distribution:
[ 0] count: 625, width: 508 us [456;568] ( 127 S)
[ 1] count: 606, width: 1528 us [1476;1584] ( 382 S)
[ 2] count: 18, width: 7116 us [7084;7152] (1779 S)
[ 3] count: 1, width: 15844 us [15844;15844] (3961 S)
Level estimates [high, low]: 3043, 2
RSSI: -7.3 dB SNR: 31.8 dB Noise: -39.1 dB
Frequency offsets [F1, F2]: -5247, 0 (-20.0 kHz, +0.0 kHz)
Guessing modulation: Pulse Width Modulation with multiple packets
view at https://triq.org/pdv/#AAB02A040101FC05F81BCC3DE4809090909081909090819081818190909081908190819090818190818190908255+AAB02B041101FC05F81BCC3DE490909090909081909090819081818190909081908190819090818190818190908255+AAB02A040101FC05F81BCC3DE4909090909090819090908190818181909090819081908190908181908181909355
Attempting demodulation... short_width: 512, long_width: 1532, reset_limit: 7156, sync_width: 0
Use a flex decoder with -X 'n=name,m=OOK_PWM,s=512,l=1532,r=7156,g=1584,t=408,y=0'
From the last line, I was able to try the custom flex decoder for the doorbell(*). Running it from the command line looked like this:
rtl_433 -f 433920000 -X \
'n=EnergiserDoorbell,m=OOK_PWM,s=512,l=1532,r=7156,g=1584,t=408,y=0'
And when the signal on the flipper was replayed, the output looked like this:
root@homeauto-01:/usr/local/etc/rtl_433# rtl_433 -r doorbell.iq
rtl_433 version 23.11-29-g10bd337d branch master at 202401052308 inputs file rtl_tcp RTL-SDR with TLS
Reading conf from "rtl_433.conf".
Use "-F log" if you want any messages, warnings, and errors in the console.
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 2, "num_rows" : 2, "rows" : [{"len" : 56, "data" : "7fffffffffffff"}, {"len" : 0, "data" : ""}], "codes" : ["{56}7fffffffffffff", "{0}0"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 5, "num_rows" : 5, "rows" : [{"len" : 10, "data" : "b64"}, {"len" : 33, "data" : "022e2a6c8"}, {"len" : 15, "data" : "022e"}, {"len" : 18, "data" : "15364"}, {"len" : 33, "data" : "022e2a6c8"}], "codes" : ["{10}b64", "{33}022e2a6c8", "{15}022e", "{18}15364", "{33}022e2a6c8"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 5, "num_rows" : 5, "rows" : [{"len" : 7, "data" : "02"}, {"len" : 8, "data" : "17"}, {"len" : 11, "data" : "152"}, {"len" : 3, "data" : "a"}, {"len" : 4, "data" : "9"}], "codes" : ["{7}02", "{8}17", "{11}152", "{3}a", "{4}9"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 4, "num_rows" : 4, "rows" : [{"len" : 7, "data" : "02"}, {"len" : 4, "data" : "1"}, {"len" : 3, "data" : "6"}, {"len" : 19, "data" : "8a9b2"}], "codes" : ["{7}02", "{4}1", "{3}6", "{19}8a9b2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 7, "num_rows" : 7, "rows" : [{"len" : 11, "data" : "022"}, {"len" : 2, "data" : "4"}, {"len" : 1, "data" : "8"}, {"len" : 5, "data" : "88"}, {"len" : 4, "data" : "5"}, {"len" : 4, "data" : "3"}, {"len" : 6, "data" : "64"}], "codes" : ["{11}022", "{2}4", "{1}8", "{5}88", "{4}5", "{4}3", "{6}64"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 16, "num_rows" : 16, "rows" : [{"len" : 13, "data" : "0228"}, {"len" : 13, "data" : "c548"}, {"len" : 7, "data" : "b2"}, {"len" : 15, "data" : "022e"}, {"len" : 6, "data" : "14"}, {"len" : 2, "data" : "4"}, {"len" : 3, "data" : "2"}, {"len" : 4, "data" : "b"}, {"len" : 3, "data" : "2"}, {"len" : 7, "data" : "02"}, {"len" : 6, "data" : "14"}, {"len" : 1, "data" : "8"}, {"len" : 5, "data" : "88"}, {"len" : 14, "data" : "5364"}, {"len" : 30, "data" : "022e2a6c"}, {"len" : 3, "data" : "2"}], "codes" : ["{13}0228", "{13}c548", "{7}b2", "{15}022e", "{6}14", "{2}4", "{3}2", "{4}b", "{3}2", "{7}02", "{6}14", "{1}8", "{5}88", "{14}5364", "{30}022e2a6c", "{3}2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 16, "num_rows" : 16, "rows" : [{"len" : 26, "data" : "022e2a4"}, {"len" : 4, "data" : "b"}, {"len" : 3, "data" : "2"}, {"len" : 7, "data" : "02"}, {"len" : 8, "data" : "17"}, {"len" : 8, "data" : "15"}, {"len" : 3, "data" : "2"}, {"len" : 7, "data" : "b2"}, {"len" : 7, "data" : "02"}, {"len" : 6, "data" : "14"}, {"len" : 2, "data" : "c"}, {"len" : 6, "data" : "14"}, {"len" : 5, "data" : "48"}, {"len" : 3, "data" : "a"}, {"len" : 1, "data" : "8"}, {"len" : 3, "data" : "2"}], "codes" : ["{26}022e2a4", "{4}b", "{3}2", "{7}02", "{8}17", "{8}15", "{3}2", "{7}b2", "{7}02", "{6}14", "{2}c", "{6}14", "{5}48", "{3}a", "{1}8", "{3}2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 6, "num_rows" : 6, "rows" : [{"len" : 11, "data" : "022"}, {"len" : 4, "data" : "7"}, {"len" : 11, "data" : "152"}, {"len" : 1, "data" : "8"}, {"len" : 2, "data" : "4"}, {"len" : 4, "data" : "9"}], "codes" : ["{11}022", "{4}7", "{11}152", "{1}8", "{2}4", "{4}9"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 7, "num_rows" : 7, "rows" : [{"len" : 13, "data" : "0228"}, {"len" : 1, "data" : "8"}, {"len" : 9, "data" : "8a8"}, {"len" : 4, "data" : "3"}, {"len" : 2, "data" : "4"}, {"len" : 1, "data" : "8"}, {"len" : 3, "data" : "2"}], "codes" : ["{13}0228", "{1}8", "{9}8a8", "{4}3", "{2}4", "{1}8", "{3}2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 5, "num_rows" : 5, "rows" : [{"len" : 14, "data" : "022c"}, {"len" : 5, "data" : "88"}, {"len" : 2, "data" : "4"}, {"len" : 5, "data" : "48"}, {"len" : 7, "data" : "b2"}], "codes" : ["{14}022c", "{5}88", "{2}4", "{5}48", "{7}b2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 7, "num_rows" : 7, "rows" : [{"len" : 11, "data" : "022"}, {"len" : 10, "data" : "714"}, {"len" : 5, "data" : "48"}, {"len" : 1, "data" : "8"}, {"len" : 2, "data" : "4"}, {"len" : 1, "data" : "8"}, {"len" : 3, "data" : "2"}], "codes" : ["{11}022", "{10}714", "{5}48", "{1}8", "{2}4", "{1}8", "{3}2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 7, "num_rows" : 7, "rows" : [{"len" : 14, "data" : "022c"}, {"len" : 5, "data" : "88"}, {"len" : 2, "data" : "4"}, {"len" : 2, "data" : "4"}, {"len" : 3, "data" : "2"}, {"len" : 4, "data" : "b"}, {"len" : 3, "data" : "2"}], "codes" : ["{14}022c", "{5}88", "{2}4", "{2}4", "{3}2", "{4}b", "{3}2"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:33.389363", "model" : "EnergiserDoorbell", "count" : 6, "num_rows" : 6, "rows" : [{"len" : 19, "data" : "022e2"}, {"len" : 2, "data" : "4"}, {"len" : 2, "data" : "4"}, {"len" : 3, "data" : "2"}, {"len" : 1, "data" : "8"}, {"len" : 5, "data" : "60"}], "codes" : ["{19}022e2", "{2}4", "{2}4", "{3}2", "{1}8", "{5}60"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.021, "noise" : -28.165}
{"time" : "2024-01-18 18:39:34.586744", "model" : "EnergiserDoorbell", "count" : 6, "num_rows" : 6, "rows" : [{"len" : 6, "data" : "fc"}, {"len" : 0, "data" : ""}, {"len" : 0, "data" : ""}, {"len" : 0, "data" : ""}, {"len" : 0, "data" : ""}, {"len" : 60, "data" : "fffffffffffffff"}], "codes" : ["{6}fc", "{0}0", "{0}0", "{0}0", "{0}0", "{60}fffffffffffffff"], "mod" : "ASK", "freq" : 433.899, "rssi" : -12.144, "snr" : 16.576, "noise" : -28.720}
Now completed, I added the decoder line in to rtl_433.conf like so:
decoder n=EnergiserDoorbell,m=OOK_PWM,s=512,l=1532,r=7156,g=1584,t=408,y=0
And retested to confirm it was all working. Once I had confirmed that the doorbell(*) was being detected, I moved to using rtl433 to MQTT software. This takes the rtl433 decoded events, and then sends them to your MQTT server. The software turned the detection in to MQTT events which in my case, had the topic of:
/sensors/rtl_433/EnergiserDoorbell/*
Where the star in this case is a few parameters from the dooorbell. For the detection, I chose a parameter that wasn't going to change like mod, which had a value of ASK. I then set up a home assistant event to listen to published the published event:
alias: Doorbell detection
description: ""
trigger:
- platform: mqtt
topic: sensors/rtl_433/EnergiserDoorbell/mod
payload: ASK
condition: []
action:
- service: notify.mobile_app_pixel_7a
data:
message: Doorbell
- service: script.office_batman_cycle
metadata: {}
data: {}
mode: single
This would send me a message saying "Doorbell" when the doorbell was pushed and cycle the colour of my bat symbol in my office. Tested again with the flipper zero, and it worked like a charm.
(*) Turns out, I don't actually have the signal. While the decoder works for the signal recorded by the flipper, it doesn't work with the doorbell. The chimer rings despite a replay or a doorbell push. There will definately be a part 2 to this....