SDK Thread Network for Android

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

L'SDK di rete Thread fornisce funzionalità simili a una portachiavi digitale, consentendo alle app Android di condividere le credenziali di rete di 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 Thread preferite da Google Play Services.
  2. Configura nuovi router di confine e aggiungi le tue credenziali di rete Thread a Google Play Services.
  3. Se hai già router di confine sul campo, puoi controllare se i tuoi router di confine si trovano nella rete preferita ed eseguirne la migrazione, se necessario.

Devi prendere in considerazione diversi percorsi degli utenti e degli sviluppatori. Ne tratteremo la maggior parte in questa guida, insieme ad altre funzionalità chiave e ai dati consigliati per l'utilizzo.

Concetti chiave sulla terminologia e sulle API

Prima di iniziare, è utile comprendere i seguenti termini:

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

  • Credenziali di rete Thread preferite: le credenziali di rete Thread selezionate automaticamente che possono essere condivise con app di fornitori diversi utilizzando l'API getPreferredCredentials.

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

  • App Configurazione router di confine Thread: questa è la tua app per Android che configura i nuovi dispositivi Router di confine Thread e aggiunge le credenziali di rete Thread ai servizi Google Play. L'app è il proprietario autore delle credenziali aggiunte e vi ha accesso.

Molte delle API Thread Network restituiscono una Attività completata in modo asincrono. Puoi utilizzare addOnSuccess listener e addOnFailure listener 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 ha le autorizzazioni complete per accedervi. Se tenti di accedere alle credenziali aggiunte da altre app, riceverai un errore PERMISSION_DENIED.

Come proprietario dell'app, ti consigliamo di mantenere aggiornate le credenziali in Google Play Services quando viene aggiornata la rete del router di confine Thread. Ciò significa aggiungere credenziali quando necessario, aggiornare le credenziali quando cambiano le credenziali di rete Thread del router di confine e rimuovere le credenziali quando il router di confine Thread viene rimosso o ripristinato ai dati di fabbrica.

Rilevamento dell'agente di confine

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

I router di confine Thread devono utilizzare mDNS per pubblicizzare le informazioni di rete Thread, tra cui Network Name, Extended Pan ID e Border Agent ID. I valori txt corrispondenti per questi attributi sono nn, xp e id, rispettivamente.

Per le reti con router di confine Google, Google Play Services riceve automaticamente le credenziali di rete di Google Thread per l'utilizzo.

Integra l'SDK nella tua app per Android

Per iniziare, completa i seguenti passaggi:

  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'
    
  3. Facoltativo: definisci una classe dati BorderAgent per archiviare le informazioni del router di confine. In questa guida utilizzeremo i seguenti dati:

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

Quindi, vedremo 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 le credenziali di rete preferite. In questo modo, i dispositivi Thread sono connessi a una singola rete Thread, quando possibile.

Una chiamata al numero 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, vengono restituite alla tua app.

Richiedi credenziali

Per chiedere all'utente le credenziali preferite:

  1. Dichiara un ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Gestisci il risultato dell'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 Thread 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 tue credenziali di rete Thread ad altri fornitori di Thread, dovremo aggiungerle a Google Play Services. Prima di poter aggiungere le nostre nuove credenziali, dobbiamo sapere a quale dispositivo di router di confine appartiene a questa rete Thread.

In questo esempio creeremo un ThreadBorderAgent da un ID agente di confine e trasferiamo le nuove credenziali di 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}]") }
}

Rileva ed esegui la migrazione dei router di confine sul campo

Se attualmente disponi di router di confine sul campo, puoi utilizzare isPreferredCredentials per determinare se appartengono a una rete preferita. Questa API non richiede l'autorizzazione all'utente e controlla le credenziali del router di confine in base a quanto archiviato in Google Play Services.

isPreferredCredentails restituisce 0 per i tipi senza dati e 1 per quelli corrispondenti, come tipo di dati Int. Puoi usare IsPreferredCredentialsResult per controllare i 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 ThreadNetworkCredentials. Nei passaggi successivi, esamineremo queste opzioni.

Thread credenziali di rete per set di dati operativi

In alcuni casi, il router di confine Thread è 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 di dati attivi attivi Thread non elaborati:

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

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Usa fromActiveOperationalDataset per creare ThreadNetworkCredentials. Se l'operazione riesce, potrai recuperare il nome, il canale e altre informazioni sulla rete Thread. Per un elenco completo delle proprietà, consulta ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Chiama l'API isPreferredCredentials e supera 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 credenziali di rete da Border Agent

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

Dopo aver creato l'oggetto ThreadBorderAgent, chiama 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 credenziali di rete per ID pan esteso

Analogamente a getPreferredCredentials, puoi richiedere all'utente le credenziali dall'ID PAN esteso del router di confine. getCredentialsByExtendedPanId restituisce un 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 router di confine 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 rete Thread, consulta la pagina Riferimento API.