Tuesday, December 9, 2014

Using CherryPy for interprocess Communication Part 3

Part 1 is here <link>, and part 2 is here <link>.

I've been devoting my project time to the weather station, and completely forgot about finishing my testing of using HTTP to communicate between processes.  It's time to finish the experiment and actually implement it for the various processes I have running on the Pi.  As I mentioned before, I want to do this so I can move any of the processes to a different machine when I finally outgrow the single Raspberry PI.  No, I'm not changing machines, I'm going to add others to the collection.

I started with the code that controls the Wemo light switches I have and let it run for a while to make sure there wasn't something weird going to pop up; it didn't.  So now is the time to make corresponding changes to the code that sends signals to control the lights.  Currently there are two places I do this: a process that runs and handles scheduled events around the house and the web interface I use to manually control and look at things.  I'll start with the event controller since it's the easiest piece of code.

Basically, it's just a matter of sending an HTML request to the address and port number I assigned to the Wemo code.  I use different port numbers so I can have multiple addresses on a single machine.  This way, the  regular web server watches on port 80 like all the web sites out there, and the control processes watch on whatever port I decided to put them on.  To do this and maintain versatility, I put the address in my .houserc file and read it when the process first comes up.  Here's the entry I have:

"wemocontrol":{
"ipAddress":"192.168.0.205",
"port": 51001},

I just read the file using the code I already posted here <link> and set the Cherry Pi server to listen to it.  Now I need to have some code to send to it.  Here's the code fragment I came up with:

#! /usr/bin/python
import datetime
import time
import urllib2
import BaseHTTPServer
import os, sys
lib_path = os.path.abspath('../house')
sys.path.append(lib_path)
from houseutils import lprint, getHouseValues, timer, checkTimer

def openSite(Url):
 #print Url
 try:
  webHandle = urllib2.urlopen(Url, timeout=5) #if it doesn't answer in 5 seconds, it won't
 except urllib2.HTTPError, e:
  errorDesc = BaseHTTPServer.BaseHTTPRequestHandler.responses[e.code][0]
  print "Error: cannot retrieve URL: " + str(e.code) + ": " + errorDesc
  raise
 except urllib2.URLError, e:
  print "Error: cannot retrieve URL: " + e.reason[1]
  raise
 except urllib2.HTTPError as e:
  print e.code
  print e.read()
  raise
 except:  #I kept getting strange errors when I was first testing it
  e = sys.exc_info()[0]
  print ("Odd Error: %s" % e )
  raise
 return webHandle

def talktoWemo(ip, command):
 website = openSite("HTTP://" + ip + '/' + command)
 # now read the status that came back from it
 websiteHtml = website.read()
 # After getting the status from the little web server,
 # strip off the trailing cr,lf
 # and separate the values into a list that can
 # be used to tell what is going on
 return websiteHtml
    
# Get the ip address and port number you want to use
# from the houserc file
ipAddress=getHouseValues()["wemocontrol"]["ipAddress"]
port = getHouseValues()["wemocontrol"]["port"]
wemoController = ipAddress + ":" + str(port)
print(talktoWemo(wemoController, "status"))

print(talktoWemo (wemoController, "pCommand?command=patioToggle"))

Well, it's actually more than a fragment, This code will actually control my patio light.  Each time I run it, it will toggle the switch.  It turned out to be pretty simple when done in python, I just used the normal facilities for reading a web site.  In there are also examples of how I read the address and port number from the .houserc file, and how I handle possible errors in the HTTP request.  I came up with that huge set of error conditions as I was learning how to send and receive HTTP; there's a lot that can go wrong and I hated having to look up the errors each time I messed something up.

Now I need to understand how to do the same thing from php so I can command it with a request over the internet.  I guess while I'm in there I'll add some code to read the .houserc file; here's how I send the HTML request to the Wemo control software:

function ipControl($whichOne,$command){
    echo "<br />";
    echo "URL will be: $whichOne/$command";
    $response = file_get_contents("http://$whichOne/$command");
    return(true);

};

This is how I read the .houserc file to get the address I assigned it:

$config = file_get_contents("/home/pi/.houserc");

Then in the case statement for controlling the lights I decode the JSON request and grab the address and port number I put in there.

case "lights":
    $wemoIp = json_decode($config,true)["wemocontrol"]["ipAddress"];
    $wemoPort = json_decode($config,true)["wemocontrol"]["port"];
    $c = $commandParts[1];
    ipControl("$wemoIp:$wemoPort", "pCommand?command=$c");
    break;

This set of changes is merged into my php script that handles web commands, 'command.php'.  Yes, I managed to get it into github so you can grab the entire thing from there and see how it fits together.
The file is in the 'wwwsrc' directory and here's a link to the page <link>.

The very last thing is to include the fragment above into the scheduled event process.  This separate process handles events like: turn the outside lights on at 7PM; turn them off at 10PM, shut the pool motor off in case I forget, etc.  I haven't talked about this process much previously because it had several things in it that I didn't want to put on the web.  When I moved my various keys and such into the .houserc file, that problem disappeared, so this file has the changes above added to it and is called 'events.py' and is in the directory 'house' in the github page above.

So, one set of controls is done.  I'll have to visit each of the others over time and make similar changes to them, but I won't be limited to one machine anymore.  To move a process to another machine, just change the address in the .houserc file; HTTP interactions don't care that the process is on another machine.

7 comments:

  1. I have an issue with two of my three WEMO switches. Both are located on outside walls. Overnight it got down to 35 degrees and when I looked at my wemocontroller output they had stopped reporting. They still work manually. The third switch which is located on an inside wall continues to report just fine. Now another interesitng point is that the outside wall swiches are using new firmware and the inside switch has an older version of the code. I'm wondering if you have seen this behaviour?

    ReplyDelete
  2. Update: The outside temperature has climbed to 41 degrees and both switches are now working. I think this is a temperature range problem with the switches and not a firmware issue.

    ReplyDelete
    Replies
    1. I haven't seen that problem. I have two of them on outside walls, but it doesn't get that cold here very often. Go get some spray foam and drill a hole in the box, and spray it behind the box. If you fill the cavity behind it with spray foam it may start working at lower temperatures.

      The switches run a little warm, so a little insulation to hold in the heat may be enough.

      Delete
  3. Great idea. That might just do the trick.
    Thanks.

    ReplyDelete
  4. Dave:
    I just purchased one of Belkin's latest wall warts. It's called the Insight switch. You may want to take a closer look at it. Like the IRIS it allows one to monitor current flow. What is more it actually calculates the cost per hour of the energy use. Best of all it's WIFI, so unlike the IRIS there is no big amount of additional software to get it going. I have a bunch more work to do on it to get the scheduling stuff in it and the data out but I think I will be going to more of these rather than more IRIS switches. Having most on WIFI and the use of JSON makes life a lot easier.

    Glenn

    ReplyDelete
    Replies
    1. I've seen the insight switches several times and they look like nice devices, but I'm not a big fan of using wifi if you want to monitor something 24/7. At my place an ethernet problem comes up at least once a day, and sometimes much more often. I've gotten much better results over time with the packet networks.

      Delete
  5. My use for them is somewhat different. I have several devices that are seasonally adjusted. In winter I have barn heaters (electrical) and in summers I have fans in the barn that need to be controlled. I see a much better use of these WIFI based units for these applications vs the IRIS switches. I'll be interested to see their 24/7 performance but I suspect they will work just fine. After all I've had WIFI routers working between the barn and the house for the last 3 years without any problems. I have been using a temperature and humidity monitor out there that is ethernet based all that time. The only Ethernet problems I have on my network tend to be caused by my ISP. They can be very flaky...... Once I get the CISCO 3825 up and running it will be most interesting to see how the traffic flows over a 24 hour period.

    ReplyDelete