Os eventos são assíncronos e gerenciados pelo Google Cloud Pub/Sub, em um único tópico por Project. Os eventos fornecem atualizações para todos os dispositivos e estruturas, e o recebimento de eventos é garantido, desde que o token de acesso não seja revogado pelo usuário e as mensagens do evento não tenham expirado.
Ativar eventos
Os eventos são um recurso opcional da API SDM. Consulte Ativar eventos para saber como ativá-los no Project.
Google Cloud Pub/Sub
Consulte a documentação do Google Cloud Pub/Sub para saber mais sobre como ele funciona. Especificamente, faça o seguinte:
- Aprenda os conceitos básicos do Pub/Sub com os guias de instruções.
- Entenda como a autenticação funciona.
- Escolha uma biblioteca de cliente fornecida ou crie sua própria e use as plataformas da API REST/HTTP ou gRPC.
Inscrição em eventos
Quando os eventos estiverem ativados para Project, você receberá um tema específico para esse Project ID na forma de:
projects/sdm-prod/topics/enterprise-project-id
Para receber eventos, crie uma assinatura de pull ou push nesse tópico, dependendo do seu caso de uso. São aceitas várias assinaturas no tópico do SDM. Consulte Como gerenciar assinaturas para mais informações.
Iniciar eventos
Para iniciar eventos pela primeira vez após a criação da assinatura do Pub/Sub, faça uma chamada de API
devices.list
como um gatilho único. Os eventos de todas as estruturas e dispositivos serão publicados após essa
chamada.
Por exemplo, consulte a página Autorizar no Guia de início rápido.
Ordem do evento
O Pub/Sub não garante a entrega ordenada de eventos, e a ordem de recebimento dos eventos pode não
corresponder à ordem em que os eventos realmente ocorreram. Use o campo timestamp
para ajudar na reconciliação da ordem dos eventos. Os eventos também podem chegar individualmente ou combinados em uma única mensagem de evento.
Para mais informações, consulte Como ordenar mensagens.
User-IDs
Se a implementação for baseada em usuários, e não em estrutura ou dispositivo, use o campo userID
do payload do evento para correlacionar recursos e eventos. Esse campo é um ID ofuscado que representa um usuário específico.
O userID
também está disponível no cabeçalho de resposta HTTP de cada chamada de API.
Eventos de relação
Os eventos relacionais representam uma atualização relacional de um recurso. Por exemplo, quando um dispositivo é adicionado a uma estrutura ou quando um dispositivo é excluído de uma estrutura.
Há três tipos de eventos relacionais:
- CRIADO
- EXCLUÍDA
- ATUALIZADO
O payload de um evento de relação é o seguinte:
Payload
{ "eventId" : "eed9763a-8735-45d9-81d9-e0621c130eb1", "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" }
Em um evento de relação, object
é o recurso que acionou o evento, e subject
é o recurso com que object
agora tem uma relação. No exemplo acima, um user concedeu a esse dispositivo específico acesso a um developer, e o dispositivo autorizado do useragora está relacionado à estrutura autorizada, que aciona o evento.
Um subject
só pode ser um ambiente ou uma estrutura. Se a developer não tiver permissão para visualizar a estrutura do user, o subject
estará sempre vazio.
Campos
Campo | Descrição | Tipo de dados |
---|---|---|
eventId |
Identificador exclusivo do evento. | string Exemplo: "1362476b-4ac4-4608-a8be-4c8cf4101426" |
timestamp |
A hora em que o evento ocorreu. | string Exemplo: "2019-01-01T00:00:01Z" |
relationUpdate |
Um objeto que detalha informações sobre a atualização da relação. | object |
userId |
Um identificador exclusivo e ofuscado que representa o usuário. | string Exemplo: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi" |
Consulte Eventos para mais informações sobre os diferentes tipos de eventos e como eles funcionam.
Exemplos
Os payloads do evento diferem para cada tipo de evento de relação:
CREATED
Estrutura criada
"relationUpdate" : { "type" : "CREATED", "subject" : "", "object" : "enterprises/project-id/structures/structure-id" }
Dispositivo criado
"relationUpdate" : { "type" : "CREATED", "subject" : "enterprises/project-id/structures/structure-id", "object" : "enterprises/project-id/devices/device-id" }
Dispositivo criado
"relationUpdate" : { "type" : "CREATED", "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id", "object" : "enterprises/project-id/devices/device-id" }
ATUALIZADO
Dispositivo movido
"relationUpdate" : { "type" : "UPDATED", "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id", "object" : "enterprises/project-id/devices/device-id" }
EXCLUÍDA
Estrutura excluída
"relationUpdate" : { "type" : "DELETED", "subject" : "", "object" : "enterprises/project-id/structures/structure-id" }
Dispositivo excluído
"relationUpdate" : { "type" : "DELETED", "subject" : "enterprises/project-id/structures/structure-id", "object" : "enterprises/project-id/devices/device-id" }
Dispositivo excluído
"relationUpdate" : { "type" : "DELETED", "subject" : "enterprises/project-id/structures/structure-id/rooms/room-id", "object" : "enterprises/project-id/devices/device-id" }
Eventos de relação não são enviados quando:
- Uma sala foi excluída
Eventos do recurso
Um evento de recurso representa uma atualização específica de um recurso. Pode ser em resposta a uma mudança no valor de um campo de característica, como a mudança do modo de um termostato. Também pode representar uma ação do dispositivo que não muda um campo de característica, como pressionar um botão.
Um evento gerado em resposta a uma mudança no valor do campo de característica contém um objeto
traits
, semelhante a uma chamada GET de dispositivo:
Payload
{
"eventId" : "5b98a768-6771-4d4d-836d-58cce3a62cca",
"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 a documentação de características individuais para entender o formato de payload de qualquer evento de recurso de alteração de campo de característica.
Um evento gerado em resposta a uma ação do dispositivo que não altera um campo de característica também tem um
payload com um objeto resourceUpdate
, mas com um objeto events
em vez de um objeto traits
:
Payload
{ "eventId" : "3426d266-406b-48f3-9595-5192229a39a0",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion
" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "8XZ1cQ76Becovj551YfM9ZnuwB...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }
Esses eventos são definidos com características específicas. Por exemplo, o evento de movimento é definido na característica CameraMotion . Consulte a documentação de cada característica para entender o formato de payload para esses tipos de eventos de recursos.
Campos
Campo | Descrição | Tipo de dados |
---|---|---|
eventId |
Identificador exclusivo do evento. | string Exemplo: "3426d266-406b-48f3-9595-5192229a39a0" |
timestamp |
A hora em que o evento ocorreu. | string Exemplo: "2019-01-01T00:00:01Z" |
resourceUpdate |
Um objeto com informações sobre a atualização do recurso. | object |
userId |
Um identificador exclusivo e ofuscado que representa o usuário. | string Exemplo: "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi" |
eventThreadId |
O identificador exclusivo da thread de evento. | string Exemplo: "d67cd3f7-86a7-425e-8bb3-462f92ec9f59" |
eventThreadState |
O estado da thread de evento. | string Valores: "STARTED", "UPDATED", "ENDED" |
resourceGroup |
Objeto que indica recursos que podem ter atualizações semelhantes a este evento. O recurso do próprio evento (do objeto resourceUpdate ) sempre estará presente nesse objeto. |
object |
Consulte Eventos para mais informações sobre os diferentes tipos de eventos e como eles funcionam.
Notificações atualizáveis
Notificações baseadas em eventos de recursos podem ser implementadas em um app, como para Android ou iOS. Para reduzir o número de notificações enviadas, é possível implementar um recurso chamado notificações atualizáveis, em que as notificações existentes são atualizadas com novas informações com base em eventos subsequentes na mesma linha de execução de eventos.Alguns eventos são compatíveis com o recurso de notificações atualizáveis e são marcados como
Updateable eventThreadId
nos payloads. Use esse campo para vincular eventos individuais com o objetivo de atualizar uma notificação existente que foi exibida para um usuário.
Uma linha de execução de evento não é o mesmo que uma sessão de evento. A linha de execução de evento identifica um status atualizado de um evento anterior na mesma linha. A sessão do evento identifica eventos separados que se relacionam entre si, e pode haver várias linhas de execução para uma determinada sessão.
Para fins de notificação, diferentes tipos de eventos são agrupados em diferentes linhas de execução.
Essa lógica de agrupamento de linhas de execução e de tempo é processada pelo Google e está sujeita a mudanças a qualquer momento. Um developer precisa atualizar as notificações com base nas sessões e linhas de execução do evento fornecidas pela API SDM.
Estado da linha de execução
Os eventos compatíveis com notificações atualizáveis também têm um campo eventThreadState
que indica o estado da linha de execução de eventos nesse momento. Esse
campo tem os seguintes valores:
- STARTED — o primeiro evento em uma thread de evento.
- UPDATED — um evento em uma thread de evento em andamento. Pode haver zero ou mais eventos com esse estado em uma única linha de execução.
- ENDED — o último evento em uma thread de evento, que pode ser uma cópia do último evento UPDATED, dependendo do tipo de thread.
Esse campo pode ser usado para acompanhar o progresso de uma linha de execução de eventos e quando ela é finalizada.
Filtragem de eventos
Em alguns casos, os eventos detectados por um dispositivo podem ser filtrados da publicação em um tópico do Pub/Sub do SDM. Esse comportamento é chamado de filtragem de eventos. O objetivo da filtragem de eventos é evitar publicar muitas mensagens de eventos semelhantes em um curto período.
Por exemplo, uma mensagem pode ser publicada em um tópico de SDM para um evento de movimento inicial. Outras mensagens para "Movimento" depois disso serão filtradas da publicação até um determinado período. Após esse período, uma mensagem de evento para esse tipo de evento poderá ser publicada novamente.
No app Google Home (GHA, na sigla em inglês), os eventos que foram filtrados ainda vão aparecer no histórico de eventos do user. No entanto, esses eventos não geram uma notificação do app, mesmo que o tipo de notificação esteja ativado.
Cada tipo de evento tem a própria lógica de filtragem de eventos, que é definida pelo Google e está sujeita a mudanças a qualquer momento. Essa lógica de filtragem de eventos é independente da linha de execução de eventos e da lógica da sessão.
Contas de serviço
As contas de serviço são recomendadas para gerenciar assinaturas da API SDM e mensagens de eventos. Uma conta de serviço é usada por um aplicativo ou máquina virtual, não por uma pessoa, e tem uma chave de conta exclusiva.
A autorização da conta de serviço para a API Pub/Sub usa o OAuth de duas etapas (2LO, na sigla em inglês).
No fluxo de autorização 2LO:
- O developer solicita um token de acesso usando uma chave de serviço.
- O developer usa o token de acesso com chamadas à API.
Para saber mais sobre o Google 2LO e como configurá-lo, consulte Usar o OAuth 2.0 para aplicativos de servidor para servidor.
Autorização
A conta de serviço precisa ter autorização para uso com a API Pub/Sub:
- Ative a API Cloud Pub/Sub no Google Cloud.
- Crie uma conta de serviço e uma chave de conta de serviço, conforme descrito em Como criar uma conta de serviço. Recomendamos conceder apenas o papel de Assinante do Pub/Sub. Faça o download da chave da conta de serviço para a máquina que usará a API Pub/Sub.
- Forneça suas credenciais de autenticação (chave da conta de serviço) ao código do aplicativo seguindo as instruções na página da etapa anterior ou receba um token de acesso manualmente usando
oauth2l
, se quiser testar rapidamente o acesso à API. - Use as credenciais da conta de serviço ou o token de acesso com a
API Pub/Sub
project.subscriptions
para extrair e confirmar mensagens.
OAuth2l
O Google oauth2l
é uma ferramenta de linha de comando para OAuth escrita em Go. Instale-a para Mac ou Linux usando Go.
- Se você não tem o Go no seu sistema, faça o download e instale-o primeiro.
- Depois que o Go for instalado, instale
oauth2l
e adicione o local dele à sua variável de ambientePATH
:go install github.com/google/oauth2l@latest
export PATH=$PATH:~/go/bin
- Use
oauth2l
para receber um token de acesso à API, com os escopos apropriados do OAuth:
Por exemplo, se a chave de serviço estiver localizada emoauth2l 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...
Consulte o README do oauth2l
(em inglês) para mais informações
de uso.
Bibliotecas de cliente de APIs do Google
Há várias bibliotecas de cliente disponíveis para APIs do Google que utilizam o OAuth 2.0. Consulte Bibliotecas de cliente das APIs do Google para mais informações sobre a linguagem escolhida.
Ao usar essas bibliotecas com o Pub/Sub API, use as seguintes strings de escopo:
https://www.googleapis.com/auth/pubsub https://www.googleapis.com/auth/cloud-platform
Erros
Os seguintes códigos de erro podem ser retornados em relação a este guia:
Mensagem de erro | RPC | Solução de problemas |
---|---|---|
A imagem da câmera não está mais disponível para download. | DEADLINE_EXCEEDED |
As imagens do evento expiram 30 segundos após a publicação dele. Faça o download da imagem antes da data de validade. |
O ID do evento não pertence à câmera. | FAILED_PRECONDITION |
Use a eventID correta retornada pelo evento da câmera. |
Consulte a referência de código de erro da API para ver a lista completa desses códigos.