Raspberry Pi Home Automation Project: Remote Power Plug Socket Control

From hacking dash buttons it is a small step towards further home automation. Home automation in the sense of remotely controlling power plug sockets. This way a dash button can be used as an additional light switch.
The ingredients for such a project are

Raspberry Pi (Zero W)
Amazon Dash Button
433 MHz receiver and transmitter
Remote controlled power plug sockets (ideally with DIP switches)

Software

On the Raspberry Pi the following libraries are required at least:

sudo pip3 install rpi-rf     # https://github.com/milaq/rpi-rf
sudo pip3 install scapy-python3   # https://github.com/phaethon/scapy

Setup

433MHz Receiver

Pi (Zero W) 433 MHz Receiver
GND GND
3,3 V 3,3 V
GPIO 27 Data

433MHz Transmitter

Pi (Zero W) 433 MHz Transmitter
GND GND
3,3 V 3,3 V
GPIO 17 Data

Power Plug Sockets

To set up the power plug sockets see their manual. The ones with DIP switches should be preferred over those without. DIP switches allow to precisely select the addresses of the power plug sockets.

Preparations

First the codes to toggle the power plug sockets are required. These can be read using the example script from  the rpi-rf library.

sudo python3 rcv.py

Make a note of the codes for turning the power on and for turning the power off for each power plug socket. The codes have to be adapted in the python script below. Required is also the MAC adress of the Dash Button to be used as an additional light switch.

from scapy.all import *
import http.client, urllib
from rpi_rf import RFDevice

from time import sleep

#A on : 1234567 A off: 9876543

fileLRL="/home/pi/state.txt"

rfdevice = RFDevice(17)
rfdevice.enable_tx()
protocol = 1
pulselength = 350

def readFile(fileName):
  state=0
  try:
    target = open(fileName, 'r')
    state = target.read()
    target.close()
    print("Read toggle state: " + str(state))
  except FileNotFoundError:
    writeFile(fileName, state)
  return state

def writeFile(fileName, state):
  print("Store toggle state: " + str(state))
  target = open(fileName, 'w')
  target.write(str(state))
  target.close()
  return True

def toggleLight():
  state = readFile(fileLRL)
  print("LRL state " + str(state))
  if state == str(0):
    print ("light is currently off, turn it on")
    rfdevice.tx_code(1234567, protocol, pulselength)
    writeFile(fileLRL, 1)
  else:
    print ("light is currently on, turn it off")
    rfdevice.tx_code(9876543, protocol, pulselength)
    writeFile(fileLRL, 0)

def arp_detect(pkt):
  if pkt[ARP].op == 1: # network request
    mac = pkt[ARP].hwsrc
    mac = mac.lower()
    ip = pkt[ARP].psrc

  if mac == 'xx:xx:yy:xx:yy:xx': # dash button
    toggleLight()
    sleep(5)
    return "dash button detected\n"

try:
  print( sniff(prn=arp_detect, filter="arp", store=0))
except KeyboardInterrupt:
  rfdevice.cleanup()
  exit()

This way the dash button can be used as an additional remote control in parallel to the original remote control of the power plug sockets. Although this solution cannot keep up with the original remote control regarding the response time. There are several steps in between which take their time…

Raspberry Pi Zero, dash button, remote power plug socket
Raspberry Pi Zero, dash button, remote power plug socket