iOS 應用程式開發人員可以使用 Home API 管理 Thread 邊界路由器。
GoogleBorderRouterDevice 是透過兩個主要裝置特徵實作:ThreadNetworkCapabilitiesTrait,提供唯讀屬性來檢查邊界路由器功能;以及 ThreadNetworkManagementTrait,使用 Commissioner 的暫時預先共用金鑰 (ePSKc) 處理網路生命週期指令和憑證共用。結構層級的網際網路存取政策是透過 ThreadNetworkSettingsTrait 特徵管理。
使用任何功能或嘗試更新屬性之前,請務必先檢查裝置是否支援屬性和指令。詳情請參閱「透過iOS 控制裝置」。
| Home API 裝置類型 | 特徵 | Swift 範例應用程式 | 用途 |
|---|---|---|---|
|
邊界路由器
|
必要特徵 google ThreadNetworkCapabilitiesTrait google ThreadNetworkManagementTrait |
邊界路由器 |
取得裝置的基本資訊
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 特徵檢查邊界路由器的唯讀功能,例如 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 工作階段結束時 (例如因為金鑰已使用、工作階段過期或手動取消),執行緒邊界路由器會發出事件。
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,指令 Thread 邊界路由器加入新的 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 (代表住家或建築物) 的可更新特徵。開發人員可藉此設定 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)")
}
}