Руководство по использованию пограничного маршрутизатора для iOS

Разработчики iOS-приложений могут использовать API Home для управления пограничным маршрутизатором Thread.

Объект GoogleBorderRouterDevice реализован с использованием двух основных характеристик устройства: ThreadNetworkCapabilitiesTrait , которая предоставляет атрибуты только для чтения для проверки функций пограничного маршрутизатора, и ThreadNetworkManagementTrait , которая обрабатывает команды жизненного цикла сети и совместное использование учетных данных с помощью временного предварительно согласованного ключа для комиссара (ePSKc). Политики доступа в Интернет на уровне структуры управляются с помощью характеристики ThreadNetworkSettingsTrait .

Перед использованием каких-либо функций или попыткой обновления атрибутов всегда проверяйте поддержку атрибутов и команд для устройства. См. раздел «Управление устройствами» .iOS для получения дополнительной информации.

Главная API Тип устройства Черты Пример приложения на Swift Вариант использования

Пограничный маршрутизатор

Google Border Router DeviceType

home.matter.6006.types.0161

Необходимые характеристики
google ThreadNetworkCapabilitiesTrait
google ThreadNetworkManagementTrait

Пограничный маршрутизатор

Получите основную информацию об устройстве.

Параметр BasicInformation включает в себя такую ​​информацию, как название производителя, идентификатор производителя, идентификатор продукта, название продукта (включая информацию о модели) и версия программного обеспечения устройства:

let vendorName = basicInfoTrait.attributes.vendorName!
let vendorID = basicInfoTrait.attributes.vendorID!
let productID = basicInfoTrait.attributes.productID!
let productName = basicInfoTrait.attributes.productName!
let softwareVersion = basicInfoTrait.attributes.softwareVersion!

Проверьте возможности пограничного маршрутизатора.

Вы можете проверить возможности маршрутизатора, доступные только для чтения (например, поддержку ePSKc и конфигурацию параметров доступа в Интернет), используя трейт ThreadNetworkCapabilitiesTrait .

func checkBorderRouterCapabilities(device: HomeDevice) async {
    // Filter for GoogleBorderRouterDevice device type
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self) else {
        print("Device is not a Google border router.")
        return
    }

    // Retrieve the ThreadNetworkCapabilitiesTrait
    guard let capabilitiesTrait = gtbrDevice.traits(Google.ThreadNetworkCapabilitiesTrait.self) else {
        print("ThreadNetworkCapabilitiesTrait not found on device.")
        return
    }

    do {
        let isEpskcSupported = try await capabilitiesTrait.epskcSupported.read()
        let internetAccessOption = try await capabilitiesTrait.internetAccessOption.read()
        let isIasSupported = internetAccessOption != .none

        print("ePSKc Supported: \(isEpskcSupported)")
        print("Internet Access Setting Supported: \(isIasSupported)")
    } catch {
        print("Failed to read capabilities: \(error)")
    }
}

Управление совместным использованием учетных данных потоков (ePSKc)

Совместное использование учетных данных Thread осуществляется с помощью временного предварительно согласованного ключа для комиссара (ePSKc). В режиме ePSKc генерируется временный, защищенный пароль, который внешние устройства или комиссары могут использовать для безопасного получения набора данных сети Thread.

Активировать режим ePSKc

func startEpskcSession(device: HomeDevice, durationSeconds: Int16) async -> Google.ThreadNetworkManagementTrait.ActivateEpskcModeResponse? {
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self),
          let mgmtTrait = gtbrDevice.traits(Google.ThreadNetworkManagementTrait.self) else {
        print("ThreadNetworkManagementTrait not found.")
        return nil
    }

    do {
        var request = Google.ThreadNetworkManagementTrait.ActivateEpskcModeRequest()
        request.requestedDurationSeconds = durationSeconds

        let response = try await mgmtTrait.activateEpskcMode(request)

        print("ePSKc Session Activated!")
        print("Status: \(response.status)")
        print("Ephemeral PSKc: \(response.epskc)")
        print("Valid Duration (s): \(response.validDurationSeconds)")

        return response
    } catch {
        print("Failed to activate ePSKc mode: \(error)")
        return nil
    }
}

Отключить режим ePSKc

func stopEpskcSession(device: HomeDevice) async {
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self),
          let mgmtTrait = gtbrDevice.traits(Google.ThreadNetworkManagementTrait.self) else {
        return
    }

    do {
        try await mgmtTrait.deactivateEpskcMode(Google.ThreadNetworkManagementTrait.DeactivateEpskcModeRequest())
        print("ePSKc mode deactivated.")
    } catch {
        print("Failed to deactivate ePSKc mode: \(error)")
    }
}

Отслеживайте события деактивации ePSKc.

Маршрутизаторы граничных потоков генерируют события при завершении сессии ePSKc (например, из-за использования ключа, истечения срока действия сессии или ее ручной отмены).

func observeEpskcEvents(device: HomeDevice) async {
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self),
          let mgmtTrait = gtbrDevice.traits(Google.ThreadNetworkManagementTrait.self) else {
        return
    }

    do {
        for try await event in mgmtTrait.epskcModeDeactivatedEvent.stream() {
            print("ePSKc Session Ended. Reason: \(event.reason)")
            switch event.reason {
            case .keyUsed:
                print("Key was successfully used to commission a device.")
            case .expired:
                print("Session timed out before the key was used.")
            case .cancelled:
                print("Session was manually cancelled.")
            @unknown default:
                print("Unknown deactivation reason.")
            }
        }
    } catch {
        print("Error streaming ePSKc events: \(error)")
    }
}

Управление членством в сети Thread

Вы можете отдать команду маршрутизатору Thread Border Router подключиться к новой сети Thread, указав активные TLV-коды операционных наборов данных, или отдать команду покинуть текущую сеть.

func joinNetwork(device: HomeDevice, datasetTlvs: Data) async {
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self),
          let mgmtTrait = gtbrDevice.traits(Google.ThreadNetworkManagementTrait.self) else {
        return
    }

    do {
        var request = Google.ThreadNetworkManagementTrait.JoinNetworkRequest()
        request.operationalDatasetTlvs = datasetTlvs

        let response = try await mgmtTrait.joinNetwork(request)
        print("Join network command sent. Status: \(response.status)")
    } catch {
        print("Join network failed: \(error)")
    }
}

func leaveNetwork(device: HomeDevice) async {
    guard let gtbrDevice = device.type(Google.GoogleBorderRouterDevice.self),
          let mgmtTrait = gtbrDevice.traits(Google.ThreadNetworkManagementTrait.self) else {
        return
    }

    do {
        try await mgmtTrait.leaveNetwork(Google.ThreadNetworkManagementTrait.LeaveNetworkRequest())
        print("Leave network command sent successfully.")
    } catch {
        print("Leave network failed: \(error)")
    }
}

Настройка доступа в интернет на структурном уровне

Трейт ThreadNetworkSettings — это обновляемый трейт, прикрепленный к Structure (представляющей дом или здание). Он позволяет разработчикам настраивать политику доступа в интернет для пограничных маршрутизаторов Thread в рамках всей структуры.

func updateStructureInternetAccess(structure: Structure, enableInternetAccess: Bool) async {
    guard let settingsTrait = structure.traits(Google.ThreadNetworkSettingsTrait.self) else {
        print("ThreadNetworkSettingsTrait not found on structure.")
        return
    }

    let option: Google.ThreadNetworkSettingsTrait.InternetAccessOption = enableInternetAccess ? .internetAccessOptionAll : .internetAccessOptionNone

    do {
        try await settingsTrait.update { mutator in
            mutator.internetAccessOption = option
        }
        print("Successfully updated Thread internet access policy.")
    } catch {
        print("Failed to update Thread internet access policy: \(error)")
    }
}