Bluetooth LE device cannot disconnect in Win 10 IoT UWP application
Asked Answered
A

1

7

I am trying to control the Bluetooth LE devices connect/disconnect in my Win 10 IoT UWP C# application, running on Raspberry Pi 3 SBC. The Win 10 IoT is Windows Insiders Preview build 10.0.17035.1000. When I start my application, it recognizes the advertising BLE device, successfully connects and communicates with it . Then I try to disconnect this device by applying the recommended procedure:

device.Dispose();

device = null;

GC.Collect();

and even stop and start again the BluetoothLEAdvertisementWatcher. But when this device starts advertising again, it is not recognized. Of my understanding the reason is that the device was not actually disconnected (despite that it shows disconnected status) or some connection information is still pending, which prevents it to be recognized on a new advertisement.

Even if I don't apply the above procedure, a new device advertisement (from the same or other BLE device) is not recognized and in both cases the only resort is to restart the Win 10 IoT and restart the application in order a new advertisement from the same device to be recognized. After the communication with the device completes, an advertisement from different device of the same type can be recognized. But when the second device completes to communicate, no new advertisement from it or the first device can be recognized again. No exceptions or other problems were reported in debug mode. This is really inacceptable in an application production version.

Please advise me how to solve this problem. Thanks.

Atoll answered 7/12, 2017 at 19:39 Comment(1)
Actually only one new advertisement from different BLE devices is recognized just once and the other advertisements from the already served devices cannot be recognized.Atoll
N
13

This issue may be caused by the active session of GattDeviceService not been closed.

When you connected a BLE device and access its services and characteristics, there is an active session for your operations. You dispose of the device but the session is still open.

To solve this problem you need do a little more work when disconnecting the device like this:

  1. If you opened a service(GattDeviceService) you need call service?.Dispose().
  2. If you opened a characteristic(GattCharacteristic) you need to call characteristic?.Service?.Dispose().

For checking the session status you can call service?.Session.SessionStatus or characteristic?.Service?.Session.SessionStatus

Update: There maybe serval characteristics belong to one service. So you may run into exception when do the dispose from the characteristic level because you may duplicate to close a closed service. To solve this problem you can do the dispose work at the service level. The following code piece based on BluetoothLE sample. You can edit ClearBluetoothLEDeviceAsync() like this:

        private async Task<bool> ClearBluetoothLEDeviceAsync()
        {
            ...

            foreach (var ser in ServiceCollection)
            {
                ser.service?.Dispose();
            }

            bluetoothLeDevice?.Dispose();
            bluetoothLeDevice = null;
            return true;
        }
Numismatics answered 8/12, 2017 at 6:18 Comment(21)
Thank you Rita. I will try your approach.Atoll
Thank you again. I implemented the active sessions and characteristics disposal, despite that the BLE devices my application communicates with are just a beacon ones and there is no need to explicitly open a connection. This helped. But another think that seemed necessary was to set up a BluetoothLEAdvertisementWatcher filter in the ServiceUuids with the device family default service UUID. Then I had to apply the sequence I mentioned earlier.Atoll
@PaulTomov To be clear, we need focus on the initial question: the issue occurs when establishing a connection or just when using beacon(without connection)? Is my misunderstanding or there is another new question?Numismatics
My explanation was not exact. Of my understanding a connection with a BLE device should be establishe as described in: learn.microsoft.com/en-us/windows/uwp/devices-sensors/…. The same link states that: "disposing of all references to a BluetoothLEDevice object for a device (and if no other app on the system has a reference to the device) will trigger an automatic disconnect after a small timeout period." But this was not enough and, in addition, I had to dispose the active device Services and Characteristics as you advised me.Atoll
So your initial question: "cannot disconnect: is solved with the help of my answer, right?Numismatics
Yes. Thank you Rita. The link I initially referred to did not give the complete solution.Atoll
Ok. Any question?Numismatics
I still wonder if the device dispose should be good enough to take care of finalizing the underlying structures, including the GATT services and characteristics.Atoll
For your concern you can comment on this document.Numismatics
One problem when disposing a BLE device active GATT services and characteristics is that a foreach loop will not work since it throws and exception that the just disposed BLE characteristics has been closed. So the next one of the current service characteristic will not be able to be disposed. Please advise me what is the best way to finalize a BLE device instance.Atoll
I think that the incomplete disposal of a BLE device instance underlying objects (Services and Characteristics) causes a memory leak.Atoll
Yes, there maybe serval characteristics belong to one service. So loop all these characteristics to dispose, result in duplicating to close the same service, then you run in exceptions. You can do this work on the service level. I update my answer you can check it.Numismatics
Hi Rita, This is exactly what I did. But the next selected in the foreach loop characteristic for a service threw a Closed exception when checking: if (characteristic?.Service.Session?.SessionStatus == GattSessionStatus.Active) or even: characteristic?.Service?.Dispose(). This is not logical. What should be the problem? Shall we dispose the services only and not each service characteristics?Atoll
@PaulTomov Use Service?.Dispose() instead of characteristic?.Service?.Dispose().Numismatics
Thank you Rita. Now I dispose only the BLE device Services. It will be good to explicitly state this feature in the related MS UWP document. As I mentioned earlier, when the BLE device object is disposed, this should finalize all its underlying structures and reliably cause its disconnect. Obviously now this is implemented in UWP on the level of GATT Services for their Characteristics.Atoll
You are welcome. I saw you add comments to this document. Thanks for your job.Numismatics
Thank you Rita. I am still chasing UWP memory leaks I tried to prevent with the correct BLE object finalization.Atoll
I found out that in addition to ser.Service?.Dispose(); for minimizing the memory leaks it is helpful to apply ser.Service?Session?.Dispose();Atoll
@RitaHan-MSFT the code in the BluetoothLE sample you have referenced ClearBluetoothLEDeviceAsync does not do service.Dispose(), but i does unsubsribe from notification.Pennell
This solution solved my mystic issue ! Thank You! I had to implement different workarounds in my apps because I never could disconnect properly from BLE. I had no idea the session not clears itself when I dispose the BLE.Centare
I did everything what is mentioned here and still no luck to disconnect device. I followed lot of samples mentioned here and nothing helped? Could someone provide his code which worked?Katushka

© 2022 - 2024 — McMap. All rights reserved.