Разработчики приложений для Android могут использовать Home API для управления Thread Border Router (TBR).
GoogleBorderRouterDevice реализуется с помощью двух основных характеристик устройства:
ThreadNetworkCapabilities,
которая предоставляет атрибуты только для чтения, чтобы проверять функции border router, и
ThreadNetworkManagement,
которая обрабатывает команды жизненного цикла сети и обмен учетными данными с помощью временного общего ключа для уполномоченного устройства (ePSKc). Правила доступа к интернету на уровне дома настраиваются с помощью типажа ThreadNetworkSettings.
Прежде чем использовать функции или обновлять атрибуты, всегда проверяйте, поддерживаются ли они на устройстве. Подробнее о том, как управлять устройствами на платформеAndroid…
| Тип устройства Home API | Черты характера | Пример приложения на Kotlin | История успеха |
|---|---|---|---|
|
Пограничный маршрутизатор
|
Обязательные характеристики 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 осуществляется с помощью временного общего ключа для уполномоченного (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
Вы можете дать команду 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}")
}
}