Pakiet SDK Thread Network na Androida

Zadbaj o dobrą organizację dzięki kolekcji Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.

Pakiet SDK Thread Network oferuje funkcję podobną do cyfrowego pęku kluczy, dzięki której aplikacje na Androida mogą udostępniać usługom Google Play dane logowania do sieci Thread. Dzięki temu aplikacje mogą skonfigurować dowolne urządzenie z wątku z dowolnego ekosystemu inteligentnego domu bez ujawniania danych logowania i danych użytkownika.

Wystarczy kilka wywołań interfejsu API, aby:

  1. Poproś o preferowane dane logowania do sieci dotyczące wątków z Usług Google Play.
  2. Skonfiguruj nowe routery graniczne i dodaj dane uwierzytelniające sieć Thread do usług Google Play.
  3. Jeśli masz już routery graniczne, możesz sprawdzić, czy routery graniczne są w preferowanej sieci, i w razie potrzeby je przenieść.

Warto wziąć pod uwagę kilka ścieżek użytkowników i deweloperów. Większość z nich opisujemy w tym przewodniku, a także o innych najważniejszych funkcjach i zalecanych zastosowaniach.

Kluczowa terminologia i pojęcia związane z interfejsami API

Zanim rozpoczniesz, warto zapoznać się z tymi terminami:

  • Dane uwierzytelniające sieci z wątkami: binarny obiekt blob TLV wątku, który koduje nazwę sieci z wątkami, klucz sieciowy i inne właściwości wymagane przez urządzenie z wątkiem, by połączyć się z daną siecią Thread.

  • Preferowane dane logowania do sieci Thread: automatycznie wybrane dane logowania do sieci Thread, które mogą być udostępniane aplikacjom innych dostawców za pomocą interfejsu API getPreferredCredentials.

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

  • Aplikacja do konfigurowania routerów granitowych: to aplikacja na Androida, która konfiguruje nowe urządzenia routera w wątku i dodaje do tych usług dane logowania do sieci tworzącej wątek. Twoja aplikacja jest wiarygodnym właścicielem dodanych danych logowania i ma bezpłatny dostęp do tych danych logowania.

Wiele interfejsów Thread Network API zwraca zadanie, które jest wykonywane asynchronicznie. Możesz użyć funkcji addOnSuccessListener i addOnFailureListener, aby zarejestrować wywołania zwrotne i otrzymać wynik. Więcej informacji znajdziesz w dokumentacji zadań.

Własność i konserwacja danych logowania

Aplikacja, która dodaje dane logowania do sieci w wątku, staje się ich właścicielem i ma pełne uprawnienia dostępu do tych danych. Próba uzyskania dostępu do danych logowania dodanych przez inne aplikacje spowoduje wyświetlenie błędu PERMISSION_DENIED.

Jako właściciel aplikacji zalecamy, aby dane logowania w Usługach Google Play były aktualne, gdy sieć Thread Line jest aktualizowana. Oznacza to, że w razie potrzeby możesz dodać dane logowania, zaktualizować dane logowania, gdy zmieni się dane logowania routera obramowania, a także usunąć dane logowania po usunięciu routera z granicy wątku lub przywrócenia ustawień fabrycznych.

Wykrywanie agenta granicznego

Dane logowania muszą być zapisane z identyfikatorem agenta granicy. Upewnij się, że Twoja aplikacja do konfigurowania granic routera Threader potrafi rozpoznać identyfikatory agentów granicy routerów obramowania.

Routery obramowania wątków muszą używać mDNS, aby reklamować informacje o sieci, w tym nazwę sieci, rozszerzony identyfikator pana i identyfikator agenta obramowania. Odpowiednie wartości tych atrybutów txt to nn, xp i id.

W przypadku sieci z routerami obramowania Google Usługi Google Play automatycznie pobierają dane logowania do sieci Google Thread.

Zintegruj pakiet SDK z aplikacją na Androida

Aby to zrobić:

  1. Postępuj zgodnie z instrukcjami podanymi w artykule Konfigurowanie Usług Google Play.

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

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0-beta01'
    
  3. Opcjonalnie: zdefiniuj BorderAgent data class, aby przechowywać informacje o routerze granicznym. Wykorzystamy te dane w tym przewodniku:

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

Potem omówimy zalecane sposoby dodawania preferowanych danych logowania i zarządzania nimi.

Nowe konfiguracje routerów granicznych

Zanim utworzysz nową sieć dla nowych routerów granicznych, spróbuj najpierw użyć preferowanych danych logowania do sieci. Dzięki temu urządzenia z wątkami są połączone z pojedynczą siecią Thread, gdy to możliwe.

Wywołanie funkcji getPreferredCredentials rozpoczyna działanie z prośbą o zezwolenie na żądanie sieciowe. Jeśli dane logowania do sieci są przechowywane w cyfrowym pęku kluczy pakietu Thread SDK, dane logowania zostaną zwrócone do aplikacji.

Poproś o dane logowania

Aby poprosić użytkownika o preferowanie danych logowania:

  1. Zadeklaruj właściwość ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. Przetwórz wynik aktywności zwrócony 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. Zadzwoń do: preferredCredentials i uruchom Aktywność:

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

Tworzenie nowej sieci Thread

Jeśli w sieci użytkownika nie są dostępne preferowane dane logowania do sieci z wątkami, interfejs API addCredentials umożliwia dodanie danych logowania do usług Google Play. Aby to zrobić, musisz utworzyć obiekt ThreadBorderAgent i podać obiekt ThreadNetworkCredentials.

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

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

Aby określić nazwę sieci:

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

Dodaj dane logowania

Aby udostępnić dane logowania do sieci dla innych dostawców, musisz je dodać do usług Google Play. Zanim dodamy nowe dane logowania, musimy też wiedzieć, do którego urządzenia granicznego należy sieć z tą siecią Thread.

W tym przykładzie utworzymy ThreadBorderAgent z identyfikatora agenta obramowania i przekażemy 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}]") }
}

Wykrywaj i przenoś routery graniczne

Jeśli masz obecnie routery graniczne w polu, możesz użyć isPreferredCredentials, aby sprawdzić, czy routery graniczne należą do preferowanej sieci. Ten interfejs API nie prosi użytkownika o zgodę i porównuje dane logowania routera obramowania z danymi przechowywanymi w Usługach Google Play.

isPreferredCredentails zwraca 0 w przypadku braku dopasowania i 1 w przypadku dopasowania jako typ danych Int. Wyniki możesz sprawdzić w IsPreferredCredentialsResult.

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

Aby używać obiektu isPreferredCredentials, musisz najpierw utworzyć obiekt ThreadNetworkCredentials. Wystąpienie ThreadNetworkCredentials możesz utworzyć na kilka sposobów. W kolejnych krokach omówimy te opcje.

Dane logowania do sieci według wątków według zbioru danych

Może się zdarzyć, że router z wątkiem wątków jest już skonfigurowany z siecią Thread, i chcesz dodać tę sieć do usług Google Play, aby udostępnić ją innym dostawcom. Instancja ThreadNetworkCredential możesz utworzyć z nieprzetworzonej listy TLV aktywnego wątku:

  1. Przekonwertuj zbiór danych operacyjnych na ByteArray. Przykład:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. Użyj fromActiveOperationalDataset, aby utworzyć ThreadNetworkCredentials. Jeśli wszystko będzie w porządku, uda Ci się uzyskać nazwę sieci, kanał i inne informacje o wątku. Pełną listę właściwości znajdziesz w artykule ThreadNetworkCredentials.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. Wywołaj interfejs isPreferredCredentials API i przekaż 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 dotyczące wątków według agenta obramowania

Identyfikator agenta granicy jednoznacznie identyfikuje urządzenie routera granicznego. Aby używać interfejsu API getCredentialsByBorderAgent, musisz utworzyć obiekt ThreadBorderAgent i przekazać identyfikator agenta granicy.

Po utworzeniu obiektu ThreadBorderAgent wywołaj 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 logowania do sieci dla wątków przy użyciu rozszerzonego identyfikatora Pan

Podobnie jak w polu getPreferredCredentials, możesz też poprosić użytkownika o dane logowania z routera brzegowego. getCredentialsByExtendedPanId zwraca błąd IntentSender, a wynik działania zawiera obiekt ThreadNetworkCredentials, gdy użytkownik zatwierdzi prośbę.

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

Usuń dane logowania

Gdy usuniesz router routera z domu lub przywrócisz na nim ustawienia fabryczne, musisz usunąć sieć z wątków 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 API.