Android 向けボーダー ルーター デバイスガイド

Android アプリ デベロッパーは、Home API を使用して Thread Border Router (TBR) を管理できます。

GoogleBorderRouterDevice は、2 つのプライマリ デバイス トレイト(ThreadNetworkCapabilitiesThreadNetworkManagement)を使用して実装されます。ThreadNetworkCapabilities は、border router 機能を検査するための読み取り専用属性を提供します。ThreadNetworkManagement は、コミッショナー(ePSKc)の一時的な事前共有鍵を使用して、ネットワーク ライフサイクル コマンドと認証情報の共有を処理します。構造レベルのインターネット アクセス ポリシーは、ThreadNetworkSettings トレイトを使用して管理されます。

機能を使用したり、属性を更新しようとしたりする前に、デバイスの属性とコマンドのサポートを必ず確認してください。詳しくは、Androidでデバイスを制御するをご覧ください。

Google Home の API のデバイスタイプ トレイト Kotlin サンプルアプリ ユースケース

ボーダー ルーター

GoogleBorderRouterDevice

home.matter.6006.types.0161

必須のトレイト
     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 トレイトを使用すると、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}")
    }
}