mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-03-03 16:56:54 +00:00
98_WOL.pm: Removed dependency on Twilight Module, German commandref, ...
git-svn-id: https://svn.fhem.de/fhem/trunk@18573 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
63292badaa
commit
984bd39408
@ -1,6 +1,8 @@
|
||||
# $Id$
|
||||
# erweitert um die Funktion nas_control Dietmar Ortmann $
|
||||
#
|
||||
# Maintenance since 2019 KernSani - Thanks Dietmar for all you did for FHEM, RIP
|
||||
#
|
||||
# This file is part of fhem.
|
||||
#
|
||||
# Fhem is free software: you can redistribute it and/or modify
|
||||
@ -16,6 +18,16 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with fhem. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
#============================================================================
|
||||
# Changelog:
|
||||
# 2019-02-10, v1.03: Fixed check for invalid broadcast address
|
||||
# 2019-02-07, v1.02: First quick revision of commandref
|
||||
# Added German commandref
|
||||
# Removed textboxes for set commands
|
||||
# 2019-02-07, v1.01: Removed dependency on Twilight Module
|
||||
#
|
||||
#
|
||||
##############################################################################
|
||||
package main;
|
||||
|
||||
@ -25,338 +37,343 @@ use IO::Socket;
|
||||
use Blocking;
|
||||
use Time::HiRes qw(gettimeofday);
|
||||
|
||||
my $version = "1.03";
|
||||
|
||||
################################################################################
|
||||
sub WOL_Initialize($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
if(!$modules{Twilight}{LOADED} && -f "$attr{global}{modpath}/FHEM/59_Twilight.pm") {
|
||||
my $ret = CommandReload(undef, "59_Twilight");
|
||||
Log3 undef, 1, $ret if($ret);
|
||||
}
|
||||
my ($hash) = @_;
|
||||
|
||||
$hash->{SetFn} = "WOL_Set";
|
||||
$hash->{DefFn} = "WOL_Define";
|
||||
$hash->{UndefFn} = "WOL_Undef";
|
||||
$hash->{AttrFn} = "WOL_Attr";
|
||||
$hash->{AttrList} = "interval shutdownCmd sysCmd sysInterface useUdpBroadcast ".
|
||||
$readingFnAttributes;
|
||||
$hash->{SetFn} = "WOL_Set";
|
||||
$hash->{DefFn} = "WOL_Define";
|
||||
$hash->{UndefFn} = "WOL_Undef";
|
||||
$hash->{AttrFn} = "WOL_Attr";
|
||||
$hash->{AttrList} = "interval shutdownCmd sysCmd sysInterface useUdpBroadcast " . $readingFnAttributes;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_Set($@) {
|
||||
my ($hash, @a) = @_;
|
||||
return "no set value specified" if(int(@a) < 2);
|
||||
return "Unknown argument $a[1], choose one of on off refresh" if($a[1] eq "?");
|
||||
|
||||
my $name = shift @a;
|
||||
my $v = join(" ", @a);
|
||||
my ( $hash, @a ) = @_;
|
||||
return "no set value specified" if ( int(@a) < 2 );
|
||||
return "Unknown argument $a[1], choose one of on:noArg off:noArg refresh:noArg" if ( $a[1] eq "?" );
|
||||
|
||||
Log3 $hash, 3, "[$name] set $name $v";
|
||||
|
||||
if ($v eq "on") {
|
||||
readingsSingleUpdate($hash, "active", $v, 1);
|
||||
Log3 $hash, 3, "[$name] waking $name with MAC $hash->{MAC} IP $hash->{IP} ";
|
||||
WOL_GetUpdate( { 'HASH' => $hash } );
|
||||
} elsif ($v eq "off") {
|
||||
readingsSingleUpdate($hash, "active", $v, 1);
|
||||
my $cmd = AttrVal($name, "shutdownCmd", "");
|
||||
if ($cmd eq "") {
|
||||
Log3 $hash, 3, "[$name] no shutdown command given (see shutdownCmd attribute)!";
|
||||
}
|
||||
$cmd = SemicolonEscape($cmd);
|
||||
Log3 $hash, 3, "[$name] shutdownCmd: $cmd executed";
|
||||
my $ret = AnalyzeCommandChain(undef, $cmd);
|
||||
Log3 ($hash, 3, "[$name]" . $ret) if($ret);
|
||||
} elsif ($v eq "refresh") {
|
||||
WOL_UpdateReadings( { 'HASH' => $hash } );
|
||||
}
|
||||
my $name = shift @a;
|
||||
my $v = join( " ", @a );
|
||||
|
||||
return undef;
|
||||
Log3 $hash, 3, "[$name] set $name $v";
|
||||
|
||||
if ( $v eq "on" ) {
|
||||
readingsSingleUpdate( $hash, "active", $v, 1 );
|
||||
Log3 $hash, 3, "[$name] waking $name with MAC $hash->{MAC} IP $hash->{IP} ";
|
||||
WOL_GetUpdate($hash);
|
||||
}
|
||||
elsif ( $v eq "off" ) {
|
||||
readingsSingleUpdate( $hash, "active", $v, 1 );
|
||||
my $cmd = AttrVal( $name, "shutdownCmd", "" );
|
||||
if ( $cmd eq "" ) {
|
||||
Log3 $hash, 3, "[$name] no shutdown command given (see shutdownCmd attribute)!";
|
||||
}
|
||||
$cmd = SemicolonEscape($cmd);
|
||||
Log3 $hash, 3, "[$name] shutdownCmd: $cmd executed";
|
||||
my $ret = AnalyzeCommandChain( undef, $cmd );
|
||||
Log3( $hash, 3, "[$name]" . $ret ) if ($ret);
|
||||
}
|
||||
elsif ( $v eq "refresh" ) {
|
||||
WOL_UpdateReadings($hash);
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_Define($$) {
|
||||
my ($hash, $def) = @_;
|
||||
my @a = split("[ \t][ \t]*", $def);
|
||||
my ( $hash, $def ) = @_;
|
||||
my @a = split( "[ \t][ \t]*", $def );
|
||||
|
||||
my $u = "wrong syntax: define <name> WOL <MAC_ADRESS> <IP> <mode> <repeat> ";
|
||||
return $u if(int(@a) < 4);
|
||||
my $name = shift @a;
|
||||
my $type = shift @a;
|
||||
my $mac = shift @a;
|
||||
my $ip = shift @a;
|
||||
my $mode = shift @a;
|
||||
my $repeat = shift @a;
|
||||
my $u = "wrong syntax: define <name> WOL <MAC_ADRESS> <IP> <mode> <repeat> ";
|
||||
return $u if ( int(@a) < 4 );
|
||||
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);
|
||||
$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 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 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 mode<$mode> - use EW|UDP|BOTH"
|
||||
if ( !( $mode =~ m/^(BOTH|EW|UDP)$/ ) );
|
||||
|
||||
return "invalid repeat<$repeat> - use 999"
|
||||
if(!($repeat =~ m/^[0-9]{1,3}$/i));
|
||||
return "invalid repeat<$repeat> - use 999"
|
||||
if ( !( $repeat =~ m/^[0-9]{1,3}$/i ) );
|
||||
|
||||
$hash->{NAME} = $name;
|
||||
$hash->{MAC} = $mac;
|
||||
$hash->{IP} = $ip;
|
||||
$hash->{REPEAT} = $repeat;
|
||||
$hash->{MODE} = $mode;
|
||||
|
||||
delete $hash->{helper}{RUNNING_PID};
|
||||
$hash->{NAME} = $name;
|
||||
$hash->{MAC} = $mac;
|
||||
$hash->{IP} = $ip;
|
||||
$hash->{REPEAT} = $repeat;
|
||||
$hash->{MODE} = $mode;
|
||||
|
||||
readingsSingleUpdate($hash, "packet_via_EW", "none",0);
|
||||
readingsSingleUpdate($hash, "packet_via_UDP", "none",0);
|
||||
readingsSingleUpdate($hash, "state", "none",0);
|
||||
readingsSingleUpdate($hash, "active", "off", 0);
|
||||
$hash->{VERSION} = $version;
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
WOL_SetNextTimer($hash, 10);
|
||||
return undef;
|
||||
delete $hash->{helper}{RUNNING_PID};
|
||||
|
||||
readingsSingleUpdate( $hash, "packet_via_EW", "none", 0 );
|
||||
readingsSingleUpdate( $hash, "packet_via_UDP", "none", 0 );
|
||||
readingsSingleUpdate( $hash, "state", "none", 0 );
|
||||
readingsSingleUpdate( $hash, "active", "off", 0 );
|
||||
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
WOL_SetNextTimer( $hash, 10 );
|
||||
return undef;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_Undef($$) {
|
||||
|
||||
my ($hash, $arg) = @_;
|
||||
my ( $hash, $arg ) = @_;
|
||||
|
||||
myRemoveInternalTimer("ping", $hash);
|
||||
myRemoveInternalTimer("wake", $hash);
|
||||
BlockingKill($hash->{helper}{RUNNING_PID}) if(defined($hash->{helper}{RUNNING_PID}));
|
||||
return undef;
|
||||
RemoveInternalTimer($hash);
|
||||
BlockingKill( $hash->{helper}{RUNNING_PID} ) if ( defined( $hash->{helper}{RUNNING_PID} ) );
|
||||
return undef;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_UpdateReadings($) {
|
||||
my ($myHash) = @_;
|
||||
|
||||
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
|
||||
return if (!defined($hash));
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $timeout = 4;
|
||||
my $arg = $hash->{NAME}."|".$hash->{IP};
|
||||
my $blockingFn = "WOL_Ping";
|
||||
my $finishFn = "WOL_PingDone";
|
||||
my $abortFn = "WOL_PingAbort";
|
||||
|
||||
if (!(exists($hash->{helper}{RUNNING_PID}))) {
|
||||
$hash->{helper}{RUNNING_PID} =
|
||||
BlockingCall($blockingFn, $arg, $finishFn, $timeout, $abortFn, $hash);
|
||||
} else {
|
||||
Log3 $hash, 3, "[$name] Blocking Call running no new started";
|
||||
WOL_SetNextTimer($hash);
|
||||
}
|
||||
my ($hash) = @_;
|
||||
|
||||
return if ( !defined($hash) );
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
my $timeout = 4;
|
||||
my $arg = $hash->{NAME} . "|" . $hash->{IP};
|
||||
my $blockingFn = "WOL_Ping";
|
||||
my $finishFn = "WOL_PingDone";
|
||||
my $abortFn = "WOL_PingAbort";
|
||||
|
||||
if ( !( exists( $hash->{helper}{RUNNING_PID} ) ) ) {
|
||||
$hash->{helper}{RUNNING_PID} =
|
||||
BlockingCall( $blockingFn, $arg, $finishFn, $timeout, $abortFn, $hash );
|
||||
}
|
||||
else {
|
||||
Log3 $hash, 3, "[$name] Blocking Call running no new started";
|
||||
WOL_SetNextTimer($hash);
|
||||
}
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_Ping($){
|
||||
my ($string) = @_;
|
||||
my ($name, $ip) = split("\\|", $string);
|
||||
my $hash = $defs{$name};
|
||||
|
||||
my $ping = "ping -c 1 -w 2 $ip";
|
||||
Log3 $hash, 4, "[$name] executing: $ping";
|
||||
my $res = qx ($ping);
|
||||
$res = "" if (!defined($res));
|
||||
|
||||
Log3 $hash, 4, "[$name] result executing ping: $res";
|
||||
|
||||
my $erreichbar = !($res =~ m/100%/);
|
||||
my $return = "$name|$erreichbar";
|
||||
return $return;
|
||||
sub WOL_Ping($) {
|
||||
my ($string) = @_;
|
||||
my ( $name, $ip ) = split( "\\|", $string );
|
||||
my $hash = $defs{$name};
|
||||
|
||||
my $ping = "ping -c 1 -w 2 $ip";
|
||||
Log3 $hash, 4, "[$name] executing: $ping";
|
||||
my $res = qx ($ping);
|
||||
$res = "" if ( !defined($res) );
|
||||
|
||||
Log3 $hash, 4, "[$name] result executing ping: $res";
|
||||
|
||||
my $erreichbar = !( $res =~ m/100%/ );
|
||||
my $return = "$name|$erreichbar";
|
||||
return $return;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_PingDone($){
|
||||
my ($string) = @_;
|
||||
my ($name, $erreichbar) = split("\\|", $string);
|
||||
my $hash = $defs{$name};
|
||||
|
||||
readingsBeginUpdate ($hash);
|
||||
sub WOL_PingDone($) {
|
||||
my ($string) = @_;
|
||||
my ( $name, $erreichbar ) = split( "\\|", $string );
|
||||
my $hash = $defs{$name};
|
||||
|
||||
if ($erreichbar) {
|
||||
Log3 $hash, 4, "[$name] ping succesful - state = on";
|
||||
readingsBulkUpdate ($hash, "isRunning", "true");
|
||||
readingsBulkUpdate ($hash, "state", "on");
|
||||
} else {
|
||||
Log3 $hash, 4, "[$name] ping not succesful - state = off";
|
||||
readingsBulkUpdate ($hash, "isRunning", "false");
|
||||
readingsBulkUpdate ($hash, "state", "off");
|
||||
}
|
||||
|
||||
readingsEndUpdate($hash, defined($hash->{LOCAL} ? 0 : 1));
|
||||
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
|
||||
WOL_SetNextTimer($hash);
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
if ($erreichbar) {
|
||||
Log3 $hash, 4, "[$name] ping succesful - state = on";
|
||||
readingsBulkUpdate( $hash, "isRunning", "true" );
|
||||
readingsBulkUpdate( $hash, "state", "on" );
|
||||
}
|
||||
else {
|
||||
Log3 $hash, 4, "[$name] ping not succesful - state = off";
|
||||
readingsBulkUpdate( $hash, "isRunning", "false" );
|
||||
readingsBulkUpdate( $hash, "state", "off" );
|
||||
}
|
||||
|
||||
readingsEndUpdate( $hash, defined( $hash->{LOCAL} ? 0 : 1 ) );
|
||||
|
||||
delete( $hash->{helper}{RUNNING_PID} );
|
||||
|
||||
WOL_SetNextTimer($hash);
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_PingAbort($){
|
||||
my ($hash) = @_;
|
||||
sub WOL_PingAbort($) {
|
||||
my ($hash) = @_;
|
||||
|
||||
delete($hash->{helper}{RUNNING_PID});
|
||||
delete( $hash->{helper}{RUNNING_PID} );
|
||||
|
||||
Log3 $hash->{NAME}, 3, "BlockingCall for ".$hash->{NAME}." was aborted";
|
||||
WOL_SetNextTimer($hash);
|
||||
Log3 $hash->{NAME}, 3, "BlockingCall for " . $hash->{NAME} . " was aborted";
|
||||
WOL_SetNextTimer($hash);
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_GetUpdate($) {
|
||||
my ($myHash) = @_;
|
||||
|
||||
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
|
||||
return if (!defined($hash));
|
||||
my ($hash) = @_;
|
||||
|
||||
my $active = ReadingsVal($hash->{NAME}, "active", "nF");
|
||||
if ($active eq "on") {
|
||||
WOL_wake($hash);
|
||||
if ($hash->{REPEAT} > 0) {
|
||||
myRemoveInternalTimer("wake", $hash);
|
||||
myInternalTimer ("wake", gettimeofday()+$hash->{REPEAT}, "WOL_GetUpdate", $hash, 0);
|
||||
}
|
||||
}
|
||||
return if ( !defined($hash) );
|
||||
|
||||
my $active = ReadingsVal( $hash->{NAME}, "active", "nF" );
|
||||
if ( $active eq "on" ) {
|
||||
WOL_wake($hash);
|
||||
if ( $hash->{REPEAT} > 0 ) {
|
||||
RemoveInternalTimer( $hash, "WOL_GetUpdate" );
|
||||
InternalTimer( gettimeofday() + $hash->{REPEAT}, "WOL_GetUpdate", $hash );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_wake($){
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $mac = $hash->{MAC};
|
||||
my $host = $hash->{IP};
|
||||
|
||||
$host = '255.255.255.255' if (!defined $host);
|
||||
$host = AttrVal($name, "useUdpBroadcast",$host);
|
||||
|
||||
readingsBeginUpdate ($hash);
|
||||
|
||||
Log3 $hash, 4, "[$name] keeping $name with MAC $mac IP $host busy";
|
||||
sub WOL_wake($) {
|
||||
my ($hash) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my $mac = $hash->{MAC};
|
||||
my $host = $hash->{IP};
|
||||
|
||||
if ($hash->{MODE} eq "BOTH" || $hash->{MODE} eq "EW" ) {
|
||||
WOL_by_ew ($hash, $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));
|
||||
$host = '255.255.255.255' if ( !defined $host );
|
||||
$host = AttrVal( $name, "useUdpBroadcast", $host );
|
||||
|
||||
readingsBeginUpdate($hash);
|
||||
|
||||
Log3 $hash, 4, "[$name] keeping $name with MAC $mac IP $host busy";
|
||||
|
||||
if ( $hash->{MODE} eq "BOTH" || $hash->{MODE} eq "EW" ) {
|
||||
WOL_by_ew( $hash, $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
|
||||
sub WOL_by_udp {
|
||||
my ($hash, $mac_addr, $host, $port) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my ( $hash, $mac_addr, $host, $port ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
# use the discard service if $port not passed in
|
||||
if (!defined $port || $port !~ /^\d+$/ ) { $port = 9 }
|
||||
# use the discard service if $port not passed in
|
||||
if ( !defined $port || $port !~ /^\d+$/ ) { $port = 9 }
|
||||
|
||||
my $sock = new IO::Socket::INET(Proto=>'udp') or die "socket : $!";
|
||||
if(!$sock) {
|
||||
Log3 $hash, 1, "[$name] 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);
|
||||
my $sock = new IO::Socket::INET( Proto => 'udp' ) or die "socket : $!";
|
||||
if ( !$sock ) {
|
||||
Log3 $hash, 1, "[$name] Can't create WOL socket";
|
||||
return 1;
|
||||
}
|
||||
|
||||
setsockopt($sock, SOL_SOCKET, SO_BROADCAST, 1) or die "setsockopt : $!";
|
||||
send($sock, $packet, 0, $sock_addr) or die "send : $!";
|
||||
close ($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 );
|
||||
|
||||
return 1;
|
||||
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 wake via system command
|
||||
sub WOL_by_ew($$) {
|
||||
my ($hash, $mac) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
my ( $hash, $mac ) = @_;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
# Fritzbox Raspberry Raspberry aber root
|
||||
my @commands = ("/usr/bin/ether-wake", "/usr/bin/wakeonlan", "/usr/sbin/etherwake" );
|
||||
# Fritzbox Raspberry Raspberry aber root
|
||||
my @commands = ( "/usr/bin/ether-wake", "/usr/bin/wakeonlan", "/usr/sbin/etherwake" );
|
||||
|
||||
my $standardEtherwake = "no WOL found - use '/usr/bin/ether-wake' or '/usr/bin/wakeonlan' or define Attribut sysCmd";
|
||||
foreach my $tstCmd (@commands) {
|
||||
if (-e $tstCmd) {
|
||||
$standardEtherwake = $tstCmd;
|
||||
last;
|
||||
}
|
||||
}
|
||||
my $standardEtherwake =
|
||||
"no WOL found - use '/usr/bin/ether-wake' or '/usr/bin/wakeonlan' or define Attribut sysCmd";
|
||||
foreach my $tstCmd (@commands) {
|
||||
if ( -e $tstCmd ) {
|
||||
$standardEtherwake = $tstCmd;
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
Log3 $hash, 4, "[$name] standard wol command: $standardEtherwake";
|
||||
Log3 $hash, 4, "[$name] standard wol command: $standardEtherwake";
|
||||
|
||||
my $sysCmd = AttrVal($hash->{NAME}, "sysCmd", "");
|
||||
my $sysInterface = AttrVal($hash->{NAME}, "sysInterface", "");
|
||||
|
||||
if ($sysCmd gt "") {
|
||||
Log3 $hash, 4, "[$name] user wol command(sysCmd): '$sysCmd'";
|
||||
} else {
|
||||
$sysCmd = $standardEtherwake;
|
||||
}
|
||||
|
||||
# wenn noch keine $mac dann $mac anhängen.
|
||||
$sysCmd .= ' $mac' if ($sysCmd !~ m/\$mac/g);
|
||||
|
||||
# sysCmd splitten und den nur ersten Teil (-e teil[0])prüfen
|
||||
my ($sysWake) = split (" ", $sysCmd);
|
||||
if (-e $sysWake) {
|
||||
$sysCmd =~ s/\$mac/$mac/;
|
||||
$sysCmd =~ s/\$sysInterface/$sysInterface/;
|
||||
Log3 $hash, 4, "[$name] executing $sysCmd";
|
||||
qx ($sysCmd);
|
||||
} else {
|
||||
Log3 $hash, 1, "[$hash->{NAME}] system command '$sysWake' not found";
|
||||
}
|
||||
my $sysCmd = AttrVal( $hash->{NAME}, "sysCmd", "" );
|
||||
my $sysInterface = AttrVal( $hash->{NAME}, "sysInterface", "" );
|
||||
|
||||
return;
|
||||
if ( $sysCmd gt "" ) {
|
||||
Log3 $hash, 4, "[$name] user wol command(sysCmd): '$sysCmd'";
|
||||
}
|
||||
else {
|
||||
$sysCmd = $standardEtherwake;
|
||||
}
|
||||
|
||||
# wenn noch keine $mac dann $mac anhängen.
|
||||
$sysCmd .= ' $mac' if ( $sysCmd !~ m/\$mac/g );
|
||||
|
||||
# sysCmd splitten und den nur ersten Teil (-e teil[0])prüfen
|
||||
my ($sysWake) = split( " ", $sysCmd );
|
||||
if ( -e $sysWake ) {
|
||||
$sysCmd =~ s/\$mac/$mac/;
|
||||
$sysCmd =~ s/\$sysInterface/$sysInterface/;
|
||||
Log3 $hash, 4, "[$name] executing $sysCmd";
|
||||
qx ($sysCmd);
|
||||
}
|
||||
else {
|
||||
Log3 $hash, 1, "[$hash->{NAME}] system command '$sysWake' not found";
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_SetNextTimer($;$) {
|
||||
my ($hash, $int) = @_;
|
||||
my ( $hash, $int ) = @_;
|
||||
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
$int = AttrVal($hash->{NAME}, "interval", 900) if not defined $int;
|
||||
if ($int != 0) {
|
||||
Log3 $hash, 5, "[$name] WOL_SetNextTimer to $int";
|
||||
myRemoveInternalTimer("ping", $hash);
|
||||
myInternalTimer ("ping", gettimeofday() + $int, "WOL_UpdateReadings", $hash, 0);
|
||||
}
|
||||
return;
|
||||
my $name = $hash->{NAME};
|
||||
|
||||
$int = AttrVal( $hash->{NAME}, "interval", 900 ) if not defined $int;
|
||||
if ( $int != 0 ) {
|
||||
Log3 $hash, 5, "[$name] WOL_SetNextTimer to $int";
|
||||
RemoveInternalTimer( $hash, "WOL_UpdateReadings" );
|
||||
InternalTimer( gettimeofday() + $int, "WOL_UpdateReadings", $hash );
|
||||
}
|
||||
return;
|
||||
}
|
||||
################################################################################
|
||||
sub WOL_Attr($$$) {
|
||||
my ($cmd, $name, $attrName, $attrVal) = @_;
|
||||
$attrVal = "" if(!defined $attrVal);
|
||||
|
||||
my $hash = $defs{$name};
|
||||
|
||||
if ($attrName eq "useUdpBroadcast") {
|
||||
if(!($attrVal =~ m/^([0-9]{1,3}([.-]|$)){4}$/i)) {
|
||||
Log3 $hash, 3, "[$name] invalid Broadcastadress<$attrVal> - use ddd.ddd.ddd.ddd";
|
||||
}
|
||||
}
|
||||
|
||||
if ($attrName eq "interval") {
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# when deleting the interval we trigger an update in one second
|
||||
my $int = ($cmd eq "del") ? 1 : $attrVal;
|
||||
if ($int != 0) {
|
||||
# restart timer with new interval
|
||||
WOL_SetNextTimer($hash, $int);
|
||||
}
|
||||
}
|
||||
my ( $cmd, $name, $attrName, $attrVal ) = @_;
|
||||
$attrVal = "" if ( !defined $attrVal );
|
||||
|
||||
return undef;
|
||||
my $hash = $defs{$name};
|
||||
|
||||
if ( $attrName eq "useUdpBroadcast" ) {
|
||||
if ( !( $attrVal =~ m/^([0-9]{1,3}([.-]|$)){4}$/i ) ) {
|
||||
return "[$name] invalid Broadcastadress<$attrVal> - use ddd.ddd.ddd.ddd";
|
||||
}
|
||||
}
|
||||
|
||||
if ( $attrName eq "interval" ) {
|
||||
RemoveInternalTimer($hash);
|
||||
|
||||
# when deleting the interval we trigger an update in one second
|
||||
my $int = ( $cmd eq "del" ) ? 1 : $attrVal;
|
||||
if ( $int != 0 ) {
|
||||
|
||||
# restart timer with new interval
|
||||
WOL_SetNextTimer( $hash, $int );
|
||||
}
|
||||
}
|
||||
|
||||
return undef;
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
|
||||
=pod
|
||||
=item helper
|
||||
=item summary turn on or wake up a computer by sending it a network message
|
||||
=item summary_DE Einschalten oder Aufwecken eines Computers durch Netzwerknachricht
|
||||
=begin html
|
||||
|
||||
<a name="WOL"></a>
|
||||
@ -364,7 +381,7 @@ sub WOL_Attr($$$) {
|
||||
|
||||
Defines a WOL device via its MAC and IP address.<br><br>
|
||||
|
||||
when sending the <b>on</b> 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.
|
||||
when sending the <b>on</b> command to a WOL device it wakes up the dependent device by sending a magic packet. When running in repeat mode the magic packet ist sent every n seconds to the device.
|
||||
So, for example a Buffalo NAS can be kept awake.
|
||||
<ul>
|
||||
<a name="WOLdefine"></a>
|
||||
@ -389,15 +406,14 @@ So, for example a Buffalo NAS can be kept awake.
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 switching only one time</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW by ether-wake(linux command)</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH by both methods</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 in repeat mode<i><b>usr/bin/ether-wake</b></i> in repeatmode</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 in repeat mode</code><br>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
<b><font size="+1">Notes</font></b>:
|
||||
<ul>
|
||||
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.
|
||||
Not every hardware is able to wake up other devices by default. Often firewalls filter magic packets and have to be configured accordingly.
|
||||
You may need a packet sniffer to check some malfunction.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
@ -437,11 +453,98 @@ So, for example a Buffalo NAS can be kept awake.
|
||||
</PRE>
|
||||
<li><code>attr <name> interval <seconds></code></a>
|
||||
<br>defines the time between two checks by a <i>ping</i> if state of <name> is <i>on</i>. By using 0 as parameter for interval you can switch off checking the device.</li>
|
||||
<li><code>attr <name> useUdpBroadcast <broardcastAdress></code>
|
||||
<br>When using UDP then the magic packet can be send to one of the broardcastAdresses (x.x.x.255, x.x.255.255, x.255.255.255) instead of the target host address.
|
||||
<li><code>attr <name> useUdpBroadcast <broadcastAdress></code>
|
||||
<br>When using UDP then the magic packet can be send to one of the broadcastAdresses (x.x.x.255, x.x.255.255, x.255.255.255) instead of the target host address.
|
||||
Try using this, when you want to wake up a machine in your own subnet and the wakekup with the target adress is instable or doesn't work.</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
=end html
|
||||
=cut
|
||||
=begin html_DE
|
||||
|
||||
<a name="WOL"></a>
|
||||
<h3>WOL</h3>
|
||||
|
||||
Definiert ein WOL Gerät über seine MAC und IP Addresse.<br><br>
|
||||
|
||||
Wenn der <b>on</b> Befehl an das WOL Gerät gesendet wird, wird das entsprechende Gerät durch das Senden eines "magic packet" aufgeweckt. Wenn WOL im repeat Modus läuft, wird das "magic packet" alle n Sekunden zum Gerät geschickt.
|
||||
So kann z.B. ein Buffalo NAS "wach" gehalten werden.
|
||||
<ul>
|
||||
<a name="WOLdefine"></a>
|
||||
<h4>Define</h4>
|
||||
<ul>
|
||||
<code><b><font size="+1">define <name> WOL <MAC> <IP> [<mode> [<repeat>]]</font></b></code>
|
||||
<br><br>
|
||||
|
||||
<dl>
|
||||
<dt><b>MAC</b></dt>
|
||||
<dd>MAC-Adresse des Hosts</dd>
|
||||
<dt><b>IP</b></dt>
|
||||
<dd>IP-Adresse des Hosts (oder broadcast Addresse des lokalen Netzwerks, wenn die IP des Hosts unbekannt ist)</dd>
|
||||
<dt><b>mode <i>[EW|UDP]</i></b></dt>
|
||||
<dd>EW: aufwecken durch <i>usr/bin/ether-wake</i> </dd>
|
||||
<dd>UDP: aufwecken durch eine Implementierung wie <i>Net::Wake(CPAN)</i></dd>
|
||||
</dl>
|
||||
<br><br>
|
||||
|
||||
<b><font size="+1">Beispiele</font></b>:
|
||||
<ul>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 nur einmal schalten</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW über ether-wake(Linux Befehl)</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH über beide Methoden</code><br>
|
||||
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 im repeat Modus</code><br>
|
||||
</ul>
|
||||
<br><br>
|
||||
|
||||
<b><font size="+1">Anmerkungen</font></b>:
|
||||
<ul>
|
||||
Nicht jede Hardware kann standardmäßig andere Geräte aufwecken. Firewalls filtern häufig magic packets und müssen entsprechend konfiguriert werden.
|
||||
Möglicherweise ist ein Packet Sniffer notwendig um Fehlfunktionen zu überprüfen.
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<a name="WOLset"></a>
|
||||
<h4>Set </h4>
|
||||
<ul>
|
||||
<code><b><font size="+1">set <name> <value></font></b></code>
|
||||
<br><br>
|
||||
wobei <code>value</code> einer der folgenden ist:<br>
|
||||
<pre>
|
||||
<b>refresh</b> # überprüft (mittels ping) ob das Gerät gerade läuft
|
||||
<b>on</b> # schickt ein magic packet an die definierte MAC-Adresse
|
||||
<b>off</b> # beemdet das Senden von magic packets schickt das <b>shutdownCmd</b>(siehe Attribute)
|
||||
</pre>
|
||||
|
||||
<b><font size="+1">Beispiele</font></b>:
|
||||
<ul>
|
||||
<code>set computer1 on</code><br>
|
||||
<code>set computer1 off</code><br>
|
||||
<code>set computer1 refresh</code><br>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
<a name="WOLattr"></a>
|
||||
<h4>Attribute</h4>
|
||||
<ul>
|
||||
<li><code>attr <name> sysCmd <string></code>
|
||||
<br>Eigener Befehl, um ein entferntes Gerät aufzuwecken, z.B. <code>/usr/bin/ether-wake or /usr/bin/wakeonlan</code></li>
|
||||
<li><code>attr <name> shutdownCmd <command></code>
|
||||
<br>Eigener Befehl, um ein entferntes Gerät herunter zu fahren. Es können <command>, wie in at, notify oder Watchdog verwendet werden</li>
|
||||
<br><br>
|
||||
Beispiele:
|
||||
<PRE>
|
||||
attr wol shutdownCmd set lamp on # fhem Befehl
|
||||
attr wol shutdownCmd { Log 1, "Teatime" } # Perl Befehl
|
||||
attr wol shutdownCmd "/bin/echo "Teatime" > /dev/console" # shell Befehl
|
||||
</PRE>
|
||||
<li><code>attr <name> interval <seconds></code></a>
|
||||
<br>definiert die Zeit zwischen zwei Checks mittels <i>ping</i> Wenn der state von <name> <i>on</i> ist. Mit dem Wert 0 als interval wird die regelmäßige Überprüfung abgeschaltet.</li>
|
||||
<li><code>attr <name> useUdpBroadcast <broadcastAdress></code>
|
||||
<br>Bei der Nutzung von UDP kann das magic packet an eine det broadcastAdressen (x.x.x.255, x.x.255.255, x.255.255.255) geschickt werden, an Stelle des Ziel-Hosts address.
|
||||
Diese Methode sollte verwendet werden, wenn ein Gerät im eigenen Subnetz aufgeweckt werden soll, aber der wakeup mit dem Zielhost nicht funktioniert oder nicht stabil ist.</li>
|
||||
</ul>
|
||||
</ul>
|
||||
|
||||
=end html_DE
|
||||
|
||||
=cut
|
||||
|
Loading…
x
Reference in New Issue
Block a user