מדריך למכשיר נתב גבולות ל-Android

מפתחי אפליקציות ל-Android יכולים להשתמש בממשקי Home API כדי לנהל Thread Border Router (TBR).

ה-GoogleBorderRouterDevice מיושם באמצעות שתי תכונות מכשיר עיקריות: ThreadNetworkCapabilities, שמספקת מאפיינים לקריאה בלבד כדי לבדוק את התכונות של border router, ו- ThreadNetworkManagement, שמטפלת בפקודות של מחזור החיים של הרשת ובשיתוף פרטי הכניסה באמצעות מפתח ששותף מראש זמני עבור ה-Commissioner‏ (ePSKc). מדיניות הגישה לאינטרנט ברמת המבנה מנוהלת באמצעות המאפיין ThreadNetworkSettings.

לפני שמשתמשים בתכונות או מנסים לעדכן מאפיינים, תמיד צריך לבדוק אם המכשיר תומך במאפיינים ובפקודות. מידע נוסף זמין במאמר שליטה במכשירים ב-Android.

סוג המכשיר ב-Home APIs תכונות אפליקציה לדוגמה ב-Kotlin תרחיש לדוגמה

נתב גבולות

GoogleBorderRouterDevice

home.matter.6006.types.0161

מאפיינים נדרשים
     google ThreadNetworkCapabilities
     google ThreadNetworkManagement

נתב גבולות

לקבל מידע בסיסי על מכשיר

   הטמעה באפליקציה לדוגמה ל-Android   

המאפיין BasicInformation כולל מידע כמו שם הספק, מזהה הספק, מזהה המוצר, שם המוצר (כולל מידע על הדגם) וגרסת התוכנה של המכשיר:

// Get device basic information. All general information traits are on the RootNodeDevice type.
    device.type(RootNodeDevice).first().standardTraits.basicInformation?.let { basicInformation ->
        println("vendorName ${basicInformation.vendorName}")
        println("vendorId ${basicInformation.vendorId}")
        println("productId ${basicInformation.productId}")
        println("productName ${basicInformation.productName}")
        println("softwareVersion ${basicInformation.softwareVersion}")
    }

בדיקת היכולות של נתב הגבולות

אפשר לבדוק את היכולות של border router לקריאה בלבד (כמו תמיכה ב-ePSKc והגדרת הגישה לאינטרנט) באמצעות התכונה ThreadNetworkCapabilities.

suspend fun checkBorderRouterCapabilities(device: HomeDevice) {
    // Filter for GoogleBorderRouterDevice device type
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    if (gtbrDevice == null) {
        println("Device is not a Google border router.")
        return
    }

    // Retrieve the ThreadNetworkCapabilities trait
    val capabilitiesTrait = gtbrDevice.trait(ThreadNetworkCapabilities)
    if (capabilitiesTrait == null) {
        println("ThreadNetworkCapabilities trait not found on device.")
        return
    }

    val isEpskcSupported = capabilitiesTrait.epskcSupported ?: false
    val internetAccessOption = capabilitiesTrait.internetAccessOption?.name ?: "None"
    val isIasSupported = !internetAccessOption.equals("None", ignoreCase = true)

    println("ePSKc Supported: $isEpskcSupported")
    println("Internet Access Setting Supported: $isIasSupported")
}

ניהול השיתוף של פרטי הכניסה של פרוטוקול Thread‏ (ePSKc)

כדי לשתף את פרטי הכניסה של Thread, משתמשים במפתח זמני ששותף מראש עבור ה-Commissioner‏ (ePSKc). מצב ePSKc יוצר מפתח גישה זמני ומאובטח, שבו מכשירים חיצוניים או Commissioners יכולים להשתמש כדי לקבל באופן מאובטח את מערך הנתונים של רשת Thread.

הפעלת מצב ePSKc

suspend fun startEpskcSession(device: HomeDevice, durationSeconds: Short): ActivateEpskcModeCommand.Response? {
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    val mgmtTrait = gtbrDevice?.trait(ThreadNetworkManagement)

    if (mgmtTrait == null) {
        println("ThreadNetworkManagement trait not found.")
        return null
    }

    return try {
        val response = mgmtTrait.activateEpskcMode(
            optionalArgs = { this.requestedDurationSeconds = durationSeconds }
        )

        println("ePSKc Session Activated!")
        println("Status: ${response.status}")
        println("Ephemeral PSKc: ${response.epskc}")
        println("Valid Duration (s): ${response.validDurationSeconds}")

        response
    } catch (e: Exception) {
        println("Failed to activate ePSKc mode: ${e.message}")
        null
    }
}

השבתת מצב ePSKc

suspend fun stopEpskcSession(device: HomeDevice) {
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    val mgmtTrait = gtbrDevice?.trait(ThreadNetworkManagement)

    mgmtTrait?.deactivateEpskcMode()
    println("ePSKc mode deactivated.")
}

מעקב אחרי אירועי השבתה של ePSKc

TBRs מפעילים אירועים כשסשן ePSKc מסתיים (לדוגמה, כי המפתח היה בשימוש, הסשן פג או שהוא בוטל באופן ידני).

suspend fun observeEpskcEvents(device: HomeDevice) {
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    val mgmtTrait = gtbrDevice?.trait(ThreadNetworkManagement)

    mgmtTrait?.epskcModeDeactivatedEventFlow()?.collect { event ->
        println("ePSKc Session Ended. Reason: ${event.reason}")
        when (event.reason?.name) {
            "KeyUsed" -> println("Key was successfully used to commission a device.")
            "Expired" -> println("Session timed out before the key was used.")
            "Cancelled" -> println("Session was manually cancelled.")
        }
    }
}

ניהול החברות ברשת Thread

אתם יכולים להורות ל-TBR להצטרף לרשת Thread חדשה על ידי מתן ערכי ה-TLV של קבוצת הנתונים התפעולית הפעילה, או להורות לו לעזוב את הרשת הנוכחית שלו.

suspend fun joinNetwork(device: HomeDevice, datasetTlvs: ByteArray) {
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    val mgmtTrait = gtbrDevice?.trait(ThreadNetworkManagement)

    try {
        val response = mgmtTrait?.joinNetwork(operationalDatasetTlvs = datasetTlvs)
        println("Join network command sent. Status: ${response?.status}")
    } catch (e: Exception) {
        println("Join network failed: ${e.message}")
    }
}

suspend fun leaveNetwork(device: HomeDevice) {
    val gtbrDevice = device.type(GoogleBorderRouterDevice).firstOrNull()
    val mgmtTrait = gtbrDevice?.trait(ThreadNetworkManagement)

    try {
        mgmtTrait?.leaveNetwork()
        println("Leave network command sent successfully.")
    } catch (e: Exception) {
        println("Leave network failed: ${e.message}")
    }
}

הגדרת גישה לאינטרנט ברמת המבנה

המאפיין ThreadNetworkSettings הוא מאפיין שניתן לעדכון ומצורף ל-Structure (שמייצג בית או מבנה). היא מאפשרת למפתחים להגדיר את מדיניות הגישה לאינטרנט לכל המבנה של TBR.

suspend fun updateStructureInternetAccess(structure: Structure, enableInternetAccess: Boolean) {
    // Retrieve the ThreadNetworkSettings trait for the structure
    val settingsTrait = structure.trait(ThreadNetworkSettings).firstOrNull()
    if (settingsTrait == null) {
        println("ThreadNetworkSettings trait not found on structure.")
        return
    }

    val option = if (enableInternetAccess) {
        InternetAccessOption.InternetAccessOptionAll
    } else {
        InternetAccessOption.InternetAccessOptionNone
    }

    try {
        settingsTrait.update {
            setInternetAccessOption(option)
        }
        println("Successfully updated Thread internet access policy to: ${option.name}")
    } catch (e: Exception) {
        println("Failed to update Thread internet access policy: ${e.message}")
    }
}