Saturday, August 29, 2009

Automating the Dog Feeder

We have an older version of this dog feeder. Programming it always was a chore and after a while, it stopped accurately dispensing food - almost always giving too much. Whenever we use it now, it's just as a single meal dispenser and that makes the programming even more annoying. So this was a great opportunity for automation.

The feeder takes 3 D batteries so I dug out a 5V wall wart from my junk drawer. I opened up the feeder and found the motor that dispenses the food. After using a voltmeter to figure out the polarity, I soldered the wall wart to the motor, routed the cable out and closed up the feeder. The wall wart was then plugged into an appliance module.

The next step was to build an easy to use interface, which was a simple HTML form. The data gets loaded into starCOMUltra, and at the appropriate time, sCU turns on the feeder for about 45 seconds to dispense the food. Since it's a single serve feeder now, the feeder is disabled until programmed again.

Friday, August 28, 2009

New Bullet Camera

I just put up a new bullet camera Wednesday to replace my main front camera, which is an aging 10 year old B&W camera I got from Target. The new camera is a day/night camera with a Sony CCD so it's a marked improvement in resolution & clarity. However, at night time, it's still not as good as the old Target cam even with the help of the front floods. The old camera moved over slightly and is angled toward the opposite direction for better coverage. The new camera is my first "real" camera, as it has a BNC connector and I had to run it over RG6. As I was prepping to run the new RG6, I took some time to clean up the messy wiring from the other cameras. It was definitely something that needed to be done. I also ordered another different day/night cam to replace another old camera and it should come next week. I plan on moving the older camera to a different location.

Tuesday, August 25, 2009


My Craigslist bot script found a Squeezebox MP3 player with the enhanced screen for $20! This is the 3rd Squeezebox deal I got off Craigslist. The first I got several years ago for $35. The 2nd I found for $10, but it had a broken display & IR receiver. However, the folks at SlimDevices GAVE me a free replacement screen & IR receiver. Of course, those guys rock. This latest Squeezebox is replacing my office Rio Receiver and is paired with a ThingFling Altec Lansing SoundBar.

Saturday, August 22, 2009

Google Voice Automation

We've been using Google Voice since it was Grand Central. The one number for life really is a great convenience. I like having it ring all the phones I have when I get a call - so if my cell coverage is weak or I'm running out of minutes, I can just answer a landline. Realistically though, I only want it to ring all the phones that I can answer based on where I am. Recently, I found pygooglevoice, which exposes the Google Voice API to Python. This is exactly what I need - now I can write a script to choose which phones to forward calls to - based on where I am. No sense on forwarding calls there if nobody's there. Also, if my wife's at home but I'm at work, there's no need to bother her by having my calls forwarded home. With our Bluetracker software, the HA system can tell if we're at one of our homes and execute a Python script to forward to the appropriate phones.

A sample script follows, based heavily on the gvoice script included in pygooglevoice:

import sys
from atexit import register
from optparse import OptionParser
from googlevoice import Voice,util
from googlevoice.util import LoginError,input,print_

parser = OptionParser(usage='''gvoice [-e -p ] commands
Where commands are

parser.add_option("-e", "--email", dest="email", default=None,
help="Google Voice Account Email")
parser.add_option("-p", "--password", dest='passwd', default=None,
help='Your account password (prompted if blank)')
options, args = parser.parse_args()

def login(, passwd=options.passwd):
global voice
except LoginError:
if input('Login failed. Retry?[Y/n] ').lower() in ('', 'y'):
login(None, None)

action,args = args[0],args[1:]
except IndexError:
print "you need to give a command"

voice = Voice()


if action == "home":
voice.phones[0].disable() # work
voice.phones[1].enable() # mobile
voice.phones[2].enable() # home
voice.phones[3].disable() # home 2
elif action == "work":
elif action == "home2":
elif action == "out":

You give it three options - your email address, your password and the command (in this case home, home2, work and out): -e -p password work

Friday, August 21, 2009

TV Lineup Changes = Bad For SageTV

TV lineup changes are one of the downsides of a non-TiVo DVR. I have always found TiVo soooo good at updating channel lineups. I haven't been so lucky with SageTV. So rather than deal with a missed recording, I wrote a script to download the latest TV lineup from our cable provider and compare it to the previous day's lineup. If there are any differences, it will fire off an email to me with the changes. That way I know when I have to rescan the lineup for the HDHomeruns and SageTV if SageTV hasn't already done the right thing.

I'd love to publish it, but it's one of those things that I'm afraid could get blocked if too many people are using it and that would backfire on me. I do my best to disguise the user-agent and randomize the time of day the script runs to make it seem less bot-like.

In any case, it took all of 10 minutes to code up in Perl, so maybe this will inspire others to write their own should they feel the need.

Thursday, August 20, 2009

Remove Hidden & Ghost Hardware from XP

Wow, it's been 2 weeks since I've posted. I don't really have any excuse, although my HAI UPB PIM died after less than a year. No warranty, of course, since I got it cheap off eBay. Anyway, I've been cleaning up my HA server today and thought this would be a useful topic.

One very annoying thing I've run into as I'm installing/removing hardware from my server is that I end up with unusable serial ports. For example, I was removing the bluetooth adapter quite often without uninstalling it. As as result, in the Device Manager, I ended up with things like Bluetooth Device (Personal Area Network) #26 and Standard Serial Port over Bluetooth link(COM25). Every time I unplugged the adapter, I lost 2 serial ports and created 2 more when I plugged it back in. This can cause a problem because some software isn't very happy with COM ports over a certain number. I suppose the easiest thing is to make sure to uninstall USB hardware like the bluetooth adapter before unplugging it, but sometimes you forget. In that case, here's a tip to help you uninstall the ghost devices and recover their resources. Thanks to this, I'm back down to COM11 instead of COM26 :)

Thursday, August 6, 2009

My Take on SageTV Server Power Savings

I've been working off & on with the media server's power management. Since we have a DirecTiVo, most of our live viewing is done on that along with some recording, so the Sage server doesn't need to be online unless we're watching some recorded content from it or it's recording. So I can really keep this thing powered down 70% of the time, and almost 90% of the time since it's summer. So I spent some more time figuring out when SageTV is being used and came up with this write up. My solution, like our home automation system, integrates a lot of separate pieces to get things just right.

Let's get to it. First off, as in my previous post, we use the exported sage schedule. Grab this Perl file and save it as a .pl file. The script is fairly simple. It takes a command line argument, the path to the schedule file, and figures out what hours of the day SageTV is recording. It puts that info into a mySQL database called mystuff with username and password as the login credentials. You don't have to use mySQL, that's just what I use to pass data between different components of our system.

The next step involves our xPL Plugin for SageTV and your favorite xPL scripting engine. The engine we use is our homebrew xPL sCU - an xPL bridge to starCOMUltra, the HA software we use. With the xPL plugin for Sage, you can query it for which clients & extenders are currently playing media (or you can rely on the hidden feature where the plugin will check the playing status whenever it receives any xPL message - it will send an update only if the status has changed). In xPL sCU, I've scripted up logic for processing those updates:

function xPLReceived(e,schema,source,dest,msgtype) {
switch(schema.toLowerCase()) {
case "":
if (schema.toLowerCase()=="media.mptrnspt") {
mpName=e.XplMsg.GetParam(1, "mp");
mpCommand=e.XplMsg.GetParam(1, "command");
mpStatus = mySQLQuery("locals","value","SagePlayerStatus");
switch (mpName) {
case "LR":
case "FR":
case "Master":
if (mpCommand=="play") {
mpStatus=mpStatus | Math.pow(2,mpID);
} else {
mpStatus=mpStatus & (7-Math.pow(2,mpID));
if (mpStatus==0) {
if (mpStatus!=0) {

What the snippet does is process xPL messages about the media players' state. If any player is in use, it clears the SageClientIdle flag in starCOMUltra. If a player becomes idle, it checks to see if all the players are idle and starts a 20 minute timer. Elsewhere in the code (not shown) is if that timer expires and all players are still idle, the SageClientIdle flag is set. You can choose your own idle timer length.

Now we have the player and recording status, but wait, what if I'm using the server for some other purpose? The only way I'd be using the server is via remote desktop, so i set up an EventGhost macro on the Sage server to send xPL messages when an RDP session is initiated or closed. A timeout period after a session is closed will determine if that aspect of the server is idle.

Finally, we have all the pieces in the place. In starCOMUltra, where everything comes together, we have this piece of code that runs hourly (along with the script):

// to prevent unneeded throttling, we'll check if sage is currently
// recording or will need to in the next 3 hours
for (i=0;i<4;i++) {
if (mySQLQuery2("sagesched","value","hour",TimeHour()+i)==1) {
// check if media server is awake and no RDP sessions open and no recordings
// for the next 3 hours and no players in use - then 10 after the hour
// we'll put the server to sleep
if (mySQLQuery("locals","value","MediaAwake")==1 && \
mySQLQuery("locals","value","mediaRDP")==0 && \
Devices.Flags.Item("SageClientIdle").State==1) { \
sageRecord==0 && mins==10) {
LogDevice("# stop sage server");

To wake up the server manually, all our viewing areas have a 3Com Audrey touchscreen nearby. It has a screen to wake up the media server which takes a few minutes. Not perfect, but like I said, we use the DirecTivo for most of the on demand TV watching. Plus, most of the time, we watch recordings during prime time and the server is already on.

"That's all!" ;) Obviously, this is very specific to our setup and situation, but hopefully there are ideas and code bits that may be useful to you.

Tuesday, August 4, 2009

Remote W800 Deployed & Remote System Summary

I just installed the new W800 at our other house. In keeping with my tradition of cheapness, I ordered the bare $49 W800 instead of the $75 kit. I made my own power adapter from a leftover 9V wall wart and a 3.5mm mono jack (tip positive). I had 3 different 9V wall warts to choose from in my junk box, one output 8.7V, one 10.5V, and the third put out 11.5V. The W800 would only work with the highest output wall wart, which jives with the output from power supply from the first W800. Instead of the kit antenna, I connected the W800 to a set of leftover TV rabbit ears. I'm not looking for long distance reception as it's a small place. Finally, I had an extra serial cable in a spare parts bin.

I'm using xPLW800 and it works perfectly. I installed a few devices from my leftovers - 2 DS10A's as leak detectors and a few Hawkeye motion detectors. The motion sensors, combined with the Bluetooth tracking, will allow the system to track occupancy and execute the security lighting scheme if we're not around.

So far, the remote thin client is loaded up with:
* CM11A on a USB-serial adapter, using xPLCM11 for lighting/device control
* W800 on COM1, using xPLW800 for occupancy, dusk/dawn & leak detectors
* xPL Rocket for remote pan/tilt control of the USB rocket launcher & AirLink netcam wire-tied to it
* BlueTracker for occupancy detection
* EventGhost with xPL Plugin for all automation logic

With those apps running, there's still about 190MB of RAM free after I did the 512MB upgrade. CPU utilization is low, typically around 5-10% and briefly jumping to about 20-25% when an X10 command is issued. I can probably add a couple more small apps without killing the system.

The thin client is turning out to be the perfect device for our application. It is slow, but we don't interact with it at all, unlike our main home's automation server. It has low power consumption (10-12W), solid state disk reliablity and auto-powers on after an outage. I thought about putting it on a UPS, but since we won't be at house very often, I'm wary of leaving a UPS there. I've had one UPS burn up after several months and 2 others ended up with cracked and leaking batteries.

I've been very pleased with EventGhost as the heart of the system. It's lightweight in memory and CPU, has many useful plugins (Network Sender & Receiver are key for me) and has tons of flexibility with integrated Python scripting. It wouldn't be very useful to me if it weren't for the great xPL plugin I wrote ;)

Saturday, August 1, 2009

XTB Update

I plugged in the XTB and plugged into it the TW523 from my TimeCommander+, and now I've got solid X10 to the dead zone in the family room. Something was completely killing the family room, but now all is good. I haven't noticed any odd things when there's UPB on the power lines. Thumbs up for a great product.