From b17c1971fb1d6c38086f262971325c1a13ffa28d Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Fri, 12 Oct 2018 23:09:22 +0200
Subject: [PATCH 1/7] Use resistance measurement to calculate body composition
data.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Coƫfficients were obtained by reverse-engineering the discontinued Trisa Vital
Bluetooth app. The resulting figures do not seem to be very accurate.
---
.../bluetooth/BluetoothTrisaBodyAnalyze.java | 5 +-
.../bluetooth/lib/TrisaBodyAnalyzeLib.java | 70 ++++++++++++++++---
.../openscale/TrisaBodyAnalyzeLibTest.java | 52 ++++++++++++--
3 files changed, 113 insertions(+), 14 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
index e549e934..6e846e5c 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
@@ -23,7 +23,9 @@ import android.preference.PreferenceManager;
import android.support.annotation.Nullable;
import com.health.openscale.R;
+import com.health.openscale.core.OpenScale;
import com.health.openscale.core.datatypes.ScaleMeasurement;
+import com.health.openscale.core.datatypes.ScaleUser;
import java.util.UUID;
@@ -252,7 +254,8 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication {
}
private void onScaleMeasurumentReceived(byte[] data) {
- ScaleMeasurement scaleMeasurement = parseScaleMeasurementData(data);
+ ScaleUser user = OpenScale.getInstance().getSelectedScaleUser();
+ ScaleMeasurement scaleMeasurement = parseScaleMeasurementData(data, user);
if (scaleMeasurement == null) {
Timber.e("Failed to parse scale measure measurement data: %s", byteInHex(data));
return;
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
index ccff9009..c25d2f99 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
@@ -18,6 +18,8 @@ package com.health.openscale.core.bluetooth.lib;
import android.support.annotation.Nullable;
import com.health.openscale.core.datatypes.ScaleMeasurement;
+import com.health.openscale.core.datatypes.ScaleUser;
+import com.health.openscale.core.utils.Converters;
import java.util.Date;
@@ -64,25 +66,75 @@ public class TrisaBodyAnalyzeLib {
}
@Nullable
- public static ScaleMeasurement parseScaleMeasurementData(byte[] data) {
- // Byte 0 contains info.
- // Byte 1-4 contains weight.
- // Byte 5-8 contains timestamp, if bit 0 in info byte is set.
+ public static ScaleMeasurement parseScaleMeasurementData(byte[] data, @Nullable ScaleUser user) {
+ // data contains:
+ //
+ // 1 byte: info about presence of other fields:
+ // bit 0: timestamp
+ // bit 1: resistance1
+ // bit 2: resistance2
+ // (other bits aren't used here)
+ // 4 bytes: weight
+ // 4 bytes: timestamp (if info bit 0 is set)
+ // 4 bytes: resistance1 (if info bit 1 is set)
+ // 4 bytes: resistance2 (if info bit 2 is set)
+ // (following fields aren't used here)
+
// Check that we have at least weight & timestamp, which is the minimum information that
// ScaleMeasurement needs.
- if (data.length < 9 || (data[0] & 1) == 0) {
+ if (data.length < 9) {
+ return null; // data is too short
+ }
+ byte infoByte = data[0];
+ boolean hasTimestamp = (infoByte & 1) == 1;
+ boolean hasResistance1 = (infoByte & 2) == 2;
+ boolean hasResistance2 = (infoByte & 4) == 4;
+ if (!hasTimestamp) {
return null;
}
-
- double weight = getBase10Float(data, 1);
+ double weightKg = getBase10Float(data, 1);
int deviceTimestamp = getInt32(data, 5);
ScaleMeasurement measurement = new ScaleMeasurement();
measurement.setDateTime(new Date(convertDeviceTimestampToJava(deviceTimestamp)));
- measurement.setWeight((float)weight);
- // TODO: calculate body composition (if possible) and set those fields too
+ measurement.setWeight((float) weightKg);
+
+ // Only resistance 2 is used; resistance 1 is 0, even if it is present.
+ int resistance2Offset = 9 + (hasResistance1 ? 4 : 0);
+ if (hasResistance2 && resistance2Offset + 4 <= data.length && isValidUser(user)) {
+ // Calculate body composition statistics from measured weight & resistance, combined
+ // with age, height and sex from the user profile. The accuracy of the resulting figures
+ // is questionable, but it's better than nothing. Even if the absolute numbers aren't
+ // very meaningful, it might still be useful to track changes over time.
+ double resistance2 = getBase10Float(data, resistance2Offset);
+ int ageYears = user.getAge();
+ double heightCm = Converters.toCentimeter(user.getBodyHeight(), user.getMeasureUnit());
+ boolean isMale = user.getGender().isMale();
+ double impedance = resistance2 < 410 ? 3.0 : 0.3 * (resistance2 - 400);
+ double bmi = weightKg * 1e4 / (heightCm * heightCm);
+ double fat = isMale
+ ? bmi * (1.479 + 4.4e-4 * impedance) + 0.1 * ageYears - 21.764
+ : bmi * (1.506 + 3.908e-4 * impedance) + 0.1 * ageYears - 12.834;
+ double water = isMale
+ ? 87.51 + (-1.162 * bmi - 0.00813 * impedance + 0.07594 * ageYears)
+ : 77.721 + (-1.148 * bmi - 0.00573 * impedance + 0.06448 * ageYears);
+ double muscle = isMale
+ ? 74.627 + (-0.811 * bmi - 0.00565 * impedance - 0.367 * ageYears)
+ : 57.0 + (-0.694 * bmi - 0.00344 * impedance - 0.255 * ageYears);
+ double bone = isMale
+ ? 7.829 + (-0.0855 * bmi - 5.92e-4 * impedance - 0.0389 * ageYears)
+ : 7.98 + (-0.0973 * bmi - 4.84e-4 * impedance - 0.036 * ageYears);
+ measurement.setFat((float) fat);
+ measurement.setWater((float) water);
+ measurement.setMuscle((float) muscle);
+ measurement.setBone((float) bone);
+ }
return measurement;
}
+ private static boolean isValidUser(@Nullable ScaleUser user) {
+ return user != null && user.getAge() > 0 && user.getBodyHeight() > 0;
+ }
+
private TrisaBodyAnalyzeLib() {}
}
diff --git a/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java b/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
index 4c98e64f..c54d69e2 100644
--- a/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
@@ -1,12 +1,16 @@
package com.health.openscale;
import com.health.openscale.core.datatypes.ScaleMeasurement;
+import com.health.openscale.core.datatypes.ScaleUser;
+import com.health.openscale.core.utils.Converters;
import junit.framework.Assert;
import org.junit.Test;
+import java.util.Calendar;
import java.util.Date;
+import java.util.GregorianCalendar;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.convertDeviceTimestampToJava;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.convertJavaTimestampToDevice;
@@ -68,14 +72,49 @@ public class TrisaBodyAnalyzeLibTest {
}
@Test
- public void parseScaleMeasurementDataTests() {
+ public void parseScaleMeasurementData_validUserData() {
+ long expected_timestamp_seconds = 1539205852L; // Wed Oct 10 21:10:52 UTC 2018
+ byte[] bytes = hexToBytes("9f:b0:1d:00:fe:dc:2f:81:10:00:00:00:ff:0a:15:00:ff:00:09:00");
+
+ ScaleUser user = new ScaleUser();
+ user.setGender(Converters.Gender.MALE);
+ user.setBirthday(ageToBirthday(36));
+ user.setBodyHeight(186);
+ user.setMeasureUnit(Converters.MeasureUnit.CM);
+
+ ScaleMeasurement measurement = parseScaleMeasurementData(bytes, user);
+
+ float eps = 1e-3f;
+ assertEquals(76.0f, measurement.getWeight(), eps);
+ assertEquals(new Date(expected_timestamp_seconds * 1000), measurement.getDateTime());
+ assertEquals(14.728368f, measurement.getFat(), eps);
+ assertEquals(64.37914f, measurement.getWater(), eps);
+ assertEquals(43.36414f, measurement.getMuscle(), eps);
+ assertEquals(4.525733f, measurement.getBone());
+ }
+
+ @Test
+ public void parseScaleMeasurementData_missingUserData() {
long expected_timestamp_seconds = 1538156082L; // Fri Sep 28 17:34:42 UTC 2018
byte[] bytes = hexToBytes("9f:ba:1d:00:fe:32:2b:71:10:00:00:00:ff:8d:14:00:ff:00:09:00");
- ScaleMeasurement measurement = parseScaleMeasurementData(bytes);
+ ScaleMeasurement measurement = parseScaleMeasurementData(bytes, null);
- assertEquals(measurement.getWeight(), 76.1f, 1e-6f);
+ assertEquals(76.1f, measurement.getWeight(), 1e-3f);
assertEquals(new Date(expected_timestamp_seconds * 1000), measurement.getDateTime());
+ assertEquals(0f, measurement.getFat());
+ }
+
+ @Test
+ public void parseScaleMeasurementData_invalidUserData() {
+ long expected_timestamp_seconds = 1538156082L; // Fri Sep 28 17:34:42 UTC 2018
+ byte[] bytes = hexToBytes("9f:ba:1d:00:fe:32:2b:71:10:00:00:00:ff:8d:14:00:ff:00:09:00");
+
+ ScaleMeasurement measurement = parseScaleMeasurementData(bytes, new ScaleUser());
+
+ assertEquals(76.1f, measurement.getWeight(), 1e-3f);
+ assertEquals(new Date(expected_timestamp_seconds * 1000), measurement.getDateTime());
+ assertEquals(0f, measurement.getFat());
}
/**
@@ -124,7 +163,7 @@ public class TrisaBodyAnalyzeLibTest {
}
/** Parses a colon-separated hex-encoded string like "aa:bb:cc:dd" into an array of bytes. */
- private byte[] hexToBytes(String s) {
+ private static byte[] hexToBytes(String s) {
String[] parts = s.split(":");
byte[] bytes = new byte[parts.length];
for (int i = 0; i < bytes.length; ++i) {
@@ -135,4 +174,9 @@ public class TrisaBodyAnalyzeLibTest {
}
return bytes;
}
+
+ private static Date ageToBirthday(int years) {
+ int currentYear = GregorianCalendar.getInstance().get(Calendar.YEAR);
+ return new GregorianCalendar(currentYear - years, Calendar.JANUARY, 1).getTime();
+ }
}
From 303aedb4e7de7a40c5987ab573373b3d03931a22 Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Sat, 13 Oct 2018 14:13:02 +0200
Subject: [PATCH 2/7] Reuse Converters.fromUnsignedInt24Le() to implement
getBase10Float().
From the observed data, it's not clear whether the mantissa should be
interpreted as signed or not. Since two metrics encoded as base-10 floats
(weight and resistance) cannot be negative, and the Trisa Health Vital app
interprets the mantissa as unsigned, we will treat it as unsigned here, too.
---
.../openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
index c25d2f99..3e918464 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
@@ -51,8 +51,7 @@ public class TrisaBodyAnalyzeLib {
* @throws IndexOutOfBoundsException if {@code offset < 0} or {@code offset + 4> data.length}
*/
public static double getBase10Float(byte[] data, int offset) {
- int mantissa = (data[offset] & 0xff) | ((data[offset + 1] & 0xff) << 8) |
- ((data[offset + 2] & 0xff) << 16);
+ int mantissa = Converters.fromUnsignedInt24Le(data, offset);
int exponent = data[offset + 3]; // note: byte is signed.
return mantissa * Math.pow(10, exponent);
}
From 94d138b9af3b89cabf6d3060f9fe9e44c71fe7b8 Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Sat, 13 Oct 2018 14:40:54 +0200
Subject: [PATCH 3/7] Rename `Converters.toUnsignedInt*` to
`Convertors.toInt*`.
These functions work equally well with signed values.
---
.../core/bluetooth/BluetoothBeurerSanitas.java | 2 +-
.../core/bluetooth/BluetoothMedisanaBS44x.java | 2 +-
.../core/bluetooth/BluetoothYunmaiSE_Mini.java | 4 ++--
.../com/health/openscale/core/utils/Converters.java | 6 +++---
.../java/com/health/openscale/ConvertersTest.java | 12 ++++++------
5 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothBeurerSanitas.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothBeurerSanitas.java
index 2b646a6d..17313ef4 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothBeurerSanitas.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothBeurerSanitas.java
@@ -588,7 +588,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication {
private void updateDateTime() {
// Update date/time of the scale
long unixTime = System.currentTimeMillis() / 1000L;
- byte[] unixTimeBytes = Converters.toUnsignedInt32Be(unixTime);
+ byte[] unixTimeBytes = Converters.toInt32Be(unixTime);
Timber.d("Write new Date/Time: %d (%s)", unixTime, byteInHex(unixTimeBytes));
writeBytes(new byte[]{(byte) getAlternativeStartByte(9),
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS44x.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS44x.java
index f80ae6bb..f496b8df 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS44x.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS44x.java
@@ -73,7 +73,7 @@ public class BluetoothMedisanaBS44x extends BluetoothCommunication {
// send magic number to receive weight data
long timestamp = new Date().getTime() / 1000;
timestamp -= SCALE_UNIX_TIMESTAMP_OFFSET;
- byte[] date = Converters.toUnsignedInt32Le(timestamp);
+ byte[] date = Converters.toInt32Le(timestamp);
byte[] magicBytes = new byte[] {(byte)0x02, date[0], date[1], date[2], date[3]};
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYunmaiSE_Mini.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYunmaiSE_Mini.java
index fcd2993d..4fdc7b65 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYunmaiSE_Mini.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYunmaiSE_Mini.java
@@ -58,7 +58,7 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication {
protected boolean nextInitCmd(int stateNr) {
switch (stateNr) {
case 0:
- byte[] userId = Converters.toUnsignedInt16Be(getUniqueNumber());
+ byte[] userId = Converters.toInt16Be(getUniqueNumber());
final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser();
byte sex = selectedUser.getGender().isMale() ? (byte)0x01 : (byte)0x02;
@@ -74,7 +74,7 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication {
writeBytes(WEIGHT_CMD_SERVICE, WEIGHT_CMD_CHARACTERISTIC, user_add_or_query);
break;
case 1:
- byte[] unixTime = Converters.toUnsignedInt32Be(new Date().getTime() / 1000);
+ byte[] unixTime = Converters.toInt32Be(new Date().getTime() / 1000);
byte[] set_time = new byte[]{(byte)0x0d, (byte) 0x0d, (byte) 0x11,
unixTime[0], unixTime[1], unixTime[2], unixTime[3],
diff --git a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
index 1f755885..fc3a5caf 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
@@ -247,7 +247,7 @@ public class Converters {
return value;
}
- public static byte[] toUnsignedInt16Be(int value) {
+ public static byte[] toInt16Be(int value) {
byte[] data = new byte[2];
data[0] = (byte) ((value >> 8) & 0xFF);
data[1] = (byte) (value & 0xFF);
@@ -277,7 +277,7 @@ public class Converters {
return value;
}
- public static byte[] toUnsignedInt32Le(long value) {
+ public static byte[] toInt32Le(long value) {
byte[] data = new byte[4];
data[3] = (byte) ((value >> 24) & 0xFF);
data[2] = (byte) ((value >> 16) & 0xFF);
@@ -286,7 +286,7 @@ public class Converters {
return data;
}
- public static byte[] toUnsignedInt32Be(long value) {
+ public static byte[] toInt32Be(long value) {
byte[] data = new byte[4];
data[0] = (byte) ((value >> 24) & 0xFF);
data[1] = (byte) ((value >> 16) & 0xFF);
diff --git a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
index 4b95155c..6deead16 100644
--- a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
@@ -96,10 +96,10 @@ public class ConvertersTest {
assertEquals(0x107f, Converters.fromUnsignedInt16Be(data, 3));
data = new byte[]{(byte) 0xff, (byte) 0xfe};
- assertArrayEquals(data, Converters.toUnsignedInt16Be(0xfffe));
+ assertArrayEquals(data, Converters.toInt16Be(0xfffe));
assertEquals(0xffff,
Converters.fromUnsignedInt16Be(
- Converters.toUnsignedInt16Be(0xffff), 0));
+ Converters.toInt16Be(0xffff), 0));
}
@Test
@@ -130,13 +130,13 @@ public class ConvertersTest {
assertEquals(0x1ff00L, Converters.fromUnsignedInt32Be(data, 1));
data = new byte[]{(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc};
- assertArrayEquals(data, Converters.toUnsignedInt32Le(0xfcfdfeffL));
- assertArrayEquals(data, Converters.toUnsignedInt32Be(0xfffefdfcL));
+ assertArrayEquals(data, Converters.toInt32Le(0xfcfdfeffL));
+ assertArrayEquals(data, Converters.toInt32Be(0xfffefdfcL));
assertEquals(0xffffffffL,
Converters.fromUnsignedInt32Le(
- Converters.toUnsignedInt32Le(0xffffffffL), 0));
+ Converters.toInt32Le(0xffffffffL), 0));
assertEquals(0xffffffffL,
Converters.fromUnsignedInt32Be(
- Converters.toUnsignedInt32Be(0xffffffffL), 0));
+ Converters.toInt32Be(0xffffffffL), 0));
}
}
From 90ea78f4898960fc26b02adb16b1b13e3a85d243 Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Sat, 13 Oct 2018 14:45:08 +0200
Subject: [PATCH 4/7] Add Converters.toInt16Le() for symmetry with toInt16Be().
---
.../health/openscale/core/utils/Converters.java | 7 +++++++
.../java/com/health/openscale/ConvertersTest.java | 14 ++++++++------
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
index fc3a5caf..01c2b31a 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
@@ -247,6 +247,13 @@ public class Converters {
return value;
}
+ public static byte[] toInt16Le(int value) {
+ byte[] data = new byte[2];
+ data[0] = (byte) (value & 0xFF);
+ data[1] = (byte) ((value >> 8) & 0xFF);
+ return data;
+ }
+
public static byte[] toInt16Be(int value) {
byte[] data = new byte[2];
data[0] = (byte) ((value >> 8) & 0xFF);
diff --git a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
index 6deead16..f90ac557 100644
--- a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
@@ -82,7 +82,7 @@ public class ConvertersTest {
}
@Test
- public void unsignedInt16Converters() throws Exception {
+ public void fromUnsignedInt16Converters() throws Exception {
byte[] data = new byte[]{(byte) 0xfd, (byte) 0xfe, (byte) 0xfc, (byte) 0x10, (byte) 0x7f};
assertEquals(0xfefd, Converters.fromUnsignedInt16Le(data, 0));
@@ -94,12 +94,14 @@ public class ConvertersTest {
assertEquals(0xfefc, Converters.fromUnsignedInt16Be(data, 1));
assertEquals(0xfc10, Converters.fromUnsignedInt16Be(data, 2));
assertEquals(0x107f, Converters.fromUnsignedInt16Be(data, 3));
+ }
- data = new byte[]{(byte) 0xff, (byte) 0xfe};
- assertArrayEquals(data, Converters.toInt16Be(0xfffe));
- assertEquals(0xffff,
- Converters.fromUnsignedInt16Be(
- Converters.toInt16Be(0xffff), 0));
+ @Test
+ public void toInt16Converters() throws Exception {
+ assertArrayEquals(new byte[]{(byte) 0x12, (byte) 0x34}, Converters.toInt16Be(0x1234));
+ assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, Converters.toInt16Be(0xfffe));
+ assertArrayEquals(new byte[]{(byte) 0x34, (byte) 0x12}, Converters.toInt16Le(0x1234));
+ assertArrayEquals(new byte[]{(byte) 0xfe, (byte) 0xff}, Converters.toInt16Le(0xfffe));
}
@Test
From d9885b967f353a44d378ddcf2d8332620088ecb4 Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Sat, 13 Oct 2018 15:01:42 +0200
Subject: [PATCH 5/7] Create overloads of Converters.toInt* that write to an
existing buffer.
This is symmetric with Converters.from*Int* which take a buffer and offset too.
---
.../bluetooth/BluetoothTrisaBodyAnalyze.java | 12 +++---
.../openscale/core/utils/Converters.java | 40 +++++++++++++------
.../com/health/openscale/ConvertersTest.java | 21 +++++++++-
3 files changed, 52 insertions(+), 21 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
index 6e846e5c..78bd03be 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
@@ -26,6 +26,7 @@ import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.datatypes.ScaleUser;
+import com.health.openscale.core.utils.Converters;
import java.util.UUID;
@@ -275,13 +276,10 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication {
* encoded in little-endian byte order.
*/
private void writeCommand(byte commandByte, int argument) {
- writeCommandBytes(new byte[]{
- commandByte,
- (byte) (argument >> 0),
- (byte) (argument >> 8),
- (byte) (argument >> 16),
- (byte) (argument >> 24),
- });
+ byte[] bytes = new byte[5];
+ bytes[0] = commandByte;
+ Converters.toInt32Le(bytes, 1, argument);
+ writeCommandBytes(bytes);
}
private void writeCommandBytes(byte[] bytes) {
diff --git a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
index 01c2b31a..8461d920 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
@@ -247,17 +247,25 @@ public class Converters {
return value;
}
+ public static void toInt16Le(byte[] data, int offset, int value) {
+ data[offset + 0] = (byte) (value & 0xFF);
+ data[offset + 1] = (byte) ((value >> 8) & 0xFF);
+ }
+
+ public static void toInt16Be(byte[] data, int offset, int value) {
+ data[offset + 0] = (byte) ((value >> 8) & 0xFF);
+ data[offset + 1] = (byte) (value & 0xFF);
+ }
+
public static byte[] toInt16Le(int value) {
byte[] data = new byte[2];
- data[0] = (byte) (value & 0xFF);
- data[1] = (byte) ((value >> 8) & 0xFF);
+ toInt16Le(data, 0, value);
return data;
}
public static byte[] toInt16Be(int value) {
byte[] data = new byte[2];
- data[0] = (byte) ((value >> 8) & 0xFF);
- data[1] = (byte) (value & 0xFF);
+ toInt16Be(data, 0, value);
return data;
}
@@ -284,21 +292,29 @@ public class Converters {
return value;
}
+ public static void toInt32Le(byte[] data, int offset, long value) {
+ data[offset + 3] = (byte) ((value >> 24) & 0xFF);
+ data[offset + 2] = (byte) ((value >> 16) & 0xFF);
+ data[offset + 1] = (byte) ((value >> 8) & 0xFF);
+ data[offset + 0] = (byte) (value & 0xFF);
+ }
+
+ public static void toInt32Be(byte[] data, int offset, long value) {
+ data[offset + 0] = (byte) ((value >> 24) & 0xFF);
+ data[offset + 1] = (byte) ((value >> 16) & 0xFF);
+ data[offset + 2] = (byte) ((value >> 8) & 0xFF);
+ data[offset + 3] = (byte) (value & 0xFF);
+ }
+
public static byte[] toInt32Le(long value) {
byte[] data = new byte[4];
- data[3] = (byte) ((value >> 24) & 0xFF);
- data[2] = (byte) ((value >> 16) & 0xFF);
- data[1] = (byte) ((value >> 8) & 0xFF);
- data[0] = (byte) (value & 0xFF);
+ toInt32Le(data, 0, value);
return data;
}
public static byte[] toInt32Be(long value) {
byte[] data = new byte[4];
- data[0] = (byte) ((value >> 24) & 0xFF);
- data[1] = (byte) ((value >> 16) & 0xFF);
- data[2] = (byte) ((value >> 8) & 0xFF);
- data[3] = (byte) (value & 0xFF);
+ toInt32Be(data, 0, value);
return data;
}
}
diff --git a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
index f90ac557..dd102e8b 100644
--- a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
@@ -20,6 +20,8 @@ import com.health.openscale.core.utils.Converters;
import org.junit.Test;
+import javax.sql.ConnectionEvent;
+
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
@@ -102,6 +104,12 @@ public class ConvertersTest {
assertArrayEquals(new byte[]{(byte) 0xff, (byte) 0xfe}, Converters.toInt16Be(0xfffe));
assertArrayEquals(new byte[]{(byte) 0x34, (byte) 0x12}, Converters.toInt16Le(0x1234));
assertArrayEquals(new byte[]{(byte) 0xfe, (byte) 0xff}, Converters.toInt16Le(0xfffe));
+
+ byte[] data = new byte[6];
+ Converters.toInt16Be(data, 1, 0x0102);
+ Converters.toInt16Be(data, 3, 0x0304);
+ Converters.toInt16Le(data, 2, 0x0506);
+ assertArrayEquals(new byte[]{ 0, 1, 6, 5, 4, 0}, data);
}
@Test
@@ -114,7 +122,7 @@ public class ConvertersTest {
}
@Test
- public void unsignedInt32Converters() throws Exception {
+ public void fromUnsignedInt32Converters() throws Exception {
byte[] data = new byte[]{(byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0x7f, (byte) 0x7e};
assertEquals(0x7ff3f2f1, Converters.fromUnsignedInt32Le(data, 0));
@@ -130,8 +138,11 @@ public class ConvertersTest {
assertEquals(0x800001ffL, Converters.fromUnsignedInt32Be(data, 0));
assertEquals(0x1ff00L, Converters.fromUnsignedInt32Be(data, 1));
+ }
- data = new byte[]{(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc};
+ @Test
+ public void toInt32Converters() throws Exception {
+ byte[] data = new byte[]{(byte) 0xff, (byte) 0xfe, (byte) 0xfd, (byte) 0xfc};
assertArrayEquals(data, Converters.toInt32Le(0xfcfdfeffL));
assertArrayEquals(data, Converters.toInt32Be(0xfffefdfcL));
assertEquals(0xffffffffL,
@@ -140,5 +151,11 @@ public class ConvertersTest {
assertEquals(0xffffffffL,
Converters.fromUnsignedInt32Be(
Converters.toInt32Be(0xffffffffL), 0));
+
+ data = new byte[10];
+ Converters.toInt32Be(data, 1, 0x01020304);
+ Converters.toInt32Be(data, 6, 0x05060708);
+ Converters.toInt32Le(data, 3, 0x090a0b0c);
+ assertArrayEquals(new byte[]{ 0, 1, 2, 12, 11, 10, 9, 6, 7, 8}, data);
}
}
From 28cee4ea04a80b8a5ee71cbad576fd60b54f28fc Mon Sep 17 00:00:00 2001
From: Maks Verver
Date: Sat, 13 Oct 2018 16:12:31 +0200
Subject: [PATCH 6/7] Add Converters.fromSignedInt* methods.
---
.../bluetooth/BluetoothTrisaBodyAnalyze.java | 5 +--
.../bluetooth/lib/TrisaBodyAnalyzeLib.java | 12 +----
.../openscale/core/utils/Converters.java | 40 ++++++++++++-----
.../com/health/openscale/ConvertersTest.java | 45 +++++++++++++++++--
.../openscale/TrisaBodyAnalyzeLibTest.java | 28 ------------
5 files changed, 75 insertions(+), 55 deletions(-)
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
index 78bd03be..978eca49 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothTrisaBodyAnalyze.java
@@ -33,7 +33,6 @@ import java.util.UUID;
import timber.log.Timber;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.convertJavaTimestampToDevice;
-import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.getInt32;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.parseScaleMeasurementData;
/**
@@ -219,7 +218,7 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication {
Timber.e("Password data too short");
return;
}
- password = getInt32(data, 1);
+ password = Converters.fromSignedInt32Le(data, 1);
if (deviceId == null) {
Timber.e("Can't save password: device id not set!");
} else {
@@ -247,7 +246,7 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication {
disconnect(true);
return;
}
- int challenge = getInt32(data, 1);
+ int challenge = Converters.fromSignedInt32Le(data, 1);
int response = challenge ^ password;
writeCommand(DOWNLOAD_INFORMATION_RESULT_COMMAND, response);
int deviceTimestamp = convertJavaTimestampToDevice(System.currentTimeMillis());
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
index 3e918464..862ef23a 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/lib/TrisaBodyAnalyzeLib.java
@@ -33,16 +33,6 @@ public class TrisaBodyAnalyzeLib {
// Timestamp of 2010-01-01 00:00:00 UTC (or local time?)
private static final long TIMESTAMP_OFFSET_SECONDS = 1262304000L;
- /**
- * Converts 4 little-endian bytes to a 32-bit integer, starting from {@code offset}.
- *
- * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code offset + 4> data.length}
- */
- public static int getInt32(byte[] data, int offset) {
- return (data[offset] & 0xff) | ((data[offset + 1] & 0xff) << 8) |
- ((data[offset + 2] & 0xff) << 16) | ((data[offset + 3] & 0xff) << 24);
- }
-
/** Converts 4 bytes to a floating point number, starting from {@code offset}.
*
* The first three little-endian bytes form the 24-bit mantissa. The last byte contains the
@@ -92,7 +82,7 @@ public class TrisaBodyAnalyzeLib {
return null;
}
double weightKg = getBase10Float(data, 1);
- int deviceTimestamp = getInt32(data, 5);
+ int deviceTimestamp = Converters.fromSignedInt32Le(data, 5);
ScaleMeasurement measurement = new ScaleMeasurement();
measurement.setDateTime(new Date(convertDeviceTimestampToJava(deviceTimestamp)));
diff --git a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
index 8461d920..e0d69a3e 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/utils/Converters.java
@@ -235,18 +235,26 @@ public class Converters {
return kg;
}
- public static int fromUnsignedInt16Le(byte[] data, int offset) {
- int value = (data[offset + 1] & 0xFF) << 8;
+ public static int fromSignedInt16Le(byte[] data, int offset) {
+ int value = data[offset + 1] << 8;
value += data[offset] & 0xFF;
return value;
}
- public static int fromUnsignedInt16Be(byte[] data, int offset) {
- int value = (data[offset] & 0xFF) << 8;
+ public static int fromSignedInt16Be(byte[] data, int offset) {
+ int value = data[offset] << 8;
value += data[offset + 1] & 0xFF;
return value;
}
+ public static int fromUnsignedInt16Le(byte[] data, int offset) {
+ return fromSignedInt16Le(data, offset) & 0xFFFF;
+ }
+
+ public static int fromUnsignedInt16Be(byte[] data, int offset) {
+ return fromSignedInt16Be(data, offset) & 0xFFFF;
+ }
+
public static void toInt16Le(byte[] data, int offset, int value) {
data[offset + 0] = (byte) (value & 0xFF);
data[offset + 1] = (byte) ((value >> 8) & 0xFF);
@@ -269,29 +277,41 @@ public class Converters {
return data;
}
- public static int fromUnsignedInt24Le(byte[] data, int offset) {
- int value = (data[offset + 2] & 0xFF) << 16;
+ public static int fromSignedInt24Le(byte[] data, int offset) {
+ int value = data[offset + 2] << 16;
value += (data[offset + 1] & 0xFF) << 8;
value += data[offset] & 0xFF;
return value;
}
- public static long fromUnsignedInt32Le(byte[] data, int offset) {
- long value = (long) (data[offset + 3] & 0xFF) << 24;
+ public static int fromUnsignedInt24Le(byte[] data, int offset) {
+ return fromSignedInt24Le(data, offset) & 0xFFFFFF;
+ }
+
+ public static int fromSignedInt32Le(byte[] data, int offset) {
+ int value = data[offset + 3] << 24;
value += (data[offset + 2] & 0xFF) << 16;
value += (data[offset + 1] & 0xFF) << 8;
value += data[offset] & 0xFF;
return value;
}
- public static long fromUnsignedInt32Be(byte[] data, int offset) {
- long value = (long) (data[offset] & 0xFF) << 24;
+ public static int fromSignedInt32Be(byte[] data, int offset) {
+ int value = data[offset] << 24;
value += (data[offset + 1] & 0xFF) << 16;
value += (data[offset + 2] & 0xFF) << 8;
value += data[offset + 3] & 0xFF;
return value;
}
+ public static long fromUnsignedInt32Le(byte[] data, int offset) {
+ return (long) fromSignedInt32Le(data, offset) & 0xFFFFFFFFL;
+ }
+
+ public static long fromUnsignedInt32Be(byte[] data, int offset) {
+ return (long) fromSignedInt32Be(data, offset) & 0xFFFFFFFFL;
+ }
+
public static void toInt32Le(byte[] data, int offset, long value) {
data[offset + 3] = (byte) ((value >> 24) & 0xFF);
data[offset + 2] = (byte) ((value >> 16) & 0xFF);
diff --git a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
index dd102e8b..379be790 100644
--- a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
@@ -84,18 +84,33 @@ public class ConvertersTest {
}
@Test
- public void fromUnsignedInt16Converters() throws Exception {
+ public void fromInt16Converters() throws Exception {
byte[] data = new byte[]{(byte) 0xfd, (byte) 0xfe, (byte) 0xfc, (byte) 0x10, (byte) 0x7f};
+ assertEquals(0xfffffefd, Converters.fromSignedInt16Le(data, 0));
+ assertEquals(0xfffffcfe, Converters.fromSignedInt16Le(data, 1));
+ assertEquals(0x000010fc, Converters.fromSignedInt16Le(data, 2));
+ assertEquals(0x00007f10, Converters.fromSignedInt16Le(data, 3));
+
assertEquals(0xfefd, Converters.fromUnsignedInt16Le(data, 0));
assertEquals(0xfcfe, Converters.fromUnsignedInt16Le(data, 1));
assertEquals(0x10fc, Converters.fromUnsignedInt16Le(data, 2));
assertEquals(0x7f10, Converters.fromUnsignedInt16Le(data, 3));
+ assertEquals(0xfffffdfe, Converters.fromSignedInt16Be(data, 0));
+ assertEquals(0xfffffefc, Converters.fromSignedInt16Be(data, 1));
+ assertEquals(0xfffffc10, Converters.fromSignedInt16Be(data, 2));
+ assertEquals(0x0000107f, Converters.fromSignedInt16Be(data, 3));
+
assertEquals(0xfdfe, Converters.fromUnsignedInt16Be(data, 0));
assertEquals(0xfefc, Converters.fromUnsignedInt16Be(data, 1));
assertEquals(0xfc10, Converters.fromUnsignedInt16Be(data, 2));
assertEquals(0x107f, Converters.fromUnsignedInt16Be(data, 3));
+
+ assertEquals(-12345,
+ Converters.fromSignedInt16Le(Converters.toInt16Le(-12345), 0));
+ assertEquals(-12345,
+ Converters.fromSignedInt16Be(Converters.toInt16Be(-12345), 0));
}
@Test
@@ -113,31 +128,55 @@ public class ConvertersTest {
}
@Test
- public void unsignedInt24Converters() throws Exception {
+ public void fromInt24Converters() throws Exception {
byte[] data = new byte[]{(byte) 0xfd, (byte) 0xfe, (byte) 0xfc, (byte) 0x10, (byte) 0x7f};
+ assertEquals(0xfffcfefd, Converters.fromSignedInt24Le(data, 0));
+ assertEquals(0x0010fcfe, Converters.fromSignedInt24Le(data, 1));
+ assertEquals(0x007f10fc, Converters.fromSignedInt24Le(data, 2));
+
assertEquals(0xfcfefd, Converters.fromUnsignedInt24Le(data, 0));
assertEquals(0x10fcfe, Converters.fromUnsignedInt24Le(data, 1));
assertEquals(0x7f10fc, Converters.fromUnsignedInt24Le(data, 2));
+
+ assertEquals(-1234567,
+ Converters.fromSignedInt24Le(Converters.toInt32Le(-1234567), 0));
}
@Test
- public void fromUnsignedInt32Converters() throws Exception {
+ public void fromInt32Converters() throws Exception {
byte[] data = new byte[]{(byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0x7f, (byte) 0x7e};
+ assertEquals(0x7ff3f2f1, Converters.fromSignedInt32Le(data, 0));
+ assertEquals(0x7e7ff3f2, Converters.fromSignedInt32Le(data, 1));
+
assertEquals(0x7ff3f2f1, Converters.fromUnsignedInt32Le(data, 0));
assertEquals(0x7e7ff3f2, Converters.fromUnsignedInt32Le(data, 1));
+ assertEquals(0xf1f2f37f, Converters.fromSignedInt32Be(data, 0));
+ assertEquals(0xf2f37f7e, Converters.fromSignedInt32Be(data, 1));
+
assertEquals(0xf1f2f37fL, Converters.fromUnsignedInt32Be(data, 0));
assertEquals(0xf2f37f7eL, Converters.fromUnsignedInt32Be(data, 1));
data = new byte[]{(byte) 0x80, (byte) 0x00, (byte) 0x01, (byte) 0xff, (byte) 0x00};
+ assertEquals(0xff010080, Converters.fromSignedInt32Le(data, 0));
+ assertEquals(0xff0100, Converters.fromSignedInt32Le(data, 1));
+
assertEquals(0xff010080L, Converters.fromUnsignedInt32Le(data, 0));
assertEquals(0xff0100, Converters.fromUnsignedInt32Le(data, 1));
+ assertEquals(0x800001ff, Converters.fromSignedInt32Be(data, 0));
+ assertEquals(0x1ff00, Converters.fromSignedInt32Be(data, 1));
+
assertEquals(0x800001ffL, Converters.fromUnsignedInt32Be(data, 0));
assertEquals(0x1ff00L, Converters.fromUnsignedInt32Be(data, 1));
+
+ assertEquals(-1234567890,
+ Converters.fromSignedInt32Le(Converters.toInt32Le(-1234567890), 0));
+ assertEquals(-1234567890,
+ Converters.fromSignedInt32Be(Converters.toInt32Be(-1234567890), 0));
}
@Test
diff --git a/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java b/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
index c54d69e2..ad9cfe96 100644
--- a/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/TrisaBodyAnalyzeLibTest.java
@@ -15,27 +15,12 @@ import java.util.GregorianCalendar;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.convertDeviceTimestampToJava;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.convertJavaTimestampToDevice;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.getBase10Float;
-import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.getInt32;
import static com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib.parseScaleMeasurementData;
import static junit.framework.Assert.assertEquals;
/** Unit tests for {@link com.health.openscale.core.bluetooth.lib.TrisaBodyAnalyzeLib}.*/
public class TrisaBodyAnalyzeLibTest {
- @Test
- public void getInt32Tests() {
- byte[] data = new byte[]{1, 2, 3, 4, 5, 6};
- assertEquals(0x04030201, getInt32(data, 0));
- assertEquals(0x05040302, getInt32(data, 1));
- assertEquals(0x06050403, getInt32(data, 2));
-
- assertEquals(0xa7bdd385, getInt32(new byte[]{-123, -45, -67, -89}, 0));
-
- assertThrows(IndexOutOfBoundsException.class, getInt32Runnable(data, -1));
- assertThrows(IndexOutOfBoundsException.class, getInt32Runnable(data, 5));
- assertThrows(IndexOutOfBoundsException.class, getInt32Runnable(new byte[]{1,2,3}, 0));
- }
-
@Test
public void getBase10FloatTests() {
double eps = 1e-9; // margin of error for inexact floating point comparisons
@@ -117,19 +102,6 @@ public class TrisaBodyAnalyzeLibTest {
assertEquals(0f, measurement.getFat());
}
- /**
- * Creates a {@link Runnable} that will call getInt32(). In Java 8, this can be done more
- * easily with a lambda expression at the call site, but we are using Java 7.
- */
- private static Runnable getInt32Runnable(final byte[] data, final int offset) {
- return new Runnable() {
- @Override
- public void run() {
- getInt32(data, offset);
- }
- };
- }
-
/**
* Creates a {@link Runnable} that will call getBase10Float(). In Java 8, this can be done more
* easily with a lambda expression at the call site, but we are using Java 7.
From 7940ad95ed2b75712eb3305d9d536c698fd4e0b7 Mon Sep 17 00:00:00 2001
From: Erik Johansson
Date: Sat, 13 Oct 2018 20:09:26 +0200
Subject: [PATCH 7/7] Remove unused imports
---
.../java/com/health/openscale/DatabaseMigrationTest.java | 2 --
.../java/com/health/openscale/gui/AddMeasurementTest.java | 3 ---
.../java/com/health/openscale/gui/AddUserTest.java | 3 ---
.../openscale/core/bluetooth/BluetoothDigooDGSO38H.java | 1 -
.../openscale/core/bluetooth/BluetoothExcelvanCF36xBLE.java | 1 -
.../health/openscale/core/bluetooth/BluetoothExingtechY1.java | 1 -
.../com/health/openscale/core/datatypes/ScaleMeasurement.java | 2 --
.../src/main/java/com/health/openscale/gui/MainActivity.java | 4 ----
.../com/health/openscale/gui/views/BMRMeasurementView.java | 2 --
.../src/test/java/com/health/openscale/ConvertersTest.java | 2 --
10 files changed, 21 deletions(-)
diff --git a/android_app/app/src/androidTest/java/com/health/openscale/DatabaseMigrationTest.java b/android_app/app/src/androidTest/java/com/health/openscale/DatabaseMigrationTest.java
index e294bb00..6945ca03 100644
--- a/android_app/app/src/androidTest/java/com/health/openscale/DatabaseMigrationTest.java
+++ b/android_app/app/src/androidTest/java/com/health/openscale/DatabaseMigrationTest.java
@@ -31,8 +31,6 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import java.util.Date;
-
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertNotSame;
import static junit.framework.Assert.assertTrue;
diff --git a/android_app/app/src/androidTest/java/com/health/openscale/gui/AddMeasurementTest.java b/android_app/app/src/androidTest/java/com/health/openscale/gui/AddMeasurementTest.java
index 3ef62437..d7917afe 100644
--- a/android_app/app/src/androidTest/java/com/health/openscale/gui/AddMeasurementTest.java
+++ b/android_app/app/src/androidTest/java/com/health/openscale/gui/AddMeasurementTest.java
@@ -44,7 +44,6 @@ import com.health.openscale.gui.views.DateMeasurementView;
import com.health.openscale.gui.views.FatMeasurementView;
import com.health.openscale.gui.views.HipMeasurementView;
import com.health.openscale.gui.views.LBMMeasurementView;
-import com.health.openscale.gui.views.MeasurementView;
import com.health.openscale.gui.views.MuscleMeasurementView;
import com.health.openscale.gui.views.NeckMeasurementView;
import com.health.openscale.gui.views.ThighMeasurementView;
@@ -55,7 +54,6 @@ import com.health.openscale.gui.views.WaterMeasurementView;
import com.health.openscale.gui.views.WeightMeasurementView;
import org.hamcrest.Matchers;
-import org.junit.After;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Rule;
@@ -67,7 +65,6 @@ import java.util.List;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
-import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.replaceText;
import static android.support.test.espresso.action.ViewActions.scrollTo;
import static android.support.test.espresso.matcher.ViewMatchers.withClassName;
diff --git a/android_app/app/src/androidTest/java/com/health/openscale/gui/AddUserTest.java b/android_app/app/src/androidTest/java/com/health/openscale/gui/AddUserTest.java
index 79da11bf..52108e90 100644
--- a/android_app/app/src/androidTest/java/com/health/openscale/gui/AddUserTest.java
+++ b/android_app/app/src/androidTest/java/com/health/openscale/gui/AddUserTest.java
@@ -17,8 +17,6 @@ package com.health.openscale.gui;
import android.content.Context;
import android.content.SharedPreferences;
-import android.content.res.Configuration;
-import android.content.res.Resources;
import android.preference.PreferenceManager;
import android.support.test.InstrumentationRegistry;
import android.support.test.espresso.ViewInteraction;
@@ -47,7 +45,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.Calendar;
-import java.util.Locale;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDigooDGSO38H.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDigooDGSO38H.java
index eeecd0da..a8200df4 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDigooDGSO38H.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDigooDGSO38H.java
@@ -23,7 +23,6 @@ import android.content.Context;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.datatypes.ScaleUser;
-import com.health.openscale.core.utils.Converters;
import java.util.Date;
import java.util.UUID;
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExcelvanCF36xBLE.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExcelvanCF36xBLE.java
index aa93327f..4d675d6c 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExcelvanCF36xBLE.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExcelvanCF36xBLE.java
@@ -20,7 +20,6 @@ import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.content.Context;
-import com.health.openscale.R;
import com.health.openscale.core.OpenScale;
import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.datatypes.ScaleUser;
diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExingtechY1.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExingtechY1.java
index 7e169a2e..e7ed5301 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExingtechY1.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothExingtechY1.java
@@ -25,7 +25,6 @@ import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.datatypes.ScaleUser;
import com.health.openscale.core.utils.Converters;
-import java.util.Calendar;
import java.util.Date;
import java.util.UUID;
diff --git a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleMeasurement.java b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleMeasurement.java
index 2634425f..0cbf9cec 100644
--- a/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleMeasurement.java
+++ b/android_app/app/src/main/java/com/health/openscale/core/datatypes/ScaleMeasurement.java
@@ -22,8 +22,6 @@ import android.arch.persistence.room.ForeignKey;
import android.arch.persistence.room.Index;
import android.arch.persistence.room.PrimaryKey;
-import com.health.openscale.R;
-import com.health.openscale.core.utils.Converters;
import com.j256.simplecsv.common.CsvColumn;
import java.lang.reflect.Field;
diff --git a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java
index 7cbe29a4..9557b4b6 100644
--- a/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java
+++ b/android_app/app/src/main/java/com/health/openscale/gui/MainActivity.java
@@ -16,7 +16,6 @@
package com.health.openscale.gui;
-import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
@@ -31,8 +30,6 @@ import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.support.annotation.NonNull;
-import android.support.design.internal.BottomNavigationItemView;
-import android.support.design.internal.BottomNavigationMenuView;
import android.support.design.widget.BottomNavigationView;
import android.support.design.widget.NavigationView;
import android.support.v4.app.Fragment;
@@ -64,7 +61,6 @@ import com.health.openscale.gui.fragments.TableFragment;
import com.health.openscale.gui.preferences.BluetoothPreferences;
import java.io.File;
-import java.lang.reflect.Field;
import java.util.List;
import cat.ereza.customactivityoncrash.config.CaocConfig;
diff --git a/android_app/app/src/main/java/com/health/openscale/gui/views/BMRMeasurementView.java b/android_app/app/src/main/java/com/health/openscale/gui/views/BMRMeasurementView.java
index 87c9008e..5d28c611 100644
--- a/android_app/app/src/main/java/com/health/openscale/gui/views/BMRMeasurementView.java
+++ b/android_app/app/src/main/java/com/health/openscale/gui/views/BMRMeasurementView.java
@@ -23,8 +23,6 @@ import com.health.openscale.core.datatypes.ScaleMeasurement;
import com.health.openscale.core.evaluation.EvaluationResult;
import com.health.openscale.core.evaluation.EvaluationSheet;
-import java.util.Locale;
-
public class BMRMeasurementView extends FloatMeasurementView {
// Don't change key value, it may be stored persistent in preferences
public static final String KEY = "bmr";
diff --git a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
index 379be790..066ffcad 100644
--- a/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
+++ b/android_app/app/src/test/java/com/health/openscale/ConvertersTest.java
@@ -20,8 +20,6 @@ import com.health.openscale.core.utils.Converters;
import org.junit.Test;
-import javax.sql.ConnectionEvent;
-
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;