2016-06-21 1 views
0

Je suis en train de développer une application qui se connecte à une balise BLE, pour cela j'utilise l'API BluetoothLEAdvertisementWatcher. Quand je reçois une publicité, je veux me connecter à l'appareil pour lire les caractéristiques du GATT.FromBluetoothAddressAsync throws 'System.IO.FileNotFoundException' dans mscorlib.ni.dll

Je commence un BLEwatcher

BluetoothLEAdvertisementWatcher watcher; 
    watcher.Received += OnAdvertisementReceived; 
    watcher.Stopped += OnAdvertisementWatcherStopped; 
    watcher.Start(); 

Alors je tente d'accéder à l'appareil

private async void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) 
{ 
    var address = eventArgs.BluetoothAddress; 

    BluetoothLEDevice device = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress); 
    Debug.WriteLine(device.Name + " - " + device.DeviceId); 
    .... 

Cela échoue (à la ligne FromBluetoothAddressAsync)

Une exception du type « système .IO.FileNotFoundException 's'est produite dans mscorlib.ni.dll mais n'a pas été gérée dans le code utilisateur

Informations supplémentaires: Le système ne trouve pas le fichier spécifié. (Exception de HRESULT: 0x80070002)

La chose amusante est: si j'ouvre la fenêtre de dispositifs bluetooth du système cela fonctionne très bien! Par conséquent, lorsque j'ouvre la fenêtre des périphériques bluetooth et que j'exécute l'application, l'erreur n'est pas levée. Lorsque je ferme la fenêtre des périphériques bluetooth, elle renvoie l'erreur. Notez qu'il lance toujours cette erreur dans une tâche d'arrière-plan.

Apparemment, cela fonctionne sur la version 10.0.10586.218. J'ai trouvé en ligne de quelqu'un avec le même numéro:

LUMIA 950, Windows 10, 1511, 10.0.14332.1001

Exception jetée sur FromIdAsync(): 'System.IO.FileNotFoundException' dans mscorlib.ni.dll

LUMIA 730, Windows 10, 1511, 10.0.10586.218

Exception jetée sur FindAllAsync(): « Sys tem.ArgumentException »

LUMIA 920, Windows 10, 1511, 10.0.10586.218

Pas d'erreur!

Captures d'écran: When it fails

When it works

Répondre

0

ne sont pas les API de Windows BLE belle et agréable (un) exceptions documentées qu'ils vous donnent?

Vous ne devriez pas utiliser AdvertisementWatcher si vous avez l'intention de coupler à un appareil je suppose. Utilisez plutôt un observateur DeviceInformation avec un sélecteur spécifique pour les périphériques BLE qui contiennent à la fois des périphériques appariés et non appariés. Cela donnera un objet DeviceInformation prêt à l'emploi avec lequel vous pouvez être associé.

L'exemple de code pour que l'on voit à https://github.com/Microsoft/Windows-universal-samples/tree/master/Samples/DeviceEnumerationAndPairing, numéro de scénario 8.

2

Le problème

Cette erreur est due en appelant FromBluetoothAddressAsync dans un thread non-UI. Windows 10 requiert le consentement de l'utilisateur lorsqu'une application tente d'accéder à un périphérique Bluetooth. Lorsque FromBluetoothAddressAsync est appelée, Windows essaie de créer un dialogue de consentement. Parce que ce n'est pas un thread d'interface utilisateur, le dialogue de consentement ne peut pas apparaître et une exception est levée.

Solution

D'abord, vous devez faire le BluetoothLEAdvertisementWatcher plus spécifique au périphérique que vous recherchez. Si vous ne le faites pas, alors votre application verra chaque périphérique Bluetooth LE et demandera le consentement de l'utilisateur sur chacun - une expérience utilisateur terrible.

Il existe plusieurs façons de filtrer les publicités. Vous pouvez le faire manuellement dans votre méthode OnAdvertisementReceived en utilisant les propriétés de eventArgs ou vous pouvez définir des filtres dans le BluetoothLEAdvertisementWatcher lui-même. Par exemple, pour trouver des périphériques Bluetooth LE qui ont un moniteur de fréquence cardiaque, faire:

watcher.AdvertisementFilter.Advertisement.ServiceUuids.Add(GattServiceUuids.HeartRate); 

Pour faire un appel sur un thread d'interface utilisateur, vous devez utiliser un répartiteur. Vous pouvez configurer un répartiteur en utilisant le code suivant:

// Variable in your class 
CoreDispatcher dispatcher; 

// Init for your class 
public MainPage() { 
    ... 
    // Init the dispatcher, this must be done on the main thread 
    this.dispatcher = CoreWindow.GetForCurrentThread().Dispatcher; 
    ... 
} 

Ensuite, lorsque vous recevez une publicité, vous pouvez faire votre propre filtrage puis dire le répartiteur de se connecter à l'appareil LE Bluetooth sur le thread principal.

private async void ConnectToBTDevice(BluetoothLEAdvertisementReceivedEventArgs eventArgs) { 
    // This will cause a consent prompt if the user hasn't already consented 
    var btDevice = await BluetoothLEDevice.FromBluetoothAddressAsync(eventArgs.BluetoothAddress); 
} 

private bool Filter(BluetoothLEAdvertisementReceivedEventArgs eventArgs) { 
    // Return true if the advertisement has the name we're looking for 
    return eventArgs.Advertisement.LocalName != null && eventArgs.Advertisement.LocalName.Equals("Peripheral Name"); 
} 

private void OnAdvertisementReceived(BluetoothLEAdvertisementWatcher watcher, BluetoothLEAdvertisementReceivedEventArgs eventArgs) { 

    // Do our own filtering (for example) 
    if(!this.Filter(eventArgs)) return; 

    // Connect to the Bluetooth device in the UI (main) thread 
    this.dispatcher.RunAsync(CoreDispatcherPriority.Normal,() => this.ConnectToBTDevice(eventArgs)); 
} 
+0

Le problème de connexion a été résolu par le commentaire que j'ai marqué comme réponse, en couplant d'abord puis en utilisant FromIdAsync. Cependant, j'ai aussi utilisé une partie de cela pour le réparer, merci. – vixez