イベント

イベントは非同期で、Google Cloud Pub/Sub で管理されます。 Projectごとに 1 つのトピックがあります。イベントはすべてのデバイスと構造で生じた更新の状態を提供します。ユーザーがアクセス トークンを取り消さず、イベント メッセージの有効期限が切れていない限り、イベントの受信は保証されます。

イベントを有効にする

イベントは SDM API のオプション機能です。 イベントを有効にする で、 Projectのイベントを有効にする方法をご確認ください。

Google Cloud Pub/Sub

Pub/Sub の仕組みについては、Google Cloud Pub/Sub のドキュメントをご覧ください。具体的には、次のとおりです。

イベント サブスクリプション

2025 年 1 月より前は、 Projectでイベントが有効になっている場合、その Project ID に固有のトピックが次の形式で提供されていました。

projects/gcp-project-name/subscriptions/topic-id
2025 年 1 月以降に作成されたプロジェクトでは、Pub/Sub トピックをセルフホストする必要があります。独自のトピック ID を指定する必要があります。詳細については、トピックを作成するをご覧ください。

イベントを受信するには、ユースケースに応じて、そのトピックへの pull サブスクリプションまたは push サブスクリプションを作成します。SDM トピックへの複数のサブスクリプションがサポートされています。詳しくは、サブスクリプションの管理をご覧ください。

イベントを開始する

Pub/Sub サブスクリプションの作成後に初めてイベントを開始するには、1 回限りのトリガーとして devices.list API 呼び出しを行います。この呼び出しの後、すべての構造とデバイスのイベントが公開されます。

例については、クイック スタートガイドの承認ページをご覧ください。

イベントの順序

Pub/Sub はイベントの順序どおりの配信を保証しません。イベントの受信順序は、イベントが実際に発生した順序と一致しない場合があります。timestamp フィールドを使用して、イベントの順序の調整を支援します。イベントは個別に到着する場合も、単一のイベント メッセージに結合されて到着する場合もあります。

詳細については、メッセージの順序指定をご覧ください。

ユーザー ID

実装が(構造やデバイスではなく)ユーザーを中心に行われている場合は、イベント ペイロードの userID フィールドを使用して、リソースとイベントを関連付けます。このフィールドは、特定のユーザーを表す難読化された ID です。

userID は、各 API 呼び出しの HTTP レスポンス ヘッダーでも使用できます。

関係者イベント

関係イベントは、リソースの関係更新を表します。たとえば、デバイスが構造に追加されたときや、デバイスが構造から削除されたときなどです。

関係イベントには次の 3 種類があります。

  • CREATED
  • 削除済み
  • 更新済み

関連イベントのペイロードは次のとおりです。

ペイロード

{
  "eventId" : "81688b62-4f69-432f-bbe0-5270032f5466",
  "timestamp" : "2019-01-01T00:00:01Z",
  "relationUpdate" : {
    "type" : "CREATED",
    "subject" : "enterprises/project-id/structures/structure-id",
    "object" : "enterprises/project-id/devices/device-id"
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"
}

関連イベントでは、object はイベントをトリガーしたリソースで、subjectobject が関連付けられたリソースです。上記の例では、a user がこの特定のデバイスへのアクセスを developerに許可し、 userの承認済みデバイスが承認済み構造に関連付けられたため、イベントがトリガーされています。

subject はルームまたは構造体のみにできます。 a developer に userの構造を表示する権限がない場合、subject は常に空になります。

フィールド

フィールド 説明 データ型
eventId イベントの一意の識別子。 string
例: 「4ec221c5-4cbc-4fd5-ae2e-6eebd1311876」
timestamp イベントが発生した時間。 string
例: 「2019-01-01T00:00:01Z」
relationUpdate リレーションの更新に関する詳細情報を含むオブジェクト。 object
userId ユーザーを表す一意の難読化された識別子。 string
例: 「AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi」

さまざまなタイプのイベントとその仕組みについては、イベントをご覧ください。

イベント ペイロードは、関係イベントのタイプごとに異なります。

CREATED

ストラクチャを作成しました

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

デバイスが作成されました

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

デバイスが作成されました

"relationUpdate" : {
  "type" : "CREATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

更新済み

デバイスを移動しました

"relationUpdate" : {
  "type" : "UPDATED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

削除済み

構造が削除されました

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "",
  "object" : "enterprises/project-id/structures/structure-id"
}

デバイスを削除しました

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id",
  "object" : "enterprises/project-id/devices/device-id"
}

デバイスを削除しました

"relationUpdate" : {
  "type" : "DELETED",
  "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id",
  "object" : "enterprises/project-id/devices/device-id"
}

次の場合は、関連イベントは送信されません。

  • チャットルームが削除された

リソース イベント

リソース イベントは、リソースに固有の更新を表します。これは、サーモスタットのモードの変更など、トレイト フィールドの値の変更に対する応答である可能性があります。 また、デバイスボタンを押すなど、トレイト フィールドを変更しないデバイス アクションを表すこともできます。

トレイト フィールドの値の変更に応じて生成されるイベントには、デバイスの GET 呼び出しと同様に traits オブジェクトが含まれます。

ペイロード

{
  "eventId" : "b5a3cb32-3ca8-4b0b-9510-c6a9e70f00f4",
  "timestamp" : "2019-01-01T00:00:01Z",
  "resourceUpdate" : {
    "name" : "enterprises/project-id/devices/device-id",
    "traits" : {
      "sdm.devices.traits.ThermostatMode" : {
        "mode" : "COOL"
      }
    }
  },
  "userId": "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
  "resourceGroup" : [
    "enterprises/project-id/devices/device-id"
  ]
}

個々の特性のドキュメントを使用して、特性フィールド変更リソース イベントのペイロード形式を確認します。

特性フィールドを変更しないデバイス アクションに応じて生成されたイベントにも、resourceUpdate オブジェクトを含むペイロードがありますが、traits オブジェクトではなく events オブジェクトが含まれています。

ペイロード

{
  "eventId" : "803821e5-2626-41d5-8ea2-04b6fdb88f8c",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "HEQiFiTuneH7NJVZ-kHxnbZyU9...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

これらのタイプのリソース イベントは、特定のトレイトで定義されます。たとえば、モーション イベントは CameraMotion トレイトで定義されています。これらのタイプのリソース イベントのペイロード形式については、各トレイトのドキュメントをご覧ください。

フィールド

フィールド 説明 データ型
eventId イベントの一意の識別子。 string
例: 「803821e5-2626-41d5-8ea2-04b6fdb88f8c」
timestamp イベントが発生した時間。 string
例: 「2019-01-01T00:00:01Z」
resourceUpdate リソースの更新に関する詳細情報を含むオブジェクト。 object
userId ユーザーを表す一意の難読化された識別子。 string
例: 「AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi」
eventThreadId イベント スレッドの一意の識別子。 string
例: 「d67cd3f7-86a7-425e-8bb3-462f92ec9f59」
eventThreadState イベント スレッドの状態。 string
値: 「STARTED」、「UPDATED」、「ENDED」
resourceGroup このイベントと同様の更新が行われる可能性があるリソースを示すオブジェクト。イベント自体のリソース(resourceUpdate オブジェクトから)は、常にこのオブジェクトに存在します。 object

さまざまなタイプのイベントとその仕組みについては、イベントをご覧ください。

更新可能な通知

リソース イベントに基づく通知は、Android や iOS などのアプリで実装できます。送信される通知の数を減らすために、更新可能な通知と呼ばれる機能が実装されることがあります。この機能では、同じイベント スレッドの後続のイベントに基づいて、既存の通知が新しい情報で更新されます。

更新可能な通知をサポートするイベント機能は、ドキュメントで 更新可能  とタグ付けされています。これらのイベントのペイロードには、eventThreadId という追加のフィールドがあります。このフィールドを使用して、ユーザーに表示された既存の通知を更新するために、個々のイベントをリンクします。

イベント スレッドはイベント セッションと同じではありません。イベント スレッドは、同じスレッド内の前のイベントの更新されたステータスを識別します。イベント セッションは、互いに関連する個別のイベントを識別します。特定のイベント セッションに対して複数のイベント スレッドが存在する可能性があります。

通知の目的で、さまざまな種類のイベントがさまざまなスレッドにグループ化されます。

このスレッドのグループ化とタイミングのロジックは Google によって処理され、いつでも変更される可能性があります。A developer は、SDM API によって提供されるイベント スレッドとセッションに基づいて通知を更新する必要があります。

スレッドの状態

更新可能な通知をサポートするイベントには、その時点でのイベント スレッドの状態を示す eventThreadState フィールドもあります。このフィールドには次の値があります。

  • STARTED - イベント スレッドの最初のイベント。
  • 更新済み - 進行中のイベント スレッド内のイベント。1 つのスレッドにこの状態のイベントが 0 個以上存在することがあります。
  • ENDED - イベント スレッドの最後のイベント。スレッドのタイプによっては、最後の UPDATED イベントの重複である可能性があります。

このフィールドは、イベント スレッドの進行状況と終了時期を追跡するために使用できます。

イベント フィルタリング

デバイスで検出されたイベントが、SDM Pub/Sub トピックへのパブリッシュから除外されることがあります。この動作はイベント フィルタリングと呼ばれます。イベント フィルタリングの目的は、短時間に類似したイベント メッセージが大量に公開されるのを防ぐことです。

たとえば、最初のモーション イベントのメッセージが SDM トピックに公開されることがあります。その後、Motion の他のメッセージは、設定された期間が経過するまで公開から除外されます。この期間が経過すると、そのイベントタイプのイベント メッセージが再びパブリッシュされる可能性があります。

Google Home アプリ(GHA)では、フィルタされたアクティビティは userのアクティビティの履歴に引き続き表示されます。ただし、このようなイベントでは、アプリの通知は生成されません(通知タイプが有効になっている場合でも同様です)。

各イベントタイプには独自のイベント フィルタリング ロジックがあり、これは Google によって定義され、いつでも変更される可能性があります。このイベント フィルタリング ロジックは、イベント スレッドとセッション ロジックとは独立しています。

サービス アカウント

SDM API のサブスクリプションとイベント メッセージの管理には、サービス アカウントをおすすめします。サービス アカウントは、ユーザーではなくアプリケーションや仮想マシンで使用され、独自の固有のアカウント キーがあります。

Pub/Sub API のサービス アカウントの認可では、2LO(Two-legged OAuth)が使用されます。

2LO 認証フローでは:

  • developer は、サービスキーを使用してアクセス トークンをリクエストします。
  • developer は、API への呼び出しでアクセス トークンを使用します。

Google 2LO とその設定方法について詳しくは、サーバー間アプリケーションでの OAuth 2.0 の使用をご覧ください。

承認

サービス アカウントは、Pub/Sub API での使用が承認されている必要があります。

  1. Google Cloud で Cloud Pub/Sub API を有効にします
  2. サービス アカウントの作成の説明に従って、サービス アカウントとサービス アカウント キーを作成します。Pub/Sub サブスクライバーのロールのみを付与することをおすすめします。Pub/Sub API を使用するマシンにサービス アカウント キーをダウンロードしてください。
  3. 前の手順のページの手順に沿って認証情報(サービス アカウント キー)をアプリケーション コードに指定するか、API アクセスをすばやくテストする場合は、oauth2l を使用してアクセス トークンを手動で取得します。
  4. Pub/Sub project.subscriptions API でサービス アカウント認証情報またはアクセス トークンを使用して、メッセージを pull して確認応答します。

oauth2l

Google oauth2l は、Go で記述された OAuth のコマンドライン ツールです。Go を使用して Mac または Linux にインストールします。

  1. システムに Go がない場合は、まずダウンロードしてインストールします
  2. Go をインストールしたら、oauth2l をインストールし、その場所を PATH 環境変数に追加します。
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. oauth2l を使用して、適切な OAuth スコープを使用して API のアクセス トークンを取得します。
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    たとえば、サービスキーが ~/myServiceKey-eb0a5f900ee3.json にある場合:
    oauth2l fetch --credentials ~/myServiceKey-eb0a5f900ee3.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    ya29.c.Elo4BmHXK5...

使用方法の詳細については、oauth2l README をご覧ください。

Google API クライアント ライブラリ

OAuth 2.0 を利用する Google API には、いくつかのクライアント ライブラリが用意されています。選択した言語の詳細については、Google API クライアント ライブラリをご覧ください。

これらのライブラリを Pub/Sub APIで使用する場合は、次のスコープ文字列を使用します。

https://www.googleapis.com/auth/pubsub
https://www.googleapis.com/auth/cloud-platform

エラー

このガイドに関連して、次のエラーコードが返されることがあります。

エラー メッセージ RPC トラブルシューティング
カメラの画像はダウンロードできなくなりました。 DEADLINE_EXCEEDED イベント画像は、イベントの公開から 30 秒後に期限切れになります。有効期限が切れる前に必ず画像をダウンロードしてください。
イベント ID がカメラに属していません。 FAILED_PRECONDITION カメラ イベントから返された正しい eventID を使用します。

API エラーコードの一覧については、API エラーコードのリファレンスをご覧ください。