![](/img/trans.png)
[英]FromBluetoothAddressAsync never returns on Windows 10 Creators Update in WPF Application
[英]How to register for BLE notifcations from a WPF app running on Windows 10 Creators Update?
我试图编写一个使用WinRT蓝牙LE API(Windows.Devices.Bluetooth命名空间)的C#应用程序。 该应用程序是Windows Classic Desktop应用程序(WPF, 而不是 UWP)。 当运行Creators Update之前的Windows 10版本时,这些API会按预期运行。 但是,在运行Creators Update时,应将数据发送到Bluetooth设备的API无法正常工作。 具体来说,以下方法返回成功状态代码,但不通过蓝牙无线电传输任何数据(使用蓝牙流量嗅探器进行验证):
结果,任何为特性注册ValueChanged处理程序的尝试均不起作用。 由于注册永远不会发送到Bluetooth LE设备,因此应用程序不会收到任何通知。
我知道不是所有的UWP API都可以从非UWP应用程序中使用,但是我希望有人能够以这种配置成功开发BLE应用程序(或者至少可以确认现在不可能)。 在Creators Update之前,我能够从BLE设备进行连接和读取数据,以及将数据写入BLE设备,并且仅在Windows 10的最新版本中,上述问题才会显现。 (注意:示例代码中使用的Async API已在“创建者更新”中添加。我们应用程序的先前版本使用了较早的BLE API,但在运行“创建者更新”时也无法正常工作。)
具体来说,我的问题是: 给定以下项目参考列表和示例代码,我是否可以尝试从非UWP应用程序运行运行Creators Update的Windows 10上获得有效的Bluetooth LE连接? 请注意,“将应用程序转换为UWP应用程序”这一明显答案对我们不起作用,因为我们以其他方式与其他硬件和文件进行交互,而这种方式在UWP沙箱中是不可能的。
该项目配置有以下参考:
以下是我的应用程序中非常简化的蓝牙代码版本。 请注意,为清楚起见,已删除了许多错误处理等内容,但是它应该可以大致了解我要执行的操作:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Foundation;
using Windows.Storage.Streams;
using System.Threading;
namespace BLEMinimumApp
{
class Program
{
private List<string> foundDevices = new List<string>(5);
static void Main(string[] args)
{
new Program().Execute();
}
private void Execute()
{
Console.WriteLine("Starting device watcher...");
string[] requestedProperties = { "System.Devices.Aep.IsConnected" };
String query = "";
//query for Bluetooth LE devices
query += "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";
//query for devices with controllers' name
query += " AND (System.ItemNameDisplay:=\"GPLeft\" OR System.ItemNameDisplay:=\"GPRight\")";
var deviceWatcher = DeviceInformation.CreateWatcher(query, requestedProperties, DeviceInformationKind.AssociationEndpoint);
deviceWatcher.Added += DeviceWatcher_OnAdded;
deviceWatcher.Start();
Console.ReadLine();
}
private async void DeviceWatcher_OnAdded(DeviceWatcher sender, DeviceInformation deviceInfo)
{
lock (foundDevices)
{
if (foundDevices.Contains(deviceInfo.Name))
{
return;
}
foundDevices.Add(deviceInfo.Name);
}
Console.WriteLine($"[{deviceInfo.Name}] DeviceWatcher_OnAdded...");
await ConnectTo(deviceInfo);
}
private async Task ConnectTo(DeviceInformation deviceInfo)
{
try
{
// get the device
BluetoothLEDevice device = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
Console.WriteLine($"[{device.Name}] Device found: connectionStatus={device?.ConnectionStatus}");
// get the GATT service
Thread.Sleep(150);
Console.WriteLine($"[{device.Name}] Get GATT Services");
var gattServicesResult = await device.GetGattServicesForUuidAsync(new Guid("<GUID REMOVED FOR SO POST"));
Console.WriteLine($"[{device.Name}] GATT services result: status={gattServicesResult?.Status}, count={gattServicesResult?.Services?.Count}, cx={device.ConnectionStatus}");
if (gattServicesResult == null
|| gattServicesResult.Status != GattCommunicationStatus.Success
|| gattServicesResult.Services == null
|| gattServicesResult.Services?.Count < 1)
{
Console.WriteLine($"[{device.Name}] Failed to find GATT service.");
return;
}
var service = gattServicesResult.Services[0];
Console.WriteLine($"[{device?.Name}] GATT service found: gattDeviceService={service.Uuid}");
// get the GATT characteristic
Thread.Sleep(150);
Console.WriteLine($"[{device.Name}] Get GATT characteristics");
var gattCharacteristicsResult = await service.GetCharacteristicsForUuidAsync(new Guid("<GUID REMOVED FOR SO POST>"));
Console.WriteLine($"[{device.Name}] GATT Characteristics result: status={gattCharacteristicsResult?.Status}, count={gattCharacteristicsResult?.Characteristics?.Count}, cx={device.ConnectionStatus}");
if (gattCharacteristicsResult == null
|| gattCharacteristicsResult.Status != GattCommunicationStatus.Success
|| gattCharacteristicsResult.Characteristics == null
|| gattCharacteristicsResult.Characteristics?.Count < 1)
{
Console.WriteLine($"[{device.Name}] Failed to find GATT characteristic.");
return;
}
var characteristic = gattCharacteristicsResult.Characteristics[0];
// register for notifications
Thread.Sleep(150);
characteristic.ValueChanged += (sender, args) =>
{
Console.WriteLine($"[{device.Name}] Received notification containing {args.CharacteristicValue.Length} bytes");
};
Console.WriteLine($"[{device.Name}] Writing CCCD...");
GattWriteResult result =
await characteristic.WriteClientCharacteristicConfigurationDescriptorWithResultAsync(GattClientCharacteristicConfigurationDescriptorValue.Notify);
Console.WriteLine($"[{device?.Name}] Characteristics write result: status={result.Status}, protocolError={result.ProtocolError}");
// send configuration to device
await SendConfiguration(device, characteristic);
}
catch (Exception ex) when((uint) ex.HResult == 0x800710df)
{
Console.WriteLine("bluetooth error 1");
// ERROR_DEVICE_NOT_AVAILABLE because the Bluetooth radio is not on.
}
}
private async Task SendConfiguration(BluetoothLEDevice device, GattCharacteristic characteristic)
{
if (characteristic != null)
{
var writer = new DataWriter();
// CONFIGURATION REMOVED, but this code writes device-specific bytes to the DataWriter
await SendMessage(device, characteristic, writer.DetachBuffer());
}
}
private async Task SendMessage(BluetoothLEDevice device, GattCharacteristic characteristic, IBuffer message)
{
if (characteristic != null && device.ConnectionStatus.Equals(BluetoothConnectionStatus.Connected) && message != null)
{
Console.WriteLine($"[{device.Name}] Sending message...");
GattCommunicationStatus result = await characteristic.WriteValueAsync(message);
Console.WriteLine($"[{device.Name}] Result: {result}");
}
}
}
}
COM安全性可能阻止您的应用程序接收通知。 请参考以下主题以获取解决方案。 我建议使用注册表黑客。
我遇到了类似的问题,并且在更改了上述注册表后,我的应用收到的通知很少,并且没有任何明显的原因停止。 在这个问题上浪费了很多时间,等待微软的补丁。
最新更新纠正了此问题。 您也可以使用其他海报引用的链接上的Matt Beaver的说明来解决此问题。
基本上是:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.