您可以透過 iOS 版 Home API 存取裝置 API。將下列套件匯入應用程式:
import GoogleHomeSDK
import GoogleHomeTypes
詳情請參閱「iOS 資料模型」一文。
處理錯誤
Home API 中的某些方法會擲回 HomeError
,因此建議您使用 do-catch
區塊,在這些呼叫中擷取 HomeError
。
處理 HomeError
時,請檢查 code
和 message
欄位,瞭解發生錯誤的原因。
任何未處理的錯誤都會導致應用程式當機。
詳情請參閱「錯誤處理」一節。
如需範例,請參閱「將指令傳送至裝置」。
呼叫範例
取得裝置清單
取得 Home
物件的參照後,請叫用 devices()
取得可存取裝置的 Query
。呼叫 Query
的 batched()
方法,每次裝置中繼資料變更時,都會發出反映 Home 目前狀態的 Set。或者呼叫 Query.list()
取得可用裝置的快照。這是便利方法,可訂閱 batched()
串流並傳回第一個發出的值。Query.stream()
會產生串流,在裝置中繼資料 (例如名稱、房間或結構) 變更時發出新值。在內部,這會使用 batched()
,且只會發出變更的屬性。
// Get a list of all devices accessible to the user let homeDevices = try await self.home.devices().list()
您可以在這裡存取各裝置的狀態,並將支援的指令傳送至裝置。
取得裝置類型
如要取得與裝置相關聯的裝置類型,請讀取裝置的 types
屬性,該屬性會傳回 DeviceTypeController
。
呼叫 DeviceTypeController.subscribe(_:)
即可訂閱特定裝置類型的更新:
let devices = try await self.home.devices().list() if let device = devices.first(where: { $0.id == myDeviceId }) { var receivedUpdate1 = false var receivedUpdate2 = false device.types.subscribe(OnOffLightDeviceType.self) .assertNoFailure() .sink { device in if !receivedUpdate1 { receivedUpdate1 = true Task { try await device.matterTraits.onOffTrait?.on() } return } if !receivedUpdate2 { receivedUpdate2 = true return } fatalError("Received unexpected update") } }
如果裝置不支援指定的裝置類型,系統會立即傳回 Empty
Publisher
。
如果裝置支援特定裝置類型,您可以呼叫 get()
取得該類型的控制代碼:
if let device = devices.first(where: { $0.id == myDeviceId }) { let deviceType = await device.types.get(OnOffLightDeviceType.self) }
如果裝置不支援指定的類型,則會傳回 nil
。
呼叫 DeviceTypeController.subscribeAll()
取得 Publisher
的 DeviceTypeCollection
。這個類別可讓您檢查裝置是否屬於特定裝置類型:
if let device = devices.first(where: { $0.id == myDeviceId }) { device.types.subscribeAll() .assertNoFailure() .sink { types in let lightDeviceType = types[OnOffLightDeviceType.self] let fanDeviceType = types[FanDeviceType.self] } }
取得裝置類型特徵
裝置類型是讀取特徵的進入點,因為這類類型會將裝置分解為功能片段 (例如 Matter 中的端點)。
如果裝置有兩種裝置類型,且這兩種裝置類型可能具有相同特徵,系統也會將特徵衝突納入考量。舉例來說,如果裝置同時是音箱和可調光燈具,就會有兩個開/關和兩個層級控制特徵。
如果裝置有兩個名稱相同的特徵,也可能發生特徵衝突。舉例來說,onOff
可以參照標準 OnOff
特徵的例項,也可以參照製造商定義的 OnOff
特徵例項。為避免可能出現的特徵不明確情況,請透過各裝置類型上的其中一個特徵集合參照特徵。
如果是標準特徵 (即與 Matter 標準叢集類似的特徵),請使用 matterTraits
。舉例來說,如要取得可調光燈具裝置類型的特定特徵:
if let dimmableLightDeviceType = await device.types.get(DimmableLightDeviceType.self) { // Accessing standard trait on the type. let levelControlTrait = dimmableLightDeviceType.matterTraits.levelControlTrait.self }
如要使用 Google 特徵,請使用 googleTraits
:
if let doorbellDeviceType = await device.types.get(GoogleDoorbellDeviceType.self) { // Accessing Google trait on the type. let doorbellPressTrait = doorbellDeviceType.googleTraits.doorbellPressTrait.self }
如要存取特定製造商的特徵,請透過 traits
屬性參照該特徵,但請先加上製造商的套件名稱:
let deviceType = await device1?.types.get(OnOffLightDeviceType.self) // Accessing custom trait on the type. if let spinnerTrait = deviceType?.traits[ExampleOrganization.SpinnerTrait.self] { let rpmVal = spinnerTrait.attributes.rpm }
讀取裝置狀態
請參閱以下範例,瞭解如何從裝置的 On/Off 特徵檢查 OnOff
屬性:
let lightDevices = devices.filter { $0.types.contains(OnOffLightDeviceType.self) } let light1 = lightDevices.first let lightDeviceTypeOptional = await light1?.types.get(OnOffLightDeviceType.self) if let onOffTrait = lightDeviceTypeOptional?.matterTraits.onOffTrait { let onOffVal = onOffTrait.attributes.onOff }
取得具有特定特徵的裝置清單
如要取得具有特定特徵的裝置清單,您需要疊代裝置、每個裝置的裝置類型,以及每個裝置類型的特徵。舉例來說,如要取得住家中所有具有「開/關」特徵的裝置清單,請執行下列操作:
// Get all light devices that support levelControl var levelControlDevices: [HomeDevice] = [] var allDevices = try await home.devices().list() for device in allDevices { if let deviceType = await device.types.get(OnOffLightDeviceType.self) { if deviceType.traits.contains(Matter.LevelControlTrait.self) { levelControlDevices.append(device) } } }
如需 Home API 提供的完整特徵清單,請參閱「iOS 上的特徵索引」。
取得裝置類型相似的裝置清單
如要取得代表住家所有燈具的裝置清單,請按照下列步驟操作:
// Get a list of devices with similar device types (lights) let lightDevices = try await self.home.devices().list().compactMap { $0.types.contains(DimmableLightDeviceType.self) || $0.types.contains(OnOffLightDeviceType.self) || $0.types.contains(ColorTemperatureLightDeviceType.self) || $0.types.contains(ExtendedColorLightDeviceType.self) }
Home API 中有多種裝置類型,可代表核心裝置類型。舉例來說,沒有「燈具」裝置類型。如上述範例所示,燈光有四種不同的裝置類型。因此,如要全面瞭解住家中的高階裝置類型,必須納入多種裝置類型。
如需 Home API 支援的裝置類型及其特徵完整清單,請參閱「iOS 支援的裝置類型」。
取得裝置的供應商名稱、供應商 ID 或產品 ID
BasicInformationTrait
特徵包含裝置的供應商 ID、產品 ID、產品名稱和序號等資訊:
guard let vendorName = basicInfoTrait.attributes.vendorName else { fatalError("Failed to get vendorName") } guard let vendorID = basicInfoTrait.attributes.vendorID else { fatalError("Failed to get vendorID") } guard let productID = basicInfoTrait.attributes.productID else { fatalError("Failed to get productID") }
裝置製造商的雲端對雲端裝置識別
如果您是裝置製造商,且建構 Cloud-to-cloud 裝置,如要透過 BasicInformation
特徵識別 Cloud-to-cloud 裝置,可以在 SYNC
回應中加入下列字串欄位:
Connectivity Standards Alliance (CSA) 已核發供應商 ID:
"matterOriginalVendorId": "0xfff1",
可專屬識別供應商產品的產品 ID:
"matterOriginalProductId": "0x1234",
裝置的專屬 ID,以製造商專屬方式建構:
"matterUniqueId": "matter-device-id",
輸入這些字串欄位時,請使用供應商和產品 ID (如有)。Matter如果不是 CSA 成員,且未獲派這些 ID,請將 matterOriginalVendorId
和 matterOriginalProductId
欄位留空,並提供 matterUniqueId
做為 ID。
範例 SYNC 回應會顯示這些欄位的使用情形:
{
"requestId": "ff36a3cc-ec34-11e6-b1a0-64510650abcf",
"payload": {
"agentUserId": "1836.15267389",
"devices": [
{
"id": "456",
"type": "action.devices.types.LIGHT",
"traits": [
"action.devices.traits.OnOff",
"action.devices.traits.Brightness",
"action.devices.traits.ColorSetting",
],
"willReportState": true,
"deviceInfo": { ... },
"matterOriginalVendorId": "0xfff1",
"matterOriginalProductId": "0x1234",
"matterUniqueId": "matter-device-id",
"otherDeviceIds": [
{
"deviceId": "local-device-id",
}
]
}
]
}
}
詳情請參閱Cloud-to-cloud SYNC
說明文件。
裝置和特徵中繼資料
Google Home API 中的裝置和特徵會與中繼資料建立關聯,有助於管理應用程式中的使用者體驗。
Home API 中的每個特徵都包含 sourceConnectivity
屬性,其中含有特徵的線上狀態和位置資訊 (本機或遠端路徑)。
取得裝置的主要類型
部分裝置可能會透過 Home API 呈現多種裝置類型。 為確保使用者在應用程式中看到裝置的適當選項 (例如裝置控制和建議的自動化動作),請檢查裝置類型是否為裝置的主要類型。
if let deviceType = await device?.types.get(HumiditySensorDeviceType.self) { if deviceType.metadata.isPrimaryType { print("Humidity Sensor is the primary type on this device.") } else { print("Humidity Sensor isn't the primary type on this device.") } }
檢查特徵是否處於線上狀態
請讀取 connectivityState
屬性,檢查特徵的連線狀態:
let levelControlConnectivity = levelControlTrait.metadata.sourceConnectivity .connectivityState
如果裝置未連上網際網路,部分特徵 (通常是 Google smart home 特徵) 可能會顯示為離線。這是因為這些特徵是以雲端為基礎,沒有本機路徑。
檢查裝置的連線狀態
裝置的連線狀態實際上是在裝置類型層級檢查,因為部分裝置支援多種裝置類型。傳回的狀態是該裝置上所有特徵的連線狀態組合。
let lightConnectivity = dimmableLightDeviceType.metadata.sourceConnectivity .connectivityState
如果沒有網際網路連線,混合裝置類型可能會顯示 partiallyOnline
狀態。Matter標準特徵可能仍會因本地路徑而處於線上狀態,但雲端特徵會離線。
檢查特徵的網路路徑
特徵的地域性也可在 Home API 中使用。dataSourceLocality
表示特徵是透過雲端遠端傳送、透過本機中樞傳送,還是透過對等互連 (直接從裝置傳送至裝置,不透過中樞)。
舉例來說,應用程式啟動時可能尚未連上中樞或伺服器,因此會出現不明的地區值 unspecified
。這些裝置無法連線,因此指令或事件的互動要求會失敗。如何處理這類裝置,則由用戶端決定。
let levelControlLocality = levelControlTrait.metadata.sourceConnectivity .dataSourceLocality
檢查裝置的網路路徑
與連線能力一樣,區域性是在裝置類型層級檢查。傳回的狀態是該裝置上所有特徵的地區性組合。
let lightLocality = dimmableLightDeviceType.metadata.sourceConnectivity.dataSourceLocality
在類似 partiallyOnline
連線的案例中,可能會出現 mixed
狀態:部分特徵以雲端為基礎,其他特徵則為本機。
變更裝置名稱
呼叫 setName(_:)
方法來變更裝置名稱:
let updatedDevice = try await theDevice.setName("new device name")
變更裝置名稱時,原始 HomeDevice
結構體會保持不變,變更會反映在傳回的更新 HomeDevice
物件中。
如果名稱超過 60 個 Unicode 碼點 (字元) 的限制,系統會截斷名稱,且不會擲回錯誤。開發人員有責任處理長名稱,例如決定是否要通知使用者名稱會遭到截斷。
API 清單
建立 Home
執行個體後,即可透過該執行個體存取下列裝置 API:
API | 說明 |
---|---|
device(id:) |
針對指定裝置傳回 Publisher ,每當裝置狀態變更時,就會發出該狀態。 |
devices() |
取得 Google 帳戶中所有結構的所有裝置。傳回 Query<HomeDevice> ,提供進一步的擷取和篩選選項。 |
取得 HomeDevice
後,您就可以透過該權杖存取下列 API:
API | 說明 |
---|---|
id |
裝置的專屬系統 ID。 |
name |
使用者提供的裝置名稱。 |
structureID |
裝置所屬的結構體 ID。傳回 String? 。 |
roomID |
裝置所屬房間的 ID。傳回 String? 。 |
types |
取得裝置上的特定類型或所有可用類型。 |
isMatterDevice |
如果裝置有 Matter 支援。 |
sourceConnectivity |
裝置的來源連線,代表裝置特徵的匯總連線狀態和網路位置。 |