簡體   English   中英

Windows UWP 藍牙應用程序,即使關閉電源,設備也會在掃描時顯示

[英]Windows UWP bluetooth app, devices showing up when scanning even when they are powered off

我正在開發一個使用藍牙連接到不同設備的 UWP 應用程序。

我的問題是,一些已配對或先前發現的設備顯示在我的設備列表中,即使它們已關閉或不在范圍內。

據我了解,屬性System.Devices.Aep.IsPresent可用於過濾掉當時不可用的緩存設備,但即使我知道該設備無法訪問,我也總是為該屬性獲得“True”。

關於如何解決這個問題的任何想法?

設置

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;

添加設備時的回調

這里 isPresent 永遠是真的

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));
    }
}

查看GattSampleContextMicrosoft Bluetooth LE Explorer 源代碼 您需要獲取屬性: System.Devices.Aep.IsConnected, System.Devices.Aep.Bluetooth.Le.IsConnectable並僅過濾可連接的設備。 請注意,在調用DeviceWatcher.Updated事件后,設備可能會變得可連接。 所以你必須跟蹤一些未使用的unusedDevices

例如,我的 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;
}

對我有用的是讓設備觀察者枚舉 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 的所有屬性來解決這個問題,發現 AssociationEndpointContainer 與 AssociationEndpoint 和 Device (Device!) 相反,System.Devices.Aep.Bluetooth.Le.IsConnectable 屬性總是出現並且直接對應設備是否開機。

順便說一句,回想起來,這是有道理的。 在文檔中,我們看到 AssociationEndpointContainer

表示可能具有多個關聯的AssociationEndpoint對象的單個物理設備。 例如,如果電視支持兩種不同的網絡協議,則AssociationEndpointContainer就是電視。 它還有兩個AssociationEndpoint對象來表示每個協議。

因此,這是 Windows 構建的用於跟蹤設備連接的中心結構。 它能夠告訴我們設備是否可以連接,這是有道理的。

我必須說令人困惑的是,相比之下,DeviceInformationKind.Device 不提供此功能,而且,它甚至不代表設備,而是設備的組件:

這些設備是代表一部分設備功能的對象,並且可以選擇在其上加載驅動程序。 當一個物理設備與 windows 配對時,會為其創建多個Device對象。 一個設備包含 0 個或多個DeviceInterface對象,是一個DeviceContainer對象的子對象,並且與 0 個或 1 個AssociationEndpoint對象相關。

關於這個主題的官方文檔非常糟糕。 微軟,這是一個提示,如果你不希望人們在你的 API 上絆倒。 我知道時間是寶貴的,有財力的人很難在他們冰冷的心中找到體面來支付開發人員來正確記錄他們的東西,但是為了所有神聖的東西,如果你要提供僅提供有關如何使用您的東西的示例,然后提供解決初學者最常見問題的示例

舉個例子,對於初級 BLE 開發人員來說,哪個是更可能的目標? 您想要發現設備,即使它們無法連接,或者您只想發現可以連接的設備。

噓!

順便說一句,在我弄明白這一點之前,我走上了使用 AdvertisementWatcher 的路線。 具體來說,我會檢測廣告,從廣告連接到設備以獲取其名稱,然后對其進行處理。 這非常慢,並且可能會占用大量內存來啟動(間接地,通過設備關聯服務)。

這種方法,以我的經驗,各方面都優越; 它更快、更可靠,對系統資源的要求更低。

具體回答您的問題有點困難,因為您可以通過多種方式使用藍牙連接到設備。 例如,某些設備需要配對才能使用。 除非藍牙堆棧發出查詢,否則無法發現某些設備。

不過,要使這指向正確的方向,還需要做一些事情。

  1. 您要做的第一件事是使用 AQS 選擇器字符串來限制您發現的內容。 選擇器還應約束協議,因為您不希望 PC 發現 WiFiDirect 設備和網絡設備。 后過濾不利於性能。
  2. 接下來看看藍牙示例。 他們有許多用於不同場景的 get 選擇器類型方法,您可以使用它們傳遞給創建觀察者。 其中任何一個都可以滿足您的需求,或者您可以查看它們的 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

選擇器可能如下所示以枚舉配對的藍牙 BR 設備:

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

如果您有更具體的設備場景,我可以詳細說明更具體的答案。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM