Thread Network SDK na Androida

Pakiet Thread Network SDK udostępnia funkcje podobne do usług cyfrowych, pęku kluczy, który umożliwia aplikacjom na Androida udostępnianie danych logowania do sieci Thread, Usługi Google Play. Dzięki temu Twoje aplikacje będą mogły skonfigurować dowolne urządzenie Thread do dowolnego ekosystemu inteligentnego domu bez ujawniania bezpośrednio danych logowania i danych użytkownika.

Za pomocą zaledwie kilku wywołań interfejsu API możesz:

  1. Wysyłanie do Usług Google Play preferowanych danych logowania do sieci Thread.
  2. Skonfiguruj nowe routery brzegowe i dodaj dane logowania do sieci Thread do usług Google Play.
  3. Jeśli masz już routery graniczne w terenie, możesz sprawdzić, routery znajdują się w preferowanej sieci i w razie potrzeby mogą je przenieść.

Trzeba wziąć pod uwagę kilka ścieżek użytkowników i programistów. Omówimy większość w tym przewodniku, a także z innymi kluczowymi funkcjami i zalecanym użyciem.

Kluczowa terminologia i koncepcje związane z interfejsami API

Zanim zaczniesz, zapoznaj się z tymi terminami:

  • Dane logowania do sieci typu Thread: Binarny obiekt blob TLV Thread, który koduje Nazwa sieci wątku, klucz sieci i inne właściwości wymagane przez urządzenie Thread, aby dołączyło do danej sieci Thread.

  • Preferowane dane logowania do sieci Thread:automatycznie wybrana sieć Thread. dane logowania, które można udostępniać aplikacjom różnych dostawców za pomocą Interfejs API getPreferredCredentials.

  • Identyfikator agenta granicznego: 16-bajtowy identyfikator globalny urządzenia Thread Border Router. Ten identyfikator jest tworzony i zarządzany przez dostawców routerów granicznych.

  • Aplikacja do konfigurowania routera granicznego Thread: to aplikacja na Androida, która konfiguruje nowe urządzenia z routerem granicznikiem Thread i dodaje do Usług Google Play poświadczenia sieci Thread. Twoja aplikacja jest autorytetem w dodanych dane logowania i ma do nich dostęp.

Wiele interfejsów Thread Network API zwraca błąd Zadanie który kończy się asynchronicznie. Za pomocą addOnSuccessListener i addOnFailureListener , aby zarejestrować wywołania zwrotne związane z odebraniem wyniku. Więcej informacji znajdziesz w dokumentacji Task.

Własność i utrzymanie danych logowania

Aplikacja, która dodaje dane logowania do sieci Thread, staje się właścicielem dane logowania i ma pełne uprawnienia dostępu do danych logowania. Jeśli spróbujesz uzyskać dostęp do danych logowania dodanych przez inne aplikacje, pojawi się błąd PERMISSION_DENIED.

Jako właściciel aplikacji zalecamy przechowywanie danych logowania w Google Usługi Google Play są aktualne po zaktualizowaniu sieci routera Thread Border Router. Oznacza to dodawanie danych logowania w razie potrzeby, aktualizowanie danych logowania w przypadku zmiany danych logowania sieci Thread na routerze brzegowym oraz usuwanie danych logowania w przypadku usunięcia routera brzegowego Thread lub przywrócenia ustawień fabrycznych.

Wykrywanie agenta granicznego

Dane logowania muszą być zapisane przy użyciu identyfikatora agenta Border. Upewnij się, że aplikacja do konfigurowania routera granicznego Thread może określić identyfikatory agenta granicznego routerów granicznego Thread.

Routery brzegowe Thread muszą używać mDNS do reklamowania informacji o sieci Thread, w tym nazwy sieci, rozszerzonego identyfikatora Pan i identyfikatora agenta brzegowego. Odpowiednie wartości txt dla tych atrybutów to odpowiednio nn, xp i id.

W przypadku sieci z routerami Google na granicy usługa Google Play automatycznie otrzymuje do użycia dane logowania do sieci Thread od Google.

Integracja pakietu SDK z aplikacją na Androida

Aby rozpocząć, wykonaj te czynności:

  1. Postępuj zgodnie z instrukcjami podanymi na stronie Skonfiguruj Usługi Google Play.

  2. Dodaj zależność Usług Google Play do pliku build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'
    
  3. Opcjonalnie: zdefiniuj klasę danych BorderAgent do przechowywania routera granicy i informacjami o nich. W tym przewodniku użyjemy tych danych:

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

Następnie omówimy zalecane kroki, które należy wykonać, aby dodać preferowane dane logowania i nimi zarządzać.

Nowe konfiguracje routerów granicznych

Zanim utworzysz nową sieć dla nowych routerów granicznych, spróbuj użyć preferowanych danych logowania. Dzięki temu urządzenia Thread są w miarę możliwości połączone z jedną siecią Thread.

Wywołanie getPreferredCredentials uruchamia aktywność, która prosi użytkowników o zezwolenie na żądanie sieci. Jeśli sieć dane logowania zostały zapisane w cyfrowym pęku kluczy Thread SDK, są zwracane do aplikacji.

Poproś o dane logowania

Aby poprosić użytkownika o podanie preferowanych danych logowania:

  1. Zadeklaruj ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Przetwórz wynik działania, który jest zwracany jako 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. Jeśli konfigurujesz nowy router brzegowy Thread, zalecamy wywołanie funkcjipreferredCredentials i uruchomienie aktywności. Dzięki temu nowy router brzegowy Thread będzie używać tych samych danych logowania, które są już zapisane w telefonie jako preferowane, co ułatwia konwergencję różnych routerów brzegowych Thread w ramach tej samej sieci.

    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. Jeśli Twój przypadek użycia dotyczy konfigurowania urządzeń innych niż TBR, takich jak nowe urządzenie końcowe Matter over Thread, zalecamy użycie interfejsu API allActiveCredentials do pobierania danych logowania. Ten wywołanie skanuje TBR-y znalezione w lokalnej sieci, więc nie zwraca danych logowania, które nie są dostępne dla istniejącego TBR na poziomie lokalnym.

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

Utwórz nową sieć Thread

Jeśli nie ma preferowanych danych logowania do sieci typu Thread ani aktywnego wątku dane logowania użytkownika z siecią Thread, a następnie za pomocą interfejsu API addCredentials możesz dodać do niej dane logowania. Usługi Google Play. Aby to zrobić, musisz utworzyć obiekt ThreadBorderAgent i podać obiekt ThreadNetworkCredentials.

Aby utworzyć losową sieć, wywołaj funkcję newRandomizeBuilder:

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

Aby określić nazwę sieci Thread:

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

Dodawanie danych logowania

Aby udostępnić dane logowania do sieci Thread innym dostawcom Thread: musimy dodać je do Usług Google Play. Zanim dodamy nowe dane logowania, musimy wiedzieć, do którego routera granicznego jest przypisany do której należy sieć.

W tym przykładzie utworzymy ThreadBorderAgent z identyfikatora agenta Border. prześlij nowo utworzone dane logowania do sieci Thread:

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

Wykrywanie i migracja wewnętrznych routerów granicznych

Jeśli masz obecnie routery graniczne w terenie, isPreferredCredentials, aby sprawdzić, czy routery graniczne należą z preferowaną siecią. Ten interfejs API nie wysyła promptów użytkownika w celu uzyskania uprawnień i porównuje dane logowania do routera granicznego z zapisanymi w Usługach Google Play.

Funkcja isPreferredCredentails zwraca wartość 0, gdy nie ma dopasowania, oraz 1, gdy jest ono zgodne, jako typ danych Int. Aby sprawdzić wyniki, możesz użyć IsPreferredCredentialsResult.

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

Aby skorzystać z usługi isPreferredCredentials, musisz utworzyć Najpierw ThreadNetworkCredentials obiekt. Obiekt ThreadNetworkCredentials można utworzyć na kilka sposobów. W kolejnych krokach omówimy te opcje.

Dane logowania do sieci typu Thread według działającego zbioru danych

Czasami router graniczny Thread jest już skonfigurowany z siecią Thread i chcesz dodać tę sieć do usług Google Play, aby udostępnić ją innym dostawcom. Możesz utworzyć ThreadNetworkCredential instancji z nieprzetworzonej listy TLV działającego zbioru danych w wątkach:

  1. Przekonwertuj operacyjny zbiór danych na ByteArray. Na przykład:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Utwórz ThreadNetworkCredentials za pomocą aplikacji fromActiveOperationalDataset. Jeśli się uda, możesz uzyskać nazwę sieci Thread, kanał i inne informacje o sieci. Pełną listę właściwości znajdziesz tutaj: ThreadNetworkCredentials,

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Wywołaj interfejs API isPreferredCredentials i przekaż parametr 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}]") }
    

Dane logowania do sieci Thread według agenta Border

Identyfikator agenta Border jednoznacznie identyfikuje urządzenie routera granicznego. Aby użyć funkcji interfejsu API getCredentialsByBorderAgent, musisz najpierw utworzyć ThreadBorderAgent i przekazać identyfikator agenta Border.

Po utworzeniu obiektu ThreadBorderAgent wywołaj funkcję getCredentialsByBorderAgent. Jeśli dane logowania zostały zapisane, sprawdź, czy są preferowane.

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

Dane uwierzytelniające sieci Thread według rozszerzonego identyfikatora Pan-ID

Podobnie jak w przypadku getPreferredCredentials, możesz też poprosić użytkownika o dane logowania z rozszerzonego identyfikatora PAN routera granicznego. Gdy użytkownik zatwierdzi, funkcja getCredentialsByExtendedPanId zwraca obiekt IntentSender, a wynik funkcji Activity zawiera obiekt ThreadNetworkCredentials.

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

Usuwanie danych logowania

Usunięcie urządzenia Border Router z domu lub przywrócenia go do ustawień fabrycznych Musisz usunąć swoją sieć Thread z Usług 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}]") }
}

Zasoby

Więcej informacji o pakiecie Thread Network SDK znajdziesz w dokumentacji interfejsu API.