LoginSignup
8
8

More than 3 years have passed since last update.

[C#/WinRT] WPFでBluetooth v4(BLE)機器とペアリングする

Last updated at Posted at 2019-08-17

BLE関連記事

やりたいこと

BLE機器をペアリングするときに、Windowsの設定画面でペアリングするのではなく、プログラム中にペアリング処理をいれたい。

やり方

こちらでやったようにしてDeviceInformationを取得して、それをもとに、ペアリングを行う。サンプルは下記。

ペアリング.cs
private async void DoPairing(DeviceInformation devInfo)
{
    // devInfoが、watcherで取得したデバイス情報。
    if (devInfo == null) return;

    if (devInfo.Pairing.IsPaired == false)
    {
        DeviceInformationCustomPairing customPairing = devInfo.Pairing.Custom;
        customPairing.PairingRequested += PairingRequestedHandler;
        DevicePairingResult result = await customPairing.PairAsync(DevicePairingKinds.ConfirmOnly, DevicePairingProtectionLevel.Default);
        customPairing.PairingRequested -= PairingRequestedHandler;
        Debug.WriteLine($"ペアリング結果:{result.Status}");
    }
    else
    {
        // すでにペアリング済み
    }
}
ペアリング解除.cs
private async void DoUnpairing(DeviceInformation devInfo)
{
    if (devInfo == null) return;

    if (devInfo.Pairing.IsPaired == true)
    {
        var result = await devInfo.Pairing.UnpairAsync();
        Debug.WriteLine($"ペアリング解除結果:{result.Status}");
    }
    else
    {
        // すでにペアリング解除済み
    }
}
ペアリング要求時のハンドラ.cs
private static void PairingRequestedHandler(DeviceInformationCustomPairing sender, DevicePairingRequestedEventArgs args)
{
    switch (args.PairingKind)
    {
        case DevicePairingKinds.ConfirmOnly:
            args.Accept();
            break;
    }
}

ペアリング要求時のハンドラについて

下記に、上のコードの基にしたマイクロソフトのペアリングのサンプルがある。

■コードのサンプル
https://github.com/microsoft/Windows-universal-samples/blob/master/Samples/DeviceEnumerationAndPairing/cs/Scenario9_CustomPairDevice.xaml.cs

■DevicePairingKindsのenumについて
https://docs.microsoft.com/en-us/uwp/api/windows.devices.enumeration.devicepairingkinds

このハンドラ(ここではPairingRequestedHandler)では、アプリのユーザーに「本当にペアリングしてよいですか?」や「パスワードを入力してください」、「今表示しているPINコードを、相手のデバイスに入力してください」などの「確認」の制御を行う。

上のサンプルでは、簡単のために何も確認せずにペアリングを実行するようにしたが、MSのサンプルでは、下記のように各種確認ダイアログの表示を行っていた。

Scenario9_CustomPairDevice.xaml.cs
private async void PairingRequestedHandler(
    DeviceInformationCustomPairing sender,
    DevicePairingRequestedEventArgs args)
{
    switch (args.PairingKind)
    {
        case DevicePairingKinds.ConfirmOnly:
            // Windows itself will pop the confirmation dialog as part of "consent" if this is running on Desktop or Mobile
            // If this is an App for 'Windows IoT Core' where there is no Windows Consent UX, you may want to provide your own confirmation.
            args.Accept();
            break;

        case DevicePairingKinds.DisplayPin:
            // We just show the PIN on this side. The ceremony is actually completed when the user enters the PIN
            // on the target device. We automatically accept here since we can't really "cancel" the operation
            // from this side.
            args.Accept();

            // No need for a deferral since we don't need any decision from the user
            await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
            {
                ShowPairingPanel(
                    "Please enter this PIN on the device you are pairing with: " + args.Pin,
                    args.PairingKind);

            });
            break;

        case DevicePairingKinds.ProvidePin:
            // A PIN may be shown on the target device and the user needs to enter the matching PIN on
            // this Windows device. Get a deferral so we can perform the async request to the user.
            var collectPinDeferral = args.GetDeferral();

            await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                string pin = await GetPinFromUserAsync();
                if (!string.IsNullOrEmpty(pin))
                {
                    args.Accept(pin);
                }

                collectPinDeferral.Complete();
            });
            break;

        case DevicePairingKinds.ProvidePasswordCredential:
            var collectCredentialDeferral = args.GetDeferral();
            await rootPage.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                var credential = await GetPasswordCredentialFromUserAsync();
                if (credential != null)
                {
                    args.AcceptWithPasswordCredential(credential);
                }
                collectCredentialDeferral.Complete();
            });
            break;

        case DevicePairingKinds.ConfirmPinMatch:
            // We show the PIN here and the user responds with whether the PIN matches what they see
            // on the target device. Response comes back and we set it on the PinComparePairingRequestedData
            // then complete the deferral.
            var displayMessageDeferral = args.GetDeferral();

            await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async () =>
            {
                bool accept = await GetUserConfirmationAsync(args.Pin);
                if (accept)
                {
                    args.Accept();
                }

                displayMessageDeferral.Complete();
            });
            break;
    }
}
enum名 意味
DevicePairingKinds.ConfirmOnly ペアリングするか確認だけ行う。今回のサンプルでは確認ダイアログを出したりはしていない。確認ダイアログ必要な場合は、Accept()の前にダイアログを出す処理を書いて、OKを押したときだけAccept()する、などしてやる
DevicePairingKinds.ConfirmPinMatch ユーザーにPINを表示して、「表示中のPINは相手のデバイスに表示されているPINと一致していますか?」という確認をさせる
DevicePairingKinds.DisplayPin ユーザーにPINを表示して、「表示中のPINを相手のデバイスに入力してください」という指示をする
DevicePairingKinds.None ペアリングに対応していない
DevicePairingKinds.ProvidePasswordCredential ユーザーにパスワードを入力させる
DevicePairingKinds.ProvidePin ユーザーにPINを入力させる

※詳細は、こちら参照。

8
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
8