2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-03 23:06:37 +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:
KernSani 2019-02-12 21:42:18 +00:00
parent 63292badaa
commit 984bd39408

View File

@ -1,6 +1,8 @@
# $Id$ # $Id$
# erweitert um die Funktion nas_control Dietmar Ortmann $ # 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. # This file is part of fhem.
# #
# Fhem is free software: you can redistribute it and/or modify # 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 # You should have received a copy of the GNU General Public License
# along with fhem. If not, see <http://www.gnu.org/licenses/>. # 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; package main;
@ -25,27 +37,23 @@ use IO::Socket;
use Blocking; use Blocking;
use Time::HiRes qw(gettimeofday); use Time::HiRes qw(gettimeofday);
my $version = "1.03";
################################################################################ ################################################################################
sub WOL_Initialize($) { sub WOL_Initialize($) {
my ($hash) = @_; 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);
}
$hash->{SetFn} = "WOL_Set"; $hash->{SetFn} = "WOL_Set";
$hash->{DefFn} = "WOL_Define"; $hash->{DefFn} = "WOL_Define";
$hash->{UndefFn} = "WOL_Undef"; $hash->{UndefFn} = "WOL_Undef";
$hash->{AttrFn} = "WOL_Attr"; $hash->{AttrFn} = "WOL_Attr";
$hash->{AttrList} = "interval shutdownCmd sysCmd sysInterface useUdpBroadcast ". $hash->{AttrList} = "interval shutdownCmd sysCmd sysInterface useUdpBroadcast " . $readingFnAttributes;
$readingFnAttributes;
} }
################################################################################ ################################################################################
sub WOL_Set($@) { sub WOL_Set($@) {
my ( $hash, @a ) = @_; my ( $hash, @a ) = @_;
return "no set value specified" if ( int(@a) < 2 ); return "no set value specified" if ( int(@a) < 2 );
return "Unknown argument $a[1], choose one of on off refresh" if($a[1] eq "?"); return "Unknown argument $a[1], choose one of on:noArg off:noArg refresh:noArg" if ( $a[1] eq "?" );
my $name = shift @a; my $name = shift @a;
my $v = join( " ", @a ); my $v = join( " ", @a );
@ -55,8 +63,9 @@ sub WOL_Set($@) {
if ( $v eq "on" ) { if ( $v eq "on" ) {
readingsSingleUpdate( $hash, "active", $v, 1 ); readingsSingleUpdate( $hash, "active", $v, 1 );
Log3 $hash, 3, "[$name] waking $name with MAC $hash->{MAC} IP $hash->{IP} "; Log3 $hash, 3, "[$name] waking $name with MAC $hash->{MAC} IP $hash->{IP} ";
WOL_GetUpdate( { 'HASH' => $hash } ); WOL_GetUpdate($hash);
} elsif ($v eq "off") { }
elsif ( $v eq "off" ) {
readingsSingleUpdate( $hash, "active", $v, 1 ); readingsSingleUpdate( $hash, "active", $v, 1 );
my $cmd = AttrVal( $name, "shutdownCmd", "" ); my $cmd = AttrVal( $name, "shutdownCmd", "" );
if ( $cmd eq "" ) { if ( $cmd eq "" ) {
@ -66,8 +75,9 @@ sub WOL_Set($@) {
Log3 $hash, 3, "[$name] shutdownCmd: $cmd executed"; Log3 $hash, 3, "[$name] shutdownCmd: $cmd executed";
my $ret = AnalyzeCommandChain( undef, $cmd ); my $ret = AnalyzeCommandChain( undef, $cmd );
Log3( $hash, 3, "[$name]" . $ret ) if ($ret); Log3( $hash, 3, "[$name]" . $ret ) if ($ret);
} elsif ($v eq "refresh") { }
WOL_UpdateReadings( { 'HASH' => $hash } ); elsif ( $v eq "refresh" ) {
WOL_UpdateReadings($hash);
} }
return undef; return undef;
@ -107,6 +117,8 @@ sub WOL_Define($$) {
$hash->{REPEAT} = $repeat; $hash->{REPEAT} = $repeat;
$hash->{MODE} = $mode; $hash->{MODE} = $mode;
$hash->{VERSION} = $version;
delete $hash->{helper}{RUNNING_PID}; delete $hash->{helper}{RUNNING_PID};
readingsSingleUpdate( $hash, "packet_via_EW", "none", 0 ); readingsSingleUpdate( $hash, "packet_via_EW", "none", 0 );
@ -124,16 +136,14 @@ sub WOL_Undef($$) {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
myRemoveInternalTimer("ping", $hash); RemoveInternalTimer($hash);
myRemoveInternalTimer("wake", $hash);
BlockingKill( $hash->{helper}{RUNNING_PID} ) if ( defined( $hash->{helper}{RUNNING_PID} ) ); BlockingKill( $hash->{helper}{RUNNING_PID} ) if ( defined( $hash->{helper}{RUNNING_PID} ) );
return undef; return undef;
} }
################################################################################ ################################################################################
sub WOL_UpdateReadings($) { sub WOL_UpdateReadings($) {
my ($myHash) = @_; my ($hash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if ( !defined($hash) ); return if ( !defined($hash) );
my $name = $hash->{NAME}; my $name = $hash->{NAME};
@ -146,7 +156,8 @@ sub WOL_UpdateReadings($) {
if ( !( exists( $hash->{helper}{RUNNING_PID} ) ) ) { if ( !( exists( $hash->{helper}{RUNNING_PID} ) ) ) {
$hash->{helper}{RUNNING_PID} = $hash->{helper}{RUNNING_PID} =
BlockingCall( $blockingFn, $arg, $finishFn, $timeout, $abortFn, $hash ); BlockingCall( $blockingFn, $arg, $finishFn, $timeout, $abortFn, $hash );
} else { }
else {
Log3 $hash, 3, "[$name] Blocking Call running no new started"; Log3 $hash, 3, "[$name] Blocking Call running no new started";
WOL_SetNextTimer($hash); WOL_SetNextTimer($hash);
} }
@ -180,7 +191,8 @@ sub WOL_PingDone($){
Log3 $hash, 4, "[$name] ping succesful - state = on"; Log3 $hash, 4, "[$name] ping succesful - state = on";
readingsBulkUpdate( $hash, "isRunning", "true" ); readingsBulkUpdate( $hash, "isRunning", "true" );
readingsBulkUpdate( $hash, "state", "on" ); readingsBulkUpdate( $hash, "state", "on" );
} else { }
else {
Log3 $hash, 4, "[$name] ping not succesful - state = off"; Log3 $hash, 4, "[$name] ping not succesful - state = off";
readingsBulkUpdate( $hash, "isRunning", "false" ); readingsBulkUpdate( $hash, "isRunning", "false" );
readingsBulkUpdate( $hash, "state", "off" ); readingsBulkUpdate( $hash, "state", "off" );
@ -203,17 +215,16 @@ sub WOL_PingAbort($){
} }
################################################################################ ################################################################################
sub WOL_GetUpdate($) { sub WOL_GetUpdate($) {
my ($myHash) = @_; my ($hash) = @_;
my $hash = myGetHashIndirekt($myHash, (caller(0))[3]);
return if ( !defined($hash) ); return if ( !defined($hash) );
my $active = ReadingsVal( $hash->{NAME}, "active", "nF" ); my $active = ReadingsVal( $hash->{NAME}, "active", "nF" );
if ( $active eq "on" ) { if ( $active eq "on" ) {
WOL_wake($hash); WOL_wake($hash);
if ( $hash->{REPEAT} > 0 ) { if ( $hash->{REPEAT} > 0 ) {
myRemoveInternalTimer("wake", $hash); RemoveInternalTimer( $hash, "WOL_GetUpdate" );
myInternalTimer ("wake", gettimeofday()+$hash->{REPEAT}, "WOL_GetUpdate", $hash, 0); InternalTimer( gettimeofday() + $hash->{REPEAT}, "WOL_GetUpdate", $hash );
} }
} }
@ -277,7 +288,8 @@ sub WOL_by_ew($$) {
# Fritzbox Raspberry Raspberry aber root # Fritzbox Raspberry Raspberry aber root
my @commands = ( "/usr/bin/ether-wake", "/usr/bin/wakeonlan", "/usr/sbin/etherwake" ); 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"; my $standardEtherwake =
"no WOL found - use '/usr/bin/ether-wake' or '/usr/bin/wakeonlan' or define Attribut sysCmd";
foreach my $tstCmd (@commands) { foreach my $tstCmd (@commands) {
if ( -e $tstCmd ) { if ( -e $tstCmd ) {
$standardEtherwake = $tstCmd; $standardEtherwake = $tstCmd;
@ -292,7 +304,8 @@ sub WOL_by_ew($$) {
if ( $sysCmd gt "" ) { if ( $sysCmd gt "" ) {
Log3 $hash, 4, "[$name] user wol command(sysCmd): '$sysCmd'"; Log3 $hash, 4, "[$name] user wol command(sysCmd): '$sysCmd'";
} else { }
else {
$sysCmd = $standardEtherwake; $sysCmd = $standardEtherwake;
} }
@ -306,7 +319,8 @@ sub WOL_by_ew($$) {
$sysCmd =~ s/\$sysInterface/$sysInterface/; $sysCmd =~ s/\$sysInterface/$sysInterface/;
Log3 $hash, 4, "[$name] executing $sysCmd"; Log3 $hash, 4, "[$name] executing $sysCmd";
qx ($sysCmd); qx ($sysCmd);
} else { }
else {
Log3 $hash, 1, "[$hash->{NAME}] system command '$sysWake' not found"; Log3 $hash, 1, "[$hash->{NAME}] system command '$sysWake' not found";
} }
@ -321,8 +335,8 @@ sub WOL_SetNextTimer($;$) {
$int = AttrVal( $hash->{NAME}, "interval", 900 ) if not defined $int; $int = AttrVal( $hash->{NAME}, "interval", 900 ) if not defined $int;
if ( $int != 0 ) { if ( $int != 0 ) {
Log3 $hash, 5, "[$name] WOL_SetNextTimer to $int"; Log3 $hash, 5, "[$name] WOL_SetNextTimer to $int";
myRemoveInternalTimer("ping", $hash); RemoveInternalTimer( $hash, "WOL_UpdateReadings" );
myInternalTimer ("ping", gettimeofday() + $int, "WOL_UpdateReadings", $hash, 0); InternalTimer( gettimeofday() + $int, "WOL_UpdateReadings", $hash );
} }
return; return;
} }
@ -335,7 +349,7 @@ sub WOL_Attr($$$) {
if ( $attrName eq "useUdpBroadcast" ) { if ( $attrName eq "useUdpBroadcast" ) {
if ( !( $attrVal =~ m/^([0-9]{1,3}([.-]|$)){4}$/i ) ) { if ( !( $attrVal =~ m/^([0-9]{1,3}([.-]|$)){4}$/i ) ) {
Log3 $hash, 3, "[$name] invalid Broadcastadress<$attrVal> - use ddd.ddd.ddd.ddd"; return "[$name] invalid Broadcastadress<$attrVal> - use ddd.ddd.ddd.ddd";
} }
} }
@ -345,6 +359,7 @@ sub WOL_Attr($$$) {
# when deleting the interval we trigger an update in one second # when deleting the interval we trigger an update in one second
my $int = ( $cmd eq "del" ) ? 1 : $attrVal; my $int = ( $cmd eq "del" ) ? 1 : $attrVal;
if ( $int != 0 ) { if ( $int != 0 ) {
# restart timer with new interval # restart timer with new interval
WOL_SetNextTimer( $hash, $int ); WOL_SetNextTimer( $hash, $int );
} }
@ -355,8 +370,10 @@ sub WOL_Attr($$$) {
1; 1;
=pod =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 =begin html
<a name="WOL"></a> <a name="WOL"></a>
@ -364,7 +381,7 @@ sub WOL_Attr($$$) {
Defines a WOL device via its MAC and IP address.<br><br> 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. So, for example a Buffalo NAS can be kept awake.
<ul> <ul>
<a name="WOLdefine"></a> <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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switching only one time</code><br> <code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;switching only one time</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by ether-wake(linux command)</code><br> <code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by ether-wake(linux command)</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by both methods</code><br> <code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; by both methods</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 &nbsp;&nbsp;&nbsp; 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 &nbsp;&nbsp;&nbsp; in repeat mode</code><br>
</ul> </ul>
<br><br> <br><br>
<b><font size="+1">Notes</font></b>: <b><font size="+1">Notes</font></b>:
<ul> <ul>
Not every hardware is able to wake up other devices by default. Oftenly firewalls filter magic packets. Switch them first off. 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 malfunktion. You may need a packet sniffer to check some malfunction.
With this module you get two methods to do the job: see the mode parameter.
</ul> </ul>
</ul> </ul>
@ -437,11 +453,98 @@ So, for example a Buffalo NAS can be kept awake.
</PRE> </PRE>
<li><code>attr &lt;name&gt; interval &lt;seconds&gt;</code></a> <li><code>attr &lt;name&gt; interval &lt;seconds&gt;</code></a>
<br>defines the time between two checks by a <i>ping</i> if state of &lt;name&gt is <i>on</i>. By using 0 as parameter for interval you can switch off checking the device.</li> <br>defines the time between two checks by a <i>ping</i> if state of &lt;name&gt is <i>on</i>. By using 0 as parameter for interval you can switch off checking the device.</li>
<li><code>attr &lt;name&gt; useUdpBroadcast &lt;broardcastAdress&gt;</code> <li><code>attr &lt;name&gt; useUdpBroadcast &lt;broadcastAdress&gt;</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. <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> 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>
</ul> </ul>
=end html =end html
=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 &lt;name&gt; WOL &lt;MAC&gt; &lt;IP&gt; [&lt;mode&gt; [&lt;repeat&gt;]]</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&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;nur einmal schalten</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 EW&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; über ether-wake(Linux Befehl)</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 BOTH&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; über beide Methoden</code><br>
<code>define computer1 WOL 72:11:AC:4D:37:13 192.168.0.24 UDP 200 &nbsp;&nbsp;&nbsp; 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 &lt;name&gt; &lt;value&gt;</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 &lt;name&gt; sysCmd &lt;string&gt;</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 &lt;name&gt; shutdownCmd &lt;command&gt;</code>
<br>Eigener Befehl, um ein entferntes Gerät herunter zu fahren. Es können &lt;command&gt;, 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 &lt;name&gt; interval &lt;seconds&gt;</code></a>
<br>definiert die Zeit zwischen zwei Checks mittels <i>ping</i> Wenn der state von &lt;name&gt <i>on</i> ist. Mit dem Wert 0 als interval wird die regelmäßige Überprüfung abgeschaltet.</li>
<li><code>attr &lt;name&gt; useUdpBroadcast &lt;broadcastAdress&gt;</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 =cut