イベント

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

イベントを有効にする

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

Google Cloud Pub/Sub

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

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

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

projects/sdm-prod/topics/enterprise-project-id

すべてのプロジェクトで、独自の Google Cloud プロジェクトで Pub/Sub トピックをセルフホストする必要があります(2025 年 1 月以降の新しいプロジェクトでは必須、既存のすべてのプロジェクトでは 2026 年 11 月 30 日までに必要)。形式は次のとおりです。

projects/gcp-project-name/subscriptions/topic-id

project がすでに独自の Google Cloud プロジェクトでセルフホスト トピックを使用している場合は、対応は不要です。Pub/Sub トピック構成を移行しても、既存のユーザー アクセス トークンや OAuth 権限は無効になりません。セルフホスト型のトピックとサブスクリプションには、標準の Google Cloud Pub/Sub の料金が適用されます(1 か月あたり 10 GB の無料枠が含まれます)。詳細については、トピックを作成するをご覧ください。

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

イベントを開始する

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

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

イベントの順序

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

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

ユーザー ID

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

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

リレーション イベント

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

リレーション イベントには次の 3 種類があります。

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

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

ペイロード

{
  "eventId" : "768e4eea-b61d-428b-8926-c67e2abaddf9",
  "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 はイベントをトリガーしたリソースであり、subject は object が関係を持つリソースです。上記の例では、 user がこの特定のデバイスへのアクセスを developerに許可し、 userの承認済みデバイスが承認済みのストラクチャに関連付けられ、イベントがトリガーされます。

subject には、部屋またはストラクチャのみを指定できます。 a developer に userの構造を表示する権限がない場合、subject は常に空になります。

フィールド

フィールド 説明 データ型
eventId イベントの一意の識別子。 string
例: "d575caa5-75d3-4536-9ee3-287610a433a8"
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" : "ae3f760e-9e1f-4c14-b911-28482e86e56d",
  "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" : "aecdfca3-25ec-4738-bdbf-d24c4a209d93",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "jE1ZfUIAp6z2anjwTJp5E8QxvC...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

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

フィールド

フィールド 説明 データ型
eventId イベントの一意の識別子。 string
例: "aecdfca3-25ec-4738-bdbf-d24c4a209d93"
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 - イベント スレッドの最初のイベント。
  • UPDATED - 進行中のイベント スレッド内のイベント。1 つのスレッドにこの状態のイベントが 1 つ以上存在することもあります。
  • ENDED - イベント スレッドの最後のイベント。スレッドの種類によっては、最後の UPDATED イベントの重複となる場合があります。

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

イベント フィルタリング

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

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

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

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

サービス アカウント

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

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

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 エラーコードのリファレンスをご覧ください。