Share via


DeviceInformationPairing.Custom 속성과 집합 페어링

참고 항목

일부 정보는 상업용으로 출시되기 전에 상당 부분 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.

Windows.Devices.Enumeration API를 사용하여 디바이스를 집합으로 페어링합니다.

Windows는 디바이스 컬렉션을 집합으로 페어링하도록 지원합니다. 플랫폼은 두 가지 유형의 집합을 지원합니다.

  • 자동으로 검색된 집합입니다. 이 문제는 프로토콜(예: Bluetooth LE)이 기본 엔드포인트를 페어링하는 동안 집합에 속한 다른 엔드포인트를 자동으로 검색할 때 발생합니다. 예를 들어 사용자가 Bluetooth LE를 통해 오른쪽 이어버드를 구문 분석하는 동안 프로토콜 스택은 왼쪽 이어버드를 검색할 수 있습니다. 따라서 둘 다 집합으로 함께 페어링할 수 있습니다.
  • 명시적 집합입니다. 둘 이상의 프로토콜을 통해 디바이스를 검색할 때 유용합니다. 예를 들어 IPP(인터넷 인쇄 프로토콜) 프린터는 일반적으로 IPP, WSD 및 eSCL의 세 가지 프로토콜을 통해 검색됩니다. 동일한 디바이스에 대한 여러 엔드포인트가 검색되면 명시적으로 집합으로 함께 페어링할 수 있습니다.

자동으로 검색된 집합에 대한 코드 예제(Bluetooth 스타일)

이 코드 예제에서는 사용자 지정 페어링 개체를 사용하여 자동으로 검색된(Bluetooth 스타일) 집합 페어링을 구현합니다. 사용자 지정 페어링 의 일반적인 구현과 마찬가지로 페어링 식을 처리하려면 페어링 요청 처리기가 필요합니다. 이 경우 코드 예제에서는 확인 전용 페어링 식만 구현합니다. 새롭고 흥미로운 부분은 pairing-set-member-requested 처리기를 추가하는 것입니다.

set-member-handler를 사용하면 플랫폼에서 전달된 디바이스를 집합으로 페어링할 수 있습니다. 해당 처리기가 없으면 프로토콜 스택은 페어링 집합의 멤버를 열거하려고 시도하지 않습니다. Bluetooth 프로토콜은 페어링을 완료하는 과정의 일부로 집합 멤버를 검색하므로 집합 처리기는 의식 처리기가 반환된 후 언젠가 호출됩니다. 이 흐름에서 집합 처리기는 일반적으로 집합 멤버의 고정 목록을 사용하여 의식을 처리한 후 한 번 호출될 것으로 예상할 수 있습니다. 즉, 프로토콜은 페어링 중에 사용할 수 있는 모든 엔드포인트를 검색하며 나중에 더 이상 검색되지 않습니다.

이 코드 예제에서는 검색된 모든 집합 멤버를 기본 디바이스/엔드포인트를 페어링하는 데 사용되는 동일한 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 코드 예제와 마찬가지로 새롭고 흥미로운 부분은 pairing-set-member-requested 처리기를 추가하는 것입니다. 집합 멤버 처리기를 사용하면 플랫폼에서 디바이스를 집합으로 페어링할 수 있습니다.

Bluetooth 스타일 집합 페어링 시나리오와 비교할 때 이 코드 예제에서는 명시적으로 디바이스를 집합에 추가합니다. Bluetooth에 비해 집합 처리기는 IPP 프린터 페어링과 관련된 프로토콜과 약간 다른 것을 의미합니다. 이는 클라이언트가 다양한 프로토콜을 통해 디바이스 검색을 처리하고 있으며, 모든 집합 멤버를 페어링한 결과로 생성된 PnP 상태 및 인쇄 큐를 동기화해야 했음을 의미합니다.

코드 예제의 구현을 간단하게 유지하기 위해 집합 멤버 엔드포인트의 벡터가 사전에 검색되어 기본 디바이스와 함께 매개 변수로 전달되었다고 가정합니다. 예를 들어 일반적인 IPP 시나리오에서 엔드포인트는 임의의 순서로 검색됩니다. 예를 들어 WSD를 통해 기본 디바이스를 검색할 수 있습니다. 그러면 벡터에는 IPP 및 eSCL을 통해 검색된 엔드포인트를 나타내는 디바이스가 포함됩니다. 그러나 모든 조합이 가능하고 유효합니다. 앱의 기본 스레드에서 기본 디바이스의 사용자 지정 페어링 개체에 집합 멤버를 추가한 다음 PairAsync를 호출합니다.

참고 항목

실제로 집합 멤버는 스레드에서 언제든지 사용자 지정 페어링 개체에 추가될 수 있습니다. 프로토콜에 대한 작업은 시간이 오래 걸리거나 시간이 초과될 때까지 차단될 수도 있으므로 겹치는 것이 유용합니다. API의 병렬 처리를 활용하여 디바이스를 동시에 추가하고 페어링하는 것이 좋습니다. 이는 여전히 유선으로 디바이스를 열거하는 동안에도 가능합니다. 집합으로 페어링할 때의 장점은 여전히 일반적으로 적용됩니다.

이 구현을 사용하면 기본 집합 멤버가 집합 멤버와 동시에 페어링됩니다. 집합 멤버는 처리기에서 동기적으로 한 번에 하나씩 페어링됩니다. 그러나 효율성 향상을 위해 병렬로 페어링할 수 있습니다.

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) to
        // a Bluetooth device. Note: there still might be no set members.
        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 auto-discovered Bluetooth set scenario.
        // Error handling can go here.
    }

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

일반 논평

자동으로 검색(Bluetooth 스타일) 집합 페어링

이 API는 기본 엔드포인트가 페어링된 후 프로토콜에 의해 집합 멤버가 검색되는 Bluetooth 스타일 집합 페어링을 수행하기 위해 필요합니다. 간단한 예는 무선 이어버드 집합일 수 있습니다. 첫 번째 이어버드의 페어링이 완료되면 디바이스는 세트의 일부로 페어링할 두 번째 디바이스가 있음을 PC에 알릴 수 있습니다. 사용자 지정 페어링 API는 앱이 새 집합 멤버 추가 상태 처리기를 통해 집합 작업을 처리할 수 있도록 확장됩니다.

명시적(IPP 스타일) 집합 페어링

마찬가지로 이 API를 사용하여 AEP(연결 엔드포인트) 디바이스 그룹을 집합으로 페어링할 수도 있습니다. 사용자 지정 페어링 개체를 사용하면 앱이 스레드에서 언제든지 페어링 집합에 다른 엔드포인트를 추가할 수 있습니다. 네트워크를 통한 디바이스 검색 및 페어링은 각 디바이스에 시간이 오래 걸릴 수 있으므로 이러한 작업을 방지할 수 있을 때 직렬화하지 않으려고 하기 때문입니다.

프로토콜 및 디바이스 스택이 쉽게 조정되지 않는 많은 프로토콜을 통해 디바이스를 검색할 때 집합에서 페어링하는 것이 특히 유용합니다. 예를 들어 최신 네트워크 프린터는 각각 연결 엔드포인트를 생성하는 세 가지 네트워크 프로토콜이 있는 Windows에서 검색될 가능성이 높습니다. 이 경우 세 개의 엔드포인트를 모두 세트로 페어링하는 것은 몇 가지 이유로 매우 유용합니다. 이 경우 와이어를 통해 낭비되는 검색을 방지하고 단일 간소화된 인쇄 큐를 만듭니다.

네트워크 프린터가 집합으로 페어링되지 않더라도 인쇄 스풀러는 여러 프로토콜을 통해 페어링할 수 있는지 여부에 관계없이 사용자당 단일 인쇄 큐를 만들려고 시도합니다. 프린터가 처음에 하나의 프로토콜을 통해 쌍을 이루는 경우 운영 체제(OS)는 지원되는 다른 프로토콜을 통해 프린터를 다시 검색하고 중복 인쇄 큐를 방지하기 위해 모든 프로토콜에 연결하려고 시도합니다. 일반적으로 OS는 이를 빠르고 성공적으로 수행하고 하나의 간소화된 인쇄 큐를 생성할 수 있습니다.

그러나 앱이 프린터의 모든 엔드포인트를 이미 검색한 경우 이 검색 단계는 낭비됩니다. 그리고 더 나쁜, 프린터를 사용할 준비가 되기 전에 긴 지연을 추가할 수 있습니다. 또한 프로토콜이 너무 동기화되지 않거나 지연된 경우 스풀러는 동일한 프린터에 대한 추가 인쇄 큐를 만들어야 할 수 있으므로 최종 사용자에게 혼동을 줄 수 있습니다.

집합으로 모든 엔드포인트를 한 번에 페어링하면 잠재적으로 느린 검색을 방지할 수 있습니다. PnP 상태가 동기화되고 최적의 간소화된 인쇄 큐를 생성합니다.

디바이스 노드 동기화

디바이스가 이 API와 집합으로 페어링되면 결과 PnP 디바이스 상태가 편리하게 동기화됩니다. API는 앱이 설정된 멤버를 추가할 수 있는 시기를 제한하지 않지만 플랫폼이 디바이스 노드를 동기화할 수 있는 시기에는 제한이 있습니다. 집합의 모든 엔드포인트에 페어링이 완료될 때까지 디바이스 노드 동기화가 차단됩니다. 그런 다음 모든 엔드포인트에 대한 모든 디바이스 노드가 한 번에 만들어집니다. 해당 시점 이후에 집합에 집합 멤버를 더 추가할 수 있지만 후속 디바이스 노드 만들기는 차단되지 않지만 대신 바로 만들어집니다.

  • 다음과 같은 경우 디바이스 노드 만들기 동기화됩니다.
    • 집합 멤버는 페어링이 시작되기 전에 추가됩니다.
    • 집합 멤버 중 하나 이상이 완료되지 않은 동안 집합 멤버가 추가됩니다.
  • 디바이스 노드 만들기가 동기화되지 않습니다 .
    • 추가된 모든 집합 멤버가 종료된 후 언제든지.

실제로 API는 디바이스 노드가 동기화되는 방식에 이 동작에 영향을 미치기 위해 의식 종료가 완료되는 시기를 앱이 제어하는 것을 허용하지 않습니다. 가장 가까운 근사값은 앱이 의식을 완료하도록 선택할 때입니다. 앱의 의식 처리기가 반환될 때까지 페어링을 완료할 수 없습니다. 따라서 모든 집합 멤버가 완료될 때 앱이 영향을 줄 수 있는 마지막 기회입니다.