SDK של רשת Thread ל-Android

ערכת ה-SDK של רשת Thread מספקת פונקציונליות שדומה לפונקציונליות של דפדפן דיגיטלי keychain, שמאפשר לאפליקציות ל-Android לשתף פרטי כניסה לרשת בפרוטוקול Thread עם Google Play Services. כך האפליקציות שלך יכולות להגדיר כל מכשיר בפרוטוקול Thread בכל סביבה עסקית של בית חכם, בלי לחשוף את פרטי הכניסה ואת נתוני המשתמשים באופן ישיר.

באמצעות כמה קריאות ל-API תוכלו:

  1. בקשה לפרטי כניסה מועדפים לרשת בפרוטוקול Thread מ-Google Play Services.
  2. הגדרה של נתבי גבולות חדשים והוספת פרטי הכניסה ל-Google של רשת פרוטוקול Thread Play Services.
  3. אם כבר יש לכם נתבי גבולות בתוך השטח, אפשר לבדוק אם הגבול הנתבים נמצאים ברשת המועדפת ומעבירים אותם, אם יש צורך.

יש מספר מסלולים של משתמשים ומפתחים שכדאי לשקול. נעסוק ברוב הנושאים במדריך זה, יחד עם תכונות מפתח נוספות ושימוש מומלץ.

מונחים מרכזיים ומושגי API

לפני שמתחילים, חשוב להבין את המונחים הבאים:

  • פרטי כניסה לרשת בפרוטוקול Thread: blob בינארי של רכיבי Thread מסוג Thread שמקודדים שם רשת פרוטוקול Thread, מפתח רשת ומאפיינים אחרים שנדרשים על ידי מכשיר בפרוטוקול Thread כדי להצטרף לרשת בפרוטוקול Thread.

  • פרטי כניסה לרשת מועדפת של פרוטוקול Thread: רשת פרוטוקול Thread שנבחרה באופן אוטומטי שאפשר לשתף עם אפליקציות של ספקים שונים באמצעות API של getPreferredCredentials.

  • Border Agent ID: מזהה ייחודי גלובלי בגודל 16 בייט לנתב Thread Border במכשיר. המזהה הזה נוצר ומנוהל על ידי ספקים של נתבי גבול.

  • האפליקציה 'הגדרת נתב Thread Border': האפליקציה ל-Android שמגדירה מכשירים חדשים מסוג Thread Border Router ומוסיף את פרטי הכניסה לרשת של פרוטוקול Thread אל Google Play Services. האפליקציה שלך היא הבעלים המוסמך של האפליקציה שהוספת ויש לו גישה אליהם.

רבים מממשקי ה-API של רשת Thread מחזירים משימה שמסתיימת באופן אסינכרוני. אפשר להשתמש addOnSuccessListener ו-addOnFailureListener כדי לרשום קריאות חוזרות (callback) לקבלת התוצאה. מידע נוסף זמין משימה התיעוד.

בעלות ותחזוקה של פרטי כניסה

האפליקציה שמוסיפה את פרטי הכניסה לרשת בפרוטוקול Thread הופכת לבעלים של ויש לו הרשאות מלאות לגשת לפרטי הכניסה. אם תנסה כדי לגשת לפרטי כניסה שנוספו על ידי אפליקציות אחרות, תקבלו PERMISSION_DENIED שגיאה.

כבעלים של האפליקציה, מומלץ לשמור את פרטי הכניסה ששמורים ב-Google שירותי Play מעודכנים כשרשת נתב Thread Border מעודכנת. הזה פירושו הוספת פרטי כניסה בעת הצורך, עדכון פרטי הכניסה כאשר הגבול פרטי הכניסה לרשת בפרוטוקול Thread של הנתב משתנים, ומסירים פרטי כניסה כאשר הוסר נתב גבולות לשרשורים או אופס להגדרות המקוריות.

גילוי סוכן גבול

צריך לשמור את פרטי הכניסה עם מזהה של סוכן גבול. צריך לוודא האפליקציה 'הגדרת נתב Thread Border' יכולה לזהות את המזהים של סוכני הגבול של נתבי הגבולות בפרוטוקול Thread.

נתבי Thread Border חייבים להשתמש ב-mDNS כדי לפרסם פרטי רשת בפרוטוקול Thread, כולל שם הרשת, מזהה תנועה מורחב ומזהה סוכן גבול. ערכי txt התואמים למאפיינים האלה הם nn, xp ו-id, בהתאמה.

לרשתות עם נתבי גבול של Google, Google Play Services באופן אוטומטי מקבל את פרטי הכניסה של רשת Google Thread לשימוש.

שילוב ה-SDK באפליקציה ל-Android

כדי להתחיל, מבצעים את השלבים הבאים:

  1. צריך לפעול לפי ההוראות שמפורטות בכתובת מגדירים את Google Play Services.

  2. צריך להוסיף את התלות של Google Play Services לקובץ build.gradle:

    implementation 'com.google.android.gms:play-services-threadnetwork:16.0.0'
    
  3. אופציונלי: הגדרת סיווג נתונים BorderAgent לאחסון נתב גבול מידע. אנחנו נשתמש בנתונים האלה לאורך המדריך הזה:

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

בשלב הבא, נעבור על השלבים המומלצים להוספה ולניהול של הקמפיינים המועדפים פרטי הכניסה.

הגדרות חדשות של נתב גבול

לפני שיוצרים רשת חדשה לנתבי גבולות חדשים, חשוב עליך לנסות קודם להשתמש בפרטי הכניסה לרשת המועדפת. כך אפשר להבטיח מכשירים בפרוטוקול 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. התקשרות אל preferredCredentials והפעלה של הפעילות:

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

יצירה של רשת פרוטוקול Thread חדשה

אם אין פרטי כניסה מועדפים לרשת בפרוטוקול Thread זמינים רשת של פרוטוקול Thread, ואז אפשר להשתמש ב-API addCredentials כדי להוסיף פרטי כניסה Google Play Services. לשם כך עליך ליצור ThreadBorderAgent, וגם מספקים אובייקט ThreadNetworkCredentials.

כדי ליצור רשת אקראית, קוראים ל-newRandomizeBuilder:

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

כדי לציין את שם הרשת של פרוטוקול Thread:

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

הוספת פרטי כניסה

כדי שפרטי הכניסה לרשת בפרוטוקול Thread יהיו זמינים לספקי פרוטוקולי Thread אחרים: אנחנו צריכים להוסיף אותן ל-Google Play Services. לפני שנוסיף את האפשרות אנחנו צריכים גם לדעת לאיזה נתב גבול שייכת ל- .

בדוגמה הזו, ניצור 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}]") }
}

זיהוי והעברה של נתבי גבולות בתוך השטח

אם יש לכם כרגע נתבי גבולות בתוך השטח, אפשר להשתמש isPreferredCredentials כדי לקבוע אם נתבי הגבולות שלך שייכים לרשת המועדפת. ה-API הזה לא מציג משתמש מורשה ובודק את פרטי הכניסה של נתב הגבולות מול מה שמאוחסן ב-Google Play Services.

הפונקציה isPreferredCredentails מחזירה 0 עבור not Match, ו-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 לפי מערך נתונים תפעולי

יש מקרים שבהם נתב Thread Border [נתב גבול של פרוטוקול Thread] כבר מוגדר עם רשת של פרוטוקול Thread, וברצונך להוסיף את הרשת הזו של פרוטוקול Thread לשירותי Google Play כדי לשתף אותו עם ספקים אחרים. אפשר ליצור ThreadNetworkCredential מכונה מרשימת TLV גולמיים של Thread Active למערך נתונים תפעולי:

  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. קוראים ל-API של isPreferredCredentials ומעבירים את 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 לפי סוכן גבול

מזהה סוכן גבול הוא מזהה ייחודי של מכשיר נתב גבול. כדי להשתמש ב- API getCredentialsByBorderAgent, תחילה צריך ליצור אובייקט ThreadBorderAgent ומעבירים את המזהה של סוכן הגבול.

אחרי שיוצרים את האובייקט 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 לפי מזהה תנועה מורחבת

בדומה ל-getPreferredCredentials, אפשר גם לבקש מהמשתמש בפרטי הכניסה מהמזהה המורחב של נתב הגבולות. 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}]") }
}

הסרת פרטי הכניסה

כשמסירים את נתב הגבול מהבית או כשמאפסים להגדרות המקוריות, צריך להסיר את הרשת בפרוטוקול Thread מ-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}]") }
}

משאבים

מידע נוסף על Thread Network SDK זמין הפניית API.