デバイス API には、iOS 向け Home 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()
を呼び出して、DeviceTypeCollection
の Publisher
を取得します。このクラスを使用すると、デバイスに特定のデバイスタイプがあるかどうかを確認できます。
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 のエンドポイントなど)に分解するため、特性を読み取るためのエントリ ポイントとなります。
また、デバイスに 2 つのデバイスタイプがあり、両方に同じトレイトが含まれている場合、トレイトの競合も考慮されます。たとえば、デバイスがスピーカーと調光可能な照明の両方である場合、オン/オフとレベル制御のトレイトが 2 つずつあります。
別の種類のトレイトの競合は、デバイスに同じ名前の 2 つのトレイトがある場合に発生する可能性があります。たとえば、onOff
は標準の OnOff
トレイトのインスタンスを参照することも、メーカー定義の OnOff
トレイトのインスタンスを参照することもできます。どのトレイトが意図されているかについての曖昧さを解消するため、各デバイスタイプの 2 つのトレイト コレクションのいずれかを通じてトレイトを参照します。
標準特性(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 }
デバイスの状態を読み取る
デバイスのオン/オフ トレイトから 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 には、コア デバイスタイプを表す可能性のあるデバイスタイプが複数あります。たとえば、「Light」というデバイスタイプはありません。代わりに、前述の例に示すように、照明を表す 4 つの異なるデバイスタイプがあります。そのため、家にある上位レベルのデバイスのタイプを包括的に把握するには、複数のデバイスタイプを含める必要があります。
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",
デバイスの一意の識別子。メーカー固有の方法で構築されます。
"matterUniqueId": "matter-device-id",
これらの文字列フィールドを入力する際は、Matter ベンダー ID とプロダクト ID がある場合はそれらを使用します。CSA メンバーではなく、これらの ID が割り当てられていない場合は、matterOriginalVendorId
フィールドと matterOriginalProductId
フィールドを空白のままにして、matterUniqueId
を識別子として指定できます。
次の 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
ドキュメントをご覧ください。
デバイスとトレイトのメタデータ
Home API のデバイスとトレイトにはメタデータが関連付けられています。このメタデータは、アプリでのユーザー エクスペリエンスの管理に役立ちます。
Home API の各トレイトには、トレイトのオンライン ステータスとローカリティ(ローカル ルーティングまたはリモート ルーティング)に関する情報を含む sourceConnectivity
プロパティが含まれています。
デバイスのプライマリ タイプを取得する
一部のデバイスは、Google 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 |
デバイスのソース接続。デバイスの特性の接続状態とネットワークのローカリティを集約した状態を表します。 |