SDK Thread Network pour Android

Le SDK Thread Network offre des fonctionnalités semblables à celles qui permet à vos applications Android de partager les identifiants du réseau Thread avec services Google Play. Cela permet à vos applications de configurer n'importe quel appareil Thread n'importe quel écosystème de maison connectée, sans exposer directement les identifiants et les données utilisateur.

En quelques appels d'API, vous pouvez :

  1. Demandez les identifiants de réseau Thread préférés aux services Google Play.
  2. Configurer de nouveaux routeurs de bordure et ajouter vos identifiants de réseau Thread à Google Services Play.
  3. Si vous disposez déjà de routeurs de bordure sur le terrain, les routeurs se trouvent dans le réseau préféré et les migrez, si nécessaire.

Il existe plusieurs parcours utilisateur et développeur à prendre en compte. Nous aborderons la plupart des dans ce guide, ainsi que d'autres fonctionnalités clés et l'utilisation recommandée.

Terminologie et concepts clés des API

Avant de commencer, il est utile de comprendre les termes suivants :

  • Identifiants réseau Thread:blob binaire des TLV Thread qui encodent. Nom du réseau du thread, clé réseau et autres propriétés requises par un appareil Thread à rejoindre un réseau Thread donné.

  • Identifiants réseau Thread préférés : identifiants réseau Thread sélectionnés automatiquement qui peuvent être partagés avec des applications de différents fournisseurs à l'aide de l'API getPreferredCredentials.

  • ID de l'agent de bord : identifiant global unique de 16 octets pour un appareil Thread Border Router. Cet ID est créé et géré par les fournisseurs de routeurs de bordure.

  • Application de configuration du routeur de bordure Thread:il s'agit de l'application Android qui configure de nouveaux routeurs de bordure Thread et ajoute les identifiants du réseau Thread au services Google Play. Votre application est le propriétaire faisant autorité identifiants et y a accès.

De nombreuses API Thread Network renvoient une tâche qui se termine de manière asynchrone. Vous pouvez utiliser addOnSuccessListener et addOnFailureListener pour enregistrer des rappels afin de recevoir le résultat. Pour en savoir plus, consultez la documentation sur la tâche.

Propriété et maintenance des identifiants

L'application qui ajoute les identifiants du réseau Thread devient propriétaire des identifiants et dispose de toutes les autorisations d'accès aux identifiants. Si vous essayez d'accéder aux identifiants ajoutés par d'autres applications, un message d'erreur PERMISSION_DENIED s'affiche.

En tant que propriétaire de l'application, nous vous recommandons de conserver les identifiants stockés dans Google Les services Play sont à jour lorsque le réseau du routeur de bordure Thread est mis à jour. Cela signifie ajouter des identifiants si nécessaire, les mettre à jour lorsque les identifiants du réseau Thread du routeur de bord changent et les supprimer lorsque le routeur de bord Thread est supprimé ou réinitialisé.

Découverte de l'agent de bordure

Les identifiants doivent être enregistrés avec un ID d'agent des douanes. Vous devrez vous assurer que l'application de configuration du routeur de bordure Thread peut déterminer les ID d'agents de bordure des routeurs de bordure Thread.

Les routeurs de bordure Thread doivent utiliser un mDNS pour annoncer les informations du réseau Thread. y compris le nom du réseau, l'ID de panoramique étendu et l'ID de l'agent de frontière. Les valeurs txt correspondantes pour ces attributs sont nn, xp et id, respectivement.

Pour les réseaux avec des routeurs de bordure Google, les services Google Play obtiennent automatiquement les identifiants réseau Google Thread à utiliser.

Intégrer le SDK à votre application Android

Pour commencer, procédez comme suit:

  1. Suivez les instructions fournies dans la section Configurer les services Google Play.

  2. Ajoutez la dépendance des services Google Play à votre fichier build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'
    
  3. Facultatif : définissez une classe de données BorderAgent pour stocker les informations sur le routeur de bordure. Nous utiliserons ces données tout au long de ce guide:

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

Nous allons ensuite passer en revue les étapes recommandées pour ajouter et gérer identifiants de connexion.

Nouvelles configurations de routeurs de bordure

Avant de créer un réseau pour de nouveaux routeurs de bordure, il est important d'essayer d'abord d'utiliser les identifiants réseau préférés. Cela garantit que Dans la mesure du possible, les appareils Thread sont connectés à un seul réseau Thread.

Un appel à getPreferredCredentials lance une activité, invitant les utilisateurs à autoriser la requête réseau. Si des identifiants réseau ont été stockés dans le trousseau numérique du SDK Thread, ils sont renvoyés à votre application.

Demander des identifiants

Pour inviter l'utilisateur à saisir ses identifiants préférés:

  1. Déclarez un ActivityLauncher :

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Gérez le résultat de l'activité, renvoyé sous la forme 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.")
       }
     }
    
  3. Si vous configurez un nouveau routeur de bordure Thread, nous vous recommandons d'appeler preferredCredentials et lancez l'activité. Cet appel garantit que votre nouveau routeur de bord Thread utilisera les mêmes identifiants déjà stockés en tant que préféré dans le téléphone, ce qui favorise la convergence de différents routeurs de bord Thread vers le même réseau.

    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. Si votre cas d'utilisation concerne la configuration d'appareils autres que TBR, tels qu'un nouvel appareil final Matter over Thread, nous vous recommandons d'utiliser l'API allActiveCredentials pour extraire les identifiants. Cet appel recherche les TBR trouvés sur le réseau local et ne renvoie donc pas les identifiants qui ne sont pas disponibles par un TBR existant localement.

    // 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
    }
    

Créer un réseau Thread

S'il n'existe ni identifiants réseau Thread préférés, ni thread actif les identifiants disponibles dans le compte réseau Thread, vous pouvez utiliser l'API addCredentials pour ajouter des identifiants services Google Play. Pour ce faire, vous devez créer un ThreadBorderAgent, ainsi qu'un objet ThreadNetworkCredentials.

Pour créer un réseau aléatoire, appelez newRandomizeBuilder :

val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder().build()

Pour spécifier le nom du réseau Thread :

val threadCredentials = ThreadNetworkCredentials.newRandomizedBuilder()
  .setNetworkName("ThreadNetworkSDK")
  .build()

Ajouter des identifiants

Pour que vos identifiants de réseau Thread soient disponibles pour d'autres fournisseurs Thread, nous devons les ajouter aux services Google Play. Avant de pouvoir ajouter nos nouvelles identifiants, nous devons également savoir à quel routeur de bordure ce réseau Thread appartient.

Dans cet exemple, nous allons créer un ThreadBorderAgent à partir d'un ID d'agent de bord et transmettre les nouveaux identifiants réseau Thread que vous venez de créer :

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}]") }
}

Détecter et migrer les routeurs de bordure sur site

Si vous disposez actuellement de routeurs de bordure sur le terrain, vous pouvez utiliser isPreferredCredentials pour déterminer si vos routeurs de bordure appartiennent au réseau préféré. Cette API n'invite pas l'utilisateur à autoriser l'accès et vérifie les identifiants du routeur de bordure avec ceux stockés dans les services Google Play.

isPreferredCredentails renvoie 0 si aucune correspondance n'est trouvée et 1 pour correspondant, en tant que type de données Int. Vous pouvez utiliser IsPreferredCredentialsResult pour vérifier vos résultats.

public @interface IsPreferredCredentialsResult {
    int PREFERRED_CREDENTIALS_NOT_FOUND = -1;
    int PREFERRED_CREDENTIALS_NOT_MATCHED = 0;
    int PREFERRED_CREDENTIALS_MATCHED = 1;
}

Pour utiliser isPreferredCredentials, vous devez créer un ThreadNetworkCredentials. Il existe plusieurs façons d'instancier ThreadNetworkCredentials. Nous reviendrons sur ces options dans les étapes suivantes.

Identifiants du réseau Thread par ensemble de données opérationnel

Il est possible que votre routeur de bordure Thread soit déjà configuré avec un réseau Thread et que vous souhaitiez ajouter ce réseau Thread aux services Google Play pour le partager avec d'autres fournisseurs. Vous pouvez créer un ThreadNetworkCredential à partir d'une liste brute des TLV d'un ensemble de données opérationnel actif Thread:

  1. Convertissez l'ensemble de données opérationnel en ByteArray. Exemple :

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Utilisez fromActiveOperationalDataset pour créer le ThreadNetworkCredentials. Lorsque l'opération réussit, vous pouvez obtenir le nom, le canal et la valeur d'autres informations sur le réseau. Pour obtenir la liste complète des propriétés, consultez ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Appelez l'API isPreferredCredentials et transmettez la 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}]") }
    

Identifiants réseau Thread par agent de bordure

Cet ID identifie de manière unique un routeur de bordure. Pour utiliser l'API getCredentialsByBorderAgent, vous devez d'abord créer un objet ThreadBorderAgent et transmettre l'ID de l'agent des douanes.

Une fois l'objet ThreadBorderAgent créé, appelez getCredentialsByBorderAgent Si les identifiants ont été enregistrés, vérifiez s'ils sont préférés.

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}]") }
}

Identifiants du réseau Thread par ID de réseau étendu

Comme pour getPreferredCredentials, vous pouvez également inviter l'utilisateur à saisir à partir de l'ID de panoramique étendu d'un routeur de bordure. La getCredentialsByExtendedPanId renvoie un IntentSender, et l'activité Le résultat contient un objet ThreadNetworkCredentials lorsque l'utilisateur les approuve.

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}]") }
}

Supprimer des identifiants

Lorsque votre routeur de bordure est supprimé de votre maison ou rétabli à ses paramètres d'usine, vous devez supprimer son réseau Thread des services 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}]") }
}

Ressources

Pour en savoir plus sur le SDK réseau Thread, consultez Documentation de référence de l'API