Windows 10 Creators Updateで動作しているWPFアプリからBLE通知を登録するにはどうすればいいですか?

私はWinRT Bluetooth LE API(Windows.Devices.Bluetooth名前空間)を使用するC#アプリを書き込もうとしています。このアプリはWindowsクラシックデスクトップアプリケーションです(WPF、ない UWP)。 Creators Updateより前のバージョンのWindows 10を実行している場合、これらのAPIは予想通りに機能します。ただし、Creators Updateを実行すると、Bluetoothデバイスにデータを送信する必要があるAPIは機能しません。具体的には、次のメソッドは成功ステータスコードを返しますが、Bluetooth無線を介してデータを送信しません(Bluetoothトラフィックスニファを使用して検証された場合)。

  • GattCharacteristic.WriteClientCharacteristicConfigurationDescriptorWithResultAsync
  • GattCharacteristic.WriteValueAsync

その結果、特性に対してValueChangedハンドラを登録しようとしても機能しません。登録はBluetooth LEデバイスに送信されないため、アプリケーションによって通知は受信されません。

すべてのUWP APIが非UWPアプリから使用できるわけではないことを私は理解していますが、そのような構成で誰かがBLEアプリを正常に開発できたことを私は願っています。 Creators Updateの前にBLEデバイスに接続してデータを読み書きすることができますが、この問題はWindows 10の最新バージョンでのみ発生します。 (注:サンプルコードで使用されているAsync APIはCreators Updateで追加されました。以前のバージョンのアプリケーションは古いBLE APIを使用していましたが、Creators Updateを実行しても機能しません。)

具体的には、次のようなプロジェクト参照リストとサンプルコードがあれば、UWP以外のアプリケーションからCreators Updateを実行しているWindows 10でBluetooth LEの接続を機能させることができますか。 UWPサンドボックス内では不可能な方法で他のハードウェアやファイルとやり取りするため、「アプリケーションをUWPアプリに変換する」という明白な答えは私たちにはうまくいきません。

プロジェクトは次の参照を使用して構成されました。

  • System.Runtime.WindowsRuntime、C:¥Program Files(x86)¥Reference Assemblies¥Microsoft¥Framework.NETCore¥v4.5¥System.Runtime.WindowsRuntime.dllにあります。
  • Windows、C:¥Program Files(x86)¥Windows Kits¥10¥UnionMetadata¥Facade¥Windows.WinMDにあります。
  • Windows.Foundation.FoundationContract、C:¥Program Files(x86)¥Windows Kits¥10¥References¥10.0.15063.0¥Windows.Foundation.FoundationContract¥3.0.0.0¥Windows.Foundation.FoundationContract.winmd
  • Windows.Foundation.UniversalApiContract、C:¥Program Files(x86)¥Windows Kits¥10¥References¥10.0.15063.0¥Windows.Foundation.UniversalApiContract¥4.0.0.0¥Windows.Foundation.UniversalApiContract.winmd

以下は私のアプリケーションからのBluetoothコードの非常に削除されたバージョンです。明確にするために、多くのエラー処理などが削除されていますが、私が何をしようとしているのかについての一般的な考えを与えるはずです。

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 foundDevices = new List(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(""));
                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}");
            }
        }
    }
}
1

6 答え

最新のアップデートでこれが修正されています。他のポスターが参照しているリンクでMatt Beaverからの指示を使用して問題を回避することもできます。

基本的には:

  1. AppIdを指定します。あなたのアプリケーション用。
  2. CoInitializeSecurity お客様のアプリケーションでコールバックを許可する
回答いただきありがとうございます。 vt08505によってリンクされたスレッドで説明されているようにAppIDを指定することは私たちの問題を解決するように見えます。私はまた、これがWindows Insiderプログラム(OS Build 16278.1000)から入手可能な最新のビルドで解決されるように思われることを確認しました。
追加された 著者 Sean Kleinjung,

最新のアップデートでこれが修正されています。他のポスターが参照しているリンクでMatt Beaverからの指示を使用して問題を回避することもできます。

基本的には:

  1. AppIdを指定します。あなたのアプリケーション用。
  2. CoInitializeSecurity お客様のアプリケーションでコールバックを許可する
回答いただきありがとうございます。 vt08505によってリンクされたスレッドで説明されているようにAppIDを指定することは私たちの問題を解決するように見えます。私はまた、これがWindows Insiderプログラム(OS Build 16278.1000)から入手可能な最新のビルドで解決されるように思われることを確認しました。
追加された 著者 Sean Kleinjung,

最新のアップデートでこれが修正されています。他のポスターが参照しているリンクでMatt Beaverからの指示を使用して問題を回避することもできます。

基本的には:

  1. AppIdを指定します。あなたのアプリケーション用。
  2. CoInitializeSecurity お客様のアプリケーションでコールバックを許可する
回答いただきありがとうございます。 vt08505によってリンクされたスレッドで説明されているようにAppIDを指定することは私たちの問題を解決するように見えます。私はまた、これがWindows Insiderプログラム(OS Build 16278.1000)から入手可能な最新のビルドで解決されるように思われることを確認しました。
追加された 著者 Sean Kleinjung,

COMセキュリティによって、アプリが通知を受け取れなくなる可能性があります。解決方法については、次のスレッドを参照してください。レジストリハックを使用することをお勧めします。

https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-com-com-001-163 forum = wdk

私は同様の問題を抱えており、上記のレジストリの変更により、私のアプリは通知をほとんど受け取らず、明白な理由もなく停止します。 この問題に多くの時間を浪費し、マイクロソフトからのパッチを待つ。

1
追加された
回答いただきありがとうございます。私はそのスレッドで説明されているようにAppIDを指定しました、そしてこれは問題を解決したようです。あなたがまだ説明したように通知が止まるかどうかを確かめるために徹底的なテストをしていません。うまくいけば。 :)
追加された 著者 Sean Kleinjung,

COMセキュリティによって、アプリが通知を受け取れなくなる可能性があります。解決方法については、次のスレッドを参照してください。レジストリハックを使用することをお勧めします。

https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-com-com-001-163 forum = wdk

私は同様の問題を抱えており、上記のレジストリの変更により、私のアプリは通知をほとんど受け取らず、明白な理由もなく停止します。 この問題に多くの時間を浪費し、マイクロソフトからのパッチを待つ。

1
追加された
回答いただきありがとうございます。私はそのスレッドで説明されているようにAppIDを指定しました、そしてこれは問題を解決したようです。あなたがまだ説明したように通知が止まるかどうかを確かめるために徹底的なテストをしていません。うまくいけば。 :)
追加された 著者 Sean Kleinjung,

COMセキュリティによって、アプリが通知を受け取れなくなる可能性があります。解決方法については、次のスレッドを参照してください。レジストリハックを使用することをお勧めします。

https://social.msdn.microsoft.com/Forums/en-US/58da3fdb-a0e1-4161-8af3-778b6839f4e1/bluetooth-bluetoothledevicefromidasync-does-not-com-com-001-163 forum = wdk

私は同様の問題を抱えており、上記のレジストリの変更により、私のアプリは通知をほとんど受け取らず、明白な理由もなく停止します。 この問題に多くの時間を浪費し、マイクロソフトからのパッチを待つ。

1
追加された
回答いただきありがとうございます。私はそのスレッドで説明されているようにAppIDを指定しました、そしてこれは問題を解決したようです。あなたがまだ説明したように通知が止まるかどうかを確かめるために徹底的なテストをしていません。うまくいけば。 :)
追加された 著者 Sean Kleinjung,