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

Device API には、Android 向け 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

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

エラー処理

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 つの On/Off トレイトと 2 つの Level Control トレイトがあります。

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

// 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() デバイスで使用可能なすべてのタイプのリストを取得します。