com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException Java Examples

The following examples show how to use com.polidea.rxandroidble2.exceptions.BleCannotSetCharacteristicNotificationException. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: NotificationAndIndicationManager.java    From RxAndroidBle with Apache License 2.0 5 votes vote down vote up
@NonNull
static Completable setCharacteristicNotification(final BluetoothGatt bluetoothGatt,
                                                 final BluetoothGattCharacteristic characteristic,
                                                 final boolean isNotificationEnabled) {
    return Completable.fromAction(new Action() {
        @Override
        public void run() {
            if (!bluetoothGatt.setCharacteristicNotification(characteristic, isNotificationEnabled)) {
                throw new BleCannotSetCharacteristicNotificationException(
                        characteristic, BleCannotSetCharacteristicNotificationException.CANNOT_SET_LOCAL_NOTIFICATION, null
                );
            }
        }
    });
}
 
Example #2
Source File: NotificationAndIndicationManager.java    From RxAndroidBle with Apache License 2.0 5 votes vote down vote up
@NonNull
static Completable writeClientCharacteristicConfig(
        final BluetoothGattCharacteristic bluetoothGattCharacteristic,
        final DescriptorWriter descriptorWriter,
        final byte[] value
) {
    final BluetoothGattDescriptor descriptor = bluetoothGattCharacteristic.getDescriptor(CLIENT_CHARACTERISTIC_CONFIG_UUID);
    if (descriptor == null) {
        return Completable.error(new BleCannotSetCharacteristicNotificationException(
                bluetoothGattCharacteristic,
                BleCannotSetCharacteristicNotificationException.CANNOT_FIND_CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR,
                null
        ));
    }

    return descriptorWriter.writeDescriptor(descriptor, value)
            .onErrorResumeNext(new Function<Throwable, CompletableSource>() {
                @Override
                public CompletableSource apply(Throwable throwable) {
                    return Completable.error(new BleCannotSetCharacteristicNotificationException(
                            bluetoothGattCharacteristic,
                            BleCannotSetCharacteristicNotificationException.CANNOT_WRITE_CLIENT_CHARACTERISTIC_CONFIG_DESCRIPTOR,
                            throwable
                    ));
                }
            });
}
 
Example #3
Source File: Ob1G5StateMachine.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
public static boolean doCheckAuth(Ob1G5CollectionService parent, RxBleConnection connection) {

    if (connection == null) return false;
    parent.msg("Authorizing");

    if (parent.android_wear) {
        speakSlowly = true;
        UserError.Log.d(TAG, "Setting speak slowly to true"); // WARN should be reactive or on named devices
    }

    final AuthRequestTxMessage authRequest = new AuthRequestTxMessage(getTokenSize(), usingAlt());
    UserError.Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));

    connection.setupNotification(Authentication)
            // .timeout(10, TimeUnit.SECONDS)
            .timeout(15, TimeUnit.SECONDS) // WARN
            // .observeOn(Schedulers.newThread()) // needed?
            .doOnNext(notificationObservable -> {
                connection.writeCharacteristic(Authentication, nn(authRequest.byteSequence))
                        .subscribe(
                                characteristicValue -> {
                                    // Characteristic value confirmed.
                                    if (d)
                                        UserError.Log.d(TAG, "Wrote authrequest, got: " + JoH.bytesToHex(characteristicValue));
                                    speakSlowly();
                                    connection.readCharacteristic(Authentication).subscribe(
                                            readValue -> {
                                                authenticationProcessor(parent, connection, readValue);
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not read after AuthRequestTX: " + throwable);
                                            });
                                    //parent.background_automata();
                                },
                                throwable -> {
                                    UserError.Log.e(TAG, "Could not write AuthRequestTX: " + throwable);
                                    parent.incrementErrors();
                                }

                        );
            }).flatMap(notificationObservable -> notificationObservable)
            //.timeout(5, TimeUnit.SECONDS)
            //.observeOn(Schedulers.newThread())
            .subscribe(bytes -> {
                // incoming notifications
                UserError.Log.d(TAG, "Received Authentication notification bytes: " + JoH.bytesToHex(bytes));
                authenticationProcessor(parent, connection, bytes);

            }, throwable -> {
                if (!(throwable instanceof OperationSuccess)) {
                    if (((parent.getState() == Ob1G5CollectionService.STATE.CLOSED)
                            || (parent.getState() == Ob1G5CollectionService.STATE.CLOSE))
                            && (throwable instanceof BleDisconnectedException)) {
                        UserError.Log.d(TAG, "normal authentication notification throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.connectionStateChange(CLOSED_OK_TEXT);
                    } else if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) && (throwable instanceof TimeoutException)) {
                        // TODO Trigger on Error count / Android wear metric
                        // UserError.Log.e(TAG,"Attempting to reset/create bond due to: "+throwable);
                        // parent.reset_bond(true);
                        // parent.unBond(); // WARN
                    } else {
                        UserError.Log.e(TAG, "authentication notification  throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.incrementErrors();
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException
                                || throwable instanceof BleGattCharacteristicException) {
                            parent.tryGattRefresh();
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                    if ((throwable instanceof BleDisconnectedException) || (throwable instanceof TimeoutException)) {
                        if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) || (parent.getState() == Ob1G5CollectionService.STATE.CHECK_AUTH)) {

                            if (parent.getState() == Ob1G5CollectionService.STATE.BOND) {
                                UserError.Log.d(TAG, "SLEEPING BEFORE RECONNECT");
                                threadSleep(15000);
                            }
                            UserError.Log.d(TAG, "REQUESTING RECONNECT");
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                }
            });
    return true;
}
 
Example #4
Source File: MiBandService.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
private void authPhase() {
    extendWakeLock(30000);
    RxBleConnection connection = I.connection;
    if (d)
        UserError.Log.d(TAG, "Authorizing");
    if (I.connection == null) {
        if (d)
            UserError.Log.d(TAG, "Cannot enable as connection is null!");
        return;
    }

    String authKey = MiBand.getPersistentAuthKey();
    if (MiBand.getMibandType() == MI_BAND4) {
        if (authKey.isEmpty()) {
            authKey = MiBand.getAuthKey();
            if (authKey.isEmpty()) {
                authKey = AuthMessages.getAuthCodeFromFilesSystem(MiBand.getMac());
            }
            if (!AuthMessages.isValidAuthKey(authKey)) {
                JoH.static_toast_long("Wrong miband authorization key, please recheck a key and try to reconnect again");
                changeState(AUTHORIZE_FAILED);
                return;
            } else {
                MiBand.setAuthKey(authKey);
            }
        }
    }
    if (!AuthMessages.isValidAuthKey(authKey)) {
        authKey = "";
    }
    if (d)
        UserError.Log.d(TAG, "authKey: " + authKey);

    authorisation = new AuthMessages(MiBand.getMibandType(), authKey);
    if (d)
        UserError.Log.d(TAG, "localKey: " + JoH.bytesToHex(authorisation.getLocalKey()));
    authSubscription = new Subscription(
            connection.setupNotification(authorisation.getCharacteristicUUID())
                    .timeout(20, TimeUnit.SECONDS) // WARN
                    // .observeOn(Schedulers.newThread()) // needed?
                    .doOnNext(notificationObservable -> {
                                if (d)
                                    UserError.Log.d(TAG, "Notification for auth enabled");
                                if (MiBand.isAuthenticated()) {
                                    connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()) //get random key from band
                                            .subscribe(val -> {
                                                if (d)
                                                    UserError.Log.d(TAG, "Wrote getAuthKeyRequest: " + JoH.bytesToHex(val));
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not getAuthKeyRequest: " + throwable);
                                            });
                                } else {
                                    connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthCommand())
                                            .subscribe(characteristicValue -> {
                                                        UserError.Log.d(TAG, "Wrote getAuthCommand, got: " + JoH.bytesToHex(characteristicValue));
                                                    },
                                                    throwable -> {
                                                        UserError.Log.e(TAG, "Could not write getAuthCommand: " + throwable);
                                                    }
                                            );
                                }

                            }
                    )
                    .flatMap(notificationObservable -> notificationObservable)
                    .subscribe(bytes -> {
                        // incoming notifications
                        if (d)
                            UserError.Log.d(TAG, "Received auth notification bytes: " + bytesToHex(bytes));
                        ProcessAuthCommands(connection, bytes);
                        // changeNextState();
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                        } else if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                        } else if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                        } else if (throwable instanceof TimeoutException) {
                            //check if it is normal timeout
                            if (!MiBand.isAuthenticated()) {
                                String errorText = "MiBand authentication failed due to authentication timeout. When your Mi Band vibrates and blinks, tap it a few times in a row.";
                                UserError.Log.d(TAG, errorText);
                                JoH.static_toast_long(errorText);
                            }
                        }
                        if (authSubscription != null) {
                            authSubscription.unsubscribe();
                        }
                        changeState(CLOSE);
                    }));
}
 
Example #5
Source File: MiBandService.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
private void installWatchface() {
    //TODO decrease display brightness before uploading watchface to minimize battery consumption
    RxBleConnection connection = I.connection;
    if (d)
        UserError.Log.d(TAG, "Install WatchFace");
    if (I.connection == null) {
        if (d)
            UserError.Log.d(TAG, "Cannot enable as connection is null!");
        return;
    }
    try {
        WatchFaceGenerator wfGen = new WatchFaceGenerator(getBaseContext().getAssets());
        byte[] fwArray = wfGen.genWatchFace();
        if (fwArray == null || fwArray.length == 0) {
            resetFirmwareState(false, "Empty image");
            return;
        }
        firmware = new FirmwareOperations(fwArray);
    } catch (Exception e) {
        resetFirmwareState(false, "FirmwareOperations error " + e.getMessage());
        return;
    }
    if (d)
        UserError.Log.d(TAG, "Begin uploading Watchface, lenght: " + firmware.getSize());
    if (d)
        UserError.Log.d(TAG, "Requesting to enable notifications for installWatchface");
    watchfaceSubscription = new Subscription(
            connection.setupNotification(firmware.getFirmwareCharacteristicUUID())
                    .timeout(400, TimeUnit.SECONDS) // WARN
                    .doOnNext(notificationObservable -> {
                                if (d)
                                    UserError.Log.d(TAG, "Notification for firmware enabled");
                                firmware.nextSequence();
                                processFirmwareCommands(null, true);
                            }
                    )
                    .flatMap(notificationObservable -> notificationObservable)
                    .subscribe(bytes -> {
                        // incoming notifications
                        if (d)
                            UserError.Log.d(TAG, "Received firmware notification bytes: " + bytesToHex(bytes));
                        processFirmwareCommands(bytes, false);
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in firmware Notification: " + throwable);
                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                        } else if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                        } else if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                        } else if (throwable instanceof TimeoutException) {
                            UserError.Log.d(TAG, "Timeout");
                        }
                        resetFirmwareState(false);
                    }));
}
 
Example #6
Source File: BlueJayService.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
private void enableNotifications() {
    UserError.Log.d(TAG, "enableNotifications called()");
    if (I.isNotificationEnabled) {
        UserError.Log.d(TAG, "Notifications already enabled");
        changeNextState();
        return;
    }
    if (notificationSubscription != null) {
        notificationSubscription.unsubscribe();
    }
    JoH.threadSleep(500);
    UserError.Log.d(TAG, "Requesting to enable notifications");
    notificationSubscription = new Subscription(
            I.connection.setupNotification(THINJAM_WRITE)
                    // .timeout(15, TimeUnit.SECONDS) // WARN
                    // .observeOn(Schedulers.newThread()) // needed?
                    .doOnNext(notificationObservable -> {

                                UserError.Log.d(TAG, "Notifications enabled");
                                I.connection.writeCharacteristic(THINJAM_BULK, new byte[]{0x55});

                                JoH.threadSleep(500); // Debug sleep to make sure notifications are actually enabled???
                                I.isNotificationEnabled = true;
                                changeNextState();
                            }

                    ).flatMap(notificationObservable -> notificationObservable)
                    //.timeout(5, TimeUnit.SECONDS)
                    .observeOn(Schedulers.newThread())
                    .subscribe(bytes -> {
                        // incoming notifications
                        UserError.Log.d(TAG, "Received notification bytes: " + JoH.bytesToHex(bytes));
                        val pushRx = PushRx.parse(bytes);
                        if (pushRx != null) {
                            UserError.Log.d(TAG, "Received PushRX: " + pushRx.toS());
                            getInfo().processPushRx(pushRx);
                            processPushRxActions(pushRx);
                        } else if (bytes[0] == 0x06) {
                            // TODO move this to parsed response
                            final int replyParam = ((int) bytes[1]) & 0xff;
                            if (replyParam == 0) {
                                UserError.Log.d(TAG, "Bulk up success reply marker received! - removing queue head item");
                                commandQueue.poll(); // removes first item from the queue which should be the one we just processed!
                                UserError.Log.d(TAG, "Scheduling immediate run of queue");
                                Inevitable.kill("tj-next-queue"); // remove timeout retry task
                                Inevitable.task("tj-next-queue", 0, this::processQueue);
                            } else {
                                revisedOffset = replyParam;
                                UserError.Log.d(TAG, "Bulk up failure at: " + revisedOffset); // race condition on display
                            }
                        } else if (bytes[0] == (byte) 0xFE) {
                            audioStreamCallBack(bytes);
                        } else {
                            if (ThinJamActivity.isD()) {
                                notificationString.append(new String(bytes));
                                Inevitable.task("tj update notifi", 250, new Runnable() {
                                    @Override
                                    public void run() {
                                        stringObservableField.set(notificationString.toString());
                                    }
                                });
                            }
                        }
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
                        I.isNotificationEnabled = false;

                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                            debug.processTestSuite("logcharerror");
                            tryGattRefresh(getI().connection);
                        }
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                            changeState(CLOSE);
                        }
                        if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                            changeState(CLOSE);
                        }

                    }));
}
 
Example #7
Source File: Ob1G5StateMachine.java    From xDrip with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
public static boolean doCheckAuth(Ob1G5CollectionService parent, RxBleConnection connection) {

    if (connection == null) return false;
    parent.msg("Authorizing");

    if (parent.android_wear) {
        speakSlowly = true;
        UserError.Log.d(TAG, "Setting speak slowly to true"); // WARN should be reactive or on named devices
    }

    final AuthRequestTxMessage authRequest = new AuthRequestTxMessage(getTokenSize(), usingAlt());
    UserError.Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));

    connection.setupNotification(Authentication)
            // .timeout(10, TimeUnit.SECONDS)
            .timeout(15, TimeUnit.SECONDS) // WARN
            // .observeOn(Schedulers.newThread()) // needed?
            .doOnNext(notificationObservable -> {
                connection.writeCharacteristic(Authentication, nn(authRequest.byteSequence))
                        .subscribe(
                                characteristicValue -> {
                                    // Characteristic value confirmed.
                                    if (d)
                                        UserError.Log.d(TAG, "Wrote authrequest, got: " + JoH.bytesToHex(characteristicValue));
                                    speakSlowly();
                                    connection.readCharacteristic(Authentication).subscribe(
                                            readValue -> {
                                                authenticationProcessor(parent, connection, readValue);
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not read after AuthRequestTX: " + throwable);
                                            });
                                    //parent.background_automata();
                                },
                                throwable -> {
                                    UserError.Log.e(TAG, "Could not write AuthRequestTX: " + throwable);
                                    parent.incrementErrors();
                                }

                        );
            }).flatMap(notificationObservable -> notificationObservable)
            //.timeout(5, TimeUnit.SECONDS)
            //.observeOn(Schedulers.newThread())
            .subscribe(bytes -> {
                // incoming notifications
                UserError.Log.d(TAG, "Received Authentication notification bytes: " + JoH.bytesToHex(bytes));
                authenticationProcessor(parent, connection, bytes);

            }, throwable -> {
                if (!(throwable instanceof OperationSuccess)) {
                    if (((parent.getState() == Ob1G5CollectionService.STATE.CLOSED)
                            || (parent.getState() == Ob1G5CollectionService.STATE.CLOSE))
                            && (throwable instanceof BleDisconnectedException)) {
                        UserError.Log.d(TAG, "normal authentication notification throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.connectionStateChange(CLOSED_OK_TEXT);
                    } else if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) && (throwable instanceof TimeoutException)) {
                        // TODO Trigger on Error count / Android wear metric
                        // UserError.Log.e(TAG,"Attempting to reset/create bond due to: "+throwable);
                        // parent.reset_bond(true);
                        // parent.unBond(); // WARN
                    } else {
                        UserError.Log.e(TAG, "authentication notification  throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.incrementErrors();
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException
                                || throwable instanceof BleGattCharacteristicException) {
                            parent.tryGattRefresh();
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                    if ((throwable instanceof BleDisconnectedException) || (throwable instanceof TimeoutException)) {
                        if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) || (parent.getState() == Ob1G5CollectionService.STATE.CHECK_AUTH)) {

                            if (parent.getState() == Ob1G5CollectionService.STATE.BOND) {
                                UserError.Log.d(TAG, "SLEEPING BEFORE RECONNECT");
                                threadSleep(15000);
                            }
                            UserError.Log.d(TAG, "REQUESTING RECONNECT");
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                }
            });
    return true;
}
 
Example #8
Source File: Ob1G5StateMachine.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
public static boolean doCheckAuth(Ob1G5CollectionService parent, RxBleConnection connection) {

    if (connection == null) return false;
    parent.msg("Authorizing");

    if (parent.android_wear) {
        speakSlowly = true;
        UserError.Log.d(TAG, "Setting speak slowly to true"); // WARN should be reactive or on named devices
    }

    final AuthRequestTxMessage authRequest = new AuthRequestTxMessage(getTokenSize(), usingAlt());
    UserError.Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));

    connection.setupNotification(Authentication)
            // .timeout(10, TimeUnit.SECONDS)
            .timeout(15, TimeUnit.SECONDS) // WARN
            // .observeOn(Schedulers.newThread()) // needed?
            .doOnNext(notificationObservable -> {
                connection.writeCharacteristic(Authentication, nn(authRequest.byteSequence))
                        .subscribe(
                                characteristicValue -> {
                                    // Characteristic value confirmed.
                                    if (d)
                                        UserError.Log.d(TAG, "Wrote authrequest, got: " + JoH.bytesToHex(characteristicValue));
                                    speakSlowly();
                                    connection.readCharacteristic(Authentication).subscribe(
                                            readValue -> {
                                                authenticationProcessor(parent, connection, readValue);
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not read after AuthRequestTX: " + throwable);
                                            });
                                    //parent.background_automata();
                                },
                                throwable -> {
                                    UserError.Log.e(TAG, "Could not write AuthRequestTX: " + throwable);
                                    parent.incrementErrors();
                                }

                        );
            }).flatMap(notificationObservable -> notificationObservable)
            //.timeout(5, TimeUnit.SECONDS)
            //.observeOn(Schedulers.newThread())
            .subscribe(bytes -> {
                // incoming notifications
                UserError.Log.d(TAG, "Received Authentication notification bytes: " + JoH.bytesToHex(bytes));
                authenticationProcessor(parent, connection, bytes);

            }, throwable -> {
                if (!(throwable instanceof OperationSuccess)) {
                    if (((parent.getState() == Ob1G5CollectionService.STATE.CLOSED)
                            || (parent.getState() == Ob1G5CollectionService.STATE.CLOSE))
                            && (throwable instanceof BleDisconnectedException)) {
                        UserError.Log.d(TAG, "normal authentication notification throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.connectionStateChange(CLOSED_OK_TEXT);
                    } else if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) && (throwable instanceof TimeoutException)) {
                        // TODO Trigger on Error count / Android wear metric
                        // UserError.Log.e(TAG,"Attempting to reset/create bond due to: "+throwable);
                        // parent.reset_bond(true);
                        // parent.unBond(); // WARN
                    } else {
                        UserError.Log.e(TAG, "authentication notification  throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.incrementErrors();
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException
                                || throwable instanceof BleGattCharacteristicException) {
                            parent.tryGattRefresh();
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                    if ((throwable instanceof BleDisconnectedException) || (throwable instanceof TimeoutException)) {
                        if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) || (parent.getState() == Ob1G5CollectionService.STATE.CHECK_AUTH)) {

                            if (parent.getState() == Ob1G5CollectionService.STATE.BOND) {
                                UserError.Log.d(TAG, "SLEEPING BEFORE RECONNECT");
                                threadSleep(15000);
                            }
                            UserError.Log.d(TAG, "REQUESTING RECONNECT");
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                }
            });
    return true;
}
 
Example #9
Source File: MiBandService.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
private void authPhase() {
    extendWakeLock(30000);
    RxBleConnection connection = I.connection;
    if (d)
        UserError.Log.d(TAG, "Authorizing");
    if (I.connection == null) {
        if (d)
            UserError.Log.d(TAG, "Cannot enable as connection is null!");
        return;
    }

    String authKey = MiBand.getPersistentAuthKey();
    if (MiBand.getMibandType() == MI_BAND4) {
        if (authKey.isEmpty()) {
            authKey = MiBand.getAuthKey();
            if (authKey.isEmpty()) {
                authKey = AuthMessages.getAuthCodeFromFilesSystem(MiBand.getMac());
            }
            if (!AuthMessages.isValidAuthKey(authKey)) {
                JoH.static_toast_long("Wrong miband authorization key, please recheck a key and try to reconnect again");
                changeState(AUTHORIZE_FAILED);
                return;
            } else {
                MiBand.setAuthKey(authKey);
            }
        }
    }
    if (!AuthMessages.isValidAuthKey(authKey)) {
        authKey = "";
    }
    if (d)
        UserError.Log.d(TAG, "authKey: " + authKey);

    authorisation = new AuthMessages(MiBand.getMibandType(), authKey);
    if (d)
        UserError.Log.d(TAG, "localKey: " + JoH.bytesToHex(authorisation.getLocalKey()));
    authSubscription = new Subscription(
            connection.setupNotification(authorisation.getCharacteristicUUID())
                    .timeout(20, TimeUnit.SECONDS) // WARN
                    // .observeOn(Schedulers.newThread()) // needed?
                    .doOnNext(notificationObservable -> {
                                if (d)
                                    UserError.Log.d(TAG, "Notification for auth enabled");
                                if (MiBand.isAuthenticated()) {
                                    connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthKeyRequest()) //get random key from band
                                            .subscribe(val -> {
                                                if (d)
                                                    UserError.Log.d(TAG, "Wrote getAuthKeyRequest: " + JoH.bytesToHex(val));
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not getAuthKeyRequest: " + throwable);
                                            });
                                } else {
                                    connection.writeCharacteristic(authorisation.getCharacteristicUUID(), authorisation.getAuthCommand())
                                            .subscribe(characteristicValue -> {
                                                        UserError.Log.d(TAG, "Wrote getAuthCommand, got: " + JoH.bytesToHex(characteristicValue));
                                                    },
                                                    throwable -> {
                                                        UserError.Log.e(TAG, "Could not write getAuthCommand: " + throwable);
                                                    }
                                            );
                                }

                            }
                    )
                    .flatMap(notificationObservable -> notificationObservable)
                    .subscribe(bytes -> {
                        // incoming notifications
                        if (d)
                            UserError.Log.d(TAG, "Received auth notification bytes: " + bytesToHex(bytes));
                        ProcessAuthCommands(connection, bytes);
                        // changeNextState();
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                        } else if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                        } else if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                        } else if (throwable instanceof TimeoutException) {
                            //check if it is normal timeout
                            if (!MiBand.isAuthenticated()) {
                                String errorText = "MiBand authentication failed due to authentication timeout. When your Mi Band vibrates and blinks, tap it a few times in a row.";
                                UserError.Log.d(TAG, errorText);
                                JoH.static_toast_long(errorText);
                            }
                        }
                        if (authSubscription != null) {
                            authSubscription.unsubscribe();
                        }
                        changeState(CLOSE);
                    }));
}
 
Example #10
Source File: MiBandService.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
private void installWatchface() {
    //TODO decrease display brightness before uploading watchface to minimize battery consumption
    RxBleConnection connection = I.connection;
    if (d)
        UserError.Log.d(TAG, "Install WatchFace");
    if (I.connection == null) {
        if (d)
            UserError.Log.d(TAG, "Cannot enable as connection is null!");
        return;
    }
    try {
        WatchFaceGenerator wfGen = new WatchFaceGenerator(getBaseContext().getAssets());
        byte[] fwArray = wfGen.genWatchFace();
        if (fwArray == null || fwArray.length == 0) {
            resetFirmwareState(false, "Empty image");
            return;
        }
        firmware = new FirmwareOperations(fwArray);
    } catch (Exception e) {
        resetFirmwareState(false, "FirmwareOperations error " + e.getMessage());
        return;
    }
    if (d)
        UserError.Log.d(TAG, "Begin uploading Watchface, lenght: " + firmware.getSize());
    if (d)
        UserError.Log.d(TAG, "Requesting to enable notifications for installWatchface");
    watchfaceSubscription = new Subscription(
            connection.setupNotification(firmware.getFirmwareCharacteristicUUID())
                    .timeout(400, TimeUnit.SECONDS) // WARN
                    .doOnNext(notificationObservable -> {
                                if (d)
                                    UserError.Log.d(TAG, "Notification for firmware enabled");
                                firmware.nextSequence();
                                processFirmwareCommands(null, true);
                            }
                    )
                    .flatMap(notificationObservable -> notificationObservable)
                    .subscribe(bytes -> {
                        // incoming notifications
                        if (d)
                            UserError.Log.d(TAG, "Received firmware notification bytes: " + bytesToHex(bytes));
                        processFirmwareCommands(bytes, false);
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in firmware Notification: " + throwable);
                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                        } else if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                        } else if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                        } else if (throwable instanceof TimeoutException) {
                            UserError.Log.d(TAG, "Timeout");
                        }
                        resetFirmwareState(false);
                    }));
}
 
Example #11
Source File: BlueJayService.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
private void enableNotifications() {
    UserError.Log.d(TAG, "enableNotifications called()");
    if (I.isNotificationEnabled) {
        UserError.Log.d(TAG, "Notifications already enabled");
        changeNextState();
        return;
    }
    if (notificationSubscription != null) {
        notificationSubscription.unsubscribe();
    }
    JoH.threadSleep(500);
    UserError.Log.d(TAG, "Requesting to enable notifications");
    notificationSubscription = new Subscription(
            I.connection.setupNotification(THINJAM_WRITE)
                    // .timeout(15, TimeUnit.SECONDS) // WARN
                    // .observeOn(Schedulers.newThread()) // needed?
                    .doOnNext(notificationObservable -> {

                                UserError.Log.d(TAG, "Notifications enabled");
                                I.connection.writeCharacteristic(THINJAM_BULK, new byte[]{0x55});

                                JoH.threadSleep(500); // Debug sleep to make sure notifications are actually enabled???
                                I.isNotificationEnabled = true;
                                changeNextState();
                            }

                    ).flatMap(notificationObservable -> notificationObservable)
                    //.timeout(5, TimeUnit.SECONDS)
                    .observeOn(Schedulers.newThread())
                    .subscribe(bytes -> {
                        // incoming notifications
                        UserError.Log.d(TAG, "Received notification bytes: " + JoH.bytesToHex(bytes));
                        val pushRx = PushRx.parse(bytes);
                        if (pushRx != null) {
                            UserError.Log.d(TAG, "Received PushRX: " + pushRx.toS());
                            getInfo().processPushRx(pushRx);
                            processPushRxActions(pushRx);
                        } else if (bytes[0] == 0x06) {
                            // TODO move this to parsed response
                            final int replyParam = ((int) bytes[1]) & 0xff;
                            if (replyParam == 0) {
                                UserError.Log.d(TAG, "Bulk up success reply marker received! - removing queue head item");
                                commandQueue.poll(); // removes first item from the queue which should be the one we just processed!
                                UserError.Log.d(TAG, "Scheduling immediate run of queue");
                                Inevitable.kill("tj-next-queue"); // remove timeout retry task
                                Inevitable.task("tj-next-queue", 0, this::processQueue);
                            } else {
                                revisedOffset = replyParam;
                                UserError.Log.d(TAG, "Bulk up failure at: " + revisedOffset); // race condition on display
                            }
                        } else if (bytes[0] == (byte) 0xFE) {
                            audioStreamCallBack(bytes);
                        } else {
                            if (ThinJamActivity.isD()) {
                                notificationString.append(new String(bytes));
                                Inevitable.task("tj update notifi", 250, new Runnable() {
                                    @Override
                                    public void run() {
                                        stringObservableField.set(notificationString.toString());
                                    }
                                });
                            }
                        }
                    }, throwable -> {
                        UserError.Log.d(TAG, "Throwable in Record Notification: " + throwable);
                        I.isNotificationEnabled = false;

                        if (throwable instanceof BleCharacteristicNotFoundException) {
                            // maybe legacy - ignore for now but needs better handling
                            UserError.Log.d(TAG, "Characteristic not found for notification");
                            debug.processTestSuite("logcharerror");
                            tryGattRefresh(getI().connection);
                        }
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException) {
                            UserError.Log.e(TAG, "Problems setting notifications - disconnecting");
                            changeState(CLOSE);
                        }
                        if (throwable instanceof BleDisconnectedException) {
                            UserError.Log.d(TAG, "Disconnected while enabling notifications");
                            changeState(CLOSE);
                        }

                    }));
}
 
Example #12
Source File: Ob1G5StateMachine.java    From xDrip-plus with GNU General Public License v3.0 4 votes vote down vote up
@SuppressLint("CheckResult")
public static boolean doCheckAuth(Ob1G5CollectionService parent, RxBleConnection connection) {

    if (connection == null) return false;
    parent.msg("Authorizing");

    if (parent.android_wear) {
        speakSlowly = true;
        UserError.Log.d(TAG, "Setting speak slowly to true"); // WARN should be reactive or on named devices
    }

    final AuthRequestTxMessage authRequest = new AuthRequestTxMessage(getTokenSize(), usingAlt());
    UserError.Log.i(TAG, "AuthRequestTX: " + JoH.bytesToHex(authRequest.byteSequence));

    connection.setupNotification(Authentication)
            // .timeout(10, TimeUnit.SECONDS)
            .timeout(15, TimeUnit.SECONDS) // WARN
            // .observeOn(Schedulers.newThread()) // needed?
            .doOnNext(notificationObservable -> {
                connection.writeCharacteristic(Authentication, nn(authRequest.byteSequence))
                        .subscribe(
                                characteristicValue -> {
                                    // Characteristic value confirmed.
                                    if (d)
                                        UserError.Log.d(TAG, "Wrote authrequest, got: " + JoH.bytesToHex(characteristicValue));
                                    speakSlowly();
                                    connection.readCharacteristic(Authentication).subscribe(
                                            readValue -> {
                                                authenticationProcessor(parent, connection, readValue);
                                            }, throwable -> {
                                                UserError.Log.e(TAG, "Could not read after AuthRequestTX: " + throwable);
                                            });
                                    //parent.background_automata();
                                },
                                throwable -> {
                                    UserError.Log.e(TAG, "Could not write AuthRequestTX: " + throwable);
                                    parent.incrementErrors();
                                }

                        );
            }).flatMap(notificationObservable -> notificationObservable)
            //.timeout(5, TimeUnit.SECONDS)
            //.observeOn(Schedulers.newThread())
            .subscribe(bytes -> {
                // incoming notifications
                UserError.Log.d(TAG, "Received Authentication notification bytes: " + JoH.bytesToHex(bytes));
                authenticationProcessor(parent, connection, bytes);

            }, throwable -> {
                if (!(throwable instanceof OperationSuccess)) {
                    if (((parent.getState() == Ob1G5CollectionService.STATE.CLOSED)
                            || (parent.getState() == Ob1G5CollectionService.STATE.CLOSE))
                            && (throwable instanceof BleDisconnectedException)) {
                        UserError.Log.d(TAG, "normal authentication notification throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.connectionStateChange(CLOSED_OK_TEXT);
                    } else if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) && (throwable instanceof TimeoutException)) {
                        // TODO Trigger on Error count / Android wear metric
                        // UserError.Log.e(TAG,"Attempting to reset/create bond due to: "+throwable);
                        // parent.reset_bond(true);
                        // parent.unBond(); // WARN
                    } else {
                        UserError.Log.e(TAG, "authentication notification  throwable: (" + parent.getState() + ") " + throwable + " " + JoH.dateTimeText(tsl()));
                        parent.incrementErrors();
                        if (throwable instanceof BleCannotSetCharacteristicNotificationException
                                || throwable instanceof BleGattCharacteristicException) {
                            parent.tryGattRefresh();
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                    if ((throwable instanceof BleDisconnectedException) || (throwable instanceof TimeoutException)) {
                        if ((parent.getState() == Ob1G5CollectionService.STATE.BOND) || (parent.getState() == Ob1G5CollectionService.STATE.CHECK_AUTH)) {

                            if (parent.getState() == Ob1G5CollectionService.STATE.BOND) {
                                UserError.Log.d(TAG, "SLEEPING BEFORE RECONNECT");
                                threadSleep(15000);
                            }
                            UserError.Log.d(TAG, "REQUESTING RECONNECT");
                            parent.changeState(Ob1G5CollectionService.STATE.SCAN);
                        }
                    }
                }
            });
    return true;
}