Will man seine WakeOnLAN (WOL) fähigen Geräte im Netzwerk aufwecken, so braucht man normalerweise ein Programm, welches die Magic-Packets versendet. Es geht aber auch per Weboberfläche. Praktisch, wenn man eine Synology oder einen RaspberryPi zur Hand hat.
Man benötigt nicht viel:
- Installierte WebStation bzw. auf dem RaspberryPi einen WebServer (z.B. Apache)
- PHP Version 4 oder höher
Im Web-Homeverzeichnis (Synology /volume1/web bzw. httpdocs im Apache) ein Unterverzeichnis z.B. WOL anlegen.
Eine index.html Datei erstellen mit z.B. folgendem Inhalt:
<!doctype html>
<html>
<head>
<title>WOL over Web</title>
</head>
<body>
Start Computer/Server (192.168.0.X) <br>via WakeOnLAN (WOL)
<br>
<form method="POST" action="StartServer.php" name="WOL_form.php">
<input type="submit" name="submit" value="Start1"></input>
</form>
</body>
</html>
Und noch die dazugehörige PHP Datei „StartServer.php„:
<?php
// More info: http://wolviaphp.sourceforge.net
// License: GPLv2.0
$mac_address = "00:00:00:00:00:00"; // SERVER
$addr = "192.168.0.x"; // Adresse aus dem eigenen Segment, Router oder aktueller Rechner sind OK.
$cidr = "24"; // MASK: 255.255.255.0 ==> 24 (3 Byte * 8 Bit)
$port = "9";
function WakeOnLan($mac_address, $addr, $cidr, $port)
{
// Prepare magic packet: part 1/3 (defined constant)
$buf="";
for($a=0; $a<6; $a++) $buf .= chr(255); // the defined constant as represented in hexadecimal: FF FF FF FF FF FF (i.e., 6 bytes of hexadecimal FF)
//Check whether $mac_address is valid
$mac_address=strtoupper($mac_address);
$mac_address=str_replace(":", "-", $mac_address);
if ((!preg_match("/([A-F0-9]{2}[-]){5}([0-9A-F]){2}/",$mac_address)) || (strlen($mac_address) != 17))
{
$error = "Input error: Pattern of MAC-address is not \"xx-xx-xx-xx-xx-xx\" (x = digit or letter).<br>\n";
return $error; // false
}
else
{
// Prepare magic packet: part 2/3 (16 times MAC-address)
$addr_byte = explode('-', $mac_address); // Split MAC-address into an array of (six) bytes
$hw_addr="";
for ($a=0; $a<6; $a++) $hw_addr .= chr(hexdec($addr_byte[$a])); // Convert MAC-address from bytes to hexadecimal to decimal
$hw_addr_string="";
for ($a=0; $a<16; $a++) $hw_addr_string .= $hw_addr;
$buf .= $hw_addr_string;
}
// Resolve broadcast address
if (filter_var ($addr, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) // same as (but easier than): preg_match("/\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b/",$addr)
{
// $addr has an IP-adres format
}
else
{
// Whitespaces confuse name lookups
$addr=trim($addr);
// If you pass to gethostbyname() an:
// unresolvable domainname, gethostbyname() returns the domainname (rather than 'false')
// IP address, gethostbyname() returns that IP address.
if (gethostbyname($addr) == $addr)
{
// $addr is NOT a resolvable domainname
$error = "Input error: host name of broadcast address is unresolvable.<br>\n";
return $error; // false
}
else
{
// $addr IS a resolvable domainname
$addr = gethostbyname($addr);
}
}
// Store input value for cookie
$resolved_addr = $addr;
// If $cidr is set, replace $addr for its broadcast address
if ($cidr != "")
{
// Check whether $cidr is valid
if ((!ctype_digit($cidr)) || ($cidr < 0) || ($cidr > 32))
{
$error = "Input error: CIDR subnet mask is not a number within the range of 0 till 32.<br>\n";
return $error; // false
}
// Convert $cidr from one decimal to one inverted binary array
$inverted_binary_cidr="";
for ($a=0; $a<$cidr; $a++) $inverted_binary_cidr .= "0"; // Build $inverted_binary_cidr by $cidr * zeros (this is the mask)
$inverted_binary_cidr = $inverted_binary_cidr.substr("11111111111111111111111111111111",0,32-strlen($inverted_binary_cidr)); // Invert the mask (by postfixing ones to $inverted_binary_cidr untill 32 bits are filled/ complete)
$inverted_binary_cidr_array = str_split($inverted_binary_cidr); // Convert $inverted_binary_cidr to an array of bits
// Convert IP address from four decimals to one binary array
$addr_byte = explode('.', $addr); // Split IP address into an array of (four) decimals
$binary_addr="";
for ($a=0; $a<4; $a++) {
$pre = substr("00000000",0,8-strlen(decbin($addr_byte[$a]))); // Prefix zeros
$post = decbin($addr_byte[$a]); // Postfix binary decimal
$binary_addr .= $pre.$post;
}
$binary_addr_array = str_split($binary_addr); // Convert $binary_addr to an array of bits
// Perform a bitwise OR operation on arrays ($binary_addr_array & $inverted_binary_cidr_array)
$binary_broadcast_addr_array="";
for ($a=0; $a<32; $a++) $binary_broadcast_addr_array[$a] = ($binary_addr_array[$a] | $inverted_binary_cidr_array[$a]); // binary array of 32 bit variables ('|' = logical operator 'or')
$binary_broadcast_addr = chunk_split(implode("", $binary_broadcast_addr_array),8,"."); // build binary address of four bundles of 8 bits (= 1 byte)
$binary_broadcast_addr = substr($binary_broadcast_addr,0,strlen($binary_broadcast_addr)-1); // chop off last dot ('.')
$binary_broadcast_addr_array = explode(".", $binary_broadcast_addr); // binary array of 4 byte variables
$broadcast_addr_array="";
for ($a=0; $a<4; $a++) $broadcast_addr_array[$a] = bindec($binary_broadcast_addr_array[$a]); // decimal array of 4 byte variables
$addr = implode(".", $broadcast_addr_array); // broadcast address
}
// Check whether $port is valid
if ((!ctype_digit($port)) || ($port < 0) || ($port > 65536))
{
$error = "Input error: Port is not a number within the range of 0 till 65536.<br>\n";
return $error; // false
}
// Check whether UDP is supported
if (!array_search('udp', stream_get_transports()))
{
$error = "No magic packet can been sent, since UDP is unsupported (not a registered socket transport).<br>\n";
return $error; // false
}
if (function_exists('fsockopen'))
{
// Try fsockopen function - To do: handle error 'Permission denied'
$socket=fsockopen("udp://" . $addr, $port, $errno, $errstr);
if($socket)
{
$socket_data = fwrite($socket, $buf);
if($socket_data)
{
$function = "fwrite";
// $sent_fsockopen = "A magic packet of ".$socket_data." bytes has been sent via UDP to IP address: ".$addr.":".$port.", using the '".$function."()' function.<br>";
$sent_fsockopen = "OK (fsockopen)" ;
// $content = bin2hex($buf);
// $sent_fsockopen = $sent_fsockopen."Contents of magic packet:<br><textarea rows=\"1\" name=\"content\" cols=\"".strlen($content)."\">".$content."</textarea><br>\n";
fclose($socket);
unset($socket);
return $sent_fsockopen; // true
}
else
{
echo "Using 'fwrite()' failed, due to error: '".$errstr."' (".$errno.")<br>\n";
fclose($socket);
unset($socket);
}
}
else
{
echo "Using 'fsockopen()' failed, due to denied permission.<br>\n";
unset($socket);
}
}
// Try socket_create function
if (function_exists('socket_create'))
{
$socket = socket_create(AF_INET, SOCK_DGRAM, SOL_UDP); // create socket based on IPv4, datagram and UDP
if($socket)
{
$level = SOL_SOCKET; // to enable manipulation of options at the socket level (you may have to change this to 1)
$optname = SO_BROADCAST; // to enable permission to transmit broadcast datagrams on the socket (you may have to change this to 6)
$optval = true;
$opt_returnvalue = socket_set_option($socket, $level, $optname, $optval);
if($opt_returnvalue < 0)
{
$error = "Using 'socket_set_option()' failed, due to error: '".socket_strerror($opt_returnvalue)."'<br>\n";
return $error; // false
}
$flags = 0;
// To do: handle error 'Operation not permitted'
$socket_data = socket_sendto($socket, $buf, strlen($buf), $flags, $addr, $port);
if($socket_data)
{
$function = "socket_sendto";
// $socket_create = "A magic packet of ".$socket_data." bytes has been sent via UDP to IP address: ".$addr.":".$port.", using the '".$function."()' function.<br>";
// $content = bin2hex($buf);
// $socket_create = $socket_create."Contents of magic packet:<br><textarea rows=\"1\" name=\"content\" cols=\"".strlen($content)."\">".$content."</textarea><br>\n";
$socket_create = "OK (create)";
socket_close($socket);
unset($socket);
return $socket_create; // true
}
else
{
$error = "Using 'socket_sendto()' failed, due to error: '".socket_strerror(socket_last_error($socket))."' (".socket_last_error($socket).")<br>\n";
socket_close($socket);
unset($socket);
return $error; // false
}
}
else
{
$error = "Using 'socket_create()' failed, due to error: '".socket_strerror(socket_last_error($socket))."' (".socket_last_error($socket).")<br>\n";
return $error; // false
}
}
else
{
$error = "No magic packet has been sent, since no functions are available to transmit it.<br>\n";
return $error; // false
}
}
//
$Return_WakeOnLan = WakeOnLan($mac_address, $addr, $cidr, $port); // executes this function
//
?>
<!DOCTYPE HTML>
<HTML>
<HEAD>
<meta name="robots" content="noindex">
<meta http-equiv="expires" content="0">
<TITLE>WOL over Web - Result</TITLE>
</HEAD>
<BODY>
Magic paket send, device should be available within a few minutes.
<br><font face="Courier">
<?php
echo "Return-message: ",$Return_WakeOnLan;
$TimeStamp = time();
$datum = date("d.m.Y",$TimeStamp);
$uhrzeit = date("H:i:s",$TimeStamp);
echo " ",$datum," - ",$uhrzeit," h";
echo "<font color=#FFFFFF>";
$fp = fsockopen($addr, 80);
if(!$fp)
{
echo "<BR>";
echo "<img src=\"error.png\" width=40px><br>";
echo "<font color=#000000>";
echo "IP $addr down";
}
else
{
echo "<BR><br>";
echo "<img src=\"img_business.jpg\" width=50px>";
echo "<font color=#000000>";
echo "IP $addr up";
socket_set_timeout($fp, 2);
$res = fread($fp, 2000);
fclose($fp);
print $res;
}
?>
<p>
</font>
</BODY>
</HTML>
Es muss nur in Zeile 6 die IP-Adresse angegeben werden und schon funktioniert es.
Will man mehrere Geräte auf diese Weise starten, so muss man entsprechend den POST Parameter auswerten und eine Tabelle mit den verschiedenen IP-Adressen im PHP-Code hinterlegen.
Wenn ich Zeit finde, werde ich es einbauen.