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:
- Learn the basics of Pub/Sub with their How-to guides.
- Understand how Authentication works.
- Choose a provided Client Library or write your own and use the REST/HTTP or gRPC API surfaces.
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" : "d5c0f0bd-de65-44fd-ac60-686c302e56eb", "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: "64b87b46-1aec-42a4-8c01-997a407814df" |
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" : "a88bc884-d2b8-42d6-adba-b7be92c232a3",
"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" : "4f80de08-1b77-42a4-b33e-40876a2a1865",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion
" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "MWJ253hZMPAsJZJWbrGM4ThsKM...", } } } "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: "4f80de08-1b77-42a4-b33e-40876a2a1865" |
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 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:
- Enable the Cloud Pub/Sub API in Google Cloud.
- 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.
- 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. - 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.
- If you do not have Go on your system, download and install it first.
- Once Go is installed, install
oauth2l
and add its location to yourPATH
environment variable:go install github.com/google/oauth2l@latest
export PATH=$PATH:~/go/bin
- Use
oauth2l
to get an access token for the API, using the appropriate OAuth scope(s):
For example, if your service key is located atoauth2l 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...
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.