Added possiblity to send WOL Requests to configured Hostname, also removed unnecessary unit from Timeout Annotation in WakeOnLanPacketSenderTest (#11199)

Signed-off-by: Jonathan Saxen <jonathan@saxen.info>
This commit is contained in:
Jonathan S 2021-09-19 21:55:39 +02:00 committed by GitHub
parent cfdabc4060
commit 8a7f15e232
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 105 additions and 23 deletions

View File

@ -13,16 +13,13 @@
package org.openhab.binding.network.internal;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.SocketException;
import java.net.UnknownHostException;
import java.net.*;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Stream;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.jdt.annotation.NonNullByDefault;
import org.eclipse.jdt.annotation.Nullable;
import org.openhab.core.net.NetUtil;
@ -50,12 +47,28 @@ public class WakeOnLanPacketSender {
private final Logger logger = LoggerFactory.getLogger(WakeOnLanPacketSender.class);
private final String macAddress;
@Nullable
private final String hostname;
@Nullable
private final Integer port;
private byte @Nullable [] magicPacket;
private final Consumer<byte[]> magicPacketSender;
public WakeOnLanPacketSender(String macAddress, @Nullable String hostname, @Nullable Integer port) {
this.macAddress = macAddress;
this.hostname = hostname;
this.port = port;
this.magicPacketSender = this::sendMagicPacket;
}
public WakeOnLanPacketSender(String macAddress) {
this.macAddress = macAddress;
this.magicPacketSender = this::broadcastMagicPacket;
this.hostname = null;
this.port = null;
this.magicPacketSender = this::sendMagicPacket;
}
/**
@ -63,6 +76,8 @@ public class WakeOnLanPacketSender {
*/
WakeOnLanPacketSender(String macAddress, Consumer<byte[]> magicPacketSender) {
this.macAddress = macAddress;
this.hostname = null;
this.port = null;
this.magicPacketSender = magicPacketSender;
}
@ -96,26 +111,46 @@ public class WakeOnLanPacketSender {
return bytes;
}
private void broadcastMagicPacket(byte[] magicPacket) {
private void sendMagicPacket(byte[] magicPacket) {
try (DatagramSocket socket = new DatagramSocket()) {
broadcastAddressStream().forEach(broadcastAddress -> {
try {
DatagramPacket packet = new DatagramPacket(magicPacket, MAGIC_PACKET_BYTE_SIZE, broadcastAddress,
WOL_UDP_PORT);
socket.send(packet);
logger.debug("Wake-on-LAN packet sent (MAC address: {}, broadcast address: {})", macAddress,
broadcastAddress.getHostAddress());
} catch (IOException e) {
logger.debug("Failed to send Wake-on-LAN packet (MAC address: {}, broadcast address: {})",
macAddress, broadcastAddress.getHostAddress(), e);
}
});
logger.info("Wake-on-LAN packets sent (MAC address: {})", macAddress);
if (StringUtils.isEmpty(hostname)) {
broadcastMagicPacket(magicPacket, socket);
} else {
SocketAddress socketAddress = new InetSocketAddress(this.hostname,
Objects.requireNonNullElse(this.port, WOL_UDP_PORT));
sendMagicPacketToIp(magicPacket, socket, socketAddress);
}
} catch (SocketException e) {
logger.error("Failed to open Wake-on-LAN datagram socket", e);
}
}
private void broadcastMagicPacket(byte[] magicPacket, DatagramSocket socket) {
broadcastAddressStream().forEach(broadcastAddress -> {
try {
DatagramPacket packet = new DatagramPacket(magicPacket, MAGIC_PACKET_BYTE_SIZE, broadcastAddress,
WOL_UDP_PORT);
socket.send(packet);
logger.debug("Wake-on-LAN packet sent (MAC address: {}, broadcast address: {})", macAddress,
broadcastAddress.getHostAddress());
} catch (IOException e) {
logger.debug("Failed to send Wake-on-LAN packet (MAC address: {}, broadcast address: {})", macAddress,
broadcastAddress.getHostAddress(), e);
}
});
logger.info("Wake-on-LAN packets sent (MAC address: {})", macAddress);
}
private void sendMagicPacketToIp(byte[] magicPacket, DatagramSocket socket, SocketAddress ip) {
DatagramPacket packet = new DatagramPacket(magicPacket, MAGIC_PACKET_BYTE_SIZE, ip);
try {
socket.send(packet);
} catch (IOException e) {
logger.debug("Failed to send Wake-on-LAN packet (MAC address: {}, address: {})", macAddress, ip, e);
}
logger.info("Wake-on-LAN packets sent (MAC address: {}, IP address: {})", macAddress, ip);
}
private Stream<InetAddress> broadcastAddressStream() {
return NetUtil.getAllBroadcastAddresses().stream().map(address -> {
try {

View File

@ -198,7 +198,8 @@ public class NetworkHandler extends BaseThingHandler
presenceDetection.setRefreshInterval(handlerConfiguration.refreshInterval.longValue());
presenceDetection.setTimeout(handlerConfiguration.timeout.intValue());
wakeOnLanPacketSender = new WakeOnLanPacketSender(handlerConfiguration.macAddress);
wakeOnLanPacketSender = new WakeOnLanPacketSender(handlerConfiguration.macAddress,
handlerConfiguration.hostname, handlerConfiguration.port);
updateStatus(ThingStatus.ONLINE);
presenceDetection.startAutomaticRefresh(scheduler);

View File

@ -17,9 +17,12 @@ import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.openhab.binding.network.internal.WakeOnLanPacketSender.*;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Timeout;
import org.openhab.core.util.HexUtils;
@ -29,7 +32,7 @@ import org.openhab.core.util.HexUtils;
*
* @author Wouter Born - Initial contribution
*/
@Timeout(value = 10, unit = TimeUnit.SECONDS)
@Timeout(value = 10)
public class WakeOnLanPacketSenderTest {
private void assertValidMagicPacket(byte[] macBytes, byte[] packet) {
@ -79,6 +82,49 @@ public class WakeOnLanPacketSenderTest {
assertValidMagicPacket(HexUtils.hexToBytes("6f70656e4841"), actualPacket);
}
@Test
public void sendWithHostnameAndPort() throws IOException, InterruptedException {
sendWOLTest("127.0.0.1", 4444);
}
@Test
public void sendWithHostnameAndPortNull() throws IOException, InterruptedException {
sendWOLTest("127.0.0.1", null);
}
@Test
public void sendWithHostnameNullAndPortNull() throws IOException, InterruptedException {
sendWOLTest(null, null);
}
@Test
public void sendWithHostnameNull() throws IOException, InterruptedException {
sendWOLTest(null, 4444);
}
private void sendWOLTest(String hostname, Integer port) throws InterruptedException, IOException {
DatagramSocket socket = new DatagramSocket(4444);
byte[] buf = new byte[256];
DatagramPacket datagramPacket = new DatagramPacket(buf, buf.length);
while (socket.isClosed()) {
Thread.sleep(100);
}
WakeOnLanPacketSender sender = new WakeOnLanPacketSender("6f70656e4841", hostname, port);
sender.sendPacket();
// This Test is only applicable for IP Requests
if (hostname != null && port != null) {
socket.receive(datagramPacket);
}
socket.close();
Assertions.assertTrue(datagramPacket.getData().length > 0);
}
@Test
public void sendWithEmptyMacAddressThrowsException() {
assertThrows(IllegalStateException.class, () -> new WakeOnLanPacketSender("").sendPacket());