iOS 裝置的邊界路由器裝置指南

iOS 應用程式開發人員可以使用 Home API 管理 Thread Border Router (TBR)

GoogleBorderRouterDevice 是透過兩個主要裝置特徵實作:ThreadNetworkCapabilitiesTrait,提供唯讀屬性來檢查 border router 功能;以及 ThreadNetworkManagementTrait,使用 Commissioner 的暫時性預先共用金鑰 (ePSKc) 處理網路生命週期指令和憑證共用。結構層級的網際網路存取政策是透過 ThreadNetworkSettingsTrait 特徵管理。

使用任何功能或嘗試更新屬性之前,請務必先檢查裝置是否支援屬性和指令。詳 情請參閱「透過 iOS 控制裝置」。

Home API 裝置類型 特徵 Swift 範例應用程式 用途

邊界路由器

GoogleBorderRouterDeviceType

home.matter.6006.types.0161

必要特徵
     google ThreadNetworkCapabilitiesTrait
     google ThreadNetworkManagementTrait

邊界路由器

取得裝置的基本資訊

   在 iOS 範例應用程式中導入   

BasicInformation 特徵包含裝置的供應商名稱、供應商 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 特徵檢查 border router 的唯讀功能 (例如 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 憑證共用功能是透過 Commissioner 的暫時預先共用金鑰 (ePSKc) 達成。ePSKc 模式會產生臨時安全密碼金鑰,外部裝置或 Commissioner 可使用該金鑰安全取得 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 網路成員資格

你可以 提供有效的作業資料集 TLV,指令 TBR 加入新的 Thread 網路,或指令 離開 目前的網路。

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