From 214345e0eb6292fc4d5649328a87766a4ff01b69 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Sun, 22 Jan 2012 08:50:17 +0000 Subject: [PATCH] Wake on Lan module from Matthias K. git-svn-id: https://svn.fhem.de/fhem/trunk@1201 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_WOL.pm | 151 ++++++++++++++++++++++++++++++++++++++ fhem/docs/commandref.html | 50 +++++++++++++ fhem/docs/fhem.html | 4 + 3 files changed, 205 insertions(+) create mode 100644 fhem/FHEM/98_WOL.pm diff --git a/fhem/FHEM/98_WOL.pm b/fhem/FHEM/98_WOL.pm new file mode 100644 index 000000000..82c9cc129 --- /dev/null +++ b/fhem/FHEM/98_WOL.pm @@ -0,0 +1,151 @@ +############################################## +# $Id: 99_WOL.pm 1116 2012-01-21 15:01:34Z matthiasklass $ +package main; + +use strict; +use warnings; +use IO::Socket; +use Time::HiRes qw(gettimeofday); + +sub +WOL_Initialize($) +{ + my ($hash) = @_; + + $hash->{SetFn} = "WOL_Set"; + $hash->{DefFn} = "WOL_Define"; + $hash->{UndefFn} = "WOL_Undef"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6"; +} + +################################### +sub +WOL_Set($@) +{ + my ($hash, @a) = @_; + + return "no set value specified" if(int(@a) < 2); + return "Unknown argument $a[1], choose one of refresh on" if($a[1] eq "?"); + + + my $name = shift @a; + my $v = join(" ", @a); + + Log GetLogLevel($name,2), "WOL set $name $v"; + + + + my $mac = $hash->{MAC}; + + if($v eq "on") + { + eval { + #for(my $i = 1; $i <= 3; $i++) { + wake($mac); + #} + }; + if ($@){ + ### catch block + Log GetLogLevel($name,2), "WOL error: $@"; + }; + Log GetLogLevel($name,2), "WOL waking $name ($mac)"; + + } elsif ($v eq "refresh") + { + WOL_GetUpdate($hash); + } else + { + return "unknown argument $v, choose one of refresh, on"; + } + + $hash->{CHANGED}[0] = $v; + $hash->{STATE} = $v; + $hash->{READINGS}{state}{TIME} = TimeNow(); + $hash->{READINGS}{state}{VAL} = $v; + + return undef; +} + +sub +WOL_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + + my $u = "wrong syntax: define WOL MAC_ADRESS IP"; + return $u if(int(@a) < 4); + + $hash->{MAC} = $a[2]; + $hash->{IP} = $a[3]; + $hash->{INTERVAL} = 600; + + InternalTimer(gettimeofday()+$hash->{INTERVAL}, "WOL_GetUpdate", $hash, 0); + return undef; +} + +sub WOL_Undef($$) { + + my ($hash, $arg) = @_; + + RemoveInternalTimer($hash); + return undef; +} + +sub WOL_GetUpdate($) +{ + my ($hash) = @_; + + my $ip = $hash->{IP}; + if (system("ping -q -c 1 $ip > /dev/null") == 0) + { + $hash->{READINGS}{state}{VAL} = "on"; + $hash->{READINGS}{isRunning}{VAL} = "true"; + } else + { + $hash->{READINGS}{state}{VAL} = "off"; + $hash->{READINGS}{isRunning}{VAL} = "false"; + } + $hash->{READINGS}{state}{TIME} = TimeNow(); + $hash->{READINGS}{isRunning}{TIME} = TimeNow(); + + InternalTimer(gettimeofday()+$hash->{INTERVAL}, "WOL_GetUpdate", $hash, 0); +} + +sub wake($) +{ + my ($mac) = @_; + + Log GetLogLevel("WOL",2), "trying to wake $mac"; + + my $response = `/usr/bin/ether-wake $mac`; + Log GetLogLevel("WOL",4), "trying etherwake with response: $response"; + + wol_by_udp($mac); + Log GetLogLevel("WOL",4), "trying direct socket via UDP"; +} + +# method to wake via lan, taken from Net::Wake package +sub wol_by_udp { + my ($mac_addr, $host, $port) = @_; + + # use the discard service if $port not passed in + if (! defined $host) { $host = '255.255.255.255' } + if (! defined $port || $port !~ /^\d+$/ ) { $port = 9 } + + my $sock = new IO::Socket::INET(Proto=>'udp') or die "socket : $!"; + die "Can't create WOL socket" if(!$sock); + + my $ip_addr = inet_aton($host); + my $sock_addr = sockaddr_in($port, $ip_addr); + $mac_addr =~ s/://g; + my $packet = pack('C6H*', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, $mac_addr x 16); + + setsockopt($sock, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!"; + + send($sock, $packet, 0, $sock_addr) or die "send : $!"; + close ($sock); + + return 1; +} + +1; diff --git a/fhem/docs/commandref.html b/fhem/docs/commandref.html index d88a96019..ad034595c 100644 --- a/fhem/docs/commandref.html +++ b/fhem/docs/commandref.html @@ -123,6 +123,7 @@ WS300   WS3600   Weather   + WOL   X10   xxLG7000   @@ -3880,6 +3881,53 @@ A line ending with \ will be concatenated with the next one, so long lines
+ +

WOL

+ +

X10