";
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);
+ my $name = shift @a;
+ my $type = shift @a;
+ my $mac = shift @a;
+ my $ip = shift @a;
+ my $mode = shift @a;
+ my $repeat = shift @a;
+
+ $repeat = "000" if (!defined $repeat);
+ $mode = "BOTH" if (!defined $mode);
+
+ return "invalid MAC<$mac> - use HH:HH:HH:HH:HH"
+ if(!($mac =~ m/^([0-9a-f]{2}([:-]|$)){6}$/i ));
+
+ return "invalid IP<$ip> - use ddd.ddd.ddd.ddd"
+ if(!($ip =~ m/^([0-9]{1,3}([.-]|$)){4}$/i ));
+
+ return "invalid mode<$mode> - use EW|UDP|BOTH"
+ if(!($mode =~ m/^(BOTH|EW|UDP)$/));
+
+ return "invalid repeat<$repeat> - use 999"
+ if(!($repeat =~ m/^[0-9]{3,3}$/i));
+
+ $hash->{NAME} = $name;
+ $hash->{MAC} = $mac;
+ $hash->{IP} = $ip;
+ $hash->{REPEAT} = $repeat;
+ $hash->{MODE} = $mode;
+
+ $hash->{INTERVAL} = AttrVal($hash->{NAME}, "interval", 900);
+
+ RemoveInternalTimer($hash);
+ InternalTimer(gettimeofday()+5, "WOL_UpdateReadings", $hash, 0);
+ InternalTimer(gettimeofday()+30,"WOL_GetUpdate", $hash, 0);
+
+ readingsSingleUpdate($hash, "packet_via_EW", "none",0);
+ readingsSingleUpdate($hash, "packet_via_UDP", "none",0);
return undef;
}
-
+#
+#
+#
sub WOL_Undef($$) {
my ($hash, $arg) = @_;
@@ -95,123 +130,182 @@ sub WOL_Undef($$) {
RemoveInternalTimer($hash);
return undef;
}
+#
+#
+#
+sub WOL_UpdateReadings($)
+{
+ my ($hash) = @_;
+ $hash->{INTERVAL} = AttrVal($hash->{NAME}, "interval", 900);
+ my $ip = $hash->{IP};
+
+ readingsBeginUpdate ($hash);
+
+ if (`ping -c 1 -w 2 $ip` =~ m/100%/) {
+ readingsBulkUpdate ($hash, "isRunning", "false");
+ } else {
+ readingsBulkUpdate ($hash, "isRunning", "true");
+ }
+
+ readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
+ InternalTimer(gettimeofday()+$hash->{INTERVAL}, "WOL_UpdateReadings", $hash, 0);
+}
+#
+#
+#
sub WOL_GetUpdate($)
{
my ($hash) = @_;
-
- my $ip = $hash->{IP};
- #if (system("ping -q -c 1 $ip > /dev/null") == 0)
- ####
- #changed 2013-07-27 by UliM
- #based on Thread http://forum.fhem.de/index.php?t=msg&th=11823&goto=69801&rid=86#msg_69801
- #if (`ping -c 1 $ip` =~ m/100/)
- if (`ping -c 1 -w 1 $ip` =~ m/100%/)
- {
- $hash->{READINGS}{state}{VAL} = "off";
- $hash->{READINGS}{isRunning}{VAL} = "false";
- } else
- {
- $hash->{READINGS}{state}{VAL} = "on";
- $hash->{READINGS}{isRunning}{VAL} = "true";
+
+ if ($hash->{STATE} eq "on") {
+ wake($hash);
}
- $hash->{READINGS}{state}{TIME} = TimeNow();
- $hash->{READINGS}{isRunning}{TIME} = TimeNow();
-
- InternalTimer(gettimeofday()+$hash->{INTERVAL}, "WOL_GetUpdate", $hash, 0);
-}
-sub wake
+ if ($hash->{REPEAT} > 0 && $hash->{STATE} eq "on" ) {
+ InternalTimer(gettimeofday()+$hash->{REPEAT}, "WOL_GetUpdate", $hash, 0);
+ }
+}
+#
+#
+#
+sub wake($)
{
- my ($hash, $logLevel) = @_;
- my $mac = $hash->{MAC};
-
- Log $logLevel, "trying to wake $mac";
+ my ($hash) = @_;
+ my $name = $hash->{NAME};
+ my $mac = $hash->{MAC};
+ my $host = $hash->{IP};
- my $response = `/usr/bin/ether-wake $mac`;
- Log $logLevel, "trying etherwake with response: $response";
+ readingsBeginUpdate ($hash);
- wol_by_udp($mac);
- Log $logLevel, "trying direct socket via UDP";
+ Log3 $hash, 3, "WOL keeping $name with MAC $mac IP $host busy";
+
+ if ($hash->{MODE} eq "BOTH" || $hash->{MODE} eq "EW" ) {
+ wol_by_ew ($mac);
+ readingsBulkUpdate ($hash, "packet_via_EW", $mac);
+ }
+ if ($hash->{MODE} eq "BOTH" || $hash->{MODE} eq "UDP" ) {
+ wol_by_udp ($hash, $mac, $host);
+ readingsBulkUpdate ($hash, "packet_via_UDP", $host);
+ }
+ readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
}
-# method to wake via lan, taken from Net::Wake package
+#
+#
+# method to wakevia lan, taken from Net::Wake package
sub wol_by_udp {
- my ($mac_addr, $host, $port) = @_;
+ my ($hash, $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);
+ if(!$sock) {
+ Log3 $hash, 1, "Can't create WOL socket";
+ return 1;
+ }
+
+ 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);
+ $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;
}
+#
+#
+# method to wakevia ether-wake
+sub wol_by_ew {
+ my ($mac) = @_;
+
+ my $response = `/usr/bin/ether-wake $mac`;
+
+ return 1;
+}
1;
+
=pod
=begin html
WOL
+
+Defines a WOL device via its MAC and IP address.
+
+when sending the on command to a WOL device it wakes up the dependent device by sending a magic packet. When running in repeat mode the magic paket ist sent every n seconds to the device.
+So, for example a Buffalo NAS can be kept awake.
Define
- define <name> WOL <MAC> <IP>
- <unitcode>
+ define <name> WOL <MAC> <IP> [<mode> [<repeat>]]
- Defines a WOL device via its MAC and IP address.
+
+ - MAC
+ - MAC-Adress of the host
+ - IP
+ - IP-Adress of the host (or broadcast address of the local network if IP of the host is unknown)
+ - mode [EW|UDP]
+ - EW: wakeup by usr/bin/ether-wake
+ - UDP: wakeup by an implementation like Net::Wake(CPAN)
+
+
- Example:
+ Examples:
- define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24
+ define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 switching only one time
+ define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW by ether-wake(linux command)
+ define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH by both methods
+ define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 in repeat modeusr/bin/ether-wake in repeatmode
- Notes:
+
+
+ Notes:
- - Module uses
ether-wake
on FritzBoxes.
- - For other computers the WOL implementation of Net::Wake is used
+ Not every hardware is able to wake up other devices by default. Oftenly firewalls filter magic packets. Switch them first off.
+ You may need a packet sniffer to check some malfunktion.
+ With this module you get two methods to do the job: see the mode parameter.
Set
- set <name> <value>
+ set <name> <value>
where value
is one of:
- refresh # checks whether the computer is currently running
- on # sends a magic packet to the defined MAC address
+ refresh # checks(by ping) whether the device is currently running
+ on # sends a magic packet to the defined MAC address
+ off # stops sending magic packets and sends the shutdownCmd(see attributes)
- Examples:
+ Examples:
set computer1 on
+ set computer1 off
set computer1 refresh
- Attributes
+ Attributes
- attr <name> shutdownCmd <string>
-
Custom command executed to shutdown a remote machine, i.e. sh /path/to/some/shell/script.sh
+ attr <name> shutdownCmd <string>
+
Custom command executed to shutdown a remote machine, i.e. sh /path/to/some/shell/script.sh
+ attr <name> interval <seconds>
+
defines the time between two checks by a ping if state of <name> is on
=end html
-=cut
+=cut
\ No newline at end of file