Wydarzenia

Zdarzenia są asynchroniczne i zarządzane przez Google Cloud Pub/Sub w jednym temacie na Project. Zdarzenia dostarczają aktualizacji dla wszystkich urządzeń i struktur. Odbieranie zdarzeń jest zapewnione, o ile użytkownik nie cofnie tokenu dostępu, a wiadomości zdarzeń nie wygasną.

Włącz wydarzenia

Zdarzenia są opcjonalną funkcją interfejsu SDM API. Aby dowiedzieć się, jak włączyć te funkcje w przypadku usługi Project, przejdź do: Włączanie zdarzeń .

Google Cloud Pub/Sub

Więcej informacji o działaniu usługi Pub/Sub znajdziesz w dokumentacji Google Cloud Pub/Sub. W szczególności:

Subskrypcja zdarzeń

Gdy zdarzenia są włączone w przypadku Twojej domeny ( Project), otrzymasz temat dotyczący tego identyfikatora ( Project ) w postaci:

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

Aby otrzymywać zdarzenia, utwórz subskrypcję pull lub push tego tematu, w zależności od przypadku użycia. Obsługiwane są liczne subskrypcje tematu SDM. Więcej informacji znajdziesz w artykule Zarządzanie subskrypcjami.

Inicjowanie zdarzeń

Aby po raz pierwszy wywołać zdarzenia po utworzeniu subskrypcji Pub/Sub, wykonaj wywołanie interfejsu API devices.list jako jednorazowe zdarzenie. Po tym wywołaniu zostaną opublikowane zdarzenia dotyczące wszystkich struktur i urządzeń.

Przykładem jest strona Autoryzuj w Krótkim przewodniku.

kolejność zdarzeń,

Pub/Sub nie gwarantuje uporządkowanej dostawy zdarzeń, a kolejność ich odbioru może nie odpowiadać kolejności, w jakiej zdarzenia faktycznie miały miejsce. Użyj pola timestamp do ułatwienia uzgadniania kolejności zdarzeń. Wydarzenia mogą być wysyłane pojedynczo lub połączone w jedną wiadomość.

Więcej informacji znajdziesz w artykule Ustalanie kolejności wiadomości.

Identyfikatory użytkowników

Jeśli Twoja implementacja opiera się na użytkownikach (a nie na strukturze ani urządzeniu), użyj pola userID z ładunku zdarzenia, aby powiązać zasoby i zdarzenia. To pole to zniekształcony identyfikator reprezentujący konkretnego użytkownika.

Wartość userID jest też dostępna w nagłówku odpowiedzi HTTP każdego wywołania interfejsu API.

Zdarzenia związane z relacją

Zdarzenia dotyczące relacji to aktualizacje relacyjne zasobu. Na przykład gdy urządzenie zostanie dodane do struktury lub usunięte z niej.

Istnieją 3 rodzaje zdarzeń dotyczących relacji:

  • CREATED
  • USUNIĘTY
  • ZAKTUALIZOWANO

Ładunek zdarzenia relacji:

Ładunek

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

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 tym przykładzie user przyznał dostęp do tego konkretnego urządzenia developer, a urządzenie userjest teraz powiązane z autoryzowaną strukturą, która powoduje wystąpienie zdarzenia.

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

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „64b87b46-1aec-42a4-8c01-997a407814df”
timestamp Czas wystąpienia zdarzenia. string
Przykład: „2019-01-01T00:00:01Z”
relationUpdate Obiekt zawierający szczegółowe informacje o zmianie relacji. object
userId Unikalny, zanonimizowany 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 sekcji Zdarzenia.

Przykłady

Dane ładunku zdarzenia różnią się w zależności od typu zdarzenia relacji:

UTWORZONO

Struktura została utworzona

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

Urządzenie zostało utworzone

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

Urządzenie zostało utworzone

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

ZAKTUALIZOWANO

Przeniesienie urządzenia

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

USUNIĘTY

Struktura została usunięta

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

Urządzenie zostało usunięte

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

Urządzenie zostało usunięte

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

Zdarzenia dotyczące relacji nie są wysyłane, gdy:

  • Pokój został usunięty

Zdarzenia związane z zasobami

Zdarzenie dotyczące zasobu reprezentuje aktualizację dotyczącą konkretnego zasobu. Może to być reakcja na zmianę wartości pola cechy, np. zmianę trybu termostatu. Może też reprezentować działanie urządzenia, które nie zmienia pola atrybutu, takie jak naciśnięcie przycisku urządzenia.

Zdarzenie wygenerowane w odpowiedzi na zmianę wartości pola cechy zawiera obiekt traits, podobnie jak wywołanie GET urządzenia:

Ładunek

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

Aby poznać format danych dla zdarzenia zmiany zasobu pola cechy, zapoznaj się z dokumentacją dotyczącą poszczególnych cech.

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

Ładunek

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

Te typy zdarzeń związanych z zasobami są definiowane w konkretnych cechach. Na przykład zdarzenie Ruch jest zdefiniowane w profilu CameraMotion . Aby poznać format danych payload w przypadku tych typów zdarzeń związanych ze zbiorem zasobów, zapoznaj się z dokumentacją poszczególnych atrybutów.

Pola

Pole Opis Typ danych
eventId Unikalny identyfikator zdarzenia. string
Przykład: „4f80de08-1b77-42a4-b33e-40876a2a1865”.
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, zanonimizowany 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” (rozpoczęto), „UPDATED” (zaktualizowano) i „ENDED” (zakończono).
resourceGroup Obiekt wskazujący zasoby, które mogą mieć podobne aktualizacje do tego zdarzenia. Zasoby samego zdarzenia (z obiektu resourceUpdate) będą zawsze obecne w tym obiekcie. object

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

Powiadomienia z możliwością aktualizacji

Powiadomienia oparte na zdarzeniach dotyczących zasobów można implementować w aplikacji, np. na Androida lub iOS. Aby zmniejszyć liczbę wysyłanych powiadomień, możesz wdrożyć funkcję powiadomień z możliwością aktualizacji, w ramach której istniejące powiadomienia są aktualizowane o nowe informacje na podstawie kolejnych zdarzeń w tym samym wątku zdarzeń.

Wybrane zdarzenia obsługują powiadomienia z możliwością aktualizacji i są oznaczone w dokumentacji jako z możliwością aktualizacji . Te zdarzenia mają w swoim ładunku dodatkowe pole o nazwie eventThreadId. Użyj tego pola, aby powiązać poszczególne zdarzenia w celu zaktualizowania istniejącego powiadomienia wyświetlanego użytkownikowi.

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

W celu wysyłania powiadomień różne typy zdarzeń są grupowane w różne wątki.

Za logikę grupowania wątków i określanie ich czasu odpowiada Google i może ona ulec zmianie w dowolnym momencie. A developer powinien aktualizować powiadomienia na podstawie wątków zdarzeń i sesji udostępnianych przez interfejs SDM API.

Stan wątku

Wydarzenia, które obsługują powiadomienia z możliwością aktualizacji, mają też pole eventThreadState, które wskazuje stan wątku wydarzenia w danym momencie. To pole może mieć te wartości:

  • STARTED (rozpoczęto) – pierwsze zdarzenie w wątku zdarzenia.
  • UPDATED – zdarzenie w bieżącym wątku zdarzenia. W ramach jednego wątku może wystąpić 0 lub więcej zdarzeń o tym stanie.
  • ENDED (Zakończono) – ostatnie zdarzenie w wątku zdarzenia, które może być duplikatem ostatniego zdarzenia UPDATED (Zaktualizowano) w zależności od typu wątku.

Tego pola można używać do śledzenia postępów w rozwijaniu 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 działanie nazywamy filtrowaniem zdarzeń. Filtrowanie zdarzeń ma na celu unikanie publikowania zbyt wielu podobnych komunikatów o zdarzeniach w krótkim czasie.

Na przykład wiadomość może zostać opublikowana w temacie SDM dla początkowego zdarzenia Motion. Inne wiadomości dotyczące Motion po tym czasie zostaną odfiltrowane i nie będą publikowane do czasu upłynięcia określonego czasu. Po upływie tego czasu wiadomość o danym typie zdarzenia może zostać opublikowana ponownie.

W aplikacji Google Home (GHA) odfiltrowane zdarzenia będą nadal widoczne w historii zdarzeń user. Jednak takie zdarzenia nie generują powiadomienia z aplikacji (nawet jeśli ten typ powiadomienia jest włączony).

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

Konta usługi

Konta usługi są zalecane do zarządzania subskrypcjami interfejsu SDM API i wiadomościami o zdarzeniach. 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 przypadku interfejsu Pub/Sub API korzysta z dwuetapowej autoryzacji OAuth (2LO).

W procesie autoryzacji 2 FA:

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

Więcej informacji o Google 2LO i o tym, jak go skonfigurować, znajdziesz w artykule Używanie OAuth 2.0 w aplikacjach serwer-serwer.

Autoryzacja

Konto usługi powinno być autoryzowane do korzystania z interfejsu Pub/Sub API:

  1. Włącz interfejs API Cloud Pub/Sub 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 tylko roli subskrybenta Pub/Sub. Pamiętaj, aby pobrać klucz konta usługi na maszynę, która będzie używać interfejsu Pub/Sub API.
  3. Aby szybko przetestować dostęp do interfejsu API, podaj swoje poświadczenia logowania (klucz konta usługi) w kodzie aplikacji, postępując zgodnie z instrukcjami na stronie z poprzedniego kroku, lub ręcznie pobierz token dostępu za pomocą funkcji oauth2l.
  4. Użyj danych logowania konta usługi lub tokenu dostępu w interfejsie Pub/Sub project.subscriptionsAPI, aby pobierać i potwierdzać wiadomości.

oauth2l

Google oauth2l to narzędzie wiersza poleceń do obsługi OAuth napisane w języku Go. Zainstaluj je na Macu lub Linuxie za pomocą Go.

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

Biblioteki klienta Google API

Do interfejsów API Google, które korzystają z protokołu OAuth 2.0, dostępnych jest kilka bibliotek klienta. Więcej informacji o konkretnym języku znajdziesz w bibliotekach klienta interfejsu API Google.

Podczas korzystania z tych bibliotek z  Pub/Sub APIużyj tych ciągów zakresu:

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 aparatu nie jest już dostępny do pobrania. DEADLINE_EXCEEDED Obrazy wydarzeń wygasają 30 sekund po opublikowaniu wydarzenia. Pamiętaj, aby pobrać obraz przed wygaśnięciem.
Identyfikator zdarzenia nie należy do kamery. FAILED_PRECONDITION Użyj prawidłowej wartości eventID zwróconej przez zdarzenie związane z kamerą.

Pełną listę kodów błędów interfejsu API znajdziesz w przewodniku po kodach błędów interfejsu API.