Lightswitch Replacement
Parts:
PiFace $30,
Rpi Model A $25,
Wifi Adapter $10,
120v to 5vdc adapter $5ish,
Low voltage 2 gange wall box $5
Blank wall plate $2
2x low profile
sanwa arcade buttons $4
This was one of my first pi projects in my home automation endeavor. I wanted something simple and that wasn't too expensive. I decided to go with the PiFace add-on board.
One really important thing I wanted was to be able to control the light switch via the web. I ran into a problem with the webapp though. Every time I opened it up it would reset the piface card. I found it was reinitializing the card every time it opened my cgi script. I then decided I needed a python program that would run on boot that would listen for commands to execute against the piface card. I then came upon Pyro, which came in very handy.
Source for my pyro piface
import Pyro.core
import piface.pfio as cmd
import os
from time import sleep
from sys import exit
from os import fork,chdir,setsid,umask
class Command(Pyro.core.ObjBase):
def __init__(self):
Pyro.core.ObjBase.__init__(self)
def outputStatus(self):
list1=cmd.read_output()
status = '{0:08b}'.format(list1)[::-1]
return status
#output command for piface outputs
def outputCmd(self,pin,value):
cmd.digital_write(pin,value)
return self.outputStatus()
#command to return input statuses
def inputStatus(self):
list1 = cmd.read_input()
status = '{0:08b}'.format(list1)[::-1]
return status
#read cpu temperature
def pitemperature(self):
return open('/sys/class/thermal/thermal_zone0/temp','r').read()
def main():
Pyro.core.initServer()
cmd.init()
daemon = Pyro.core.Daemon()
uri = daemon.connect(Command(),"cmd")
print "cmd port: ", daemon.port
print "cmd uri:", uri
daemon.requestLoop()
if __name__ == "__main__":
try:
pid = fork()
if pid > 0:
exit(0)
except OSError, e:
exit(1)
chdir("/")
setsid()
umask(0)
try:
pid = fork()
if pid > 0:
exit(0)
except OSError, e:
exit(1)
main()
I then have either my button listener script(which runs as a daemon on boot) or the web cgi script. Here's the lightswitch.py daemon code:
import sys
from pymodbus.client.sync import ModbusTcpClient as ModbusClient
from os import fork,chdir,setsid,umask
from sys import exit
from time import sleep
import time
import os
import Pyro.core
def main():
loop=True
#connect to the piface pyro daemon we created earlier
cmd = Pyro.core.getProxyForURI("PYROLOC://localhost:7766/cmd")
time_pushed=0
pushed_1=False
pushed_2=False
longpush_2=False
count=0
client = ModbusClient('ip_address_of_modbus_IO')
client.close()
while loop:
sleep(.05)
status = cmd.outputStatus()
inputstatus = cmd.inputStatus()
#toggle button turn relay 1 on
if inputstatus[0]=='1' and pushed_1 != True:
if status[0]=='0':
cmd.outputCmd(0,1)
else:
cmd.outputCmd(0,0)
pushed_1=True
if inputstatus[0]=='0' and pushed_1:
pushed_1=False
#toggle button turn relay 2 on
if inputstatus[1]=='1' and pushed_2 !=True:
pushed_2=True
longpush_2=False
time_pushed=time.time()
#if both buttons are pressed for 10 second the reboot the pi
while inputstatus[0]=='1' and inputstatus[1]=='1':
sleep(1)
count=count+1
if(count==10):
os.system("sudo reboot")
#button released
if inputstatus[1]=='0' and pushed_2:
#calculate the time the button was pressed to determine what to do
time_taken = time.time()-time_pushed
pushed_2=False
if(time_taken<.5):
if status[1]=='0':
cmd.outputCmd(1,1)
else:
cmd.outputCmd(1,0)
#send command to remote i/o using modbus to turn on some lamps if you hold the button longer than 1/2 second
if (time_taken>.5):
try:
if(client.connect()):
if(client.read_discrete_inputs(200,1).bits[0]==True):
client.write_coil(0,True)
else:
client.write_coil(2,True)
client.close()
except:
e = sys.exc_info()[0]
f=open('error.log','w+')
f.write(e+'\n')
f.close()
time_pushed=0
#turn off light at certain time
hour=time.localtime(time.time())[3]
minute=time.localtime(time.time())[4]
second=time.localtime(time.time())[5]
if(hour==5 and minute == 0 and second == 0 and status[0]=='1'):
cmd.outputCmd(1,0)
#useful daemon-like code:
if __name__ == "__main__":
try:
pid = fork()
if pid > 0:
exit(0)
except OSError, e:
exit(1)
chdir("/")
setsid()
umask(0)
try:
pid = fork()
if pid > 0:
exit(0)
except OSError, e:
exit(1)
main()
I threw in a bit of modbus to talk to some of my remote i/o to control some lamps throughout the room. The web code is similar to the lightswitch code (without listening for button presses of course). It response to AJAX requests to give the statuses of the outputs. If desired I can post the web code later.
Pics
see part one to this series here:
Sprinkler Control