适用于 iOS 的边界路由器设备指南

iOS 应用开发者可以使用 Home API 管理 Thread Border Router (TBR)

GoogleBorderRouterDevice 是使用两个主要设备 trait 实现的: ThreadNetworkCapabilitiesTrait, 它提供只读属性来检查 border router 功能; 以及 ThreadNetworkManagementTrait, 它使用专员的临时预共享密钥 (ePSKc) 处理网络生命周期命令和凭据共享。结构级 互联网访问政策使用 ThreadNetworkSettingsTrait trait 进行管理。

在使用任何功能或尝试更新属性之前,请务必检查设备是否支持属性和命令。如需了解详情,请参阅在 Control devices on iOS 上控制设备。

Home API 设备类型 trait Swift 示例应用 使用场景

边界路由器

GoogleBorderRouterDeviceType

home.matter.6006.types.0161

必需的 trait
     google ThreadNetworkCapabilitiesTrait
     google ThreadNetworkManagementTrait

边界路由器

获取有关设备的基本信息

   在 iOS 示例应用中实现   

BasicInformation trait 包含设备的相关信息,例如供应商名称、供应商 ID、产品 ID、 产品名称(包括型号信息)和软件版本:

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!

检查边界路由器功能

您可以使用 ThreadNetworkCapabilitiesTrait trait 检查 border router's 的只读功能(例如 ePSKc 支持和互联网访问设置配置)。

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 停用事件

当 ePSKc 会话结束时(例如, 因为密钥已被使用、会话已过期或会话已被手动取消),TBR 会发出事件。

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 网络(通过 提供有效的 Operational Dataset 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 trait 是附加到 Structure(代表住宅或建筑物)的可更新 trait。借助此 trait,开发者可以为 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)")
    }
}