Windows UWP蓝牙应用程序,即使在电源关闭时也会显示设备

时间:2017-08-08 12:26:28

标签: c# windows bluetooth uwp

我正在开发一个使用蓝牙连接到不同设备的UWP应用程序。

我的问题是,已配对或之前发现的某些设备会显示在我的设备列表中,即使它们已关闭或未在范围内。

根据我的理解,属性System.Devices.Aep.IsPresent可用于过滤掉当时不可用的缓存设备,但即使我知道设备无法访问,我仍然会为该属性获得“True”。 / p>

关于如何解决这个问题的任何想法?

设置

string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.IsPresent", "System.Devices.Aep.ContainerId", "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.Manufacturer", "System.Devices.Aep.ModelId", "System.Devices.Aep.ProtocolId", "System.Devices.Aep.SignalStrength"};
        _deviceWatcher = DeviceInformation.CreateWatcher("{REMOVED, NOT IMPORTANT}", requestedProperties, DeviceInformationKind.AssociationEndpoint);
        _deviceWatcher.Added += DeviceAdded;
        _deviceWatcher.Updated += DeviceUpdated;
        _deviceWatcher.Removed += DeviceRemoved;
        _deviceWatcher.EnumerationCompleted += DeviceEnumerationCompleted;

添加设备时的回调

这里是完全真实的

private void DeviceAdded(DeviceWatcher sender, DeviceInformation deviceInfo)
{
    Device device = new Device(deviceInfo);
    bool isPresent = (bool)deviceInfo.Properties.Single(p => p.Key == "System.Devices.Aep.IsPresent").Value;
    Debug.WriteLine("*** Found device " + deviceInfo.Id + " / " + device.Id + ", " + "name: " + deviceInfo.Name + " ***");
    Debug.WriteLine("RSSI = " + deviceInfo.Properties.Single(d => d.Key == "System.Devices.Aep.SignalStrength").Value);
    Debug.WriteLine("Present: " + isPresent);
    var rssi = deviceInfo.Properties.Single(d => d.Key == "System.Devices.Aep.SignalStrength").Value;
    if (rssi != null)
        device.Rssi = int.Parse(rssi.ToString());
    if (DiscoveredDevices.All(x => x.Id != device.Id) && isPresent)
    {
        DiscoveredDevices.Add(device);
        DeviceDiscovered(this, new DeviceDiscoveredEventArgs(device));
    }
}

3 个答案:

答案 0 :(得分:3)

查看Microsoft Bluetooth LE Explorer source code of GattSampleContext。您需要获取属性:System.Devices.Aep.IsConnected, System.Devices.Aep.Bluetooth.Le.IsConnectable并仅过滤可连接的设备。请注意,在调用DeviceWatcher.Updated事件后,设备可能会变为可连接。因此,您必须跟踪unusedDevices

E.g。我的IsConnactable过滤方法是:

private static bool IsConnectable(DeviceInformation deviceInformation)
{
    if (string.IsNullOrEmpty(deviceInformation.Name))
        return false;
    // Let's make it connectable by default, we have error handles in case it doesn't work
    bool isConnectable = (bool?)deviceInformation.Properties["System.Devices.Aep.Bluetooth.Le.IsConnectable"] == true;
    bool isConnected = (bool?)deviceInformation.Properties["System.Devices.Aep.IsConnected"] == true;
    return isConnectable || isConnected;
}

答案 1 :(得分:1)

对我有用的是让设备观察者枚举AssociationEndpointContainers,与文档中的建议相反。

我具体使用

string[] RequestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable"};
 DeviceInformation.CreateWatcher(BluetoothLEDevice.GetDeviceSelectorFromConnectionStatus(BluetoothConnectionStatus.Disconnected), RequestedProperties, DeviceInformationKind.AssociationEndpointContainer)

我通过记录发现期间提供的每个DeviceInformation和DeviceInformationUpdate的所有属性来解决这个问题,发现与AssociationEndpoint和设备(设备!)相反,AssociationEndpointContainer是System.Devices.Aep.Bluetooth.Le.IsConnectable属性始终显示,并且直接对应于设备是否开机。

回想一下,这很有意义。在文档中,我们看到AssociationEndpointContainer

表示可能有多个物理设备的单个物理设备 与之关联的 AssociationEndpoint 对象。例如,如果电视支持两种不同的网络协议, AssociationEndpointContainer 是电视。它还将具有两个 AssociationEndpoint 对象来表示每个协议。

因此,这是Windows构造的用于跟踪与设备的连接的中央结构。能够告诉我们该设备是否可以连接是很有意义的。

我必须说,与之相反,DeviceInformationKind.Device不提供此功能,而且它甚至不代表设备,而是设备的组件,实在令人困惑。

这些设备是代表设备一部分的对象 功能,并有选择地加载驱动程序。当一个 物理设备与Windows配对,多个 Device 对象是 为此创建。一个设备包含0个或多个 DeviceInterface 对象, 是一个 DeviceContainer 对象的子对象,并且与0或1相关 AssociationEndpoint 对象。

有关此主题的官方文档非常糟糕。 Microsoft,如果您不希望人们在您的API上绊倒,这里有个提示。我知道时间很宝贵,有钱袋的人很难找到冷酷的心态来付钱给开发人员以适当地记录他们的东西,但是如果您愿意提供一切,那将是神圣的爱仅提供有关如何使用您的东西的示例,然后提供解决初学者最常见问题的示例。

案例,对于BLE初学者来说,这是一个更高的目标吗?您希望发现即使无法连接的设备,或者只发现可以连接的设备。

嘘!

顺便说一句,在我弄清楚这一点之前,我走了使用AdvertisementWatcher的路线。具体来说,我将检测广告,从广告连接到设备以获得其名称,然后处理它。这非常慢,并且可能占用大量内存来启动(通过设备关联服务间接启动)。

以我的经验,这种方法在各方面都优越。它更快,更可靠并且对系统资源的要求更低。

答案 2 :(得分:0)

要具体回答您的问题有些困难,因为您可以通过多种方式使用蓝牙连接到设备。例如,某些设备需要配对才能使用。除非蓝牙协议栈发出查询,否则无法发现某些设备。

要做一些事情才能使这个方向正确。

  1. 您要做的第一件事是使用AQS选择器字符串来约束您发现的内容。选择器还应约束协议,因为您不希望PC发现WiFiDirect设备和网络设备。后过滤不利于性能。
  2. 接下来看一下蓝牙示例。对于不同的场景,它们具有许多get选择器类型方法,您可以使用这些方法将其传递给create watcher。这些方法之一可以满足您的要求,或者您可以查看其AQS字符串以了解过滤器的外观。

就可以用于AQS选择器的属性而言,我不确定是否存在该属性会有效,但是您可能会在构造选择器/过滤器时考虑其他一些属性。就像我说的,情况有很大的不同。例如耳机必须配对,而某些LE设备无法配对且只能连接。

System.Devices.Aep.Bluetooth.IssueInquiry
System.Devices.Aep.Bluetooth.LastSeenTime
System.Devices.Aep.Bluetooth.Le.IsConnectable
System.Devices.Aep.IsPaired
System.Devices.Aep.CanPair
System.Devices.Aep.IsConnected
System.Devices.Aep.IsPresent
System.Devices.Aep.ProtocolId

选择器可能看起来像这样,以枚举已配对的Bluetooth BR设备:

System.Devices.Aep.ProtocolId:="{e0cbf06c-cd8b-4647-bb8a-263b43f0f974}" AND System.Devices.Aep.IsPaired:=System.StructuredQueryType.Boolean#True";

如果您有更具体的设备方案,我可以为您提供更具体的答案。