کیت توسعه نرم‌افزار Thread Network برای Android

«کیت توسعه نرم‌افزار شبکه Thread» عملکردی مشابه دسته‌کلید دیجیتال ارائه می‌دهد و به برنامه‌های Android شما امکان می‌دهد اطلاعات کاربری شبکه Thread را با «خدمات Google Play» هم‌رسانی کنند. این کار به برنامه‌هایتان اجازه می‌دهد هر دستگاه Thread را از هر بوم‌سازگان خانه هوشمند راه‌اندازی کنند، بدون اینکه اطلاعات کاربری و داده‌های کاربر مستقیماً فاش شود.

فقط با چند فراخوانی میانای برنامه‌سازی کاربردی می‌توانید:

  1. اعتبارنامه شبکه Thread ترجیحی را از «خدمات Google Play» درخواست کنید.
  2. Thread Border Router (TBR) جدیدی راه‌اندازی کنید و اطلاعات اعتباری شبکه Thread خود را به خدمات Google Play اضافه کنید.
  3. اگر ازقبل TBR در محل دارید، می‌توانید بررسی کنید که آیا TBRهایتان در شبکه ترجیحی هستند یا نه و درصورت لزوم آن‌ها را منتقل کنید.

چندین سفر کاربر و توسعه‌دهنده وجود دارد که باید درنظر گرفته شود. در این راهنما، به اکثر آن‌ها و همچنین سایر ویژگی‌های کلیدی و موارد استفاده توصیه‌شده خواهیم پرداخت.

اصطلاحات کلیدی و مفاهیم API

قبل‌از شروع، بهتر است با اصطلاحات زیر آشنا شوید:

  • اعتبارنامه‌های شبکه Thread: حباب دودویی Thread TLV که نام شبکه Thread، کلید شبکه، و دیگر ویژگی‌های موردنیاز دستگاه Thread را برای پیوستن به شبکه Thread مشخص‌شده کدگذاری می‌کند.

  • اعتبارنامه‌های شبکه Thread ترجیحی: اعتبارنامه‌های شبکه Thread که به‌طور خودکار انتخاب شده‌اند و می‌توانند بااستفاده از getPreferredCredentials API با برنامه‌های فروشندگان مختلف هم‌رسانی شوند.

  • شناسه Border Agent: شناسه یکتای جهانی ۱۶ بایتی برای TBR دستگاه. این شناسه را فروشندگان border router ایجاد و مدیریت می‌کنند.

  • برنامه راه‌اندازی TBR: این برنامه Android شما است که دستگاه‌های TBR جدید را راه‌اندازی می‌کند و اطلاعات کاربری شبکه Thread را به «خدمات Google Play» اضافه می‌کند. برنامه شما مالک معتبر اعتبارنامه‌های اضافه‌شده است و به آن‌ها دسترسی دارد.

بسیاری از Thread Network APIها یک Task برمی‌گردانند که به‌صورت ناهمگام تکمیل می‌شود. می‌توانید از addOnSuccessListener و addOnFailureListener برای ثبت فراخوانی‌های برگشتی جهت دریافت نتیجه استفاده کنید. برای کسب اطلاعات بیشتر، به Task مراجعه کنید.

مالکیت و نگهداری اعتبارنامه‌ها

برنامه‌ای که اطلاعات اعتباری شبکه Thread را اضافه می‌کند، مالک اطلاعات اعتباری می‌شود و اجازه‌های کامل برای دسترسی به اطلاعات اعتباری را دارد. اگر بخواهید به اطلاعات اعتباری اضافه‌شده توسط برنامه‌های دیگر دسترسی پیدا کنید، خطای PERMISSION_DENIED دریافت خواهید کرد.

به‌عنوان مالک برنامه، توصیه می‌شود که وقتی شبکه TBR به‌روز می‌شود، اعتبارنامه‌های ذخیره‌شده در «خدمات Google Play» را به‌روز نگه دارید. این یعنی افزودن اطلاعات اعتباری درصورت نیاز، به‌روزرسانی اطلاعات اعتباری هنگام تغییر اطلاعات اعتباری شبکه Thread مربوط به border router، و برداشتن اطلاعات اعتباری هنگام برداشته شدن یا بازنشانی کارخانه‌ای TBR.

کاوش Border Agent

اعتبارنامه‌ها باید با «شناسه مأمور مرزی» ذخیره شوند. باید مطمئن شوید که برنامه راه‌اندازی TBR شما می‌تواند شناسه‌های «نماینده مرزی» TBR شما را تعیین کند.

‫TBRها باید از mDNS برای تبلیغ اطلاعات شبکه Thread استفاده کنند، ازجمله «نام شبکه»، «شناسه Pan گسترده»، و «شناسه عامل مرزی». مقادیر txt متناظر برای این مشخصه‌ها به‌ترتیب nn، xp، و id است.

برای شبکه‌های دارای Google Thread Border Router (gTBR)s، «خدمات Google Play» به‌طور خودکار اعتبارنامه شبکه Google Thread را برای استفاده دریافت می‌کند.

ادغام کردن کیت توسعه نرم‌افزار در برنامه Android

برای شروع به کار، مراحل زیر را تکمیل کنید:

  1. دستورالعمل‌های ارائه‌شده در راه‌اندازی خدمات Google Play را دنبال کنید.

  2. وابستگی «خدمات Google Play» را به فایل build.gradle اضافه کنید:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'
    
  3. اختیاری: کلاس داده BorderAgent را برای ذخیره کردن TBR اطلاعات تعریف کنید. در سراسر این راهنما از این داده‌ها استفاده خواهیم کرد:

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

سپس مراحل توصیه‌شده برای افزودن و مدیریت اطلاعات کاربری ترجیحی را مرور خواهیم کرد.

راه‌اندازی‌های جدید «رهیاب مرزی Thread»

قبل‌از ایجاد شبکه جدید برای رهیاب‌های مرزی جدید، مهم است که ابتدا از اطلاعات اعتباری شبکه ترجیحی استفاده کنید. این کار تضمین می‌کند که دستگاه‌های Thread درصورت امکان به یک شبکه Thread متصل شوند.

فراخوانی getPreferredCredentials یک «فعالیت» را راه‌اندازی می‌کند و از کاربران می‌خواهد درخواست شبکه را مجاز کنند. اگر اعتبارنامه شبکه در دسته کلید دیجیتال Thread SDK ذخیره شده باشد، اعتبارنامه به برنامه شما برگردانده می‌شود.

درخواست اعتبارنامه

برای درخواست اطلاعات اعتباری ترجیحی از کاربر:

  1. اعلام ActivityLauncher:

    private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
    
  2. نتیجه «فعالیت» را که به‌صورت 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. اگر درحال راه‌اندازی TBR جدیدی هستید، توصیه می‌شود preferredCredentials را فراخوانی کنید و «فعالیت» را راه‌اندازی کنید. این تماس تضمین می‌کند که TBR جدیدتان از همان اطلاعات اعتباری‌ای استفاده کند که قبلاً به‌عنوان ترجیحی در تلفن ذخیره شده است، و همگرایی TBRهای مختلف را به همان شبکه ارتقا می‌دهد.

    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. اگر مورد استفاده شما مربوط به راه‌اندازی دستگاه‌های غیر TBR است، مانند دستگاه نهایی Matter-over-Thread جدید، توصیه می‌شود از allActiveCredentials api برای واکشی اطلاعات کاربری استفاده کنید. این فراخوانی برای یافتن TBRهای موجود در شبکه محلی اسکن می‌کند و بنابراین اطلاعات اعتباری را که ازطریق TBR موجود به‌صورت محلی دردسترس نیست برنمی‌گرداند.

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

ایجاد شبکه Thread جدید

اگر نه اطلاعات کاربری شبکه Thread ترجیحی و نه اطلاعات کاربری Thread فعال در شبکه Thread کاربر دردسترس نباشد، می‌توانید از میانای برنامه‌سازی کاربردی addCredentials برای افزودن اطلاعات کاربری به «خدمات Google Play» استفاده کنید. برای انجام این کار، باید ThreadBorderAgent ایجاد کنید، و همچنین شیء ThreadNetworkCredentials ارائه دهید.

برای ایجاد شبکه تصادفی، newRandomizeBuilder را فراخوانی کنید:

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

برای مشخص کردن نام شبکه Thread:

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

افزودن اعتبارنامه‌ها

برای اینکه اعتبارنامه‌های شبکه Thread شما برای سایر فروشندگان Thread دردسترس قرار گیرد، باید آن‌ها را به «خدمات Google Play» اضافه کنیم. قبل‌از اینکه بتوانیم اعتبارنامه‌های جدیدمان را اضافه کنیم، باید بدانیم این شبکه Thread به کدام دستگاه TBR تعلق دارد.

در این مثال، یک ThreadBorderAgent از «شناسه عامل مرزی» ایجاد می‌کنیم و اعتبارنامه شبکه 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}]") }
}

شناسایی و انتقال border routerهای درون‌زمینه

اگر border routerهای درون‌زمینه دارید، می‌توانید از isPreferredCredentials استفاده کنید تا مشخص کنید آیا border routerهایتان به شبکه ترجیحی تعلق دارند یا نه. این میانای برنامه‌سازی کاربردی از کاربر درخواست اجازه نمی‌کند و اعتبارنامه border router را با آنچه در «خدمات Google Play» ذخیره شده است مطابقت می‌دهد.

isPreferredCredentials برای موارد منطبق‌نشده 0 و برای موارد منطبق‌شده 1 را به‌عنوان نوع داده Int برمی‌گرداند. می‌توانید از IsPreferredCredentialsResult برای بررسی نتایجتان استفاده کنید.

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

برای استفاده از isPreferredCredentials، ابتدا باید شیء ThreadNetworkCredentials ایجاد کنید. چندین روش برای نمونه‌سازی ThreadNetworkCredentials وجود دارد. در مراحل بعدی، این گزینه‌ها را بررسی خواهیم کرد.

اعتبارنامه‌های شبکه Thread براساس «مجموعه داده‌های عملیاتی»

مواردی وجود دارد که TBR شما ازقبل با شبکه Thread راه‌اندازی شده است و می‌خواهید این شبکه Thread را به خدمات Google Play اضافه کنید تا آن را با فروشندگان دیگر هم‌رسانی کنید. می‌توانید نمونه ThreadNetworkCredential را از فهرست TLV «مجموعه‌داده عملیاتی فعال Thread» خام ایجاد کنید:

  1. تبدیل «مجموعه داده‌های عملیاتی» به ByteArray. برای مثال:

    val activeDataset =
          "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
    
    fun String.dsToByteArray(): ByteArray {
      return chunked(2).map { it.toInt(16).toByte() }.toByteArray()
    }
    
  2. از fromActiveOperationalDataset برای ایجاد ThreadNetworkCredentials استفاده کنید. درصورت موفقیت‌آمیز بودن، می‌توانید نام، کانال، و سایر اطلاعات شبکه Thread را دریافت کنید. برای مشاهده فهرست کامل ویژگی‌ها، به ThreadNetworkCredentials مراجعه کنید.

    val threadNetworkCredentials =
        ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset)
    Log.d(
        "threadNetworkCredentials",
        threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
    
  3. isPreferredCredentials API را فراخوانی کنید و 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 توسط «عامل مرزی»

«شناسه عامل مرزی» به‌طور منحصربه‌فرد دستگاه TBR را شناسایی می‌کند. برای استفاده از getCredentialsByBorderAgent API، ابتدا باید یک شیء ThreadBorderAgent ایجاد کنید و شناسه Border Agent را ارسال کنید.

پس‌از ایجاد شیء ThreadBorderAgent، getCredentialsByBorderAgent را فراخوانی کنید. اگر اطلاعات کاربری ذخیره شده است، بررسی کنید ببینید آیا ترجیح داده شده‌اند یا نه.

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 براساس شناسه PAN گسترش‌یافته

مشابه getPreferredCredentials، می‌توانید از کاربر بخواهید اعتبارنامه‌های مربوط به شناسه PAN گسترش‌یافته TBR را ارائه دهد. getCredentialsByExtendedPanId یک IntentSender برمی‌گرداند و وقتی کاربر تأیید می‌کند، نتیجه «فعالیت» حاوی شیء 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}]") }
}

برداشتن اعتبارنامه‌ها

وقتی دستگاه border router از خانه شما برداشته می‌شود یا بازنشانی کارخانه‌ای می‌شود، باید شبکه Thread آن را از «خدمات 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}]") }
}

منابع

برای کسب اطلاعات بیشتر درباره Thread Network SDK، به مرجع میانای برنامه‌سازی کاربردی مراجعه کنید.