diff --git a/pom.xml b/pom.xml index f7862f2..cb87fc3 100644 --- a/pom.xml +++ b/pom.xml @@ -27,132 +27,138 @@ - Christian Fischer (computerlyrik) --> - 4.0.0 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 - com.github.mob41.blapi - broadlink-java-api - jar + com.github.mob41.blapi + broadlink-java-api + jar - broadlink-java-api - A clean, hacked Broadlink API for Java - http://github.com/mob41/broadlink-java-api - - - - MIT License - http://www.opensource.org/licenses/mit-license.php - - - - - - Anthony Law - anthonylaw0401@gmail.com - Anthony Law - http://github.com/mob41 - - - - - scm:git:git://github.com/mob41/broadlink-java-api.git - scm:git:ssh://github.com:mob41/broadlink-java-api.git - http://github.com/mob41/broadlink-java-api/tree/master - - - - - ossrh - https://oss.sonatype.org/content/repositories/snapshots - - - ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ - - + broadlink-java-api + A clean, hacked Broadlink API for Java + http://github.com/mob41/broadlink-java-api - - UTF-8 - 1.8 - 1.8 - + + + MIT License + http://www.opensource.org/licenses/mit-license.php + + - - - junit - junit - 4.12 - test - - - org.slf4j - slf4j-api - 1.7.22 - - - org.slf4j - slf4j-simple - 1.7.22 - test - - - - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar-no-fork - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9.1 - - - attach-javadocs - - jar - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - org.codehaus.mojo - cobertura-maven-plugin - 2.7 - - - html - xml - - - - - - - - 1.0.1 + + + Anthony Law + anthonylaw0401@gmail.com + Anthony Law + http://github.com/mob41 + + + + + scm:git:git://github.com/mob41/broadlink-java-api.git + scm:git:ssh://github.com:mob41/broadlink-java-api.git + http://github.com/mob41/broadlink-java-api/tree/master + + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + + + + UTF-8 + 1.8 + 1.8 + + + + + junit + junit + 4.12 + test + + + org.hamcrest + hamcrest + 2.2 + test + + + org.slf4j + slf4j-api + 1.7.22 + + + org.slf4j + slf4j-simple + 1.7.22 + test + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar-no-fork + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + org.codehaus.mojo + cobertura-maven-plugin + 2.7 + + + html + xml + + + + + + + + 1.0.1 diff --git a/src/main/java/com/github/mob41/blapi/A1Device.java b/src/main/java/com/github/mob41/blapi/A1Device.java index 03e683e..1dea0d7 100644 --- a/src/main/java/com/github/mob41/blapi/A1Device.java +++ b/src/main/java/com/github/mob41/blapi/A1Device.java @@ -31,12 +31,12 @@ import java.io.IOException; import java.net.DatagramPacket; -import javax.xml.bind.DatatypeConverter; - import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.CmdPayload; import com.github.mob41.blapi.pkt.Payload; +import static com.github.mob41.blapi.ByteToHexString.*; + public class A1Device extends BLDevice { public A1Device(String host, Mac mac) throws IOException { @@ -68,13 +68,13 @@ public byte[] getData() { }); byte[] data = packet.getData(); - log.debug("A1 check sensors received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("A1 check sensors received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { byte[] pl = decryptFromDeviceMessage(data); - log.debug("A1 check sensors received bytes (decrypted):" + DatatypeConverter.printHexBinary(pl)); + log.debug("A1 check sensors received bytes (decrypted):" + toHexString(pl)); float temp = (float) ((pl[0x4] * 10 + pl[0x5]) / 10.0); float hum = (float) ((pl[0x6] * 10 + pl[0x7]) / 10.0); diff --git a/src/main/java/com/github/mob41/blapi/BLDevice.java b/src/main/java/com/github/mob41/blapi/BLDevice.java index da60a5f..2ce1068 100644 --- a/src/main/java/com/github/mob41/blapi/BLDevice.java +++ b/src/main/java/com/github/mob41/blapi/BLDevice.java @@ -38,8 +38,6 @@ import java.util.List; import java.util.Random; -import javax.xml.bind.DatatypeConverter; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -51,6 +49,8 @@ import com.github.mob41.blapi.pkt.auth.AuthCmdPayload; import com.github.mob41.blapi.pkt.dis.DiscoveryPacket; +import static com.github.mob41.blapi.ByteToHexString.*; + /** * This is the base class of all Broadlink devices (e.g. SP1, RMPro) * @@ -389,7 +389,7 @@ public boolean auth(boolean reauth) throws IOException { log.debug("auth Sending CmdPacket with AuthCmdPayload: cmd=" + Integer.toHexString(sendPayload.getCommand()) + " len=" + sendPayload.getPayload().getData().length); - log.debug("auth AuthPayload initial bytes to send: {}", DatatypeConverter.printHexBinary(sendPayload.getPayload().getData())); + log.debug("auth AuthPayload initial bytes to send: {}", toHexString(sendPayload.getPayload().getData())); DatagramPacket recvPack = sendCmdPkt(10000, 2048, sendPayload); @@ -401,7 +401,7 @@ public boolean auth(boolean reauth) throws IOException { return false; } - log.debug("auth recv encrypted data bytes (" + data.length +") after initial req: {}", DatatypeConverter.printHexBinary(data)); + log.debug("auth recv encrypted data bytes (" + data.length +") after initial req: {}", toHexString(data)); byte[] payload = null; try { @@ -417,11 +417,11 @@ public boolean auth(boolean reauth) throws IOException { return false; } - log.debug("auth Packet received payload bytes: " + DatatypeConverter.printHexBinary(payload)); + log.debug("auth Packet received payload bytes: " + toHexString(payload)); key = subbytes(payload, 0x04, 0x14); - log.debug("auth Packet received key bytes: " + DatatypeConverter.printHexBinary(key)); + log.debug("auth Packet received key bytes: " + toHexString(key)); if (key.length % 16 != 0) { log.error("auth Received key len is not a multiple of 16! Aborting"); @@ -434,7 +434,7 @@ public boolean auth(boolean reauth) throws IOException { id = subbytes(payload, 0x00, 0x04); - log.debug("auth Packet received id bytes: " + DatatypeConverter.printHexBinary(id) + " with ID len=" + id.length); + log.debug("auth Packet received id bytes: " + toHexString(id) + " with ID len=" + id.length); log.debug("auth End of authentication method"); alreadyAuthorized = true; @@ -530,7 +530,7 @@ public DatagramPacket sendCmdPkt(int timeout, int bufSize, CmdPayload cmdPayload public DatagramPacket sendCmdPkt(InetAddress sourceIpAddr, int sourcePort, int timeout, int bufSize, CmdPayload cmdPayload) throws IOException { CmdPacket cmdPkt = new CmdPacket(mac, pktCount++, id, aes, cmdPayload); - log.debug("sendCmdPkt - Send Command Packet bytes: {}", DatatypeConverter.printHexBinary(cmdPkt.getData())); + log.debug("sendCmdPkt - Send Command Packet bytes: {}", toHexString(cmdPkt.getData())); return sendPkt(sock, cmdPkt, InetAddress.getByName(host), 80, timeout, bufSize); } @@ -1041,7 +1041,7 @@ public static DatagramPacket sendPkt(DatagramSocket sock, Packet pkt, InetAddres } } - log.debug("sendPkt - recv data bytes (" + recepack.getData().length +") after initial req: {}", DatatypeConverter.printHexBinary(recepack.getData())); + log.debug("sendPkt - recv data bytes (" + recepack.getData().length +") after initial req: {}", toHexString(recepack.getData())); recepack.setData(removeNullsFromEnd(recepack.getData(), 0)); return recepack; } diff --git a/src/main/java/com/github/mob41/blapi/ByteToHexString.java b/src/main/java/com/github/mob41/blapi/ByteToHexString.java new file mode 100644 index 0000000..f514579 --- /dev/null +++ b/src/main/java/com/github/mob41/blapi/ByteToHexString.java @@ -0,0 +1,24 @@ +package com.github.mob41.blapi; + +public final class ByteToHexString { + private static final char[] hexCode = "0123456789ABCDEF".toCharArray(); + + private ByteToHexString() { + } + + /** + * Converts the given byte array to a hex string where each byte is represented by exactly two characters. + * For example, a byte + * + * @param data the array to convert + * @return the resulting hex string + */ + public static String toHexString(byte[] data) { + StringBuilder r = new StringBuilder(data.length * 2); + for (byte b : data) { + r.append(hexCode[(b >> 4) & 0xF]); + r.append(hexCode[(b & 0xF)]); + } + return r.toString(); + } +} diff --git a/src/main/java/com/github/mob41/blapi/MP1Device.java b/src/main/java/com/github/mob41/blapi/MP1Device.java index c7a8143..a4c4ee3 100644 --- a/src/main/java/com/github/mob41/blapi/MP1Device.java +++ b/src/main/java/com/github/mob41/blapi/MP1Device.java @@ -32,12 +32,12 @@ import java.io.IOException; import java.net.DatagramPacket; -import javax.xml.bind.DatatypeConverter; - import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.CmdPayload; import com.github.mob41.blapi.pkt.Payload; +import static com.github.mob41.blapi.ByteToHexString.*; + public class MP1Device extends BLDevice { /** * Generic way to create a MP1Device @@ -116,7 +116,7 @@ public byte[] getData() { int err = data[0x22] | (data[0x23] << 8); if (err == 0) { - log.debug("MP1 set state mask received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("MP1 set state mask received encrypted bytes: " + toHexString(data)); } else { log.warn("MP1 set state mask received returned err: " + Integer.toHexString(err) + " / " + err); } @@ -171,13 +171,13 @@ public byte[] getData() { byte[] data = packet.getData(); - log.debug("MP1 get states raw received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("MP1 get states raw received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { byte[] pl = decryptFromDeviceMessage(data); - log.debug("MP1 get states raw received bytes (decrypted): " + DatatypeConverter.printHexBinary(pl)); + log.debug("MP1 get states raw received bytes (decrypted): " + toHexString(pl)); byte state = 0; if (pl[0x3c] >= 48 && pl[0x3c] <= 57) { String decodeValue1; diff --git a/src/main/java/com/github/mob41/blapi/RM2Device.java b/src/main/java/com/github/mob41/blapi/RM2Device.java index 301644d..dff09cc 100644 --- a/src/main/java/com/github/mob41/blapi/RM2Device.java +++ b/src/main/java/com/github/mob41/blapi/RM2Device.java @@ -31,13 +31,13 @@ import java.io.IOException; import java.net.DatagramPacket; -import javax.xml.bind.DatatypeConverter; - import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.cmd.rm2.CheckDataCmdPayload; import com.github.mob41.blapi.pkt.cmd.rm2.EnterLearnCmdPayload; import com.github.mob41.blapi.pkt.cmd.rm2.RMTempCmdPayload; +import static com.github.mob41.blapi.ByteToHexString.*; + /** * Broadlink RM2 device client * @@ -88,7 +88,7 @@ public byte[] checkData() throws Exception { int err = data[0x22] | (data[0x23] << 8); - log.debug("RM2 check data received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("RM2 check data received encrypted bytes: " + toHexString(data)); if (err == 0) { @@ -115,7 +115,7 @@ public boolean enterLearning() throws IOException { DatagramPacket packet = sendCmdPkt(10000, cmdPayload); byte[] data = packet.getData(); - log.debug("RM2 enter learning received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("RM2 enter learning received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { @@ -139,12 +139,12 @@ public double getTemp() throws Exception { DatagramPacket packet = sendCmdPkt(new RMTempCmdPayload()); byte[] data = packet.getData(); - log.debug("RM2 get temp received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("RM2 get temp received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { byte[] pl = decryptFromDeviceMessage(data); - log.debug("RM2 get temp received bytes (decrypted): " + DatatypeConverter.printHexBinary(pl)); + log.debug("RM2 get temp received bytes (decrypted): " + toHexString(pl)); return (double) (pl[0x4] * 10 + pl[0x5]) / 10.0; } else { diff --git a/src/main/java/com/github/mob41/blapi/SP1Device.java b/src/main/java/com/github/mob41/blapi/SP1Device.java index 6bc2829..afce150 100644 --- a/src/main/java/com/github/mob41/blapi/SP1Device.java +++ b/src/main/java/com/github/mob41/blapi/SP1Device.java @@ -32,12 +32,12 @@ import java.io.IOException; import java.net.DatagramPacket; -import javax.xml.bind.DatatypeConverter; - import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.CmdPayload; import com.github.mob41.blapi.pkt.Payload; +import static com.github.mob41.blapi.ByteToHexString.*; + public class SP1Device extends BLDevice { public SP1Device(String host, Mac mac) throws IOException { @@ -70,7 +70,7 @@ public byte[] getData() { byte[] data = packet.getData(); - log.debug("SP1 set power received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("SP1 set power received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); diff --git a/src/main/java/com/github/mob41/blapi/SP2Device.java b/src/main/java/com/github/mob41/blapi/SP2Device.java index ba33cc8..bbfc555 100644 --- a/src/main/java/com/github/mob41/blapi/SP2Device.java +++ b/src/main/java/com/github/mob41/blapi/SP2Device.java @@ -32,12 +32,12 @@ import java.io.IOException; import java.net.DatagramPacket; -import javax.xml.bind.DatatypeConverter; - import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.CmdPayload; import com.github.mob41.blapi.pkt.Payload; +import static com.github.mob41.blapi.ByteToHexString.*; + public class SP2Device extends BLDevice { protected SP2Device(short deviceType, String deviceDesc, String host, Mac mac) throws IOException { @@ -75,7 +75,7 @@ public byte[] getData() { byte[] data = packet.getData(); - log.debug("SP2 set state received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("SP2 set state received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); @@ -109,13 +109,13 @@ public byte[] getData() { }); byte[] data = packet.getData(); - log.debug("SP2 get state received encrypted bytes: " + DatatypeConverter.printHexBinary(data)); + log.debug("SP2 get state received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { byte[] pl = decryptFromDeviceMessage(data); - log.debug("SP2 get state received bytes (decrypted): " + DatatypeConverter.printHexBinary(pl)); + log.debug("SP2 get state received bytes (decrypted): " + toHexString(pl)); return pl[0x4] == 1 ? true : false; } else { log.warn("SP2 get state received an error: " + Integer.toHexString(err) + " / " + err); diff --git a/src/main/java/com/github/mob41/blapi/dev/hysen/BaseHysenDevice.java b/src/main/java/com/github/mob41/blapi/dev/hysen/BaseHysenDevice.java index d8cf639..132302e 100644 --- a/src/main/java/com/github/mob41/blapi/dev/hysen/BaseHysenDevice.java +++ b/src/main/java/com/github/mob41/blapi/dev/hysen/BaseHysenDevice.java @@ -31,7 +31,7 @@ import java.io.IOException; -import javax.xml.bind.DatatypeConverter; +import com.github.mob41.blapi.ByteToHexString; import com.github.mob41.blapi.BLDevice; import com.github.mob41.blapi.mac.Mac; @@ -42,6 +42,8 @@ import com.github.mob41.blapi.pkt.cmd.hysen.SetPoweCommand; import com.github.mob41.blapi.pkt.cmd.hysen.SetTempCommand; +import static com.github.mob41.blapi.ByteToHexString.*; + /** * Base hysen "class" thermostats * @@ -92,7 +94,7 @@ public double getRoomTemp() throws Exception { public BaseStatusInfo getBasicStatus() throws Exception { byte[] pl = new GetBasicInfoCommand().execute(this); if (pl != null) { - log.debug("getBasicStatus - received bytes: {}", DatatypeConverter.printHexBinary(pl)); + log.debug("getBasicStatus - received bytes: {}", toHexString(pl)); return new BaseStatusInfo(pl); } return null; @@ -101,7 +103,7 @@ public BaseStatusInfo getBasicStatus() throws Exception { public AdvancedStatusInfo getAdvancedStatus() throws Exception { byte[] pl = new GetStatusCommand().execute(this); if (pl != null) { - log.debug("getAdvancedStatus - received bytes: {}", DatatypeConverter.printHexBinary(pl)); + log.debug("getAdvancedStatus - received bytes: {}", toHexString(pl)); return new AdvancedStatusInfo(pl); } return null; diff --git a/src/main/java/com/github/mob41/blapi/pkt/CmdPacket.java b/src/main/java/com/github/mob41/blapi/pkt/CmdPacket.java index 939625f..99f11ff 100644 --- a/src/main/java/com/github/mob41/blapi/pkt/CmdPacket.java +++ b/src/main/java/com/github/mob41/blapi/pkt/CmdPacket.java @@ -28,7 +28,7 @@ *******************************************************************************/ package com.github.mob41.blapi.pkt; -import javax.xml.bind.DatatypeConverter; +import com.github.mob41.blapi.ByteToHexString; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +38,8 @@ import com.github.mob41.blapi.mac.Mac; import com.github.mob41.blapi.pkt.auth.AES; +import static com.github.mob41.blapi.ByteToHexString.*; + /** * This constructs a byte array with the format of a command to the Broadlink * device @@ -146,7 +148,7 @@ public CmdPacket(Mac targetMac, int count, byte[] id, AES aesInstance, CmdPayloa log.debug("Encrypting payload"); payload = aesInstance.encrypt(payloadPad); - log.debug("Encrypted payload bytes: {}", DatatypeConverter.printHexBinary(payload)); + log.debug("Encrypted payload bytes: {}", toHexString(payload)); log.debug("Encrypted. len=" + payload.length); } catch (Exception e) { diff --git a/src/main/java/com/github/mob41/blapi/pkt/cmd/hysen/BaseHysenCommand.java b/src/main/java/com/github/mob41/blapi/pkt/cmd/hysen/BaseHysenCommand.java index 0273ad0..c66a76d 100644 --- a/src/main/java/com/github/mob41/blapi/pkt/cmd/hysen/BaseHysenCommand.java +++ b/src/main/java/com/github/mob41/blapi/pkt/cmd/hysen/BaseHysenCommand.java @@ -3,8 +3,6 @@ import java.net.DatagramPacket; import java.util.Arrays; -import javax.xml.bind.DatatypeConverter; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -13,12 +11,14 @@ import com.github.mob41.blapi.pkt.Crc16; import com.github.mob41.blapi.pkt.Payload; +import static com.github.mob41.blapi.ByteToHexString.*; + /** * Base hysen command Payload. Handles crc calculation - * - * + * + * * Adapted from https://github.com/mjg59/python-broadlink - * + * * @author alpapad * */ @@ -32,15 +32,13 @@ public byte[] execute(BaseHysenDevice device) throws Exception { byte[] data = packet.getData(); - log.debug(this.getClass().getSimpleName() + " received encrypted bytes: " - + DatatypeConverter.printHexBinary(data)); + log.debug(this.getClass().getSimpleName() + " received encrypted bytes: " + toHexString(data)); int err = data[0x22] | (data[0x23] << 8); if (err == 0) { byte[] pl = device.decryptFromDeviceMessage(data); - log.debug(this.getClass().getSimpleName() + " received bytes (decrypted): " - + DatatypeConverter.printHexBinary(pl)); + log.debug(this.getClass().getSimpleName() + " received bytes (decrypted): " + toHexString(pl)); return Arrays.copyOfRange(pl, 2, pl.length); } else { log.warn(this.getClass().getSimpleName() + " received an error: " + Integer.toHexString(err) + " / " + err); @@ -59,7 +57,7 @@ public Payload getPayload() { /** * hysen thermostats require a crc16 calculated on the payload before it can be * send and a length field. - * + * * Payload format: 2 bytes len: first byte is len, second is 0. len includes * also CRC (2 bytes_ X bytes payload 2 bytes CRC16 in ModBus format */ diff --git a/src/test/java/com/github/mob41/blapi/ByteToHexStringTest.java b/src/test/java/com/github/mob41/blapi/ByteToHexStringTest.java new file mode 100644 index 0000000..5194695 --- /dev/null +++ b/src/test/java/com/github/mob41/blapi/ByteToHexStringTest.java @@ -0,0 +1,24 @@ +package com.github.mob41.blapi; + +import org.junit.Test; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +public class ByteToHexStringTest { + @Test + public void toHexBinary() { + byte[] source = new byte[Byte.MAX_VALUE - Byte.MIN_VALUE + 1]; + for (int i = 0; i <= Byte.MAX_VALUE - Byte.MIN_VALUE; i++) { + //noinspection NumericCastThatLosesPrecision + source[i] = (byte) (i + Byte.MIN_VALUE); + } + StringBuilder sb = new StringBuilder((Byte.MAX_VALUE - Byte.MIN_VALUE + 1) * 2); + for (byte b : source) { + sb.append(String.format("%02X", b)); + } + String expectedResult = sb.toString(); + + assertThat(ByteToHexString.toHexString(source), is(expectedResult)); + } +} \ No newline at end of file