1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-19 23:12:12 +02:00

refactoring bluetooth communication class for more abstraction and to load dynamically all available devices.

This commit is contained in:
OliE
2017-06-18 13:56:48 +02:00
parent cadedb9a60
commit 490061f7b8
10 changed files with 248 additions and 161 deletions

View File

@@ -25,10 +25,6 @@ import android.util.Log;
import com.health.openscale.core.alarm.AlarmHandler; import com.health.openscale.core.alarm.AlarmHandler;
import com.health.openscale.core.bluetooth.BluetoothCommunication; import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.bluetooth.BluetoothCustomOpenScale;
import com.health.openscale.core.bluetooth.BluetoothMedisanaBS444;
import com.health.openscale.core.bluetooth.BluetoothMiScale;
import com.health.openscale.core.bluetooth.BluetoothSanitasSbf70;
import com.health.openscale.core.database.ScaleDatabase; import com.health.openscale.core.database.ScaleDatabase;
import com.health.openscale.core.database.ScaleUserDatabase; import com.health.openscale.core.database.ScaleUserDatabase;
import com.health.openscale.core.datatypes.ScaleData; import com.health.openscale.core.datatypes.ScaleData;
@@ -48,11 +44,6 @@ import java.util.ArrayList;
import java.util.Map; import java.util.Map;
import java.util.TreeMap; import java.util.TreeMap;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_MEDISANA_BS444;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_MI_SCALE;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_OPEN_SCALE;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_SANITAS_SBF70;
public class OpenScale { public class OpenScale {
private static OpenScale instance; private static OpenScale instance;
@@ -354,24 +345,7 @@ public class OpenScale {
public void startSearchingForBluetooth(int btScales, String deviceName, Handler callbackBtHandler) { public void startSearchingForBluetooth(int btScales, String deviceName, Handler callbackBtHandler) {
Log.d("OpenScale", "Bluetooth Server started! I am searching for device ..."); Log.d("OpenScale", "Bluetooth Server started! I am searching for device ...");
switch (btScales) { btCom = BluetoothCommunication.getBtDevice(context, btScales);
case BT_MI_SCALE:
btCom = new BluetoothMiScale(context);
break;
case BT_OPEN_SCALE:
btCom = new BluetoothCustomOpenScale();
break;
case BT_SANITAS_SBF70:
btCom = new BluetoothSanitasSbf70(context);
break;
case BT_MEDISANA_BS444:
btCom = new BluetoothMedisanaBS444(context);
break;
default:
Log.e("OpenScale", "No valid scale type selected");
return;
}
btCom.registerCallbackHandler(callbackBtHandler); btCom.registerCallbackHandler(callbackBtHandler);
btDeviceName = deviceName; btDeviceName = deviceName;

View File

@@ -17,34 +17,79 @@
package com.health.openscale.core.bluetooth; package com.health.openscale.core.bluetooth;
import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.os.Handler; import android.os.Handler;
import com.health.openscale.core.datatypes.ScaleData;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_RETRIEVE_SCALE_DATA;
public abstract class BluetoothCommunication { public abstract class BluetoothCommunication {
public static final int BT_MI_SCALE = 0; public enum BT_STATUS_CODE {BT_RETRIEVE_SCALE_DATA, BT_INIT_PROCESS, BT_CONNECTION_ESTABLISHED, BT_CONNECTION_LOST, BT_NO_DEVICE_FOUND, BT_UNEXPECTED_ERROR };
public static final int BT_OPEN_SCALE = 1;
public static final int BT_SANITAS_SBF70 = 2;
public static final int BT_MEDISANA_BS444 = 3;
public static final int BT_RETRIEVE_SCALE_DATA = 0; private Handler callbackBtHandler;
public static final int BT_INIT_PROCESS = 1;
public static final int BT_CONNECTION_ESTABLISHED = 2;
public static final int BT_CONNECTION_LOST = 3;
public static final int BT_NO_DEVICE_FOUND = 4;
public static final int BT_UNEXPECTED_ERROR = 5;
protected Handler callbackBtHandler;
protected BluetoothAdapter btAdapter; protected BluetoothAdapter btAdapter;
public BluetoothCommunication() protected Context context;
public BluetoothCommunication(Context context)
{ {
this.context = context;
btAdapter = BluetoothAdapter.getDefaultAdapter(); btAdapter = BluetoothAdapter.getDefaultAdapter();
} }
public static BluetoothCommunication getBtDevice(Context context, int i) {
switch (i) {
case 0:
return new BluetoothCustomOpenScale(context);
case 1:
return new BluetoothMiScale(context);
case 2:
return new BluetoothSanitasSbf70(context);
case 3:
return new BluetoothMedisanaBS444(context);
}
return null;
}
public void registerCallbackHandler(Handler cbBtHandler) { public void registerCallbackHandler(Handler cbBtHandler) {
callbackBtHandler = cbBtHandler; callbackBtHandler = cbBtHandler;
} }
protected void setBtStatus(BT_STATUS_CODE statusCode) {
setBtStatus(statusCode, "");
}
protected void setBtStatus(BT_STATUS_CODE statusCode, String infoText) {
callbackBtHandler.obtainMessage(statusCode.ordinal(), infoText).sendToTarget();
}
protected void addScaleData(ScaleData scaleData) {
callbackBtHandler.obtainMessage(BT_RETRIEVE_SCALE_DATA.ordinal(), scaleData).sendToTarget();
}
abstract public String deviceName();
abstract public String defaultDeviceName();
abstract public void startSearching(String deviceName); abstract public void startSearching(String deviceName);
abstract public void stopSearching(); abstract public void stopSearching();
public boolean initSupported() {
return true;
}
public boolean transferSupported() {
return true;
}
public boolean historySupported() {
return true;
}
public boolean isBLE() {
return true;
}
} }

View File

@@ -17,6 +17,7 @@ package com.health.openscale.core.bluetooth;
import android.bluetooth.BluetoothDevice; import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket; import android.bluetooth.BluetoothSocket;
import android.content.Context;
import android.util.Log; import android.util.Log;
import com.health.openscale.core.datatypes.ScaleData; import com.health.openscale.core.datatypes.ScaleData;
@@ -29,6 +30,11 @@ import java.text.SimpleDateFormat;
import java.util.Set; import java.util.Set;
import java.util.UUID; import java.util.UUID;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_LOST;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_NO_DEVICE_FOUND;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_UNEXPECTED_ERROR;
public class BluetoothCustomOpenScale extends BluetoothCommunication { public class BluetoothCustomOpenScale extends BluetoothCommunication {
private final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // Standard SerialPortService ID private final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // Standard SerialPortService ID
@@ -37,11 +43,29 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
private BluetoothConnectedThread btConnectThread = null; private BluetoothConnectedThread btConnectThread = null;
public BluetoothCustomOpenScale(Context context) {
super(context);
}
@Override @Override
public String deviceName() {
return "Custom Open Scale";
}
@Override
public String defaultDeviceName() {
return "openScale_MCU";
}
public boolean isBLE() {
return false;
}
@Override
public void startSearching(String deviceName) { public void startSearching(String deviceName) {
if (btAdapter == null) { if (btAdapter == null) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
return; return;
} }
@@ -56,7 +80,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
// Get a BluetoothSocket to connect with the given BluetoothDevice // Get a BluetoothSocket to connect with the given BluetoothDevice
btSocket = btDevice.createRfcommSocketToServiceRecord(uuid); btSocket = btDevice.createRfcommSocketToServiceRecord(uuid);
} catch (IOException e) { } catch (IOException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Can't get a bluetooth socket").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Can't get a bluetooth socket");
} }
Thread socketThread = new Thread() { Thread socketThread = new Thread() {
@@ -69,7 +93,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
btSocket.connect(); btSocket.connect();
// Bluetooth connection was successful // Bluetooth connection was successful
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_ESTABLISHED).sendToTarget(); setBtStatus(BT_CONNECTION_ESTABLISHED);
btConnectThread = new BluetoothConnectedThread(); btConnectThread = new BluetoothConnectedThread();
btConnectThread.start(); btConnectThread.start();
@@ -77,7 +101,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
} catch (IOException connectException) { } catch (IOException connectException) {
// Unable to connect; close the socket and get out // Unable to connect; close the socket and get out
stopSearching(); stopSearching();
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
} }
} }
}; };
@@ -87,7 +111,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
} }
} }
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
} }
@Override @Override
@@ -98,7 +122,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
btSocket.close(); btSocket.close();
btSocket = null; btSocket = null;
} catch (IOException closeException) { } catch (IOException closeException) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Can't close bluetooth socket").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Can't close bluetooth socket");
} }
} }
} }
@@ -140,7 +164,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
btInStream = btSocket.getInputStream(); btInStream = btSocket.getInputStream();
btOutStream = btSocket.getOutputStream(); btOutStream = btSocket.getOutputStream();
} catch (IOException e) { } catch (IOException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Can't get bluetooth input or output stream " + e.getMessage()).sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Can't get bluetooth input or output stream " + e.getMessage());
} }
} }
@@ -159,7 +183,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
ScaleData scaleData = parseBtString(btLine.toString()); ScaleData scaleData = parseBtString(btLine.toString());
if (scaleData != null) { if (scaleData != null) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_RETRIEVE_SCALE_DATA, scaleData).sendToTarget(); addScaleData(scaleData);
} }
btLine.setLength(0); btLine.setLength(0);
@@ -167,7 +191,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
} catch (IOException e) { } catch (IOException e) {
cancel(); cancel();
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_LOST).sendToTarget(); setBtStatus(BT_CONNECTION_LOST);
} }
} }
} }
@@ -177,7 +201,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
btString = btString.substring(0, btString.length() - 1); // delete newline '\n' of the string btString = btString.substring(0, btString.length() - 1); // delete newline '\n' of the string
if (btString.charAt(0) != '$' && btString.charAt(2) != '$') { if (btString.charAt(0) != '$' && btString.charAt(2) != '$') {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Parse error of bluetooth string. String has not a valid format").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Parse error of bluetooth string. String has not a valid format");
} }
String btMsg = btString.substring(3, btString.length()); // message string String btMsg = btString.substring(3, btString.length()); // message string
@@ -224,16 +248,16 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
return scaleBtData; return scaleBtData;
} else { } else {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error calculated checksum (" + checksum + ") and received checksum (" + btChecksum + ") is different").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error calculated checksum (" + checksum + ") and received checksum (" + btChecksum + ") is different");
} }
} catch (ParseException e) { } catch (ParseException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")");
} catch (NumberFormatException e) { } catch (NumberFormatException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error while decoding a number of bluetooth string (" + e.getMessage() + ")").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding a number of bluetooth string (" + e.getMessage() + ")");
} }
break; break;
default: default:
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error unknown MCU command").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error unknown MCU command");
} }
return null; return null;
@@ -243,7 +267,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
try { try {
btOutStream.write(bytes); btOutStream.write(bytes);
} catch (IOException e) { } catch (IOException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error while writing to bluetooth socket " + e.getMessage()).sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error while writing to bluetooth socket " + e.getMessage());
} }
} }

View File

@@ -31,6 +31,10 @@ import com.health.openscale.core.datatypes.ScaleData;
import java.util.Date; import java.util.Date;
import java.util.UUID; import java.util.UUID;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_LOST;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_NO_DEVICE_FOUND;
public class BluetoothMedisanaBS444 extends BluetoothCommunication { public class BluetoothMedisanaBS444 extends BluetoothCommunication {
private BluetoothGatt bluetoothGatt; private BluetoothGatt bluetoothGatt;
private BluetoothAdapter.LeScanCallback scanCallback; private BluetoothAdapter.LeScanCallback scanCallback;
@@ -45,17 +49,30 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication {
private String btDeviceName; private String btDeviceName;
private Handler searchHandler; private Handler searchHandler;
private Context context;
private ScaleData btScaleData; private ScaleData btScaleData;
private int nextCmdState; private int nextCmdState;
public BluetoothMedisanaBS444(Context context) { public BluetoothMedisanaBS444(Context context) {
this.context = context; super(context);
searchHandler = new Handler(); searchHandler = new Handler();
btScaleData = new ScaleData(); btScaleData = new ScaleData();
scanCallback = null; scanCallback = null;
} }
@Override
public String deviceName() {
return "Medisana BS444";
}
@Override
public String defaultDeviceName() {
return "Medisana BS444";
}
public boolean initSupported() {
return false;
}
@Override @Override
public void startSearching(String deviceName) { public void startSearching(String deviceName) {
btDeviceName = deviceName; btDeviceName = deviceName;
@@ -82,7 +99,7 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication {
public void run() public void run()
{ {
btAdapter.stopLeScan(scanCallback); btAdapter.stopLeScan(scanCallback);
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
} }
}, 10000); }, 10000);
@@ -105,10 +122,10 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication {
@Override @Override
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) { public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) { if (newState == BluetoothProfile.STATE_CONNECTED) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_ESTABLISHED).sendToTarget(); setBtStatus(BT_CONNECTION_ESTABLISHED);
gatt.discoverServices(); gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_LOST).sendToTarget(); setBtStatus(BT_CONNECTION_LOST);
stopSearching(); stopSearching();
} }
} }
@@ -204,7 +221,7 @@ public class BluetoothMedisanaBS444 extends BluetoothCommunication {
if (characteristic.getUuid().equals(FEATURE_MEASUREMENT_CHARACTERISTIC)) { if (characteristic.getUuid().equals(FEATURE_MEASUREMENT_CHARACTERISTIC)) {
parseFeatureData(data); parseFeatureData(data);
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_RETRIEVE_SCALE_DATA, btScaleData).sendToTarget(); addScaleData(btScaleData);
} }
} }
}; };

View File

@@ -39,6 +39,12 @@ import java.util.Date;
import java.util.Random; import java.util.Random;
import java.util.UUID; import java.util.UUID;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_LOST;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_INIT_PROCESS;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_NO_DEVICE_FOUND;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_UNEXPECTED_ERROR;
public class BluetoothMiScale extends BluetoothCommunication { public class BluetoothMiScale extends BluetoothCommunication {
private BluetoothGatt bluetoothGatt; private BluetoothGatt bluetoothGatt;
@@ -51,7 +57,6 @@ public class BluetoothMiScale extends BluetoothCommunication {
private final UUID WEIGHT_MEASUREMENT_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb"); private final UUID WEIGHT_MEASUREMENT_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
private Handler searchHandler; private Handler searchHandler;
private Context context;
private String btDeviceName; private String btDeviceName;
private int nextCmdState; private int nextCmdState;
private int nextInitState; private int nextInitState;
@@ -59,12 +64,23 @@ public class BluetoothMiScale extends BluetoothCommunication {
private boolean initProcessOn; private boolean initProcessOn;
private boolean clearUpProcessOn; private boolean clearUpProcessOn;
public BluetoothMiScale(Context con) { public BluetoothMiScale(Context context) {
super(context);
searchHandler = new Handler(); searchHandler = new Handler();
context = con;
scanCallback = null; scanCallback = null;
} }
@Override
public String deviceName() {
return "Xiaomi Mi Scale";
}
@Override
public String defaultDeviceName() {
return "MI_SCALE";
}
@Override @Override
public void startSearching(String deviceName) { public void startSearching(String deviceName) {
btDeviceName = deviceName; btDeviceName = deviceName;
@@ -98,7 +114,7 @@ public class BluetoothMiScale extends BluetoothCommunication {
public void run() public void run()
{ {
btAdapter.stopLeScan(scanCallback); btAdapter.stopLeScan(scanCallback);
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
} }
}, 10000); }, 10000);
@@ -164,13 +180,13 @@ public class BluetoothMiScale extends BluetoothCommunication {
scaleBtData.setWeight(weight); scaleBtData.setWeight(weight);
scaleBtData.setDateTime(date_time); scaleBtData.setDateTime(date_time);
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_RETRIEVE_SCALE_DATA, scaleBtData).sendToTarget(); addScaleData(scaleBtData);
} else { } else {
Log.e("BluetoothMiScale", "Invalid Mi scale weight year " + year); Log.e("BluetoothMiScale", "Invalid Mi scale weight year " + year);
} }
} }
} catch (ParseException e) { } catch (ParseException e) {
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")").sendToTarget(); setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")");
} }
} }
@@ -231,11 +247,11 @@ public class BluetoothMiScale extends BluetoothCommunication {
public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) { public void onConnectionStateChange(final BluetoothGatt gatt, int status, int newState) {
if (newState == BluetoothProfile.STATE_CONNECTED) { if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d("BluetoothMiScale", "Connection established"); Log.d("BluetoothMiScale", "Connection established");
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_ESTABLISHED).sendToTarget(); setBtStatus(BT_CONNECTION_ESTABLISHED);
gatt.discoverServices(); gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d("BluetoothMiScale", "Connection lost"); Log.d("BluetoothMiScale", "Connection lost");
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_LOST).sendToTarget(); setBtStatus(BT_CONNECTION_LOST);
stopSearching(); stopSearching();
} }
} }
@@ -376,7 +392,7 @@ public class BluetoothMiScale extends BluetoothCommunication {
switch (nextInitState) { switch (nextInitState) {
case 0: case 0:
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_INIT_PROCESS).sendToTarget(); setBtStatus(BT_INIT_PROCESS);
// set current time // set current time
characteristic = gatt.getService(WEIGHT_MEASUREMENT_SERVICE) characteristic = gatt.getService(WEIGHT_MEASUREMENT_SERVICE)

View File

@@ -33,6 +33,11 @@ import java.util.LinkedList;
import java.util.Queue; import java.util.Queue;
import java.util.UUID; import java.util.UUID;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_CONNECTION_LOST;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_NO_DEVICE_FOUND;
import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_UNEXPECTED_ERROR;
public class BluetoothSanitasSbf70 extends BluetoothCommunication { public class BluetoothSanitasSbf70 extends BluetoothCommunication {
public final static String TAG = "BluetoothSanitasSbf70"; public final static String TAG = "BluetoothSanitasSbf70";
@@ -94,7 +99,6 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
private static final UUID CUSTOM_CHARACTERISTIC_IMG_BLOCK = // write-only, notify private static final UUID CUSTOM_CHARACTERISTIC_IMG_BLOCK = // write-only, notify
UUID.fromString("F000FFC2-0451-4000-8000-000000000000"); UUID.fromString("F000FFC2-0451-4000-8000-000000000000");
private Context context;
private BluetoothAdapter.LeScanCallback scanCallback = null; private BluetoothAdapter.LeScanCallback scanCallback = null;
// default name is usually "SANITAS SBF70" // default name is usually "SANITAS SBF70"
private String btDeviceName = null; private String btDeviceName = null;
@@ -104,11 +108,24 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
private BluetoothGatt bluetoothGatt; private BluetoothGatt bluetoothGatt;
public BluetoothSanitasSbf70(Context context) { public BluetoothSanitasSbf70(Context context) {
super(); super(context);
this.context = context;
searchHandler = new Handler(); searchHandler = new Handler();
} }
@Override
public String deviceName() {
return "Sanitas SBF70";
}
@Override
public String defaultDeviceName() {
return "SANITAS SBF70";
}
public boolean initSupported() {
return false;
}
private static final String HEX_DIGITS = "0123456789ABCDEF"; private static final String HEX_DIGITS = "0123456789ABCDEF";
/** /**
@@ -164,11 +181,11 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
Log.d(TAG, "onConnectionStatechange(" + status + ", " + newState + ")"); Log.d(TAG, "onConnectionStatechange(" + status + ", " + newState + ")");
if (newState == BluetoothProfile.STATE_CONNECTED) { if (newState == BluetoothProfile.STATE_CONNECTED) {
Log.d(TAG, "Connection established"); Log.d(TAG, "Connection established");
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_ESTABLISHED).sendToTarget(); setBtStatus(BT_CONNECTION_ESTABLISHED);
gatt.discoverServices(); gatt.discoverServices();
} else if (newState == BluetoothProfile.STATE_DISCONNECTED) { } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
Log.d(TAG, "Connection lost"); Log.d(TAG, "Connection lost");
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_CONNECTION_LOST).sendToTarget(); setBtStatus(BT_CONNECTION_LOST);
stopSearching(); stopSearching();
} }
} }
@@ -329,9 +346,7 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
Log.i(TAG, "Got muscle: " + muscle + "%"); Log.i(TAG, "Got muscle: " + muscle + "%");
scaleBtData.setMuscle(muscle); scaleBtData.setMuscle(muscle);
callbackBtHandler.obtainMessage( addScaleData(scaleBtData);
BluetoothCommunication.BT_RETRIEVE_SCALE_DATA, scaleBtData
).sendToTarget();
Log.d(TAG, "ACK Extra data (end)"); Log.d(TAG, "ACK Extra data (end)");
msgQueue.add(new byte[] { msgQueue.add(new byte[] {
@@ -359,8 +374,7 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
} else { } else {
Log.w(TAG, "Unidentified notification !"); Log.w(TAG, "Unidentified notification !");
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_UNEXPECTED_ERROR, setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding bluetooth value");
"Error while decoding bluetooth value").sendToTarget();
return; return;
} }
} }
@@ -407,7 +421,7 @@ public class BluetoothSanitasSbf70 extends BluetoothCommunication {
public void run() public void run()
{ {
btAdapter.stopLeScan(scanCallback); btAdapter.stopLeScan(scanCallback);
callbackBtHandler.obtainMessage(BluetoothCommunication.BT_NO_DEVICE_FOUND).sendToTarget(); setBtStatus(BT_NO_DEVICE_FOUND);
} }
}, 10000); }, 10000);

View File

@@ -39,8 +39,8 @@ import android.view.MenuItem;
import android.widget.Toast; import android.widget.Toast;
import com.health.openscale.R; import com.health.openscale.R;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.OpenScale; import com.health.openscale.core.OpenScale;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import com.health.openscale.core.datatypes.ScaleData; import com.health.openscale.core.datatypes.ScaleData;
import com.health.openscale.gui.activities.SettingsActivity; import com.health.openscale.gui.activities.SettingsActivity;
import com.health.openscale.gui.activities.UserSettingsActivity; import com.health.openscale.gui.activities.UserSettingsActivity;
@@ -184,10 +184,10 @@ public class MainActivity extends ActionBarActivity implements
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
String deviceName = prefs.getString("btDeviceName", "MI_SCALE"); String deviceName = prefs.getString("btDeviceName", "MI_SCALE");
String deviceType = prefs.getString("btDeviceTypes", "0"); int deviceType = Integer.parseInt(prefs.getString("btDeviceTypes", "0"));
// Check if Bluetooth 4.x is available // Check if Bluetooth 4.x is available
if (Integer.parseInt(deviceType) != BluetoothCommunication.BT_OPEN_SCALE) { if (BluetoothCommunication.getBtDevice(getApplicationContext(), deviceType).isBLE()) {
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) { if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
setBluetoothStatusIcon(R.drawable.bluetooth_disabled); setBluetoothStatusIcon(R.drawable.bluetooth_disabled);
Toast.makeText(getApplicationContext(), "Bluetooth 4.x " + getResources().getString(R.string.info_is_not_available), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), "Bluetooth 4.x " + getResources().getString(R.string.info_is_not_available), Toast.LENGTH_SHORT).show();
@@ -199,15 +199,17 @@ public class MainActivity extends ActionBarActivity implements
setBluetoothStatusIcon(R.drawable.bluetooth_searching); setBluetoothStatusIcon(R.drawable.bluetooth_searching);
OpenScale.getInstance(getApplicationContext()).stopSearchingForBluetooth(); OpenScale.getInstance(getApplicationContext()).stopSearchingForBluetooth();
OpenScale.getInstance(getApplicationContext()).startSearchingForBluetooth(Integer.parseInt(deviceType), deviceName, callbackBtHandler); OpenScale.getInstance(getApplicationContext()).startSearchingForBluetooth(deviceType, deviceName, callbackBtHandler);
} }
private final Handler callbackBtHandler = new Handler() { private final Handler callbackBtHandler = new Handler() {
@Override @Override
public void handleMessage(Message msg) { public void handleMessage(Message msg) {
switch (msg.what) { BluetoothCommunication.BT_STATUS_CODE btStatusCode = BluetoothCommunication.BT_STATUS_CODE.values()[msg.what];
case BluetoothCommunication.BT_RETRIEVE_SCALE_DATA:
switch (btStatusCode) {
case BT_RETRIEVE_SCALE_DATA:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_success); setBluetoothStatusIcon(R.drawable.bluetooth_connection_success);
ScaleData scaleBtData = (ScaleData) msg.obj; ScaleData scaleBtData = (ScaleData) msg.obj;
@@ -217,27 +219,27 @@ public class MainActivity extends ActionBarActivity implements
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_no_selected_user), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_no_selected_user), Toast.LENGTH_SHORT).show();
} }
break; break;
case BluetoothCommunication.BT_INIT_PROCESS: case BT_INIT_PROCESS:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_success); setBluetoothStatusIcon(R.drawable.bluetooth_connection_success);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_init), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_init), Toast.LENGTH_SHORT).show();
Log.d("OpenScale", "Bluetooth initializing"); Log.d("OpenScale", "Bluetooth initializing");
break; break;
case BluetoothCommunication.BT_CONNECTION_LOST: case BT_CONNECTION_LOST:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost); setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_lost), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_lost), Toast.LENGTH_SHORT).show();
Log.d("OpenScale", "Bluetooth connection lost"); Log.d("OpenScale", "Bluetooth connection lost");
break; break;
case BluetoothCommunication.BT_NO_DEVICE_FOUND: case BT_NO_DEVICE_FOUND:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost); setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_no_device), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_no_device), Toast.LENGTH_SHORT).show();
Log.d("OpenScale", "No Bluetooth device found"); Log.d("OpenScale", "No Bluetooth device found");
break; break;
case BluetoothCommunication.BT_CONNECTION_ESTABLISHED: case BT_CONNECTION_ESTABLISHED:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_success); setBluetoothStatusIcon(R.drawable.bluetooth_connection_success);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_successful), Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_successful), Toast.LENGTH_SHORT).show();
Log.d("OpenScale", "Bluetooth connection successful established"); Log.d("OpenScale", "Bluetooth connection successful established");
break; break;
case BluetoothCommunication.BT_UNEXPECTED_ERROR: case BT_UNEXPECTED_ERROR:
setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost); setBluetoothStatusIcon(R.drawable.bluetooth_connection_lost);
Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_error) + ": " + msg.obj, Toast.LENGTH_SHORT).show(); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_error) + ": " + msg.obj, Toast.LENGTH_SHORT).show();
Log.e("OpenScale", "Bluetooth unexpected error: " + msg.obj); Log.e("OpenScale", "Bluetooth unexpected error: " + msg.obj);

View File

@@ -27,38 +27,37 @@ import android.preference.PreferenceGroup;
import android.text.Html; import android.text.Html;
import com.health.openscale.R; import com.health.openscale.R;
import com.health.openscale.core.bluetooth.BluetoothCommunication;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
public class BluetoothPreferences extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { import static com.health.openscale.core.bluetooth.BluetoothCommunication.getBtDevice;
public static final String PREFERENCE_KEY_BLUETOOTH_SMARTUSERASSIGN = "smartUserAssign"; public class BluetoothPreferences extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String PREFERENCE_KEY_BLUETOOTH_DEVICE_TYPE = "btDeviceTypes";
private static final String PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME = "btDeviceName";
private static final String PREFERENCE_KEY_BLUETOOTH_SMARTUSERASSIGN = "smartUserAssign";
private static final String PREFERENCE_KEY_BLUETOOTH_IGNOREOUTOFRANGE = "ignoreOutOfRange"; private static final String PREFERENCE_KEY_BLUETOOTH_IGNOREOUTOFRANGE = "ignoreOutOfRange";
private ListPreference deviceTypes;
private EditTextPreference deviceName;
private CheckBoxPreference smartAssignEnable; private CheckBoxPreference smartAssignEnable;
private CheckBoxPreference ignoreOutOfRangeEnable; private CheckBoxPreference ignoreOutOfRangeEnable;
private String[] btDeviceSupportInit;
private String[] btDeviceSupportDataTransfer;
private String[] btDeviceSupportDataHistory;
private String[] btDeviceDefaultName;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.bluetooth_preferences); addPreferencesFromResource(R.xml.bluetooth_preferences);
deviceTypes = (ListPreference)findPreference(PREFERENCE_KEY_BLUETOOTH_DEVICE_TYPE);
deviceName = (EditTextPreference)findPreference(PREFERENCE_KEY_BLUETOOTH_DEVICE_NAME);
smartAssignEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_BLUETOOTH_SMARTUSERASSIGN); smartAssignEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_BLUETOOTH_SMARTUSERASSIGN);
ignoreOutOfRangeEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_BLUETOOTH_IGNOREOUTOFRANGE); ignoreOutOfRangeEnable = (CheckBoxPreference) findPreference(PREFERENCE_KEY_BLUETOOTH_IGNOREOUTOFRANGE);
btDeviceSupportInit = getResources().getStringArray(R.array.bt_device_support_initializing); updateBluetoothPreferences();
btDeviceSupportDataTransfer = getResources().getStringArray(R.array.bt_device_support_data_transfer);
btDeviceSupportDataHistory = getResources().getStringArray(R.array.bt_device_support_data_history);
btDeviceDefaultName = getResources().getStringArray(R.array.bt_device_default_name);
initSummary(getPreferenceScreen()); initSummary(getPreferenceScreen());
} }
@@ -73,6 +72,29 @@ public class BluetoothPreferences extends PreferenceFragment implements SharedPr
} }
} }
public void updateBluetoothPreferences() {
int i = 0;
ArrayList<String> btEntries = new ArrayList();
ArrayList<String> btEntryValues = new ArrayList();
while (true) {
BluetoothCommunication btCom = getBtDevice(getActivity().getApplicationContext(), i);
if (btCom == null) {
break;
}
btEntries.add(btCom.deviceName());
btEntryValues.add(String.valueOf(i));
i++;
}
deviceTypes.setEntries(btEntries.toArray(new CharSequence[btEntries.size()]));
deviceTypes.setEntryValues(btEntryValues.toArray(new CharSequence[btEntryValues.size()]));
}
@Override @Override
public void onResume() { public void onResume() {
super.onResume(); super.onResume();
@@ -103,17 +125,35 @@ public class BluetoothPreferences extends PreferenceFragment implements SharedPr
int i = Integer.parseInt(listPref.getValue()); int i = Integer.parseInt(listPref.getValue());
p.setSummary(Html.fromHtml(listPref.getEntry() + "<br>" + BluetoothCommunication btCom = BluetoothCommunication.getBtDevice(getActivity().getApplicationContext(), i);
getResources().getString(R.string.label_bt_device_support) + ":" + "<br>" +
getResources().getString(R.string.label_bt_device_initialization) + ": " + btDeviceSupportInit[i] + "<br>" +
getResources().getString(R.string.label_bt_device_data_transfer) + ": " + btDeviceSupportDataTransfer[i] + "<br>" +
getResources().getString(R.string.label_bt_device_data_history) + ": " + btDeviceSupportDataHistory[i]
));
getPreferenceManager().getDefaultSharedPreferences(getActivity().getApplicationContext()).edit().putString("btDeviceName", btDeviceDefaultName[i]).commit(); String summary = new String();
EditTextPreference prefDeviceName = (EditTextPreference)findPreference("btDeviceName");
prefDeviceName.setSummary(btDeviceDefaultName[i]); summary += listPref.getEntry() + "<br>" +
prefDeviceName.setText(btDeviceDefaultName[i]); getResources().getString(R.string.label_bt_device_support) + ":" + "<br>";
if (btCom.initSupported()) {
summary += getResources().getString(R.string.label_bt_device_initialization) + ": " + getResources().getString(R.string.label_yes)+ "<br>";
} else {
summary += getResources().getString(R.string.label_bt_device_initialization) + ": " + getResources().getString(R.string.label_no)+ "<br>";
}
if (btCom.transferSupported()) {
summary += getResources().getString(R.string.label_bt_device_data_transfer) + ": " + getResources().getString(R.string.label_yes)+ "<br>";
} else {
summary += getResources().getString(R.string.label_bt_device_data_transfer) + ": " + getResources().getString(R.string.label_no)+ "<br>";
}
if (btCom.historySupported()) {
summary += getResources().getString(R.string.label_bt_device_data_history) + ": " + getResources().getString(R.string.label_yes);
} else {
summary += getResources().getString(R.string.label_bt_device_data_history) + ": " + getResources().getString(R.string.label_no);
}
p.setSummary(Html.fromHtml(summary));
deviceName.setSummary(btCom.defaultDeviceName());
deviceName.setText(btCom.defaultDeviceName());
} }
if (p instanceof EditTextPreference) { if (p instanceof EditTextPreference) {

View File

@@ -1,45 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:tools="http://schemas.android.com/tools" tools:ignore="MissingTranslation">
<string-array name="bt_device_entries">
<item>Xiaomi Mi Scale v1</item>
<item>openScale Custom Scale</item>
<item>Sanitas SBF-70</item>#
<item>Medisana BS444 Connect</item>
</string-array>
<string-array name="bt_device_values">
<item>0</item>
<item>1</item>
<item>2</item>
<item>3</item>
</string-array>
<string-array name="bt_device_default_name">
<item>MI_SCALE</item>
<item>openScale_MCU</item>
<item>SANITAS SBF70</item>
<item>Medisana BS444</item>
</string-array>
<string-array name="bt_device_support_initializing">
<item>@string/label_yes</item>
<item>@string/label_yes</item>
<item>@string/label_no</item>
<item>@string/label_no</item>
</string-array>
<string-array name="bt_device_support_data_transfer">
<item>@string/label_yes</item>
<item>@string/label_yes</item>
<item>@string/label_yes</item>
<item>@string/label_yes</item>
</string-array>
<string-array name="bt_device_support_data_history">
<item>@string/label_yes</item>
<item>@string/label_yes</item>
<item>@string/label_no</item>
<item>@string/label_yes</item>
</string-array>
</resources>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<ListPreference android:title="@string/label_device_type" android:key="btDeviceTypes" android:entries="@array/bt_device_entries" android:entryValues="@array/bt_device_values" android:defaultValue="0"/> <ListPreference android:title="@string/label_device_type" android:key="btDeviceTypes"/>
<EditTextPreference android:title="@string/label_device_name" android:key="btDeviceName" android:defaultValue="MI_SCALE" /> <EditTextPreference android:title="@string/label_device_name" android:key="btDeviceName"/>
<CheckBoxPreference android:title="@string/label_bluetooth_enable" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="btEnable" android:defaultValue="false"/> <CheckBoxPreference android:title="@string/label_bluetooth_enable" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="btEnable" android:defaultValue="false"/>
<CheckBoxPreference android:title="@string/label_smartUserAssign" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="smartUserAssign" android:defaultValue="false"/> <CheckBoxPreference android:title="@string/label_smartUserAssign" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="smartUserAssign" android:defaultValue="false"/>
<CheckBoxPreference android:title="@string/label_ignoreOutOfRange" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="ignoreOutOfRange" android:enabled="false" android:defaultValue="false"/> <CheckBoxPreference android:title="@string/label_ignoreOutOfRange" android:summaryOn="@string/info_is_enable" android:summaryOff="@string/info_is_not_enable" android:key="ignoreOutOfRange" android:enabled="false" android:defaultValue="false"/>