Android 向け Thread ネットワーク SDK

Thread Network SDK はデジタル キーチェーンに似た機能を提供します。これにより、Android アプリは Thread ネットワークの認証情報を Google Play 開発者サービスと共有できます。これにより、認証情報とユーザーデータを直接公開することなく、アプリで任意のスマートホーム エコシステムの Thread デバイスを設定できます。

わずか数回の API 呼び出しで、次のことができます。

  1. Google Play 開発者サービスから優先される Thread ネットワーク認証情報をリクエストします。
  2. 新しいボーダー ルーターを設定し、Thread ネットワーク認証情報を Google に追加する Play 開発者サービス。
  3. 現場のボーダー ルーターがすでにある場合は、 優先ネットワーク内にあるルーターが 必要に応じて移行されます

考慮すべきユーザー ジャーニーとデベロッパー ジャーニーはいくつかあります。このガイドでは、その他の主な機能と推奨される使用方法とともに、それらのほとんどについて説明します。

主な用語と API のコンセプト

始める前に、以下の用語を理解しておくと役に立ちます。

  • Thread ネットワーク認証情報: エンコードするスレッド TLV のバイナリ blob スレッド ネットワーク名、ネットワーク キー、および Thread デバイス: 特定の Thread ネットワークに接続します。

  • 推奨される Thread ネットワーク認証情報: getPreferredCredentials API を使用して異なるベンダーのアプリと共有できる、自動選択された Thread ネットワーク認証情報。

  • 境界エージェント ID: Thread 境界ルーター デバイスの 16 バイトのグローバルに一意の ID。この ID は、境界ルーター ベンダーによって作成および管理されます。

  • Thread Border Router Setup アプリ: 新しい Thread ボーダー ルーター デバイスに接続し、Thread ネットワーク認証情報を Google Play 開発者サービス。お客様のアプリは、追加されたアプリの正式な所有者です 認証情報にアクセスしてアクセスできます。

Thread Network API の多くは、 タスク 非同期で完了します次を使用: addOnSuccessListener および addOnFailureListener 結果を受け取るコールバックを登録します。詳しくは、 タスク ご覧ください

認証情報の所有権とメンテナンス

Thread のネットワーク認証情報を追加したアプリが、 その認証情報にアクセスするための完全な権限があります。他のアプリによって追加された認証情報にアクセスしようとすると、PERMISSION_DENIED エラーが発生します。

アプリ所有者は、Thread Border Router ネットワークが更新されたときに、Google Play サービスに保存されている認証情報を最新の状態に保つことをおすすめします。この つまり、必要に応じて認証情報を追加し、境界が変化したときに認証情報を Thread ネットワーク認証情報が変更されると、 Thread ボーダー ルーターが削除されているか、出荷時設定にリセットされている。

ボーダー エージェントの探索

認証情報は Border Agent ID と一緒に保存する必要があります。Thread ボーダー ルーター設定アプリが、Thread ボーダー ルーターのボーダー エージェント ID を特定できることを確認する必要があります。

Thread ボーダー ルーターは、Thread ネットワーク情報をアドバタイズするために mDNS を使用する必要があります。 (ネットワーク名、拡張パン ID、ボーダー エージェント ID など)が含まれます。これらの属性に対応する txt 値は、それぞれ nnxpid です。

Google ボーダー ルーターを使用するネットワークの場合、Google Play 開発者サービスは 使用する Google Thread ネットワーク認証情報を取得します。

SDK を Android アプリに統合する

開始するには、次の手順を完了します。

  1. Google Play 開発者サービスのセットアップの手順に沿って操作します。

  2. Google Play 開発者サービスの依存関係を build.gradle ファイルに追加します。

    implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'
    
  3. 省略可: ボーダー ルーターを格納する BorderAgent データクラスを定義する 情報です。このガイドでは、次のデータを使用します。

    data class BorderAgentInfo(
      // Network Name max 16 len
      val networkName: String = "",
      val extPanId: ByteArray = ByteArray(16),
      val borderAgentId: ByteArray = ByteArray(16),
      ...
    )
    

次に、優先ルールを追加、管理するための推奨手順について説明します。 認証情報が必要です。

新しいボーダー ルーターの設定

新しい境界ルータの新しいネットワークを作成する前に、優先ネットワークの認証情報の使用を試すことが重要です。これにより Thread デバイスは、可能な限り単一の Thread ネットワークに接続されます。

getPreferredCredentials を呼び出すとアクティビティが起動し、ネットワーク リクエストを許可するようユーザーに求めるメッセージが表示されます。ネットワーク Thread SDK のデジタル キーチェーンに保存されている場合、 アプリに返されます。

認証情報をリクエストする

ユーザーに優先する認証情報を尋ねるには:

  1. ActivityLauncher を宣言します。

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. ThreadNetworkCredentials として返される Activity の結果を処理します。

    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.")
       }
     }
    
  3. 新しい Thread ボーダー ルーターを設定する場合は、 preferredCredentials を実行してアクティビティを起動します。この呼び出しにより、 新しい Thread ボーダー ルーターでは、すでに保存されているものと同じ認証情報が 電話では優先として指定し、さまざまな 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}]") }
    }
    
  4. ユースケースが TBR 以外のデバイス(新しいデバイスなど)のセットアップに関連する場合は、 allActiveCredentials を使用することをおすすめします。 認証情報を取得するための API です。この呼び出しは、ローカル ネットワークで見つかった 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 ネットワークがどの境界ルーター デバイスに属しているかを確認する必要があります。

この例では、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 開発者サービスに追加して他のベンダーと共有したい場合があります。未加工の Thread アクティブな運用データセット TLV リストから ThreadNetworkCredential インスタンスを作成できます。

  1. 運用データセットを ByteArray に変換します。例:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. fromActiveOperationalDataset を使用して ThreadNetworkCredentials を作成します。 成功すると、Thread のネットワーク名、チャンネル、 その他のネットワーク情報。プロパティの完全なリストについては、 ThreadNetworkCredentials

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. 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 による Thread ネットワーク認証情報

ボーダー エージェント ID は、ボーダー ルーター デバイスを一意に識別する ID です。用途 getCredentialsByBorderAgent API を作成するには、まず、 ThreadBorderAgent オブジェクトを作成し、ボーダー エージェント 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 と同様に、ユーザーに次の入力を促すこともできます。 認証情報をボーダー ルーターの Extended Pan ID から取得するgetCredentialsByExtendedPanIdIntentSender を返します。ユーザーが承認すると、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}]") }
}

認証情報を削除

ボーダー ルーター デバイスを家から削除したり、出荷時の設定にリセットしたりすると、 Thread ネットワークを Google Play 開発者サービスから削除する必要がある。

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 リファレンス