SDK de red de Thread para Android

Organiza tus páginas con colecciones Guarda y categoriza el contenido según tus preferencias.

El SDK de red de Thread proporciona una funcionalidad similar a un llavero digital, lo que permite que tus apps de Android compartan credenciales de red de Thread con los Servicios de Google Play. Esto permite que tus apps configuren cualquier dispositivo Thread desde cualquier ecosistema del hogar inteligente, sin exponer credenciales ni datos del usuario directamente.

Con solo unas pocas llamadas a la API, puedes hacer lo siguiente:

  1. Solicita credenciales de red de Thread preferidas a los Servicios de Google Play.
  2. Configura routers perimetrales nuevos y agrega tus credenciales de red de Thread a los Servicios de Google Play.
  3. Si ya tienes routers de borde en el campo, puedes verificar si están en la red preferida y migrarlos, si es necesario.

Hay varios recorridos del usuario y del desarrollador que se deben considerar. En esta guía, abordaremos la mayoría de ellas, junto con otras funciones clave y el uso recomendado.

Terminología clave y conceptos de API

Antes de comenzar, es útil comprender los siguientes términos:

  • Credenciales de la red de Thread: BLOB binario de los TLV de Thread que codifican el nombre de la red de Thread, la clave de red y otras propiedades que requiere un dispositivo Thread para unirse a una red Thread determinada.

  • Credenciales de red de Thread preferidas: Son las credenciales de red de Thread seleccionadas automáticamente que se pueden compartir con apps de diferentes proveedores mediante la API de getPreferredCredentials.

  • ID del agente de borde: Es un ID único global de 16 bytes para un dispositivo de router de borde de Thread. Los proveedores de routers fronterizos crean y administran este ID.

  • App de configuración del router de borde de Thread:Esta es tu app para Android que configura nuevos dispositivos de router de borde de Thread y agrega las credenciales de la red de Thread a los Servicios de Google Play. Tu app es el propietario autorizado de las credenciales agregadas y tiene acceso gratuito a las credenciales.

Muchas de las API de red de subprocesos muestran una Task que se completa de forma asíncrona. Puedes usar addOnSuccessListener y addOnFailureListener para registrar devoluciones de llamada a fin de recibir el resultado. Para obtener más información, consulta la documentación de Tarea.

Propiedad y mantenimiento de las credenciales

La app que agrega las credenciales de red de Thread se convierte en la propietaria de las credenciales y tiene permisos completos para acceder a ellas. Si intentas acceder a las credenciales agregadas por otras apps, recibirás un error PERMISSION_DENIED.

Como propietario de la app, te recomendamos que mantengas actualizadas las credenciales almacenadas en los Servicios de Google Play cuando se actualice la red de Thread Border Router. Esto significa agregar credenciales cuando sea necesario, actualizarlas cuando cambien las credenciales de red de Thread del router de borde y quitar las credenciales cuando se quite el router de borde de Thread o se restablezca la configuración de fábrica.

Descubrimiento del agente fronterizo

Las credenciales deben guardarse con un ID de agente fronterizo. Deberás asegurarte de que tu app de configuración de router de borde de Thread pueda determinar los ID de agente de borde de tus routers de borde de Thread.

Los routers de borde de Thread deben usar mDNS para anunciar la información de red de Thread, que incluye el nombre de la red, el ID de desplazamiento lateral extendido y el ID de agente de borde. Los valores txt correspondientes para estos atributos son nn, xp y id, respectivamente.

En el caso de las redes con routers perimetrales de Google, los Servicios de Google Play obtienen automáticamente las credenciales de red de Google Thread para usarlas.

Cómo integrar el SDK en tu app para Android

Para comenzar, sigue estos pasos:

  1. Sigue las instrucciones que se proporcionan en Cómo configurar los Servicios de Google Play.

  2. Agrega la dependencia de los Servicios de Google Play a tu archivo build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta02'
    
  3. Opcional: Define una clase de datos BorderAgent para almacenar la información del router perimetral. Utilizaremos estos datos a lo largo de esta guía:

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

A continuación, veremos los pasos recomendados para agregar y administrar las credenciales preferidas.

Nuevas configuraciones de routers fronterizos

Antes de crear una red nueva para routers nuevos, es importante que intentes usar las credenciales de red preferidas primero. Esto garantiza que los dispositivos Thread estén conectados a una sola red Thread cuando sea posible.

Una llamada a getPreferredCredentials inicia una actividad y les solicita a los usuarios que permitan la solicitud de red. Si se almacenaron las credenciales de red en el llavero digital del SDK de Thread, estas se muestran en tu app.

Solicitar credenciales

Para solicitar al usuario las credenciales preferidas:

  1. Declara un ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Controla el resultado de la actividad, que se muestra como 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. Llama a preferredCredentials e inicia la actividad:

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

Cómo crear una nueva red Thread

Si no hay credenciales de red Thread preferidas disponibles en la red Thread de un usuario, puedes usar la API de addCredentials para agregar credenciales a Google Play Services. Para ello, deberás crear un ThreadBorderAgent y también proporcionar un objeto ThreadNetworkCredentials.

Para crear una red aleatoria, llama a newRandomizeBuilder:

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

Para especificar el nombre de la red Thread, haz lo siguiente:

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

Agregar credenciales

Para que tus credenciales de red de Thread estén disponibles para otros proveedores de Thread, debemos agregarlas a los Servicios de Google Play. Antes de poder agregar nuestras credenciales nuevas, también necesitamos saber a qué dispositivo de router de borde pertenece esta red de Thread.

En este ejemplo, crearemos una ThreadBorderAgent a partir de un ID de agente fronterizo y pasaremos las credenciales de red de Thread nuevas que acabas de crear:

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

Detecta y migra routers de borde en campo

Si actualmente tienes routers de borde en el campo, puedes usar isPreferredCredentials para determinar si estos pertenecen a la red preferida. Esta API no le solicita permiso al usuario y verifica las credenciales del router fronterizo con lo que se almacena en los Servicios de Google Play.

isPreferredCredentails muestra 0 si no coincide y 1 si coincide, como un tipo de datos Int. Puedes usar IsPreferredCredentialsResult para verificar los resultados.

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

Para usar isPreferredCredentials, primero debes crear un objeto ThreadNetworkCredentials. Existen varias formas de crear instancias de ThreadNetworkCredentials. En los siguientes pasos, repasaremos estas opciones.

Credenciales de la red de subprocesos por conjunto de datos operativo

En algunos casos, el router de borde de Thread ya está configurado con una red Thread, y quieres agregar esta red Thread a los Servicios de Google Play para compartirla con otros proveedores. Puedes crear una instancia ThreadNetworkCredential a partir de una lista de TLV del conjunto de datos operativos activos de subprocesos:

  1. Convierte el conjunto de datos operativo en ByteArray. Por ejemplo:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Usa fromActiveOperationalDataset para crear ThreadNetworkCredentials. Cuando tenga éxito, podrás obtener el nombre de red de Thread, el canal y otra información de red. Para obtener una lista completa de propiedades, consulta ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Llama a la API de isPreferredCredentials y pasa 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}]") }
    

Credenciales de red de subprocesos por agente de borde

Un ID de agente de frontera identifica de forma única un dispositivo de router de borde. Para usar la API de getCredentialsByBorderAgent, primero debes crear un objeto ThreadBorderAgent y pasar el ID del agente fronterizo.

Una vez que hayas creado el objeto ThreadBorderAgent, llama a getCredentialsByBorderAgent. Si se guardaron las credenciales, verifica si se prefieren.

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

Credenciales de la red de subprocesos por ID de desplazamiento extendido

Al igual que con getPreferredCredentials, también puedes pedirle al usuario las credenciales de un ID de desplazamiento extendido del router perimetral. El getCredentialsByExtendedPanId muestra un IntentSender, y el resultado de la actividad contiene un objeto ThreadNetworkCredentials cuando el usuario lo aprueba.

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

Quitar credenciales

Cuando se quita el dispositivo del router de borde de tu casa o el restablecimiento de la configuración de fábrica, debes quitar su red Thread de los Servicios de 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}]") }
}

Recursos

Para obtener más información sobre el SDK de red de subprocesos, consulta la referencia de la API.