Android app developers can use the Home APIs to manage a Thread Border Router (TBR).

The `GoogleBorderRouterDevice` is implemented using two primary device
traits:
[`ThreadNetworkCapabilities`](https://developers.home.google.com/reference/kotlin/com/google/home/google/ThreadNetworkCapabilities.md.txt),
which provides read-only attributes to inspect border router features, and
[`ThreadNetworkManagement`](https://developers.home.google.com/reference/kotlin/com/google/home/google/ThreadNetworkManagement.md.txt),
which handles network lifecycle commands and credential sharing
using an Ephemeral Pre-Shared Key for the Commissioner (ePSKc). Structure-level
internet access policies are managed using the
[`ThreadNetworkSettings`](https://developers.home.google.com/reference/kotlin/com/google/home/google/ThreadNetworkSettings.md.txt)
trait.

Always check for attribute and command support for a device prior to using any
features or attempting to update attributes. See [Control devices on
Android](https://developers.home.google.com/apis/android/device/control) for more
information.

<br />


| Home APIs Device Type | Traits | Kotlin Sample App | Use Case |
|---|---|:---:|:---:|
| Border Router `GoogleBorderRouterDevice` `home.matter.6006.types.0161` | Required Traits google [ThreadNetworkCapabilities](https://developers.home.google.com/reference/kotlin/com/google/home/google/ThreadNetworkCapabilities.md.txt) google [ThreadNetworkManagement](https://developers.home.google.com/reference/kotlin/com/google/home/google/ThreadNetworkManagement.md.txt) | Yes | [Border Router](https://developers.home.google.com/use-cases?device=border-router) |

<br />

> [!NOTE]
> **Note:** The Automation API doesn't support these traits.

## Get basic information about a device

[Implemented in Sample App for Android](https://developers.home.google.com/apis/android/sample-app/build.md.txt)

The [`BasicInformation`](https://developers.home.google.com/reference/kotlin/com/google/home/matter/standard/BasicInformation.md.txt)
trait includes information like vendor name, vendor ID, product ID,
product name (includes model information), and software version for a device:

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

## Inspect border router capabilities

You can examine a border router's read-only capabilities
(such as ePSKc support and Internet Access setting configuration) using the
`ThreadNetworkCapabilities` trait.

```kotlin
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")
}
```

## Manage Thread credential sharing (ePSKc)

Thread credential sharing is achieved using an Ephemeral Pre-Shared Key for the
Commissioner (ePSKc). ePSKc mode generates a temporary, secure passkey that
external devices or commissioners can use to securely obtain the Thread network
dataset.

### Activate ePSKc mode

```kotlin
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
    }
}
```

### Deactivate ePSKc mode

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

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

### Observe ePSKc deactivation events

TBRs emit events when an ePSKc session ends (for example,
because the key was used, the session expired, or it was manually cancelled).

```kotlin
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.")
        }
    }
}
```

## Manage Thread network membership

You can command a TBR to join a new Thread network by
providing the active Operational Dataset TLVs, or command it to leave its
current network.

```kotlin
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}")
    }
}
```

## Configure structure-level internet access

The `ThreadNetworkSettings` trait is an updatable trait attached to a
`Structure` (representing a home or building). It allows developers to configure
the structure-wide internet access policy for TBRs.

```kotlin
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}")
    }
}
```