1

Trying to get data from a BLE blood pressure device. Docs say that the date/time must be synced each time the device is connected. Code:

interactionSub = Observable.concat(  
        deviceConnection
                .writeCharacteristic( ReactiveBluetoothHelpers.DATE_TIME_CHARACTERISTIC_UUID, testDateTime )
                .doOnSubscribe(() -> Log.d(TAG, "doOnSubscribe called inside writeCharacteristic!"))
                .doOnError(Error -> Log.e(TAG, "doOnError called inside writeCharacteristic. " + Error.getMessage()))
                .doOnNext(bytes -> Log.d(TAG, "doOnNext called inside writeCharacteristic."))
                .delay( 500L, TimeUnit.MILLISECONDS )  
                .ignoreElements(), 
        deviceConnection
                .setupIndication( ReactiveBluetoothHelpers.BLOOD_PRESSURE_MEASUREMENT_UUID )
                .doOnNext( indicationObservable -> {
                    Log.d(TAG, "Blood Pressure measurement indication has been set up.");
                } )
                .flatMap(indicationObservable -> indicationObservable) // 
)  // end of concat
        .subscribe(
                this::handleBpMeasurement,
                this::handleBpMeasurementError
        );

The device connects and is subscribed but the attempt to write the Characteristic causes an error. The error message from the BleDisconnectedException is just "Disconnected from F4:5E:AB:10:DF:5C" without explanation.

I can't imagine where this error is coming from. The test date/time I'm trying to write has valid values for year (16-bit little-endian) and the other 1-byte quantities.

Typical log sequence:

12-04 15:47:46.617 16544-16612/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue:   QUEUED ConnectOperation(13884208)
12-04 15:47:46.618 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: unregisterApp() - mClientIf=8
12-04 15:47:46.621 16544-16565/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue: FINISHED DisconnectOperation(252854751)
12-04 15:47:46.624 16544-16565/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue:  STARTED ConnectOperation(13884208)
12-04 15:47:46.630 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: connect() - device: F4:5E:AB:10:DF:5C, auto: false
12-04 15:47:46.630 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: registerApp()
12-04 15:47:46.630 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: registerApp() - UUID=91617ce4-e91f-4117-acd4-95a1b2acbf29
12-04 15:47:46.633 16544-16575/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: onClientRegistered() - status=0 clientIf=8
12-04 15:47:47.042 16544-16575/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: onClientConnectionState() - status=0 clientIf=8 device=F4:5E:AB:10:DF:5C
12-04 15:47:47.043 16544-16575/com.calderadev.truecareccm.truecareservice D/RxBle#BluetoothGatt: onConnectionStateChange newState=2 status=0
12-04 15:47:47.044 16544-16575/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: onClientConnectionState() - status=62 clientIf=8 device=F4:5E:AB:10:DF:5C
12-04 15:47:47.044 16544-16575/com.calderadev.truecareccm.truecareservice D/RxBle#BluetoothGatt: onConnectionStateChange newState=0 status=62
12-04 15:47:47.045 16544-16575/com.calderadev.truecareccm.truecareservice I/RxBle#ConnectionOperationQueue: Connection operations queue to be terminated (F4:5E:AB:10:DF:5C)
12-04 15:47:47.047 16544-16565/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue: FINISHED ConnectOperation(13884208)
12-04 15:47:47.054 16544-16612/com.calderadev.truecareccm.truecareservice D/BPMonitor: We have connected to A&D_UA-651BLE_10DF5C with MAC F4:5E:AB:10:DF:5C
12-04 15:47:47.062 16544-16611/com.calderadev.truecareccm.truecareservice D/RxBle#Executors$RunnableAdapter: Terminated.
12-04 15:47:47.083 16544-16612/com.calderadev.truecareccm.truecareservice D/BPMonitor: doOnSubscribe called inside writeCharacteristic!
12-04 15:47:47.100 16544-16612/com.calderadev.truecareccm.truecareservice E/BPMonitor: doOnError called inside writeCharacteristic. Disconnected from F4:5E:AB:10:DF:5C
12-04 15:47:47.118 16544-16612/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue:   QUEUED DisconnectOperation(246198672)
12-04 15:47:47.120 16544-16565/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue:  STARTED DisconnectOperation(246198672)
12-04 15:47:47.121 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothManager: getConnectionState()
12-04 15:47:47.121 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothManager: getConnectedDevices
12-04 15:47:47.125 16544-16612/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue:   QUEUED ConnectOperation(589767105)
12-04 15:47:47.125 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: close()
12-04 15:47:47.127 16544-16571/com.calderadev.truecareccm.truecareservice D/BluetoothGatt: unregisterApp() - mClientIf=8
12-04 15:47:47.131 16544-16565/com.calderadev.truecareccm.truecareservice D/RxBle#ClientOperationQueue: FINISHED DisconnectOperation(246198672)
Robert Lewis
  • 1,847
  • 2
  • 18
  • 43

1 Answers1

1

As you can see in the logs the onConnectionStateChange() is called with status=62 which corresponds to 0x3E. The Android Sources point to:

#define GATT_CONN_FAIL_ESTABLISH    HCI_ERR_CONN_FAILED_ESTABLISHMENT /* 0x03E connection fail to establish  */

So it seems that the connection is not really established on the lower layers of the OS though it is reported as connected first:

12-04 15:47:47.043 16544-16575/com.calderadev.truecareccm.truecareservice D/RxBle#BluetoothGatt: onConnectionStateChange newState=2 status=0
12-04 15:47:47.044 16544-16575/com.calderadev.truecareccm.truecareservice D/RxBle#BluetoothGatt: onConnectionStateChange newState=0 status=62
Dariusz Seweryn
  • 3,212
  • 2
  • 14
  • 21
  • Interesting, but what can I do about it? Is it likely a failure in the phone's BLE stack? I have an earlier version of the code (without the `Observable.concat()`) that at least allows `setupIndication()` to work, although the peripheral then reports wrong data, seemingly cached from an earlier measurement, which would be expected if the attempt to set the device's internal clock with `writeCharacteristic()` fails. Thus, in the earlier version, `writeCharacteristic()` doesn't work but at least doesn't cause the connection to be broken. Maybe I'll replace `concat()` with `concatDelayError()`. – Robert Lewis Dec 05 '17 at 15:22
  • `Is it likely a failure in the phone's BLE stack?` Definitely something is going on the lower level than Android BLE API. Currently the characteristic write is not even executed. I doubt that there is anything you could do from the application side to help. You could check the HCI logs if they contain anything interesting. It may also be that your peripheral is now failing. HCI log or sniffer logs could tell more. – Dariusz Seweryn Dec 05 '17 at 17:41
  • Could this be explained by `writeCharacteristic()` writing an illegal value to the device, causing it to immediately disconnect? Logging indicates that the Observable was subscribed briefly before disconnecting. – Robert Lewis Dec 05 '17 at 22:07
  • No. As you can see in the logs there is absolutely no indication that characteristic write was executed. – Dariusz Seweryn Dec 05 '17 at 22:10
  • Don't know what to say, but when I used the correct characteristic UUID and correctly-formatted data, it worked. I guess if you have the wrong UUID then it won't execute? (I was trying to write the standard Date/Time characteristic but discovered that for some reason the device has a custom service for this purpose.) – Robert Lewis Dec 05 '17 at 23:51
  • If you try to use a characteristic with `UUID` that was not discovered you would get `BleCharacteristicNotFoundException`. – Dariusz Seweryn Dec 06 '17 at 09:14
  • The Date/Time characteristic is documented to exist, but it appears that writing to it fails (it's difficult to interpret the documentation). Setting the date with the alternative custom characteristic worked. So the standard UUID may have been discovered but for some reason writing to it was disabled. – Robert Lewis Dec 06 '17 at 15:53