Thread Network SDK は、デジタル キーチェーンに類似した機能を提供し、Android アプリが Thread ネットワーク認証情報を Google Play 開発者サービスと共有できるようにします。これにより、認証情報やユーザーデータを直接公開することなく、スマートホーム エコシステムから任意の Thread デバイスを設定できます。
数回の API 呼び出しで、次のことができます。
- Google Play 開発者サービスの優先 Thread ネットワーク認証情報をリクエストします。
- 新しいボーダー ルーターを設定し、Thread ネットワーク認証情報を Google Play 開発者サービスに追加します。
- すでに現場のボーダー ルーターがある場合は、ボーダー ルーターが優先ネットワークにあるかどうかを確認し、必要に応じて移行します。
考慮すべきユーザーとデベロッパー ジャーニーがいくつかあります。このガイドでは、ほとんどの説明とともに、他の主な機能と推奨使い方について説明します。
主な用語と API のコンセプト
始める前に、以下の用語を理解しておくと役立ちます。
Thread ネットワーク認証情報: Thread デバイスが Thread ネットワークに接続するために必要な、Thread ネットワーク名、ネットワーク キー、その他のプロパティをエンコードする Thread TLV のバイナリ blob。
優先スレッド ネットワーク認証情報:
getPreferredCredentials
API を使用してさまざまなベンダーのアプリと共有可能な、自動的に選択されたスレッド ネットワーク認証情報。ボーダー エージェント ID: スレッド ボーダー ルーター デバイスの 16 バイトのグローバルに一意の ID。この ID は、ボーダー ルーターのベンダーによって作成され、管理されます。
Thread Border Router 設定アプリ: 新しい Thread Border Router デバイスをセットアップし、Thread ネットワーク認証情報を Google Play 開発者サービスに追加する Android アプリです。アプリが、追加された認証情報の信頼できる所有者であり、認証情報に無料でアクセスできる。
Thread ネットワーク API の多くは、非同期的に完了するタスクを返します。addOnSuccessListener と addOnFailureListener を使用して、結果を受け取るコールバックを登録できます。詳細については、タスクのドキュメントをご覧ください。
認証情報の所有権とメンテナンス
Thread ネットワーク認証情報を追加するアプリは、認証情報の所有者となり、認証情報にアクセスするための完全な権限を持ちます。他のアプリによって追加された認証情報にアクセスしようとすると、PERMISSION_DENIED
エラーが発生します。
アプリのオーナーとして、Thread ボーダー ルーター ネットワークの更新時に Google Play 開発者サービスに保存されている認証情報を最新の状態に保つことをおすすめします。つまり、必要に応じて認証情報の追加、ボーダー ルーターの Thread ネットワーク認証情報の変更時の認証情報の更新、Thread Border Router の削除または出荷時設定へのリセット時の認証情報の削除を行います。
Border Agent の検出
認証情報は Border Agent ID で保存する必要があります。Thread ボーダー ルーターのセットアップ アプリで、Thread ボーダー ルーターのボーダー エージェント ID を特定できることを確認する必要があります。
Thread ボーダー ルーターは、mDNS を使用して Thread ネットワーク情報(ネットワーク名、拡張パン ID、ボーダー エージェント ID など)をアドバタイズする必要があります。これらの属性に対応する txt
値は、それぞれ nn
、xp
、id
です。
Google ボーダー ルーターのネットワークの場合、Google Play 開発者サービスは、使用する Google Thread ネットワーク認証情報を自動的に取得します。
Android アプリに SDK を統合する
使用を開始するには、次の手順を行います。
Google Play 開発者サービスの設定の手順を行います。
Google Play 開発者サービスの依存関係を
build.gradle
ファイルに追加します。implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta02'
省略可: ボーダー ルーター情報を格納する
BorderAgent
データクラスを定義します。このガイド全体でこのデータを使用します。data class BorderAgentInfo( // Network Name max 16 len val networkName: String = "", val extPanId: ByteArray = ByteArray(16), val borderAgentId: ByteArray = ByteArray(16), ... )
次に、推奨される認証情報を追加して管理するための推奨手順について説明します。
新しいボーダー ルーターのセットアップ
新しいボーダー ルーター用の新しいネットワークを作成する前に、優先するネットワーク認証情報を使用してみることが重要です。これにより、可能であれば Thread デバイスが 1 つの Thread ネットワークに接続されます。
getPreferredCredentials
を呼び出すと、Activity が起動し、ネットワーク リクエストを許可するようユーザーに促します。ネットワーク認証情報が 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.") } }
preferredCredentials
を呼び出して、アクティビティを起動します。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}]") } }
新しい 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 ネットワークがどのボーダー ルーター デバイスに属しているのかも把握する必要があります。
この例では、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}]") }
}
フィールド内ボーダー ルーターの検出と移行
フィールド内ボーダー ルーターがある場合は、isPreferredCredentials
を使用して、ボーダー ルーターが優先ネットワークに属しているかどうかを判断できます。この API は、ユーザーに権限を求めるプロンプトを表示しません。また、ボーダー ルーターの認証情報を Google Play 開発者サービスに保存されているものと照合します。
isPreferredCredentails
は、一致しない場合は 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 ボーダー ルーターがすでに Thread ネットワークでセットアップされており、この Thread ネットワークを Google Play 開発者サービスに追加して、他のベンダーと共有する場合があります。ThreadNetworkCredential
インスタンスは、未加工のスレッドのアクティブ オペレーション データセット TLV リストから作成できます。
オペレーション データセットを
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)
isPreferredCredentials
API を呼び出して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}]") }
Border Agent によるスレッド ネットワークの認証情報
ボーダー エージェント ID によって、ボーダー ルーター デバイスを一意に識別します。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}]") }
}
拡張パン ID 別のスレッド ネットワーク認証情報
getPreferredCredentials
と同様に、ボーダー ルーターの拡張パン ID からユーザーに認証情報の入力を求めることもできます。getCredentialsByExtendedPanId
は IntentSender
を返し、ユーザーが承認すると、Activity の結果には 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}]") }
}
認証情報を削除
ボーダー ルーター デバイスを家から出荷時の設定にリセットするか、出荷時の設定にリセットした場合は、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 リファレンスをご覧ください。