Monday, September 08, 2008

WakeUpTool (!) - Waking up your PC's with Domia Lite or BBSB Network Controller

If you've been reading closely, you'll have discovered an application on my blog for 'Sleeping' PC's on reciept of a configured Domia Lite / BBSB device code or event. Well, for some time, I've been pondering a solution to the other problem - that of 'waking up' PC's according to a Domia Lite command.

Now, you could take the brutal approach, and put a Domia Appliance Module on the power feed for your PC, but this would effectivley 'dump' the machine when the signal was recieved, though it would quite nicely wake (or boot) the machine when turned on, if you have a BIOS that supports power-on boot-up. (good luck with your data integrity on that one)

Here's a more elegant solution:

You can use Wake-on-Lan (WOL) to do this, but in order to do that, you need something that can send the WOL magic packet on reciept of a DLC code. Now, one day, Domia might add this to their controller (after all it's on all the time, and on the network) (hint hint hint domia), but until then, here's a perl script that you can run in the background on a Linux machine or device that will do the same job.

#!/usr/bin/perl -w

use strict;
use IO::Socket;
use Sys::Syslog qw( :DEFAULT setlogsock);

my($sock, $oldmsg, $newmsg, $hisaddr, $hishost, $MAXLEN, $PORTNO);
$MAXLEN = 1024;
$PORTNO = 53003;
my $programname = '';
$ENV{PATH} = "";

$sock = IO::Socket::INET->new(LocalPort => $PORTNO, Proto => 'udp')
or die "socket: $@";

logit('info',"Listening on Port $PORTNO for Domia Lite Messages..");
print "Awaiting UDP messages on port $PORTNO\n";

while ($sock->recv($newmsg, $MAXLEN)) {
my($port, $ipaddr) = sockaddr_in($sock->peername);
#$hishost = gethostbyaddr($ipaddr, AF_INET);
print "Recieved DLC Command `$newmsg'\n";
logit('info',"Recieved DLC Command: $newmsg");

if ($newmsg eq "devicecommand:1a01:")
logit('info',"Waking PC..");
print "waking up PC.\n";
system("/sbin/wakelan -m 0123ABCDEF11");

die "recv: $!";

sub logit {
my ($priority, $msg) = @_;
return 0 unless ($priority =~ /infoerrdebug/);
# $programname is assumed to be a global. Also log the PID
# and to CONSole if there's a problem. Use facility 'user'.
openlog($programname, 'pid,cons', 'user');
syslog($priority, $msg);
return 1;

Once you're up and tested (replace 0123ABCDEF11 with your PC's MAC Address, and correct the DLC code - example above uses A1 ON), you can add this to your boot-up so it runs in the background by appending the line

/wherever/ & 2 >/dev/null

(dont forget the ampersand &, as your box will not complete it's boot up scripts.. like I did)

Now, clearly if you run a 150w PC all the time with this, then it kind-of defeats the point of all this, but some small embedded linux device, like a Router, or Unslung Linksys NSLU2 can do the job just nicely.

Stay tuned for some more postings in Perl, as we build a Home Automation controller out of that handly NSLU2 that takes a whole 2watts of power 8-)