RaspiTX Makes Dumb Devices Smart

Lights, fans, blinds, anything with a radio remote can be made smart

Kory Kirk
7 min readAug 6, 2023

This article builds off of my two previous articles about Raspberry Pis, RTL-SDR and Home Automation, but reading those is not necessary to follow along here.

Disclaimer

This article is intended solely for educational and research purposes. It is not intended to promote or engage in any unlawful activity or to violate any laws or regulations, including, but not limited to, those concerning the transmission of radio signals. Unauthorized transmissions, interference with licensed broadcasts, or the use of certain frequencies may be in violation of FCC rules and regulations. Please be aware of your local radio transmission laws before trying this at home. If you do not have an amateur radio license, consider contacting your local radio club for assistance.

Chart of my Raspberry Pi deployments at home. The filter on the RPITX part is there for a good reason.

Raspberry Pi and Safe Radio Transmission

You don’t need any additional hardware to get started with sending signals with a Raspberry Pi. All you need to do is attach a wire to one of the GPIO pins, load up rpitx and you’ve something that can transmit radio signals! Just because you can transmit, does not mean you should. This blog posts claims a range of over 300 meters with a 6 foot wire, broadcasting on the 2 meter band (144 MHz). That’s a big distance for a small device. Before we start transmitting, we have to ensure that we are not spamming higher bands with harmonics.

Band pass filter + antenna + raspi. Source: Hackaday

Due to the way that rpitx generates signals, we are pretty much guaranteed to generate spurious transmissions. In order to mitigate this effect, we add a filter between the GPIO pins and the antenna. I will quote user F4VQG from the rpitx group.io:

You have to consider that the output of the Raspberry Pi is more or less a square wave. When you transmit on a specific frequency, let’s say 10MHz, you only want a sine wave at that specific frequency. But a 10 MHz square wave is the sum of a sine wave at 10MHz (which is what you want), but also of sine waves at 30, 50, 70, 90… MHz (they are called harmonics).

Passing your signal through a filter before hitting the antenna helps clear up these harmonics so you are not emitting unintentional interference on other bands. You can buy a pass filter for the frequency that you want to transmit online or at an electronics store. You can also get a kit to build your own.

The amount of trouble you can cause depends on the frequency you choose to transmit on. A low frequency will have a lot more harmonics in commonly used bands. In our example we are going to focus on 315MHz and 433.93MHz. One way to verify that your set up is not generating harmonics, you can plug in an RTL-SDR to your laptop and load up SDR# or GNU Radio. Look at the third harmonic for your frequency. For 315MHz we look at 945MHz. I can barely detect a harmonic from my set up, likely generated from the wire leading up to the filter.

The original signal on 315MHz as seen by SDR#. I overlaid the detectable harmonic on 945MHZ and highlighted with red. It’s barely detectable with my equipment practically touching the raspi. Source: Me

Copy and Paste Radio Signals

Now that we’ve checked ourselves and we aren’t doing anything illegal, let’s start making our dumb devices smart. First, we need to find a good dumb device. You’re going to want to choose something simple that has a radio remote. You can usually find these because they say their frequency on the back of the device or have an FCC id on them. You can distinguish them from IR remotes, because they usually don’t have an LED embedded in the tip.

Three radio remotes, two fans and blinds. Source: Me

Only simple devices will work, something like your garage or car opener will not work. We are essentially replaying a recorded radio signal, and those devices use rolling codes. Once you have a device in mind, find its frequency on the back of the device, in the manual, or look up the FCC id online. Once we have our working remote in hand and we know our frequency, it’s time to load up the raspi and pull up a terminal.

Recording signals

While transmitting signals requires no extra hardware from a Raspi, recording signals from your remotes requires you to have an RTL-SDR and the appropriate drivers installed on your pi as well.

Rpitx has a nice little CLI GUI (oxymoron, I know) you can use to pick different menu options. You can load this menu with ./rtlmenu.sh. The ability to record a signal using your RTL-SDR is one of these menu options. The command it uses in the background is as follows:
rtl_sdr -s 250000 -g “$INPUT_GAIN” -f “$INPUT_RTLSDR”e6 record.iq

Here, we have some variables. For $INPUT_GAIN I used 35, for $INPUT_RTLSDR I used my frequency 314.92 . The e6 is there to convert it into MHz. If you run this on your linux box with an RTL-SDR, you should see something like this:

For each remote button that you want to be called from the Raspberry Pi, do the following:
1. Have your remote close to your RTL-SDR antenna
2. Run the command defined above with your own frequency. Make sure to output it to a filename that makes sense to you.
3. Press the button on your remote.
4. Stop the recording (ctrl+c).

Complete the steps above until you have all your buttons recorded to iq files. Next step, we are going to build a small web server to run these commands.

Controlling your dumb devices with the Raspberry Pi

We are going to put some python code in front of this so we can control our devices with Home Assistant and Alexa. The code can be found here. The command we are using to send the raw data from our raspi is: sudo sendiq -s 250000 -f 314.962e6 -t u8 -i /home/pi/dev/rpitx/samples/filename.iq — you will want to replace the last argument with the path to your own iq file.

The code sample will need to be adjusted. The lookup array at the top of the class has dictionaries containing the definition for each endpoint and radio call you want to make. I chose the HTTPRequestHandler class in python, because it can only run one request at a time. That means that it will queue the next request meaning multiple requests will not be fighting each other over sending data at the same time.

Once you have this code up and running you should be able to send GET requests to the endpoints you configured and see that radio signals are being sent.

Solidifying Smartness

My next step was to add these devices into Home Assistant. The way I did this was by defining a template for my devices. So, I defined a fan template for my fan, a cover template for my blinds, a light template for my lights. You can find more documentation on this here. I will provide an example of my fan template:

fan:                                                                                                                               
- platform: template
fans:
living_room_fan:
value_template: "{{ states('input_boolean.state') }}"
percentage_template: "{{ states('input_number.percentage') }}"
turn_on:
service: script.living_room_fan_power_toggle
turn_off:
service: script.living_room_fan_power_toggle
set_percentage:
service: >
{% if percentage > 0 and percentage <= 33 %}
script.living_room_fan_power_1
{% elif percentage > 33 and percentage <= 66 %}
script.living_room_fan_power_2
{% elif percentage > 66 %}
script.living_room_fan_power_3
{% endif %}
speed_count: 3

I put the above yaml into my configuration.yaml file to define the template for my fan. We are configuring the template to run a script for each action that we are setting up. You will need to go into Home Assistant and build these scripts how you like. I currently use the scripts to trigger events, so I could potentially hook more functionality up to this. The event is being monitored and will send a request to my Raspberry Pi whenever it fires. Here is an example of one of my script yamls:

toggle_living_room_fan_light:
alias: Toggle Living Room Fan Light
sequence:
- event: living_room_fan.light_toggle
event_data: {}
mode: queued
max: 10
icon: mdi:ceiling-fan-light

To hook it up to Alexa, I use the amazon-echo-hub node in Node Red. It allows you to masquerade as automatically discovered smart devices. So, all I need to do is add the device to Node Red, ask Alexa to “discover devices” and it shortly is registered and I can do stuff like “Turn blinds on” or “Turn fan light on,” and it sends a request to my Raspi, which generates a radio signal.

My Node Red flow for these Alexa integration

Final Thoughts

I finished this project in one afternoon, 3–4 hours. It was a twitch stream, and after I finished the stream, I never touched it again. It’s been controlling my devices since then. The solution is pretty simple, but robust. I may have forgotten something in the instructions, so feel free to reach out with any questions. I found this to be a fun and interesting project that helped me learn more about radio and exercise my ham license a little bit. I hope that you can find your own value in a project like this. As always, thank you for reading.

--

--

Kory Kirk

From thought to thing: hacking, thinking, doing stuff