diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothFactory.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothFactory.java index 3938cbd0..82e4cad2 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothFactory.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothFactory.java @@ -136,6 +136,9 @@ public class BluetoothFactory { if (deviceName.equals("CH100")){ return new BluetoothHuaweiAH100(context); } + if (deviceName.equals("Yoda1")){ + return new BluetoothYoda1Scale(context); + } return null; } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYoda1Scale.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYoda1Scale.java new file mode 100644 index 00000000..87930476 --- /dev/null +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothYoda1Scale.java @@ -0,0 +1,109 @@ +package com.health.openscale.core.bluetooth; + +import android.bluetooth.le.ScanFilter; +import android.bluetooth.le.ScanResult; +import android.content.Context; +import android.os.Handler; +import android.os.Looper; +import android.util.SparseArray; + +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 com.welie.blessed.BluetoothCentralManager; +import com.welie.blessed.BluetoothCentralManagerCallback; +import com.welie.blessed.BluetoothPeripheral; + +import org.jetbrains.annotations.NotNull; + +import java.util.LinkedList; +import java.util.List; + +import timber.log.Timber; + +public class BluetoothYoda1Scale extends BluetoothCommunication { + + private BluetoothCentralManager central; + private final BluetoothCentralManagerCallback btCallback = new BluetoothCentralManagerCallback() { + @Override + public void onDiscoveredPeripheral(@NotNull BluetoothPeripheral peripheral, @NotNull ScanResult scanResult) { + SparseArray manufacturerSpecificData = scanResult.getScanRecord().getManufacturerSpecificData(); + byte[] weightBytes = manufacturerSpecificData.valueAt(0); + + //int featuresAndCounter = manufacturerSpecificData.keyAt(0); + //Timber.d("Feature: %d, Counter: %d", featuresAndCounter & 0xFF, featuresAndCounter >> 8); + + final byte ctrlByte = weightBytes[6]; + + final boolean isStabilized = isBitSet(ctrlByte, 0); + final boolean isKgUnit = isBitSet(ctrlByte, 2); + final boolean isOneDecimal = isBitSet(ctrlByte, 3); + + if (isStabilized) { + Timber.d("One digit decimal: %s", isOneDecimal); + Timber.d("Unit Kg: %s", isKgUnit); + + float weight; + + if (isKgUnit) { + weight = (float) (((weightBytes[0] & 0xFF) << 8) | (weightBytes[1] & 0xFF)) / 10.0f; + } else { + // catty + weight = (float) (((weightBytes[0] & 0xFF) << 8) | (weightBytes[1] & 0xFF)) / 20.0f; + } + + if (!isOneDecimal) { + weight /= 10.0; + } + + Timber.d("Got weight: %f", weight); + + final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser(); + ScaleMeasurement scaleBtData = new ScaleMeasurement(); + + scaleBtData.setWeight(Converters.toKilogram(weight, selectedUser.getScaleUnit())); + addScaleMeasurement(scaleBtData); + + disconnect(); + } + } + }; + + public BluetoothYoda1Scale(Context context) { + super(context); + central = new BluetoothCentralManager(context, btCallback, new Handler(Looper.getMainLooper())); + } + + @Override + public void connect(String macAddress) { + Timber.d("Mac address: %s", macAddress); + List filters = new LinkedList(); + + ScanFilter.Builder b = new ScanFilter.Builder(); + b.setDeviceAddress(macAddress); + + b.setDeviceName("Yoda1"); + filters.add(b.build()); + + central.scanForPeripheralsUsingFilters(filters); + } + + @Override + public void disconnect() { + if (central != null) + central.stopScan(); + central = null; + super.disconnect(); + } + + @Override + public String driverName() { + return "Yoda1 Scale"; + } + + @Override + protected boolean onNextStep(int stepNr) { + return false; + } +}