事件是异步的,并由 Google Cloud Pub/Sub 进行管理,每个 Project。事件为所有设备和结构提供更新,而事件的接收则是 只要用户未撤消访问令牌,且事件消息尚未 已过期。
允许显示活动
事件是 SDM API 的可选功能。请参阅 启用事件 了解如何为您的 Project启用这些功能。
Google Cloud Pub/Sub
请参阅 Google Cloud Pub/Sub 文档了解详情 Pub/Sub 的工作原理具体而言:
- 通过 GCP 控制台中的 方法指南。
- 了解身份验证的工作原理。
- 选择提供的客户端库 或自行编写,并使用 REST/HTTP 或 gRPC API surface。
活动订阅
为您的 Project启用活动后,系统会为您提供与该主题相关的主题 Project ID,格式为:
projects/sdm-prod/topics/enterprise-project-id
要接收事件,请创建一个 pull 或 推送订阅到该主题,具体取决于您的 应用场景。支持多个订阅 SDM 主题。请参阅 管理订阅以了解详情 信息。
启动事件
要在创建 Pub/Sub 订阅后首次启动事件,请
<ph type="x-smartling-placeholder"></ph>
devices.list
作为一次性触发器调用 API。在此之后,系统会发布针对所有结构和设备的事件
调用。
有关示例,请参见 快速入门中的授权页面 指南。
事件顺序
Pub/Sub 不保证有序地传送事件,而且事件的接收顺序可能并不保证
与事件实际发生的顺序相对应。使用 timestamp
字段以帮助协调活动顺序。还可以单独提交活动或合并活动
合并成一条事件消息
如需了解详情,请参阅 对消息进行排序。
用户 ID
如果您的实现基于用户(而不是结构或设备),请使用
userID
字段,以将资源与事件相关联。此字段为
代表特定用户的经过混淆处理的 ID。
也可以在每个 API 调用的 HTTP 响应标头中找到 userID
。
关系事件
关系事件表示资源的关系更新。例如,当设备 向结构中添加设备,或从结构中删除设备时。
关系事件有三种类型:
- 创建时间:
- 已删除
- 已更新
关系事件的载荷如下所示:
载荷
{ "eventId" : "d93fe80c-dd14-4afb-80bd-b12dc7dca526", "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 示例:“96305092-d82e-4e52-9115-29bfd0594bf0” |
timestamp |
事件发生的时间。 | string 示例:“2019-01-01T00:00:01Z” |
relationUpdate |
详细说明关系更新相关信息的对象。 | object |
userId |
用于代表用户的唯一且经过混淆处理的标识符。 | string 示例:“AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi” |
请参阅事件,详细了解 事件类型及其运作方式。
示例
每种关系事件的事件载荷各不相同:
创建时间
已创建结构
"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" }
在以下情况下不会发送关系事件:
- 删除了会议室
资源事件
资源事件表示特定于资源的更新。它可以响应更改 例如,更改温控器的模式。 也可以表示一种设备操作 不更改特征字段,例如按设备按钮。
为响应特征字段的值发生变化而生成的事件包含
traits
对象,类似于设备 GET 调用:
载荷
{
"eventId" : "ba462282-5053-4e3c-bf38-612b802dfa53",
"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"
]
}
使用 个人 trait 文档,以了解任何特征字段更改资源的载荷格式 事件。
为响应不会更改特征字段的设备操作而生成的事件还具有
载荷中包含 resourceUpdate
对象,但包含 events
对象
而不是 traits
对象:
载荷
{ "eventId" : "a556db20-2bab-4bd4-bb39-9c036a252a7e",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion
" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "MnCcivUK74q3Zq7CNUSsnYcAcM...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }
这些类型的资源事件在特定特征中定义。例如, 在 CameraMotion trait.查看每个 trait 的文档 了解此类资源事件的载荷格式。
字段
字段 | 说明 | 数据类型 |
---|---|---|
eventId |
事件的唯一标识符。 | string 示例:“a556db20-2bab-4bd4-bb39-9c036a252a7e” |
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 - 正在进行的活动会话中的活动。单个线程中可以有零个或多个具有此状态的事件。
- ENDED ,即事件线程中的最后一个事件,根据线程类型,它可能与最后一个 UPDATED 事件重复。
此字段可用于跟踪事件线程的进度以及 已结束。
事件过滤
在某些情况下,设备检测到的事件可能会被滤除,无法发布 SDM Pub/Sub 主题。此行为 称为事件过滤。事件过滤的目的在于 在短时间内发布过多类似的事件消息。
例如,消息可能会发布到 SDM 主题 指定初始动作事件。其他 之后,关于 Motion 的消息会 被滤除,直到设定的时间过后才会发布。这段时间内 一段时间后,该事件类型的事件消息可能会再次发布。
Google Home 应用 (GHA) 中 被滤除的仍会显示在 user的事件记录中。但是, 事件不会生成应用通知(即使该通知类型为 )。
每种类型的事件都有自己的事件过滤逻辑,该逻辑由 Google,随时可能更改。此事件过滤逻辑 独立于事件线程和会话逻辑
服务账号
建议使用服务账号来管理 SDM API 和事件消息一个服务账号由应用或 而不是个人,并且拥有自己唯一的账号密钥。
Pub/Sub API 的服务账号授权使用 两方模式 OAuth (2LO)。
在 2LO 授权流程中:
- developer 使用服务密钥请求访问令牌。
- developer 会在调用 API 时使用访问令牌。
如需详细了解 Google 2LO 以及如何进行设置,请参阅 针对服务器到服务器使用 OAuth 2.0 应用。
授权
该服务账号应获得授权,可用于 Pub/Sub API:
- 启用 Cloud Pub/Sub API Google Cloud 中的资源。
- 按照说明创建服务账号和服务账号密钥 创建服务账号。 建议您仅为其分配 Pub/Sub Subscriber 角色。请务必 将服务账号密钥下载到将使用 Pub/Sub API。
- 向
请参阅上一节中的页面说明,
步骤,或者使用
oauth2l
手动获取访问令牌(前提是 来快速测试 API 访问权限 - 将服务账号凭据或访问令牌与
Pub/Sub
project.subscriptions
API 来拉取和确认消息
OAuth2L
Google oauth2l
是用于以 Go 编写的 OAuth 命令行工具。安装适用于
在 Mac 或 Linux 中使用 Go。
- 如果您的系统上没有 Go,请先下载并安装。
- 安装 Go 后,安装
oauth2l
并将其位置添加到您的PATH
环境变量:go install github.com/google/oauth2l@latest
export PATH=$PATH:~/go/bin
- 使用
oauth2l
获取 API 的访问令牌,并使用适当的 OAuth 范围:
例如,如果您的服务密钥位于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 的 Google API 2.0。请参阅 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 错误代码的完整列表。