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

Разработчики приложений для iOS могут использовать Home API для управления Thread Border Router (TBR).

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

Перед использованием функций или попыткой обновить атрибуты всегда проверяйте, поддерживаются ли они устройством. Подробнее о том, как управлять устройствами на сайтеiOS…

Тип устройства для Home API Функции Пример приложения на языке Swift История успеха

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

GoogleBorderRouterDeviceType

home.matter.6006.types.0161

Обязательные признаки
     google ThreadNetworkCapabilitiesTrait
     google ThreadNetworkManagementTrait

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

Как получить основную информацию об устройстве

   Реализовано в примере приложения для iOS   

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!

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

Вы можете проверить возможности border router только для чтения (например, поддержку 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)")
    }
}

Как управлять обменом учетными данными Thread (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

TBRУстройства отправляют события, когда сеанс 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

Вы можете дать команду TBR присоединиться к новой сети 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 (представляющему дом или здание). Оно позволяет разработчикам настраивать правила доступа к интернету для всех TBR.

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