SDK Thread Network for Android

Mantieni tutto organizzato con le raccolte Salva e classifica i contenuti in base alle tue preferenze.

L'SDK Thread Network fornisce funzionalità simili a un portachiavi digitale, consentendo alle tue app Android di condividere le credenziali di rete Thread con Google Play Services. In questo modo, le app possono configurare qualsiasi dispositivo Thread da qualsiasi ecosistema per la smart home, senza esporre direttamente credenziali e dati utente.

Con poche chiamate API puoi:

  1. Richiedi le credenziali di rete preferite del thread da Google Play Services.
  2. Configurare nuovi router di confine e aggiungere le tue credenziali di rete Thread a Google Play Services.
  3. Se hai già dei router in campo, puoi controllare se i tuoi router di confine si trovano nella rete preferita ed eseguirne la migrazione, se necessario.

Esistono diversi percorsi da parte di sviluppatori e utenti da prendere in considerazione. Ne tratteremo la maggior parte in questa guida, oltre ad altre funzionalità principali e per un utilizzo consigliato.

Concetti chiave e concetti chiave dell'API

Prima di iniziare, è utile comprendere i seguenti termini:

  • Credenziali di rete Thread:blob binario di TLV thread che codificano il nome rete, la chiave di rete e altre proprietà richieste da un dispositivo Thread per collegarsi a una determinata rete Thread.

  • Credenziali di rete per il thread preferito: le credenziali di rete per il thread selezionate automaticamente che possono essere condivise con app di diversi fornitori utilizzando l'API getPreferredCredentials.

  • ID agente di confine: un ID univoco globale a 16 byte per un dispositivo router Thread. Questo ID è creato e gestito dai fornitori di router di confine.

  • App di configurazione del router di confine Thread: si tratta dell'app Android che configura i nuovi dispositivi del router di Thread Border e aggiunge le credenziali di rete del thread a Google Play Services. L'app è il proprietario autorevole delle credenziali aggiunte e ha accesso senza costi alle credenziali.

Molte delle API Thread Network restituiscono una attività che viene completata in modo asincrono. Puoi usare addOnSuccessListener e addOnFailureListener per registrare i callback per la ricezione del risultato. Per ulteriori informazioni, consulta la documentazione di Task.

Proprietà e manutenzione delle credenziali

L'app che aggiunge le credenziali di rete Thread diventa il proprietario delle credenziali e dispone di autorizzazioni complete per accedervi. Se tenti di accedere alle credenziali aggiunte da altre app, riceverai un errore PERMISSION_DENIED.

In qualità di proprietario dell'app, ti consigliamo di mantenere aggiornate le credenziali memorizzate in Google Play Services al momento dell'aggiornamento della rete del router Thread Border. In questo modo, è necessario aggiungere credenziali quando necessario, aggiornare le credenziali quando cambiano le credenziali di rete del router Thread e rimuovere le credenziali quando il router Border Border viene rimosso o ripristinato ai dati di fabbrica.

Rilevamento agenti di confine

Le credenziali devono essere salvate con un ID agente di confine. Dovrai assicurarti che l'app di configurazione del router di confine Thread sia in grado di determinare gli ID dell'agente di confine dei router di confine Thread.

I router di confine Thread devono utilizzare mDNS per pubblicizzare le informazioni di rete Thread, tra cui nome rete, ID panoramica esteso e ID agente di confine. I valori corrispondenti txt per questi attributi sono nn, xp e id.

Per le reti con router Google di confine, Google Play Services riceve automaticamente le credenziali di rete di Google Thread da utilizzare,

Integra l'SDK nella tua app Android

Per iniziare, procedi come descritto di seguito:

  1. Segui le istruzioni fornite in Configurare Google Play Services.

  2. Aggiungi la dipendenza Google Play Services al file build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta01'
    
  3. Facoltativo: definisci un BorderAgent data class per archiviare le informazioni del router di confine. Useremo questi dati in questa guida:

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

A questo punto, esamineremo i passaggi consigliati per aggiungere e gestire le credenziali preferite.

Nuove configurazioni del router di confine

Prima di creare una nuova rete per i nuovi router di confine, è importante provare a utilizzare prima le credenziali di rete preferite. In questo modo, i dispositivi Thread possono essere collegati a una singola rete Thread, quando possibile.

Una chiamata a getPreferredCredentials avvia un'attività, chiedendo agli utenti di consentire la richiesta di rete. Se le credenziali di rete sono state archiviate nel portachiavi digitale dell'SDK Thread, le credenziali verranno restituite alla tua app.

Richiedi credenziali

Per richiedere all'utente le credenziali preferite:

  1. Dichiara un ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Gestisci il risultato di Attività, restituito come 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. Chiama il numero preferredCredentials e avvia l'attività:

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

Creare una nuova rete Thread

Se nella rete Thread di un utente non sono disponibili credenziali di rete preferite, puoi utilizzare l'API addCredentials per aggiungere credenziali a Google Play Services. Per farlo, dovrai creare un ThreadBorderAgent e fornire anche un oggetto ThreadNetworkCredentials.

Per creare una rete casuale, chiama newRandomizeBuilder.

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

Per specificare il nome della rete Thread:

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

Aggiungi credenziali

Per rendere disponibili le credenziali di rete Thread per gli altri fornitori di Thread, dobbiamo aggiungerle a Google Play Services. Prima di poter aggiungere le nostre nuove credenziali, dobbiamo anche sapere a quale dispositivo di confine router appartiene questa rete Thread.

In questo esempio creeremo un elemento ThreadBorderAgent da un ID agente di confine e passeremo le nuove credenziali della rete Thread che hai appena creato:

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

Rilevare e eseguire la migrazione dei router di confine nel campo

Se attualmente disponi di router di confine, puoi utilizzare isPreferredCredentials per determinare se i tuoi router di confine appartengono alla rete preferita. Questa API non richiede l'autorizzazione all'utente e controlla le credenziali del router di confine in base ai contenuti memorizzati in Google Play Services.

isPreferredCredentails restituisce 0 per l'assenza di corrispondenze e 1 per l'attributo con corrispondenza, come tipo di dati Int. Puoi usare IsPreferredCredentialsResult per controllare i tuoi risultati.

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

Per utilizzare isPreferredCredentials, devi prima creare un oggetto ThreadNetworkCredentials. Esistono diversi modi per creare un'istanza di ThreadNetworkCredentials. Nei passaggi successivi, illustreremo queste opzioni.

Thread di credenziali di rete in base al set di dati operativi

In alcuni casi, il router Thread Border è già configurato con una rete Thread e vuoi aggiungerlo a Google Play Services per condividerlo con altri fornitori. Puoi creare un'istanza ThreadNetworkCredential da un elenco TLV Thread Active Operational Dataset non elaborato:

  1. Converti il set di dati operativo in ByteArray. Ad esempio:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Utilizza fromActiveOperationalDataset per creare l'elemento ThreadNetworkCredentials. In caso di esito positivo, sarai in grado di ottenere il nome della rete Thread, il canale e altre informazioni sulla rete. Per un elenco completo delle proprietà, consulta ThreadNetworkCredentials.

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

Thread di credenziali di rete per Border Agent

Un ID agente di confine identifica in modo univoco il dispositivo del router di confine. Per utilizzare l'API getCredentialsByBorderAgent, devi prima creare un oggetto ThreadBorderAgent e passare l'ID agente di confine.

Dopo aver creato l'oggetto ThreadBorderAgent, richiama getCredentialsByBorderAgent. Se le credenziali sono state salvate, controlla se sono preferite.

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

Thread di credenziali di rete per ID panoramica esteso

Come per l'elemento getPreferredCredentials, puoi richiedere all'utente anche le credenziali dall'ID panoramica esteso del router di confine. getCredentialsByExtendedPanId restituisce un elemento IntentSender e il risultato dell'attività contiene un oggetto ThreadNetworkCredentials quando l'utente approva.

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

Rimuovi credenziali

Quando il dispositivo Border Router viene rimosso dalla casa o dal ripristino dei dati di fabbrica, devi rimuovere la rete Thread da 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}]") }
}

Risorse

Per scoprire di più sull'SDK di Thread Network, consulta il riferimento API.