Wydarzenia

Zdarzenia są asynchroniczne i zarządzane przez Google Cloud Pub/Sub w jednym temacie na Project. Zdarzenia zapewniają aktualizacje na wszystkich urządzeniach i we wszystkich strukturach, a ich odbiór jest gwarantowany, dopóki token dostępu nie zostanie unieważniony przez użytkownika i dopóki wiadomości o zdarzeniach nie wygasną.

Włącz wydarzenia

Zdarzenia są opcjonalną funkcją interfejsu SDM API. Więcej informacji o tym, jak włączyć zdarzenia w przypadku , znajdziesz w artykule Włączanie zdarzeń . Project

Google Cloud Pub/Sub

Więcej informacji o tym, jak działa Pub/Sub, znajdziesz w dokumentacji Google Cloud Pub/Sub. W szczególności:

Subskrypcja zdarzeń

Przed styczniem 2025 r., jeśli zdarzenia były włączone w przypadku Project, otrzymywałeś temat hostowany przez Google, przypisany do tego Project identyfikatora, w postaci:

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

Wszystkie projekty muszą teraz samodzielnie hostować swoje tematy Pub/Sub we własnym projekcie Google Cloud (jest to obowiązkowe w przypadku nowych projektów od stycznia 2025 r. i wymagane w przypadku wszystkich istniejących projektów do 30 listopada 2026 r.) w postaci:

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

Jeśli już korzysta z tematu hostowanego samodzielnie we własnym projekcie w chmurze Google, nie musisz nic robić. project Migracja konfiguracji tematu Pub/Sub nie unieważnia istniejących tokenów dostępu użytkownika ani uprawnień OAuth. Tematy i subskrypcje hostowane samodzielnie podlegają standardowym cenom Google Cloud Pub/Sub (które obejmują poziom bezpłatny 10 GB miesięcznie). Więcej informacji znajdziesz w artykule Tworzenie tematu.

Aby otrzymywać zdarzenia, utwórz subskrypcję typu pull lub push w tym temacie, w zależności od przypadku użycia. Obsługiwanych jest wiele subskrypcji tematu SDM. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami.

Inicjowanie zdarzeń

Aby po raz pierwszy zainicjować zdarzenia po utworzeniu subskrypcji Pub/Sub, wywołaj interfejs API devices.list jako jednorazowy wyzwalacz. Po tym wywołaniu będą publikowane zdarzenia dotyczące wszystkich struktur i urządzeń.

Przykład znajdziesz na stronie Autoryzacja w przewodniku dla początkujących.

Kolejność zdarzeń

Pub/Sub nie gwarantuje dostarczania zdarzeń w określonej kolejności, a kolejność ich odbierania może nie odpowiadać kolejności, w jakiej faktycznie wystąpiły. Aby ułatwić uzgadnianie kolejności zdarzeń, użyj pola timestamp. Zdarzenia mogą też docierać pojedynczo lub w postaci jednej wiadomości o zdarzeniu.

Więcej informacji znajdziesz w artykule Zamawianie wiadomości.

Identyfikatory użytkowników

Jeśli Twoje wdrożenie opiera się na użytkownikach (a nie na strukturze lub urządzeniu), użyj pola userID z ładunku zdarzenia, aby skorelować zasoby i zdarzenia. To pole jest zniekształconym identyfikatorem reprezentującym konkretnego użytkownika.

Pole userID jest też dostępne w nagłówku odpowiedzi HTTP każdego wywołania interfejsu API.

Zdarzenia relacji

Zdarzenia relacji reprezentują aktualizację relacji dla zasobu. Na przykład gdy urządzenie zostanie dodane do struktury lub gdy zostanie z niej usunięte.

Istnieją 3 rodzaje zdarzeń relacji:

  • CREATED
  • USUNIĘTY
  • ZAKTUALIZOWANO

Ładunek zdarzenia relacji wygląda tak:

Ładunek

{
  "eventId" : "768e4eea-b61d-428b-8926-c67e2abaddf9",
  "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"
}

W zdarzeniu relacji object to zasób, który wywołał zdarzenie, a subject to zasób, z którym object ma teraz relację. W powyższym przykładzie user przyznał dostęp do tego konkretnego urządzenia użytkownikowi developer, a autoryzowane urządzenie użytkownika userjest teraz powiązane z jego autoryzowaną strukturą, co wywołuje zdarzenie.

subject może być tylko pokojem lub strukturą. Jeśli a developer nie ma uprawnień do wyświetlania struktury user, pole subject jest zawsze puste.

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „d575caa5-75d3-4536-9ee3-287610a433a8”
timestamp Czas wystąpienia zdarzenia. string
Przykład: „2019-01-01T00:00:01Z”
relationUpdate Obiekt zawierający szczegółowe informacje o aktualizacji relacji. object
userId Unikalny, celowo zniekształcony identyfikator reprezentujący użytkownika. string
Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”

Więcej informacji o różnych typach zdarzeń i ich działaniu znajdziesz w artykule Zdarzenia.

Przykłady

Ładunki zdarzeń różnią się w zależności od typu zdarzenia relacji:

UTWORZONO

Utworzono strukturę

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

Utworzono urządzenie

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

Utworzono urządzenie

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

ZAKTUALIZOWANO

Przeniesiono urządzenie

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

USUNIĘTY

Usunięto strukturę

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

Usunięto urządzenie

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

Usunięto urządzenie

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

Zdarzenia relacji nie są wysyłane, gdy:

  • pokój zostanie usunięty.

Zdarzenia związane z zasobami

Zdarzenie związane z zasobem reprezentuje aktualizację dotyczącą konkretnego zasobu. Może to być odpowiedź na zmianę wartości pola cechy, np. zmianę trybu termostatu. Może też reprezentować działanie urządzenia, które nie zmienia pola cechy, np. naciśnięcie przycisku urządzenia.

Zdarzenie wygenerowane w odpowiedzi na zmianę wartości pola cechy zawiera obiekt traits podobny do wywołania GET urządzenia:

Ładunek

{
  "eventId" : "ae3f760e-9e1f-4c14-b911-28482e86e56d",
  "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"
  ]
}

Aby poznać format ładunku zdarzenia związanego z zasobem, które jest wywoływane przez zmianę pola cechy, zapoznaj się z dokumentacją poszczególnych cech.

Zdarzenie wygenerowane w odpowiedzi na działanie urządzenia, które nie zmienia pola cechy, również ma ładunek z obiektem resourceUpdate, ale zamiast obiektu traits zawiera obiekt events:

Ładunek

{
  "eventId" : "aecdfca3-25ec-4738-bdbf-d24c4a209d93",
"timestamp" : "2019-01-01T00:00:01Z",
"resourceUpdate" : { "name" : "enterprises/project-id/devices/device-id", "events" : { "sdm.devices.events.CameraMotion.Motion" : { "eventSessionId" : "CjY5Y3VKaTZwR3o4Y19YbTVfMF...", "eventId" : "jE1ZfUIAp6z2anjwTJp5E8QxvC...", } } } "userId" : "AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi",
"eventThreadId" : "d67cd3f7-86a7-425e-8bb3-462f92ec9f59",
"eventThreadState" : "STARTED",
"resourceGroup" : [ "enterprises/project-id/devices/device-id" ] }

Te typy zdarzeń związanych z zasobami są zdefiniowane w konkretnych cechach. Na przykład zdarzenie Motion jest zdefiniowane w cechy CameraMotion . Aby poznać format ładunku tych typów zdarzeń związanych z zasobami, zapoznaj się z dokumentacją każdej cechy.

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „aecdfca3-25ec-4738-bdbf-d24c4a209d93”
timestamp Czas wystąpienia zdarzenia. string
Przykład: „2019-01-01T00:00:01Z”
resourceUpdate Obiekt zawierający szczegółowe informacje o aktualizacji zasobu. object
userId Unikalny, celowo zniekształcony identyfikator reprezentujący użytkownika. string
Przykład: „AVPHwEuBfnPOnTqzVFT4IONX2Qqhu9EJ4ubO-bNnQ-yi”
eventThreadId Unikalny identyfikator wątku zdarzenia. string
Przykład: „d67cd3f7-86a7-425e-8bb3-462f92ec9f59”
eventThreadState Stan wątku zdarzenia. string
Wartości: „STARTED”, „UPDATED”, „ENDED”
resourceGroup Obiekt wskazujący zasoby, które mogą mieć podobne aktualizacje do tego zdarzenia. Zasób samego zdarzenia (z obiektu resourceUpdate) będzie zawsze obecny w tym obiekcie. object

Więcej informacji o różnych typach zdarzeń i ich działaniu znajdziesz w artykule Zdarzenia.

Powiadomienia, które można aktualizować

Powiadomienia oparte na zdarzeniach związanych z zasobami można zaimplementować w aplikacji, np. na Androida lub iOS. Aby zmniejszyć liczbę wysyłanych powiadomień, można zaimplementować funkcję powiadomień, które można aktualizować. W takim przypadku istniejące powiadomienia są aktualizowane o nowe informacje na podstawie kolejnych zdarzeń w tym samym wątku zdarzenia.

Funkcja zdarzeń obsługuje powiadomienia, które można aktualizować, i jest oznaczona w dokumentacji jako Możliwość aktualizacji . Te zdarzenia mają w swoich ładunkach dodatkowe pole eventThreadId. Użyj tego pola, aby połączyć poszczególne zdarzenia w celu zaktualizowania istniejącego powiadomienia, które zostało wyświetlone użytkownikowi.

Wątek zdarzenia nie jest tym samym co sesja zdarzenia. Wątek zdarzenia wskazuje zaktualizowany stan poprzedniego zdarzenia w tym samym wątku. Sesja zdarzenia wskazuje oddzielne zdarzenia, które są ze sobą powiązane. W przypadku danej sesji zdarzenia może występować wiele wątków zdarzeń.

Na potrzeby powiadomień różne typy zdarzeń są grupowane w różne wątki.

Tą logiką grupowania i synchronizacji wątków zarządza Google i może ją w dowolnym momencie zmienić. A developer powinien aktualizować powiadomienia na podstawie wątków i sesji zdarzeń udostępnianych przez interfejs SDM API.

Stan wątku

Zdarzenia, które obsługują powiadomienia, które można aktualizować, mają też pole eventThreadState wskazujące stan wątku zdarzenia w danym momencie. To pole ma te wartości:

  • STARTED – pierwsze zdarzenie w wątku zdarzenia.
  • UPDATED – zdarzenie w trwającym wątku zdarzenia. W jednym wątku może występować zero lub więcej zdarzeń o tym stanie.
  • ENDED – ostatnie zdarzenie w wątku zdarzenia, które w zależności od typu wątku może być duplikatem ostatniego zdarzenia UPDATED.

To pole może służyć do śledzenia postępu wątku zdarzenia i jego zakończenia.

Filtrowanie zdarzeń

W niektórych przypadkach zdarzenia wykryte przez urządzenie mogą zostać odfiltrowane z publikowania w temacie SDM Pub/Sub. Takie zachowanie nazywa się filtrowaniem zdarzeń. Filtrowanie zdarzeń ma na celu uniknięcie publikowania zbyt wielu podobnych wiadomości o zdarzeniach w krótkim czasie.

Na przykład wiadomość może zostać opublikowana w temacie SDM w przypadku początkowego zdarzenia Motion. Inne wiadomości dotyczące zdarzenia Motion będą odfiltrowywane z publikowania do momentu upłynięcia określonego czasu. Po upływie tego czasu wiadomość o zdarzeniu tego typu może zostać ponownie opublikowana.

W aplikacji Google Home odfiltrowane zdarzenia będą nadal widoczne w historii zdarzeń userużytkownika. Takie zdarzenia nie generują jednak powiadomienia w aplikacji (nawet jeśli ten typ powiadomień jest włączony).

Każdy typ zdarzenia ma własną logikę filtrowania zdarzeń, która jest definiowana przez Google i może ulec zmianie w dowolnym momencie. Ta logika filtrowania zdarzeń jest niezależna od logiki wątku i sesji zdarzenia.

Konta usługi

Do zarządzania subskrypcjami interfejsu SDM API i wiadomościami o zdarzeniach zalecamy używanie kont usługi. Konto usługi jest używane przez aplikację lub maszynę wirtualną, a nie przez osobę, i ma własny unikalny klucz konta.

Autoryzacja konta usługi w interfejsie Pub/Sub API korzysta z dwuskładnikowego uwierzytelniania OAuth (2LO).

W procesie autoryzacji 2LO:

  • developer wysyła żądanie tokena dostępu za pomocą klucza usługi.
  • developer używa tokena dostępu do wywoływania interfejsu API.

Więcej informacji o protokole Google 2LO i jego konfiguracji znajdziesz w artykule Używanie OAuth 2.0 w aplikacjach serwer-serwer.

Autoryzacja

Konto usługi powinno być autoryzowane do używania interfejsu Pub/Sub API:

  1. Włącz interfejs Cloud Pub/Sub API w Google Cloud.
  2. Utwórz konto usługi i klucz konta usługi zgodnie z opisem w artykule Tworzenie konta usługi. Zalecamy przypisanie do niego tylko roli Subskrybent Pub/Sub. Pobierz klucz konta usługi na komputer, który będzie używać interfejsu Pub/Sub API.
  3. Podaj dane uwierzytelniające (klucz konta usługi) w kodzie aplikacji, postępując zgodnie z instrukcjami na stronie z poprzedniego kroku, lub ręcznie uzyskaj token dostępu za pomocą narzędzia oauth2l, jeśli chcesz szybko przetestować dostęp do interfejsu API.
  4. Użyj danych logowania konta usługi lub tokena dostępu w interfejsie Pub/Sub project.subscriptions API aby pobierać i potwierdzać wiadomości.

oauth2l

Narzędzie Google oauth2l to narzędzie wiersza poleceń do obsługi protokołu OAuth napisane w języku Go. Zainstaluj je na komputerze z systemem Mac lub Linux za pomocą języka Go.

  1. Jeśli nie masz w systemie języka Go, najpierw go pobierz i zainstaluj.
  2. Po zainstalowaniu języka Go zainstaluj narzędzie oauth2l i dodaj jego lokalizację do zmiennej środowiskowej PATH:
    go install github.com/google/oauth2l@latest
    export PATH=$PATH:~/go/bin
  3. Użyj narzędzia oauth2l, aby uzyskać token dostępu do interfejsu API, używając odpowiednich zakresów OAuth:
    oauth2l fetch --credentials path-to-service-key.json --scope https://www.googleapis.com/auth/pubsub
    https://www.googleapis.com/auth/cloud-platform
    Jeśli na przykład klucz usługi znajduje się w lokalizacji ~/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...

Więcej informacji o użyciu znajdziesz w pliku oauth2l README narzędzia.

Biblioteki klienta interfejsów API Google

Dostępnych jest kilka bibliotek klienta interfejsów API Google, które korzystają z protokołu OAuth 2.0. Więcej informacji o wybranym języku znajdziesz w artykule Biblioteki klienta interfejsów API Google.

Gdy używasz tych bibliotek z Pub/Sub API, użyj tych ciągów zakresów:

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

Błędy

W związku z tym przewodnikiem mogą zostać zwrócone te kody błędów:

Komunikat o błędzie RPC Rozwiązywanie problemów
Obraz z kamery nie jest już dostępny do pobrania. DEADLINE_EXCEEDED Obrazy zdarzeń wygasają 30 sekund po opublikowaniu zdarzenia. Pamiętaj, aby pobrać obraz przed wygaśnięciem.
Identyfikator zdarzenia nie należy do kamery. FAILED_PRECONDITION Użyj prawidłowego identyfikatora eventID zwróconego przez zdarzenie kamery.

Pełną listę kodów błędów interfejsu API znajdziesz w dokumentacji API Error Code Reference.