Android 边界路由器设备指南

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

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

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

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

边界路由器

GoogleBorderRouterDevice

home.matter.6006.types.0161

必需的 trait
     google ThreadNetworkCapabilities
     google ThreadNetworkManagement

边界路由器

获取设备的基本信息

   在 Android 示例应用中实现   

BasicInformation 特征包含供应商名称、供应商 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 的只读功能(例如 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 网络成员资格

您可以通过提供活跃的操作数据集 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 特征是附加到 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}")
    }
}