From 3a577b92928a0d2e644aa2c63ffeb9b2f3deaf91 Mon Sep 17 00:00:00 2001 From: OliE Date: Thu, 21 Feb 2019 18:52:44 +0100 Subject: [PATCH] Bluetooth state machine 2.0 (#404) simplified Bluetooth machine state --- .../bluetooth/BluetoothBeurerSanitas.java | 110 ++--- .../bluetooth/BluetoothCommunication.java | 375 ++++++++---------- .../bluetooth/BluetoothCustomOpenScale.java | 27 +- .../core/bluetooth/BluetoothDebug.java | 20 +- .../core/bluetooth/BluetoothDigooDGSO38H.java | 20 +- .../bluetooth/BluetoothExcelvanCF36xBLE.java | 18 +- .../core/bluetooth/BluetoothExingtechY1.java | 19 +- .../core/bluetooth/BluetoothHesley.java | 16 +- .../core/bluetooth/BluetoothIhealthHS3.java | 39 +- .../core/bluetooth/BluetoothInlife.java | 16 +- .../core/bluetooth/BluetoothMGB.java | 19 +- .../bluetooth/BluetoothMedisanaBS44x.java | 17 +- .../core/bluetooth/BluetoothMiScale.java | 93 ++--- .../core/bluetooth/BluetoothMiScale2.java | 88 ++-- .../core/bluetooth/BluetoothOneByone.java | 20 +- .../core/bluetooth/BluetoothQNScale.java | 32 +- .../core/bluetooth/BluetoothSenssun.java | 16 +- .../bluetooth/BluetoothTrisaBodyAnalyze.java | 44 +- .../bluetooth/BluetoothYunmaiSE_Mini.java | 19 +- .../health/openscale/gui/MainActivity.java | 26 +- .../gui/preferences/BluetoothPreferences.java | 5 +- .../gui/views/ChartMeasurementView.java | 7 +- 22 files changed, 354 insertions(+), 692 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 cf094fc5..00f73c1d 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 @@ -168,9 +168,8 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: // Setup notification setNotificationOn(CUSTOM_CHARACTERISTIC_WEIGHT); @@ -212,26 +211,10 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { if (currentRemoteUser != null) { Timber.d("Request saved measurements for %s", currentRemoteUser.name); sendCommand(CMD_GET_SAVED_MEASUREMENTS, encodeUserId(currentRemoteUser)); - - // Wait for all measurements to be received stopMachineState(); - } else { - nextMachineStateStep(); } break; case 6: - if (currentRemoteUser != null) { - Timber.d("Deleting saved measurements for %s", currentRemoteUser.name); - sendCommand(CMD_DELETE_SAVED_MEASUREMENTS, encodeUserId(currentRemoteUser)); - - // Return to the previous state until all users have been processed - repeatMachineStateSteps(2); - stopMachineState(); - } else { - nextMachineStateStep(); - } - break; - case 7: // Create a remote user for selected openScale user if needed currentRemoteUser = null; final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser(); @@ -244,14 +227,20 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { if (currentRemoteUser == null) { createRemoteUser(selectedUser); stopMachineState(); - } else { - nextMachineStateStep(); } break; - case 8: + case 7: sendCommand(CMD_USER_DETAILS, encodeUserId(currentRemoteUser)); stopMachineState(); break; + case 8: + if (!currentRemoteUser.isNew) { + sendCommand(CMD_DO_MEASUREMENT, encodeUserId(currentRemoteUser)); + stopMachineState(); + } else { + return false; + } + break; default: // Finish init if everything is done return false; @@ -260,40 +249,6 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { - case 0: - if (!currentRemoteUser.isNew) { - sendCommand(CMD_DO_MEASUREMENT, encodeUserId(currentRemoteUser)); - stopMachineState(); - } else { - nextMachineStateStep(); - } - break; - case 1: - setBtMachineState(BT_MACHINE_STATE.BT_CLEANUP_STATE); - break; - default: - return false; - - } - return true; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - switch (stateNr) { - case 0: - // Force disconnect - sendAlternativeStartCode(ID_START_NIBBLE_DISCONNECT, (byte) 0x02); - break; - default: - return false; - } - return true; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { byte[] data = value; @@ -303,7 +258,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { if (data[0] == getAlternativeStartByte(ID_START_NIBBLE_INIT)) { Timber.d("Got init ack from scale; scale is ready"); - resumeMachineState(true); + resumeMachineState(); return; } @@ -377,7 +332,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { } // All users received - resumeMachineState(true); + resumeMachineState(); } private void processMeasurementData(byte[] data, int offset, boolean firstPart) { @@ -401,11 +356,18 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { int current = data[3] & 0xFF; processMeasurementData(data, 4, current % 2 == 1); - if (current == count) { - // Resume but don't do next step until ACK has been sent - resumeMachineState(false); - } + sendAck(data); + + if (current == count) { + Timber.d("Deleting saved measurements for %s", currentRemoteUser.name); + sendCommand(CMD_DELETE_SAVED_MEASUREMENTS, encodeUserId(currentRemoteUser)); + + if (currentRemoteUser.remoteUserId != remoteUsers.get(remoteUsers.size() - 1).remoteUserId) { + jumpNextToStepNr(5); + resumeMachineState(); + } + } } private void processWeightMeasurement(byte[] data) { @@ -483,7 +445,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { Timber.d("Set scale unit to %s (%d)", user.getScaleUnit(), requestedUnit); sendCommand(CMD_SET_UNIT, requestedUnit); } else { - resumeMachineState(true); + resumeMachineState(); } break; @@ -491,7 +453,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { if (data[3] == 0) { Timber.d("Scale unit successfully set"); } - resumeMachineState(true); + resumeMachineState(); break; case CMD_USER_LIST: @@ -499,7 +461,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { int maxUserCount = data[5] & 0xFF; Timber.d("Have %d users (max is %d)", userCount, maxUserCount); if (userCount == 0) { - resumeMachineState(true); + resumeMachineState(); } // Otherwise wait for CMD_USER_INFO notifications break; @@ -508,8 +470,9 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { int measurementCount = data[3] & 0xFF; if (measurementCount == 0) { // Skip delete all measurements step (since there are no measurements to delete) - repeatMachineStateSteps(1); - resumeMachineState(true); + Timber.d("No saved measurements found for user " + currentRemoteUser.name); + jumpNextToStepNr(5); + resumeMachineState(); } // Otherwise wait for CMD_SAVED_MEASUREMENT notifications which will, // once all measurements have been received, resume the state machine. @@ -517,9 +480,9 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { case CMD_DELETE_SAVED_MEASUREMENTS: if (data[3] == 0) { - Timber.d("Saved measurements successfully deleted"); + Timber.d("Saved measurements successfully deleted for user " + currentRemoteUser.name); } - resumeMachineState(true); + resumeMachineState(); break; case CMD_USER_ADD: @@ -533,7 +496,10 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { Timber.d("Cannot create additional scale user (error 0x%02x)", data[3]); sendMessage(R.string.error_max_scale_users, 0); - setBtMachineState(BT_MACHINE_STATE.BT_CLEANUP_STATE); + // Force disconnect + Timber.d("Send disconnect command to scale"); + jumpNextToStepNr(8); + resumeMachineState(); break; case CMD_DO_MEASUREMENT: @@ -556,7 +522,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { Timber.d("Name: %s, Birthday: %d-%02d-%02d, Height: %d, Sex: %s, activity: %d", name, year, month, day, height, male ? "male" : "female", activity); } - resumeMachineState(true); + resumeMachineState(); break; default: @@ -596,7 +562,7 @@ public class BluetoothBeurerSanitas extends BluetoothCommunication { receivedMeasurement.setMuscle(muscle); receivedMeasurement.setBone(bone); - addScaleData(receivedMeasurement); + addScaleMeasurement(receivedMeasurement); } private void writeBytes(byte[] data) { diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCommunication.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCommunication.java index b952c115..9aa6e818 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCommunication.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCommunication.java @@ -38,40 +38,38 @@ import java.util.UUID; import androidx.core.content.ContextCompat; import io.reactivex.Observable; +import io.reactivex.Single; import io.reactivex.android.schedulers.AndroidSchedulers; import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.Disposable; import io.reactivex.exceptions.UndeliverableException; import io.reactivex.plugins.RxJavaPlugins; +import io.reactivex.schedulers.Schedulers; import io.reactivex.subjects.PublishSubject; import timber.log.Timber; import static android.content.Context.LOCATION_SERVICE; public abstract class BluetoothCommunication { - public enum BT_STATUS_CODE { - BT_RETRIEVE_SCALE_DATA, - BT_INIT_PROCESS, - BT_CONNECTION_RETRYING, - BT_CONNECTION_ESTABLISHED, - BT_CONNECTION_DISCONNECT, - BT_CONNECTION_LOST, - BT_NO_DEVICE_FOUND, - BT_UNEXPECTED_ERROR, - BT_SCALE_MESSAGE + public enum BT_STATUS { + RETRIEVE_SCALE_DATA, + INIT_PROCESS, + CONNECTION_RETRYING, + CONNECTION_ESTABLISHED, + CONNECTION_DISCONNECT, + CONNECTION_LOST, + NO_DEVICE_FOUND, + UNEXPECTED_ERROR, + SCALE_MESSAGE } - public enum BT_MACHINE_STATE { - BT_INIT_STATE, - BT_CMD_STATE, - BT_CLEANUP_STATE, - BT_STOPPED_STATE - } - - private final int BT_RETRY_TIMES_ON_ERROR = 3; + private int stepNr; + private boolean stopped; protected Context context; + private final int BT_RETRY_TIMES_ON_ERROR = 3; + private RxBleClient bleClient; private RxBleDevice bleDevice; private Observable connectionObservable; @@ -80,13 +78,6 @@ public abstract class BluetoothCommunication { private PublishSubject disconnectTriggerSubject = PublishSubject.create(); private Handler callbackBtHandler; - - private int cmdStepNr; - private int initStepNr; - private int cleanupStepNr; - private BT_MACHINE_STATE btMachineState; - private BT_MACHINE_STATE btStopppedMachineState; - private Handler disconnectHandler; public BluetoothCommunication(Context context) @@ -95,6 +86,8 @@ public abstract class BluetoothCommunication { this.bleClient = OpenScale.getInstance().getBleClient(); this.scanSubscription = null; this.disconnectHandler = new Handler(); + this.stepNr = 0; + this.stopped = false; RxJavaPlugins.setErrorHandler(e -> { if (e instanceof UndeliverableException && e.getCause() instanceof BleException) { @@ -126,7 +119,7 @@ public abstract class BluetoothCommunication { } /** - * Register a callback Bluetooth handler that notify any BT_STATUS_CODE changes for GUI/CORE. + * Register a callback Bluetooth handler that notify any BT_STATUS changes for GUI/CORE. * * @param cbBtHandler a handler that is registered */ @@ -137,10 +130,10 @@ public abstract class BluetoothCommunication { /** * Set for the openScale GUI/CORE the Bluetooth status code. * - * @param statusCode the status code that should be set + * @param status the status code that should be set */ - protected void setBtStatus(BT_STATUS_CODE statusCode) { - setBtStatus(statusCode, ""); + protected void setBluetoothStatus(BT_STATUS status) { + setBluetoothStatus(status, ""); } /** @@ -149,7 +142,7 @@ public abstract class BluetoothCommunication { * @param statusCode the status code that should be set * @param infoText the information text that is displayed to the status code. */ - protected void setBtStatus(BT_STATUS_CODE statusCode, String infoText) { + protected void setBluetoothStatus(BT_STATUS statusCode, String infoText) { if (callbackBtHandler != null) { callbackBtHandler.obtainMessage( statusCode.ordinal(), infoText).sendToTarget(); @@ -161,10 +154,10 @@ public abstract class BluetoothCommunication { * * @param scaleMeasurement the scale data that should be added to openScale */ - protected void addScaleData(ScaleMeasurement scaleMeasurement) { + protected void addScaleMeasurement(ScaleMeasurement scaleMeasurement) { if (callbackBtHandler != null) { callbackBtHandler.obtainMessage( - BT_STATUS_CODE.BT_RETRIEVE_SCALE_DATA.ordinal(), scaleMeasurement).sendToTarget(); + BT_STATUS.RETRIEVE_SCALE_DATA.ordinal(), scaleMeasurement).sendToTarget(); } } @@ -177,7 +170,7 @@ public abstract class BluetoothCommunication { protected void sendMessage(int msg, Object value) { if (callbackBtHandler != null) { callbackBtHandler.obtainMessage( - BT_STATUS_CODE.BT_SCALE_MESSAGE.ordinal(), msg, 0, value).sendToTarget(); + BT_STATUS.SCALE_MESSAGE.ordinal(), msg, 0, value).sendToTarget(); } } @@ -191,70 +184,10 @@ public abstract class BluetoothCommunication { /** * State machine for the initialization process of the Bluetooth device. * - * @param stateNr the current step number + * @param stepNr the current step number * @return false if no next step is available otherwise true */ - abstract protected boolean nextInitCmd(int stateNr); - - /** - * State machine for the normal/command process of the Bluetooth device. - * - * This state machine is automatically triggered if initialization process is finished. - * - * @param stateNr the current step number - * @return false if no next step is available otherwise true - */ - abstract protected boolean nextBluetoothCmd(int stateNr); - - /** - * Step the current machine state backwards. Needs to be called before a command. - * - * @param steps Number of steps to back the machine. - */ - protected void repeatMachineStateSteps(int steps) { - switch (btMachineState) { - case BT_INIT_STATE: - initStepNr = initStepNr - steps; - break; - case BT_CMD_STATE: - cmdStepNr = cmdStepNr - steps; - break; - case BT_CLEANUP_STATE: - cleanupStepNr = cleanupStepNr - steps; - break; - } - } - - /** - * Stopped the current machine state - */ - protected void stopMachineState() { - Timber.d("Machine state stopped"); - btStopppedMachineState = btMachineState; - btMachineState = BT_MACHINE_STATE.BT_STOPPED_STATE; - } - - /** - * Resumed the current machine state - */ - protected void resumeMachineState(boolean doNextStep) { - Timber.d("Machine state resumed"); - btMachineState = btStopppedMachineState; - - if (doNextStep) { - nextMachineStateStep(); - } - } - - /** - * State machine for the clean up process for the Bluetooth device. - * - * This state machine is *not* automatically triggered. You have to setBtMachineState(BT_MACHINE_STATE.BT_CLEANUP_STATE) to trigger this process if necessary. - * - * @param stateNr the current step number - * @return false if no next step is available otherwise true - */ - abstract protected boolean nextCleanUpCmd(int stateNr); + abstract protected boolean onNextStep(int stepNr); /** * Method is triggered if a Bluetooth data is read from a device. @@ -279,17 +212,20 @@ public abstract class BluetoothCommunication { */ protected void onBluetoothDiscovery(RxBleDeviceServices rxBleDeviceServices) { } - /** - * Set the Bluetooth machine state to a specific state. - * - * @note after setting a new state the next step is automatically triggered. - * - * @param btMachineState the machine state that should be set. - */ - protected void setBtMachineState(BT_MACHINE_STATE btMachineState) { - this.btMachineState = btMachineState; + protected synchronized void stopMachineState() { + Timber.d("Stop machine state"); + stopped = true; + } - nextMachineStateStep(); + protected synchronized void resumeMachineState() { + Timber.d("Resume machine state"); + stopped = false; + nextMachineStep(); + } + + protected synchronized void jumpNextToStepNr(int nr) { + Timber.d("Jump next to step nr " + nr); + stepNr = nr; } /** @@ -297,22 +233,25 @@ public abstract class BluetoothCommunication { * @param characteristic the Bluetooth UUID characteristic * @param bytes the bytes that should be write */ - protected void writeBytes(UUID characteristic, byte[] bytes) { - final Disposable disposable = connectionObservable + protected Observable writeBytes(UUID characteristic, byte[] bytes) { + Timber.d("Invoke write bytes [" + byteInHex(bytes) + "] on " + BluetoothGattUuid.prettyPrint(characteristic)); + Observable observable = connectionObservable .flatMapSingle(rxBleConnection -> rxBleConnection.writeCharacteristic(characteristic, bytes)) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) - .retry(BT_RETRY_TIMES_ON_ERROR) - .subscribe( + .retry(BT_RETRY_TIMES_ON_ERROR); + + compositeDisposable.add(observable.subscribe( value -> { Timber.d("Write characteristic %s: %s", BluetoothGattUuid.prettyPrint(characteristic), byteInHex(value)); - nextMachineStateStep(); }, throwable -> onError(throwable) - ); + ) + ); - compositeDisposable.add(disposable); + return observable; } /** @@ -321,20 +260,25 @@ public abstract class BluetoothCommunication { * @note onBluetoothRead() will be triggered if read command was successful. nextMachineStep() needs to manually called! *@param characteristic the Bluetooth UUID characteristic */ - protected void readBytes(UUID characteristic) { - final Disposable disposable = connectionObservable + protected Single readBytes(UUID characteristic) { + Timber.d("Invoke read bytes on " + BluetoothGattUuid.prettyPrint(characteristic)); + Single observable = connectionObservable .firstOrError() .flatMap(rxBleConnection -> rxBleConnection.readCharacteristic(characteristic)) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) - .retry(BT_RETRY_TIMES_ON_ERROR) - .subscribe(bytes -> { - Timber.d("Read characteristic %s", BluetoothGattUuid.prettyPrint(characteristic)); - onBluetoothRead(characteristic, bytes); - }, - throwable -> onError(throwable) - ); + .retry(BT_RETRY_TIMES_ON_ERROR); - compositeDisposable.add(disposable); + compositeDisposable.add(observable + .subscribe(bytes -> { + Timber.d("Read characteristic %s", BluetoothGattUuid.prettyPrint(characteristic)); + onBluetoothRead(characteristic, bytes); + }, + throwable -> onError(throwable) + ) + ); + + return observable; } /** @@ -342,29 +286,32 @@ public abstract class BluetoothCommunication { * * @param characteristic the Bluetooth UUID characteristic */ - protected void setIndicationOn(UUID characteristic) { - final Disposable disposable = connectionObservable + protected Observable setIndicationOn(UUID characteristic) { + Timber.d("Invoke set indication on " + BluetoothGattUuid.prettyPrint(characteristic)); + Observable observable = connectionObservable .flatMap(rxBleConnection -> rxBleConnection.setupIndication(characteristic)) .doOnNext(notificationObservable -> { Timber.d("Successful set indication on for %s", BluetoothGattUuid.prettyPrint(characteristic)); - nextMachineStateStep(); } ) .flatMap(indicationObservable -> indicationObservable) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) - .retry(BT_RETRY_TIMES_ON_ERROR) - .subscribe( - bytes -> { - onBluetoothNotify(characteristic, bytes); - Timber.d("onCharacteristicChanged %s: %s", - BluetoothGattUuid.prettyPrint(characteristic), - byteInHex(bytes)); - resetDisconnectTimer(); - }, - throwable -> onError(throwable) - ); + .retry(BT_RETRY_TIMES_ON_ERROR); - compositeDisposable.add(disposable); + compositeDisposable.add(observable.subscribe( + bytes -> { + Timber.d("onCharacteristicChanged %s: %s", + BluetoothGattUuid.prettyPrint(characteristic), + byteInHex(bytes)); + onBluetoothNotify(characteristic, bytes); + resetDisconnectTimer(); + }, + throwable -> onError(throwable) + ) + ); + + return observable; } /** @@ -372,46 +319,69 @@ public abstract class BluetoothCommunication { * * @param characteristic the Bluetooth UUID characteristic */ - protected void setNotificationOn(UUID characteristic) { - final Disposable disposable = connectionObservable + protected Observable setNotificationOn(UUID characteristic) { + Timber.d("Invoke set notification on " + BluetoothGattUuid.prettyPrint(characteristic)); + stopped = true; + Observable observable = connectionObservable .flatMap(rxBleConnection -> rxBleConnection.setupNotification(characteristic)) .doOnNext(notificationObservable -> { Timber.d("Successful set notification on for %s", BluetoothGattUuid.prettyPrint(characteristic)); - nextMachineStateStep(); + stopped = false; + nextMachineStep(); } ) .flatMap(notificationObservable -> notificationObservable) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) - .retry(BT_RETRY_TIMES_ON_ERROR) - .subscribe( - bytes -> { - onBluetoothNotify(characteristic, bytes); - Timber.d("onCharacteristicChanged %s: %s", - BluetoothGattUuid.prettyPrint(characteristic), - byteInHex(bytes)); - resetDisconnectTimer(); - }, - throwable -> onError(throwable) - ); + .retry(BT_RETRY_TIMES_ON_ERROR); - compositeDisposable.add(disposable); + compositeDisposable.add(observable.subscribe( + bytes -> { + Timber.d("onCharacteristicChanged %s: %s", + BluetoothGattUuid.prettyPrint(characteristic), + byteInHex(bytes)); + onBluetoothNotify(characteristic, bytes); + resetDisconnectTimer(); + }, + throwable -> onError(throwable) + )); + + return observable; } - public void doBluetoothDiscoverServices() { - final Disposable connectionDisposable = connectionObservable + protected Observable discoverBluetoothServices() { + Timber.d("Invoke discover Bluetooth services"); + final Observable observable = connectionObservable .flatMapSingle(RxBleConnection::discoverServices) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) - .retry(BT_RETRY_TIMES_ON_ERROR) - .subscribe( - deviceServices -> { - Timber.d("Successful Bluetooth services discovered"); - onBluetoothDiscovery(deviceServices); - nextMachineStateStep(); - }, - throwable -> onError(throwable) - ); + .retry(BT_RETRY_TIMES_ON_ERROR); - compositeDisposable.add(connectionDisposable); + compositeDisposable.add(observable.subscribe( + deviceServices -> { + Timber.d("Successful Bluetooth services discovered"); + onBluetoothDiscovery(deviceServices); + }, + throwable -> onError(throwable) + ) + ); + + return observable; + } + + /** + * Disconnect from a Bluetooth device + */ + public void disconnect() { + Timber.d("Bluetooth disconnect"); + setBluetoothStatus(BT_STATUS.CONNECTION_DISCONNECT); + if (scanSubscription != null) { + scanSubscription.dispose(); + } + callbackBtHandler = null; + disconnectHandler.removeCallbacksAndMessages(null); + disconnectTriggerSubject.onNext(true); + compositeDisposable.clear(); } /** @@ -496,11 +466,12 @@ public abstract class BluetoothCommunication { //.setCallbackType(ScanSettings.CALLBACK_TYPE_ALL_MATCHES) .build() ) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(bleScanResult -> { if (bleScanResult.getBleDevice().getMacAddress().equals(macAddress)) { connectToDevice(macAddress); - }}, throwable -> setBtStatus(BT_STATUS_CODE.BT_NO_DEVICE_FOUND)); + }}, throwable -> setBluetoothStatus(BT_STATUS.NO_DEVICE_FOUND)); } else { Timber.d("No coarse location permission, connecting without LE scan"); @@ -515,7 +486,6 @@ public abstract class BluetoothCommunication { Timber.d("Stop Le san"); scanSubscription.dispose(); scanSubscription = null; - } Handler handler = new Handler(); @@ -527,19 +497,18 @@ public abstract class BluetoothCommunication { connectionObservable = bleDevice .establishConnection(false) .takeUntil(disconnectTriggerSubject) - .doOnError(throwable -> setBtStatus(BT_STATUS_CODE.BT_CONNECTION_RETRYING)) + .doOnError(throwable -> setBluetoothStatus(BT_STATUS.CONNECTION_RETRYING)) + .subscribeOn(Schedulers.trampoline()) .observeOn(AndroidSchedulers.mainThread()) .compose(ReplayingShare.instance()); if (isConnected()) { disconnect(); } else { - initStepNr = -1; - cmdStepNr = -1; - cleanupStepNr = -1; + stepNr = 0; setBtMonitoringOn(); - setBtMachineState(BT_MACHINE_STATE.BT_INIT_STATE); + nextMachineStep(); resetDisconnectTimer(); } } @@ -552,7 +521,7 @@ public abstract class BluetoothCommunication { connectionState -> { switch (connectionState) { case CONNECTED: - setBtStatus(BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED); + setBluetoothStatus(BT_STATUS.CONNECTION_ESTABLISHED); break; case CONNECTING: // empty @@ -561,7 +530,7 @@ public abstract class BluetoothCommunication { // empty break; case DISCONNECTED: - // setBtStatus(BT_STATUS_CODE.BT_CONNECTION_LOST); + // setBluetoothStatus(BT_STATUS.CONNECTION_LOST); break; } }, @@ -571,20 +540,20 @@ public abstract class BluetoothCommunication { compositeDisposable.add(disposableConnectionState); } - private void onError(Throwable throwable) { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, throwable.getMessage()); + protected void onError(Throwable throwable) { + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, throwable.getMessage()); } private boolean isConnected() { return bleDevice.getConnectionState() == RxBleConnection.RxBleConnectionState.CONNECTED; } - public void resetDisconnectTimer() { + private void resetDisconnectTimer() { disconnectHandler.removeCallbacksAndMessages(null); disconnectWithDelay(); } - public void disconnectWithDelay() { + private void disconnectWithDelay() { disconnectHandler.postDelayed(new Runnable() { @Override public void run() { @@ -594,48 +563,16 @@ public abstract class BluetoothCommunication { }, 60000); // 60s timeout } - /** - * Disconnect from a Bluetooth device - */ - public void disconnect() { - Timber.d("Bluetooth disconnect"); - setBtStatus(BT_STATUS_CODE.BT_CONNECTION_DISCONNECT); - if (scanSubscription != null) { - scanSubscription.dispose(); - } - callbackBtHandler = null; - disconnectHandler.removeCallbacksAndMessages(null); - disconnectTriggerSubject.onNext(true); - compositeDisposable.clear(); - } - - /** - * Invoke next step for internal Bluetooth state machine. - */ - protected void nextMachineStateStep() { - switch (btMachineState) { - case BT_INIT_STATE: - initStepNr++; - Timber.d("INIT STATE: %d", initStepNr); - if (!nextInitCmd(initStepNr)) { - setBtMachineState(BT_MACHINE_STATE.BT_CMD_STATE); - } - break; - case BT_CMD_STATE: - cmdStepNr++; - Timber.d("CMD STATE: %d", cmdStepNr); - if (!nextBluetoothCmd(cmdStepNr)) { - disconnectWithDelay(); - } - break; - case BT_CLEANUP_STATE: - cleanupStepNr++; - Timber.d("CLEANUP STATE: %d", cleanupStepNr); - if (!nextCleanUpCmd(cleanupStepNr)) { - Timber.d("Cleanup Bluetooth disconnect"); - disconnect(); - } - break; + private synchronized void nextMachineStep() { + if (!stopped) { + Timber.d("Step Nr " + stepNr); + if (onNextStep(stepNr)) { + stepNr++; + nextMachineStep(); + } else { + Timber.d("Invoke delayed disconnect in 60s"); + disconnectWithDelay(); + } } } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCustomOpenScale.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCustomOpenScale.java index 26b7b6ec..1f1ff930 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCustomOpenScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothCustomOpenScale.java @@ -18,7 +18,6 @@ package com.health.openscale.core.bluetooth; import android.content.Context; import com.health.openscale.core.datatypes.ScaleMeasurement; -import com.polidea.rxandroidble2.RxBleClient; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -44,8 +43,8 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC ); @@ -70,16 +69,6 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - public void clearEEPROM() { byte[] cmd = {(byte)'9'}; @@ -106,7 +95,7 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication { 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: " + btString); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Parse error of bluetooth string. String has not a valid format: " + btString); } String btMsg = btString.substring(3, btString.length()); // message string @@ -156,18 +145,18 @@ public class BluetoothCustomOpenScale extends BluetoothCommunication { scaleBtData.setWater(Float.parseFloat(csvField[8])); scaleBtData.setMuscle(Float.parseFloat(csvField[9])); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } else { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error calculated checksum (" + checksum + ") and received checksum (" + btChecksum + ") is different"); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Error calculated checksum (" + checksum + ") and received checksum (" + btChecksum + ") is different"); } } catch (ParseException e) { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); } catch (NumberFormatException e) { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error while decoding a number of bluetooth string (" + e.getMessage() + ")"); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Error while decoding a number of bluetooth string (" + e.getMessage() + ")"); } break; default: - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error unknown MCU command : " + btString); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Error unknown MCU command : " + btString); } } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDebug.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDebug.java index 29fe81d5..0210f083 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDebug.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothDebug.java @@ -164,14 +164,14 @@ public class BluetoothDebug extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: - doBluetoothDiscoverServices(); + discoverBluetoothServices(); break; case 1: - int offset = stateNr; + int offset = stepNr; for (BluetoothGattService service : rxBleDeviceServices.getBluetoothGattServices()) { offset = readServiceCharacteristics(service, offset); @@ -181,7 +181,7 @@ public class BluetoothDebug extends BluetoothCommunication { logService(service, false); } - setBtStatus(BT_STATUS_CODE.BT_CONNECTION_LOST); + setBluetoothStatus(BT_STATUS.CONNECTION_LOST); break; case 2: disconnect(); @@ -192,14 +192,4 @@ public class BluetoothDebug extends BluetoothCommunication { return true; } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } } 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 fd706215..5e9c4e38 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 @@ -56,8 +56,8 @@ public class BluetoothDigooDGSO38H extends BluetoothCommunication { @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: //Tell device to send us weight measurements setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); @@ -65,19 +65,11 @@ public class BluetoothDigooDGSO38H extends BluetoothCommunication { case 1: sendMessage(R.string.info_step_on_scale, 0); break; + default: + return false; } - return false; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; + return true; } private void parseBytes(byte[] weightBytes) { @@ -135,7 +127,7 @@ public class BluetoothDigooDGSO38H extends BluetoothCommunication { scaleBtData.setVisceralFat(visceralFat); } scaleBtData.setWeight(weight); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } } } 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 a49029b0..f876ced9 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 @@ -44,13 +44,8 @@ public class BluetoothExcelvanCF36xBLE extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser(); @@ -103,12 +98,7 @@ public class BluetoothExcelvanCF36xBLE extends BluetoothCommunication { return false; } - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; + return true; } @Override @@ -150,6 +140,6 @@ public class BluetoothExcelvanCF36xBLE extends BluetoothCommunication { scaleBtData.setBone(bone); scaleBtData.setVisceralFat(visceralFat); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } } 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 de903537..d4fd8046 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 @@ -42,11 +42,10 @@ public class BluetoothExingtechY1 extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: - setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC - ); + setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); break; case 1: final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser(); @@ -71,16 +70,6 @@ public class BluetoothExingtechY1 extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -118,6 +107,6 @@ public class BluetoothExingtechY1 extends BluetoothCommunication { scaleBtData.setVisceralFat(visc_fat); scaleBtData.setDateTime(new Date()); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothHesley.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothHesley.java index 3c838790..0c910dbf 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothHesley.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothHesley.java @@ -39,8 +39,8 @@ public class BluetoothHesley extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); break; @@ -58,16 +58,6 @@ public class BluetoothHesley extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -101,6 +91,6 @@ public class BluetoothHesley extends BluetoothCommunication { scaleBtData.setBone(bone); scaleBtData.setDateTime(new Date()); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } } \ No newline at end of file diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothIhealthHS3.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothIhealthHS3.java index 4b742a95..90e16c77 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothIhealthHS3.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothIhealthHS3.java @@ -23,14 +23,13 @@ import android.bluetooth.BluetoothSocket; import android.content.Context; import com.health.openscale.core.datatypes.ScaleMeasurement; -import com.polidea.rxandroidble2.RxBleClient; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.UUID; -import java.util.Date; import java.util.Arrays; +import java.util.Date; +import java.util.UUID; import timber.log.Timber; @@ -57,20 +56,8 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - Timber.w("ihealthHS3 - nextInitCmd - returning false"); - return false; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - Timber.w("ihealthHS3 - nextBluetoothCmd - returning false"); - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - Timber.w("ihealthHS3 - nextCleanUpCmd - returning false"); + protected boolean onNextStep(int stepNr) { + Timber.w("ihealthHS3 - onNextStep - returning false"); return false; } @@ -79,7 +66,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter(); if (btAdapter == null) { - setBtStatus(BT_STATUS_CODE.BT_NO_DEVICE_FOUND); + setBluetoothStatus(BT_STATUS.NO_DEVICE_FOUND); return; } @@ -88,7 +75,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { // 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"); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Can't get a bluetooth socket"); btDevice = null; return; } @@ -103,7 +90,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { btSocket.connect(); // Bluetooth connection was successful - setBtStatus(BT_STATUS_CODE.BT_CONNECTION_ESTABLISHED); + setBluetoothStatus(BT_STATUS.CONNECTION_ESTABLISHED); btConnectThread = new BluetoothConnectedThread(); btConnectThread.start(); @@ -111,7 +98,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { } catch (IOException connectException) { // Unable to connect; close the socket and get out disconnect(); - setBtStatus(BT_STATUS_CODE.BT_NO_DEVICE_FOUND); + setBluetoothStatus(BT_STATUS.NO_DEVICE_FOUND); } } }; @@ -129,7 +116,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { btSocket.close(); btSocket = null; } catch (IOException closeException) { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Can't close bluetooth socket"); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Can't close bluetooth socket"); } } } @@ -171,7 +158,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { 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()); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Can't get bluetooth input or output stream " + e.getMessage()); } } @@ -209,7 +196,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { ScaleMeasurement scaleMeasurement = parseWeightArray(weightBytes); if (scaleMeasurement != null) { - addScaleData(scaleMeasurement); + addScaleMeasurement(scaleMeasurement); } } @@ -227,7 +214,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { } catch (IOException e) { cancel(); - setBtStatus(BT_STATUS_CODE.BT_CONNECTION_LOST); + setBluetoothStatus(BT_STATUS.CONNECTION_LOST); } } } @@ -266,7 +253,7 @@ public class BluetoothIhealthHS3 extends BluetoothCommunication { try { btOutStream.write(bytes); } catch (IOException e) { - setBtStatus(BT_STATUS_CODE.BT_UNEXPECTED_ERROR, "Error while writing to bluetooth socket " + e.getMessage()); + setBluetoothStatus(BT_STATUS.UNEXPECTED_ERROR, "Error while writing to bluetooth socket " + e.getMessage()); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothInlife.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothInlife.java index 82afe233..d705f4f8 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothInlife.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothInlife.java @@ -73,8 +73,8 @@ public class BluetoothInlife extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); break; @@ -98,16 +98,6 @@ public class BluetoothInlife extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -229,7 +219,7 @@ public class BluetoothInlife extends BluetoothCommunication { measurement.setLbm(lbm); measurement.setVisceralFat(clamp(visceral, 1, 50)); - addScaleData(measurement); + addScaleMeasurement(measurement); sendCommand(0xd4); } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMGB.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMGB.java index a615958a..8052a4b5 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMGB.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMGB.java @@ -82,8 +82,8 @@ public class BluetoothMGB extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: setNotificationOn(uuid_char_ctrl ); @@ -126,19 +126,6 @@ public class BluetoothMGB extends BluetoothCommunication { return true; } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { packet_buf = value; @@ -202,7 +189,7 @@ public class BluetoothMGB extends BluetoothCommunication { popInt(); // unknown =02 popInt(); // unknown =47;48;4e;4b;42 - addScaleData(measurement); + addScaleMeasurement(measurement); // Visceral fat? // Standard weight? 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 67734990..79675e57 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 @@ -51,13 +51,8 @@ public class BluetoothMedisanaBS44x extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: // set indication on for feature characteristic setIndicationOn(FEATURE_MEASUREMENT_CHARACTERISTIC); @@ -92,12 +87,6 @@ public class BluetoothMedisanaBS44x extends BluetoothCommunication { return true; } - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -109,7 +98,7 @@ public class BluetoothMedisanaBS44x extends BluetoothCommunication { if (characteristic.equals(FEATURE_MEASUREMENT_CHARACTERISTIC)) { parseFeatureData(data); - addScaleData(btScaleMeasurement); + addScaleMeasurement(btScaleMeasurement); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale.java index 91f67ece..de5ee229 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale.java @@ -35,7 +35,7 @@ import java.util.UUID; import timber.log.Timber; -import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_UNEXPECTED_ERROR; +import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS.UNEXPECTED_ERROR; public class BluetoothMiScale extends BluetoothCommunication { private final UUID WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC = UUID.fromString("00002a2f-0000-3512-2118-0009af100700"); @@ -60,11 +60,21 @@ public class BluetoothMiScale extends BluetoothCommunication { int scaleMonth = (int) data[2]; int scaleDay = (int) data[3]; - if (currentYear == scaleYear && currentMonth == scaleMonth && currentDay == scaleDay) { - setBtMachineState(BT_MACHINE_STATE.BT_CMD_STATE); - } else { + if (!(currentYear == scaleYear && currentMonth == scaleMonth && currentDay == scaleDay)) { Timber.d("Current year and scale year is different"); - nextMachineStateStep(); + + // set current time + Calendar currentDateTime = Calendar.getInstance(); + int year = currentDateTime.get(Calendar.YEAR); + byte month = (byte)(currentDateTime.get(Calendar.MONTH)+1); + byte day = (byte)currentDateTime.get(Calendar.DAY_OF_MONTH); + byte hour = (byte)currentDateTime.get(Calendar.HOUR_OF_DAY); + byte min = (byte)currentDateTime.get(Calendar.MINUTE); + byte sec = (byte)currentDateTime.get(Calendar.SECOND); + + byte[] dateTimeByte = {(byte)(year), (byte)(year >> 8), month, day, hour, min, sec, 0x03, 0x00, 0x00}; + + writeBytes(BluetoothGattUuid.CHARACTERISTIC_CURRENT_TIME, dateTimeByte); } } @@ -76,7 +86,15 @@ public class BluetoothMiScale extends BluetoothCommunication { // Stop command from mi scale received if (data[0] == 0x03) { - setBtMachineState(BT_MACHINE_STATE.BT_CLEANUP_STATE); + // send stop command to mi scale + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x03}); + // acknowledge that you received the last history data + int uniqueNumber = getUniqueNumber(); + + byte[] userIdentifier = new byte[]{(byte)0x04, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); + + resumeMachineState(); } if (data.length == 20) { @@ -95,82 +113,37 @@ public class BluetoothMiScale extends BluetoothCommunication { @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: // read device time readBytes(BluetoothGattUuid.CHARACTERISTIC_CURRENT_TIME); break; case 1: - // set current time - Calendar currentDateTime = Calendar.getInstance(); - int year = currentDateTime.get(Calendar.YEAR); - byte month = (byte)(currentDateTime.get(Calendar.MONTH)+1); - byte day = (byte)currentDateTime.get(Calendar.DAY_OF_MONTH); - byte hour = (byte)currentDateTime.get(Calendar.HOUR_OF_DAY); - byte min = (byte)currentDateTime.get(Calendar.MINUTE); - byte sec = (byte)currentDateTime.get(Calendar.SECOND); - - byte[] dateTimeByte = {(byte)(year), (byte)(year >> 8), month, day, hour, min, sec, 0x03, 0x00, 0x00}; - - writeBytes(BluetoothGattUuid.CHARACTERISTIC_CURRENT_TIME, dateTimeByte); - break; - case 2: // Set on history weight measurement byte[] magicBytes = new byte[]{(byte)0x01, (byte)0x96, (byte)0x8a, (byte)0xbd, (byte)0x62}; writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, magicBytes); break; - default: - return false; - } - - return true; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { - case 0: + case 2: // set notification on for weight measurement history setNotificationOn(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC); break; - case 1: + case 3: // set notification on for weight measurement setNotificationOn(BluetoothGattUuid.CHARACTERISTIC_WEIGHT_MEASUREMENT); break; - case 2: + case 4: // configure scale to get only last measurements int uniqueNumber = getUniqueNumber(); byte[] userIdentifier = new byte[]{(byte)0x01, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); break; - case 3: + case 5: // invoke receiving history data writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x02}); - break; - default: - return false; - } - - return true; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - - switch (stateNr) { - case 0: - // send stop command to mi scale - writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x03}); - break; - case 1: - // acknowledge that you received the last history data - int uniqueNumber = getUniqueNumber(); - - byte[] userIdentifier = new byte[]{(byte)0x04, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; - writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); + stopMachineState(); break; default: return false; @@ -225,13 +198,13 @@ public class BluetoothMiScale extends BluetoothCommunication { scaleBtData.setWeight(Converters.toKilogram(weight, selectedUser.getScaleUnit())); scaleBtData.setDateTime(date_time); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } else { Timber.e("Invalid Mi scale weight year %d", year); } } } catch (ParseException e) { - setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); + setBluetoothStatus(UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale2.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale2.java index 3006cd50..d962420d 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale2.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothMiScale2.java @@ -31,7 +31,6 @@ import com.health.openscale.gui.views.FatMeasurementView; import com.health.openscale.gui.views.LBMMeasurementView; import com.health.openscale.gui.views.MeasurementViewSettings; import com.health.openscale.gui.views.WaterMeasurementView; -import com.polidea.rxandroidble2.RxBleClient; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -43,7 +42,7 @@ import java.util.UUID; import timber.log.Timber; -import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS_CODE.BT_UNEXPECTED_ERROR; +import static com.health.openscale.core.bluetooth.BluetoothCommunication.BT_STATUS.UNEXPECTED_ERROR; public class BluetoothMiScale2 extends BluetoothCommunication { private final UUID WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC = UUID.fromString("00002a2f-0000-3512-2118-0009af100700"); @@ -69,7 +68,18 @@ public class BluetoothMiScale2 extends BluetoothCommunication { // Stop command from mi scale received if (data[0] == 0x03) { - setBtMachineState(BT_MACHINE_STATE.BT_CLEANUP_STATE); + Timber.d("Scale stop byte received"); + // send stop command to mi scale + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x03}); + // acknowledge that you received the last history data + int uniqueNumber = getUniqueNumber(); + + byte[] userIdentifier = new byte[]{(byte)0x04, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); + + disconnect(); + + resumeMachineState(); } if (data.length == 26) { @@ -88,8 +98,8 @@ public class BluetoothMiScale2 extends BluetoothCommunication { @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: // set scale units final ScaleUser selectedUser = OpenScale.getInstance().getSelectedScaleUser(); @@ -108,73 +118,23 @@ public class BluetoothMiScale2 extends BluetoothCommunication { byte[] dateTimeByte = {(byte)(year), (byte)(year >> 8), month, day, hour, min, sec, 0x03, 0x00, 0x00}; - writeBytes( - BluetoothGattUuid.CHARACTERISTIC_CURRENT_TIME, dateTimeByte); + writeBytes(BluetoothGattUuid.CHARACTERISTIC_CURRENT_TIME, dateTimeByte); break; case 2: // set notification on for weight measurement history - setNotificationOn( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC - ); + setNotificationOn(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC); break; - default: - return false; - } - - return true; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { - case 0: + case 3: // configure scale to get only last measurements int uniqueNumber = getUniqueNumber(); byte[] userIdentifier = new byte[]{(byte)0x01, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; - writeBytes( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); break; - case 1: - // set notification on for weight measurement history - setNotificationOn( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC - ); - break; - case 2: + case 4: // invoke receiving history data - writeBytes( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x02}); - break; - default: - return false; - } - - return true; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - - switch (stateNr) { - case 0: - // send stop command to mi scale - writeBytes( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x03}); - break; - case 1: - // acknowledge that you received the last history data - int uniqueNumber = getUniqueNumber(); - - byte[] userIdentifier = new byte[]{(byte)0x04, (byte)0xFF, (byte)0xFF, (byte) ((uniqueNumber & 0xFF00) >> 8), (byte) ((uniqueNumber & 0xFF) >> 0)}; - writeBytes( - WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, userIdentifier); - break; - case 2: - // set notification on for body composition measurement - setNotificationOn( - BluetoothGattUuid.CHARACTERISTIC_BODY_COMPOSITION_MEASUREMENT - ); + writeBytes(WEIGHT_MEASUREMENT_HISTORY_CHARACTERISTIC, new byte[]{0x02}); + stopMachineState(); break; default: return false; @@ -239,13 +199,13 @@ public class BluetoothMiScale2 extends BluetoothCommunication { EstimatedLBMMetric.FORMULA.valueOf(settings.getEstimationFormula())); scaleBtData.setLbm(lbmMetric.getLBM(selectedUser, scaleBtData)); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } else { Timber.e("Invalid Mi scale weight year %d", year); } } } catch (ParseException e) { - setBtStatus(BT_UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); + setBluetoothStatus(UNEXPECTED_ERROR, "Error while decoding bluetooth date string (" + e.getMessage() + ")"); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothOneByone.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothOneByone.java index afadc79f..c01d75ba 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothOneByone.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothOneByone.java @@ -47,12 +47,10 @@ public class BluetoothOneByone extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: - setNotificationOn( - WEIGHT_MEASUREMENT_CHARACTERISTIC_BODY_COMPOSITION - ); + setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC_BODY_COMPOSITION); break; case 1: ScaleUser currentUser = OpenScale.getInstance().getSelectedScaleUser(); @@ -83,16 +81,6 @@ public class BluetoothOneByone extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -155,6 +143,6 @@ public class BluetoothOneByone extends BluetoothCommunication { Timber.d("scale measurement [%s]", scaleBtData); - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothQNScale.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothQNScale.java index d2897b1a..1db66cf2 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothQNScale.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothQNScale.java @@ -84,13 +84,8 @@ public class BluetoothQNScale extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: // set notification on for custom characteristic 1 (weight, time, and others) setNotificationOn(CUSTOM1_MEASUREMENT_CHARACTERISTIC); @@ -101,7 +96,7 @@ public class BluetoothQNScale extends BluetoothCommunication { break; case 2: // write magicnumber 0x130915011000000042 to 0xffe3 - byte[] ffe3magicBytes = new byte[] {(byte)0x13, (byte)0x09, (byte)0x15, (byte)0x01, (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x42}; + byte[] ffe3magicBytes = new byte[]{(byte) 0x13, (byte) 0x09, (byte) 0x15, (byte) 0x01, (byte) 0x10, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x42}; writeBytes(CUSTOM3_MEASUREMENT_CHARACTERISTIC, ffe3magicBytes); break; case 3: @@ -110,34 +105,23 @@ public class BluetoothQNScale extends BluetoothCommunication { timestamp -= SCALE_UNIX_TIMESTAMP_OFFSET; byte[] date = new byte[4]; Converters.toInt32Le(date, 0, timestamp); - byte[] timeMagicBytes = new byte[] {(byte)0x02, date[0], date[1], date[2], date[3]}; + byte[] timeMagicBytes = new byte[]{(byte) 0x02, date[0], date[1], date[2], date[3]}; writeBytes(CUSTOM4_MEASUREMENT_CHARACTERISTIC, timeMagicBytes); break; case 4: sendMessage(R.string.info_step_on_scale, 0); break; - default: - return false; - } - - return true; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - - switch (stateNr) { - case 0: + /*case 5: // send stop command to scale (0x1f05151049) writeBytes(CUSTOM3_MEASUREMENT_CHARACTERISTIC, new byte[]{(byte)0x1f, (byte)0x05, (byte)0x15, (byte)0x10, (byte)0x49}); - break; + break;*/ default: return false; } + return true; } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -198,7 +182,7 @@ public class BluetoothQNScale extends BluetoothCommunication { btScaleMeasurement.setMuscle(qnscalelib.getMuscle(weightKg, impedance)); btScaleMeasurement.setBone(qnscalelib.getBone(weightKg, impedance)); btScaleMeasurement.setWeight(weightKg); - addScaleData(btScaleMeasurement); + addScaleMeasurement(btScaleMeasurement); } } } diff --git a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothSenssun.java b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothSenssun.java index b616c4d1..6cb83be0 100644 --- a/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothSenssun.java +++ b/android_app/app/src/main/java/com/health/openscale/core/bluetooth/BluetoothSenssun.java @@ -68,8 +68,8 @@ public class BluetoothSenssun extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); break; @@ -85,16 +85,6 @@ public class BluetoothSenssun extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -107,7 +97,7 @@ public class BluetoothSenssun extends BluetoothCommunication { } if (isBitSet(WeightFatMus,2) ) { - addScaleData(measurement); + addScaleMeasurement(measurement); } } 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 dc2b7ed4..b94a369a 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 @@ -92,7 +92,7 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication { * set-broadcast-id command, and should disconnect after the write succeeds. * * @see #onPasswordReceived - * @see #nextBluetoothCmd + * @see #onNextStep */ private boolean pairing = false; @@ -119,13 +119,13 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - Timber.i("nextInitCmd(%d)", stateNr); - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + Timber.i("onNextStep(%d)", stepNr); + switch (stepNr) { case 0: // Register for notifications of the measurement characteristic. setIndicationOn(MEASUREMENT_CHARACTERISTIC_UUID); - return true; // more commands follow + break; // more commands follow case 1: // Register for notifications of the command upload characteristic. // @@ -133,40 +133,22 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication { // immediately after. This is important because we should be in the main state // to handle pairing correctly. setIndicationOn(UPLOAD_COMMAND_CHARACTERISTIC_UUID); - // falls through - default: - return false; // no more commands - } - } - - @Override - protected boolean nextBluetoothCmd(int stateNr) { - Timber.i("nextBluetoothCmd(%d)", stateNr); - switch (stateNr) { - case 0: - default: - return false; // no more commands - - case 1: + break; + case 2: // This state is triggered by the write in onPasswordReceived() if (pairing) { pairing = false; disconnect(); } - return false; // no more commands; - } - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - Timber.i("nextCleanUpCmd(%d)", stateNr); - switch (stateNr) { - case 0: + break; + case 3: writeCommand(DOWNLOAD_INFORMATION_ENABLE_DISCONNECT_COMMAND); - // falls through + break; default: return false; // no more commands } + + return true; } @Override @@ -247,7 +229,7 @@ public class BluetoothTrisaBodyAnalyze extends BluetoothCommunication { return; } - addScaleData(measurement); + addScaleMeasurement(measurement); } public ScaleMeasurement parseScaleMeasurementData(byte[] data, ScaleUser user) { 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 1ac32019..83fc83e6 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 @@ -52,8 +52,8 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication { } @Override - protected boolean nextInitCmd(int stateNr) { - switch (stateNr) { + protected boolean onNextStep(int stepNr) { + switch (stepNr) { case 0: byte[] userId = Converters.toInt16Be(getUniqueNumber()); @@ -82,8 +82,7 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication { writeBytes(WEIGHT_CMD_CHARACTERISTIC, set_time); break; case 2: - setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC - ); + setNotificationOn(WEIGHT_MEASUREMENT_CHARACTERISTIC); break; case 3: byte[] magic_bytes = new byte[]{(byte)0x0d, (byte)0x05, (byte)0x13, (byte)0x00, (byte)0x16}; @@ -97,16 +96,6 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication { return true; } - @Override - protected boolean nextBluetoothCmd(int stateNr) { - return false; - } - - @Override - protected boolean nextCleanUpCmd(int stateNr) { - return false; - } - @Override public void onBluetoothNotify(UUID characteristic, byte[] value) { final byte[] data = value; @@ -154,7 +143,7 @@ public class BluetoothYunmaiSE_Mini extends BluetoothCommunication { Timber.d("scale measurement [%s]", scaleBtData); } - addScaleData(scaleBtData); + addScaleMeasurement(scaleBtData); } private int getUniqueNumber() { 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 c0b305dd..ce93a572 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 @@ -154,8 +154,8 @@ public class MainActivity extends BaseAppCompatActivity if(prefs.edit().putInt("launchCount", ++launchCount).commit()){ valueOfCountModified = true; - // ask the user once for feedback on the 30th app launch - if(launchCount == 30){ + // ask the user once for feedback on the 15th app launch + if(launchCount == 15){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage(R.string.label_feedback_message_enjoying) @@ -476,10 +476,10 @@ public class MainActivity extends BaseAppCompatActivity @Override public void handleMessage(Message msg) { - BluetoothCommunication.BT_STATUS_CODE btStatusCode = BluetoothCommunication.BT_STATUS_CODE.values()[msg.what]; + BluetoothCommunication.BT_STATUS btStatus = BluetoothCommunication.BT_STATUS.values()[msg.what]; - switch (btStatusCode) { - case BT_RETRIEVE_SCALE_DATA: + switch (btStatus) { + case RETRIEVE_SCALE_DATA: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_success); ScaleMeasurement scaleBtData = (ScaleMeasurement) msg.obj; @@ -496,42 +496,42 @@ public class MainActivity extends BaseAppCompatActivity openScale.addScaleData(scaleBtData, true); break; - case BT_INIT_PROCESS: + case INIT_PROCESS: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_success); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_init), Toast.LENGTH_SHORT).show(); Timber.d("Bluetooth initializing"); break; - case BT_CONNECTION_LOST: + case CONNECTION_LOST: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_lost); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_lost), Toast.LENGTH_SHORT).show(); Timber.d("Bluetooth connection lost"); break; - case BT_NO_DEVICE_FOUND: + case NO_DEVICE_FOUND: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_lost); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_no_device), Toast.LENGTH_SHORT).show(); Timber.e("No Bluetooth device found"); break; - case BT_CONNECTION_RETRYING: + case CONNECTION_RETRYING: setBluetoothStatusIcon(R.drawable.ic_bluetooth_searching); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_no_device_retrying), Toast.LENGTH_SHORT).show(); Timber.e("No Bluetooth device found retrying"); break; - case BT_CONNECTION_ESTABLISHED: + case CONNECTION_ESTABLISHED: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_success); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_successful), Toast.LENGTH_SHORT).show(); Timber.d("Bluetooth connection successful established"); break; - case BT_CONNECTION_DISCONNECT: + case CONNECTION_DISCONNECT: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_lost); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_disconnected), Toast.LENGTH_SHORT).show(); Timber.d("Bluetooth connection successful disconnected"); break; - case BT_UNEXPECTED_ERROR: + case UNEXPECTED_ERROR: setBluetoothStatusIcon(R.drawable.ic_bluetooth_connection_lost); Toast.makeText(getApplicationContext(), getResources().getString(R.string.info_bluetooth_connection_error) + ": " + msg.obj, Toast.LENGTH_SHORT).show(); Timber.e("Bluetooth unexpected error: %s", msg.obj); break; - case BT_SCALE_MESSAGE: + case SCALE_MESSAGE: String toastMessage = String.format(getResources().getString(msg.arg1), msg.obj); Toast.makeText(getApplicationContext(), toastMessage, Toast.LENGTH_LONG).show(); break; diff --git a/android_app/app/src/main/java/com/health/openscale/gui/preferences/BluetoothPreferences.java b/android_app/app/src/main/java/com/health/openscale/gui/preferences/BluetoothPreferences.java index fb100fcb..be491e64 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/preferences/BluetoothPreferences.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/preferences/BluetoothPreferences.java @@ -31,7 +31,6 @@ import android.preference.Preference; import android.preference.PreferenceFragment; import android.preference.PreferenceScreen; import android.widget.BaseAdapter; -import android.widget.EditText; import android.widget.Toast; import com.health.openscale.R; @@ -289,8 +288,8 @@ public class BluetoothPreferences extends PreferenceFragment { Handler btHandler = new Handler() { @Override public void handleMessage(Message msg) { - switch (BluetoothCommunication.BT_STATUS_CODE.values()[msg.what]) { - case BT_CONNECTION_LOST: + switch (BluetoothCommunication.BT_STATUS.values()[msg.what]) { + case CONNECTION_LOST: OpenScale.getInstance().disconnectFromBluetoothDevice(); dialog.dismiss(); break; diff --git a/android_app/app/src/main/java/com/health/openscale/gui/views/ChartMeasurementView.java b/android_app/app/src/main/java/com/health/openscale/gui/views/ChartMeasurementView.java index b1c5a308..d13a642c 100644 --- a/android_app/app/src/main/java/com/health/openscale/gui/views/ChartMeasurementView.java +++ b/android_app/app/src/main/java/com/health/openscale/gui/views/ChartMeasurementView.java @@ -230,8 +230,9 @@ public class ChartMeasurementView extends LineChart { } private void setMeasurementList(List measurementList) { + scaleMeasurementList = measurementList; + if (!measurementList.isEmpty()) { - scaleMeasurementList = measurementList; lastMeasurement = measurementList.get(0); Collections.reverse(measurementList); firstMeasurement = measurementList.get(0); @@ -409,12 +410,12 @@ public class ChartMeasurementView extends LineChart { } private void refresh() { + clear(); + if (scaleMeasurementList.isEmpty()) { return; } - clear(); - List lineDataSets = new ArrayList<>(); ScaleMeasurement[] avgMeasurementList = averageScaleMeasurementList(scaleMeasurementList);