Pinterest Stumbleupon Whatsapp
Advertisement

Smart power sockets are the simplest way to automate your home, but at around $40 each for a Wi-Fi or ZWave based socket, you’re unlikely to buy more than a few.

You might already have some cheap RF based sockets though – the kind that come with their own custom remote control, and have some channel and ID selectors on the back. Unfortunately, there are no smart home hubs on the market Battle of the Smart Home Hubs: What's Out There and What's Coming? Battle of the Smart Home Hubs: What's Out There and What's Coming? Read More that work with those. Wouldn’t it be great if you could link those into your DIY smart home system somehow? Well, you can – quite easily in fact – with around $10 in parts.

With a little more work, you can also integrate some other bespoke RF-based remote hardware, like this budget cinema screen.

What You Need:

If this is your first time programming the NodeMCU board, you’ll need to download the Arduino plugins for it: follow along with the first part of our Arduino Killer introductory guide Meet the Arduino Killer: ESP8266 Meet the Arduino Killer: ESP8266 What if I told you a there's an Arduino-compatible dev board with built-in Wi-Fi for less than $10? Well, there is. Read More for the NodeMCU/ESP8266 chip. You’ll also need CH430 drivers. You can find signed macOS CH430 drivers here, or Windows here.

I’ve used v1.6.5 of the Arduino because anything higher introduces more problems than it solves. Downgrade if you haven’t already.

Advertisement

Before you proceed, I’m going to assume a basic level of knowledge about Arduino programming Arduino Programming For Beginners: The Traffic Light Controller Arduino Programming For Beginners: The Traffic Light Controller Last week, we learnt about the basic structure of an Arduino program and took a closer look at the 'blink' example. Hopefully you took the opportunity to experiment with code, adjusting the timings. This time,... Read More , and that you have your NodeMCU setup in the board manager, and are able to correctly upload some demo code. You should also have added the libraries included in our download to your Arduino/libraries folder.

If you have an existing PubSubClient or MQTT library, back it up and remove it – the one I’ve included in the download is the only one where I could reliably receive messages on NodeMCU, and I tried a lot!

RF Sniffing (Optional)

This step isn’t needed if you only want to control DIP-switch or dial selector plug sockets – those are supported out of the box, and minimal code modification will be needed (this is still interesting to do first, though, so you’ll understand what’s going on behind the scenes).

If you have other RF remotes that you’d like to try adding, you’ll need to first “sniff” the RF codes being transmitted. To do so, load up the ReceiveDemo_Advanced sketch from the Menu -> Examples -> RCSwitch folder, and change the following line from 0

mySwitch.enableReceive(0); // Receiver on interrupt 0 => that is pin #2

to 2.

mySwitch.enableReceive(2); // Receiver on GPIO 2 / D4.

Wire up the receiver module as follows. Looking at the front of the receiver board (it’s the longer of the two, the transmitter is square) – the side with the components on:

  • Far right is GND. Connect to GND on the NodeMCU board.
  • Far left is VCC. Connect to VIN on the NodeMCU board.
  • Middle two pins are the signal. Connect either one to D4 on the NodeMCU (they are connected together, so it doesn’t matter which).

433 wiring-1

Now upload the modified ReceiveDemo_Advanced, and when it’s done, open up the serial monitor and start pressing buttons on your remote controls. Copy out the decimal (including bit length), pulse length, and protocol when you press a button.

screen RF sniffing

After doing this, I found my projector screen was using

  • SCREEN UP: Received 8694273 / 24bit; Pulse length: 355 or 356; Protocol: 1
  • SCREEN DOWN: Received 8694276 / 24bit;Pulse length: 355 or 356;  Protocol: 1

Continue for as many buttons as you need.

Testing the Transmitter

Next, we’re going to try sending codes using the transmitter. Wire the transmitter module (the square one) as follows. Be careful: the labelling on these pins is atrocious.

The VCC pin is actually in the middle, not on the left side. I destroyed one module in the process of figuring this out. That thing that says “ATAD” is actually “DATA”, spelled backwards. Again, the data goes to D4, VCC to VIN, and GND to GND (remove the receiver module, you no longer need it).

433 wiring-2

Load up the Examples -> RCSwitch -> TypeB_WithRotaryOrSlidingSwitches, and again, change the data pin:

mySwitch.enableTransmit(10);

to

mySwitch.enableTransmit(2);

Note, a variety of examples are in included in the library, and which one works for you will depend on the exact type of switch that you have. Type A (dip switches) and B (dials or sliders) are the most common – refer to the pictures on the RCSwitch page. For type B, turning on and off a socket is as simple as:

mySwitch.switchOn(1, 4);

mySwitch.switchOff(1, 4);

where 1 is the channel ID (the top dial), and 4 is the socket ID (the bottom dial). These were written in roman numerals on my sockets. A maximum of 16 individual sockets can therefore be addressed, though multiple sockets can use the same address if you have multiple devices to turn on at once.

However, my projector screen was a little different – it used a different pulse length. So, to operate those, the following worked. Note you can also define a different protocol if your remote needs it, BUT make sure you define the protocol BEFORE the pulse length. The pulse length is overwritten when changing protocol.


// Note that my screen actually requires TWO button presses (not a long press, but two physical presses), so I'm delaying a bit then sending the same signal again

void screenUp(){
  mySwitch.setPulseLength(358);
  mySwitch.send(8694273,24); // (decimal code, number of bits)
  delay(2000);
  mySwitch.send(8694273,24);
}
void screenDown(){
  mySwitch.setPulseLength(358);
  mySwitch.send(8694276,24);
  delay(2000);
  mySwitch.send(8694276,24);
}

Test all your codes are working first before you move on to the next step.

Controlling via MQTT

Open up the sketch you downloaded from Github named mqtt_rcswitch.ino, and start by modifying the network SSID and password for your home. Then, change the channel name if you wish, and set the MQTT server. If you don’t already have an MQTT server running on your OpenHAB install, read part 2 of our OpenHAB beginner’s guide OpenHAB Beginner's Guide Part 2: ZWave, MQTT, Rules and Charting OpenHAB Beginner's Guide Part 2: ZWave, MQTT, Rules and Charting OpenHAB, the open source home automation software, far exceeds the capabilities of other home automation systems on the market – but it's not easy to get set up. In fact, it can be downright frustrating. Read More . Note that my code is designed for type B (rotary switch) sockets, though you could easily modify it for DIP switches too.

The most important part of the code is the messageReceived() function, which responds to incoming MQTT commands. In this function, we’re first checking for the major keyword – I chose “switch” and “screen”. In the case of “switch”, we then parse out the channel and plug ID; then check the payload body for the command.


void messageReceived(String topic, String payload, char * bytes, unsigned int length) {
  
  if (topic.indexOf("switch") >=0){
    //switch control, parse out the channel and plug id 
    
    int channel = getValue(topic,'/',3).toInt();
    int plug = getValue(topic,'/',4).toInt();
    
    if(payload == "on"){   
      mySwitch.switchOn(channel, plug);
    }
    else{
      mySwitch.switchOff(channel, plug);
    }
  }
  else if (topic.indexOf("screen") >=0){
    //screen control
    if(payload == "up"){
      screenUp();
    }
    else if(payload == "down"){
      screenDown();
    }
  }
  /* add another else if here to listen for more commands (or just modify the one above if you dont want screen) */
}

By default then, the following MQTT commands work:

livingroom/control/switch/X/Y (where X is channel, and Y is plug ID; with message body on or off)
livingroom/control/screen (with message body up or down)

Use the command line or a GUI MQTT client to test your devices before adding to OpenHAB.

Adding to OpenHAB

As a last step, we just need to create some items for these switches in OpenHAB. I’ve defined the following items for now, but you should be able to figure out how to add more:

/* RF433mHz devices */
Switch CinemaScreen "Screen"  (Cinema) { mqtt=">[broker:livingroom/control/screen:command:ON:down],>[broker:livingroom/control/screen:command:OFF:up]"}
Switch Switch41 "Switch41"  (Cinema) {mqtt=">[broker:livingroom/control/switch/4/1:command:ON:on],>[broker:livingroom/control/switch/4/1:command:OFF:off]"}
Switch Switch42 "Switch42"  (Cinema) {mqtt=">[broker:livingroom/control/switch/4/2:command:ON:on],>[broker:livingroom/control/switch/4/2:command:OFF:off]"}

You should now be able to control your RF devices from OpenHAB! One thing I was pleasantly surprised by was the range – a single node was able to cover most of my house. You can of course add another node, listening to the same channel, which simply repeats the same commands, if you need further coverage.

The only limitation to bear in mind is that the sockets themselves can’t report their status, so if you use the original remote, control the status of the socket may not be accurately reflected within OpenHAB. Stick to using just the OpenHAB interface and you should be fine.

Questions or problems? Ask away in the comments, and I’ll do my best to help. If you’d like to improve on my code, feel free to submit a pull request.

  1. Patrick S.
    January 4, 2017 at 12:06 am

    Awesome article and thanks for getting me started on this project. I wanted to check with you to see if you ran into any issues with being able to receive a message.

    I was able to connect to the WiFi and also to the MQTT broker ok.
    I had to add in a username and password, as my MQTT broker requires them,

    so I declared the 2 constants and changed the following line:

    if (client.connect((char*) clientName.c_str()),mqttuser,mqttPwd)

    After connecting, I cannot for the life of me get the NodeMCU to receive the message.

    I have tested my broker using MQTT.fx, and I can successfully subscribe to and publish to the same topic (I used exactly the same as you have for testing).

    livingroom/control/switch/2/1

    On the NodeMCU, after the "Subscribed to: livingroom/control/#", I cannot get it do anything more.

    Any ideas on where to go, as far as testing, on where the issue may lie?

    Thanks for any help!

    • Patrick S.
      January 4, 2017 at 2:35 pm

      For anyone else experiencing this issue. I did figure out where the issue lies, just not sure how to fix it. Removing authentication from my Mosquitto MQTT broker and then not passing the username and password in the NodeMCU, allowed me to connect and receive messages to the topics and turn the plugs on and off.

      This is, of course, not ideal when your MQTT server is exposed to the outside world for other services I use. So, I will continue to tinker with it and try and locate why the authentication is causing an issue.

      Thanks again for this great tutorial!!

  2. Rob Markowitz
    December 31, 2016 at 4:59 am

    Sorry, I don't have any wedding card spam, just an actual question :). I'm a little unclear on the final steps: I've loaded my sketch for Type C Intertechno (no dip switches or sliders on mine) and modified the script to accommodate just one outlet to start with that I've defined as a,1,1 (Outlet #1 as labeled out of the box and defined by the included remote). You say to test your codes before proceeding, but I'm not figuring how to do that after uploading the sketch to my ESP8266.

    I've also set up a Raspi Zero with OpenHab and Mosquito/MQTT as per your guides and that seems to be working properly according to the test I ran with MQTTFX, but I'm also stymied as to what to with the mqtt_rcswitch.ino sketch after I've modified it. Do I want to upload it to the ESP8266 as well? That would overwrite the Type C Sketch then, wouldn't it? I'm guessing I want to somehow get it on the Raspi instead.

    Any clarification you can provide would be greatly appreciated, I think I have a pretty good grasp of the concepts, but I think I'm getting tripped up by syntax and my lack of experience with this type of project.

    Thanks,
    Rob

    • James Bruce
      December 31, 2016 at 8:36 am

      Once you've got the lines you need from the Type C sketch and figured out how you activate them, you'll need to copy those lines into the mqtt_rcswitch code, and modify the messageReceived function. It's in that function that the codes reside for switching on the rotary switch ones.

      Specifically, ths bit:

      if(payload == "on"){
      mySwitch.switchOn(channel, plug);
      }
      else{
      mySwitch.switchOff(channel, plug);
      }

      change mySwitch.switchOn for whatever code it is you use for your socket (I'm not familiar with the type C codes, but it sounds like you've got them working). The channel and plug number are fetched from the MQTT message.

  3. table-number-cards.com
    November 30, 2016 at 1:57 pm

    How do I best honor a friend who'd not going to be in the bridal party? My bridal party is made up of old friends who I've known for over a decade, and one girl I've gotten closer with over the last year or so won't be in I didn't want to ask her to take it on when we hadn't known each other very long, but I'd love to have her participate in the wedding We both love books more than anything else, so I was wondering about having her do one or more of the readings? I'm not sure who else would do them, to be Most of my friends are taken up in the bridal Thoughts?

Leave a Reply

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