WHAT WE THINK?

I’ve got the power – how to control remotely your PC using Grails

Sent on: 21.08.2018 | Comments:0
I’ve got the power –  how to control remotely your PC using Grails

In this article I will show you how to control remotely your windows computer via the local network using Linux machine and Grails application. First we will turn on a device with Wake-On-LAN (WOL) method and then turn it off using RPC shutdown command call. After this few steps, you won’t have to push the power button on your computer any more.

 

1. Turn on a computer – wake up, darling!!!

 

To begin with we have to check a few configuration things:

  • check if BIOS allows to use Wake-On-LAN on the computer. Go to BIOS power management settings and find the Wake-On-Lan configuration there. If related option does not exist it probably means that BIOS automatically supports WOL – most of new hardware does that. When you find an appropriate option check if it is enabled. Depends on your computer motherboard, it is automatically enabled or you will have to set it manually.
  • check your system configuration. Open Windows Device Manager, find your local network device. Right click on a device and select “Properties”. Next, select Advanced tab, find a “Wake on Magic Packet” option and check if it is enabled.

 

artukuł_WOL_config

 

Now it’s time to write a piece of code which will send a Wake-On-LAN magic packet to your device. For this purpose I have created project in Grails 3.2.0. Create a new service called “WakeOnLanService”.

 

First method converts device’s MAC address from String to byte array:


private static byte[] getMacBytes(String macAddress) 
    throws IllegalArgumentException {
    byte[] bytes
    String[] hex = macAddress.split("(\\:|\\-)")
    if(hex.length != 6) {
        throw new IllegalArgumentException("Invalid MAC address.")
    }
    try {
        bytes = hex.collect { (byte) Integer.parseInt(it, 16) }
    } catch (NumberFormatException e) {
        throw new IllegalArgumentException("Invalid hex digit in MAC address.")
    }
    return bytes
}

This method allows to pass MAC address as an argument in two formats “AA:AA:AA:AA:AA:AA” or “AA-AA-AA-AA-AA-AA”. Second method generates a magic packet from received MAC address byte array:


private static byte[] generateMagicPacket(byte[] macBytes) {
    ByteArrayOutputStream byteStream = new ByteArrayOutputStream()

    6.times { byteStream.write(0xff)}
    16.times { byteStream.write(macBytes) }

    return byteStream.toByteArray()
}

Finally the last method is used for broadcasting magic packet to all devices in your local network:


static final int PORT = 9
static final String DEFAULT_BROADCAST_IP = '255.255.255.255'

boolean sendWOLPacket(String macAddress, String broadcastIp=DEFAULT_BROADCAST_IP) {
    if(!macAddress) {
        return false
    }

    byte[] wol= generateMagicPacket(getMacBytes(macAddress))

    InetAddress address = InetAddress.getByName(broadcastIp)
    DatagramPacket packet = new DatagramPacket(wol, wol.length, address, PORT)
    DatagramSocket socket = new DatagramSocket()
    socket.send(packet)
    socket.close()

    return true
}

Now you should be able to start your windows machine remotely. PORT and BROADCAST_IP are the default values and can be changed e.g. when you want to send magic packet through a router.

 

2. Turn off the computer – just stop talking to me

 

To turn off the Windows machine we will use a shutdown method executed by remote procedure call (RPC). To do that we execute a samba net command:


net rpc shutdown -I {ipAddress} -U {username}%{password}

IpAddress is a remote windows machine IP address, username and password are credentials of a windows user with administrative privileges.

 

Below are the configuration steps needed:

  • Firstly, check if your Linux system has samba packages installed. We will use “net rpc” command to communicate with remote computer. For Ubuntu/Debian Linux distribution it is included in samba-common-bin package. To install samba use console command “sudo apt-get install samba-common-bin”.
  • Configure your windows machine to disable UAC remote restrictions. Locate the following registry subkey: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System. Check if the LocalAccountTokenFilterPolicy registry entry does exist. If not, create a new entry with DWORD value “1”.
  • check if firewall has opened port 445 for TCP connection. When not exist then you should add a new role in the firewall.

It’s time to write our Grails service for turning off the machine. I have created shutdownService file in Grails project which contains following methods:

 

void invokeShutdown(String ipAddress, String username, String password) {
    List<String> command = getShutdownCommand(ipAddress, username, password)

    StringBuilder outputStream = new StringBuilder()

    try {
        ProcessBuilder builder = new ProcessBuilder(command)
        Process process = builder.start()
        process.consumeProcessOutput(outputStream, outputStream)
        process.waitFor()
    } catch (Exception e) {
        throw new IOException(e.message)
    }
}

List<String> getShutdownCommand(String ipAddress, String username, String password) {
    return [
               'net',
               'rpc',
               'shutdown',
               '-I', "$ipAddress",
               '-U', "$username%$password"
           ]
}

 

That’s all!!! Now you should be able to control your computer remotely. You can use it in some kind of centralized control panel and control a bunch of computers from one place. You can create a schedule when computers are working and not.

Add comment: