Intro: Spying Remote Control to Open a Garage With an App and SDR
Who has never dreamed of going home just with a phone app, or being able to listen to and recopy data trams? I am happy to be able to share with you what I realized, and how I proceeded. I started this project after the second time I forgot my keys...
Of course, the encoding, the type of modulation, the frequency of the carrier, the bluetooth connection information, and the datas that I'm going to show in example are not the originals, I prefer not to have visitors ;-).
This application applies to any object capable of receiving digital information by electromagnetic waves (garage door, car, some shutters ...). The entire system consists of an object connected by bluetooth to a phone, this object being able to send the same frames as the remote associated with what we want to hack. I placed this object in my garage, and I can connect to it from the outside.
Step 1: Equipement
Languages used: C++, MATLAB, Typescript, C, html.
Basic knowledge in digital electronics and telecommunications/signal processing.
Cost: less than $35.
- NooELEC NESDR: for capturing the data. This very cheap module performs a digital demodulation, hence its high portability. This model is compatible with MATLAB. ($18.95)
- Wemos Lolin32 lite: this esp32 is a cheap microcontroller, equipped with Wifi and Bluetooth. We will not use Wifi in this application, but this is largely conceivable. ($4.74)
- CDSENET cc1101: this radio transmitter gives us an extreme flexibility, from the chosen carrier frequency to the type of modulation. ($2.63)
- Wires, headers, welding equipement, 3.7V lipo battery for autonomy ,possibly oscilloscope, and/or logic analyser for debug, and incidentally, a smartphone...
- MATLAB/Simulink: for capturing the data. Other free alternative softwares can be used, like Audacity for data visualization. (license)
- esp-idf toolchain: this will be used for programming the esp32. The Arduino ide can also be used, but it does not allow as much freedom as what we will use. (free)
- TI SmartRF Studio: this will help us configuring the cc1101 registers, according to our specifications. (free)
- Ionic: for building the app. Your can make the choice of building native apps, but Ionic allows us to run our app on both Android and IOS devices, with an only code. The performance is not sought in our case. (free)
- Your favorite ide...
Step 2: Spying the Remote Control
We will start by observing the data that the commands of the remote control produce. To do this, we will use a rtl-sdr dongle and antenna:
By following this link, you will find the MATLAB package, as well as a free book explaining all the pricipes with their explanation. To summarize what concerns us, the transit data is in the form of an IQ signal: an "I" in-phase data, combined with a "Q" quadrature data. This method facilitates telecommunications. We will only be interested in receiving the signal in phase. We will now gather the physical and digital information on the remote control.
If you can find some documentation on it, it will be easier. I did not find any. To be able to temporally observe the signal, we must first know what is the frequency carrier of the emitted signal. We will use the example provided with the package documentation "Spectral Analysis with RTL-SDR Radio", to know exactly at which frequency we observe a peak power when we send a command. In my case it is 868.22 MHz. The "standard" frequencies for this kind of applications are around 868 MHz.
With these indications, we will be able to write a MATLAB code to recover the data. This one is attached in photo and commented.
The result allows us to find the type of modulation: by retrieving the raw information, displaying the result just after having recovered the real part of the signal, we can deduce that it is an ASK / OOK modulation. Indeed, we observe that the frequency is invariant, however, the signal has only two amplitudes: a null, and a fixed. The rest of the code allows us to recover the envelope of the received signal, made easier to read to know the trame. Once displayed, we can determine the baseband modulation: this is a Manchester coding (see attached photo). We can also deduce the baud rate (symbols per second). All this information being gathered, we can know the data frame. In my case, the bytes found are: 249, 39, 75, 178, 45, 200, and repeted multiple times, to ensure that the command is well received. Fortunately, the code is not rolling, the data frame is always the same.
Step 3: Send the Same Data Frames
The Texas Instruments cc1101 is so flexible that you will still achieve your goal, even if the settings you found in the previous step are completely different from mine. Indeed, you will see in the documentation, page 2 (http://www.ti.com/lit/ds/symlink/cc1101.pdf) that it allows to perform NRZ, Manchester, FSK, ASK / OOK modulation, to reach the frequencies around 433 MHz or 868 MHz, and many other things. I advise you to read the documentation to familiarize yourself with this module.
On this link you will find as an example the work of Loboris concerning the construction of functions using this module:
We are going to write our code for our esp32 with the esp-idf toolchain (see links of the first step). You can add the files of the link in the components subdirectory of your project. To properly configure our cc1101, we will need to fix its registers. Texas Instruments provides us with software that gives us the value of the registers according to our configuration: SmartRF Studio.
Concerning me, I indicate to the software that I wish a Manchester coding, that my carrier frequency is 868.22 MHz, that my type of modulation is ASK / OOK ... I let you enter your parameters. In the case where your baseband encoding is not available, you can consider NRZ encoding, by properly increasing the baud rate, and adapting the datas.
Once you have defined your values, you have several choices concerning the use of the module: you can use the functions that I have linked to you, or what I did, only take inspiration from this code, in order to configure everything in a more brutal way (see attached photos), and only use what we need.
As the cc1101 chip communicates by SPI, you will find in the link of the example code the "spi_master_lobo.h" header file, containing more easier functions for using the SPI than if you had to use it with only the toolchain. I join you in photo the scheme of the CC1101 communication in SPI, photo taken from the page 30 of the CC1101 datasheet. The four wires presented are: CS (Chip Select, or SS: Slave Select, or here CSn), CLK (or SCLK, the Clock, provided by the master), MISO (or SO, Master In Slave Out), and MOSI (or SI, Master Out Slave In). In our case, the master is the ESP32, and the slave is the CC1101. Communications start when the CS pin is low, in general.
Don't forget to enable in the compiler options of the menuconfig the C++ exceptions for compiling.
Step 4: Connect to the System
If your code works, you have done the essential. In this part, we will focus on how to create a phone app connected to the system. The most interesting solution is to connect by bluetooth, because it allows the use of a low-power protocol: Bluetooth Low Energy (BLE). The hierarchy profile is shown in the drawing attached: we will read and write the command in a Characteristic of a Service. And of course, our esp32 and our smartphone are equipped with bluetooth.
This step is divided into two parts: the esp32 part, and the app part. The photo attached show and explain the main parts of the codes.
You can generate your UUIDs by following this link:
These are the identifiers that will provide access to the services and features of our BLE profile.
About the esp32 BLE code, Kolban did a great work making all these high level C++ functions compatible:
You can put these files in the components subdirectory. Otherwise, you will need more time to understand how to use BLE with the esp-idf toolchain.
In summary of what you will see in the code, we create a Server, a Service, and a Characteristic, with the associated UUIDs, and we add a redefined callback class, with an associated method on write: when we receive the "O" character, we send a write command to the cc1101.
Of course, don't forget to enable Bluetooth in the Component config of the Menuconfig.
About the app part, we will use the Framework Ionic. You can find more infos about it in the link presented in the first step, and for more details about how to use BLE with Ionic:
And examples, written by don:
You can edit for instance the example "Connect".
We scan devices on a first page, and reach a second page if we select our device. We then access an interface where you can add a button with the method presented in photo: it sends our command "O" with the appropriate UUIDs. You can also add in the constructor of the first page the method "enable", asking to activate the bluetooth at the start of the application.
I highly recommend you to explore the Ionic website, and to discover all the Components (buttons, alerts, checkboxs...) to enhance your application:
Step 5: Optimize Power Consumption
We started to work on low consumption, so let's work through.
The esp-idf toolchain allows us to use a configuration GUI, the menuconfig: many parameters can lower the esp32 consumption. First of all, as we don't need Wifi, we can disable it in the Component config. In the same folder, in FreeRTOS, you can select "Run FreeRTOS only on first core. Then, in ESP-specific, you can lower the CPU frequency to 80 MHz. All the functionnalities still work at this clock speed. Finally, you can check "Enable Ultra Low Power (ULP) Coprocessor. This configuration makes the current consumption go from about a hundred of mA to about thirty mA. This is still too much...
ESP32 can handle deep sleep. Only the low-energy core is on and waits for a wake up.
See this link below for more details:
Unfortunatly, in the last available version of the esp-idf toolchain (3.0), the only wakes up available are by timers and by GPIOs disruptions. Luckily, Espressif promise us BLE wake up in the next version (3.1).
You can also put the CC1101 in a sleep mode, by sending in SPI the proper command to power down the device (see cc1101 datasheet, the SPWD command, page 51). For putting the device in sleep mode or for waking it up, you may put low then high the Chip Select pin of the SPI pins (more infos in the datasheet).
These last configurations should be able to make the consumption of the system pass below the milli-ampere...
Finally, to make the system last as long as possible without recharging, or even reach a month of autonomy, choose the 3.7V battery with the most milli-amperes per hour. By measuring the power consumption of your system, with the display of a generator or a ammeter connected in series before your + pole of your system, you can estimate the time that your system will last!