Prevent reconnect regardless of disconnect reason



  • We have custom devices that implement a custom app-level protocol. The protocol requires that a reconnect is not attempted if the device goes off-line (battery pulled for instance). Can someone provide a mechanism for preventing a reconnect from ever occurring? I tried using a custom DeviceReconnectFilter but it doesn't seem to be working. When in a transaction, I pull the battery out of the device so communications stops. SweetBlue detects the disconnect but never calls my DeviceReconnectFilter which is attached to the device.

    private DeviceReconnectFilter deviceReconnectFilter = new DeviceReconnectFilter() {
            @Override
            public ConnectFailPlease onConnectFailed(ConnectFailEvent connectFailEvent) {
                // If the connection fails, begin scanning again
                bleService.internalBeginScan();
                return ConnectFailPlease.doNotRetry();
            }
    
            @Override
            public ConnectionLostPlease onConnectionLost(ConnectionLostEvent connectionLostEvent) {
                // If the connection fails, begin scanning again
                bleService.internalBeginScan();
                return ConnectionLostPlease.stopRetrying();
            }
        };
    
        private void connect() {
            // stuff here
            bleDevice.setListener_Reconnect(deviceReconnectFilter);
            // stuff here
        }
    

    This is what I see in my log:

    2019-01-09 13:29:13.511 23855-23869/com.kineteksports.clubhub D/BluetoothGatt: onClientConnectionState() - status=8 clientIf=7 device=60:50:C1:00:33:8C
    2019-01-09 13:29:13.549 23855-23869/com.kineteksports.clubhub W/P_BleDevice_ListenerProcessor [Native]: ABE(23869) onConnectionStateChange() [60:50:C1:00:33:8C] - GATT_CONN_TIMEOUT(8) STATE_DISCONNECTED(0)
    2019-01-09 13:29:13.551 23855-23944/com.kineteksports.clubhub I/P_BleDeviceNativeManager: UPDATE(23944) updateNativeConnectionState() - STATE_DISCONNECTED(0)
    2019-01-09 13:29:13.551 23855-23944/com.kineteksports.clubhub D/BluetoothGatt: close()
    2019-01-09 13:29:13.553 23855-23944/com.kineteksports.clubhub D/BluetoothGatt: unregisterApp() - mClientIf=7
    2019-01-09 13:29:13.562 23855-23944/com.kineteksports.clubhub W/P_DeviceConnectionManager: UPDATE(23944) onDisconnected() - Disconnected implicitly and attemptShortTermReconnect=true
    2019-01-09 13:29:13.563 23855-23944/com.kineteksports.clubhub D/P_BleDeviceImpl: UPDATE(23944) onReconnectingShortTerm() - Entering RECONNECTING_SHORT_TERM state.
    2019-01-09 13:29:13.570 23855-23944/com.kineteksports.clubhub I/BleTransactionImpl: UPDATE(23944) end() - transaction CANCELLED
    

    Seems that I need to set the attemptShortTermReconnect value to false but I can't figure out how to do that.



  • @mkurtz Didn't mention, but I am currently using v3.0.2 of SweetBlue.



  • I have some additional information that may help although I am new to v3.x and still don't understand what is happening under the hood. I am running in an OTA transaction. When the battery is pulled out of the device, my ReconnectFilter is not being called as mentioned previously. However, after ~10-15 seconds (wish this was much shorter), my transaction is ended with an EndReason of CANCELLED. In my onEnd() method, I call bleDevice.disconnect(). However, I do not believe that Android is disconnecting the device as I am not receiving a DISCONNECTED notification in my DeviceStateListener so my protocol gets stuck thinking that the device is still connected.

    In v2.52.17 my DeviceStateListener did receive a callback with the device didEnter(DISCONNECTED). Not sure why this isn't happening in v3.x.

    Any thoughts from anyone?



  • Set the reconnectfilter via the BleManagerConfig. There is a bug currently where the filter doesn't work properly when using setListener_DeviceReconnect(). This will be fixed in 3.0.3.

    When using an OTA, make sure to always call either succeed() or fail(), otherwise you will get weird state issues.



  • @ryanbis Thanks for the pointer. My ReconnectFilter is now being called properly so I am able to restart scanning (I don't scan while communicating with a device). I am returning ConnectionLostPlease.stopRetrying() but I still get the following message in my log: onDisconnected() - Disconnected implicitly and attemptShortTermReconnect=true.

    I am still not getting a disconnect notification in my StateListener so I am guessing that a retry is still being attempted. I have the following code in my OTATransaction class:

            @Override
            protected void onEnd(EndReason reason) {
                if (reason == EndReason.SUCCEEDED) {
                    succeed();
                } else {
                    fail();
                }
                disconnect();
            }
    

    Is it OK to attempt a bleDevice.disconnect(), which is what my "disconnect()" call does, in the onEnd method? How can I explicitly disconnect from the device after a transaction completes? Remember that I pulled the battery so a retry will never succeed but I've waited over 5 minutes and never get a notification callback.

    In my disconnect() method that is called from onEnd(...), the device's nativeStateMask == 0 which I believe means that the device is already BLE_DISCONNECTED. If this is true, why did I not receive a disconnected notification?

    Thanks,

    -Mike



  • @mkurtz What you're doing should be safe, looks like it may be a bug. I'll look into it this week, and see what I can find out.



  • @ryanbis Thanks Ryan. One other note, if it helps. When onEnd() is called after the transaction has been CANCELLED due to the battery removal, bleDevice.is(BleDeviceState.DISCONNECTED) == false and bleDevice.is(BleDeviceState.BLE_DISCONNECTED) == true.



  • Yeah, I think this isn't really an OTA thing, but a problem with reconnection. You were right in thinking that it's still trying to reconnect. I've fixed this in the current dev branch, so 3.0.3 should work for you. I'm doing my best to get it out as soon as possible, but there are a couple of other bugs I want to address before releasing.



  • @ryanbis Any estimates on the 3.0.3 release date? Do you have any additional tips for background scanning with Android 8.1? It is pretty hit and miss for us at the moment. One of our customers has a Samsung Galaxy Note 9 that is running 8.1. Our app does not work in the background at all (scanning is not returning results so our devices never connect). He went back to his Galaxy S8+ running 8.0 and things are working very well. Thanks!



  • I'm trying to get a new version out sometime this week, or next. There are a couple of other bugs I'd like to get worked out before releasing. Unfortunately, I don't have any tips for 8.1 scanning as of this moment, I'll put in a ticket for us to look into it further though.



  • @ryanbis Just tested with the new 3.0.3 release and am now receiving the disconnect notifications as expected. I notice that there is a long delay (~20ish seconds) between pulling the battery from my peripheral and being notified that the connection was dropped. Is this a SweetBlue controlled timeout or is this managed by Android? That is, do I have any control over how long it will take to receive the lost connection / disconnect notification? In iOS it takes just a moment.



  • No, there's no intentional delay in SweetBlue. It may get a little delayed from thread switching, but certainly not 20 seconds. Android's not too good at noticing dropped connections. I'd be curious to see if you get different results from changing the connection priority to high.



  • @ryanbis No real change in dropped connection detection time with the Connection Priority set to HIGH. But, my OTA transaction is about 40% faster. My firmware download went from ~75 seconds to ~45 seconds. This is still 15 seconds slower than under iOS but a huge improvement!



  • That's pretty much what I expected. Make sure to test that thoroughly, as being at the higher connection priority may make the bluetooth stack more unstable. We typically use it for OTAs, then bring it back to MEDIUM for normal use.



  • @ryanbis Ah, good to know. I will be sure to test this thoroughly. Thanks for the tip!



  • @mkurtz was this fixed for you? I have had some cases with latest sweetblue (3.2) where I can't always disconnect reliably.



  • @caeduk

    Please post a new topic with specific steps to reproduce the issue you're having so we can investigate it on our end.