diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java index d1367d403..8f100f1ad 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupport.java @@ -272,31 +272,6 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { handleGBDeviceEvent(versionCmd); } - public byte[] craftData(byte command_group, byte command, byte[] data) { - //0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB - byte[] result = new byte[FitProConstants.DATA_TEMPLATE.length + data.length]; - System.arraycopy(FitProConstants.DATA_TEMPLATE, 0, result, 0, FitProConstants.DATA_TEMPLATE.length); - result[1] = (byte) (((FitProConstants.DATA_TEMPLATE.length + data.length - 3) >> 8) & 0xff); - result[2] = (byte) ((FitProConstants.DATA_TEMPLATE.length + data.length - 3) & 0xff); - result[3] = command_group; - result[5] = command; - result[6] = (byte) ((data.length >> 8 ) & 0xff); - result[7] = (byte) (data.length & 0xff); - System.arraycopy(data, 0, result, 8, data.length); - //debug - debugPrintArray(result, "crafted packet"); - return result; - } - - // send chucked up data - public void writeChunckedData(TransactionBuilder builder, byte[] data){ - for (int start = 0; start < data.length; start += mtuSize) { - int end = start + mtuSize; - if (end > data.length) end = data.length; - builder.write(writeCharacteristic, Arrays.copyOfRange(data, start, end)); - } - } - @Override public boolean onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) { @@ -488,7 +463,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { } debugPrintArray(craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray()), "crafted call notify"); - writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray())); + writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, outputStream.toByteArray())); } else { builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_CALL, VALUE_OFF)); @@ -644,7 +619,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { byte currentConditionCode = Weather.mapToFitProCondition(weatherSpec.currentConditionCode); TransactionBuilder builder = new TransactionBuilder("weather"); - writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit})); + writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_WEATHER, new byte[]{(byte) todayMin, (byte) todayMax, (byte) currentConditionCode, (byte) weatherUnit})); builder.queue(getQueue()); } @@ -725,7 +700,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { output = outputStream.toString().substring(0, 250); } - writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_MESSAGE, output.getBytes(StandardCharsets.UTF_8))); + writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_NOTIFICATION_MESSAGE, output.getBytes(StandardCharsets.UTF_8))); builder.queue(getQueue()); } @@ -906,7 +881,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { return this; } - public void debugPrintArray(byte[] bytes, String label) { + public static void debugPrintArray(byte[] bytes, String label) { if (!debugEnabled) return; String arrayString = nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils.arrayToString(bytes); LOG.debug("FitPro debug print " + label + ": " + arrayString); @@ -923,12 +898,37 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { return this; } - public byte[] craftData(byte command_group, byte command, byte value) { + public static byte[] craftData(byte command_group, byte command) { + return craftData(command_group, command, new byte[]{}); + } + + public static byte[] craftData(byte command_group, byte command, byte value) { return craftData(command_group, command, new byte[]{value}); } - public byte[] craftData(byte command_group, byte command) { - return craftData(command_group, command, new byte[]{}); + public static byte[] craftData(byte command_group, byte command, byte[] data) { + //0xCD 0x00 0x09 0x12 0x01 0x01 0x00 0x04 0xA5 0x83 0x73 0xDB + byte[] result = new byte[FitProConstants.DATA_TEMPLATE.length + data.length]; + System.arraycopy(FitProConstants.DATA_TEMPLATE, 0, result, 0, FitProConstants.DATA_TEMPLATE.length); + result[1] = (byte) (((FitProConstants.DATA_TEMPLATE.length + data.length - 3) >> 8) & 0xff); + result[2] = (byte) ((FitProConstants.DATA_TEMPLATE.length + data.length - 3) & 0xff); + result[3] = command_group; + result[5] = command; + result[6] = (byte) ((data.length >> 8) & 0xff); + result[7] = (byte) (data.length & 0xff); + System.arraycopy(data, 0, result, 8, data.length); + //debug + debugPrintArray(result, "crafted packet"); + return result; + } + + // send chucked up data + public void writeChunkedData(TransactionBuilder builder, byte[] data) { + for (int start = 0; start < data.length; start += mtuSize) { + int end = start + mtuSize; + if (end > data.length) end = data.length; + builder.write(writeCharacteristic, Arrays.copyOfRange(data, start, end)); + } } @Override @@ -1003,7 +1003,7 @@ public class FitProDeviceSupport extends AbstractBTLEDeviceSupport { } } - writeChunckedData(builder, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); + writeChunkedData(builder, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); //builder.write(writeCharacteristic, craftData(CMD_GROUP_GENERAL, CMD_ALARM, all_alarms)); builder.queue(getQueue()); if (anyAlarmEnabled) { diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupportTest.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupportTest.java new file mode 100644 index 000000000..7ea5ea9a2 --- /dev/null +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/service/devices/fitpro/FitProDeviceSupportTest.java @@ -0,0 +1,69 @@ +package nodomain.freeyourgadget.gadgetbridge.service.devices.fitpro; + +import static junit.framework.TestCase.assertEquals; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.CMD_FIND_BAND; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.CMD_GET_HW_INFO; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.CMD_GROUP_GENERAL; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.CMD_GROUP_REQUEST_DATA; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.CMD_SET_DEVICE_VIBRATIONS; +import static nodomain.freeyourgadget.gadgetbridge.devices.fitpro.FitProConstants.VALUE_ON; +import static nodomain.freeyourgadget.gadgetbridge.util.ArrayUtils.arrayToString; + +import org.junit.Test; + +// invoke individual test this way: +//./gradlew :app:testMainDebugUnitTest --tests nodomain.freeyourgadget.gadgetbridge.service.devices.fitpro.FitProDeviceSupportTest + +public class FitProDeviceSupportTest { + + @Test + public void testCraftDataFromCommandAndSingleValue() { + byte[] data = FitProDeviceSupport.craftData(CMD_GROUP_REQUEST_DATA, CMD_GET_HW_INFO); + String result = arrayToString(data); + String expected = arrayToString(new byte[]{(byte) 0xCD, 0x00, 0x05, 0x1A, 0x01, 0x10, 0x00, 0x00}); + System.out.println("fitpro test, data 1: " + result); + assertEquals(expected, result); + } + + @Test + public void testCraftDataFromCommandSingleValueAndParameter() { + byte[] data = FitProDeviceSupport.craftData(CMD_GROUP_GENERAL, CMD_FIND_BAND, VALUE_ON); + String result = arrayToString(data); + String expected = arrayToString(new byte[]{(byte) 0xCD, 0x00, 0x06, 0x12, 0x01, 0x0B, 0x00, 0x01, 0x01}); + System.out.println("fitpro test, data 2: " + result); + assertEquals(expected, result); + } + + @Test + public void testCraftDataFromCommandAndByteArray() { + byte[] data = FitProDeviceSupport.craftData(CMD_GROUP_GENERAL, CMD_SET_DEVICE_VIBRATIONS, new byte[]{0, 0, 0, 0}); + String result = arrayToString(data); + String expected = arrayToString(new byte[]{(byte) 0xCD, 0x00, 0x09, 0x12, 0x01, 0x08, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00}); + System.out.println("fitpro test, data 3: " + result); + assertEquals(expected, result); + } + + public byte[] stringToByteArray(String s) { + byte[] byteArray = new byte[s.length() / 2]; + String[] strBytes = new String[s.length() / 2]; + int k = 0; + for (int i = 0; i < s.length(); i = i + 2) { + int j = i + 2; + strBytes[k] = s.substring(i, j); + byteArray[k] = (byte) Integer.parseInt(strBytes[k], 16); + k++; + } + return byteArray; + } + + public static byte[] stringWith0xToByteArray(String s) { + String[] split = s.split(" "); + int k = 0; + byte[] byteArray = new byte[split.length]; + for (String ch : split) { + byteArray[k] = (byte) Integer.parseInt(ch.split("x")[1], 16); + k++; + } + return byteArray; + } +} \ No newline at end of file diff --git a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/FitProTests.java b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/FitProTests.java index 99f590ff9..00c99481c 100644 --- a/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/FitProTests.java +++ b/app/src/test/java/nodomain/freeyourgadget/gadgetbridge/test/FitProTests.java @@ -22,29 +22,5 @@ public class FitProTests extends TestBase { //handleStepData(stringWith0xToByteArray(stepData)); } - public byte[] stringToByteArray(String s) { - byte[] byteArray = new byte[s.length() / 2]; - String[] strBytes = new String[s.length() / 2]; - int k = 0; - for (int i = 0; i < s.length(); i = i + 2) { - int j = i + 2; - strBytes[k] = s.substring(i, j); - byteArray[k] = (byte) Integer.parseInt(strBytes[k], 16); - k++; - } - return byteArray; - } - - - public static byte[] stringWith0xToByteArray(String s) { - String[] split = s.split(" "); - int k = 0; - byte[] byteArray = new byte[split.length]; - for (String ch : split) { - byteArray[k] = (byte) Integer.parseInt(ch.split("x")[1], 16); - k++; - } - return byteArray; - } }