デバイスとデバイスのメタデータにアクセスする

Device API には、Home API からアクセスできます。次のパッケージをアプリにインポートします。

import com.google.home.Home
import com.google.home.HomeDevice
import com.google.home.Id

Device API で特定のデバイスタイプまたは特性を使用するには、個別にインポートする必要があります。

たとえば、Matter オン/オフの特性とオン/オフのプラグイン ユニットのデバイスタイプを使用するには、次のパッケージをアプリケーションにインポートします。

import com.google.home.matter.standard.OnOff
import com.google.home.matter.standard.OnOffPluginUnitDevice

詳細については、データモデルをご覧ください。

エラー処理

Home API のどのメソッドでも HomeException をスローする可能性があるため、すべての呼び出しで try-catch ブロックを使用して HomeException をキャッチすることをおすすめします。

HomeException を処理する際は、code フィールドと message フィールドをチェックして、エラーの原因を確認します。

例外を処理しないと、アプリがクラッシュします。

詳細については、エラー処理をご覧ください。

例については、デバイスにコマンドを送信するをご覧ください。

呼び出しの例

デバイスのリストを取得する

構造が利用可能になると、devices() 呼び出しは、その構造からアクセスできるデバイスのフローを返します。

// Get a flow of all devices accessible to the user
val allDevicesFlow: HomeObjectsFlow<HomeDevice> = home.devices()

// Calling list() on a HomeObjectsFlow returns the first Set of elements.
val allDevices: Set<HomeDevice> = allDevicesFlow.list()

そこから、各デバイスの状態にアクセスし、サポートされているコマンドをデバイスに送信できます。

デバイスの状態を読み取る

デバイスのオン/オフの特性から OnOff 属性を確認する例を見てみましょう。Home APIs の特徴データモデル(この特徴は OnOff として識別されます)を使用すると、デバイスタイプの standardTraits クラスから特徴データを取得できます。

// Assuming we have a device.
val deviceFlow = home.devices().itemFlow(myDeviceId)

val device = deviceFlow.first()

// Get a flow of a standard trait on the type. distinctUntilChanged() is needed to only trigger
// on the specific trait changes and not the whole type.
val onOffTraitFlow: Flow<OnOff?> =
  device.type(DimmableLightDevice).map { it.standardTraits.onOff }.distinctUntilChanged()

val onOffTrait: OnOff = onOffTraitFlow.first()!!

Kotlin フロー関数の詳細については、distinctUntilChanged をご覧ください。

トレイト サブスクリプションで状態を無効にする

TraitStateInvalidation インターフェースには、状態が正しく報告されていない場合に、ターゲット デバイスへの定期購入を通じて取得された状態を無効にする機能が用意されています。状態が正しく報告されない例としては、品質が「C」の Matter トレイトの属性を使用している場合や、デバイスの実装が原因で問題が予期せず発生している場合などがあります。

この API は、現在のトレイト状態の強制読み取りを行い、既存のトレイトフローを通じて結果を返します。

トレイトを取得し、トレイトで forceRead を実行します。

val generalDiagnosticsTrait = device.trait(GeneralDiagnostics).first()
generalDiagnosticsTrait.forceRead()

デバイスタイプのトレイトのリストを取得する

デバイスタイプは、デバイスを機能的な部分(Matter のエンドポイントなど)に分解するため、特徴の読み取りのエントリ ポイントとして使用する必要があります。

また、デバイスに 2 つのデバイスタイプがあり、どちらも同じトレイトを持つ可能性がある場合のトレイト コリジョンも考慮されます。たとえば、デバイスがスピーカーと調光ライトの両方である場合、2 つのオン/オフ トレイトと 2 つのレベル制御トレイトがあります。

調光可能なライトのデバイスタイプで使用可能なトレイトのリストを取得するには:

// Get all types available on this device. Requires the types to be part of the registry during
// SDK initialization.
val typesFlow: Flow<Set<DeviceType>> = device.types()

// Get a snapshot of all types.
val types: Set<DeviceType> = typesFlow.first()

// Get the DimmableLightDevice instance from the set of types.
val dimmableLightDevice = types.filterIsInstance<DimmableLightDevice>().firstOrNull()

// Get all traits in the type + traits registered
val allTraits: Set<Trait> = dimmableLightDevice!!.traits()

別の種類のトレイト競合は、デバイスに同じ名前の 2 つのトレイトがある場合に発生する可能性があります。たとえば、onOff は標準の OnOff トレイトのインスタンスを参照することも、メーカー定義の OnOff トレイトのインスタンスを参照することもできます。どのトレイトが意図されているかについて曖昧さが生じないようにするには、デバイスを介して参照される Trait インスタンスの前に修飾子の名前空間を付ける必要があります。標準の特性(Matter 標準クラスタに類似する特性)の場合は、standardTraits を使用します。Google の特徴の場合は、googleTraits を使用します。

// Accessing standard traits on the type.
val onOffTrait: OnOff? = dimmableLightDevice.standardTraits.onOff
val levelControlTrait: LevelControl? = dimmableLightDevice.standardTraits.levelControl

メーカー固有の特徴にアクセスするには、その特徴を直接参照します。

// Accessing a custom trait on the type.
val customTrait = dimmableLightDevice.trait(MyCustomTrait)

特定の特徴を持つデバイスのリストを取得する

Kotlin の filter 関数を使用すると、API 呼び出しをさらに絞り込むことができます。たとえば、オン/オフの特徴を持つ家のデバイスのリストを取得するには、次のようにします。

// Get all devices that support OnOff
val onOffDevices: Flow<List<HomeDevice>> =
  home.devices().map { devices -> devices.filter { it.has(OnOff) } }

Home API で使用可能なトレイトの一覧については、Trait インターフェースをご覧ください。

類似したデバイスタイプのデバイスのリストを取得する

家にあるすべての照明を表すデバイスのリストを取得するには:

// Get a list of devices with similar device types (lights)
val lightDevices =
  home.devices().map { devices ->
    devices.filter {
      it.has(DimmableLightDevice) ||
        it.has(OnOffLightDevice) ||
        it.has(ColorTemperatureLightDevice) ||
        it.has(ExtendedColorLightDevice)
    }
  }

Home API には、コア デバイスタイプを表す複数のデバイスタイプがあります。たとえば、「照明」デバイスの種類はありません。代わりに、上の例に示すように、ライトを表す 4 つの異なるデバイスタイプがあります。そのため、家にあるデバイスのより上位の種類を包括的に把握するには、フィルタされたフロー内に複数のデバイスタイプを含める必要があります。

Home API で使用できるデバイスタイプの完全なリストについては、DeviceType インターフェースをご覧ください。

デバイスのベンダー ID または製品 ID を取得する

BasicInformation トレイトには、ベンダー ID、プロダクト ID、プロダクト名、デバイスのシリアル番号などの情報が含まれます。

// Get device basic information. All general information traits are on the RootNodeDevice type.
val basicInformation = device.type(RootNodeDevice).first().standardTraits.basicInformation!!
println("vendorName ${basicInformation.vendorName}")
println("vendorId ${basicInformation.vendorId}")
println("productId ${basicInformation.productId}")

Cloud-to-Cloud デバイスを特定する

デバイス メーカーが 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 プロパティが含まれます。このプロパティには、トレイトのオンライン ステータスとローカリティ(ローカル ルーティングまたはリモート ルーティング)に関する情報が含まれます。

デバイスのプライマリ タイプを取得する

一部のデバイスは、Home API を介して複数のデバイスタイプを提示する場合があります。デバイスに適したオプション(デバイスの操作や自動化の候補など)をアプリでユーザーに表示するには、デバイスのメインのデバイスタイプを確認すると便利です。

まず、type() を使用してデバイスのタイプを取得し、プライマリ タイプを特定します。

val types = device.types().first()
val primaryType = types.first { it.metadata.isPrimaryType }

特徴がオンラインかどうかを確認する

connectivityState() メソッドを使用して、トレイトの接続を確認します。

val onOffConnectivity = onOffTrait?.metadata?.sourceConnectivity?.connectivityState

デバイスがインターネットに接続されていない場合、一部の特徴(通常は Google smart home 特徴)がオフラインと表示されることがあります。これは、これらの特性がクラウドベースであり、ローカル ルーティングがないためです。

デバイスの接続を確認する

デバイスの接続は、デバイスタイプレベルで実際に確認されます。これは、デバイスによっては複数のデバイスタイプをサポートしているためです。返される状態は、そのデバイス上のすべてのトレイトの接続状態の組み合わせです。

val lightConnectivity = dimmableLightDevice.metadata.sourceConnectivity.connectivityState

インターネットに接続されていない場合に、デバイスの種類が混在している場合に、PARTIALLY_ONLINE の状態が観測されることがあります。Matter 標準の特徴はローカル ルーティングにより引き続きオンラインになる可能性がありますが、クラウドベースの特徴はオフラインになります。

トレイトのネットワーク ルーティングを確認する

特徴のローカリティーは、Home API でも利用できます。dataSourceLocality は、トレイトがリモート(クラウド経由)、ローカル(ローカル ハブ経由)、ピアツーピア(デバイスからデバイスへの直接接続、ハブなし)のいずれでルーティングされるかを示します。

不明なローカリティー値 UNSPECIFIED は、アプリの起動中にデバイス接続用のハブまたはサーバーにまだ到達していない場合などに使用できます。これらのデバイスには到達できず、コマンドやイベントからのインタラクション リクエストは失敗します。このようなデバイスの処理方法はクライアントが決定します。

val onOffLocality = onOffTrait?.metadata?.sourceConnectivity?.dataSourceLocality

デバイスのネットワーク ルーティングを確認する

接続と同様に、ローカリティーはデバイスタイプ レベルでチェックされます。返される状態は、そのデバイス上のすべてのトレイトのローカリティーの組み合わせです。

val lightLocality = dimmableLightDevice.metadata.sourceConnectivity.dataSourceLocality

MIXED の状態は、PARTIALLY_ONLINE 接続の場合と同様の状況で確認できます。一部の特徴はクラウドベースで、他の特徴はローカルです。

API リスト

Home のインスタンスを作成すると、次の Device API にアクセスできるようになります。

API 説明
devices() Google アカウントのすべての構造内のすべてのデバイスを取得します。詳細な取得とフィルタリング オプションを提供する HomeObjectsFlow を返します。

HomeDevice を取得すると、次の API にアクセスできます。

API 説明
allCandidates() デバイスとその子デバイスのすべての自動化候補を返します。
candidates() デバイスのすべての自動化候補を返します。
connectivityStateChanged デバイスの状態が最後に変更された日時。
events(event) 特定のイベントのフローを取得します。
events(trait) この Trait のすべてのイベントのフローを取得します。
events(traits) これらの特性によるすべてのイベントのフローを取得します。
getSourceConnectivity(trait) 特定の特徴のメタデータを取得します。SourceConnectivity を返します。
has(trait) 現在のリクエストされた特徴がデバイスでサポートされているかどうかを確認します。
has(type) デバイスが指定されたタイプをサポートしているかどうか。
id デバイスの一意のシステム ID。
isInRoom デバイスが部屋にあるかどうか。
isInStructure デバイスが構造物内にある場合。
isMatterDevice デバイスが Matter を基盤としている場合。
name ユーザーが指定したデバイスの名前。
room() デバイスが割り当てられている部屋。Room を返します。
roomId デバイスが割り当てられている部屋の ID。Id を返します。
sourceConnectivity デバイスのソース接続。デバイスの特徴の集約された接続状態とネットワーク ローカリティーを表します。
structure() デバイスが割り当てられている構造体。Structure を返します。
structureId デバイスが割り当てられている構造物の ID。Id を返します。
type(type) 直接アクセスできるように、特徴が入力された(利用可能な場合)型定義を取得します。常に最新の特徴のスナップショットを返します。
types() デバイスで使用可能なすべてのタイプのリストを取得します。