Events

Events are asynchronous and managed by Google Cloud Pub/Sub, in a single topic per Project. Events provide updates for all devices and structures and receipt of events is assured as long as the access token is not revoked by the user and the event messages have not expired.

Enable events

Events are an optional feature of the SDM API. See Enable events to learn how to enable them for your Project.

Google Cloud Pub/Sub

See the Google Cloud Pub/Sub documentation to learn more about how Pub/Sub works. In particular:

Event subscription

When events are enabled for your Project, you will be provided a topic specific to that Project ID, in the form of:

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

To receive events, create a pull or push subscription to that topic, depending on your use case. Multiple subscriptions to the SDM topic are supported. See Managing subscriptions for more information.

Initiate events

To initiate events for the first time once the Pub/Sub subscription has been created, make a devices.list API call as a one-time trigger. Events for all structures and devices will publish after this call.

For an example, see the Authorize page in the Quick Start Guide.

Event order

Pub/Sub does not guarantee ordered delivery of events, and the receipt order of events may not correspond to the order in which the events actually occurred. Use the timestamp field to aid in reconciliation of event order. Events may also arrive individually or combined into a single event message.

For more information, see Ordering messages.

User IDs

If your implementation is based around users (rather than structure or device), use the userID field from the event payload to correlate resources and events. This field is an obfuscated ID representing a specific user.

The userID is also available in the HTTP response header of each API call.

Relation events

Relation events represent a relational update for a resource. For example, when a device is added to a structure, or when a device is deleted from a structure.

There are three types of relation events:

  • CREATED
  • DELETED
  • UPDATED

The payload for a relation event is as follows:

Payload

{
  "eventId" : "cc5b6dc0-e8dc-4061-ae3d-db0807db9a4b",
  "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"
}

In a relation event, the object is the resource that triggered the event and the subject is the resource that the object now has a relation with. In the example above, a user has granted access to this specific device to a developer, and the user's authorized device is now related to their authorized structure, which triggers the event.

A subject can only be a room or a structure. If a developer does not have permission to view the user's structure, the subject is always empty.

Fields

Field Description Data Type
eventId The unique identifier for the event. string
Example: "e4198ac2-1302-497a-a701-8a056d95a998"
timestamp The time when the event occurred. string
Example: "2019-01-01T00:00:01Z"
relationUpdate An object that details information about the relation update. object
userId A unique, obfuscated identifier that represents the user. string
Example: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"

See Events for more information on the different types of events and how they work.

Examples

Event payloads differ for each type of relation event:

CREATED

Structure created

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

Device created

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

Device created

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

UPDATED

Device moved

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

DELETED

Structure deleted

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

Device deleted

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

Device deleted

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

Relation events are not sent when:

  • A room is deleted

Resource events

A resource event represents an update specific to a resource. It can be in response to a change in the value of a trait field, such as changing the mode of a thermostat. It can also represent a device action that doesn't change a trait field such as pressing a device button.

An event generated in response to a change in the value of trait field contains a traits object, similar to a device GET call:

Payload

{
  "eventId" : "9a66045e-6824-458c-b453-93856983bde3",
  "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"
  ]
}

Use the individual trait documentation to understand the payload format for any trait field change resource event.

An event generated in response to a device action that doesn't change a trait field also has a payload with a resourceUpdate object, but with an events object instead of a traits object:

Payload

{
  "eventId" : "81cf737a-0138-43d1-a2a2-06446c289aae",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "Z0ofy1OleXbiH940MyhlCv9S2f...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

These types of resource events are defined in specific traits. For example, the Motion event is defined in the CameraMotion trait. See each trait's documentation to understand the payload format for these types of resource events.

Fields

Field Description Data Type
eventId The unique identifier for the event. string
Example: "81cf737a-0138-43d1-a2a2-06446c289aae"
timestamp The time when the event occurred. string
Example: "2019-01-01T00:00:01Z"
resourceUpdate An object that details information about the resource update. object
userId A unique, obfuscated identifier that represents the user. string
Example: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi"
eventThreadId The unique identifier for the event thread. string
Example: "d67cd3f7-86a7-425e-8bb3-462f92ec9f59"
eventThreadState The state of the event thread. string
Values: "STARTED", "UPDATED", "ENDED"
resourceGroup An object that indicates resources that might have similar updates to this event. The resource of the event itself (from the resourceUpdate object) will always be present in this object. object

See Events for more information on the different types of events and how they work.

Updateable notifications

Notifications based on resource events can be implemented in an app, such as for Android or iOS. To reduce the number of notifications sent, a feature called updateable notifications may be implemented, where existing notifications are updated with new information based on subsequent events in the same event thread.

Select events feature support for updateable notifications and are tagged as Updateable  in documentation. These events have an additional field called eventThreadId in their payloads. Use this field to link individual events together for the purpose of updating an existing notification that has been surfaced for a user.

An event thread is not the same as an event session. The event thread identifies an updated status for a previous event in the same thread. The event session identifies separate events that relate to each other, and there can be multiple event threads for a given event session.

For notification purposes, different types of events are grouped into different threads.

This thread grouping and timing logic is handled by Google and is subject to change at any time. A developer should update notifications based on the event threads and sessions provided by the SDM API.

Thread state

Events that support updateable notifications also have an eventThreadState field that indicates the state of the event thread at that point in time. This field has the following values:

  • STARTED — The first event in an event thread.
  • UPDATED — An event in an ongoing event thread. There can be zero or more events with this state in a single thread.
  • ENDED — The last event in an event thread, which may be a duplicate of the last UPDATED event, depending on the thread type.

This field can be used to track the progress of an event thread and when it has ended.

Event filtering

In some cases, events detected by a device may be filtered out from publishing to an SDM Pub/Sub topic. This behavior is called event filtering. The purpose of event filtering is to avoid publishing too many similar event messages in a short amount of time.

For example, a message may get published to an SDM topic for an initial Motion event. Other messages for Motion after that will be filtered out from publishing until a set period of time passes. Once that period of time passes, an event message for that event type may be published again.

In the Google Home App (GHA), events that were filtered will still show in the user's event history. However, such events do not generate an app notification (even if that notification type is enabled).

Each type of event has its own event filtering logic, which is defined by Google and subject to change at any time. This event filtering logic is independent of the event thread and session logic.

Service accounts

Service accounts are recommended for managing SDM API subscriptions and event messages. A service account is used by an application or virtual machine, not a person, and has its own unique account key.

Service account authorization for the Pub/Sub API uses Two-legged OAuth (2LO).

In the 2LO authorization flow:

  • The developer requests an access token using a service key.
  • The developer uses the access token with calls to the API.

To learn more about Google 2LO and how to get set up, see Using OAuth 2.0 for Server to Server Applications.

Authorization

The service account should be authorized for use with the Pub/Sub API:

  1. Enable the Cloud Pub/Sub API in Google Cloud.
  2. Create a service account and service account key as described in Creating a service account. We recommend giving it only the Pub/Sub Subscriber role. Make sure to download the service account key to the machine that will be using the Pub/Sub API.
  3. Provide your authentication credentials (service account key) to your application code by following the instructions at the page in the previous step, or get an access token manually using oauth2l, if you want to quickly test API access.
  4. Use service account credentials or the access token with the Pub/Sub project.subscriptions API to pull and acknowledge messages.

oauth2l

Google oauth2l is a command line tool for OAuth written in Go. Install it for Mac or Linux using Go.

  1. If you do not have Go on your system, download and install it first.
  2. Once Go is installed, install oauth2l and add its location to your PATH environment variable:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. Use oauth2l to get an access token for the API, using the appropriate OAuth scope(s):
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    For example, if your service key is located at ~/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...

See the oauth2l README for more usage information.

Google API Client Libraries

There are several client libraries available for Google APIs that utilize OAuth 2.0. See Google API Client Libraries for more information on the language of your choice.

When using these libraries with the Pub/Sub API, use the following scope string(s):

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

Errors

The following error code(s) may be returned in relation to this guide:

Error Message RPC Troubleshooting
Camera image is no longer available for download. DEADLINE_EXCEEDED Event images expire 30 seconds after the event is published. Make sure to download the image prior to expiration.
Event id does not belong to the camera. FAILED_PRECONDITION Use the correct eventID returned by the camera event.

See the API Error Code Reference for the full list of API error codes.