0

I encountered a strange problem when trying to unpair and pair again with my smartphone. Currently I write a C# application on UWP (Windows 10) for BLE connection with a remote device. I use my smartphone with nRF Connect App as the peripheral.

After being paired for a while (and being inactive), when unpairing and pairing again, the application gets stuck when trying to pair again.

I broke everything down to the most basal application I could create. This is a Console App that scans the existing devices and then unpairs and pairs with the selected device:

using BLE_Test;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Program
    {
        static async Task Main(string[] args)
        {
            Dictionary<ulong, string> uuidDict = BleModule.Scan().Result;
            Console.WriteLine("Devices found:");
            int i = 0;
            foreach (var uuid in uuidDict.Keys)
                Console.WriteLine(string.Format("ID: {0}, UUID: {1}, Local Name: {2}", i++, uuid, uuidDict[uuid]));

            Console.WriteLine("Select ID!");
            int id = int.Parse(Console.ReadLine());
            ulong selectedUuid = (uuidDict.ElementAt(id)).Key;

            await BleModule.Unpair(selectedUuid);
            await BleModule.Pair(selectedUuid);
            Console.ReadLine();
        }
    }
}

It calls an UWP DLL called "BLE_Test" with the class "BleModule":

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.Advertisement;
using Windows.Devices.Enumeration;

namespace BLE_Test
{
    public class BleModule
    {
        public static async Task<Dictionary<ulong, string>> Scan()
        {
            var uuidDict = new Dictionary<ulong, string>();
            BluetoothLEAdvertisementWatcher watcher = new BluetoothLEAdvertisementWatcher();
            watcher.Received += (BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs eventArgs)
                => AddAdvertisement(eventArgs, uuidDict);

            watcher.Start();
            await Task.Delay(10000);
            watcher.Stop();

            return uuidDict;
        }

        private static void AddAdvertisement(BluetoothLEAdvertisementReceivedEventArgs eventArgs, Dictionary<ulong, string> uuidDict)
        {
            if (uuidDict.ContainsKey(eventArgs.BluetoothAddress) == false)
                uuidDict.Add(eventArgs.BluetoothAddress, eventArgs.Advertisement.LocalName);
        }

        public static async Task Pair(ulong uuid)
        {
            Console.WriteLine("Pairing...");
            var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
            if (bluetoothLEDevice == null)
            {
                Console.WriteLine("UUID not found!");
                return;
            }

            DeviceInformationCustomPairing customPairing = bluetoothLEDevice.DeviceInformation.Pairing.Custom;
            customPairing.PairingRequested += (DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args) => args.Accept();  // We auto-accept numeric comparison result for the sake of simplicity
            DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmPinMatch);
            Console.WriteLine("Pairing Result: " +  result.Status.ToString());
        }

        public static async Task Unpair(ulong uuid)
        {
            Console.WriteLine("Unpairing...");
            var bluetoothLEDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(uuid);
            if (bluetoothLEDevice == null)
            {
                Console.WriteLine("UUID not found!");
                return;
            }

            DeviceUnpairingResult result = await bluetoothLEDevice.DeviceInformation.Pairing.UnpairAsync();
            Console.WriteLine("Unpairing Result: " + result.Status.ToString());
        }
    }
}

If I start the program for the first time, the pairing works fine (the unpairing will be ignored as the devices are not paired yet). If I start it immediately again afterwards, it also works fine. Unpairing and pairing will both take place. But if I wait a while (typically 5-10 minutes) while not doing anything, when I start the program again, it will unpair, but then it will wait indefinitely for PairAsync() to return. No coupling request will show on the nRF Connect App, and no PairingRequested event will appear.

Aborting the stuck program and restarting it won't help. In this case, even though the smartphone is found by the BluetoothLEAdvertisementWatcher, BluetoothLEDevice.FromBluetoothAddressAsync(uuid) will return null and the device can't be paired anymore. This can only be resolved by restarting the computer or switching off and on the advertisement in the nRF Connect App, as in this case a new random BLE Address is created for the device.

I have taken a snapshot of the BLE events using Btetlparse and Wireshark. It seems that there is a problem with a malformed package: enter image description here

However, I don't really understand what is going wrong. Is this a problem of the nRF Connect App? Or the UWP commands? Or did I do something wrong? I tried two different smartphones (a Samsung Galaxy and an Oppo), so I doubt that it is a problem of the smartphone. I also added a DeviceWatcher, but this didn't change anything. Can anyone help me here?

Thern
  • 1,017
  • 8
  • 17
  • Can you try to test the Bluetooth function without using the nFR connect app? So that we could know if the issue is related to the Bluetooth function. – Roy Li - MSFT Aug 29 '22 at 06:44
  • @RoyLi-MSFT I presently have no BLE hardware counterpart yet (will be coming next month). Is there any convenient alternative to test the BLE functionality apart from the nRF Connect App? I know the LightBlue App, but that doesn't work on Android and I have no iPhone. – Thern Aug 29 '22 at 09:35
  • What about the built-in Bluetooth function of android phone – Roy Li - MSFT Aug 29 '22 at 09:41
  • @RoyLi-MSFT How would that work? Without a beacon, the smartphone will not be advertising, and even if so, I would need the pairing to be Numeric Comparison and not Just Works to have it comparable. – Thern Aug 29 '22 at 10:12
  • Do you have any other apps that could do it? – Roy Li - MSFT Aug 30 '22 at 07:45
  • @RoyLi-MSFT Currently not. I will get the actual hardware to work with next month, so maybe the issue is gone then, but this will take some weeks and I thought I could solve the current problem in advance. – Thern Aug 30 '22 at 07:53
  • In my experience with NRF Connect App I've noticed that always by default makes a bonding (stores the keys exchanged during the connection) to avoid to pair again the following times you connect to the peripheral. If the peripheral doesn't handle bonding, at the next connection (after the first time) the NRF Connect app tries to use the saved information during bonding, but the peripheral device doesn't recognized them and the connection/pairing process stucks . To solve this, usually, I delete the Bonding informations from the app: Bonded Tab -> Device -> Option -> Delete bond information. – fabik111 Aug 30 '22 at 13:25
  • @fabik111 I tried this, but it still seems to be stuck. Deleting the bond information on the App before unpairing with UnpairAsync() did not have the desired effect for me. – Thern Aug 31 '22 at 16:32

0 Answers0