Android 边界路由器设备指南

Android 应用开发者可以使用 Home API 管理 Thread Border Router (TBR)

GoogleBorderRouterDevice 是使用两个主要设备 trait 实现的: ThreadNetworkCapabilities, 它提供只读属性来检查 border router 功能;以及 ThreadNetworkManagement, 它使用专员的临时预共享密钥 (ePSKc) 处理网络生命周期命令和凭据共享。结构级 互联网访问政策使用 ThreadNetworkSettings trait 进行管理。

在使用任何功能或尝试更新属性之前,请务必检查设备是否支持属性和命令。如需了解详情,请参阅在 Control devices on Android 上控制设备。

Home API 设备类型 trait Kotlin 示例应用 使用场景

边界路由器

GoogleBorderRouterDevice

home.matter.6006.types.0161

必需的 trait
     google ThreadNetworkCapabilities
     google ThreadNetworkManagement

边界路由器

获取有关设备的基本信息

   在 Android 版示例应用中实现   

BasicInformation trait 包含设备的相关信息,例如供应商名称、供应商 ID、产品 ID、 产品名称(包括型号信息)和软件版本:

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

检查边界路由器功能

您可以使用 ThreadNetworkCapabilities trait 检查 border router's 的只读功能 (例如 ePSKc 支持和互联网访问设置配置)。

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 凭据共享是使用专员的临时预共享密钥 (ePSKc) 实现的。ePSKc 模式会生成一个临时的安全密码,外部设备或专员可以使用该密码安全地获取 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 停用事件

TBR 会在 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 网络成员资格

您可以提供有效的 Operational Dataset TLV,以命令 TBR 加入新的 Thread 网络,也可以命令它离开当前网络。

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 trait 是附加到 Structure(代表住宅或建筑物)的可更新 trait。开发者可以使用它配置 结构级互联网访问政策,适用于 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}")
    }
}