イベントは非同期で、Google Cloud Pub/Sub によって Projectごとに 1 つのトピックで管理されます。イベントは、すべてのデバイスとストラクチャの最新情報を提供します。ユーザーがアクセス トークンを取り消しておらず、イベント メッセージの有効期限が切れていない限り、イベントの受信は保証されます。
イベントを有効にする
イベントは SDM API のオプション機能です。 イベントを有効にする で、 Projectでイベントを有効にする方法をご確認ください。
Google Cloud Pub/Sub
Pub/Sub の仕組みの詳細については、Google Cloud Pub/Sub のドキュメントをご覧ください。具体的には、次のとおりです。
- 入門ガイドで Pub/Sub の基礎を学ぶ。
- 認証の仕組みを理解します。
- 提供されているクライアント ライブラリを選択するか、独自のライブラリを作成してREST/HTTP または gRPC API サーフェスを使用します。
イベント サブスクリプション
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" : "7c786f36-8068-4b86-ba67-d6e0d28ebb11",
"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 が関係を持つリソースです。上記の例では、a user がこの特定のデバイスへのアクセス権を developerに付与し、 userの承認済みデバイスが承認済み構造に関連付けられ、イベントがトリガーされています。
subject は部屋または構造物のみにできます。 a developer に userの構造を表示する権限がない場合、subject は常に空になります。
フィールド
| フィールド | 説明 | データ型 |
|---|---|---|
eventId |
イベントの一意の識別子。 | string例: "9252cbe7-f438-4e15-a65f-619fb497f78a" |
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" : "59381967-62e1-427b-98b8-67d5dbbd590c",
"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" : "1608503f-fedf-43cc-b29c-aa4e3b685a60",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : {
"name" : "enterprises/project-id/devices/device-id",
"events" : {
"sdm.devices.events.CameraMotion.Motion" : {
"eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...",
"eventId" : "Ki0F7T-Joca_uRg42loDugGevl...",
}
}
}
"userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [
"enterprises/project-id/devices/device-id"
]
}これらのタイプのリソース イベントは、特定のトレイトで定義されます。たとえば、モーション イベントは CameraMotion トレイトで定義されています。これらのタイプのリソース イベントのペイロード形式については、各トレイトのドキュメントをご覧ください。
フィールド
| フィールド | 説明 | データ型 |
|---|---|---|
eventId |
イベントの一意の識別子。 | string例: 「1608503f-fedf-43cc-b29c-aa4e3b685a60」 |
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 が処理しており、いつでも変更される可能性があります。 developer は、SDM API から提供されるイベント スレッドとセッションに基づいて通知を更新する必要があります。
スレッドの状態
更新可能な通知をサポートするイベントには、その時点でのイベント スレッドの状態を示す eventThreadState フィールドもあります。このフィールドには次の値が含まれます。
- STARTED - イベント スレッドの最初のイベント。
- UPDATED - 進行中のイベント スレッド内のイベント。1 つのスレッドに、この状態のイベントが 0 個以上存在する可能性があります。
- 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 で使用できるように承認されている必要があります。
- Google Cloud で Cloud Pub/Sub API を有効にします。
- サービス アカウントの作成の説明に従って、サービス アカウントとサービス アカウント キーを作成します。Pub/Sub サブスクライバーのロールのみを付与することをおすすめします。Pub/Sub API を使用するマシンにサービス アカウント キーをダウンロードしてください。
- 前の手順のページの手順に沿って認証情報(サービス アカウント キー)をアプリケーション コードに指定するか、API アクセスをすばやくテストする場合は、
oauth2lを使用してアクセス トークンを手動で取得します。 - Pub/Sub
project.subscriptionsAPI でサービス アカウントの認証情報またはアクセス トークンを使用して、メッセージを pull して確認応答します。
oauth2l
Google oauth2l は、Go で記述された OAuth 用のコマンドライン ツールです。Go を使用して Mac または Linux にインストールします。
- システムに Go がない場合は、まず ダウンロードしてインストールします。
- Go をインストールしたら、
oauth2lをインストールして、その場所をPATH環境変数に追加します。go install github.com/google/oauth2l@latestexport PATH=$PATH:~/go/bin 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-platformya29.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 エラーコードのリファレンスをご覧ください。