次の方法で共有


DeviceInformationPairing.Custom プロパティでセットをペアリングする

一部の情報はプレリリース製品に関連しており、商用リリース前に大幅に変更される可能性があります。 Microsoft は、ここで提供される情報に関して明示的または黙示的な保証を行いません。

Windows.Devices.Enumeration API を使用して、デバイスをセットとしてペアリングします。

Windows では、デバイスのコレクションをセットとしてペアリングできます。 プラットフォームでは、2 種類のセットがサポートされています。

  • 自動的に検出されたセット。 これは、プロトコル (Bluetooth LE など) が、プライマリ エンドポイントのペアリング中にセットに属する他のエンドポイントを自動的に検出する場合に発生します。 たとえば、ユーザーが右のイヤホンを LE でBluetoothしている間に、プロトコル スタックが左側のイヤホンを検出する場合があります。したがって、両方をセットとしてペアにすることができます。
  • 明示的な設定。 これらは、デバイスが複数のプロトコルを介して検出された場合に便利です。 たとえば、インターネット印刷プロトコル (IPP) プリンターは、通常、IPP、WSD、eSCL の 3 つのプロトコルを介して検出されます。 同じデバイスの複数のエンドポイントが検出された場合は、セットとして明示的にペアにすることができます。

自動的に検出されたセット (Bluetooth スタイル) のコード例

このコード例では、カスタム ペアリング オブジェクトを使用して、自動検出 (Bluetooth スタイル) セットのペアリングを実装します。 カスタム ペアリングの一般的な実装と同様に、 ペアリングの処理には、ペアリング要求ハンドラー が必要です。 この場合、コード例は確認のみのペアリング式を実装します。 新しい興味深い部分は、 ペアリングセットメンバー要求ハンドラーを 追加することです。

set-member-handler を使用すると、プラットフォームは、渡されたデバイスをセットとしてペアリングしようとします。 そのハンドラーがないと、プロトコル スタックはペアリング セットのメンバーの列挙を試みることはありません。 Bluetooth プロトコルは、ペアリングの最終処理の一環としてセットメンバーを検出するため、セレモニーハンドラーが返された後にセットハンドラーが呼び出されます。 このフローでは、一般に、set ハンドラーは、セット メンバーの固定リストを使用して式を処理した後に 1 回呼び出されることが想定されます。つまり、プロトコルはペアリング中に可能なすべてのエンドポイントを検出し、後でそれ以上検出することはありません。

このコード例では、検出されたすべてのセット メンバーを、プライマリ デバイスとエンドポイントのペアリングに使用される同じ BtSetPairing ルーチンと同期的にペアリングします。 それらを並列でペアリングすることもサポートされており、シナリオの効率が向上する可能性があります。 ただし、わかりやすくするために、これはコード例では示されていません。 セット メンバーとセット ハンドラーのペアリングも行っているため、ペアにするセット メンバーを再帰的に生成する可能性があります。 一般的に、検出されたセットメンバーのセットハンドラーは、セットメンバーベクターが空の状態で探索が完了したことしか表示されないでしょう。

このコード例には、大規模なシナリオやアプリのコンテキストはありません。ただし、アプリでは、ペアリングしているデバイスとペアリングの結果を追跡する必要があります。 これは、アプリがセット ペアリング操作全体が成功したかどうかを把握するためです。

これらの API は通常非同期です。 ペアリング操作には独自のワーカー スレッドがあり、ハンドラーは異なるスレッドで呼び出されます。 コードは、このコード例ほど頻繁にブロックする必要はありません。

C++/WinRT のコード例

void PairingTests::BtSetPairing(DeviceInformation device)
{
    DevicePairingKinds ceremonies = DevicePairingKinds::ConfirmOnly;
    auto customPairing = device.Pairing().Custom();
    event_revoker ceremonyEventToken = customPairing.PairingRequested(
        { this, &PairingTests::PairingRequestedHandler });
    event_revoker setEventToken = customPairing.PairingSetMembersRequested(
        { this, &PairingTests::PairingSetMembersRequestedHandler });

    DevicePairingResult result = customPairing.PairAsync(ceremonies).get();

    if (DevicePairingResultStatus::Paired == result.Status()) // Pairing worked.
    else // Handle pairing failure.
}

void PairingTests::PairingRequestedHandler(DeviceInformationCustomPairing const&,
    DevicePairingRequestedEventArgs const& args)
{
    switch (args.PairingKind())
    {
    case DevicePairingKinds::ConfirmOnly:
        args.Accept();
        break;
    default:
        // This code example doesn't implement other ceremonies.
        // The handler wouldn't be called for ceremonies that the app didn't register.
    }
}

void PairingTests::PairingSetMembersRequestedHandler(DeviceInformationCustomPairing
    const&, DevicePairingSetMembersRequestedEventArgs const& args)
{
    switch (args.Status())
    {
    case DevicePairingAddPairingSetMemberStatus::SetDiscoveryCompletedByProtocol:
        // This is the expected result if we started set pairing 
        // a Bluetooth device. Note: there still might be no set members.
        break;
    case DevicePairingAddPairingSetMemberStatus::SetDiscoveryPartiallyCompletedByProtocol:
        // The protocol enumerated some but not all set members.
        break;
    case DevicePairingAddPairingSetMemberStatus::SetDiscoveryNotAttemptedByProtocol:
        // Not expected for Bluetooth.
        // This constant implies that the protocol likely doesn't support set-pairing.
    default:
        // The other constants aren't expected in an auto-discovered Bluetooth set scenario.
        // Error handling can go here.
    }

    for (auto setMember : args.PairingSetMembers())
    {
        BtSetPairing(setMember);
    }
}

明示的なセットのコード例 (IPP スタイル)

このコード例では、カスタム ペアリング オブジェクトを使用して明示的なセット ペアリングを実装します。 カスタム ペアリングの一般的な実装と同様に、 ペアリングの処理には、ペアリング要求ハンドラー が必要です。 この場合、コード例は確認のみのペアリング式を実装します。 Bluetoothコード例と同様に、新しい興味深い部分は、 ペアリングセットメンバー要求 ハンドラーを追加することです。 set メンバー ハンドラーを使用すると、プラットフォームはデバイスをセットとしてペアリングしようとします。

このコード例は、Bluetooth スタイルのセット ペアリング シナリオと比較して、明示的にデバイスをセットに追加します。 また、設定ハンドラーは、IPP プリンターのペアリングに関連するプロトコルに対して少し異なる何かを意味します。 これは、クライアントがさまざまなプロトコルを介してデバイスの検出を処理していることを意味し、すべてのセット メンバーをペアリングした結果として作成された PnP 状態と印刷キューを同期する必要があります。

コード例の実装をシンプルにするために、セット メンバー エンドポイントのベクトルが事前に検出され、プライマリ デバイスと共にパラメーターとして渡されることを前提としています。 たとえば、一般的な IPP シナリオでは、エンドポイントは任意の順序で検出されます。 そのため、たとえば、プライマリ デバイスが WSD 経由で検出された可能性があります。ベクトルには、IPP 経由で検出されたエンドポイントと eSCL を表すデバイスが含まれます。 ただし、任意の組み合わせが可能で有効です。 アプリのメイン スレッド上のプライマリ デバイスのカスタム ペアリング オブジェクトにセット メンバーを追加し、 PairAsync を呼び出します。

実際には、セット メンバーは、任意のスレッドでいつでもカスタム ペアリング オブジェクトに追加される場合があります。 プロトコルに対する操作には時間がかかる場合や、タイムアウトするまでブロックされる場合があるため、重複すると便利です。 API の並列処理を利用して、デバイスを同時に追加およびペアリングすることを検討してください。 これは、ネットワーク経由でデバイスを列挙している間でも可能です。 セットとしてペアリングする利点は、一般的に適用されます。

この実装では、プライマリ セット メンバーはセット メンバーと同時にペアになります。 セット メンバーは、ハンドラー内で 1 つずつ同期的に組み合わされます。 しかし、再び、効率を向上するために並列でペアにすることができます。

PnP のデバイス ノード オブジェクトは、多くの場合、ペアリングの結果として作成されます。 IPP の場合、デバイス ノードは、ペアリング後にエンドポイントごとに常に作成されます。 このセット ペアリング API は、セット内のエンドポイント間でデバイス ノードの作成を暗黙的に同期します。 このコード例のフローでは、ペアリングが開始される前にすべてのセット メンバーが追加されるため、すべてのデバイス ノードが同期されます。 この API が PnP でデバイス ノードを同期する方法の詳細については、このトピックの 「一般的な解説 」セクションを参照してください。

このコード例には、大規模なシナリオやアプリのコンテキストはありません。ただし、アプリでは、ペアリングしているデバイスとペアリングの結果を追跡する必要があります。 これは、アプリがセット ペアリング操作全体が成功したかどうかを把握するためです。

C++/WinRT のコード例

void PairingTests::IppSetPairing(DeviceInformation device,
    std::vector<DeviceInformation> const& setMemberDevices)
{
    DevicePairingKinds ceremonies = DevicePairingKinds::ConfirmOnly;
    auto customPairing = device.Pairing().Custom();
    event_revoker ceremonyEventToken = customPairing.PairingRequested({ this,
                     &PairingTests::PairingRequestedHandler });
    event_revoker setEventToken = customPairing.PairingSetMembersRequested({ this,
                  &PairingTests::PairingSetMembersRequestedHandler });

    if (setMemberDevices)
    {
        for (auto setDevice : setMemberDevices)
        {
            customPairing.AddPairingSetMember(setDevice);
        }
    }

    DevicePairingResult result = customPairing.PairAsync(ceremonies).get();

    if (DevicePairingResultStatus::Paired == result.Status()) // Pairing worked.
    else // Handle pairing failure.
}

void PairingTests::PairingRequestedHandler(DeviceInformationCustomPairing const&,
    DevicePairingRequestedEventArgs const& args)
{
    switch (args.PairingKind())
    {
    case DevicePairingKinds::ConfirmOnly:
        args.Accept();
        break;
    }
}

void PairingTests::PairingSetMembersRequestedHandler(DeviceInformationCustomPairing const&,
    DevicePairingSetMembersRequestedEventArgs args)
{
    switch (args.Status())
    {
    case DevicePairingAddPairingSetMemberStatus::AddedToSet:
        // This is the expected result of adding a set member(s)
        // by calling the AddPairingSetMember method.
        break;
    case DevicePairingAddPairingSetMemberStatus::CouldNotBeAddedToSet:
        // Means we failed to add set member(s).
        break;
    case DevicePairingAddPairingSetMemberStatus::SetDiscoveryNotAttemptedByProtocol:
    default:
        // The other constants aren't expected in an explicit set scenario.
        // Error handling can go here.
    }

    for (auto setMember : args.PairingSetMembers())
    {
        IppSetPairing(setMember, nullptr);
    }
}

一般的な解説

自動的に検出された (Bluetooth スタイル) デバイスセットのペアリング

この API は、プライマリ エンドポイントがペアになった後にプロトコルによってセット メンバーが検出されるBluetoothスタイルのセット ペアリングを実現するために必要です。 簡単な例として、ワイヤレス イヤホンのセットがあります。 最初のイヤホンのペアリングが完了すると、デバイスはセットの一部としてペアリングする 2 つ目のデバイスがあることを PC に通知します。 カスタム ペアリング API が拡張され、アプリは新しい add set メンバー ステータス ハンドラーを介してセット操作を処理できます。

明示的 (IPPスタイル) 集合ペアリング

同様に、この API を使用して、関連付けエンドポイント (AEP) デバイスの任意のグループをセットとしてペアリングすることもできます。 カスタム ペアリング オブジェクトを使用すると、アプリは任意のスレッドでいつでもペアリング セットに他のエンドポイントを追加できます。 これは、ネットワーク経由でのデバイスの検出とペアリングがデバイスごとに長い時間がかかる可能性があるため、これらの操作を回避できる場合はシリアル化したくないためです。

プロトコルとデバイス スタックが簡単に調整されない多くのプロトコルでデバイスを検出する場合は、セットでペアリングすると特に便利です。 たとえば、最新のネットワーク プリンターは、3 つの異なるネットワーク プロトコルを持つ Windows によって検出され、それぞれが関連付けエンドポイントを生成します。 その場合、3 つのエンドポイントすべてをセットとしてペアリングすることは、いくつかの理由で非常に便利です。ネットワーク経由の無駄な再情報開示を回避し、1 つの合理化された印刷キューを作成します。

ネットワーク プリンターがセットとしてペアリングされていない場合でも、印刷スプーラーは、複数のプロトコルでペアリングできるかどうかに関係なく、ユーザーごとに 1 つの印刷キューを作成しようとします。 プリンターが最初に 1 つのプロトコルでペアリングされている場合、オペレーティング システム (OS) は、サポートされている他のプロトコルで再検出を試み、印刷キューが重複しないようにすべてのプロトコルに関連付けます。 通常、OS は、これを迅速かつ正常に実行し、合理化された 1 つの印刷キューを生成できます。

ただし、アプリがプリンターのすべてのエンドポイントを既に検出している場合、この再情報開示手順は無駄になります。 さらに悪いことに、プリンターを使用する準備が整う前に、長い遅延が発生する可能性があります。 また、プロトコルがあまりにも同期されていないか遅延している場合、スプーラーは同じプリンター用に追加の印刷キューを作成する必要があり、エンド ユーザーにとって混乱を招く可能性があります。

すべてのエンドポイントをまとめてセットとしてペアリングすると、スムーズに再検出が行えるようになります。 これにより、PnP 状態が同期され、最適な合理化された印刷キューが生成されます。

デバイス ノードの同期

デバイスがこの API とセットとしてペアリングされると、結果として得られる PnP デバイスの状態が簡単に同期されます。 アプリが set メンバーを追加できる 場合 、API は制約されません。ただし、プラットフォームでデバイス ノードを同期できるタイミングには制限があります。 デバイス ノードの同期は、セット内のすべてのエンドポイントのペアリングが完了するまでブロックします。 その後、すべてのエンドポイントのすべてのデバイス ノードが一度に作成されます。 その後、セット メンバーをさらにセットに追加できますが、後続のデバイス ノードの作成はブロックされませんが、代わりにすぐに作成されます。

  • デバイス ノード の作成は、 次の場合に同期されます。
    • ペアリングが開始される前に、セット メンバーが追加されます。
    • セットメンバーは、少なくとも1つのセットメンバーが確定していない間に追加されます。
  • デバイス ノードの作成は同期 されません
    • 追加されたすべてのセットメンバーが確定した後は、いつでも。

実際には、この API では、デバイス ノードの同期方法にこの動作に影響を与えるために、式の最終処理がいつ完了するかをアプリが制御することはできません。 最も近い近似値は、アプリが式を完了することを選択した場合です。 ペアリングは、アプリのセレモニーハンドラーが戻るまで確定できません。それで、これはすべてのセットメンバーが最終確定する時期に影響を与えるためのアプリの最後の機会です。