uwp - Windows 10 BLE 重新连接程序有时无法显示一些异常消息
问题描述
全部
我正在尝试在 Windows 10 上使用低功耗蓝牙实现重新连接过程。
- 当 Windows 10 通过 BLE 检测到设备断开连接时,它会调用 OnDisconnect 回调。
- 在 OnDisconnect 回调中,我将尝试使用 ReconnectManager 类(下面提到)扫描 PC 附近的 BLE 广告数据包
- 当 ReconnectManager 检测到包含制造商特定字节模式的数据包时,在这种情况下它是“0x07 0xcc 0x22 0x11”,Windows 10 会尝试重新连接发出制造商特定字节模式的设备。
- 但是,当它尝试在 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);
}
}
}
问候,
影山义照
解决方案
推荐阅读
- elasticsearch - 为什么我的弹性搜索字段自动到 UTC 时间
- mysql - Mysql 查询不起作用并显示错误
- html - 如何在 Angular / TypeScript 中切换 *ngFor 中行的背景颜色?
- c# - 如何从 JSON 对象中获取数据?从日期变量到图表的选择
- c# - IIS Server上部署Windows Authentication,windows登录提示不断出现,如何停止?
- javascript - 向下滚动时如何隐藏导航菜单的图像?
- python - 如何序列化从张量流数组创建的字典对象
- twitter-bootstrap - 单击后,工具提示对 btn-group-toggle 中的单选按钮保持可见
- oracle - OBIEE 计数不考虑应用的过滤器
- android - 推送失败:无法访问 URL:请求的 URL 返回错误:409