Reverse Engineering an RF Remote - Replace with cheap IoT computer
I purchased this Harbor Breeze Kingsbury fan a while back. While it’s a nice looking fan, and quite large, I was disappointed to find that it is controlled with a remote. Main reason being, it is not possible to control the fan without a remote. And the problem with a remote is that it inevitably gets lost and/or broken. So, I decided to undertake a project to replace the remote.
I break down this project into a couple of challenges:
sudo ln -s /Applications/Gqrx.app/Contents/MacOS/rtl_fm /usr/local/bin/rtl_fm
brew install sox
First, we want to figure out what frequency the device is broadcasting on. In this case, I disabled the remote and found the transmitter and was able to identify it as 315 Mhz - the transmitter module actually had 315 printed on it.
Let’s fire up the Software Defined Radio (Gqrx) and have a look around 315 Mhz frequency, and start pressing buttons on the remote, to see what we can see.
Pressing the buttons and watching for patterns in the waterfall view will help you dial in the exact frequency that the remote is broadcasting on. Also if your squelch is set correctly, you can even hear the signal as you push the button. We have our frequency, so now let’s capture all of the buttons into a wav file so we can analyze.
Rtl_fm will capture the AM broadcast at the given frequency (315.03 Mhz) at a high sample rate, so we can look at exact timings of the signal to decode them. Sox will take the output from rtl_fm and put it into a wav format to analyze in a sound editor.
rtl_fm -M am -f 315030000 -s 2000000 - | sox -t raw -r 2000000 -e signed-integer -b 16 -c 1 -V1 - fancontrol.wav
You will need to quit entirely from Gqrx so that the USB device is released. So, run the above command, and give it a moment to identify your RTL SDR card. Once it is capturing, press each button on the remote in a specified order (write it down), giving a few seconds between button presses. When you have run through all of the buttons, press Ctrl-C to stop the program.
Now find your fancontrol.wav file and open it in Audacity.
Above is Audacity with all of the button presses in a single view. Let’s zoom into the first set to get a better view.
Above -- So it appears that there are 6 bursts in a transmission. Are they 6 repeats of a single code, or are they all different? We’ll have to decode a few of them to find out. Let’s zoom in on the first message in the set.
Above -- There are 16 On/Off pairs that look the same, then a few that look different. Let’s see if we can find any regular intervals or timing patterns. Zooming in again…
Above -- At this resolution we can see some patterns emerge.
There are 4 distinct timings in play here, and by a lot of looking around and sampling, we can determine there’s not much more going on but patterns of Short ON, Short OFF, Long ON, and Long OFF, comprising the basic alphabet of the radio communication signal. Using Audacity, selecting an interval and subtracting end position from start position of that selection, we can determine the duration of each of the signals:
Further analysis also revealed a few other interesting facts:
Now that we know the timings, we just need to figure out the payloads so that we can reproduce in our code.
To document this, I isolated the payload in each Transmission, and documented the symbols used. You will see all of this in the code shortly.
I’m not going to duplicate information that’s easily available, so get PlatformIO working with your NodeMCU. For my system I had to search for and install CH304G drivers. Once they are installed you should see /dev/cu.wchusbserial1420 in your file system, when the NodeMCU is plugged in the USB port.
My platformio.ini settings are the following, so I can use Arduino code and libraries on NodeMCU:
[env:nodemcuv2]
platform = espressif
framework = arduino
board = nodemcuv2
Connect the NodeMCU to the 315 Mhz transmitter according to this diagram.
Please note you will want to use an antenna - it’s not necessary to get an actual gadget as seen in the wiring diagram; even a little length of wire will work fine. See below.
The code itself is pretty simple. The device fires up and joins your wireless network. It waits patently until someone goes to http://fancontrol.local -- if you are on windows you will want to install Bonjour for Windows. Otherwise on OSX and Linux you will be able to address the device in this way already.
When you bring up this site, you will see something like this:
(This is the original remote for comparison)
The web interface is created with jQuery Mobile, and is hosted on the NodeMCU in SPIFFS image.
From the web based UI you can operate the fan, as long as the NodeMCU is in range - for me 15 feet is no issue. You can also bookmark the site so it appears as an app on your IOS device.
Code can all be found at my Bitbucket Repository.
Using these tools and techniques, it should be possible to reverse engineer many 315 Mhz and 433 Mhz remote controls.
Controlling these with cheap computers with REST and Web interfaces allows you to bring these things into Internet of Things realm, where they can be remotely controlled, monitored, and potentially exploited -- well, that’s another topic.
Thanks to Samy Kamkar for some ideas on the approach.