How to Control Power Outlets Wirelessly Using the Raspberry Pi

Eteckcity RF OutletIn this blog post you’ll find instructions for using a Raspberry Pi to wirelessly control Etekcity power outlets using 433MHz RF.

Ever year during Christmas time I find myself dealing with the hassle of turning the Christmas tree lights on and off.  This year I set out to find a solution I could use to automate this task.

While I could have just used one of those cheap light timers instead I wanted something I could control wirelessly using my smart phone.  The Belkin WeMo can be controlled over the web but I think they are way too expensive at nearly $40 per outlet!

While searching for alternative options I found a blog post by Tim Leland that explained how to hack the Eteckcity remote controlled outlets using a Raspberry Pi and a cheap $5 wireless transmitter and receiver kit.

This system is significantly cheaper than using WeMo outlets plus it can also easily be scaled to control more outlets.  As an added benefit of being controlled through the Pi outlets can be automated using cron jobs, scripts, or anything else you can dream up.

Parts List

Below is a listing of all of the hardware I used for this project.  If you plan to use the hard wired ethernet port on the Pi then you won’t need the wireless adapter.

The Pi cobbler is also optional but I find it makes wiring much simpler when using a solderless breadboard.

Raspberry Pi Model B1
Edimax Nano Wireless N USB Adapter1
Sandisk Ultra 16GB Micro SDHC Card With Adapter1
Etekcity 5 Pack Remote Control Outlet Switch1
SMAKN 433Mhz RF Transmitter and Receiver Kit1
Solderless Breadboard1
Raspberry Pi T Cobbler Breakout Kit1
Assorted Breadboard Jumper Wires1

Other Required Items:

  • Soldering iron
  • Solder
  • Wire strippers
  • 12″ strand of wire (for antenna)

Step 1:  Load a disk image on the SD card

If you’re starting from scratch with a fresh SD card then the first thing you need to do is load a disk image onto the card.  I usually load Raspbian since that’s what I’m familiar with it any other image should work fine.

If you prefer not to deal with loading a disk image you can also buy a preloaded memory card.

The quickest method I’ve found to load a disk image using Mac OS X is to use a program called ApplePi-Baker.  The program will automatically detect the SD card, unmount it and load an image file of your choice.

It can also quickly setup a card for NOOBS if that is what you prefer to use.


ApplePi Baker

For Windows users Win32DiskImager is a good program to use for loading disk images on memory cards.

Step 2:  Download and Build WiringPi

WiringPi is a prerequisite package required by RFSniffer and codesend.

The source files for the software can be pulled using git.

git clone git://

Execute the build script to compile the code.

cd wiringPi

To confirm that the build process was a success you can issue the following command.

gpio -v

You should see something similar to the output below.
gpio -v test

Finally you can issue the command below to confirm that wiringPi can read from the GPIO pins.

gpio readall

If successful you’ll see a listing for all of the gpio pins and their values like the one below.

gpio readall

Step 3:  Install Apache and PHP

The Apache web server is used to serve the toggle.php page which will provide a web interface for controlling the wireless outlets.

Use the command below to install Apache with the php modules.

sudo apt-get install apache2 php5 libapache2-mod-php5 -y

To confirm that Apache is working put the IP address of your Pi into your web browser, you should see the default Apache test page.

Apache Test Page

Step 4 – Solder an Antenna Wire to the Transmitter

Without an antenna the transmitters range is extremely limited, mine wasn’t able to reach outside the room without one.  I took Tim’s recommendation and used a 12″ piece of wire from the inside of a cat 5 ethernet cable.

Solder the wire to the antenna pad on the upper right corner of the transmitter PCB.

433MHz Transmitter Module

Step 5:  Connect the RF Transmitter and Receiver Modules to the Pi

Using the solderless breadboard and the jumper wires connect the transmitter and receiver modules to the Pi as listed below.

The silk screen labels on the PCB for each module should match what is listed below.  If it doesn’t match you may have a different revision with a different pinout, in this case you may need to adjust the connections to match your specific modules.

The transmitter module is the smaller module which has 3 pins, VCC, data, and ground.

The receiver is the larger of the two modules with 4 pins, VCC, 2 data pins, and ground.  Only one of the data pins on the receiver is used for this project.

SMAKN 433MHz Transmitter and Receiver Modules

Transmitter Module

  • DATA (left pin) -> GPIO #17
  • VCC (center pin) -> +5VDC
  • GND (right pin) -> Ground

Receiver Module

  • VCC (left pin) -> +5VDC
  • DATA (2nd pin from left) -> GPIO 21/27
  • GND (far right pin) -> Ground

If you are using a solderless breadboard and a Pi breakout cable your setup will probably look something like mine below.

433MHz Transmitter and Receiver With Pi

Step 6:  Use RFSniffer to Find the Outlet Control Codes

In this step you’ll use a program called RFSniffer and the 433MHz wireless receiver to read the on and off codes for each pair of buttons.

First pull down a copy of Tim’s rfoutlet code from GitHub.  Alternatively you can download the source for 433Utils and compile the code yourself.

git clone git:// /var/www/rfoutlet

Set the appropriate ownership and permissions on the codesend executable.

sudo chown root.root /var/www/rfoutlet/codesend
sudo chmod 4755 /var/www/rfoutlet/codesend

To sniff the codes run the RFSniffer program.

sudo /var/www/rfoutlet/RFSniffer

You won’t see any output on the console when you run the program but if everything is connected properly you should see output after pressing some of the buttons on your remote.

Each press of a button on the remote should produce something like this:

Received 21811
Received pulse 192

What you’re looking for is the longer number, not the short 3 digit pulse.  In the example above 21811 would be the code you’re looking for.  Record the code for each of the on and off buttons on the remote.

Here are a few of my notes about reading the codes:

  1. The receiver is not very sensitive so make sure you have the remote nearby when reading the codes.
  2. I found that sometimes I had to press a button multiple times before a code was received, it’s not a 100% reliable process.
  3. If it’s not working, double check the wiring of the receiver module (the longer board with 4 pins)
  4. For further troubleshooting try connecting an LED to the data pin of the receiver, it should blink when receiving data.

Step 7:  Update toggle.php with the Codes for Your Remote

Using your preferred text editor edit /var/www/rfoutlet/toggle.php with the codes you recorded in step 5.  You will also need to update $rfPath to point to the correct path which in my case was /var/www/rfoutlet/codesend.


Testing the Web Outlet Controls

At this point everything should be done and ready to be tested.  The php based web control page can be accessed by visiting the http://<your-pi-ip>/rfoutlet in your browser.

The on and off buttons on the page should function just as they would on your physical remote.

Screen Shot 2014-12-28 at 7.17.51 PM


If the buttons on the web page don’t work then try manually sending a code using the command line.

root@raspberrypi:/home/pi# /var/www/rfoutlet/codesend 21820
sending code[21820]

If sending a code manually works then the transmitter is functioning but there is an issue related to the web setup.  Make sure that you made the correct modifications to toggle.php, specifically the $rfPath variable is pointing to the correct path.

You can also check the apache server logs to see if there is a syntax error in the toggle.php file.

tail -100 /var/log/apache2/error.log

If the manual code send isn’t working then check to make sure the transmitter is wired properly.  You can also connect an LED to the data pin of the transmitter to confirm that it is receiving output from the Pi, it should blink when you send a code.

Additional Resources

In addition to Tim’s blog article Ninja Blocks has a very useful article about adding 433Mhz RF to your Pi.  Ninja Blocks also maintains the 433Utils code on github which may be helpful as well.

Sam Kear

Sam graduated from the University of Missouri - Kansas City with a bachelors degree in Information Technology. Currently he works as a network analyst for an algorithmic trading firm. Sam enjoys the challenge of troubleshooting complex problems and is constantly experimenting with new technologies.

75 thoughts on “How to Control Power Outlets Wirelessly Using the Raspberry Pi

  1. Great writing! Couldn’t have been easier. I was able to use the Imation brand of these outlets which function at the same 433mhz. Much cheaper where I am. Skipped the soldering of the antenna and just put a small piece of CAT5 through the antenna hole of the transmitter and twisted it snug like a twist tie. Works through all three floors of our house.

    1. Modify the webpage by editing /var/www/rfoutlet/index.html. You can replace 1 with Porch for example, or get fancy and change the styling or background.

  2. Thank you, Sam! Great tutorial. Tim had a good start with his blog post, but I like how in depth you went.

    I’m new to breadboards, but I think I understand the concept of the GPIO/breakout connector to the board itself, but I’m a little lost beyond that. Any chance you have a wiring schematic with all slots/labels of each?

    Also, what kind of range did you get after soldering an antenna wire to the transmitter?

  3. When you say:

    DATA (2nd pin from left) -> GPIO 21/27

    Does mean to connect it to both pins, or one or the other?

    1. For others who come here with the same question, it’s either 21 or 27 depending on which rev of pi you have. I’m not sure which pin it would be on a pi2, my pi2 is doing other things :]

      1. Raketemensch : I am using Raspberry Pi 2 and wanted to know if you were able to use the same wiring schematics as the Raspberry Pi B?
        If not which GPIO pins did you use?

  4. Could you say what the remote code version is you used in your test? There is usually a 3 or 4 digit number on the back of the remote.

      1. Originally, I recorded WAV’s of the remote commands. I was able to decipher just by looking at the output in Audacity. Each key press sends a repeating block of 25 bits consisting of a 10 bit header (which is different based on the remote number), a 10 bit channel code (1-5), and a 5 bit command. The last bit is always 0, so I guess you can call it a 4 bit command with a final control bit. RFSniffer spits out codes ignoring that last bit. Here is my findings:

        1548 Sample Ch1 On Code
        [ header ] [ channel ] [Command]
        [ 1548 ] [ Ch 1 ] [ On ]
        0 1 0 0 0 1 0 1 0 0 0 1 0 1 0 1 0 0 1 1 0 0 1 1 0

        remote # 1548 = 0 1 0 0 0 1 0 1 0 0

        Ch1 = 0 1 0 1 0 1 0 0 1 1
        Ch2 = 0 1 0 1 0 1 1 1 0 0
        Ch3 = 0 1 0 1 1 1 0 0 0 0
        Ch4 = 0 1 1 1 0 1 0 0 0 0
        Ch5 = 1 1 0 1 0 1 0 0 0 0

        On = 0 0 1 1 0
        Off = 1 1 0 0 0

        Everything is pretty clear except for the header. I cant figure out exactly how it pertains to the remote number. I’ve found a pair of remote numbers that have the same header, and each end with the same number. On first guess, I’d say only that last number is significant, but I really need to collect more headers and remote numbers to verify.

      2. The more I think about it, the more the simple solution seems to stand out. Maybe the numbers on the back of the remotes mean absolutely nothing, and they are only used to match the remotes to the preprogrammed outlets. It seems that the first 10 bits that make up the header can really be anything so long as every odd bit is a 0. These are the headers I’ve collected. Would be great if others could post their RFSniffer results to see if the pattern holds.

        I would imagine we could make up any header we’d like to program different remote groups without needing an actual remote to clone, so long as it follows the every odd is a ‘0’ pattern.

        1. Brad, I have one more header to add, sticker code 0349: 0001 0100 01

          I was also trying to figure this out so that the RF code formation could be turned into code rather than hardcoded values. See this ( for where I was going, also much simpler than the existing projects that depend on the heavyweight C++ libraries.

          Can you post the pairings you have for the headers with the sticker codes? There has to be some sort of pattern that would allow not having to sniff at all, I would think.

          1. these are the only one’s I’ve gathered (including yours)

            0349 = 0 0 0 1 0 1 0 0 0 1
            0923 = 0 0 0 0 0 1 0 1 0 1
            1420 = 0 1 0 1 0 1 0 1 0 1
            1548 = 0 1 0 0 0 1 0 1 0 0

            I seems that they are using control bits at 1/5/6/7/9, but these aren’t at all required. I’ve set all bits to both 1’s and 0’s, programmed outlets from my Pi, and the codes still work.

            In the end, the remote codes don’t matter. They were totally helpful in figuring out everything I have, but the remotes really aren’t needed. As long as you know how the channels and commands are called, you can make up any header you want without sniffing. Then, just program the outlets from your Pi.

            Check my work below this post to see how to auto-generate all 5 channel on/off commands from a single code. It doesn’t even need to be a valid code to use. Just make up anything in binary that’s 23 bits or less long and convert to base-10.

            1. The remote codes *do* matter if you still want to use the remotes, of course, so there will be no re-programming of outlets for me to random 23 bit codes. My desire to understand the remote code mapping to emitted bits is so a user can simply punch in that code and go, if that is at all possible. Thanks for the listing of collected codes and matching sticker codes.

              I’ve read all your posts (thanks!), and I linked to my set of code that does a similar thing in a few lines of C code.

              1. We would need more headers collected to figure that out.

                In the meantime though, the outlets do hold onto three sets of codes at a time. So you could program a custom code from your web interface and still retain use of the original remotes.

      3. Wow! Even Simpler….

        The outlets have no control/check bits at all in the header. I’ve tested and verified that you can use any combination of 10 bits (all 0’s, all 1’s, or anything), followed by a proper channel and command.

        1. Even the channel doesn’t have to be proper. You can make up channels beyond the 5 I posted. Any combination of 10 bits for the channel will work as well. So all that really matters is that the code ends with the On/Off command.
          0011 = ON
          1100 = OFF

    1. It would certainly be possible to build an app to do this but currently it can only be accessed through the web interface or the command line. The nice thing about the web interface is that is it platform agnostic and will work on any device or operating system.

  5. I’ve modified the toggle.php to use more generic functions. You no longer have to input all of your codes. Any single code can be used to generate all codes for a particular remote.

    $rfPath = ‘/var/www/rfoutlet/codesend ‘;
    $outletLight = $_POST[‘outletId’];
    $outletStatus = $_POST[‘outletStatus’];

    // enter any captured remote code below. can be an ON or OFF command from any channel 1-5. //
    $CapturedCode = 4527411;

    // no need to change anything below this line ///////////////////////////////////////////////
    $Channel1 = 5424; //0 1 0 1 0 1 0 0 1 1 0 0 0 0
    $Channel2 = 5568; //0 1 0 1 0 1 1 1 0 0 0 0 0 0
    $Channel3 = 5888; //0 1 0 1 1 1 0 0 0 0 0 0 0 0
    $Channel4 = 7424; //0 1 1 1 0 1 0 0 0 0 0 0 0 0
    $Channel5 = 13568; //1 1 0 1 0 1 0 0 0 0 0 0 0 0
    $TurnOn = 3; //0 0 1 1
    $TurnOff = 12; //1 1 0 0

    // this sets all bits in the last 14 positions to 0, leaving only the remote group header. //
    // there isn’t a ‘NOR’ command in PHP, so we ‘OR’ to turn on all the bits we want to clear //
    $RGroup = ($CapturedCode | 16383);
    // then we subtract the value of all of those bits to clear them out.
    $RGroup = ($RGroup – 16383);

    if ($outletLight == “1” && $outletStatus == “on”) {
    $rfCodes = array($RGroup + $Channel1 + $TurnOn);
    } else if ($outletLight == “1” && $outletStatus == “off”) {
    $rfCodes = array($RGroup + $Channel1 + $TurnOff);
    } else if ($outletLight == “2” && $outletStatus == “on”) {
    $rfCodes = array($RGroup + $Channel2 + $TurnOn);
    } else if ($outletLight == “2” && $outletStatus == “off”) {
    $rfCodes = array($RGroup + $Channel2 + $TurnOff);
    } else if ($outletLight == “3” && $outletStatus == “on”) {
    $rfCodes = array($RGroup + $Channel3 + $TurnOn);
    } else if ($outletLight == “3” && $outletStatus == “off”) {
    $rfCodes = array($RGroup + $Channel3 + $TurnOff);
    } else if ($outletLight == “4” && $outletStatus == “on”) {
    $rfCodes = array($RGroup + $Channel4 + $TurnOn);
    } else if ($outletLight == “4” && $outletStatus == “off”) {
    $rfCodes = array($RGroup + $Channel4 + $TurnOff);
    } else if ($outletLight == “5” && $outletStatus == “on”) {
    $rfCodes = array($RGroup + $Channel5 + $TurnOn);
    } else if ($outletLight == “5” && $outletStatus == “off”) {
    $rfCodes = array($RGroup + $Channel5 + $TurnOff);
    } else if ($outletLight == “6” && $outletStatus == “on”) {
    $rfCodes = array(($RGroup + $Channel1 + $TurnOn), ($RGroup + $Channel2 + $TurnOn), ($RGroup + $Channel3 + $TurnOn), ($RGroup + $Channel4 + $TurnOn), ($RGroup + $Channel5 + $TurnOn));
    } else if ($outletLight == “6” && $outletStatus == “off”) {
    $rfCodes = array(($RGroup + $Channel1 + $TurnOff), ($RGroup + $Channel2 + $TurnOff), ($RGroup + $Channel3 + $TurnOff), ($RGroup + $Channel4 + $TurnOff), ($RGroup + $Channel5 + $TurnOff));

    foreach ($rfCodes as $rfCode) {
    shell_exec($rfPath . $rfCode);

    echo json_encode(array(‘success’ => true));

    1. Kudos, first off, to Sam for the great tutorial. Secondly, to Brad, your extra effort and thinking towards making the process even better I can relate to (as it is much like I think as well!).

      I do have a question that no one else seems to be able to answer for me in other places. I have these same outlets and am new to much of this, and I did get them working from my RPi but I did it slightly differently (before I saw this page). I actually used a python script to sniff the waveform for each button (yeah, the hard way apparently, lol). I am dedicated to using Python for a specific reason – I want to be free of the bounds of HTTP basically. I plan on using PubNub (a DSN) to have more control over how I can interact with my IoT stuff…long story, but I know it will work. Problem with the way I did it is this: the transmit script that I use took a bit of time getting right because I had to figure out the short and long duration of the pulses as well as the extended duration between each cycle. This was tough as it was super fast – 0.00012 and 0.00048 seconds respectively (short and long). This seemed to work well initally, though I have to loop through 20 times to be sure it doesn’t miss. Problem is I am using Python’s sleep function but it looses its accuracy quickly below 1 millisecond. Anyhow, it worked well but then I accidentally unplugged my RPi and ever since I powered it back up my outlets have been very unresponsive. They work, but I have to send the command a bunch of times sometimes.

      Anyway, I like some parts of the code used here in that you can send the decimal instead of binary (which I am sending in a variable) but my biggest question is – what controls the duration and timing in this code? I was wanting to see if I could refine my code in some way. Finally, can someone tell me if I am anywhere near correct in my timings I observed since you have the same outlets. Thanks!

      1. Awesome! I actually started out recording the RF audio transmission from the remotes, and visually decoding the waves into bits. That’s how I was able to break down the entire code from remote group headers, to specific channel within the groups, to the final ON/OFF command for that address. Once I knew how the bits came together, I was able to update the toggle.php to mathematically populate any group of codes. You don’t even need to sniff, you can enter any dummy number, and use that to generate 5 channel ON/OFF commands, then send those with the outlets in Learning mode first.

        As far as timings, I gave up looking for exact timing when I came across this page. My closest guess was .000238 + .0562pause for a 0 bit (short) and .000604 + .000196pause for 1 bit (long). Start to start length being .0008.

        I’ve since completely abandoned the RPi and have been using a Hook (gethook,io) device to control these outlets via Amazon Echo. You could use the sniffer to get the pulse length. I think that’s the start to start length in milliseconds. Also, check out the RCSwitch.cpp file in the sourcecode. It has lots of info on pulse/bit length.

  6. Hi. Many thanks for putting this together. It’s awesome.

    I have an issue though. I have two terminal windows open and I can see that I’m able to sniff the code of my Byron / Home Easy plug which has a two digit code of 20 for on and 21 for off, the Pulse is 320. I can also sniff the code that’s being sent from my RF transmitter on my breadboard using the receiver that is also on the breadboard, so I’m fairly confident RF signals are being sent out from the PI ok, otherwise I wouldn’t be picking these up.

    So, would you know why it’s not working? Is a two digit code too short for this to work? All the examples I’ve seen on the web mention 6 to 7 digits.

    Many thanks! Adam

  7. Hi!

    Great article! I have a problem…i followed your steps and all went perfectly. I could send and receive the correct ID codes for my sockets however i need to change the pulse.

    So i updated the pulselength line in codesend.cpp and then recompiled using ‘sudo make codesend’

    Now i can send the correct the id and pulse length manually through the comand console (and the socket came on!!)but now the web page will not respond and execute sendcode…

    Any ideas?… close!!! 😛

  8. Hi

    First off….fantastic tutorial, thankyou!

    I managed to follow this perfectly and all works well except I need to change the Pulse length in order for my sockets to respond. So I updated this is codesend.cpp by following these steps:

    1.sudo nano /var/www/rfoutlet/RFSource/codesend.cpp
    2.Change the line: mySwitch.setPulseLength(xxx);
    3.Verify you’re in the ‘/var/www/rfoutlet/RFSource/’ directory the file and compile with: sudo make codesend
    5.Move and overide the old codesend: mv -f codesend /var/www/rfoutlet/

    Now I can successfully turn the socket on and off manually using the command prompt but the web interface does not respond.

    Any ideas?? …i’m so close!!

  9. Hi Sam,

    Thanks a lot for the tutorial. I used it to configure my openHAB to talk to the etekcity outlets.

    Just an update for you and other people who are looking to implement these awesome remote control outlets: with the latest wiringPI and raspbian, you no longer need root to access the gpio pins. Look here for more info;

    1. Hi,
      I am just starting off with Sam’s awesome project. I had the same idea of integrating it openhab. Do you have some tutorial on how you did that? If so that would be very helpful.


      1. Hi Sarvesh,

        I don’t have any tutorials. But below is how I set up my openhab. Don’t forget to replace the outlet code (i.e. 21811, 21820) with your own.

        Switch Light_Ceiling “Ceiling” (gOH, Lights) {exec=”>[OFF:/var/www/rfoutlet/codesend 21820] >[ON:/var/www/rfoutlet/codesend 21811]”}
        Frame label=”Light Switches”{
        Switch item=Light_Ceiling label=”Ceiling” mappings=[ON=”On”, OFF=”Off”]

        1. B G thank you for that, appreciate your comments. I am all new to RPi2 and GPIO altogether. So getting the receiver and transmitter working is my first goal. If it does work for me, I will be posting a couple of more pictures here for people like me who are starting and need guidance on how the breadboard/ connection should look like.

        2. Hi B G,
          I tried your sample adding the stuff you mentioned in the items and sitemap. But unfortunately, I cannot see anything other than the label name from sitemap.
          I actually copied most of the stuff from demo files. Can you let me know if there is anything I am missing?

          ==================================== items =================
          Group All
          Group gGF (All)
          Group gFF (All)
          Group gC

          Group GF_Living “Living Room” (gGF)
          Group GF_Kitchen “Kitchen” (gGF)
          Group GF_Toilet “Toilet” (gGF)
          Group GF_Corridor “Corridor” (gGF)

          Group FF_Bath “Bathroom” (gFF)
          Group FF_Office “Office” (gFF)
          Group FF_Child “Child’s Room” (gFF)
          Group FF_Bed “Bedroom” (gFF)
          Group FF_Corridor “Corridor” (gFF)

          Group:Switch:OR(ON, OFF) Lights “All Lights [(%d)]”

          Switch Light_GF_Corridor_Ceiling “Ceiling” (GF_Corridor, Lights){exec=”>[OFF:/var/www/rfoutlet/codesend 1381692] >[ON:/var/www/rfoutlet/codesend 1381683]”}

          ======================= Sitemap ===========================
          sitemap demo label=”Home Automation”
          Frame label = “Light_Switches” {
          Switch item=Light_GF_Corridor_Ceiling label=”Ceiling” mappings=[ON=”On”, OFF=”Off”]

          Thank you
          S N

  10. Thanks for the tutorial! In my case, I had a 5-unit version but 2 of the buttons where repeats (1 & 4 are the same and 2/ & 5 are the same!) so this is the only way I could use 5 different signals. I managed to use your work to figure out the basic communication and built my own website on a Raspberry Pi using Flask. I’m now to the point where I have an entire web interface to control it. I can setup schedules, run commands based on the ambient light levels outside, and control it using a RESTful API (which allows me to use Tasker on my Android phone to do things like detect when I’m home to turn on lights!) all while having a mobile-friendly interface to manage everything. Thanks again!

    1. I’m glad you found it useful! I’m intrigued by the version of the web interface you’ve designed, would you care to share the code? Or maybe at least provide some screenshots so others might get ideas?

        1. Hey Jaron–

          I love your interface. Are you willing to post some code now? Or if not, could you go into what you did to make it so beautiful?

          I’ve never used Flask, but I’d be willing to try if I can make my home automation system look like yours.


          1. Actually, yes, I just put up a dump of my last stable build. It’s very much an Alpha product but this way people can play with it and see how it works.

            I also tried to list as many of the 3rd party plugins I used to make the interface so if you’re working on your own, you can go ahead and use them in your project!


  11. Is there a way to “poll” the status with RF? So i can modify the page to tell me if the light (or outlet) is turned on or off?


    1. Not that I’m aware of, I don’t think the outlets have any mechanism to report their status. The remote can only send a simple on or off command that the outlets respond to.

  12. Hi

    I have had this working before but have had to wipe my PI. I have edited toggle.php and set up apache ok so I can see the ‘it works’ html page but I cannot get to work. I get URl not found error.

    I have set the permissions so I cannot see what is causing it. I didnt hit this issue before.

    Any ideas?


  13. Hi
    Your project inspired me to try it out. I am new to this, and wanted to understand how to attach the cables to the breadboard. Would it be possible to put more pictures on how you are doing that? It would be really helpful for people like me, who are just starting.

    PS: Love the details you have provided.

    Thank you

  14. Would this still be the same for Raspberry Pi 2?

    Transmitter Module
    •DATA (left pin) -> GPIO #17
    •VCC (center pin) -> +5VDC
    •GND (right pin) -> Ground

    Receiver Module
    •VCC (left pin) -> +5VDC
    •DATA (2nd pin from left) -> GPIO 21/27
    •GND (far right pin) -> Ground

  15. Hi,
    I also have the Raspberry PI 2 and cant get the receiver to read anything. Does it matter which data pin I use on the receiver? I have just been trying random gpio pins now, I may have tried them all. Does anyone know what pin to use? Or what file this can be changed in?

      1. I also use this setting but my receiver has a really short range – about half inch with antena connected. Has anybody an idea what could be wrong?

    1. Derek,
      I just got mine working. I followed this site to the dot, and it worked for me. The receiver information is as follows:
      Receiver Module
      •VCC (left pin) -> +5VDC
      •DATA (2nd pin from left) -> GPIO 21/27
      •GND (far right pin) -> Ground

      I haven’t soldered the antenna yet but it is working for me. Initially I installed 433utils, even though I was able to read the code. I wasn’t able to send it. Then I tried the one mentioned here (RFSniffer) and it worked!

  16. The location of the rfoutlet git repo has changed. To clone the repo without being asked for a password use this:

    git clone git://

  17. This is hands down the best tutorial I have found for this on the net. As a php developer that is new to all of this kind of thing you explained it extremely well. Hopefully I can get started making my own soon!

    Thank you so much!!

  18. I have read this webpage on how to control power outlets via 433MHz RF using an RPi.
    Everything works except the webpage controls…
    When I hit any button nothing happens (I have a scope attached to the Tx data line).
    I have a Raspberry Pi3 with Raspbian Jessie (latest updates) and I can send the control codes manually using
    sudo sudo /var/www/html/rfoutlet/codesend 1394005
    This activates the mains switch. But using the webpage buttons does not work at all. There are no pulses sent to the transmitter…
    I have edited the toggle.php file and entered the codes RFSniffer has detected. I also changed the path to the codesend utility to the absolute path:
    $codeSendPath = ‘/var/www/html/rfoutlet/codesend’;

    What else can I do to enable the webpage operations?

    And why does one have to use sudo to run codesend? WiringPi manages to reach the GPIO as standard user pi.

    Bo B

      1. I have checked permissions:
        pi@rpi3-jessie:/var/www/html/rfoutlet $ ls -la c*
        -rwxr-xr-x 1 root root 18832 Mar 20 23:57 codesend

        pi@rpi3-jessie:/var/www/html/rfoutlet $ sudo chmod +777 codesend
        pi@rpi3-jessie:/var/www/html/rfoutlet $ ls -la c*
        -rwxrwxrwx 1 root root 18832 Mar 20 23:57 codesend

        No difference after this, I can do this on the command line:
        pi@rpi3-jessie:/var/www/html/rfoutlet $ sudo /var/www/html/rfoutlet/codesend 1394005
        Sending Code: 1394005. PIN: 0. Pulse Length: 189

        And now the switch #2 lights up, not so when hitting the webpage button on my smartphone or on my PC FireFox.

        This is how the edited part of toggle.php looks like:

        // Edit these codes for each outlet
        $codes = array(
        “1” => array(
        “on” => 1381717,
        “off” => 1381716
        “2” => array(
        “on” => 1394005,
        “off” => 1394004
        “3” => array(
        “on” => 1397077,
        “off” => 1397076
        “4” => array(
        “on” => 1397845,
        “off” => 1397844
        “5” => array(
        “on” => 1397845,
        “off” => 1397844

        // Path to the codesend binary (current directory is the default)
        $codeSendPath = ‘/var/www/html/rfoutlet/codesend’;

        So I changed all of the numeric codes and the codesend path, nothing more….

        Could there be a permission issue for Apache? Since I installed just now there might be differences from when you wrote the blog….

        For some reason the reply post I just made did not make it to the comments, so I am trying again.
        Lucky that I copied the entire reply before hitting “Post Comment”….
        Bo B

  19. I have checked permissions:
    pi@rpi3-jessie:/var/www/html/rfoutlet $ ls -la c*
    -rwxr-xr-x 1 root root 18832 Mar 20 23:57 codesend

    pi@rpi3-jessie:/var/www/html/rfoutlet $ sudo chmod +777 codesend
    pi@rpi3-jessie:/var/www/html/rfoutlet $ ls -la c*
    -rwxrwxrwx 1 root root 18832 Mar 20 23:57 codesend

    No difference after this, I can do this on the command line:
    pi@rpi3-jessie:/var/www/html/rfoutlet $ sudo /var/www/html/rfoutlet/codesend 1394005
    Sending Code: 1394005. PIN: 0. Pulse Length: 189

    And now the switch #2 lights up, not so when hitting the webpage button on my smartphone or on my PC FireFox.

    This is how the edited part of toggle.php looks like:

    // Edit these codes for each outlet
    $codes = array(
    “1” => array(
    “on” => 1381717,
    “off” => 1381716
    “2” => array(
    “on” => 1394005,
    “off” => 1394004
    “3” => array(
    “on” => 1397077,
    “off” => 1397076
    “4” => array(
    “on” => 1397845,
    “off” => 1397844
    “5” => array(
    “on” => 1397845,
    “off” => 1397844

    // Path to the codesend binary (current directory is the default)
    $codeSendPath = ‘/var/www/html/rfoutlet/codesend’;

    So I changed all of the numeric codes and the codesend path, nothing more….

    Could there be a permission issue for Apache? Since I installed just now there might be differences from when you wrote the blog….

    1. There must be some type of apache / php issue going on that prevents the codesend executable from being called.

      Does anything show up in the apache web server logs when you click the button?
      tail -100 /var/log/apache2/error.log

      1. This is what I got:
        [code] tail -100 /var/log/apache2/error.log
        [Sun Mar 27 06:25:06.738493 2016] [mpm_prefork:notice] [pid 708] AH00163: Apache/2.4.10 (Raspbian) configured — resuming normal operations
        [Sun Mar 27 06:25:06.738591 2016] [core:notice] [pid 708] AH00094: Command line: ‘/usr/sbin/apache2’
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)
        wiringPiSetup: Must be root. (Did you forget sudo?)[/code]
        When I push a button there are a number of added wiringPi lines added to the log…

      2. It seems like there are a few wiringPi problems here:
        1) The wiringPi library itself seems to check if it is called as root and errors out if not with this error message in the apache log:
        wiringPiSetup: Must be root. (Did you forget sudo?)

        2) I tried a test with a very simple webpage calling a php file which calls the rfoutlet/codesend program to switch on a certain switch, where I added sudo in front of the exec command as follows

        (file switchtest.php)
        $operation = $_POST['SW2'];
        $switchcode = $_POST['switchcode'];
        echo "Operation = $operation “;
        echo “Switchcode = $switchcode “;
        echo exec(‘whoami’) . ”;
        $result = exec (“sudo /var/www/html/rfoutlet/codesend $switchcode”);
        echo “Result of operation = $result “;

        Called from this html:

        3) Now I get this verbose text in the apache error log:
        We trust you have received the usual lecture from the local System
        Administrator. It usually boils down to these three things:

        #1) Respect the privacy of others.
        #2) Think before you type.
        #3) With great power comes great responsibility.

        sudo: no tty present and no askpass program specified

        Is there a way to:
        1- recompile codesend such that wiringPi does not require root?
        I have installed wiringPi itself and it does not require root to examine the GPIO….
        2- Make the www-data user allowed to run sudo in the php command

        1. For some reason the html code I tried to post got filtered out!
          But it is a simple one-button form which posts the switchcode to be used by codesend.
          I tried that in order to remove all of the stuff from the toggle.php file execept the bare bones.
          The output on screen when I push the button in the test page is:

          Operation = SW2 ON
          Switchcode = 1394005
          Result of operation =

          So the switchcode is transferred OK and I can see the user running the codesend program is www-data…

      3. Finally managed to get the last issue resolved (requiring sudo on the shell_exec command in toggle.php):
        So this is what I did:
        1) Added group gpio to user www-data (I do not know if this is REALLY needed..)
        sudo usermod -a -G gpio www-data

        2) Edited /etc/apache2/envvars and added this environment variable to the bottom:
        export WIRINGPI_GPIOMEM=1

        3) Restarted apache2:
        sudo /etc/init.d/apache2 restart

        4) Edited the php file and removed sudo from the shell_exec command

        Now I can switch on/off via the webpage with success and no errors in the Apache log.

  20. UPDATE
    I have done the following to fix the issue:
    1) Copied the RFSource dir content over to ~/RFSource (now pi is owner)
    2) Issued command ‘export WIRINGPI_GPIOMEM=1’
    3) Issued ‘make’ in the ~/RFSource dir to compile the utilities
    The resulting codesend program does not complain about sudo if just executed by pi
    4) Copied the file with ‘sudo cp codesend /var/www/http/rfoutlet/’ this overwrites existing file
    5) Edited the toggle.php file and added sudo before shell_exec
    6) Did ‘sudo nano /etc/sudoers’ and added this line at the bottom:
    www-data ALL=NOPASSWD: /var/www/html/rfoutlet/codesend

    Now finally the RF Outlets webpage does work to control my switches and there is no entry in the Apache error log.

  21. For those having trouble loading the web page using ip/rfoutlets, you need to edit /etc/apache2/sites-enabled/000-default. Just remove directory “html” from /var/www/html and you’ll be good to go.
    I haven’t done so, but replacing the CSS and javascript from with a local version will make the index page load quicker.

  22. Thanks for the clear write up. I used a RPi3 to do this. I however had a slight confusion about the GPIO numbers. It really uses wiring Pi #0 for sending and #2 for sniffing and BCM Pins are 17 and 27 respectively. I got confused by the output of “gpio readall” – which printed “GPIO.17, etc”

  23. I needed a timed outlets (atleast few of them) – because the main reason i need it is i forget to turn it off. So, i tweaked the index.html and toggle.php to suit my needs. If anyone is interested in it, i would make the changes public.

    here’s my web interface looks like now:

    I do this timed thing only for individual outlets – do not need it yet for ‘all’ outlets case.

  24. Hey I followed your tutorial and when i manually send in the command then the outlet works but when i try through the webpage it doesnt work. I check the apache log and it gives me this error : wiringPiSetup: Must be root. (Did you forget sudo?) . Does anyone have advice?

  25. I have seen a number of RF plug options like this. I’m wondering if there are RF switches to replace a wall switch that can be controlled in a similar manner by a raspberry pi.

  26. Hi Sam,
    thanks for that great tutorial. I’ve used another one and tried for at least two nights… but “codesend” did not work… With your tutorial: half an hour… perfect!

    But (yes I’m a really hard newbie) now I got stuck at the webpage…
    Perhaps there is just a little thing wrong.. but couldn’t find it…

    What I did:
    Codesend with terminal works perfect.
    I can see the webpage with the buttons, but the buttons do not work properly.
    I’ve edited the path in the php to my folder: $codeSendPath = ‘./var/www/html/rfoutlet/codesend’;

    But this command does not work with the terminal:
    not working: $codeSendPath = ‘./var/www/html/rfoutlet/codesend 12345678’;
    is working: $codeSendPath = ‘/var/www/html/rfoutlet/codesend 12345678’;
    so I tried to remove the “.” in the php command, but did not solve the problem.

    Can you give me some help please?
    Perhaps we can communicate on another way than this here?

    Thanks for your help!!

Leave a Reply

Your email address will not be published. Required fields are marked *