forked from robvanderleek/JLifx
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
fe3bb39
commit 3bf5e89
Showing
10 changed files
with
577 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#!/bin/sh | ||
mvn compile assembly:single | ||
TARGET="$HOME/Desktop/lifx.jar" | ||
cp target/*with-dependencies.jar $HOME/Desktop/lifx.jar | ||
echo "Launchable jar (lifx.jar) copied to $TARGET" | ||
echo "Installation done." |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" | ||
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd"> | ||
<modelVersion>4.0.0</modelVersion> | ||
<groupId>Lifx</groupId> | ||
<artifactId>Lifx</artifactId> | ||
<packaging>jar</packaging> | ||
<version>1.0-SNAPSHOT</version> | ||
<name>Lifx</name> | ||
<url>https://maven.apache.org</url> | ||
<properties> | ||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||
</properties> | ||
<build> | ||
<plugins> | ||
<plugin> | ||
<groupId>org.apache.maven.plugins</groupId> | ||
<artifactId>maven-compiler-plugin</artifactId> | ||
<version>2.0.2</version> | ||
<configuration> | ||
<source>1.5</source> | ||
<target>1.5</target> | ||
</configuration> | ||
</plugin> | ||
<plugin> | ||
<artifactId>maven-assembly-plugin</artifactId> | ||
<configuration> | ||
<archive> | ||
<manifest> | ||
<mainClass>lifx.Main</mainClass> | ||
</manifest> | ||
</archive> | ||
<descriptorRefs> | ||
<descriptorRef>jar-with-dependencies</descriptorRef> | ||
</descriptorRefs> | ||
</configuration> | ||
</plugin> | ||
</plugins> | ||
<resources> | ||
<resource> | ||
<directory>${basedir}/src/main/resources</directory> | ||
<filtering>false</filtering> | ||
<includes> | ||
<include>**/*.properties</include> | ||
<include>**/*.xml</include> | ||
<include>**/Lifx-icon.png</include> | ||
</includes> | ||
</resource> | ||
</resources> | ||
<testResources> | ||
<testResource> | ||
<directory>src/test/resources</directory> | ||
</testResource> | ||
</testResources> | ||
</build> | ||
<dependencies> | ||
<dependency> | ||
<groupId>junit</groupId> | ||
<artifactId>junit</artifactId> | ||
<version>3.8.1</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.uispec4j</groupId> | ||
<artifactId>uispec4j</artifactId> | ||
<classifier>jdk16</classifier> | ||
<version>2.4</version> | ||
<scope>test</scope> | ||
</dependency> | ||
<dependency> | ||
<groupId>org.apache.commons</groupId> | ||
<artifactId>commons-lang3</artifactId> | ||
<version>3.1</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-io</groupId> | ||
<artifactId>commons-io</artifactId> | ||
<version>2.4</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>commons-logging</groupId> | ||
<artifactId>commons-logging</artifactId> | ||
<version>1.1</version> | ||
</dependency> | ||
<dependency> | ||
<groupId>net.sourceforge.collections</groupId> | ||
<artifactId>collections-generic</artifactId> | ||
<version>4.01</version> | ||
</dependency> | ||
</dependencies> | ||
</project> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
package lifx; | ||
|
||
import java.net.InetAddress; | ||
|
||
public class Bulb { | ||
private final InetAddress inetAddress; | ||
private final byte[] macAddress; | ||
|
||
public Bulb(InetAddress inetAddress, byte[] macAddress) { | ||
this.inetAddress = inetAddress; | ||
this.macAddress = macAddress; | ||
} | ||
|
||
public InetAddress getInetAddress() { | ||
return inetAddress; | ||
} | ||
|
||
public byte[] getMacAddress() { | ||
return macAddress; | ||
} | ||
|
||
public String getMacAddressAsString() { | ||
return String.format("%02x:%02x:%02x:%02x:%02x:%02x", macAddress[0], macAddress[1], macAddress[2], | ||
macAddress[3], macAddress[4], macAddress[5]); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package lifx; | ||
|
||
import java.io.DataOutputStream; | ||
import java.io.IOException; | ||
import java.io.PrintStream; | ||
import java.net.DatagramPacket; | ||
import java.net.DatagramSocket; | ||
import java.net.InetAddress; | ||
import java.net.InterfaceAddress; | ||
import java.net.NetworkInterface; | ||
import java.net.Socket; | ||
import java.net.SocketException; | ||
import java.util.ArrayList; | ||
import java.util.Collections; | ||
import java.util.List; | ||
|
||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
public class Main { | ||
private static final Log LOG = LogFactory.getLog(Main.class); | ||
private static final int PORT = 56700; | ||
private static PrintStream OUT = System.out; | ||
|
||
private static void printUsage() { | ||
OUT.println("Usage:"); | ||
OUT.println(" java -jar lifx.jar <command>"); | ||
OUT.println(""); | ||
OUT.println("Where command can be:"); | ||
OUT.println(" scan:"); | ||
OUT.println(" Scan local network for a gateway bulb"); | ||
OUT.println(" switch <mac-address> [on|off]:"); | ||
OUT.println(" Switch selected bulb on/off"); | ||
} | ||
|
||
public static void main(String[] args) throws IOException { | ||
if (args.length < 1) { | ||
printUsage(); | ||
System.exit(1); | ||
} | ||
if (args[0].equalsIgnoreCase("scan")) { | ||
new Main().scan(); | ||
} else if (args[0].equalsIgnoreCase("switch")) { | ||
if (args.length != 3 || (!(args[2].equalsIgnoreCase("on") || args[2].equalsIgnoreCase("off")))) { | ||
printUsage(); | ||
} else { | ||
new Main().powerSwitchBulb(parseMacAddress(args[1]), args[2].equalsIgnoreCase("on") ? true : false); | ||
} | ||
} | ||
} | ||
|
||
private static byte[] parseMacAddress(String macAddress) { | ||
byte[] result = new byte[6]; | ||
result[0] = (byte)(Integer.parseInt(macAddress.substring(0, 2), 16)); | ||
result[1] = (byte)(Integer.parseInt(macAddress.substring(3, 5), 16)); | ||
result[2] = (byte)(Integer.parseInt(macAddress.substring(6, 8), 16)); | ||
result[3] = (byte)(Integer.parseInt(macAddress.substring(9, 11), 16)); | ||
result[4] = (byte)(Integer.parseInt(macAddress.substring(12, 14), 16)); | ||
result[5] = (byte)(Integer.parseInt(macAddress.substring(15, 17), 16)); | ||
return result; | ||
} | ||
|
||
private void scan() { | ||
Bulb gatewayBulb = discoverGatewayBulb(); | ||
if (gatewayBulb == null) { | ||
OUT.println("No LifX gateway bulb found!"); | ||
} else { | ||
OUT.println("Found LifX gateway bulb!"); | ||
OUT.println(" IP address: " + gatewayBulb.getInetAddress()); | ||
OUT.println(" Mac address: " + gatewayBulb.getMacAddressAsString()); | ||
} | ||
} | ||
|
||
private void powerSwitchBulb(byte[] macAddress, boolean on) throws IOException { | ||
Bulb gatewayBulb = discoverGatewayBulb(); | ||
PowerManagementPacket packet = new PowerManagementPacket(macAddress, on); | ||
Socket socket = new Socket(gatewayBulb.getInetAddress(), PORT); | ||
DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream()); | ||
dataOutputStream.write(packet.toByteArray()); | ||
socket.close(); | ||
} | ||
|
||
private Bulb discoverGatewayBulb() { | ||
LOG.info("Discovering gateway bulb..."); | ||
List<InetAddress> networkBroadcastAddresses = getNetworkBroadcastAddresses(); | ||
for (InetAddress broadcastAddress : networkBroadcastAddresses) { | ||
Bulb result = discoverGatewayBulb(broadcastAddress); | ||
if (result != null) { | ||
LOG.info("Found gateway bulb! (" + result.getInetAddress() + ")"); | ||
return result; | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private Bulb discoverGatewayBulb(InetAddress broadcastAddress) { | ||
Bulb result = null; | ||
Packet packet = new Packet(); | ||
byte[] byteArray = packet.toByteArray(); | ||
try { | ||
DatagramSocket socket = new DatagramSocket(PORT); | ||
DatagramPacket datagramPacket = new DatagramPacket(byteArray, 0, byteArray.length, broadcastAddress, PORT); | ||
socket.send(datagramPacket); | ||
DatagramPacket answer = new DatagramPacket(byteArray, 0, byteArray.length); | ||
socket.receive(answer); | ||
if (answer.getAddress().isSiteLocalAddress()) { | ||
socket.receive(answer); | ||
} | ||
Packet answerLifxPacket = Packet.fromDatagramPacket(answer); | ||
result = new Bulb(answer.getAddress(), answerLifxPacket.getGatewayMac()); | ||
} catch (SocketException e) {} catch (IOException e) {} | ||
return result; | ||
} | ||
|
||
List<InetAddress> getNetworkBroadcastAddresses() { | ||
List<InetAddress> result = new ArrayList<InetAddress>(); | ||
try { | ||
List<NetworkInterface> networkInterfaces = Collections.list(NetworkInterface.getNetworkInterfaces()); | ||
for (NetworkInterface networkInterface : networkInterfaces) { | ||
if (!networkInterface.isLoopback() && networkInterface.isUp()) { | ||
List<InterfaceAddress> interfaceAddresses = networkInterface.getInterfaceAddresses(); | ||
for (InterfaceAddress interfaceAddress : interfaceAddresses) { | ||
InetAddress broadcast = interfaceAddress.getBroadcast(); | ||
if (broadcast != null) { | ||
result.add(broadcast); | ||
} | ||
} | ||
} | ||
} | ||
} catch (SocketException e) { | ||
LOG.error("Could not retreive broadcast addresses from available network interfaces"); | ||
} | ||
return result; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
package lifx; | ||
|
||
import java.io.ByteArrayOutputStream; | ||
import java.io.IOException; | ||
import java.net.DatagramPacket; | ||
|
||
import org.apache.commons.lang3.ArrayUtils; | ||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
public class Packet { | ||
private static final Log LOG = LogFactory.getLog(Packet.class); | ||
private byte[] size = new byte[] {0x24, 0x00}; | ||
private byte[] protocol = new byte[] {0x00, 0x34}; | ||
private byte[] reserved = new byte[] {0x00, 0x00, 0x00, 0x00}; | ||
private byte[] targetMac = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
private byte[] reserved2 = new byte[] {0x00, 0x00}; | ||
private byte[] gatewayMac = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
private byte[] reserved3 = new byte[] {0x00, 0x00}; | ||
private byte[] timestamp = new byte[] {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
private byte[] type = new byte[] {0x02, 0x00}; | ||
private byte[] reserved4 = new byte[] {0x00, 0x00}; | ||
|
||
public Packet() {} | ||
|
||
public Packet(byte[] targetMac, byte[] type) { | ||
this.targetMac = targetMac; | ||
this.gatewayMac = targetMac; | ||
this.type = type; | ||
} | ||
|
||
public Packet(byte[] targetMac, byte[] gatewayMac, byte[] timestamp, byte[] type) { | ||
this.targetMac = targetMac; | ||
this.gatewayMac = gatewayMac; | ||
this.timestamp = timestamp; | ||
this.type = type; | ||
} | ||
|
||
public byte[] getTargetMac() { | ||
return targetMac; | ||
} | ||
|
||
public byte[] getGatewayMac() { | ||
return gatewayMac; | ||
} | ||
|
||
public byte[] getTimestamp() { | ||
return timestamp; | ||
} | ||
|
||
public byte[] getType() { | ||
return type; | ||
} | ||
|
||
public byte[] toByteArray() { | ||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
try { | ||
outputStream.write(size); | ||
outputStream.write(protocol); | ||
outputStream.write(reserved); | ||
outputStream.write(targetMac); | ||
outputStream.write(reserved2); | ||
outputStream.write(gatewayMac); | ||
outputStream.write(reserved3); | ||
outputStream.write(timestamp); | ||
outputStream.write(type); | ||
outputStream.write(reserved4); | ||
} catch (IOException e) { | ||
LOG.error("Could not build Lifx packet"); | ||
} | ||
return outputStream.toByteArray(); | ||
} | ||
|
||
public static Packet fromDatagramPacket(DatagramPacket datagramPacket) { | ||
byte[] data = datagramPacket.getData(); | ||
return new Packet(ArrayUtils.subarray(data, 8, 13), ArrayUtils.subarray(data, 16, 22), ArrayUtils.subarray( | ||
data, 23, 31), ArrayUtils.subarray(data, 31, 33)); | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
package lifx; | ||
|
||
import java.io.IOException; | ||
|
||
import org.apache.commons.io.output.ByteArrayOutputStream; | ||
import org.apache.commons.logging.Log; | ||
import org.apache.commons.logging.LogFactory; | ||
|
||
public class PowerManagementPacket extends Packet { | ||
private static final Log LOG = LogFactory.getLog(PowerManagementPacket.class); | ||
private final boolean on; | ||
|
||
public PowerManagementPacket(byte[] targetMacAddress, boolean on) { | ||
super(targetMacAddress, new byte[] {0x15, 0x00}); | ||
this.on = on; | ||
} | ||
|
||
@Override | ||
public byte[] toByteArray() { | ||
byte[] result = new byte[] {}; | ||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); | ||
try { | ||
outputStream.write(super.toByteArray()); | ||
outputStream.write(on ? 0x01 : 0x00); | ||
outputStream.write(0x00); | ||
result = outputStream.toByteArray(); | ||
outputStream.close(); | ||
result[0] = 0x26; | ||
} catch (IOException e) { | ||
LOG.error("Error building packet"); | ||
} | ||
return result; | ||
} | ||
} |
Oops, something went wrong.