將集合與 DeviceInformationPairing.Custom 屬性配對
注意
針對發行前產品的部分相關資訊,在產品正式發行時可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。
使用 Windows.Devices.Enumeration API 將裝置配對為集合。
Windows 支援將裝置集合配對為集合。 平台支援兩種類型的集合。
- 自動探索到的集合。 當通訊協定(例如藍牙 LE)在配對主要端點時自動探索屬於集合的其他端點時,就會發生這種情況。 例如,當使用者透過藍牙 LE 剖析右耳塞時,通訊協定堆疊可能會發現左耳塞;因此,兩者可以配對成一組。
- 明確設定。 當透過多個通訊協定探索到裝置時,這些會很有用。 例如,因特網列印通訊協定 (IPP) 印表機通常會透過三種通訊協定來探索:IPP、WSD 和 eSCL。 當探索到相同裝置的多個端點時,可以將這些端點明確配對為集合。
自動探索集的程式代碼範例 (藍牙樣式)
此程式代碼範例會使用自定義配對對對象來實作自動探索的 (藍牙樣式) 設定配對。 如同自定義配對的一般實作, 需要配對要求的處理程序 來處理配對儀式。 在此情況下,程式代碼範例只會實作確認 配對 儀式。 新的和有趣的部分是新增配對 set-member-requested 處理程式。
set-member-handler 可讓平台嘗試將傳入的裝置配對為集合。 如果沒有該處理程式,通訊協定堆疊就不會嘗試列舉配對集的成員。 藍牙通訊協定會在完成配對時探索設定成員,因此會在其儀式處理程式傳回之後呼叫集合處理程式。 在此流程中,設定處理程式通常會在處理具有固定集合成員清單的儀式之後呼叫一次;這表示通訊協定會在配對期間探索其所有端點,且稍後不會探索更多端點。
此程式代碼範例會同步配對所有探索到的集合成員與用來配對主要裝置/端點的相同 BtSetPairing 例程。 也支援以平行方式配對它們,而且對於您的案例可能更有效率。 但為了簡單起見,這不會顯示在程式碼範例中。 由於我們也將 set 成員與 set 處理程式配對,因此它們可能會以遞歸方式產生要配對的更多集合成員。 但一般而言,探索到集合成員的 set 處理程式可能只會看到 探索已完成 ,且集合成員向量是空的。
注意
此程式代碼範例沒有較大案例或應用程式的內容;但應用程式可能需要追蹤其配對的裝置,以及配對結果。 這是為了讓應用程式了解整個集合配對作業是否成功。
注意
這些 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 樣式)
此程式代碼範例會使用自定義配對對對象來實作明確的集合配對。 如同自定義配對的一般實作, 需要配對要求的處理程序 來處理配對儀式。 在此情況下,程式代碼範例只會實作確認 配對 儀式。 如同藍牙程式代碼範例,新的和有趣的部分是新增 配對-set-member-requested 處理程式。 set 成員處理程式可讓平台嘗試將裝置配對為集合。
相較於藍牙樣式集配對案例,此程式代碼範例會明確將裝置新增至集合。 與藍牙相比,set 處理程式表示與配對 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);
}
}
一般評論
自動探索 (藍牙樣式) 設定配對
此 API 是必要的,才能完成藍牙樣式集配對,其中在主要端點配對之後,通訊協定會探索設定成員。 簡單的範例可能是一組無線耳塞。 當第一個耳塞配對完成時,裝置會通知計算機有第二個裝置要配對作為集合的一部分。 自定義配對 API 已擴充,可讓應用程式透過新的 新增集成員狀態 處理程式來處理設定作業。
明確 (IPP 樣式) 設定配對
同樣地,您也可以使用此 API 將任何關聯端點 (AEP) 裝置群組配對為集合。 使用自定義配對物件,您的應用程式可以隨時在任何線程上將其他端點新增至配對集。 這是設計,因為透過網路探索和配對的每個裝置可能需要很長的時間,所以我們不想在可以避免時串行化這些作業。
在透過許多通訊協定和裝置堆疊不容易協調的通訊協定探索裝置時,在集合中配對特別有用。 例如,Windows 可能會探索具有三種不同網路協定的新式網路印表機,每個通訊協定都會產生關聯端點。 在此情況下,將這三個端點配對為集合十分有用,因為有幾個原因:它可避免透過網路浪費重新探索,並建立單一簡化的列印佇列。
即使網路印表機未配對為集合,列印後台處理程式仍會嘗試為每個使用者建立單一列印佇列,而不論是否可以透過數種通訊協議進行配對。 如果印表機一開始透過一個通訊協定配對,則操作系統 (OS) 會嘗試透過其他支援的通訊協定重新探索印表機,並建立所有通訊協議的關聯,以避免重複的列印佇列。 一般而言,OS 可以快速且成功地執行此作業,併產生一個簡化的列印佇列。
不過,如果應用程式已經探索到印表機的所有端點,則此重新探索步驟會浪費。 更糟的是,在印表機準備好使用之前,它可以增加長時間的延遲。 此外,如果通訊協定太同步或延遲,則多任務緩衝處理器可能必須為相同的印表機建立額外的列印佇列,這令終端使用者感到困惑。
當集合同時配對所有端點時,可避免重新探索速度可能變慢。 它可確保 PnP 狀態已同步處理,並產生最佳的簡化列印佇列。
裝置節點同步處理
當裝置與這個 API 配對為集合時,產生的 PnP 裝置狀態會方便同步處理。 API 不會限制 當應用程式可以新增設定成員時 ;但平臺何時可以同步處理裝置節點的限制。 裝置節點同步處理會封鎖,直到集合中的所有端點完成配對為止。 之後,會一次建立所有端點的所有裝置節點。 您可以在該點之後將更多設定成員新增至集合,但不會封鎖後續的裝置節點建立,而是立即建立。
- 裝置節點建立 會在 下列情況下同步處理:
- 在配對開始之前,會新增設定成員。
- 新增集合成員,但至少有一個集合成員未完成。
- 裝置節點建立 未 同步處理:
- 所有新增的集合成員都完成之後的任何時間。
就實際而言,API 不允許應用程式控制儀式完成的時間,以影響裝置節點同步處理方式的這種行為。 最接近的近似值是應用程式選擇完成儀式的時間。 在應用程式儀式處理程式傳回之前,配對無法完成;因此,這是應用程式在完成所有集合成員時影響的最後一次機會。