SDK da Thread Network para Android

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

O SDK da rede Thread oferece funcionalidades semelhantes a um conjunto de chaves digital, permitindo que os apps Android compartilhem credenciais de rede Thread com o Google Play Services. Isso permite que seus apps configurem qualquer dispositivo Thread de qualquer ecossistema de casa inteligente, sem expor credenciais e dados do usuário diretamente.

Com apenas algumas chamadas de API, você pode:

  1. Solicite as credenciais de rede Thread preferidas do Google Play Services.
  2. Configure novos roteadores de borda e adicione suas credenciais de rede Thread ao Google Play Services.
  3. Se você já tiver roteadores de borda em campo, verifique se eles estão na rede preferencial e migre-os, se necessário.

Há várias jornadas de usuário e desenvolvedor a considerar. Falaremos sobre a maioria deste guia, junto com outros recursos principais e uso recomendado.

Principais terminologias e conceitos de API

Antes de começar, é útil entender os termos a seguir:

  • Credenciais de rede Thread:blob binário de TLVs de linha de execução que codifica nome de rede, chave de rede e outras propriedades exigidas por um dispositivo Thread para participar de uma determinada rede Thread.

  • Credenciais preferidas de rede Thread: as credenciais de rede Thread selecionadas automaticamente que podem ser compartilhadas com aplicativos de diferentes fornecedores usando a API getPreferredCredentials.

  • ID do agente da borda: um ID globalmente exclusivo de 16 bytes para um dispositivo com roteador de borda da linha de execução. Esse ID é criado e gerenciado por fornecedores de roteadores de borda.

  • App de configuração do roteador da borda do Thread: esse é o app Android que configura novos dispositivos do roteador com borda do Thread e adiciona as credenciais da rede Thread ao Google Play Services. O app é o proprietário autorizado das credenciais adicionadas e tem acesso sem custo financeiro às credenciais.

Muitas das APIs de linha de execução retornam uma Tarefa que é concluída de forma assíncrona. Você pode usar addOnSuccessListener e addOnFailureListener para registrar callbacks para receber o resultado. Para saber mais, consulte a documentação da Tarefa.

Propriedade e manutenção de credenciais

O app que adiciona as credenciais de rede Thread se torna o proprietário delas e tem acesso total às credenciais. Se você tentar acessar as credenciais adicionadas por outros apps, receberá o erro PERMISSION_DENIED.

Como proprietário do app, recomendamos que você mantenha as credenciais armazenadas no Google Play Services atualizadas quando a rede do roteador de borda da linha de execução for atualizada. Isso significa adicionar credenciais quando necessário, atualizar credenciais quando as credenciais da rede Thread do roteador de borda mudarem e remover credenciais quando o roteador de borda da linha de execução for removido ou redefinido para a configuração original.

Descoberta do agente de borda

As credenciais precisam ser salvas com um ID de agente de borda. Você precisará garantir que o app de configuração do roteador da borda do Thread consiga determinar os códigos do agente de borda dos seus roteadores do Border Thread.

Os roteadores de borda precisam usar o mDNS para divulgar informações da rede Thread, incluindo o nome da rede, o código da extensão estendida e o código do agente da borda. Os valores txt correspondentes para esses atributos são nn, xp e id, respectivamente.

Para redes com roteadores de borda do Google, o Google Play Services recebe automaticamente as credenciais de rede do Thread do Google para uso.

Integrar o SDK ao seu app Android

Para começar, siga estas etapas:

  1. Siga as instruções fornecidas em Configurar o Google Play Services.

  2. Adicione a dependência do Google Play Services ao arquivo build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta01'
    
  3. Opcional: defina um BorderAgent data class para armazenar informações do roteador de borda. Usaremos esses dados ao longo deste guia:

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

A seguir, veremos as etapas recomendadas para adicionar e gerenciar as credenciais preferenciais.

Novas configurações do roteador de borda

Antes de criar uma nova rede para novos roteadores de borda, é importante tentar usar as credenciais de rede preferidas primeiro. Isso garante que os dispositivos Thread estejam conectados a uma única rede Thread quando possível.

Uma chamada para getPreferredCredentials inicia uma atividade, solicitando que os usuários permitam a solicitação de rede. Se as credenciais de rede estiverem armazenadas no conjunto de chaves digitais do SDK de linhas de execução, elas serão retornadas ao app.

Credenciais da solicitação

Para solicitar credenciais preferenciais ao usuário:

  1. Declare ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Gerencie o resultado da atividade retornado 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. Chame preferredCredentials e inicie a atividade:

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

Criar uma nova rede Thread

Se não houver credenciais de rede Thread preferenciais disponíveis na rede Thread de um usuário, você poderá usar a API addCredentials para adicionar credenciais ao Google Play Services. Para fazer isso, você precisará criar um ThreadBorderAgent e fornecer um objeto ThreadNetworkCredentials.

Para criar uma rede aleatória, chame o newRandomizeBuilder:

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

Para especificar o nome da rede Thread:

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

Adicionar credenciais

Para disponibilizar as credenciais de rede da Thread para outros fornecedores de linhas de execução, precisamos adicioná-las ao Google Play Services. Antes de adicionar nossas novas credenciais, também precisamos saber a que dispositivo de roteador de borda essa rede Thread pertence.

Neste exemplo, vamos criar um ThreadBorderAgent com base em um ID do agente de borda e transmitir as novas credenciais da rede Thread que você acabou de criar:

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

Detectar e migrar roteadores de borda em campo

Se você tiver roteadores de borda em campo, use isPreferredCredentials para determinar se eles pertencem à rede preferida. Essa API não solicita permissão ao usuário e verifica as credenciais do roteador da borda em relação ao que está armazenado no Google Play Services.

isPreferredCredentails retorna 0 para não correspondido e 1 para correspondente, como um tipo de dados Int. Você pode usar IsPreferredCredentialsResult para verificar os resultados.

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

Para usar isPreferredCredentials, primeiro será necessário criar um objeto ThreadNetworkCredentials. Há várias maneiras de instanciar ThreadNetworkCredentials. Nas próximas etapas, veremos essas opções.

Credenciais da rede Thread por conjunto de dados operacional

Em alguns casos, seu roteador de borda Thread já está configurado com uma rede Thread e você quer adicioná-la ao Google Play Services para compartilhá-la com outros fornecedores. Você pode criar uma instância de ThreadNetworkCredential a partir de uma lista bruta de TLV de conjuntos de dados operacionais ativos da linha de execução:

  1. Converta o conjunto de dados operacional para um ByteArray. Exemplo:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Use fromActiveOperationalDataset para criar o ThreadNetworkCredentials. Quando a conexão for concluída, você poderá ver o nome, o canal e outras informações da rede Thread. Para ver uma lista completa de propriedades, consulte ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Chame a API isPreferredCredentials e transmita o 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}]") }
    

Credenciais da rede Thread por agente de borda

Um ID do agente de borda identifica um dispositivo de roteador de borda de forma exclusiva. Para usar a API getCredentialsByBorderAgent, primeiro você precisa criar um objeto ThreadBorderAgent e transmitir o ID do agente de borda.

Depois de criar o objeto ThreadBorderAgent, chame getCredentialsByBorderAgent. Caso as credenciais tenham sido salvas, verifique se elas são preferidas.

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

Credenciais de rede da linha de execução por ID de movimentação estendida

Da mesma forma que getPreferredCredentials, também é possível solicitar ao usuário credenciais de um roteador de borda estendido. A getCredentialsByExtendedPanId retorna uma IntentSender, e o resultado da atividade contém um objeto ThreadNetworkCredentials quando o usuário aprova.

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

Remover credenciais

Quando o dispositivo do roteador de borda for removido da configuração inicial ou da configuração original, você precisará remover a rede Thread do Google Play Services.

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 saber mais sobre o SDK da rede Thread, consulte a Referência da API.