From b77fd43e979c585abb4389148ba3a9af9828cf5f Mon Sep 17 00:00:00 2001 From: Erik Johansson Date: Fri, 18 May 2018 22:33:38 +0200 Subject: [PATCH] Use Converter methods to convert bytes Medisana --- .../bluetooth/BluetoothMedisanaBS444.java | 43 ++++++++----------- .../openscale/core/utils/Converters.java | 17 ++++++++ .../com/health/openscale/ConvertersTest.java | 12 ++++++ 3 files changed, 48 insertions(+), 24 deletions(-) diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS444.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS444.java index 8eaf08e0..7840a74f 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS444.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMedisanaBS444.java @@ -20,6 +20,7 @@ import android.bluetooth.BluetoothGattCharacteristic; import android.content.Context; import com.health.openscale.core.datatypes.ScaleMeasurement; +import com.health.openscale.core.utils.Converters; import java.util.Date; import java.util.UUID; @@ -35,6 +36,9 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication { private ScaleMeasurement btScaleMeasurement; + // Scale time is in seconds since 2010-01-01 + private static final long SCALE_UNIX_TIMESTAMP_OFFSET = 1262304000; + public BluetoothMedisanaBS444(Context context) { super(context); btScaleMeasurement = new ScaleMeasurement(); @@ -67,17 +71,11 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication { break; case 3: // send magic number to receive weight data - Date date = new Date(); - int unix_timestamp = (int) ((date.getTime() / 1000) - 1262304000); // -40 years because unix time starts in year 1970 + long timestamp = new Date().getTime() / 1000; + timestamp -= SCALE_UNIX_TIMESTAMP_OFFSET; + byte[] date = Converters.toUnsignedInt32Le(timestamp); - byte[] magicBytes = new byte[] { - (byte)0x02, - (byte)(unix_timestamp), - (byte)(unix_timestamp >>> 8), - (byte)(unix_timestamp >>> 16), - (byte)(unix_timestamp >>> 24) - }; - //byte[] magicBytes = new byte[]{(byte)0x02, (byte)0x7B, (byte)0x7B, (byte)0xF6, (byte)0x0D}; // 02:7b:7b:f6:0d + byte[] magicBytes = new byte[] {(byte)0x02, date[0], date[1], date[2], date[3]}; writeBytes(WEIGHT_MEASUREMENT_SERVICE, CMD_MEASUREMENT_CHARACTERISTIC, magicBytes); break; @@ -110,26 +108,23 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication { } private void parseWeightData(byte[] weightData) { - float weight = (float)(((weightData[2] & 0xFF) << 8) | (weightData[1] & 0xFF)) / 100.0f; - long unix_timestamp = ((weightData[8] & 0xFF) << 24) | ((weightData[7] & 0xFF) << 16) | ((weightData[6] & 0xFF) << 8) | (weightData[5] & 0xFF); // elapsed time in seconds since 2010 + float weight = Converters.fromUnsignedInt16Le(weightData, 1) / 100.0f; + long timestamp = Converters.fromUnsignedInt32Le(weightData, 5); + timestamp += SCALE_UNIX_TIMESTAMP_OFFSET; - Date btDate = new Date(); - unix_timestamp += 1262304000; // +40 years because unix time starts in year 1970 - btDate.setTime(unix_timestamp*1000); // multiply with 1000 to get milliseconds - - btScaleMeasurement.setDateTime(btDate); + btScaleMeasurement.setDateTime(new Date(timestamp * 1000)); btScaleMeasurement.setWeight(weight); } private void parseFeatureData(byte[] featureData) { - //btScaleData.setKCal(((featureData[7] & 0xFF) << 8) | (featureData[6] & 0xFF)); - btScaleMeasurement.setFat(decodeFeature(featureData[8], featureData[9])); - btScaleMeasurement.setWater(decodeFeature(featureData[10], featureData[11])); - btScaleMeasurement.setMuscle(decodeFeature(featureData[12], featureData[13])); - btScaleMeasurement.setBone(decodeFeature(featureData[14], featureData[15])); + //btScaleData.setKCal(Converters.fromUnsignedInt16Le(featureData, 6)); + btScaleMeasurement.setFat(decodeFeature(featureData, 8)); + btScaleMeasurement.setWater(decodeFeature(featureData, 10)); + btScaleMeasurement.setMuscle(decodeFeature(featureData, 12)); + btScaleMeasurement.setBone(decodeFeature(featureData, 14)); } - private float decodeFeature(byte highByte, byte lowByte) { - return (float)(((lowByte& 0x0F) << 8) | (highByte & 0xFF)) / 10.0f; + private float decodeFeature(byte[] featureData, int offset) { + return (Converters.fromUnsignedInt16Le(featureData, offset) & 0x0FFF) / 10.0f; } } 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 f5087113..06f621b2 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 @@ -150,6 +150,14 @@ public class Converters { return value; } + public static long fromUnsignedInt32Le(byte[] data, int offset) { + long value = (long) (data[offset + 3] & 0xFF) << 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; value += (data[offset + 1] & 0xFF) << 16; @@ -158,6 +166,15 @@ public class Converters { return value; } + public static byte[] toUnsignedInt32Le(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); + return data; + } + public static byte[] toUnsignedInt32Be(long value) { byte[] data = new byte[4]; data[0] = (byte) ((value >> 24) & 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 eee19ac4..4b95155c 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 @@ -114,15 +114,27 @@ public class ConvertersTest { @Test public void unsignedInt32Converters() throws Exception { byte[] data = new byte[]{(byte) 0xf1, (byte) 0xf2, (byte) 0xf3, (byte) 0x7f, (byte) 0x7e}; + + assertEquals(0x7ff3f2f1, Converters.fromUnsignedInt32Le(data, 0)); + assertEquals(0x7e7ff3f2, Converters.fromUnsignedInt32Le(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(0xff010080L, Converters.fromUnsignedInt32Le(data, 0)); + assertEquals(0xff0100, Converters.fromUnsignedInt32Le(data, 1)); + assertEquals(0x800001ffL, Converters.fromUnsignedInt32Be(data, 0)); 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)); + assertEquals(0xffffffffL, + Converters.fromUnsignedInt32Le( + Converters.toUnsignedInt32Le(0xffffffffL), 0)); assertEquals(0xffffffffL, Converters.fromUnsignedInt32Be( Converters.toUnsignedInt32Be(0xffffffffL), 0));