Compartilhar via


Emparelhando um conjunto com a propriedade DeviceInformationPairing.Custom

Observação

Algumas informações relacionam-se ao produto de pré-lançamento, o qual poderá ser substancialmente modificado antes do lançamento comercial. A Microsoft não oferece nenhuma garantia, explícita ou implícita, quanto às informações fornecidas aqui.

Use as APIs Windows.Devices.Enumeration para emparelhar dispositivos como um conjunto.

O Windows dá suporte ao emparelhamento de uma coleção de dispositivos como um conjunto. A plataforma dá suporte a dois tipos de conjunto.

  • Conjunto descoberto automaticamente. Isso ocorre quando um protocolo (como Bluetooth LE) descobre automaticamente outros pontos de extremidade que pertencem ao conjunto durante o emparelhamento de um ponto de extremidade principal. Por exemplo, enquanto um usuário está emparelhando o fone de ouvido direito por meio do Bluetooth LE, a pilha de protocolos pode descobrir o fone de ouvido esquerdo, para que ambos possam ser emparelhados juntos como um conjunto.
  • Conjunto explícito. Eles são úteis quando um dispositivo é descoberto por meio de mais de um protocolo. Por exemplo, as impressoras IPP (Internet Printing Protocol) geralmente são descobertas por meio de três protocolos: IPP, WSD e eSCL. Quando vários pontos de extremidade para o mesmo dispositivo são descobertos, eles podem ser explicitamente emparelhados juntos como um conjunto.

Exemplo de código para um conjunto descoberto automaticamente (estilo Bluetooth)

Este exemplo de código implementa o emparelhamento de conjuntos descobertos automaticamente (estilo Bluetooth) usando um objeto de emparelhamento personalizado. Como ocorre com uma implementação típica de emparelhamento personalizado, um pairing-requested handler é requerido para lidar com a cerimônia de emparelhamento. Nesse caso, o exemplo de código implementa apenas a cerimônia de emparelhamento confirm only. A parte nova e interessante é adicionar um manipulador pairing-set-member-requested.

O set-member-handler permite que a plataforma tente emparelhar o dispositivo passado como um conjunto. Sem esse manipulador, a pilha de protocolos não tentará enumerar os membros de um conjunto de emparelhamento. O protocolo Bluetooth descobre set members como parte da finalização do emparelhamento, de modo que o set handler seja chamado algum tempo depois que seu manipulador de cerimônia é retornado. Nesse fluxo, o set handler geralmente pode esperar ser chamado uma vez depois de lidar com a cerimônia com uma lista fixa de set members; o que significa que o protocolo descobre todos os pontos de extremidade que pode durante o emparelhamento, e não descobrirá mais tarde.

Este exemplo de código emparelha de forma síncrona todos os discovered set members com a mesma rotina BtSetPairing usada para emparelhar o dispositivo/ponto de extremidade principal. Também há suporte para o emparelhamento em paralelo, o qual pode ser mais eficiente para o seu cenário. Porém, para simplificar, isso não é mostrado no exemplo de código. Como também estamos emparelhando os set members com um set handler, é bem provável que eles produzam recursivamente mais set members para serem emparelhados. Porém, geralmente, o set handler dos discovered set members provavelmente verá apenas uma discovery completed com o vetor set member vazio.

Observação

Este exemplo de código está sem o contexto de um cenário ou aplicativo maior, mas um aplicativo provavelmente precisará rastrear quais dispositivos está emparelhando e os resultados do emparelhamento. Isso ocorre para que o aplicativo tenha uma noção se toda a operação set-pairing foi bem-sucedida ou não.

Observação

Essas APIs geralmente são assíncronas. As operações de emparelhamento têm seus próprios threads de trabalho, e os manipuladores são chamados em threads diferentes. Seu código não precisa ser bloqueado com a mesma frequência que este exemplo de código.

Exemplo de código em 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);
    }
}

Exemplo de código para um conjunto explícito (estilo IPP)

Este exemplo de código implementa o emparelhamento de conjunto explícito usando um objeto de emparelhamento personalizado. Como ocorre com uma implementação típica de emparelhamento personalizado, um pairing-requested handler é requerido para lidar com a cerimônia de emparelhamento. Nesse caso, o exemplo de código implementa apenas a cerimônia de emparelhamento confirm only. Assim como no exemplo de código Bluetooth, a parte nova e interessante é adicionar um manipulador pairing-set-member-requested. O set member handler permite que a plataforma tente emparelhar dispositivos como um conjunto.

Em comparação com o cenário set-pairing no estilo Bluetooth, este exemplo de código adiciona explicitamente dispositivos ao conjunto. Em comparação com o Bluetooth, o set handler implica algo um pouco diferente dos protocolos relacionados ao emparelhamento de impressoras IPP. Isso significa que os clientes estão processando a descoberta de dispositivos nos vários protocolos, e o estado PnP e as filas de impressão criadas como resultado do emparelhamento de todos os set members devem ser sincronizados.

Para manter a implementação do exemplo de código simples, ele assume que um vetor de pontos de extremidade set member foram descobertos antecipadamente e transmitidos como um parâmetro junto com o dispositivo principal. Por exemplo, em um cenário IPP típico, os pontos de extremidade são descobertos em ordem arbitrária. Dessa forma, o dispositivo principal poderá ter sido descoberto por meio do WSD, por exemplo. Em seguida, o vetor conterá dispositivos que representam os pontos de extremidade descobertos por meio de IPP e eSCL. Porém, qualquer combinação é possível e válida. Ele adiciona set members ao objeto de emparelhamento personalizado do dispositivo principal no thread principal do aplicativo e, em seguida, chama PairAsync.

Observação

Na prática, set members podem ser adicionados a um objeto de emparelhamento personalizado a qualquer momento em qualquer thread. As operações em um protocolo podem levar muito tempo ou até mesmo ser bloqueadas até que atinjam o tempo limite, portando, é útil sobrepô-las. Considere a possibilidade de aproveitar o paralelismo da API para adicionar e emparelhar dispositivos simultaneamente. Isso é possível mesmo quando você ainda está enumerando dispositivos eletronicamente. As vantagens de emparelhá-los como um conjunto geralmente ainda se aplicam.

Com essa implementação, o set member principal será emparelhado simultaneamente com os set members. Os set members são emparelhados um de cada vez de forma síncrona no manipulador. Porém, novamente, eles podem ser emparelhados em paralelo para melhor eficiência.

Os objetos de nó de dispositivo no PnP geralmente são criados como resultado do emparelhamento. No caso do IPP, os nós de dispositivo são sempre criados para cada ponto de extremidade após o emparelhamento. Essa API set-pairing sincroniza implicitamente a criação de nós de dispositivo entre pontos de extremidade no conjunto. Neste fluxo de exemplo de código, todos os nós de dispositivo serão sincronizados porque todos os set members serão adicionados antes do início do emparelhamento. Para obter mais detalhes sobre como essa API sincroniza os nós de dispositivo no PnP, consulte a seção Comentários gerais neste tópico.

Observação

Este exemplo de código está sem o contexto de um cenário ou aplicativo maior, mas um aplicativo provavelmente precisará rastrear quais dispositivos está emparelhando e os resultados do emparelhamento. Isso ocorre para que o aplicativo tenha uma noção se toda a operação set-pairing foi bem-sucedida ou não.

Exemplo de código em 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);
    }
}

Comentários gerais

Emparelhamento de conjunto descoberto automaticamente (estilo Bluetooth)

Essa API é necessária para realizar o emparelhamento de conjuntos no estilo Bluetooth, em que os set members são descobertos pelo protocolo depois que o ponto de extremidade principal é emparelhado. Um exemplo simples pode ser um conjunto de fones de ouvido sem fio. À medida que o emparelhamento do primeiro fone de ouvido é finalizado, o dispositivo informa ao computador que há um segundo dispositivo a ser emparelhado como parte do conjunto. A API de emparelhamento personalizado é estendida para permitir que os aplicativos manipulem as operações de conjuntos por meio do novo handler add set member status.

Emparelhamento de conjunto explícito (estilo IPP)

Da mesma forma, você também pode usar essa API para emparelhar qualquer grupo de dispositivos de ponto de extremidade de associação (AEP) como um conjunto. Com um objeto de emparelhamento personalizado, seu aplicativo pode adicionar outros pontos de extremidade ao conjunto de emparelhamento a qualquer momento em qualquer thread. Isso ocorre por design porque a descoberta e o emparelhamento de dispositivo em uma rede podem levar muito tempo para cada dispositivo, portanto, não queremos serializar essas operações quando podemos evitá-las.

É útil emparelhar conjuntos principalmente ao descobrir dispositivos em muitos protocolos em que as pilhas de protocolo e dispositivo não são facilmente coordenadas. Por exemplo, uma impressora de rede moderna provavelmente será descoberta pelo Windows com três protocolos de rede diferentes, cada um dos quais gera pontos de extremidade de associação. Nesse caso, é muito útil emparelhar todos os três pontos de extremidade como um conjunto por alguns motivos: evita a redescoberta desnecessária eletronicamente e cria uma única fila de impressão simplificada.

Mesmo que uma impressora de rede não esteja emparelhada como um conjunto, o spooler de impressão ainda tentará criar uma única fila de impressão por usuário, independentemente de poder ser emparelhada em vários protocolos. Se uma impressora for inicialmente emparelhada por meio de um protocolo, o sistema operacional (SO) tentará redescobri-la por meio dos outros protocolos compatíveis e associá-la a todos eles para evitar filas de impressão duplicadas. Geralmente, o sistema operacional pode fazer isso de forma rápida e com sucesso e gerar uma fila de impressão simplificada.

No entanto, se o aplicativo já tiver descoberto todos os pontos de extremidade da impressora, essa etapa de redescoberta será desnecessária. E pior, longos atrasos poderão ser adicionados antes que a impressora esteja pronta para uso. Além disso, se os protocolos estiverem muito fora de sincronização ou atrasados, o spooler talvez precise criar filas de impressão extras para a mesma impressora, o que é confuso para os usuários finais.

O emparelhamento de todos os pontos de extremidade de uma só vez como um conjunto evita a redescoberta potencialmente lenta. Ele garante que o estado PnP seja sincronizado e gera filas de impressão simplificadas ideais.

Sincronização de nó de dispositivo

Quando os dispositivos são emparelhados como um conjunto com essa API, o estado do dispositivo PnP resultante é convenientemente sincronizado. A API não restringe quando um aplicativo pode adicionar um set member, mas há limites sobre quando a plataforma pode sincronizar nós de dispositivo. A sincronização do nó do dispositivo será bloqueada até que todos os pontos de extremidade no conjunto tenham seu emparelhamento finalizado. Depois disso, todos os nós de dispositivo para todos os pontos de extremidade serão criados de uma só vez. Você pode adicionar mais set members ao conjunto após esse ponto, mas nenhuma criação de nó de dispositivo subsequente é bloqueada, mas é criada imediatamente.

  • A criação do nó do dispositivo é sincronizada quando:
    • Set members são adicionados antes do início do emparelhamento.
    • Set members são adicionados enquanto pelo menos um dos set members não é finalizado.
  • A criação do nó do dispositivo não é sincronizada:
    • A qualquer momento depois que todos os set members foram finalizados.

Por uma questão prática, a API não permite que um aplicativo controle quando a finalização da cerimônia é concluída para influenciar esse comportamento sobre como os nós de dispositivo são sincronizados. A aproximação mais próxima será quando o aplicativo escolher concluir a cerimônia. Um emparelhamento não pode ser finalizado até que o manipulador de cerimônia do aplicativo retorne; portanto, essa será a última chance do aplicativo influenciar quando todos os set members forem finalizados.