Thread ネットワーク SDK は、デジタル キーチェーンに似た機能を提供し、Android アプリが Google Play 開発者サービスと Thread ネットワーク認証情報を共有できるようにします。これにより、認証情報やユーザーデータを直接公開することなく、任意のスマートホーム エコシステムから任意の Thread デバイスをセットアップできます。
数回の API 呼び出しで、次のことが可能になります。
- Google Play 開発者サービスに優先 Thread ネットワーク認証情報をリクエストします。
- 新しい Thread Border Router (TBR) をセットアップし、Thread ネットワークの認証情報を Google Play 開発者サービスに追加します。
- すでにフィールドに TBR がある場合は、TBR が優先ネットワークにあるかどうかを確認し、必要に応じて移行できます。
考慮すべきユーザー ジャーニーとデベロッパー ジャーニーがいくつかあります。このガイドでは、その他の主な機能や推奨される使用方法とともに、そのほとんどについて説明します。
主な用語と API のコンセプト
始める前に、次の用語を理解しておくと役立ちます。
Thread ネットワーク認証情報: Thread デバイスが特定の Thread ネットワークに参加するために必要な Thread ネットワーク名、ネットワーク キー、その他のプロパティをエンコードする Thread TLV のバイナリ blob。
優先 Thread ネットワーク認証情報:
getPreferredCredentialsAPI を使用して、異なるベンダーのアプリと共有できる、自動選択された Thread ネットワーク認証情報。Border Agent ID: TBR デバイスの 16 バイトのグローバルに一意の ID。この ID は border router ベンダーによって作成、管理されます。
TBR セットアップ アプリ: 新しい TBR デバイスをセットアップし、Thread ネットワーク認証情報を Google Play 開発者サービスに追加する Android アプリです。アプリは、追加された認証情報の正式な所有者であり、それらにアクセスできます。
Thread Network API の多くは、非同期で完了する Task を返します。addOnSuccessListener と addOnFailureListener を使用して、結果を受け取るコールバックを登録できます。詳細については、Task のドキュメントをご覧ください。
認証情報の所有権とメンテナンス
Thread ネットワーク認証情報を追加したアプリが認証情報のオーナーとなり、認証情報にアクセスするための完全な権限を持ちます。他のアプリによって追加された認証情報にアクセスしようとすると、PERMISSION_DENIED エラーが発生します。
アプリの所有者は、TBR ネットワークが更新されたときに、Google Play 開発者サービスに保存されている認証情報を最新の状態に保つことをおすすめします。つまり、必要に応じて認証情報を追加し、border router の Thread ネットワーク認証情報が変更されたときに認証情報を更新し、TBR が削除されたとき、または出荷時の設定にリセットされたときに認証情報を削除します。
Border Agent の検出
認証情報は Border Agent ID とともに保存する必要があります。TBR セットアップ アプリが TBR のボーダー エージェント ID を特定できるようにする必要があります。
TBR は、mDNS を使用して、ネットワーク名、拡張 PAN ID、ボーダー エージェント ID などの Thread ネットワーク情報をアドバタイズする必要があります。これらの属性に対応する txt 値は、それぞれ nn、xp、id です。
Google Thread Border Router (gTBR) を使用するネットワークの場合、Google Play 開発者サービスは Google Thread ネットワーク認証情報を自動的に取得して使用します。
SDK を Android アプリに統合する
開始するには、次の手順を完了します。
Google Play 開発者サービスをセットアップするに記載されている手順に沿って操作します。
Google Play 開発者サービスの依存関係を
build.gradleファイルに追加します。implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'省略可: TBR 情報を保存する
BorderAgentデータクラスを定義します。このガイドでは、このデータを全体で使用します。data class BorderAgentInfo( // Network Name max 16 len val networkName: String = "", val extPanId: ByteArray = ByteArray(16), val borderAgentId: ByteArray = ByteArray(16), ... )
次に、優先認証情報を追加して管理するための推奨手順について説明します。
新しい Thread ボーダー ルーターのセットアップ
新しいボーダー ルーター用に新しいネットワークを作成する前に、まず優先ネットワーク認証情報を使用してみることが重要です。これにより、Thread デバイスは可能な限り単一の Thread ネットワークに接続されます。
getPreferredCredentials を呼び出すと、アクティビティが起動し、ネットワーク リクエストを許可するようユーザーに求めます。ネットワーク認証情報が Thread SDK のデジタル キーチェーンに保存されている場合、認証情報はアプリに返されます。
認証情報をリクエストする
優先する認証情報をユーザーに求めるには:
ActivityLauncherを宣言します。private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>ThreadNetworkCredentialsとして返されるアクティビティの結果を処理します。preferredCredentialsLauncher = registerForActivityResult( StartIntentSenderForResult() ) { result: ActivityResult -> if (result.resultCode == RESULT_OK) { val threadNetworkCredentials = ThreadNetworkCredentials.fromIntentSenderResultData(result.data!!) Log.d("debug", threadNetworkCredentials.networkName) } else { Log.d("debug", "User denied request.") } }新しい TBR を設定する場合は、
preferredCredentialsを呼び出してアクティビティを起動することをおすすめします。この呼び出しにより、新しい TBR は、スマートフォンに優先としてすでに保存されているものと同じ認証情報を使用するようになり、異なる TBR の同じネットワークへの収束が促進されます。private fun getPreferredThreadNetworkCredentials() { ThreadNetwork.getClient(this) .preferredCredentials .addOnSuccessListener { intentSenderResult -> intentSenderResult.intentSender?.let { preferredCredentialsLauncher.launch(IntentSenderRequest.Builder(it).build()) } ?: Log.d("debug", "No preferred credentials found.") } .addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") } }ユースケースが、新しい Matter-over-Thread エンドデバイスなど、TBR 以外のデバイスの設定に関連している場合は、
allActiveCredentialsAPI を使用して認証情報を取得することをおすすめします。この呼び出しは、ローカル ネットワークで見つかった TBR をスキャンするため、既存の TBR でローカルに使用できない認証情報は返されません。// Creates the IntentSender result launcher for the getAllActiveCredentials API private val getAllActiveCredentialsLauncher = registerForActivityResult( StartIntentSenderForResult() ) { result: ActivityResult -> if (result.resultCode == RESULT_OK) { val activeCredentials: List<ThreadNetworkCredentials> = ThreadNetworkCredentials.parseListFromIntentSenderResultData( result.data!! ) // Use the activeCredentials list } else { // The user denied to share! } } // Invokes the getAllActiveCredentials API and starts the dialog activity with the returned // IntentSender threadNetworkClient .getAllActiveCredentials() .addOnSuccessListener { intentSenderResult: IntentSenderResult -> val intentSender = intentSenderResult.intentSender if (intentSender != null) { getAllActiveCredentialsLauncher.launch( IntentSenderRequest.Builder(intentSender).build() ) } else { // No active network credentials found! } } // Handles the failure .addOnFailureListener { e: Exception -> // Handle the exception }
新しい Thread ネットワークを作成する
ユーザーの Thread ネットワークに優先 Thread ネットワーク認証情報もアクティブな Thread 認証情報もない場合は、addCredentials API を使用して Google Play 開発者サービスに認証情報を追加できます。そのためには、ThreadBorderAgent を作成し、ThreadNetworkCredentials オブジェクトを指定する必要があります。
ランダム ネットワークを作成するには、newRandomizeBuilder を呼び出します。
val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder().build()
Thread ネットワーク名を指定するには:
val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder()
.setNetworkName("ThreadNetworkSDK")
.build()
認証情報を追加
Thread ネットワークの認証情報を他の Thread ベンダーが利用できるようにするには、Google Play 開発者サービスに追加する必要があります。新しい認証情報を追加する前に、この Thread ネットワークがどの TBR デバイスに属しているかも把握する必要があります。
この例では、Border Agent ID から ThreadBorderAgent を作成し、作成した新しい Thread ネットワーク認証情報を渡します。
private fun addCredentials(borderAgentInfo: BorderAgentInfo, credentialsToBeAdded: ThreadNetworkCredentials) {
val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
Log.d("debug", "border router id:" + threadBorderAgent.id)
ThreadNetwork.getClient(this)
.addCredentials(threadBorderAgent, credentialsToBeAdded)
.addOnSuccessListener {
Log.d("debug", "Credentials added.")
}
.addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}
現場の border router を検出して移行する
フィールドに border router がある場合は、isPreferredCredentials を使用して、border router が優先ネットワークに属しているかどうかを判断できます。この API は、ユーザーに権限を求めるプロンプトを表示せず、border router 認証情報を Google Play 開発者サービスに保存されている認証情報と照合します。
isPreferredCredentials は、一致しない場合は 0 を、一致する場合は 1 を Int データ型として返します。IsPreferredCredentialsResult を使用して結果を確認できます。
public @interface IsPreferredCredentialsResult {
int PREFERRED_CREDENTIALS_NOT_FOUND = -1;
int PREFERRED_CREDENTIALS_NOT_MATCHED = 0;
int PREFERRED_CREDENTIALS_MATCHED = 1;
}
isPreferredCredentials を使用するには、まず ThreadNetworkCredentials オブジェクトを作成する必要があります。ThreadNetworkCredentials をインスタンス化する方法はいくつかあります。次のステップでは、これらのオプションについて説明します。
運用データセットによる Thread ネットワーク認証情報
TBR がすでに Thread ネットワークでセットアップされていて、この Thread ネットワークを Google Play 開発者サービスに追加して他のベンダーと共有したい場合があります。未加工の Thread アクティブ運用データセット TLV リストから ThreadNetworkCredential インスタンスを作成できます。
運用データセットを
ByteArrayに変換します。次に例を示します。val activeDataset = "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()fun String.dsToByteArray(): ByteArray { return chunked(2).map { it.toInt(16).toByte() }.toByteArray() }fromActiveOperationalDatasetを使用してThreadNetworkCredentialsを作成します。成功すると、Thread ネットワーク名、チャンネル、その他のネットワーク情報を取得できるようになります。プロパティの完全なリストについては、ThreadNetworkCredentials をご覧ください。val threadNetworkCredentials = ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset) Log.d( "threadNetworkCredentials", threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)isPreferredCredentialsAPI を呼び出し、ThreadNetworkCredentialsを渡します。ThreadNetwork.getClient(this) .isPreferredCredentials(threadNetworkCredentials) .addOnSuccessListener { result -> when (result) { IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_NOT_MATCHED -> Log.d("isPreferredCredentials", "Credentials not matched.") IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_MATCHED -> Log.d("isPreferredCredentials", "Credentials matched.") } } .addOnFailureListener { e: Exception -> Log.d("isPreferredCredentials", "ERROR: [${e}]") }
ボーダー エージェントによる Thread ネットワーク認証情報
ボーダー エージェント ID は、TBR デバイスを一意に識別します。getCredentialsByBorderAgent API を使用するには、まず ThreadBorderAgent オブジェクトを作成し、Border Agent ID を渡す必要があります。
ThreadBorderAgent オブジェクトを作成したら、getCredentialsByBorderAgent を呼び出します。認証情報が保存されている場合は、優先されているかどうかを確認します。
private fun isPreferredThreadNetworkByBorderAgent(borderAgentInfo: BorderAgentInfo) {
val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
Log.d("debug", "border router id:" + threadBorderAgent.id)
var isPreferred = IsPreferredCredentialsResult.PREFERRED_CREDENTIALS_NOT_FOUND
var borderAgentCredentials: ThreadNetworkCredentials?
val taskByBorderAgent = ThreadNetwork.getClient(this)
taskByBorderAgent
.getCredentialsByBorderAgent(threadBorderAgent)
.addOnSuccessListener { result: ThreadNetworkCredentialsResult ->
borderAgentCredentials = result.credentials
result.credentials?.let {
taskByBorderAgent.isPreferredCredentials(it).addOnSuccessListener { result ->
isPreferred = result
}
}
}
.addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}
拡張 PAN ID による Thread ネットワーク認証情報
getPreferredCredentials と同様に、TBR の拡張 PAN ID から認証情報を入力するようユーザーに求めることもできます。getCredentialsByExtendedPanId は IntentSender を返し、ユーザーが承認すると、アクティビティの結果に ThreadNetworkCredentials オブジェクトが含まれます。
private fun getCredentialsByExtPanId(borderAgentInfo: BorderAgentInfo) {
ThreadNetwork.getClient(this)
.getCredentialsByExtendedPanId(borderAgentInfo.extPanId)
.addOnSuccessListener { intentSenderResult ->
intentSenderResult.intentSender?.let {
preferredCredentialsLauncher.launch(IntentSenderRequest.Builder(it).build())
}
?: Log.d("debug", "No credentials found.")
}
.addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}
認証情報を削除する
border router デバイスを家から削除するか、出荷時の設定にリセットした場合は、Google Play 開発者サービスから Thread ネットワークを削除する必要があります。
private fun removeCredentials(borderAgentInfo: BorderAgentInfo) {
val threadBorderAgent = ThreadBorderAgent.newBuilder(borderAgentInfo.borderAgentId).build()
Log.d("debug", "border router id:" + threadBorderAgent.id)
ThreadNetwork.getClient(this)
.removeCredentials(threadBorderAgent)
.addOnSuccessListener { Log.d("debug", "Credentials removed.") }
.addOnFailureListener { e: Exception -> Log.d(TAG, "ERROR: [${e}]") }
}
リソース
Thread Network SDK の詳細については、API リファレンスをご覧ください。