I have written a small application in Kotlin which sends a Magic Packet to a smart tv over my local network. I used this approach (code), rewritten in Kotlin (plus i hardcoded the IP and MAC for testing purposes).
When the tv is shutdown, i can easily restart it with my application. After a while, that doesn't work anymore.
import java.net.DatagramPacket
import java.net.DatagramSocket
import java.net.InetAddress
fun main() {
magicPacket("A8:23-FE:A0:5C:DB", "192.168.xx.xxx", 7)
}
/**
* Android:
* Network interaction starting in new Thread!
*/
fun magicPacket(mac: String, ip: String, PORT: Int = 7) {
// throws IllegalThreadStateException without declaration
//val t = thread {
val packet = buildPacket(mac)
val datagramSocket = DatagramSocket()
try {
datagramSocket.send(
DatagramPacket(
packet,
packet.size,
InetAddress.getByName(ip),
PORT
)
)
datagramSocket.close()
} catch (e: Exception) {
e.printStackTrace()
}
//}
}
private fun buildPacket(mac: String): ByteArray {
// prepare packet (6 bytes header) (16 * 6 bytes MAC)
val temp = ByteArray(6 + 6 * 16)
val macBytes = ByteArray(6)
for (i in 0..5) {
temp[i] = 0xFF.toByte()
macBytes[i] = mac.split(":", "-")[i].toInt(16).toByte()
}
for (i in 6 until temp.size step macBytes.size) System.arraycopy(
macBytes,
0,
temp,
i,
macBytes.size
)
return temp
}
When sending a wakeonlan packet, you need to make sure the target device can receive the packet.
At the moment, you are sending the packet to the IPv4 address of the device.
When your computer has to send a packet to an IPv4 address, it needs to know its MAC address. So it asks the network "Who has IPv4 192.168.2.32? Tell me your mac address". Since you TV is shutdown, it does not respond.
The real wake on lan packet will never be send, as it des not know the destination mac address.
The real question then becomes, why does it work directly after shutting down, and the reason for this is that your OS keeps a list of IPv4+mac address table, so it can quickly send the packet out. You can view this list with the command arp -av
on Windows
Note how it shows "dynamic" when your program successfully wakes the TV, but shows "invalid" when it fails to wake the TV up.
One solution for this, is sending the packet to the broadcast IPv4 address, which every devices receives. This IPv4 address typically ends with .255
with typical consumer IPv4 ranges.