Eventos

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 de 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 seu Project.

Google Cloud Pub/Sub

Consulte a documentação do Google Cloud Pub/Sub para saber mais sobre como o Pub/Sub funciona. Especificamente:

Inscrição em eventos

Antes de janeiro de 2025, se os eventos estivessem ativados para seu Project, você receberia um tópico hospedado pelo Google específico para esse Project ID, no formato:

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

Agora, todos os projetos precisam hospedar os próprios tópicos do Pub/Sub no projeto do Google Cloud (obrigatório para novos projetos desde janeiro de 2025 e para todos os projetos atuais até 30 de novembro de 2026), no formato:

projects/gcp-project-name/subscriptions/topic-id

Se o project já usa um tópico auto-hospedado no seu próprio projeto do Google Cloud, não é necessário fazer nada. A migração da configuração do tópico do Pub/Sub não invalida os tokens de acesso do usuário ou as permissões do OAuth. Os tópicos e as assinaturas auto-hospedados estão sujeitos aos preços padrão do Google Cloud Pub/Sub (que inclui um nível sem custo financeiro de 10 GB por mês). Consulte Criar um tópico para mais informações.

Para receber eventos, crie uma assinatura de pull ou push para esse tópico, dependendo do seu caso de uso. É possível ter várias assinaturas do 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.

Para ver um exemplo, consulte a página Autorizar no Guia de início rápido.

Pedido do evento

O Pub/Sub não garante a entrega ordenada de eventos, e a ordem de recebimento deles 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 (em vez de 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 de relação representam uma atualização relacional de um recurso. Por exemplo, quando um dispositivo é adicionado ou excluído de uma estrutura.

Há três tipos de eventos de relação:

  • CREATED
  • EXCLUÍDO
  • ATUALIZADO

O payload de um evento de relação é o seguinte:

Payload

{
  "eventId" : "1a2e13bc-c23c-4bc4-8366-6b5669607f0e",
  "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, o object é o recurso que acionou o evento, e o subject é o recurso com que o object agora tem uma relação. No exemplo acima, um user concedeu acesso a esse dispositivo específico a um developer, e o dispositivo autorizado do useragora está relacionado à estrutura autorizada dele, o 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 O identificador exclusivo do evento. string
Exemplo: "a121b435-e3bb-4ba1-9dea-945686b7dabf"
timestamp O horário 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 de evento são diferentes 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ÍDO

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"
}

Os eventos de relação não são enviados quando:

  • Uma sala é 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 atributo, como mudar o modo de um termostato. Também pode representar uma ação do dispositivo que não muda um campo de atributo, como pressionar um botão do dispositivo.

Um evento gerado em resposta a uma mudança no valor do campo de atributo contém um objeto traits, semelhante a uma chamada GET do dispositivo:

Payload

{
  "eventId" : "caec1000-1cab-43d3-946f-bc3c5f8615c9",
  "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 traços individuais para entender o formato do payload de qualquer evento de recurso de mudança de campo de traço.

Um evento gerado em resposta a uma ação do dispositivo que não muda um campo de atributo também tem um payload com um objeto resourceUpdate, mas com um objeto events em vez de um objeto traits:

Payload

{
  "eventId" : "0111d3f2-5e7d-4ecf-88ed-8f3b0324f75c",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "jOvQqNOSL76837k_JxTR4BJ6nw...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

Esses tipos de eventos de recursos são definidos em atributos específicos. Por exemplo, o evento de movimento é definido no atributo CameraMotion . Consulte a documentação de cada atributo para entender o formato do payload desses tipos de eventos de recurso.

Campos

Campo Descrição Tipo de dados
eventId O identificador exclusivo do evento. string
Exemplo: "0111d3f2-5e7d-4ecf-88ed-8f3b0324f75c"
timestamp O horário em que o evento ocorreu. string
Exemplo: "2019-01-01T00:00:01Z"
resourceUpdate Um objeto que detalha 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 linha de execução do evento. string
Exemplo: "d67cd3f7-86a7-425e-8bb3-462f92ec9f59"
eventThreadState O estado da linha de execução do evento. string
Valores: "STARTED", "UPDATED", "ENDED"
resourceGroup Um objeto que indica recursos que podem ter atualizações semelhantes a este evento. O recurso do evento em si (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

As 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 atuais são atualizadas com novas informações com base em eventos subsequentes na mesma linha de eventos.

Alguns eventos são compatíveis com notificações atualizáveis e são marcados como Atualizáveis  na documentação. Esses eventos têm um campo adicional chamado eventThreadId nos payloads. Use esse campo para vincular eventos individuais com o objetivo de atualizar uma notificação que foi mostrada para um usuário.

Uma conversa de evento não é o mesmo que uma sessão de evento. A linha de execução do evento identifica um status atualizado de um evento anterior na mesma linha de execução. A sessão de evento identifica eventos separados que se relacionam entre si, e pode haver várias linhas de execução de eventos para uma determinada sessão de evento.

Para fins de notificação, diferentes tipos de eventos são agrupados em diferentes linhas de conversa.

Essa lógica de agrupamento e de tempo de conversas é processada pelo Google e está sujeita a mudanças a qualquer momento. Um developer precisa atualizar as notificações com base nas linhas de execução de eventos e sessões fornecidas pela API SDM.

Estado da linha de execução

Os eventos que aceitam notificações atualizáveis também têm um campo eventThreadState que indica o estado da conversa do evento naquele momento. Esse campo tem os seguintes valores:

  • STARTED: o primeiro evento em uma linha de eventos.
  • UPDATED: um evento em uma linha de execução 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 linha de eventos, que pode ser uma cópia do último evento UPDATED, dependendo do tipo de linha.

Esse campo pode ser usado para acompanhar o progresso de uma linha de eventos e quando ela terminou.

Filtragem de eventos

Em alguns casos, os eventos detectados por um dispositivo podem ser filtrados para não serem publicados em um tópico do Pub/Sub do SDM. Esse comportamento é chamado de filtragem de eventos. O objetivo da filtragem de eventos é evitar a publicação de muitas mensagens de eventos semelhantes em um curto período.

Por exemplo, uma mensagem pode ser publicada em um tópico do SDM para um evento de movimento inicial. Outras mensagens para o Motion depois disso serão filtradas da publicação até que um determinado período passe. Depois que esse período passar, uma mensagem de evento para esse tipo de evento poderá ser publicada novamente.

No app Google Home (GHA), os eventos 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 esse tipo de notificação esteja ativado.

Cada tipo de evento tem uma lógica de filtragem própria, que é definida pelo Google e está sujeita a mudanças a qualquer momento. Essa lógica de filtragem de eventos é independente da lógica de linha de execução e sessão de eventos.

Contas de serviço

As contas de serviço são recomendadas para gerenciar assinaturas da API SDM e mensagens de evento. Uma conta de serviço é usada por um aplicativo ou uma 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).

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 para a API.

Para saber mais sobre o 2LO do Google e como configurá-lo, consulte Como usar o OAuth 2.0 para aplicativos de servidor para servidor.

Autorização

A conta de serviço precisa ser autorizada para uso com a API Pub/Sub:

  1. Ative a API Cloud Pub/Sub no Google Cloud.
  2. 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 a ela 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.
  3. 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.
  4. Use as credenciais da conta de serviço ou o token de acesso com a API project.subscriptions do Pub/Sub 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.

  1. Se você não tiver o Go no seu sistema, faça o download e instale-o primeiro.
  2. Depois de instalar o Go, instale o oauth2l e adicione o local dele à variável de ambiente PATH:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. Use oauth2l para receber um token de acesso para a API, usando os escopos do OAuth apropriados:
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    Por exemplo, se a chave de serviço estiver localizada em ~/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 para mais informações de uso.

Bibliotecas de cliente de APIs do Google

Há várias bibliotecas de cliente disponíveis para as APIs do Google que usam o OAuth 2.0. Consulte as bibliotecas de cliente das APIs do Google para mais informações sobre a linguagem de sua escolha.

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 do 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 de eventos expiram 30 segundos após a publicação do evento. Faça o download da imagem antes que ela expire.
O ID do evento não pertence à câmera. FAILED_PRECONDITION Use o eventID correto retornado pelo evento da câmera.

Consulte a Referência de códigos do erro da API para ver a lista completa de códigos do erro da API.