ערכת ה-SDK של רשת Thread מספקת פונקציונליות שדומה לאוסף מפתחות דיגיטלי, ומאפשרת לאפליקציות ל-Android לשתף את פרטי הכניסה לרשת Thread עם Google Play Services. כך האפליקציות שלכם יכולות להגדיר כל מכשיר Thread מכל סביבת בית חכם, בלי לחשוף פרטי כניסה ונתוני משתמשים באופן ישיר.
בעזרת כמה קריאות ל-API, תוכלו:
- לבקש מ-Google Play Services את פרטי הכניסה המועדפים לפרוטוקול Thread.
- מגדירים נתבי גבול חדשים ומוסיפים את פרטי הכניסה לרשת Thread ל-Google Play Services.
- אם כבר יש לכם נתבי גבול בשטח, תוכלו לבדוק אם נתבי הגבול נמצאים ברשת המועדפת ולעביר אותם, אם צריך.
יש כמה תהליכים שעוברים המשתמשים והמפתחים שצריך להביא בחשבון. נסביר על רובן במדריך הזה, יחד עם תכונות מפתח אחרות והמלצות לשימוש.
מונחים ומושגי API מרכזיים
לפני שמתחילים, חשוב להבין את המונחים הבאים:
פרטי הכניסה של רשת Thread: blob בינארי של ערכים מסוג TLV של Thread שמקודדים את שם רשת Thread, מפתח הרשת ומאפיינים אחרים שנדרשים למכשיר Thread כדי להצטרף לרשת Thread נתונה.
פרטי הכניסה המועדפים לרשת Thread: פרטי הכניסה לרשת Thread שנבחרו באופן אוטומטי, שאפשר לשתף עם אפליקציות של ספקים שונים באמצעות ה-API
getPreferredCredentials
.מזהה של סוכן גבול: מזהה ייחודי גלובלי באורך 16 בייטים של מכשיר Thread Border Router. המזהה הזה נוצר ומנוהל על ידי ספקי נתב הגבול.
האפליקציה 'הגדרת נתב Thread Border': האפליקציה ל-Android שמגדירה מכשירים חדשים מסוג Thread Border Router ומוסיף את פרטי הכניסה לרשת של פרוטוקול Thread אל Google Play Services. האפליקציה היא הבעלים המורשה של פרטי הכניסה שנוספו, ויש לה גישה אליהם.
הרבה ממשקי Thread Network API מחזירים משימה שמסתיימת באופן אסינכררוני. אפשר להשתמש ב-addOnSuccessListener וב-addOnFailureListener כדי לרשום פונקציות חזרה (callbacks) לקבלת התוצאה. למידע נוסף, אפשר לעיין במסמכי העזרה של Task.
בעלות ותחזוקה של פרטי כניסה
האפליקציה שמוסיפה את פרטי הכניסה לרשת בפרוטוקול Thread הופכת לבעלים של
ויש לו הרשאות מלאות לגשת לפרטי הכניסה. אם תנסה
כדי לגשת לפרטי כניסה שנוספו על ידי אפליקציות אחרות, תקבלו PERMISSION_DENIED
שגיאה.
בתור בעלי האפליקציה, מומלץ לעדכן את פרטי הכניסה ששמורים ב-Google Play Services כשהרשת של Thread Border Router מתעדכנת. הזה פירושו הוספת פרטי כניסה בעת הצורך, עדכון פרטי הכניסה כאשר הגבול פרטי הכניסה לרשת בפרוטוקול Thread של הנתב משתנים, ומסירים פרטי כניסה כאשר הוסר נתב גבולות לשרשורים או אופס להגדרות המקוריות.
גילוי סוכן גבול
צריך לשמור את פרטי הכניסה עם מזהה של סוכן גבולות. עליכם לוודא שאפליקציית ההגדרה של נתב הגבולות ל-Thread יכולה לקבוע את מזהי ה-Border Agent של נתב הגבולות ל-Thread.
נתבי הגבול של Thread חייבים להשתמש ב-mDNS כדי לפרסם את פרטי הרשת של Thread, כולל שם הרשת, מזהה Pan מורחב ומזהה הסוכן של הגבול.
ערכי txt
התואמים למאפיינים האלה הם nn
, xp
ו-id
,
בהתאמה.
ברשתות עם נתבים של Google, שירות Google Play Services מקבל באופן אוטומטי את פרטי הכניסה לרשת Google Thread לשימוש.
שילוב ה-SDK באפליקציה ל-Android
כדי להתחיל, מבצעים את השלבים הבאים:
פועלים לפי ההוראות שמפורטות במאמר הגדרת Google Play Services.
מוסיפים את התלות ב-Google Play Services לקובץ
build.gradle
:implementation 'com.google.android.gms:play-services-threadnetwork:16.2.1'
אופציונלי: מגדירים סוג נתונים
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,
יוחזרו לאפליקציה.
בקשה לפרטי כניסה
כדי לבקש מהמשתמש להזין פרטי כניסה מועדפים:
הצהרה על
ActivityLauncher
:private lateinit var preferredCredentialsLauncher: ActivityResultLauncher<IntentSenderRequest>
טיפול בתוצאה של הפעילות, שמוחזרת כ-
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.") } }
אם מגדירים נתב חדש לגבולות שרשור, מומלץ להתקשר
preferredCredentials
ומפעילים את הפעילות. הקריאה הזו תבטיחה ש-Thread Border Router החדש ישתמש באותם פרטי הכניסה שכבר מאוחסנים בתור מועדפים בטלפון, וכך תעודד את ההתכנסות של נתבים שונים מסוג 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}]") } }
אם תרחיש השימוש שלכם קשור להגדרת מכשירים שאינם 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 ברשת של המשתמש, אפשר להשתמש ב-addCredentials
API כדי להוסיף פרטי כניסה ל-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
אם אין התאמה, ואת הערך 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 הזו ל-Google Play Services כדי לשתף אותה עם ספקים אחרים. אפשר ליצור ThreadNetworkCredential
מכונה מרשימת TLV גולמיים של Thread Active למערך נתונים תפעולי:
ממירים את מערך הנתונים התפעולי ל-
ByteArray
. לדוגמה:val activeDataset = "0e080000000000010000000300000f35060004001fffe0020833333333...".dsToByteArray()
fun String.dsToByteArray(): ByteArray { return chunked(2).map { it.toInt(16).toByte() }.toByteArray() }
משתמשים ב-
fromActiveOperationalDataset
כדי ליצור את ה-ThreadNetworkCredentials
. אם הבדיקה תצליח, תוכלו לקבל את השם, הערוץ ופרטים נוספים של רשת Thread. רשימה מלאה של המאפיינים מופיעה במאמר ThreadNetworkCredentials.val threadNetworkCredentials = ThreadNetworkCredentials.fromActiveOperationalDataset(activeDataset) Log.d( "threadNetworkCredentials", threadNetworkCredentials.channel.toString() + " - " + threadNetworkCredentials.networkName)
קוראים ל-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 לפי סוכן גבול
מזהה של Border Agent מזהה באופן ייחודי מכשיר של נתב גבול. כדי להשתמש ב-
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 לפי מזהה Pan מורחב
בדומה ל-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}]") }
}
הסרת פרטי הכניסה
אם תסירו את מכשיר Border Router מהבית או תאפסו אותו להגדרות המקוריות, תצטרכו להסיר את רשת 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.