Search in sources :

Example 1 with RxBleConnection

use of com.polidea.rxandroidble2.RxBleConnection in project xDrip by NightscoutFoundation.

the class MiBandService method ProcessAuthCommands.

@SuppressLint("CheckResult")
private void ProcessAuthCommands(RxBleConnection connection, byte[] value) {
    if (value[0] == AUTH_RESPONSE && value[1] == AUTH_SEND_KEY && (value[2] & 0x0f) == AUTH_SUCCESS) {
        // get random key from band
        connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()).subscribe(val -> {
            if (d)
                UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ1: " + JoH.bytesToHex(val));
        }, throwable -> {
            UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ1: " + throwable);
        });
    } else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_REQUEST_RANDOM_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
        byte[] tmpValue = Arrays.copyOfRange(value, 3, 19);
        try {
            byte[] authReply = authorisation.calculateAuthReply(tmpValue);
            // get random key from band
            connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authReply).subscribe(val -> {
                if (d)
                    UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ2: " + JoH.bytesToHex(val));
            }, throwable -> {
                UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ2: " + throwable);
            });
        } catch (Exception e) {
            JoH.static_toast_long(e.getMessage());
            UserError.Log.e(TAG, (e.getMessage()));
            changeState(AUTHORIZE_FAILED);
        }
    } else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_SEND_ENCRYPTED_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
        isNeedToAuthenticate = false;
        if (MiBand.getPersistentAuthMac().isEmpty()) {
            MiBand.setPersistentAuthMac(MiBand.getMac());
            MiBand.setPersistentAuthKey(JoH.bytesToHex(authorisation.getLocalKey()), MiBand.getPersistentAuthMac());
            String msg = "MiBand was successfully authenticated";
            JoH.static_toast_long(msg);
            UserError.Log.e(TAG, msg);
        }
        if (authSubscription != null) {
            authSubscription.unsubscribe();
        }
        changeNextState();
    } else if (value[0] == AUTH_RESPONSE && (((value[2] & 0x0f) == AUTH_FAIL) || (value[2] == AUTH_MIBAND4_FAIL) || (value[2] == AUTH_MIBAND4_CODE_FAIL))) {
        MiBand.setPersistentAuthKey("", MiBand.getPersistentAuthMac());
        if (authSubscription != null) {
            authSubscription.unsubscribe();
        }
        String msg = "Cannot authorize miband, please recheck Auth code";
        JoH.static_toast_long(msg);
        UserError.Log.e(TAG, msg);
        changeState(AUTHORIZE_FAILED);
    }
}
Also used : AUTHORIZE_FAILED(com.eveningoutpost.dexdrip.watch.miband.MiBandService.MiBandState.AUTHORIZE_FAILED) AUTH_REQUEST_RANDOM_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_REQUEST_RANDOM_AUTH_NUMBER) AuthMessages(com.eveningoutpost.dexdrip.watch.miband.message.AuthMessages) Arrays(java.util.Arrays) com.eveningoutpost.dexdrip.xdrip(com.eveningoutpost.dexdrip.xdrip) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) PendingIntent(android.app.PendingIntent) CLOSED(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSED) INIT(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.INIT) Inevitable(com.eveningoutpost.dexdrip.UtilityModels.Inevitable) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) PowerManager(android.os.PowerManager) HeartRate(com.eveningoutpost.dexdrip.Models.HeartRate) StatusItem(com.eveningoutpost.dexdrip.UtilityModels.StatusItem) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) COMMAND_ACK_FIND_PHONE_IN_PROGRESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_ACK_FIND_PHONE_IN_PROGRESS) AUTH_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_FAIL) Schedulers(io.reactivex.schedulers.Schedulers) AUTH_MIBAND4_CODE_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_CODE_FAIL) AUTH_RESPONSE(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_RESPONSE) AUTH_SEND_KEY(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_KEY) ActiveBgAlert(com.eveningoutpost.dexdrip.Models.ActiveBgAlert) FeaturesControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.FeaturesControllMessage) MIBAND_NOTIFY_TYPE_ALARM(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_ALARM) CLOSE(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSE) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) PrefBindingFactory(com.eveningoutpost.dexdrip.watch.PrefBindingFactory) UUID(java.util.UUID) JoH.getResourceURI(com.eveningoutpost.dexdrip.Models.JoH.getResourceURI) UNKNOWN(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.UNKNOWN) JoH(com.eveningoutpost.dexdrip.Models.JoH) List(java.util.List) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) JoH.bytesToHex(com.eveningoutpost.dexdrip.Models.JoH.bytesToHex) MIBAND_NOTIFY_TYPE_CANCEL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CANCEL) R(com.eveningoutpost.dexdrip.R) Subscription(com.eveningoutpost.dexdrip.utils.bt.Subscription) PREFERRED_MTU_SIZE(com.eveningoutpost.dexdrip.watch.miband.Const.PREFERRED_MTU_SIZE) AlertLevelMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertLevelMessage) JoH.msTill(com.eveningoutpost.dexdrip.Models.JoH.msTill) AUTH_SUCCESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SUCCESS) Getter(lombok.Getter) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic) WakeLockTrampoline(com.eveningoutpost.dexdrip.utils.framework.WakeLockTrampoline) Constants(com.eveningoutpost.dexdrip.UtilityModels.Constants) AUTH_SEND_ENCRYPTED_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_ENCRYPTED_AUTH_NUMBER) Pair(android.util.Pair) FirmwareOperations(com.eveningoutpost.dexdrip.watch.miband.Firmware.FirmwareOperations) DisplayControllMessageMiband3_4(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) Intent(android.content.Intent) MediaPlayer(android.media.MediaPlayer) ArrayList(java.util.ArrayList) JoH.niceTimeScalar(com.eveningoutpost.dexdrip.Models.JoH.niceTimeScalar) SuppressLint(android.annotation.SuppressLint) Calendar(java.util.Calendar) DeviceEvent(com.eveningoutpost.dexdrip.watch.miband.message.DeviceEvent) DisplayControllMessageMiBand2(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiBand2) DisplayControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessage) COMMAND_DISABLE_CALL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_DISABLE_CALL) JamBaseBluetoothSequencer(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer) AlertMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertMessage) MI_BAND4(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND4) Sheduled(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4.NightMode.Sheduled) RxBleDeviceServices(com.polidea.rxandroidble2.RxBleDeviceServices) MI_BAND2(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND2) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) SLEEP(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.SLEEP) BluetoothGattService(android.bluetooth.BluetoothGattService) com.eveningoutpost.dexdrip.xdrip.gs(com.eveningoutpost.dexdrip.xdrip.gs) AUTH_MIBAND4_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_FAIL) WatchFaceGenerator(com.eveningoutpost.dexdrip.watch.miband.Firmware.WatchFaceGenerator) AlertPlayer(com.eveningoutpost.dexdrip.UtilityModels.AlertPlayer) PoorMansConcurrentLinkedDeque(com.eveningoutpost.dexdrip.utils.framework.PoorMansConcurrentLinkedDeque) TimeUnit(java.util.concurrent.TimeUnit) MIBAND_NOTIFY_TYPE_MESSAGE(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_MESSAGE) OperationCodes(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes) UserError(com.eveningoutpost.dexdrip.Models.UserError) MIBAND_NOTIFY_TYPE_CALL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CALL) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) TimeoutException(java.util.concurrent.TimeoutException) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) SuppressLint(android.annotation.SuppressLint)

Example 2 with RxBleConnection

use of com.polidea.rxandroidble2.RxBleConnection in project xDrip by NightscoutFoundation.

the class Ob1G5StateMachine method doGetData.

// Get Data
@SuppressLint("CheckResult")
public static boolean doGetData(Ob1G5CollectionService parent, RxBleConnection connection) {
    if (connection == null)
        return false;
    // TODO switch modes depending on conditions as to whether we are using internal
    final boolean use_g5_internal_alg = Pref.getBooleanDefaultFalse("ob1_g5_use_transmitter_alg");
    UserError.Log.d(TAG, use_g5_internal_alg ? ("Requesting Glucose Data " + (usingG6() ? "G6" : "G5")) : "Requesting Sensor Data");
    if (!use_g5_internal_alg) {
        // not applicable
        parent.lastSensorStatus = null;
        parent.lastUsableGlucosePacketTime = 0;
    }
    connection.setupIndication(Control).doOnNext(notificationObservable -> {
        if (d)
            UserError.Log.d(TAG, "Notifications enabled");
        speakSlowly();
        connection.writeCharacteristic(Control, nn(use_g5_internal_alg ? (getEGlucose() ? new EGlucoseTxMessage().byteSequence : new GlucoseTxMessage().byteSequence) : new SensorTxMessage().byteSequence)).subscribe(characteristicValue -> {
            if (d)
                UserError.Log.d(TAG, "Wrote SensorTxMessage request");
        }, throwable -> {
            UserError.Log.e(TAG, "Failed to write SensorTxMessage: " + throwable);
            if (throwable instanceof BleGattCharacteristicException) {
                final int status = ((BleGattCharacteristicException) throwable).getStatus();
                UserError.Log.e(TAG, "Got status message: " + getStatusName(status));
                if (status == 8) {
                    UserError.Log.e(TAG, "Request rejected due to Insufficient Authorization failure!");
                    parent.authResult(false);
                }
            }
        });
    }).flatMap(notificationObservable -> notificationObservable).timeout(6, TimeUnit.SECONDS).subscribe(bytes -> {
        // incoming data notifications
        UserError.Log.d(TAG, "Received indication bytes: " + JoH.bytesToHex(bytes));
        final PacketShop data_packet = classifyPacket(bytes);
        switch(data_packet.type) {
            case SensorRxMessage:
                try {
                    checkVersionAndBattery(parent, connection);
                } finally {
                    processSensorRxMessage((SensorRxMessage) data_packet.msg);
                    parent.msg("Got data");
                    parent.updateLast(tsl());
                    parent.clearErrors();
                }
                break;
            case VersionRequest1RxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 1, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case VersionRequestRxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 0, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case VersionRequest2RxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 2, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case BatteryInfoRxMessage:
                if (!setStoredBatteryBytes(getTransmitterID(), bytes)) {
                    UserError.Log.e(TAG, "Could not save out battery data!");
                } else {
                    if (parent.android_wear) {
                        PersistentStore.setBoolean(G5_BATTERY_WEARABLE_SEND, true);
                    }
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                break;
            case SessionStartRxMessage:
                final SessionStartRxMessage session_start = (SessionStartRxMessage) data_packet.msg;
                if (session_start.isOkay()) {
                    // TODO persist this
                    parent.msg("Session Started Successfully: " + JoH.dateTimeText(session_start.getSessionStart()) + " " + JoH.dateTimeText(session_start.getRequestedStart()) + " " + JoH.dateTimeText(session_start.getTransmitterTime()));
                    DexResetHelper.cancel();
                } else {
                    final String msg = "Session Start Failed: " + session_start.message();
                    parent.msg(msg);
                    UserError.Log.ueh(TAG, msg);
                    JoH.showNotification(devName() + " Start Failed", msg, null, Constants.G5_START_REJECT, true, true, false);
                    UserError.Log.ueh(TAG, "Session Start failed info: " + JoH.dateTimeText(session_start.getSessionStart()) + " " + JoH.dateTimeText(session_start.getRequestedStart()) + " " + JoH.dateTimeText(session_start.getTransmitterTime()));
                    if (session_start.isFubar()) {
                        final long tk = DexTimeKeeper.getDexTime(getTransmitterID(), tsl());
                        if (tk > 0) {
                            DexResetHelper.offer("Unusual session start failure, is transmitter crashed? Try Hard Reset?");
                        } else {
                            UserError.Log.e(TAG, "No reset as TimeKeeper reports invalid: " + tk);
                        }
                    }
                    if (Pref.getBooleanDefaultFalse("ob1_g5_restart_sensor") && (Sensor.isActive())) {
                        if (pratelimit("secondary-g5-start", 1800)) {
                            UserError.Log.ueh(TAG, "Trying to Start sensor again");
                            startSensor(tsl());
                        }
                    }
                }
                reReadGlucoseData();
                break;
            case SessionStopRxMessage:
                final SessionStopRxMessage session_stop = (SessionStopRxMessage) data_packet.msg;
                if (session_stop.isOkay()) {
                    // TODO persist this
                    final String msg = "Session Stopped Successfully: " + JoH.dateTimeText(session_stop.getSessionStart()) + " " + JoH.dateTimeText(session_stop.getSessionStop());
                    parent.msg(msg);
                    UserError.Log.ueh(TAG, msg);
                    reReadGlucoseData();
                    enqueueUniqueCommand(new TimeTxMessage(), "Query time after stop");
                } else {
                    // TODO what does an error when session isn't started look like? Probably best to downgrade those somewhat
                    final String msg = "Session Stop Failed: packet valid: " + session_stop.isValid() + "  Status code: " + session_stop.getStatus();
                    UserError.Log.uel(TAG, msg);
                }
                break;
            case GlucoseRxMessage:
                final GlucoseRxMessage glucose = (GlucoseRxMessage) data_packet.msg;
                parent.processCalibrationState(glucose.calibrationState());
                if (glucose.usable()) {
                    parent.msg("Got " + devName() + " glucose");
                } else {
                    parent.msg("Got data from " + devName());
                }
                glucoseRxCommon(glucose, parent, connection);
                break;
            // TODO base class duplication
            case EGlucoseRxMessage:
                final EGlucoseRxMessage eglucose = (EGlucoseRxMessage) data_packet.msg;
                parent.processCalibrationState(eglucose.calibrationState());
                if (eglucose.usable()) {
                    parent.msg("Got G6 glucose");
                } else {
                    parent.msg("Got data from G6");
                }
                glucoseRxCommon(eglucose, parent, connection);
                break;
            case CalibrateRxMessage:
                final CalibrateRxMessage calibrate = (CalibrateRxMessage) data_packet.msg;
                if (calibrate.accepted()) {
                    parent.msg("Calibration accepted");
                    UserError.Log.ueh(TAG, "Calibration accepted by transmitter");
                } else {
                    final String msg = "Calibration rejected: " + calibrate.message();
                    UserError.Log.wtf(TAG, msg);
                    parent.msg(msg);
                    JoH.showNotification("Calibration rejected", msg, null, Constants.G5_CALIBRATION_REJECT, true, true, false);
                }
                reReadGlucoseData();
                break;
            case BackFillRxMessage:
                final BackFillRxMessage backfill = (BackFillRxMessage) data_packet.msg;
                if (backfill.valid()) {
                    UserError.Log.d(TAG, "Backfill request confirmed");
                } else {
                    UserError.Log.wtf(TAG, "Backfill request corrupted!");
                }
                break;
            case TransmitterTimeRxMessage:
                // This message is received every 120-125m
                final TransmitterTimeRxMessage txtime = (TransmitterTimeRxMessage) data_packet.msg;
                DexTimeKeeper.updateAge(getTransmitterID(), txtime.getCurrentTime(), true);
                if (txtime.sessionInProgress()) {
                    UserError.Log.e(TAG, "Session start time reports: " + JoH.dateTimeText(txtime.getRealSessionStartTime()) + " Duration: " + JoH.niceTimeScalar(txtime.getSessionDuration()));
                    DexSessionKeeper.setStart(txtime.getRealSessionStartTime());
                } else {
                    UserError.Log.e(TAG, "Session start time reports: No session in progress");
                    DexSessionKeeper.clearStart();
                }
                if (Pref.getBooleanDefaultFalse("ob1_g5_preemptive_restart")) {
                    int restartDaysThreshold = usingG6() ? 9 : 6;
                    if (txtime.getSessionDuration() > Constants.DAY_IN_MS * restartDaysThreshold && txtime.getSessionDuration() < Constants.MONTH_IN_MS) {
                        UserError.Log.uel(TAG, "Requesting preemptive session restart");
                        restartSensorWithTimeTravel();
                    }
                }
                break;
            case F2DUnknownRxMessage:
                UserError.Log.d(TAG, "Received F2D message");
                try {
                    checkVersionAndBattery(parent, connection);
                } finally {
                    parent.msg("Got no raw");
                    // TODO verify if this is ok to do here
                    parent.updateLast(tsl());
                    // TODO verify if this is ok to do here
                    parent.clearErrors();
                }
                break;
            default:
                UserError.Log.e(TAG, "Got unknown packet rx: " + JoH.bytesToHex(bytes));
                break;
        }
        if (!queued(parent, connection)) {
            inevitableDisconnect(parent, connection);
        }
    }, throwable -> {
        if (!(throwable instanceof OperationSuccess)) {
            if (throwable instanceof BleDisconnectedException) {
                UserError.Log.d(TAG, "Disconnected when waiting to receive indication: " + throwable);
                parent.changeState(Ob1G5CollectionService.STATE.CLOSE);
            } else {
                UserError.Log.e(TAG, "Error receiving indication: " + throwable);
                // throwable.printStackTrace();
                disconnectNow(parent, connection);
            }
        }
    });
    return true;
}
Also used : PersistentStore(com.eveningoutpost.dexdrip.UtilityModels.PersistentStore) Treatments(com.eveningoutpost.dexdrip.Models.Treatments) Arrays(java.util.Arrays) com.eveningoutpost.dexdrip.xdrip(com.eveningoutpost.dexdrip.xdrip) TypeToken(com.google.gson.reflect.TypeToken) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) SecretKeySpec(javax.crypto.spec.SecretKeySpec) G5_BATTERY_FROM_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_FROM_MARKER) Inevitable(com.eveningoutpost.dexdrip.UtilityModels.Inevitable) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) Pref(com.eveningoutpost.dexdrip.UtilityModels.Pref) PowerManager(android.os.PowerManager) Authentication(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.Authentication) NotificationChannels(com.eveningoutpost.dexdrip.UtilityModels.NotificationChannels) SensorSanity(com.eveningoutpost.dexdrip.Models.SensorSanity) BleGattCharacteristicException(com.polidea.rxandroidble2.exceptions.BleGattCharacteristicException) Schedulers(io.reactivex.schedulers.Schedulers) DEXCOM_PERIOD(com.eveningoutpost.dexdrip.UtilityModels.BgGraphBuilder.DEXCOM_PERIOD) DAY_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.DAY_IN_MS) G5_BATTERY_WEARABLE_SEND(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_WEARABLE_SEND) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) Ob1G5CollectionService.android_wear(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.android_wear) Ob1G5CollectionService.wear_broadcast(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.wear_broadcast) TransmitterData(com.eveningoutpost.dexdrip.Models.TransmitterData) BluetoothGatt(android.bluetooth.BluetoothGatt) JoH(com.eveningoutpost.dexdrip.Models.JoH) List(java.util.List) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) Type(java.lang.reflect.Type) R(com.eveningoutpost.dexdrip.R) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Ob1G5CollectionService(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService) InvalidKeyException(java.security.InvalidKeyException) Home(com.eveningoutpost.dexdrip.Home) BgGraphBuilder(com.eveningoutpost.dexdrip.UtilityModels.BgGraphBuilder) UnsupportedEncodingException(java.io.UnsupportedEncodingException) G5_FIRMWARE_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_FIRMWARE_MARKER) Sensor(com.eveningoutpost.dexdrip.Models.Sensor) Constants(com.eveningoutpost.dexdrip.UtilityModels.Constants) Helper.getStatusName(com.eveningoutpost.dexdrip.utils.bt.Helper.getStatusName) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) HOUR_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.HOUR_IN_MS) Cipher(javax.crypto.Cipher) HexDump(com.eveningoutpost.dexdrip.ImportedLibraries.usbserial.util.HexDump) ArrayList(java.util.ArrayList) SuppressLint(android.annotation.SuppressLint) Prediction(com.eveningoutpost.dexdrip.Models.Prediction) G5_BATTERY_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_MARKER) BestGlucose(com.eveningoutpost.dexdrip.BestGlucose) JoH.tsl(com.eveningoutpost.dexdrip.Models.JoH.tsl) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) Build(android.os.Build) Notifications(com.eveningoutpost.dexdrip.UtilityModels.Notifications) Ob1G5CollectionService.onlyUsingNativeMode(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.onlyUsingNativeMode) WholeHouse(com.eveningoutpost.dexdrip.UtilityModels.WholeHouse) ProbablyBackfill(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.ProbablyBackfill) Control(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.Control) JoH.msSince(com.eveningoutpost.dexdrip.Models.JoH.msSince) Mimeograph(com.eveningoutpost.dexdrip.utils.bt.Mimeograph) TimeUnit(java.util.concurrent.TimeUnit) PowerStateReceiver(com.eveningoutpost.dexdrip.utils.PowerStateReceiver) BadPaddingException(javax.crypto.BadPaddingException) G5_BATTERY_LEVEL_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_LEVEL_MARKER) BroadcastGlucose(com.eveningoutpost.dexdrip.UtilityModels.BroadcastGlucose) DexCollectionType(com.eveningoutpost.dexdrip.utils.DexCollectionType) JoH.pratelimit(com.eveningoutpost.dexdrip.Models.JoH.pratelimit) SECOND_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.SECOND_IN_MS) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) WatchUpdaterService(com.eveningoutpost.dexdrip.wearintegration.WatchUpdaterService) Ob1G5CollectionService.getTransmitterID(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.getTransmitterID) UserError(com.eveningoutpost.dexdrip.Models.UserError) MINUTE_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.MINUTE_IN_MS) SuppressLint(android.annotation.SuppressLint) BleGattCharacteristicException(com.polidea.rxandroidble2.exceptions.BleGattCharacteristicException) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) SuppressLint(android.annotation.SuppressLint)

Example 3 with RxBleConnection

use of com.polidea.rxandroidble2.RxBleConnection in project xDrip-plus by jamorham.

the class Ob1G5StateMachine method doGetData.

// Get Data
@SuppressLint("CheckResult")
public static boolean doGetData(Ob1G5CollectionService parent, RxBleConnection connection) {
    if (connection == null)
        return false;
    // TODO switch modes depending on conditions as to whether we are using internal
    final boolean use_g5_internal_alg = Pref.getBooleanDefaultFalse("ob1_g5_use_transmitter_alg");
    UserError.Log.d(TAG, use_g5_internal_alg ? ("Requesting Glucose Data " + (usingG6() ? "G6" : "G5")) : "Requesting Sensor Data");
    if (!use_g5_internal_alg) {
        // not applicable
        parent.lastSensorStatus = null;
        parent.lastUsableGlucosePacketTime = 0;
    }
    connection.setupIndication(Control).doOnNext(notificationObservable -> {
        if (d)
            UserError.Log.d(TAG, "Notifications enabled");
        speakSlowly();
        connection.writeCharacteristic(Control, nn(use_g5_internal_alg ? (getEGlucose() ? new EGlucoseTxMessage().byteSequence : new GlucoseTxMessage().byteSequence) : new SensorTxMessage().byteSequence)).subscribe(characteristicValue -> {
            if (d)
                UserError.Log.d(TAG, "Wrote SensorTxMessage request");
        }, throwable -> {
            UserError.Log.e(TAG, "Failed to write SensorTxMessage: " + throwable);
            if (throwable instanceof BleGattCharacteristicException) {
                final int status = ((BleGattCharacteristicException) throwable).getStatus();
                UserError.Log.e(TAG, "Got status message: " + getStatusName(status));
                if (status == 8) {
                    UserError.Log.e(TAG, "Request rejected due to Insufficient Authorization failure!");
                    parent.authResult(false);
                }
            }
        });
    }).flatMap(notificationObservable -> notificationObservable).timeout(6, TimeUnit.SECONDS).subscribe(bytes -> {
        // incoming data notifications
        UserError.Log.d(TAG, "Received indication bytes: " + JoH.bytesToHex(bytes));
        final PacketShop data_packet = classifyPacket(bytes);
        switch(data_packet.type) {
            case SensorRxMessage:
                try {
                    checkVersionAndBattery(parent, connection);
                } finally {
                    processSensorRxMessage((SensorRxMessage) data_packet.msg);
                    parent.msg("Got data");
                    parent.updateLast(tsl());
                    parent.clearErrors();
                }
                break;
            case VersionRequest1RxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 1, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case VersionRequestRxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 0, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case VersionRequest2RxMessage:
                if (!setStoredFirmwareBytes(getTransmitterID(), 2, bytes, true)) {
                    UserError.Log.e(TAG, "Could not save out firmware version!");
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                if (JoH.ratelimit("g6-evaluate", 600)) {
                    Inevitable.task("evaluteG6Settings", 10000, () -> evaluateG6Settings());
                }
                break;
            case BatteryInfoRxMessage:
                if (!setStoredBatteryBytes(getTransmitterID(), bytes)) {
                    UserError.Log.e(TAG, "Could not save out battery data!");
                } else {
                    if (parent.android_wear) {
                        PersistentStore.setBoolean(G5_BATTERY_WEARABLE_SEND, true);
                    }
                }
                nextBackFillCheckSize = BACKFILL_CHECK_LARGE;
                break;
            case SessionStartRxMessage:
                final SessionStartRxMessage session_start = (SessionStartRxMessage) data_packet.msg;
                if (session_start.isOkay()) {
                    // TODO persist this
                    parent.msg("Session Started Successfully: " + JoH.dateTimeText(session_start.getSessionStart()) + " " + JoH.dateTimeText(session_start.getRequestedStart()) + " " + JoH.dateTimeText(session_start.getTransmitterTime()));
                    DexResetHelper.cancel();
                } else {
                    final String msg = "Session Start Failed: " + session_start.message();
                    parent.msg(msg);
                    UserError.Log.ueh(TAG, msg);
                    JoH.showNotification(devName() + " Start Failed", msg, null, Constants.G5_START_REJECT, true, true, false);
                    UserError.Log.ueh(TAG, "Session Start failed info: " + JoH.dateTimeText(session_start.getSessionStart()) + " " + JoH.dateTimeText(session_start.getRequestedStart()) + " " + JoH.dateTimeText(session_start.getTransmitterTime()));
                    if (session_start.isFubar()) {
                        final long tk = DexTimeKeeper.getDexTime(getTransmitterID(), tsl());
                        if (tk > 0) {
                            DexResetHelper.offer("Unusual session start failure, is transmitter crashed? Try Hard Reset?");
                        } else {
                            UserError.Log.e(TAG, "No reset as TimeKeeper reports invalid: " + tk);
                        }
                    }
                    if (Pref.getBooleanDefaultFalse("ob1_g5_restart_sensor") && (Sensor.isActive())) {
                        if (pratelimit("secondary-g5-start", 1800)) {
                            UserError.Log.ueh(TAG, "Trying to Start sensor again");
                            startSensor(tsl());
                        }
                    }
                }
                reReadGlucoseData();
                break;
            case SessionStopRxMessage:
                final SessionStopRxMessage session_stop = (SessionStopRxMessage) data_packet.msg;
                if (session_stop.isOkay()) {
                    // TODO persist this
                    final String msg = "Session Stopped Successfully: " + JoH.dateTimeText(session_stop.getSessionStart()) + " " + JoH.dateTimeText(session_stop.getSessionStop());
                    parent.msg(msg);
                    UserError.Log.ueh(TAG, msg);
                    reReadGlucoseData();
                    enqueueUniqueCommand(new TimeTxMessage(), "Query time after stop");
                } else {
                    // TODO what does an error when session isn't started look like? Probably best to downgrade those somewhat
                    final String msg = "Session Stop Failed: packet valid: " + session_stop.isValid() + "  Status code: " + session_stop.getStatus();
                    UserError.Log.uel(TAG, msg);
                }
                break;
            case GlucoseRxMessage:
                final GlucoseRxMessage glucose = (GlucoseRxMessage) data_packet.msg;
                parent.processCalibrationState(glucose.calibrationState());
                if (glucose.usable()) {
                    parent.msg("Got " + devName() + " glucose");
                } else {
                    parent.msg("Got data from " + devName());
                }
                glucoseRxCommon(glucose, parent, connection);
                break;
            // TODO base class duplication
            case EGlucoseRxMessage:
                final EGlucoseRxMessage eglucose = (EGlucoseRxMessage) data_packet.msg;
                parent.processCalibrationState(eglucose.calibrationState());
                if (eglucose.usable()) {
                    parent.msg("Got G6 glucose");
                } else {
                    parent.msg("Got data from G6");
                }
                glucoseRxCommon(eglucose, parent, connection);
                break;
            case CalibrateRxMessage:
                final CalibrateRxMessage calibrate = (CalibrateRxMessage) data_packet.msg;
                if (calibrate.accepted()) {
                    parent.msg("Calibration accepted");
                    UserError.Log.ueh(TAG, "Calibration accepted by transmitter");
                } else {
                    final String msg = "Calibration rejected: " + calibrate.message();
                    UserError.Log.wtf(TAG, msg);
                    parent.msg(msg);
                    JoH.showNotification("Calibration rejected", msg, null, Constants.G5_CALIBRATION_REJECT, true, true, false);
                }
                reReadGlucoseData();
                break;
            case BackFillRxMessage:
                final BackFillRxMessage backfill = (BackFillRxMessage) data_packet.msg;
                if (backfill.valid()) {
                    UserError.Log.d(TAG, "Backfill request confirmed");
                } else {
                    UserError.Log.wtf(TAG, "Backfill request corrupted!");
                }
                break;
            case TransmitterTimeRxMessage:
                // This message is received every 120-125m
                final TransmitterTimeRxMessage txtime = (TransmitterTimeRxMessage) data_packet.msg;
                DexTimeKeeper.updateAge(getTransmitterID(), txtime.getCurrentTime(), true);
                if (txtime.sessionInProgress()) {
                    UserError.Log.e(TAG, "Session start time reports: " + JoH.dateTimeText(txtime.getRealSessionStartTime()) + " Duration: " + JoH.niceTimeScalar(txtime.getSessionDuration()));
                    DexSessionKeeper.setStart(txtime.getRealSessionStartTime());
                } else {
                    UserError.Log.e(TAG, "Session start time reports: No session in progress");
                    DexSessionKeeper.clearStart();
                }
                if (Pref.getBooleanDefaultFalse("ob1_g5_preemptive_restart")) {
                    int restartDaysThreshold = usingG6() ? 9 : 6;
                    if (txtime.getSessionDuration() > Constants.DAY_IN_MS * restartDaysThreshold && txtime.getSessionDuration() < Constants.MONTH_IN_MS) {
                        UserError.Log.uel(TAG, "Requesting preemptive session restart");
                        restartSensorWithTimeTravel();
                    }
                }
                break;
            case F2DUnknownRxMessage:
                UserError.Log.d(TAG, "Received F2D message");
                try {
                    checkVersionAndBattery(parent, connection);
                } finally {
                    parent.msg("Got no raw");
                    // TODO verify if this is ok to do here
                    parent.updateLast(tsl());
                    // TODO verify if this is ok to do here
                    parent.clearErrors();
                }
                break;
            default:
                UserError.Log.e(TAG, "Got unknown packet rx: " + JoH.bytesToHex(bytes));
                break;
        }
        if (!queued(parent, connection)) {
            inevitableDisconnect(parent, connection);
        }
    }, throwable -> {
        if (!(throwable instanceof OperationSuccess)) {
            if (throwable instanceof BleDisconnectedException) {
                UserError.Log.d(TAG, "Disconnected when waiting to receive indication: " + throwable);
                parent.changeState(Ob1G5CollectionService.STATE.CLOSE);
            } else {
                UserError.Log.e(TAG, "Error receiving indication: " + throwable);
                // throwable.printStackTrace();
                disconnectNow(parent, connection);
            }
        }
    });
    return true;
}
Also used : PersistentStore(com.eveningoutpost.dexdrip.UtilityModels.PersistentStore) Treatments(com.eveningoutpost.dexdrip.Models.Treatments) Arrays(java.util.Arrays) com.eveningoutpost.dexdrip.xdrip(com.eveningoutpost.dexdrip.xdrip) TypeToken(com.google.gson.reflect.TypeToken) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) SecretKeySpec(javax.crypto.spec.SecretKeySpec) G5_BATTERY_FROM_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_FROM_MARKER) Inevitable(com.eveningoutpost.dexdrip.UtilityModels.Inevitable) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) Pref(com.eveningoutpost.dexdrip.UtilityModels.Pref) PowerManager(android.os.PowerManager) Authentication(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.Authentication) NotificationChannels(com.eveningoutpost.dexdrip.UtilityModels.NotificationChannels) SensorSanity(com.eveningoutpost.dexdrip.Models.SensorSanity) BleGattCharacteristicException(com.polidea.rxandroidble2.exceptions.BleGattCharacteristicException) Schedulers(io.reactivex.schedulers.Schedulers) DEXCOM_PERIOD(com.eveningoutpost.dexdrip.UtilityModels.BgGraphBuilder.DEXCOM_PERIOD) DAY_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.DAY_IN_MS) G5_BATTERY_WEARABLE_SEND(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_WEARABLE_SEND) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) IllegalBlockSizeException(javax.crypto.IllegalBlockSizeException) Ob1G5CollectionService.android_wear(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.android_wear) Ob1G5CollectionService.wear_broadcast(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.wear_broadcast) TransmitterData(com.eveningoutpost.dexdrip.Models.TransmitterData) BluetoothGatt(android.bluetooth.BluetoothGatt) JoH(com.eveningoutpost.dexdrip.Models.JoH) List(java.util.List) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) Type(java.lang.reflect.Type) R(com.eveningoutpost.dexdrip.R) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) Ob1G5CollectionService(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService) InvalidKeyException(java.security.InvalidKeyException) Home(com.eveningoutpost.dexdrip.Home) BgGraphBuilder(com.eveningoutpost.dexdrip.UtilityModels.BgGraphBuilder) UnsupportedEncodingException(java.io.UnsupportedEncodingException) G5_FIRMWARE_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_FIRMWARE_MARKER) Sensor(com.eveningoutpost.dexdrip.Models.Sensor) Constants(com.eveningoutpost.dexdrip.UtilityModels.Constants) Helper.getStatusName(com.eveningoutpost.dexdrip.utils.bt.Helper.getStatusName) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) HOUR_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.HOUR_IN_MS) Cipher(javax.crypto.Cipher) HexDump(com.eveningoutpost.dexdrip.ImportedLibraries.usbserial.util.HexDump) ArrayList(java.util.ArrayList) SuppressLint(android.annotation.SuppressLint) Prediction(com.eveningoutpost.dexdrip.Models.Prediction) G5_BATTERY_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_MARKER) BestGlucose(com.eveningoutpost.dexdrip.BestGlucose) JoH.tsl(com.eveningoutpost.dexdrip.Models.JoH.tsl) NoSuchPaddingException(javax.crypto.NoSuchPaddingException) Build(android.os.Build) Notifications(com.eveningoutpost.dexdrip.UtilityModels.Notifications) Ob1G5CollectionService.onlyUsingNativeMode(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.onlyUsingNativeMode) WholeHouse(com.eveningoutpost.dexdrip.UtilityModels.WholeHouse) ProbablyBackfill(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.ProbablyBackfill) Control(com.eveningoutpost.dexdrip.G5Model.BluetoothServices.Control) JoH.msSince(com.eveningoutpost.dexdrip.Models.JoH.msSince) Mimeograph(com.eveningoutpost.dexdrip.utils.bt.Mimeograph) TimeUnit(java.util.concurrent.TimeUnit) PowerStateReceiver(com.eveningoutpost.dexdrip.utils.PowerStateReceiver) BadPaddingException(javax.crypto.BadPaddingException) G5_BATTERY_LEVEL_MARKER(com.eveningoutpost.dexdrip.Services.G5BaseService.G5_BATTERY_LEVEL_MARKER) BroadcastGlucose(com.eveningoutpost.dexdrip.UtilityModels.BroadcastGlucose) DexCollectionType(com.eveningoutpost.dexdrip.utils.DexCollectionType) JoH.pratelimit(com.eveningoutpost.dexdrip.Models.JoH.pratelimit) SECOND_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.SECOND_IN_MS) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) WatchUpdaterService(com.eveningoutpost.dexdrip.wearintegration.WatchUpdaterService) Ob1G5CollectionService.getTransmitterID(com.eveningoutpost.dexdrip.Services.Ob1G5CollectionService.getTransmitterID) UserError(com.eveningoutpost.dexdrip.Models.UserError) MINUTE_IN_MS(com.eveningoutpost.dexdrip.UtilityModels.Constants.MINUTE_IN_MS) SuppressLint(android.annotation.SuppressLint) BleGattCharacteristicException(com.polidea.rxandroidble2.exceptions.BleGattCharacteristicException) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) SuppressLint(android.annotation.SuppressLint)

Example 4 with RxBleConnection

use of com.polidea.rxandroidble2.RxBleConnection in project xDrip-plus by jamorham.

the class MiBandService method processFirmwareCommands.

@SuppressLint("CheckResult")
private void processFirmwareCommands(byte[] value, boolean isSeqCommand) {
    RxBleConnection connection = I.connection;
    FirmwareOperations.SequenceType seq = firmware.getSequence();
    if (d)
        UserError.Log.d(TAG, "processFirmwareCommands: " + bytesToHex(value) + ": seq:" + seq.toString());
    if (isSeqCommand) {
        switch(seq) {
            case SET_NIGHTMODE:
                {
                    if (true) {
                        isNeedToRestoreNightMode = true;
                        DisplayControllMessageMiband3_4 dispControl = new DisplayControllMessageMiband3_4();
                        Calendar sheduledCalendar = Calendar.getInstance();
                        sheduledCalendar.set(Calendar.HOUR_OF_DAY, 0);
                        sheduledCalendar.set(Calendar.MINUTE, 0);
                        Date sheduledDate = sheduledCalendar.getTime();
                        connection.writeCharacteristic(dispControl.getCharacteristicUUID(), dispControl.setNightModeCmd(Sheduled, sheduledDate, sheduledDate)).subscribe(valB -> {
                            UserError.Log.d(TAG, "Wrote nigntmode, got: " + JoH.bytesToHex(valB));
                            firmware.nextSequence();
                            processFirmwareCommands(null, true);
                        }, throwable -> {
                            UserError.Log.e(TAG, "Could not write nigntmode: " + throwable);
                            firmware.nextSequence();
                            processFirmwareCommands(null, true);
                        });
                    } else {
                        firmware.nextSequence();
                        processFirmwareCommands(null, true);
                    }
                    break;
                }
            case PREPARE_UPLOAD:
                {
                    connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.prepareFWUploadInitCommand()).subscribe(valB -> {
                        UserError.Log.d(TAG, "Wrote prepareFWUploadInitCommand, got: " + JoH.bytesToHex(valB));
                    }, throwable -> {
                        UserError.Log.e(TAG, "Could not write prepareFWUploadInitCommand: " + throwable);
                        resetFirmwareState(false);
                    });
                    firmware.nextSequence();
                    break;
                }
        }
        return;
    } else {
        if (value.length != 3 && value.length != 11) {
            UserError.Log.e(TAG, "Notifications should be 3 or 11 bytes long.");
            return;
        }
        boolean success = value[2] == OperationCodes.SUCCESS;
        if (value[0] == OperationCodes.RESPONSE && success) {
            try {
                switch(value[1]) {
                    case OperationCodes.COMMAND_FIRMWARE_INIT:
                        {
                            if (seq == FirmwareOperations.SequenceType.TRANSFER_FW_START) {
                                connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.getFirmwareStartCommand()).subscribe(valB -> {
                                    UserError.Log.d(TAG, "Wrote Start command, got: " + JoH.bytesToHex(valB));
                                }, throwable -> {
                                    UserError.Log.e(TAG, "Could not write Start command: " + throwable);
                                    resetFirmwareState(false);
                                });
                                firmware.nextSequence();
                            } else if (seq == FirmwareOperations.SequenceType.TRANSFER_SEND_WF_INFO) {
                                connection.writeCharacteristic(firmware.getFirmwareCharacteristicUUID(), firmware.sendFwInfo()).subscribe(valB -> {
                                    UserError.Log.d(TAG, "Wrote sendFwInfo, got: " + JoH.bytesToHex(valB));
                                }, throwable -> {
                                    UserError.Log.e(TAG, "Could not write firmware info: " + throwable);
                                    resetFirmwareState(false);
                                });
                                firmware.nextSequence();
                                break;
                            }
                            break;
                        }
                    case OperationCodes.COMMAND_FIRMWARE_START_DATA:
                        {
                            sendFirmwareData();
                            break;
                        }
                    case OperationCodes.COMMAND_FIRMWARE_CHECKSUM:
                        {
                            firmware.nextSequence();
                            if (firmware.getFirmwareType() == FirmwareOperations.FirmwareType.FIRMWARE) {
                            // send reboot
                            } else {
                                UserError.Log.e(TAG, "Watch Face has been installed successfully");
                                resetFirmwareState(true);
                            }
                            break;
                        }
                    case OperationCodes.COMMAND_FIRMWARE_REBOOT:
                        {
                            UserError.Log.e(TAG, "Reboot command successfully sent.");
                            resetFirmwareState(true);
                            break;
                        }
                    default:
                        {
                            resetFirmwareState(false, "Unexpected response during firmware update");
                        }
                }
            } catch (Exception ex) {
                resetFirmwareState(false);
            }
        } else {
            String errorMessage = null;
            Boolean sendBGNotification = false;
            if (value[2] == OperationCodes.LOW_BATTERY_ERROR) {
                errorMessage = "Cannot upload watchface, low battery, please charge device";
                sendBGNotification = true;
            } else if (value[2] == OperationCodes.TIMER_RUNNING) {
                errorMessage = "Cannot upload watchface, timer running on band";
            } else if (value[2] == OperationCodes.ON_CALL) {
                errorMessage = "Cannot upload watchface, call in progress";
            } else {
                errorMessage = "Unexpected notification during firmware update:" + JoH.bytesToHex(value);
            }
            resetFirmwareState(false, errorMessage);
            if (sendBGNotification) {
                emptyQueue();
                JoH.startService(MiBandService.class, "function", "update_bg_as_notification");
                changeState(SLEEP);
            }
        }
    }
}
Also used : AUTHORIZE_FAILED(com.eveningoutpost.dexdrip.watch.miband.MiBandService.MiBandState.AUTHORIZE_FAILED) AUTH_REQUEST_RANDOM_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_REQUEST_RANDOM_AUTH_NUMBER) AuthMessages(com.eveningoutpost.dexdrip.watch.miband.message.AuthMessages) Arrays(java.util.Arrays) com.eveningoutpost.dexdrip.xdrip(com.eveningoutpost.dexdrip.xdrip) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) PendingIntent(android.app.PendingIntent) CLOSED(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSED) INIT(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.INIT) Inevitable(com.eveningoutpost.dexdrip.UtilityModels.Inevitable) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) PowerManager(android.os.PowerManager) HeartRate(com.eveningoutpost.dexdrip.Models.HeartRate) StatusItem(com.eveningoutpost.dexdrip.UtilityModels.StatusItem) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) COMMAND_ACK_FIND_PHONE_IN_PROGRESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_ACK_FIND_PHONE_IN_PROGRESS) AUTH_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_FAIL) Schedulers(io.reactivex.schedulers.Schedulers) AUTH_MIBAND4_CODE_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_CODE_FAIL) AUTH_RESPONSE(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_RESPONSE) AUTH_SEND_KEY(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_KEY) ActiveBgAlert(com.eveningoutpost.dexdrip.Models.ActiveBgAlert) FeaturesControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.FeaturesControllMessage) MIBAND_NOTIFY_TYPE_ALARM(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_ALARM) CLOSE(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSE) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) PrefBindingFactory(com.eveningoutpost.dexdrip.watch.PrefBindingFactory) UUID(java.util.UUID) JoH.getResourceURI(com.eveningoutpost.dexdrip.Models.JoH.getResourceURI) UNKNOWN(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.UNKNOWN) JoH(com.eveningoutpost.dexdrip.Models.JoH) List(java.util.List) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) JoH.bytesToHex(com.eveningoutpost.dexdrip.Models.JoH.bytesToHex) MIBAND_NOTIFY_TYPE_CANCEL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CANCEL) R(com.eveningoutpost.dexdrip.R) Subscription(com.eveningoutpost.dexdrip.utils.bt.Subscription) PREFERRED_MTU_SIZE(com.eveningoutpost.dexdrip.watch.miband.Const.PREFERRED_MTU_SIZE) AlertLevelMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertLevelMessage) JoH.msTill(com.eveningoutpost.dexdrip.Models.JoH.msTill) AUTH_SUCCESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SUCCESS) Getter(lombok.Getter) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic) WakeLockTrampoline(com.eveningoutpost.dexdrip.utils.framework.WakeLockTrampoline) Constants(com.eveningoutpost.dexdrip.UtilityModels.Constants) AUTH_SEND_ENCRYPTED_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_ENCRYPTED_AUTH_NUMBER) Pair(android.util.Pair) FirmwareOperations(com.eveningoutpost.dexdrip.watch.miband.Firmware.FirmwareOperations) DisplayControllMessageMiband3_4(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) Intent(android.content.Intent) MediaPlayer(android.media.MediaPlayer) ArrayList(java.util.ArrayList) JoH.niceTimeScalar(com.eveningoutpost.dexdrip.Models.JoH.niceTimeScalar) SuppressLint(android.annotation.SuppressLint) Calendar(java.util.Calendar) DeviceEvent(com.eveningoutpost.dexdrip.watch.miband.message.DeviceEvent) DisplayControllMessageMiBand2(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiBand2) DisplayControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessage) COMMAND_DISABLE_CALL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_DISABLE_CALL) JamBaseBluetoothSequencer(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer) AlertMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertMessage) MI_BAND4(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND4) Sheduled(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4.NightMode.Sheduled) RxBleDeviceServices(com.polidea.rxandroidble2.RxBleDeviceServices) MI_BAND2(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND2) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) SLEEP(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.SLEEP) BluetoothGattService(android.bluetooth.BluetoothGattService) com.eveningoutpost.dexdrip.xdrip.gs(com.eveningoutpost.dexdrip.xdrip.gs) AUTH_MIBAND4_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_FAIL) WatchFaceGenerator(com.eveningoutpost.dexdrip.watch.miband.Firmware.WatchFaceGenerator) AlertPlayer(com.eveningoutpost.dexdrip.UtilityModels.AlertPlayer) PoorMansConcurrentLinkedDeque(com.eveningoutpost.dexdrip.utils.framework.PoorMansConcurrentLinkedDeque) TimeUnit(java.util.concurrent.TimeUnit) MIBAND_NOTIFY_TYPE_MESSAGE(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_MESSAGE) OperationCodes(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes) UserError(com.eveningoutpost.dexdrip.Models.UserError) MIBAND_NOTIFY_TYPE_CALL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CALL) FirmwareOperations(com.eveningoutpost.dexdrip.watch.miband.Firmware.FirmwareOperations) DisplayControllMessageMiband3_4(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4) Calendar(java.util.Calendar) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) SuppressLint(android.annotation.SuppressLint)

Example 5 with RxBleConnection

use of com.polidea.rxandroidble2.RxBleConnection in project xDrip-plus by jamorham.

the class MiBandService method ProcessAuthCommands.

@SuppressLint("CheckResult")
private void ProcessAuthCommands(RxBleConnection connection, byte[] value) {
    if (value[0] == AUTH_RESPONSE && value[1] == AUTH_SEND_KEY && (value[2] & 0x0f) == AUTH_SUCCESS) {
        // get random key from band
        connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()).subscribe(val -> {
            if (d)
                UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ1: " + JoH.bytesToHex(val));
        }, throwable -> {
            UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ1: " + throwable);
        });
    } else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_REQUEST_RANDOM_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
        byte[] tmpValue = Arrays.copyOfRange(value, 3, 19);
        try {
            byte[] authReply = authorisation.calculateAuthReply(tmpValue);
            // get random key from band
            connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authReply).subscribe(val -> {
                if (d)
                    UserError.Log.d(TAG, "Wrote OPCODE_AUTH_REQ2: " + JoH.bytesToHex(val));
            }, throwable -> {
                UserError.Log.e(TAG, "Could not write OPCODE_AUTH_REQ2: " + throwable);
            });
        } catch (Exception e) {
            JoH.static_toast_long(e.getMessage());
            UserError.Log.e(TAG, (e.getMessage()));
            changeState(AUTHORIZE_FAILED);
        }
    } else if (value[0] == AUTH_RESPONSE && (value[1] & 0x0f) == AUTH_SEND_ENCRYPTED_AUTH_NUMBER && value[2] == AUTH_SUCCESS) {
        isNeedToAuthenticate = false;
        if (MiBand.getPersistentAuthMac().isEmpty()) {
            MiBand.setPersistentAuthMac(MiBand.getMac());
            MiBand.setPersistentAuthKey(JoH.bytesToHex(authorisation.getLocalKey()), MiBand.getPersistentAuthMac());
            String msg = "MiBand was successfully authenticated";
            JoH.static_toast_long(msg);
            UserError.Log.e(TAG, msg);
        }
        if (authSubscription != null) {
            authSubscription.unsubscribe();
        }
        changeNextState();
    } else if (value[0] == AUTH_RESPONSE && (((value[2] & 0x0f) == AUTH_FAIL) || (value[2] == AUTH_MIBAND4_FAIL) || (value[2] == AUTH_MIBAND4_CODE_FAIL))) {
        MiBand.setPersistentAuthKey("", MiBand.getPersistentAuthMac());
        if (authSubscription != null) {
            authSubscription.unsubscribe();
        }
        String msg = "Cannot authorize miband, please recheck Auth code";
        JoH.static_toast_long(msg);
        UserError.Log.e(TAG, msg);
        changeState(AUTHORIZE_FAILED);
    }
}
Also used : AUTHORIZE_FAILED(com.eveningoutpost.dexdrip.watch.miband.MiBandService.MiBandState.AUTHORIZE_FAILED) AUTH_REQUEST_RANDOM_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_REQUEST_RANDOM_AUTH_NUMBER) AuthMessages(com.eveningoutpost.dexdrip.watch.miband.message.AuthMessages) Arrays(java.util.Arrays) com.eveningoutpost.dexdrip.xdrip(com.eveningoutpost.dexdrip.xdrip) Date(java.util.Date) TimeoutException(java.util.concurrent.TimeoutException) PendingIntent(android.app.PendingIntent) CLOSED(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSED) INIT(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.INIT) Inevitable(com.eveningoutpost.dexdrip.UtilityModels.Inevitable) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) PowerManager(android.os.PowerManager) HeartRate(com.eveningoutpost.dexdrip.Models.HeartRate) StatusItem(com.eveningoutpost.dexdrip.UtilityModels.StatusItem) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) COMMAND_ACK_FIND_PHONE_IN_PROGRESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_ACK_FIND_PHONE_IN_PROGRESS) AUTH_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_FAIL) Schedulers(io.reactivex.schedulers.Schedulers) AUTH_MIBAND4_CODE_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_CODE_FAIL) AUTH_RESPONSE(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_RESPONSE) AUTH_SEND_KEY(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_KEY) ActiveBgAlert(com.eveningoutpost.dexdrip.Models.ActiveBgAlert) FeaturesControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.FeaturesControllMessage) MIBAND_NOTIFY_TYPE_ALARM(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_ALARM) CLOSE(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.CLOSE) BgReading(com.eveningoutpost.dexdrip.Models.BgReading) PrefBindingFactory(com.eveningoutpost.dexdrip.watch.PrefBindingFactory) UUID(java.util.UUID) JoH.getResourceURI(com.eveningoutpost.dexdrip.Models.JoH.getResourceURI) UNKNOWN(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.UNKNOWN) JoH(com.eveningoutpost.dexdrip.Models.JoH) List(java.util.List) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) JoH.bytesToHex(com.eveningoutpost.dexdrip.Models.JoH.bytesToHex) MIBAND_NOTIFY_TYPE_CANCEL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CANCEL) R(com.eveningoutpost.dexdrip.R) Subscription(com.eveningoutpost.dexdrip.utils.bt.Subscription) PREFERRED_MTU_SIZE(com.eveningoutpost.dexdrip.watch.miband.Const.PREFERRED_MTU_SIZE) AlertLevelMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertLevelMessage) JoH.msTill(com.eveningoutpost.dexdrip.Models.JoH.msTill) AUTH_SUCCESS(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SUCCESS) Getter(lombok.Getter) BluetoothGattCharacteristic(android.bluetooth.BluetoothGattCharacteristic) WakeLockTrampoline(com.eveningoutpost.dexdrip.utils.framework.WakeLockTrampoline) Constants(com.eveningoutpost.dexdrip.UtilityModels.Constants) AUTH_SEND_ENCRYPTED_AUTH_NUMBER(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_SEND_ENCRYPTED_AUTH_NUMBER) Pair(android.util.Pair) FirmwareOperations(com.eveningoutpost.dexdrip.watch.miband.Firmware.FirmwareOperations) DisplayControllMessageMiband3_4(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4) RxBleConnection(com.polidea.rxandroidble2.RxBleConnection) Intent(android.content.Intent) MediaPlayer(android.media.MediaPlayer) ArrayList(java.util.ArrayList) JoH.niceTimeScalar(com.eveningoutpost.dexdrip.Models.JoH.niceTimeScalar) SuppressLint(android.annotation.SuppressLint) Calendar(java.util.Calendar) DeviceEvent(com.eveningoutpost.dexdrip.watch.miband.message.DeviceEvent) DisplayControllMessageMiBand2(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiBand2) DisplayControllMessage(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessage) COMMAND_DISABLE_CALL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.COMMAND_DISABLE_CALL) JamBaseBluetoothSequencer(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer) AlertMessage(com.eveningoutpost.dexdrip.watch.miband.message.AlertMessage) MI_BAND4(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND4) Sheduled(com.eveningoutpost.dexdrip.watch.miband.message.DisplayControllMessageMiband3_4.NightMode.Sheduled) RxBleDeviceServices(com.polidea.rxandroidble2.RxBleDeviceServices) MI_BAND2(com.eveningoutpost.dexdrip.watch.miband.MiBand.MiBandType.MI_BAND2) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) SLEEP(com.eveningoutpost.dexdrip.Services.JamBaseBluetoothSequencer.BaseState.SLEEP) BluetoothGattService(android.bluetooth.BluetoothGattService) com.eveningoutpost.dexdrip.xdrip.gs(com.eveningoutpost.dexdrip.xdrip.gs) AUTH_MIBAND4_FAIL(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes.AUTH_MIBAND4_FAIL) WatchFaceGenerator(com.eveningoutpost.dexdrip.watch.miband.Firmware.WatchFaceGenerator) AlertPlayer(com.eveningoutpost.dexdrip.UtilityModels.AlertPlayer) PoorMansConcurrentLinkedDeque(com.eveningoutpost.dexdrip.utils.framework.PoorMansConcurrentLinkedDeque) TimeUnit(java.util.concurrent.TimeUnit) MIBAND_NOTIFY_TYPE_MESSAGE(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_MESSAGE) OperationCodes(com.eveningoutpost.dexdrip.watch.miband.message.OperationCodes) UserError(com.eveningoutpost.dexdrip.Models.UserError) MIBAND_NOTIFY_TYPE_CALL(com.eveningoutpost.dexdrip.watch.miband.Const.MIBAND_NOTIFY_TYPE_CALL) JoH.emptyString(com.eveningoutpost.dexdrip.Models.JoH.emptyString) TimeoutException(java.util.concurrent.TimeoutException) BleCannotSetCharacteristicNotificationException(com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException) BleCharacteristicNotFoundException(com.polidea.rxandroidble2.exceptions.BleCharacteristicNotFoundException) BleDisconnectedException(com.polidea.rxandroidble2.exceptions.BleDisconnectedException) SuppressLint(android.annotation.SuppressLint)

Aggregations

SuppressLint (android.annotation.SuppressLint)12 RxBleConnection (com.polidea.rxandroidble2.RxBleConnection)12 Date (java.util.Date)12 PowerManager (android.os.PowerManager)10 BgReading (com.eveningoutpost.dexdrip.Models.BgReading)10 JoH (com.eveningoutpost.dexdrip.Models.JoH)10 UserError (com.eveningoutpost.dexdrip.Models.UserError)10 R (com.eveningoutpost.dexdrip.R)10 Constants (com.eveningoutpost.dexdrip.UtilityModels.Constants)10 Inevitable (com.eveningoutpost.dexdrip.UtilityModels.Inevitable)10 PendingIntent (android.app.PendingIntent)8 BluetoothGattCharacteristic (android.bluetooth.BluetoothGattCharacteristic)8 BluetoothGattService (android.bluetooth.BluetoothGattService)8 Intent (android.content.Intent)8 MediaPlayer (android.media.MediaPlayer)8 Pair (android.util.Pair)8 ActiveBgAlert (com.eveningoutpost.dexdrip.Models.ActiveBgAlert)8 HeartRate (com.eveningoutpost.dexdrip.Models.HeartRate)8 JoH.bytesToHex (com.eveningoutpost.dexdrip.Models.JoH.bytesToHex)8 JoH.emptyString (com.eveningoutpost.dexdrip.Models.JoH.emptyString)8