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

Score!

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

home
work
home2
out''')
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(email=options.email, passwd=options.passwd):
global voice
try:
voice.login(options.email,options.passwd)
except LoginError:
if input('Login failed. Retry?[Y/n] ').lower() in ('', 'y'):
login(None, None)
else:
sys.exit(0)

try:
action,args = args[0],args[1:]
except IndexError:
print "you need to give a command"
sys.exit(2)

voice = Voice()
login()

register(voice.logout)

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":
voice.phones[0].enable()
voice.phones[1].disable()
voice.phones[2].enable()
voice.phones[3].disable()
elif action == "home2":
voice.phones[0].disable()
voice.phones[1].disable()
voice.phones[2].enable()
voice.phones[3].enable()
elif action == "out":
voice.phones[0].disable()
voice.phones[1].disable()
voice.phones[2].enable()
voice.phones[3].disable()


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

gvforward.py -e ABCdefGHI9876543210@gmail.com -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 "doghouse-sagetv.media":
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":
mpID=0;
break;
case "FR":
mpID=1;
break;
case "Master":
mpID=2;
break;
}
if (mpCommand=="play") {
mpStatus=mpStatus | Math.pow(2,mpID);
} else {
mpStatus=mpStatus & (7-Math.pow(2,mpID));
if (mpStatus==0) {
sTimers.load("SageClientIdleTimer",20*60);
}
}
if (mpStatus!=0) {
sCUDevices.Flags.Item("SageClientIdle").State=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 parseSage.pl script):

// to prevent unneeded throttling, we'll check if sage is currently
// recording or will need to in the next 3 hours
sageRecord=0;
for (i=0;i<4;i++) {
if (mySQLQuery2("sagesched","value","hour",TimeHour()+i)==1) {
sageRecord=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");
HibernateMedia();
}

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.

Thursday, July 30, 2009

XTB On The Way

I finally decided on ordering an XTB to see if it can help with some X10 signal issues in our home. The family room, over time, has moved slowly off the X10 grid for some reason. Even after unplugging a bunch of things, I wasn't able to find anything causing the noise. I've moved some stuff over to UPB, but to me, the cost of UPB (outside of Fry's clearanced modules) is too much to replace all our X10. I don't think I need the XTB-IIR, as I have really good X10 performance everywhere else. Hopefully, the XTB will co-exist with UPB. We'll find out in a few days.

Monday, July 27, 2009

Remote Home Automation

Now that I've linked our two homes across the Internet, I can work on doing some serious automation - with the spare parts in my wiring closet :) Except for one thing - I have to get a 2nd W800. I plan on sprinkling around a few motion sensors and a couple DS10As connected to leaf wetness sensors - to be used as leak detectors. So the W800 is a must have.

I already have an old CM11A connected to the thin client & it interfaces to xPLCM11 for basic lighting control. I will be moving a spare USB rocket launcher over there and strapping a netcam on it for use with xPL Rocket.

Saturday, July 25, 2009

Linking xPL Between Two Homes Over The Internet

As I wrote before, I would like to link xPL messages from our 2nd home. I needed to figure out a way to wrap the UDP xPL messages in TCP and tunnel them through some kind of connection. I decide to use EventGhost's Network Event Sender/Receiver plugins so I wouldn't have to write a separate app.

The first step is to establish a secure connection between the two networks. I chose SSH as I already have a device capable of being an SSH server at our 2nd/remote home. I will establish the SSH connection using Putty from our 1st home.



I'm creating a tunnel that will map port 8888 on the remote SSH server to port 8888 on my local machine. I'll need to click the Add button to enable it. I also checked Remote ports do the same, which will allow devices on the remote network to connect to the remote SSH server's port 8888. To enable this remote forwarding, you may have to configure your SSH server. For example, with OpenSSH, you need to add GatewayPorts yes to the sshd_config file.

Once that's set up, I can establish the SSH connection. On the local machine, I will add the Network Event Receiver plugin, point it to port 8888, set a password and an event prefix. On the remote machine, I will add the Network Event Sender plugin and point it the remote SSH server's port 888 and set a password to match the receiver.


Local EventGhost


Remote EventGhost


Now, in the remote EventGhost, I create a macro that captures all xPL messages and sends them the Network Event Sender.



Finally, on the local EventGhost, I create a Network Event Receiver macro that parses the data received and issues an xPL message with the original contents, but with the local EG as the sender instead of the original sender.




That's all there is to it. Now, I've got remote xPL messages coming across to my home network. You can easily add a remote EG receiver and local EG sender to allow xPL messages to flow in the opposite direction.