mirror of
https://github.com/oliexdev/openScale.git
synced 2025-09-02 12:54:10 +02:00
changed custom openScale scale from Bluetooth 3.x to Bluetooth 4.x to comply with openScale MCU version 1.1
This commit is contained in:
@@ -476,6 +476,8 @@ public abstract class BluetoothCommunication {
|
||||
|
||||
bluetoothGatt.close();
|
||||
bluetoothGatt = null;
|
||||
|
||||
setBtStatus(BT_STATUS_CODE.BT_CONNECTION_LOST);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -15,28 +15,26 @@
|
||||
*/
|
||||
package com.health.openscale.core.bluetooth;
|
||||
|
||||
import android.bluetooth.BluetoothDevice;
|
||||
import android.bluetooth.BluetoothSocket;
|
||||
import android.bluetooth.BluetoothGatt;
|
||||
import android.bluetooth.BluetoothGattCharacteristic;
|
||||
import android.content.Context;
|
||||
|
||||
import com.health.openscale.core.datatypes.ScaleMeasurement;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Locale;
|
||||
import java.util.UUID;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
private final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805f9b34fb"); // Standard SerialPortService ID
|
||||
private final UUID WEIGHT_MEASUREMENT_SERVICE = UUID.fromString("0000ffe0-0000-1000-8000-00805f9b34fb");
|
||||
private final UUID WEIGHT_MEASUREMENT_CHARACTERISTIC = UUID.fromString("0000ffe1-0000-1000-8000-00805f9b34fb"); // Bluetooth Modul HM-10
|
||||
private final UUID WEIGHT_MEASUREMENT_CONFIG = UUID.fromString("00002902-0000-1000-8000-00805f9b34fb");
|
||||
|
||||
private BluetoothSocket btSocket = null;
|
||||
private BluetoothDevice btDevice = null;
|
||||
|
||||
private BluetoothConnectedThread btConnectThread = null;
|
||||
private String string_data = new String();
|
||||
|
||||
public BluetoothCustomOpenScale(Context context) {
|
||||
super(context);
|
||||
@@ -44,14 +42,35 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
|
||||
@Override
|
||||
public String driverName() {
|
||||
return "Custom Open Scale";
|
||||
return "Custom openScale";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean nextInitCmd(int stateNr) {
|
||||
switch (stateNr) {
|
||||
case 0:
|
||||
setNotificationOn(WEIGHT_MEASUREMENT_SERVICE, WEIGHT_MEASUREMENT_CHARACTERISTIC, WEIGHT_MEASUREMENT_CONFIG);
|
||||
break;
|
||||
case 1:
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
String date_time = String.format(Locale.US, "2%1d,%1d,%1d,%1d,%1d,%1d,",
|
||||
cal.get(Calendar.YEAR)-2000,
|
||||
cal.get(Calendar.MONTH) + 1,
|
||||
cal.get(Calendar.DAY_OF_MONTH),
|
||||
cal.get(Calendar.HOUR_OF_DAY),
|
||||
cal.get(Calendar.MINUTE),
|
||||
cal.get(Calendar.SECOND));
|
||||
|
||||
writeBytes(WEIGHT_MEASUREMENT_SERVICE, WEIGHT_MEASUREMENT_CHARACTERISTIC, date_time.getBytes());
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean nextBluetoothCmd(int stateNr) {
|
||||
return false;
|
||||
@@ -62,153 +81,51 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect(String hwAddress) {
|
||||
|
||||
if (btAdapter == null) {
|
||||
setBtStatus(BT_STATUS_CODE.BT_NO_DEVICE_FOUND);
|
||||
return;
|
||||
}
|
||||
|
||||
btDevice = btAdapter.getRemoteDevice(hwAddress);
|
||||
try {
|
||||
// Get a BluetoothSocket to connect with the given BluetoothDevice
|
||||
btSocket = btDevice.createRfcommSocketToServiceRecord(uuid);
|
||||
} catch (IOException e) {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Can't get a bluetooth socket");
|
||||
btDevice = null;
|
||||
return;
|
||||
}
|
||||
|
||||
Thread socketThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
if (!btSocket.isConnected()) {
|
||||
// Connect the device through the socket. This will block
|
||||
// until it succeeds or throws an exception
|
||||
btSocket.connect();
|
||||
|
||||
// Bluetooth connection was successful
|
||||
setBtStatus(BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED);
|
||||
|
||||
btConnectThread = new BluetoothConnectedThread();
|
||||
btConnectThread.start();
|
||||
}
|
||||
} catch (IOException connectException) {
|
||||
// Unable to connect; close the socket and get out
|
||||
disconnect(false);
|
||||
setBtStatus(BT_STATUS_CODE.BT_NO_DEVICE_FOUND);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
socketThread.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void disconnect(boolean doCleanup) {
|
||||
if (btSocket != null) {
|
||||
if (btSocket.isConnected()) {
|
||||
try {
|
||||
btSocket.close();
|
||||
btSocket = null;
|
||||
} catch (IOException closeException) {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Can't close bluetooth socket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (btConnectThread != null) {
|
||||
btConnectThread.cancel();
|
||||
btConnectThread = null;
|
||||
}
|
||||
|
||||
btDevice = null;
|
||||
}
|
||||
|
||||
public void clearEEPROM()
|
||||
{
|
||||
sendBtData("9");
|
||||
byte[] cmd = {(byte)'9'};
|
||||
writeBytes(WEIGHT_MEASUREMENT_SERVICE, WEIGHT_MEASUREMENT_CHARACTERISTIC, cmd);
|
||||
}
|
||||
|
||||
private boolean sendBtData(String data) {
|
||||
if (btSocket.isConnected()) {
|
||||
btConnectThread = new BluetoothConnectedThread();
|
||||
btConnectThread.write(data.getBytes());
|
||||
@Override
|
||||
public void onBluetoothDataChange(BluetoothGatt bluetoothGatt, BluetoothGattCharacteristic gattCharacteristic) {
|
||||
final byte[] data = gattCharacteristic.getValue();
|
||||
|
||||
btConnectThread.cancel();
|
||||
return true;
|
||||
if (data != null) {
|
||||
for (byte character : data) {
|
||||
string_data += (char) (character & 0xFF);
|
||||
|
||||
if (character == '\n') {
|
||||
parseBtString(string_data);
|
||||
string_data = new String();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private class BluetoothConnectedThread extends Thread {
|
||||
private InputStream btInStream;
|
||||
private OutputStream btOutStream;
|
||||
private volatile boolean isCancel;
|
||||
|
||||
public BluetoothConnectedThread() {
|
||||
|
||||
isCancel = false;
|
||||
|
||||
// Get the input and output bluetooth streams
|
||||
try {
|
||||
btInStream = btSocket.getInputStream();
|
||||
btOutStream = btSocket.getOutputStream();
|
||||
} catch (IOException e) {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Can't get bluetooth input or output stream " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void run() {
|
||||
final StringBuilder btLine = new StringBuilder();
|
||||
|
||||
// Keep listening to the InputStream until an exception occurs (e.g. device partner goes offline)
|
||||
while (!isCancel) {
|
||||
try {
|
||||
// stream read is a blocking method
|
||||
char btChar = (char) btInStream.read();
|
||||
|
||||
btLine.append(btChar);
|
||||
|
||||
if (btLine.charAt(btLine.length() - 1) == '\n') {
|
||||
ScaleMeasurement scaleMeasurement = parseBtString(btLine.toString());
|
||||
|
||||
if (scaleMeasurement != null) {
|
||||
addScaleData(scaleMeasurement);
|
||||
}
|
||||
|
||||
btLine.setLength(0);
|
||||
}
|
||||
|
||||
} catch (IOException e) {
|
||||
cancel();
|
||||
setBtStatus(BT_STATUS_CODE.BT_CONNECTION_LOST);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ScaleMeasurement parseBtString(String btString) throws IOException {
|
||||
ScaleMeasurement scaleBtData = new ScaleMeasurement();
|
||||
private void parseBtString(String btString) {
|
||||
btString = btString.substring(0, btString.length() - 1); // delete newline '\n' of the string
|
||||
|
||||
if (btString.charAt(0) != '$' && btString.charAt(2) != '$') {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Parse error of bluetooth string. String has not a valid format");
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Parse error of bluetooth string. String has not a valid format: " + btString);
|
||||
}
|
||||
|
||||
String btMsg = btString.substring(3, btString.length()); // message string
|
||||
|
||||
switch (btString.charAt(1)) {
|
||||
case 'I':
|
||||
Timber.i("MCU Information: %s", btMsg);
|
||||
Timber.d("MCU Information: %s", btMsg);
|
||||
break;
|
||||
case 'E':
|
||||
Timber.e("MCU Error: %s", btMsg);
|
||||
break;
|
||||
case 'S':
|
||||
Timber.i("MCU stored data size: %s", btMsg);
|
||||
Timber.d("MCU stored data size: %s", btMsg);
|
||||
break;
|
||||
case 'F':
|
||||
Timber.d("All data sent");
|
||||
clearEEPROM();
|
||||
disconnect(false);
|
||||
break;
|
||||
case 'D':
|
||||
String[] csvField = btMsg.split(",");
|
||||
@@ -230,8 +147,8 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
int btChecksum = Integer.parseInt(csvField[10]);
|
||||
|
||||
if (checksum == btChecksum) {
|
||||
scaleBtData.setId(-1);
|
||||
scaleBtData.setUserId(Integer.parseInt(csvField[0]));
|
||||
ScaleMeasurement scaleBtData = new ScaleMeasurement();
|
||||
|
||||
String date_string = csvField[1] + "/" + csvField[2] + "/" + csvField[3] + "/" + csvField[4] + "/" + csvField[5];
|
||||
scaleBtData.setDateTime(new SimpleDateFormat("yyyy/MM/dd/HH/mm").parse(date_string));
|
||||
|
||||
@@ -240,7 +157,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
scaleBtData.setWater(Float.parseFloat(csvField[8]));
|
||||
scaleBtData.setMuscle(Float.parseFloat(csvField[9]));
|
||||
|
||||
return scaleBtData;
|
||||
addScaleData(scaleBtData);
|
||||
} else {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error calculated checksum (" + checksum + ") and received checksum (" + btChecksum + ") is different");
|
||||
}
|
||||
@@ -251,22 +168,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error unknown MCU command");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public void write(byte[] bytes) {
|
||||
try {
|
||||
btOutStream.write(bytes);
|
||||
} catch (IOException e) {
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error while writing to bluetooth socket " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
isCancel = true;
|
||||
setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error unknown MCU command : " + btString);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -38,7 +38,7 @@ public class BluetoothFactory {
|
||||
if (name.startsWith("BEURER BF710".toLowerCase(Locale.US))) {
|
||||
return new BluetoothBeurerSanitas(context, BluetoothBeurerSanitas.DeviceType.BEURER_BF710);
|
||||
}
|
||||
if (name.equals("openScale_MCU".toLowerCase(Locale.US))) {
|
||||
if (name.equals("openScale".toLowerCase(Locale.US))) {
|
||||
return new BluetoothCustomOpenScale(context);
|
||||
}
|
||||
if (name.equals("Mengii".toLowerCase(Locale.US))) {
|
||||
|
Reference in New Issue
Block a user