首页 > 解决方案 > Windows 10 BLE 重新连接程序有时无法显示一些异常消息

问题描述

全部

我正在尝试在 Windows 10 上使用低功耗蓝牙实现重新连接过程。

  1. 当 Windows 10 通过 BLE 检测到设备断开连接时,它会调用 OnDisconnect 回调。
  2. 在 OnDisconnect 回调中,我将尝试使用 ReconnectManager 类(下面提到)扫描 PC 附近的 BLE 广告数据包
  3. 当 ReconnectManager 检测到包含制造商特定字节模式的数据包时,在这种情况下它是“0x07 0xcc 0x22 0x11”,Windows 10 会尝试重新连接发出制造商特定字节模式的设备。
  4. 但是,当它尝试在 connectBLE 函数中重新连接设备时,有时尝试会失败,并显示以下消息。一旦这些消息出现,它就永远无法重新连接任何 BLE 设备......
   onecore\internal\sdk\inc\wil\opensource/wil/winrt.h(1594)\Windows.Devices.Bluetooth.dll!00007FFA2993E3F4: (caller: 00007FFA2993722E) Exception(1) tid(5860) 8000FFFF Fatal Error.
0x00007FFA58114ED9 throws exception (In CPSApplication.exe): Microsoft C++ Exception: wil::ResultException (memory location 0x00000065DF97CC90)。
0x00007FFA58114ED9  (CPSApplication.exe): Microsoft C++ excption: [rethrow] (memory location 0x0000000000000000)。
onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(1976)\Windows.Devices.Bluetooth.dll!00007FFA29A477AD: (caller: 00007FFA29943C88) ReturnHr(1) tid(5860) 8000FFFF Fatal error.
    Msg:[onecore\internal\sdk\inc\wil\opensource/wil/winrt.h(1594)\Windows.Devices.Bluetooth.dll!00007FFA2993E3F4: (caller: 00007FFA2993722E) Exception(1) tid(5860) 8000FFFF Fatal error
] 
onecoreuap\drivers\wdm\bluetooth\user\winrt\device\bluetoothledevice.cpp(1079)\Windows.Devices.Bluetooth.dll!00007FFA29943CA7: (caller: 00007FFA29946800) ReturnHr(2) tid(5860) 8000FFFF Fatal error.
Exception throws 'System.Exception' (System.Private.CoreLib.dll)

我认为BLE协议栈和connectBLE函数之间可能会出现一些竞速问题,但我不确定一些具体的解决方案和解决方法。

我的源代码如下:

My code is what is displayed below:

        private async Task<Constants.ConnectionStatus> connectBLE(string deviceID)
        {
            BluetoothLEDevice bluetoothDev;
            List<GattDeviceService> services = new List<GattDeviceService>();
            List<Guid> srvGuids = new List<Guid>();

            srvGuids.Add(Constants.BluetoothChatServiceUuid);
            srvGuids.Add(Constants.BluetoothBatteryServiceUuid);

            try {
                    // Check permission of this device.
                    DeviceAccessStatus access = DeviceAccessInformation.CreateFromId(deviceID).CurrentStatus;
                    if (access == DeviceAccessStatus.DeniedBySystem || access == DeviceAccessStatus.DeniedByUser)
                    {
                        return Constants.ConnectionStatus.BTAccessError;
                    }
                    // Get BluetoothDevice structure.
                    bluetoothDev = await BluetoothLEDevice.FromIdAsync(deviceID);
                    if (bluetoothDev == null)
                    {
                        return Constants.ConnectionStatus.BTNoDeviceError;
                    }

                    try
                    {
                        // getting result for BLE using Gatt Service
                        foreach (Guid guid in srvGuids)
                        {
                            GattDeviceServicesResult BLEServices = await bluetoothDev.GetGattServicesForUuidAsync(guid, BluetoothCacheMode.Uncached);
                            if (BLEServices.Status == GattCommunicationStatus.Success && BLEServices.Services.Count > 0)
                            {
                                services.AddRange(BLEServices.Services);
                            }
                            else
                            {
                                services.Clear();
                                return Constants.ConnectionStatus.BTDiscoverError;
                            }
                        }
                    }
                    catch (System.Exception ex)
                    {
                        Debug.WriteLine("Received an Exception!");
                        services.Clear();
                        return Constants.ConnectionStatus.BTDiscoverError;
                    }

                    List<GattCharacteristic> characteristics = new List<GattCharacteristic>();

                    foreach (GattDeviceService srv in services)
                    {
                        // Ensure we have access to the device.
                        DeviceAccessStatus accessStatus = await srv.RequestAccessAsync();
                        if (accessStatus == DeviceAccessStatus.Allowed)
                        {
                            // BT_Code: Get all the child characteristics of a service. Use the cache mode to specify uncached characterstics only 
                            // and the new Async functions to get the characteristics of unpaired devices as well. 
                            GattCharacteristicsResult result = await srv.GetCharacteristicsAsync();
                            if (result.Status == GattCommunicationStatus.Success)
                            {
                                characteristics.AddRange(result.Characteristics);
                            }
                            else
                            {
                                // On error, act as if there are no characteristics.
                                characteristics.Clear();
                                break;
                            }
                        }
                        else
                        {
                            // On error, act as if there are no characteristics.
                            characteristics.Clear();
                            break;
                        }
                    }
                    if (characteristics.Count < 1)
                    {
                        return Constants.ConnectionStatus.BTServiceNameError;
                    }
            // reconnection has successfully finished!

                    return Constants.ConnectionStatus.Success;
                }
            catch (Exception ex) when ((uint)ex.HResult == 0x80070490) // ERROR_ELEMENT_NOT_FOUND
            {
                return Constants.ConnectionStatus.BTElementNotFoundError;
            }
            catch (Exception ex) when ((uint)ex.HResult == 0x80072740) // WSAEADDRINUSE
            {
                return Constants.ConnectionStatus.BTAddrInUseError;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
                return Constants.ConnectionStatus.BTExceptionError;
            }
            finally
            {
                _semaphore.Release();
            }
        }

        private async void OnDisconnect(object sender, string e)
        {
            CPSMsgHelper msg = (CPSMsgHelper)sender;
            System.Diagnostics.Debug.WriteLine("Disconnected (reason:" + e + ")");
            Constants.ConnectionStatus status = Constants.ConnectionStatus.BTNullError;

            bool isFound = false;

            string id = msg.DeviceID;

            Boolean stopCSV = StopCSVExport(id);
            if (stopCSV != true)
            {
                Debug.WriteLine("StopCSVExport error...");
            }

            Model.Services.UpdateDevStatus.Update(id, DeviceInfo.DeviceStatus.DISCONNECT_TRY_TO_RECONNECT);
            OnPropertyChanged(msg, "DevStatusDisconnected");
            msg.OnDisconnect -= OnDisconnect;

            while (isFound == false)
            {
                Task<string> task = Task.Run(() =>
                {
                    ReconnectManager mgr = new ReconnectManager(msg.DeviceID);
                    return mgr.Start();
                });
                task.Wait();
                if (task.Result != String.Empty)
                {
                    msg.DeviceID = task.Result;
                }
                Debug.WriteLine("Device has been found. ID = " + msg.DeviceID);
                status = await connectBLE(msg.DeviceID);
                Debug.WriteLine("Connection Status = " + status);
                if (status == Constants.ConnectionStatus.Success)
                {
                    Model.Services.UpdateDevStatus.Update(id, DeviceInfo.DeviceStatus.CONNECT);
                    OnPropertyChanged(msg, "DevStatusConnected");
                    isFound = true;
                    msg.OnDisconnect += OnDisconnect;
                }
            }
        }
    }
    public class ReconnectManager
    {
        private string bleID;
        private readonly ManualResetEvent mre;
        BluetoothLEAdvertisementWatcher watcher;
        private string retBLEID;

        public ReconnectManager(string id)
        {
            try
            {
                BluetoothLEManufacturerData manufacturerData = new BluetoothLEManufacturerData();
                manufacturerData.CompanyId = 0x07cc;
                DataWriter writer = new DataWriter();
                byte[] pattern = new byte[2];
                pattern[0] = 0x22;
                pattern[1] = 0x11;
                writer.WriteBytes(pattern);
                manufacturerData.Data = writer.DetachBuffer();
                mre = new ManualResetEvent(false);
                bleID = id;
                watcher = new BluetoothLEAdvertisementWatcher();
                watcher.SignalStrengthFilter.InRangeThresholdInDBm = -70;
                watcher.SignalStrengthFilter.OutOfRangeThresholdInDBm = -75;
                watcher.SignalStrengthFilter.OutOfRangeTimeout = TimeSpan.FromMilliseconds(2000);
                watcher.ScanningMode = BluetoothLEScanningMode.Active;
                watcher.AdvertisementFilter.Advertisement.ManufacturerData.Add(manufacturerData);
                watcher.Received += watcher_received;
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }
        public string Start()
        {
            try
            {
                retBLEID = "";
                Debug.WriteLine("***Rescanning...***");
                mre.Reset();
                watcher.Start();
                mre.WaitOne();
                watcher.Stop();

            }
            catch (Exception ex)
            {
                Debug.WriteLine("Exception catched!" + ex.Message);
            }
            return retBLEID;
        }

        private async void watcher_received(BluetoothLEAdvertisementWatcher sender, BluetoothLEAdvertisementReceivedEventArgs args)
        {
            ulong bleAddr = args.BluetoothAddress;
            try
            {
                BluetoothLEDevice dev = await BluetoothLEDevice.FromIdAsync(bleID);

                if (dev != null && dev.BluetoothAddress == bleAddr)
                {
                    retBLEID = dev.BluetoothDeviceId.Id;
                    mre.Set();
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine("Error in watcher_received." + ex.Message);
            }
        }
    }

问候,

影山义照

标签: uwpwindows-10bluetooth-lowenergy

解决方案


推荐阅读